Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
20d892d
Give names to everything in t=search and only show season packs. also…
Ryder-C Nov 9, 2025
4878b71
clippy fix and unecessary serde defaults
Ryder-C Nov 9, 2025
0dc37d1
Fixed rss id mis-syncing
Ryder-C Nov 13, 2025
45cd66c
api rss filter doesnt work :(
Ryder-C Nov 14, 2025
7331c00
add anilist api to detect movies, specials, and tv. cache title resul…
Ryder-C Nov 15, 2025
6c3ea38
using tags now
Ryder-C Nov 15, 2025
4190817
Merge branch 'main' into develop
Ryder-C Nov 15, 2025
6b31937
Merge branch 'main' into develop
Ryder-C Nov 16, 2025
9875bc3
Prune titles cache after items exit releases.moe scope
Ryder-C Nov 16, 2025
4cfcd82
filter out incomplete torrents.
Ryder-C Nov 16, 2025
b9ed437
change missing season message to trace
Ryder-C Nov 17, 2025
f1df0ab
Clean up code usage
Ryder-C Nov 17, 2025
daa5070
basic movie support
Ryder-C Nov 19, 2025
abbfd64
tv show or movie is now optional
Ryder-C Nov 19, 2025
02362df
update dependencies
Ryder-C Nov 19, 2025
4131f0b
Movie parsing working and minimize anilist call.
Ryder-C Nov 19, 2025
d951892
Optimizations + radarr in readme
Ryder-C Nov 20, 2025
c9854ea
Merge branch 'main' into develop
Ryder-C Nov 23, 2025
48d7fe8
add flake with devshell for testing.
Ryder-C Nov 30, 2025
c714a0d
Hide invalid logs for easier reading.
Ryder-C Dec 2, 2025
60c00f8
drop into user shell in devshell hook.
Ryder-C Dec 2, 2025
12910b5
remove drop to user shell. (it doesnt work)
Ryder-C Dec 2, 2025
fd30ed3
clarify readme
Ryder-C Dec 2, 2025
45e3d8b
update version
Ryder-C Dec 2, 2025
0a8aca7
Merge branch 'main' into develop
Ryder-C Dec 2, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ compose.yaml
/target
data/
.vscode
.dev-env
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 12 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
[package]
name = "seadexerr"
version = "0.4.0"
version = "0.4.1"
edition = "2024"

[dependencies]
anyhow = "1.0.100"
axum = { version = "0.8.7", features = ["macros"] }
quick-xml = "0.38.4"
reqwest = { version = "0.12.24", default-features = false, features = ["json", "rustls-tls"] }
reqwest = { version = "0.12.24", default-features = false, features = [
"json",
"rustls-tls",
] }
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.145"
serde_with = "3.16.0"
thiserror = "2.0.17"
time = { version = "0.3.44", features = ["formatting", "parsing"] }
tokio = { version = "1.48.0", features = ["fs", "macros", "rt-multi-thread", "sync", "time"] }
tokio = { version = "1.48.0", features = [
"fs",
"macros",
"rt-multi-thread",
"sync",
"time",
] }
tracing = "0.1.41"
tracing-subscriber = { version = "0.3.20", features = ["fmt", "env-filter"] }
url = "2.5.7"
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
A Prowlarr indexer for [Seadex](https://releases.moe/) torrents. Always get the best Seadex release.

> [!NOTE]
> Requires indexer flag `internal` to be unused for now
> Automatic Searching requires indexer flag `internal` to be unused for now

## Docker Compose

Expand Down Expand Up @@ -77,6 +77,7 @@ In Sonarr or Radarr:
- [x] Movie Support (TMDB + Radarr)
- [x] RSS Refresh
- [x] Local PlexAniBridge Mappings
- [x] Season Pack Support

This project uses [PlexAniBridge Mappings](https://github.com/eliasbenb/PlexAniBridge-Mappings).

Expand Down
61 changes: 61 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

128 changes: 128 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
{
description = "Seadexerr development environment";

inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
};

outputs =
{
self,
nixpkgs,
flake-utils,
}:
flake-utils.lib.eachDefaultSystem (
system:
let
pkgs = import nixpkgs {
inherit system;
config.allowUnfree = true;
};
in
{
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
sonarr
radarr
prowlarr

# Rust development tools
cargo
rustc
rustfmt
clippy

# Common dependencies
pkg-config
openssl
];

shellHook = ''
echo "Seadexerr development environment loaded."

export RUST_LOG="debug"

export SEADEXERR_DEV_ROOT="$PWD/.dev-env"
mkdir -p "$SEADEXERR_DEV_ROOT"

# Create media directories for Sonarr/Radarr root paths
export RADARR_ROOT_PATH="$SEADEXERR_DEV_ROOT/media/movies"
export SONARR_ROOT_PATH="$SEADEXERR_DEV_ROOT/media/tv"
mkdir -p "$RADARR_ROOT_PATH"
mkdir -p "$SONARR_ROOT_PATH"

start_service() {
local name=$1
local cmd=$2
local data_dir="$SEADEXERR_DEV_ROOT/$name"
mkdir -p "$data_dir"

# Try to find the executable, fallback to name
if command -v $name &> /dev/null; then
EXEC=$name
elif command -v $cmd &> /dev/null; then
EXEC=$cmd
else
echo "Could not find executable for $name"
return
fi

echo "Starting $name..."
$EXEC --data="$data_dir" --nobrowser > "$data_dir/$name.log" 2>&1 &
echo $!
}

# Start services and capture PIDs
SONARR_PID=$(start_service "sonarr" "Sonarr")
RADARR_PID=$(start_service "radarr" "Radarr")
PROWLARR_PID=$(start_service "prowlarr" "Prowlarr")

# Function to extract API key from config.xml
get_api_key() {
local name=$1
local config_file="$SEADEXERR_DEV_ROOT/$name/config.xml"
local max_retries=30
local count=0

echo "Waiting for $name to generate config..." >&2
while [ ! -f "$config_file" ] || ! grep -q "<ApiKey>" "$config_file"; do
sleep 1
count=$((count+1))
if [ $count -ge $max_retries ]; then
echo "Timeout waiting for $name config" >&2
return
fi
done

# Extract key between tags
grep -o "<ApiKey>.*</ApiKey>" "$config_file" | sed -e 's/<[^>]*>//g'
}

# Export keys to environment
export SONARR_API_KEY=$(get_api_key "sonarr")
export RADARR_API_KEY=$(get_api_key "radarr")
export PROWLARR_API_KEY=$(get_api_key "prowlarr")

echo "----------------------------------------"
echo "API Keys loaded:"
echo "SONARR_API_KEY: $SONARR_API_KEY"
echo "RADARR_API_KEY: $RADARR_API_KEY"
echo "PROWLARR_API_KEY: $PROWLARR_API_KEY"
echo "----------------------------------------"

cleanup() {
echo "Stopping background services..."
[ -n "$SONARR_PID" ] && kill $SONARR_PID 2>/dev/null
[ -n "$RADARR_PID" ] && kill $RADARR_PID 2>/dev/null
[ -n "$PROWLARR_PID" ] && kill $PROWLARR_PID 2>/dev/null
}

trap cleanup EXIT

echo "Services running in background. Data stored in .dev-env/"
'';
};
}
);
}
37 changes: 29 additions & 8 deletions src/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,14 +118,35 @@ async fn torznab_handler(
TorznabOperation::Unsupported(name) => name,
};

info!(
operation = operation_name,
tvdb = query.tvdb_id.as_deref(),
tmdb = query.tmdb_id.as_deref(),
season = query.season.as_deref(),
limit = query.limit,
"torznab request received"
);
let valid = match &operation {
TorznabOperation::Caps => true,
TorznabOperation::Search => query.query.is_none() && category_filter_matches(&query.cat),
TorznabOperation::TvSearch => {
query.tvdb_identifier().is_some() && query.season_number().is_some()
}
TorznabOperation::MovieSearch => query.tmdb_identifier().is_some(),
TorznabOperation::Unsupported(_) => false,
};

if valid {
info!(
operation = operation_name,
tvdb = query.tvdb_id.as_deref(),
tmdb = query.tmdb_id.as_deref(),
season = query.season.as_deref(),
limit = query.limit,
"Valid torznab request received"
);
} else {
debug!(
operation = operation_name,
tvdb = query.tvdb_id.as_deref(),
tmdb = query.tmdb_id.as_deref(),
season = query.season.as_deref(),
limit = query.limit,
"Invalid torznab request received"
);
}

match operation {
TorznabOperation::Caps => respond_caps(&state),
Expand Down