diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f10fb7a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+nyaa-tools-old/web/.venv/
+nyaa-tools-old/web/.config/
+nyaa-tools-old/config/
+nyaa-tools-old/.env
+__pycache__/
+*.pyc
diff --git a/nyaa-tools-old/.dockerignore b/nyaa-tools-old/.dockerignore
new file mode 100644
index 0000000..a068e36
--- /dev/null
+++ b/nyaa-tools-old/.dockerignore
@@ -0,0 +1,6 @@
+web/.venv/
+web/.config/
+config-example/
+systemd/
+__pycache__/
+*.pyc
diff --git a/nyaa-tools-old/Dockerfile b/nyaa-tools-old/Dockerfile
new file mode 100644
index 0000000..51b2377
--- /dev/null
+++ b/nyaa-tools-old/Dockerfile
@@ -0,0 +1,19 @@
+FROM python:3.13-slim
+
+RUN pip install --no-cache-dir flask toml requests transmission-rpc gunicorn
+
+WORKDIR /app
+COPY . /app
+
+RUN chmod +x /app/fetch.py /app/helper.py /app/batch.py \
+ && ln -s /app/batch.py /usr/local/bin/nyaa-batch \
+ && ln -s /app/fetch.py /usr/local/bin/nyaa-fetch \
+ && ln -s /app/helper.py /usr/local/bin/nyaa-helper \
+ && chmod +x /app/docker/entrypoint-fetch.sh
+
+ENV NYAA_TOOLS_CONFIG_DIR=/etc/nyaa-tools
+
+EXPOSE 5000
+
+# default: run the web UI; the fetch service overrides this in compose
+CMD ["gunicorn", "--chdir", "web", "--bind", "0.0.0.0:5000", "server:app"]
diff --git a/nyaa-tools-old/batch.py b/nyaa-tools-old/batch.py
old mode 100644
new mode 100755
diff --git a/nyaa-tools-old/config-example/batch-groups.toml b/nyaa-tools-old/config-example/batch-groups.toml
new file mode 100644
index 0000000..73b73b2
--- /dev/null
+++ b/nyaa-tools-old/config-example/batch-groups.toml
@@ -0,0 +1,3 @@
+# same idea as release-groups.toml, but for batch releases; regex should
+# also expose "first" and "last" named groups for the episode range.
+Judas = '^\[Judas\] (?P
.+) \((?P\d+)-(?P\d+)\)'
diff --git a/nyaa-tools-old/config-example/config.toml b/nyaa-tools-old/config-example/config.toml
new file mode 100644
index 0000000..facea90
--- /dev/null
+++ b/nyaa-tools-old/config-example/config.toml
@@ -0,0 +1,10 @@
+[library]
+# root folder your Jellyfin library points at
+base_path = "/mnt/media/anime"
+
+[transmission]
+# host running transmission-daemon with RPC enabled
+host = "127.0.0.1"
+# transmission's own download directory, used to hardlink finished files
+# into the library layout above
+download_path = "/var/lib/transmission-daemon/downloads"
diff --git a/nyaa-tools-old/config-example/release-groups.toml b/nyaa-tools-old/config-example/release-groups.toml
new file mode 100644
index 0000000..1edf717
--- /dev/null
+++ b/nyaa-tools-old/config-example/release-groups.toml
@@ -0,0 +1,6 @@
+# maps a release group tag (as seen in "[TAG] Show Name - 01.mkv") to a regex
+# with named groups "title" and "episode" (and optionally "season") used to
+# parse episode info out of the torrent title. Add one entry per group you
+# want the search page and fetch job to recognize.
+SubsPlease = '^\[SubsPlease\] (?P.+) - (?P\d+) \('
+Erai-raws = '^\[Erai-raws\] (?P.+) - (?P\d+) \['
diff --git a/nyaa-tools-old/config-example/series.toml b/nyaa-tools-old/config-example/series.toml
new file mode 100644
index 0000000..228b3e1
--- /dev/null
+++ b/nyaa-tools-old/config-example/series.toml
@@ -0,0 +1 @@
+tracking = []
diff --git a/nyaa-tools-old/config-example/web.env b/nyaa-tools-old/config-example/web.env
new file mode 100644
index 0000000..4f5c8b1
--- /dev/null
+++ b/nyaa-tools-old/config-example/web.env
@@ -0,0 +1,3 @@
+# copy to /etc/nyaa-tools/web.env, chmod 600, and set a real password.
+# referenced by nyaa-tools-old/systemd/nyaa-web.service
+PASSWORD=change-me
diff --git a/nyaa-tools-old/docker-compose.yml b/nyaa-tools-old/docker-compose.yml
new file mode 100644
index 0000000..a47b825
--- /dev/null
+++ b/nyaa-tools-old/docker-compose.yml
@@ -0,0 +1,26 @@
+services:
+ web:
+ build: .
+ image: nyaa-tools:latest
+ ports:
+ - "5000:5000"
+ environment:
+ - PASSWORD=${NYAA_WEB_PASSWORD}
+ volumes:
+ - ./config:/etc/nyaa-tools
+ restart: unless-stopped
+
+ fetch:
+ build: .
+ image: nyaa-tools:latest
+ entrypoint: ["/app/docker/entrypoint-fetch.sh"]
+ environment:
+ - FETCH_INTERVAL=600
+ volumes:
+ - ./config:/etc/nyaa-tools
+ # transmission's download dir and the jellyfin library base_path (set
+ # in config/config.toml) must resolve to the SAME bind mount below —
+ # fetch.py hardlinks finished files, which only works within one
+ # filesystem/mount. Point both at a shared host media root, e.g.:
+ - /path/to/host/media:/mnt/media
+ restart: unless-stopped
diff --git a/nyaa-tools-old/docker/entrypoint-fetch.sh b/nyaa-tools-old/docker/entrypoint-fetch.sh
new file mode 100644
index 0000000..097afe3
--- /dev/null
+++ b/nyaa-tools-old/docker/entrypoint-fetch.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+set -e
+
+INTERVAL="${FETCH_INTERVAL:-600}"
+
+while true; do
+ python3 /app/fetch.py
+ sleep "$INTERVAL"
+done
diff --git a/nyaa-tools-old/web/server.py b/nyaa-tools-old/web/server.py
index 12948cb..89531a0 100644
--- a/nyaa-tools-old/web/server.py
+++ b/nyaa-tools-old/web/server.py
@@ -20,8 +20,9 @@ from flask import (
app = Flask(__name__)
-release_groups = toml.load("/etc/nyaa-tools/release-groups.toml")
-batch_groups = toml.load("/etc/nyaa-tools/batch-groups.toml")
+CONFIG_DIR = os.environ.get("NYAA_TOOLS_CONFIG_DIR", "/etc/nyaa-tools")
+release_groups = toml.load(os.path.join(CONFIG_DIR, "release-groups.toml"))
+batch_groups = toml.load(os.path.join(CONFIG_DIR, "batch-groups.toml"))
DEV_ENV = bool(os.environ.get("DEV_ENV", default=False))
if not DEV_ENV:
@@ -170,14 +171,14 @@ def series():
except ValueError:
return "Invalid season", 400
- series = toml.load("/etc/nyaa-tools/series.toml")
+ series = toml.load(os.path.join(CONFIG_DIR, "series.toml"))
if "tracking" not in series.keys():
series["tracking"] = []
# TODO: Do not allow duplicates
entry = {"name": title, "release_group": release_group, "season": season}
series["tracking"].append(entry)
- with open("/etc/nyaa-tools/series.toml", "w") as f:
+ with open(os.path.join(CONFIG_DIR, "series.toml"), "w") as f:
toml.dump(series, f)
return "OK", 200
else:
diff --git a/nyaa-tools-old/web/start.sh b/nyaa-tools-old/web/start.sh
new file mode 100755
index 0000000..065d91d
--- /dev/null
+++ b/nyaa-tools-old/web/start.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+set -euo pipefail
+
+DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+CONFIG_DIR="$DIR/.config"
+
+if ! python3 -c "import flask, toml, requests" 2>/dev/null; then
+ echo "Missing Python dependencies (flask/toml/requests)."
+ echo "Install them with:"
+ echo " sudo apt install python3-flask python3-toml python3-requests"
+ exit 1
+fi
+
+mkdir -p "$CONFIG_DIR"
+[ -f "$CONFIG_DIR/release-groups.toml" ] || cat > "$CONFIG_DIR/release-groups.toml" <<'EOF'
+# maps a release group tag (as seen in "[TAG] Show Name - 01.mkv") to a regex
+# with named groups "title" and "episode" (and optionally "season") used to
+# parse episode info out of the torrent title. Add one entry per group you
+# want the search page to recognize.
+SubsPlease = '^\[SubsPlease\] (?P.+) - (?P\d+) \('
+Erai-raws = '^\[Erai-raws\] (?P.+) - (?P\d+) \['
+EOF
+[ -f "$CONFIG_DIR/batch-groups.toml" ] || cat > "$CONFIG_DIR/batch-groups.toml" <<'EOF'
+# same idea as release-groups.toml, but for batch releases; regex should
+# also expose "first" and "last" named groups for the episode range.
+Judas = '^\[Judas\] (?P.+) \((?P\d+)-(?P\d+)\)'
+EOF
+[ -f "$CONFIG_DIR/series.toml" ] || echo "tracking = []" > "$CONFIG_DIR/series.toml"
+
+export NYAA_TOOLS_CONFIG_DIR="$CONFIG_DIR"
+export DEV_ENV=true
+export FLASK_APP="$DIR/server.py"
+
+echo "Config dir: $CONFIG_DIR"
+echo "Starting server in DEV_ENV mode (no login required) at http://127.0.0.1:5000"
+cd "$DIR"
+exec python3 server.py