Imported from wade00754/pikpak-rss-manager (
AGENTS.md). Install upstream withnpx skills add wade00754/pikpak-rss-manager. Copyright stays with the author.
PikPak RSS Manager
Purpose and architecture
Personal self-hosted Go service. Use the official hosted PikPak MCP with PAT authorization. Do not introduce rclone, a PikPak CLI runtime dependency, an LLM, MySQL, Redis, or a frontend build pipeline.
Keep HTTP/UI in internal/web, RSS and torrent metadata in internal/feed, naming rules in internal/rename, the typed MCP adapter in internal/pikpak, durable workflow in internal/worker, and SQLite migrations in internal/store/migrations.
Use Go 1.27.1, native JavaScript/CSS and embedded templates/static assets. The UI supports Traditional Chinese and English with a persistent language selector on setup, login and management pages. Translate application copy and messages only; preserve user names, paths, URLs, regex and filenames. MIT license.
Product decisions
- One administrator and one active PikPak account; no default administrator password. The user explicitly removed password length and character restrictions; require only a nonempty password created through first-run Web setup. Never persist plaintext or a reversible administrator password; store only a salted Argon2id verifier. Do not load .env or external password/PAT sources; initialize all application settings and PAT through the Web UI. Listen address and data-directory environment overrides remain optional process settings.
- Every subscription owns its destination, interval, rename checkbox, regex and replacement. New UI subscriptions default to keeping original filenames. Regex replace mode operates on each actual filename with Go replacement references ($1, ${name}, $$); preview and execution share the renderer. Replacement previews do not require the unused subscription title; saving subscriptions still validates their name, and legacy template rendering retains title validation.
- Missing rename flags/modes in existing records mean legacy template naming remains enabled. Preserve season/template support for these subscriptions and existing job snapshots; do not silently rewrite existing rules.
- Browse/create cloud folders through the official MCP. Persist selected folder IDs and their owning account; expose only opaque account references to the UI. Revalidate selected IDs, reject stale selections after switching accounts, and never retry uncertain folder creation automatically. Manual destination paths remain supported.
- Folder creation opens a compact dialog from a button; avoid a permanently visible name field. The source-preview button says 讀取種子檔名 and reads all available filenames in one action, without a manual load-more button. Read one feed snapshot and each distinct torrent URL once, with at most five simultaneous requests. Keep per-resource 2 MiB protection, a 32 MiB total metadata budget, a 10,000-sample/8 MiB output budget, and bounded timeouts; retain successful results with explicit notices for failures or limits. Cancel requests when the source changes or the dialog closes. Preserve the legacy cursor API for compatibility. Prefer available .torrent metadata for previews without changing download source selection. The RSS sample dropdown shows only actual torrent filenames, without per-option source labels. Keep provenance in the API; never guess media extensions or create download tasks for previews.
- Update filename previews automatically when naming inputs or the selected torrent filename change, using the shared Go renderer. The UI has no manual original-filename input; preview directly uses the selected torrent sample and prompts 選擇種子檔名 when none is selected. Show only the final replacement result, with a short warning when filename normalization replaces or removes unsuitable characters. Keep raw output in the API. Do not confuse a slash in an RSS title with a regex replacement escape.
- Establish an initial feed baseline by default; backfill is explicit.
- Normalize infohashes without suppressing repeated explicit downloads. Automatic RSS checks retain fingerprint baselines. Backfill lists actual torrent filenames, allows selecting whole torrents, and requires download/overwrite confirmation. Retry the same confirmation idempotently.
- Download on PikPak, then rename/move by file ID. Never transfer media through this service.
- New task staging is beneath the subscription destination (
_PikPak-RSS-Staging/<jobID>); selecting the cloud root necessarily stages there. New staging allocations opt into recoverable cleanup after completion: remove only revalidated empty folders, retain_Replacedbackups and other jobs, and keep bounded restart-safe cleanup retries independent of download status. Keep persisted staging IDs for existing tasks; legacy records without cleanup ownership are never cleaned automatically. Explicit isolated-test staging paths remain rooted in the dedicated test namespace. - Parse multiple files independently. RSS episode fallback is allowed only for one primary file in legacy template mode. Regex replace mode leaves non-matching names unchanged. Keep ambiguous files and ordinary name collisions for review. Confirmed backfills may replace same-name destination files after downloading; persist backup plans and move originals into the task staging backup before replacement. Never replace folders or permanently delete content.
- Persist task IDs and file action progress. Reconcile ambiguous submissions instead of automatically submitting another task.
- Pause authentication/quota errors and use bounded backoff for transient failures.
Commands and verification
go test ./..., go vet ./..., go build ./cmd/pikpak-rss-manager.
Use the root Makefile as the shared local/CI command entry point: make dev, make verify, make test-race, make docker-build, make test-container and make test-manifest. Keep test programs under tests/; do not reintroduce a scripts/ directory or Python/PowerShell wrappers for these commands.
Linux CI additionally runs go test -race ./... and container startup/persistence smoke tests.
The development machine has no Docker. Use GitHub Actions for Docker validation and multiarch publishing rather than installing Docker.
Meaningful tests must cover RSS/Atom and torrent parsing, independent naming rules, baselines, repeat downloads and confirmation idempotency, restart recovery, partial actions, uncertain submissions, auth/quota/rate failures, HTTP authentication and CSRF.
Folder tests cover paging, duplicate folder names by ID, creation collisions and account switches; naming tests cover disabled rules, replacement groups, nonmatches and legacy records. Opt-in PIKPAK_LIVE_FOLDERS_TEST=1 verifies folder-only operations inside a dedicated test run without downloading content. UI testing uses an isolated mocked account and data directory; screenshots contain only fixture names.
Source-preview tests cover v1/v2 torrent filenames, metadata limits, private-network protection, provenance, CSRF, no download/baseline side effects, and current-account-only cached names. Test destination-local staging and existing staging ID recovery.
Document actual results in docs/verification.md; never claim a mocked test proves a real PikPak operation.
Secrets and external actions
The user-provided .env contains PIKPAK_TOKEN. Never print, commit, embed in a build, or upload it to GitHub/Actions. Do not read it into tool output. Preserve the file and unrelated user settings.
Ignore databases, private settings, keys, local credentials and binaries before initializing Git. Check staged paths and secret leakage before every publication.
UI credentials are write-only; administrator passwords use salted Argon2id hashes and PAT uses AES-GCM encryption; keep the key in the persistent data directory with restrictive permissions. Log no credentials, authorization headers or sensitive URL queries.
User authorization already covers creating the public wade00754/pikpak-rss-manager repository, pushing this implementation, publishing GHCR images, and making the package public. Do not ask again for these same actions. It does not cover deploying to a VPS or altering unrelated repositories.
Real PikPak tests may create offline tasks and rename/move only inside _pikpak-rss-manager-test/<run-id> created by this project. Use small Public Domain/Creative Commons fixtures; preserve existing account content. Never permanently delete content. The PAT stays on the local development machine.
OAuth has been researched, not implemented. Official public discovery advertises PKCE, refresh tokens and registration; these advertisements do not prove successful client registration or a tested consent flow. Keep PAT support and the documented comparison in docs/auth-comparison.md. Never claim OAuth automatically unlocks purge/invite through the hosted MCP.
Delivery
After each implementation task, update README and relevant documentation to match changed behavior, commands or deployment steps, run relevant verification, and immediately create a Conventional Commit containing only that task's changes. Push completed commits to GitHub within the existing authorization; do not wait for another commit or upload request.
Assess release needs for every task and record the decision in docs/verification.md and the delivery response. Publish a new semantic version for user-visible fixes/features, compatibility or deployment changes; tooling/test/documentation-only changes do not require a new version. Do not move or overwrite existing release tags unless the user explicitly requests it. When releasing, synchronize the source VERSION, README and concise English release notes; verify CI, multiarch publishing and anonymous pulls. For any push, check the triggered workflows and document actual results or external blockers.
Provide non-root multistage Docker images for linux/amd64 and linux/arm64, main/tag publishing to GHCR with GITHUB_TOKEN, a compose file using the published image, and 1Panel/reverse proxy/update/backup instructions. Confirm anonymous access after first GHCR publication; public repository visibility does not make a package public automatically.
Routine implementation choices within these principles are authorized. Clearly record external blockers and incomplete validation.
Language and copy
- Write README, documentation, release notes and future public descriptions in concise English. Include only behavior changes, required usage/deployment steps, verification evidence and material limitations; omit slogans and repeated explanations.
- UI headings use page names, with only actionable labels, status, validation and necessary field help. Do not add decorative prose.
- Manual offline tasks use the durable worker queue without creating subscriptions or feed baselines. Share destination validation, destination-local staging and uncertain-submission recovery with RSS jobs; preserve original filenames by default.
- Run
make test-ui(includingnode tests/web/i18n.test.cjs) when changing UI copy or translations.
