Imported from Nikoace/bt-torrent-seeker (
AGENTS.md). Install upstream withnpx skills add Nikoace/bt-torrent-seeker. Copyright stays with the author.
bt-torrent-seeker — Project Guidelines
A personal anime BitTorrent download aggregator. Cross-site torrent search (DMHY + Nyaa), Bangumi.tv metadata sync, and a subscription/notification system for episode releases.
Architecture
Monolithic Rails 8 app with a plugin-based Source Adapter system.
Web Request → Controller → Service / Adapter → SQLite (ActiveRecord)
Background Jobs (Solid Queue) → BangumiClient / SearchAggregator → Notifications
Key layers:
- Controllers: Thin — delegate to services, no business logic
- Services:
BangumiClient(Bangumi.tv API),SearchAggregator(parallel multi-source search),TorrentFilenameParser(regex metadata extraction) - Source Adapters (
app/services/sources/):Baseabstract class →Dmhy+Nyaa; registered viaconfig/initializers/sources.rb; extend by subclassingSources::Baseand registering in the initializer - Jobs:
BangumiSyncJob(daily, 2 AM) — syncs current-season anime;SubscriptionCheckJob(every 30 min) — detects new torrent episodes per subscription - Frontend: Hotwire (Turbo Frames + Turbo Streams) + Stimulus; minimal custom JS (
magnet_copy_controller.js,torrent_filter_controller.js)
Domain Models
| Model | Key Fields | Notes |
|---|---|---|
Anime |
bangumi_id (unique), title, title_cn, season_year, season_quarter, air_weekday |
Synced from Bangumi.tv; current_season scope |
Torrent |
magnet_uri, source_site, episode_number, sub_group, resolution |
before_create parses filename metadata |
Subscription |
anime_id, keyword, sub_group, resolution, active |
active scope; keyword defaults to anime Chinese title |
Notification |
subscription_id, torrent_id, message, read |
unread scope; Turbo Stream badge update on mark-read |
Build and Test
bundle install
bin/rails db:create db:migrate
bin/rails server # http://localhost:3000
bin/rails solid_queue:start # Start Solid Queue worker (dev)
bin/rails test # All tests (MiniTest)
bin/rails test test/models/
bin/rails test test/services/
bin/rails test test/jobs/
bin/brakeman # Security scan
bundler-audit # Gem vulnerability audit
bin/rubocop # Code style (Rails Omakase preset)
Conventions
- Adding a new BT source: Subclass
Sources::Base, implementsearch(keyword, filters = {})andfetch_latest(keyword, since:), register inconfig/initializers/sources.rb - Notification messages: Format
"<title_cn> 第<NN>集 [<sub_group>] [<resolution>] 已更新"(seeSubscriptionCheckJob) - Torrent metadata extraction: Always goes through
TorrentFilenameParser.parse(title)— do not duplicate regex logic elsewhere - Async UI updates: Use Turbo Streams for partial DOM updates (e.g., notification badge); use Turbo Frames for section reloads (e.g., search results)
- No Node.js build step: Assets via Propshaft + ImportMap; add JS packages via
bin/importmap pin - Season calculation: Quarter 1 = Jan–Mar, 2 = Apr–Jun, 3 = Jul–Sep, 4 = Oct–Dec (see
BangumiSyncJob)
Key Files
config/initializers/sources.rb— enable/disable BT source adaptersconfig/recurring.yml— Solid Queue cron scheduleapp/services/sources/base.rb— adapter interface contractapp/services/search_aggregator.rb— parallel thread-safe searchdocs/superpowers/specs/— original design docdocs/superpowers/plans/— implementation plan with task checklist