torrent-finder-cli 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. torrent_finder_cli-0.1.0/.github/workflows/release.yml +58 -0
  2. torrent_finder_cli-0.1.0/.gitignore +21 -0
  3. torrent_finder_cli-0.1.0/LICENSE +21 -0
  4. torrent_finder_cli-0.1.0/PKG-INFO +356 -0
  5. torrent_finder_cli-0.1.0/README.md +333 -0
  6. torrent_finder_cli-0.1.0/pyproject.toml +50 -0
  7. torrent_finder_cli-0.1.0/requirements.txt +5 -0
  8. torrent_finder_cli-0.1.0/setup.cfg +4 -0
  9. torrent_finder_cli-0.1.0/torrent.bat +3 -0
  10. torrent_finder_cli-0.1.0/torrent_finder/__init__.py +18 -0
  11. torrent_finder_cli-0.1.0/torrent_finder/__main__.py +4 -0
  12. torrent_finder_cli-0.1.0/torrent_finder/_version.py +24 -0
  13. torrent_finder_cli-0.1.0/torrent_finder/constants.py +117 -0
  14. torrent_finder_cli-0.1.0/torrent_finder/creator_search.py +57 -0
  15. torrent_finder_cli-0.1.0/torrent_finder/credentials.py +198 -0
  16. torrent_finder_cli-0.1.0/torrent_finder/downloader.py +1087 -0
  17. torrent_finder_cli-0.1.0/torrent_finder/filters.py +52 -0
  18. torrent_finder_cli-0.1.0/torrent_finder/jimaku.py +187 -0
  19. torrent_finder_cli-0.1.0/torrent_finder/main.py +1068 -0
  20. torrent_finder_cli-0.1.0/torrent_finder/online_fix.py +285 -0
  21. torrent_finder_cli-0.1.0/torrent_finder/providers/__init__.py +131 -0
  22. torrent_finder_cli-0.1.0/torrent_finder/providers/anime_provider.py +55 -0
  23. torrent_finder_cli-0.1.0/torrent_finder/providers/base.py +247 -0
  24. torrent_finder_cli-0.1.0/torrent_finder/providers/game_provider.py +67 -0
  25. torrent_finder_cli-0.1.0/torrent_finder/providers/manga_provider.py +58 -0
  26. torrent_finder_cli-0.1.0/torrent_finder/providers/mobile_provider.py +45 -0
  27. torrent_finder_cli-0.1.0/torrent_finder/providers/movie_provider.py +93 -0
  28. torrent_finder_cli-0.1.0/torrent_finder/providers/online_fix_provider.py +34 -0
  29. torrent_finder_cli-0.1.0/torrent_finder/providers/rutracker_provider.py +29 -0
  30. torrent_finder_cli-0.1.0/torrent_finder/providers/software_provider.py +54 -0
  31. torrent_finder_cli-0.1.0/torrent_finder/resolvers/__init__.py +11 -0
  32. torrent_finder_cli-0.1.0/torrent_finder/resolvers/anilist.py +295 -0
  33. torrent_finder_cli-0.1.0/torrent_finder/resolvers/games.py +37 -0
  34. torrent_finder_cli-0.1.0/torrent_finder/resolvers/igdb.py +157 -0
  35. torrent_finder_cli-0.1.0/torrent_finder/resolvers/jikan.py +125 -0
  36. torrent_finder_cli-0.1.0/torrent_finder/resolvers/movies.py +35 -0
  37. torrent_finder_cli-0.1.0/torrent_finder/resolvers/tmdb.py +182 -0
  38. torrent_finder_cli-0.1.0/torrent_finder/resolvers/types.py +49 -0
  39. torrent_finder_cli-0.1.0/torrent_finder/resolvers/wikidata.py +155 -0
  40. torrent_finder_cli-0.1.0/torrent_finder/rutracker.py +142 -0
  41. torrent_finder_cli-0.1.0/torrent_finder/security.py +155 -0
  42. torrent_finder_cli-0.1.0/torrent_finder/state.py +268 -0
  43. torrent_finder_cli-0.1.0/torrent_finder/stats.py +151 -0
  44. torrent_finder_cli-0.1.0/torrent_finder/subtitles.py +272 -0
  45. torrent_finder_cli-0.1.0/torrent_finder/torrent_info.py +295 -0
  46. torrent_finder_cli-0.1.0/torrent_finder/torrent_meta.py +330 -0
  47. torrent_finder_cli-0.1.0/torrent_finder/torrent_session.py +125 -0
  48. torrent_finder_cli-0.1.0/torrent_finder/ui/__init__.py +1 -0
  49. torrent_finder_cli-0.1.0/torrent_finder/ui/creator.py +563 -0
  50. torrent_finder_cli-0.1.0/torrent_finder/ui/history.py +286 -0
  51. torrent_finder_cli-0.1.0/torrent_finder/ui/prompts.py +2031 -0
  52. torrent_finder_cli-0.1.0/torrent_finder/ui/selector.py +433 -0
  53. torrent_finder_cli-0.1.0/torrent_finder/ui/stats.py +188 -0
  54. torrent_finder_cli-0.1.0/torrent_finder/ui/streaming.py +169 -0
  55. torrent_finder_cli-0.1.0/torrent_finder/ui/table.py +341 -0
  56. torrent_finder_cli-0.1.0/torrent_finder/ui/tips.py +202 -0
  57. torrent_finder_cli-0.1.0/torrent_finder/ui/tips_page.py +203 -0
  58. torrent_finder_cli-0.1.0/torrent_finder/updates.py +69 -0
  59. torrent_finder_cli-0.1.0/torrent_finder/utils.py +118 -0
  60. torrent_finder_cli-0.1.0/torrent_finder_cli.egg-info/PKG-INFO +356 -0
  61. torrent_finder_cli-0.1.0/torrent_finder_cli.egg-info/SOURCES.txt +65 -0
  62. torrent_finder_cli-0.1.0/torrent_finder_cli.egg-info/dependency_links.txt +1 -0
  63. torrent_finder_cli-0.1.0/torrent_finder_cli.egg-info/entry_points.txt +2 -0
  64. torrent_finder_cli-0.1.0/torrent_finder_cli.egg-info/requires.txt +5 -0
  65. torrent_finder_cli-0.1.0/torrent_finder_cli.egg-info/scm_file_list.json +60 -0
  66. torrent_finder_cli-0.1.0/torrent_finder_cli.egg-info/scm_version.json +8 -0
  67. torrent_finder_cli-0.1.0/torrent_finder_cli.egg-info/top_level.txt +1 -0
@@ -0,0 +1,58 @@
1
+ name: Release
2
+
3
+ # Push a tag like v0.1.3 -> build + publish to PyPI.
4
+ # Run manually (Actions tab) -> build + publish to TestPyPI, to rehearse first.
5
+ on:
6
+ push:
7
+ tags:
8
+ - "v*"
9
+ workflow_dispatch: {}
10
+
11
+ jobs:
12
+ build:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ with:
17
+ fetch-depth: 0 # setuptools-scm needs full history + tags
18
+ - uses: actions/setup-python@v5
19
+ with:
20
+ python-version: "3.x"
21
+ - name: Build sdist + wheel
22
+ run: |
23
+ python -m pip install --upgrade build
24
+ python -m build
25
+ - uses: actions/upload-artifact@v4
26
+ with:
27
+ name: dist
28
+ path: dist/
29
+
30
+ testpypi:
31
+ # Manual runs only — rehearse the publish without touching real PyPI.
32
+ if: github.event_name == 'workflow_dispatch'
33
+ needs: build
34
+ runs-on: ubuntu-latest
35
+ permissions:
36
+ id-token: write # Trusted Publishing (OIDC) — no API token needed
37
+ steps:
38
+ - uses: actions/download-artifact@v4
39
+ with:
40
+ name: dist
41
+ path: dist/
42
+ - uses: pypa/gh-action-pypi-publish@release/v1
43
+ with:
44
+ repository-url: https://test.pypi.org/legacy/
45
+
46
+ pypi:
47
+ # Tag pushes only — the real release.
48
+ if: startsWith(github.ref, 'refs/tags/v')
49
+ needs: build
50
+ runs-on: ubuntu-latest
51
+ permissions:
52
+ id-token: write
53
+ steps:
54
+ - uses: actions/download-artifact@v4
55
+ with:
56
+ name: dist
57
+ path: dist/
58
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,21 @@
1
+ # Python cache
2
+ __pycache__/
3
+ *.pyc
4
+ *.pyo
5
+
6
+ # Downloaded files
7
+ downloads/
8
+
9
+ # Persisted filter/engine state
10
+ filter_state.json
11
+
12
+ # Subtitle provider credentials (OpenSubtitles / Jimaku) — never commit
13
+ subtitle_credentials.json
14
+
15
+ # Packaging / build artifacts
16
+ build/
17
+ dist/
18
+ *.egg-info/
19
+
20
+ # setuptools-scm writes this at build time
21
+ torrent_finder/_version.py
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Pietro Filippo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,356 @@
1
+ Metadata-Version: 2.4
2
+ Name: torrent-finder-cli
3
+ Version: 0.1.0
4
+ Summary: Search torrents across multiple sources from your terminal and hand them to your client — subtitles, episode picking, batch download, and search-by-creator.
5
+ Author: Pietro Filippo
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/PietroFilippo/torrent-finder-cli
8
+ Project-URL: Repository, https://github.com/PietroFilippo/torrent-finder-cli
9
+ Keywords: torrent,cli,tui,magnet,search,subtitles
10
+ Classifier: Environment :: Console
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Topic :: Utilities
14
+ Requires-Python: >=3.10
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: requests
18
+ Requires-Dist: rich
19
+ Requires-Dist: readchar
20
+ Requires-Dist: subliminal
21
+ Requires-Dist: babelfish
22
+ Dynamic: license-file
23
+
24
+ # Torrent Search CLI
25
+
26
+ An interactive command-line application for searching and downloading torrents directly from your terminal. Built with Python and `rich`.
27
+
28
+ On Windows, the included `torrent.bat` launcher can be added to your `PATH` so you can run `torrent` from any terminal directory.
29
+
30
+ ## Features
31
+
32
+ - **Multi-Category Search:** Torrents across different providers (Movies & Series, Games, Software, Anime, Manga), each with its own tailored search backends. The Movies & Series provider handles both films and TV shows — the episode-aware streaming flow kicks in automatically when a torrent contains multiple video files. **Software** is a group on the provider screen: pick it and choose a source — **Desktop** (Windows/macOS/Linux programs via The Pirate Bay's Applications categories plus SolidTorrents), **Mobile** (Android apps — APK/MOD/OBB; Android-only and says so when you search), or **RuTracker** (logs into [rutracker.org](https://rutracker.org) and searches it directly — great for software, audio, and rare content; needs an account set under the credentials menu, and stays dormant until one is configured). On the CLI these stay individually addressable: `-t software`, `-t mobile`, `-t rutracker`. **Games** is likewise a group: pick it and choose **General** (PC, consoles, ROMs & repacks from public trackers — The Pirate Bay's game categories plus SolidTorrents) or **Online-Fix** (scrapes [online-fix.me](https://online-fix.me) for co-op/online game cracks). On the CLI they're `-t game` and `-t online-fix`. Online-Fix needs **no account** — both search and download are anonymous (the file host is referer-gated, not login-gated); picking a result downloads the `.torrent` into your download folder and opens it in your system torrent client, showing the archive password (`online-fix.me`) to unpack the game with.
33
+ - **Multi-Engine Fan-Out:** Each provider queries several sources in parallel (e.g. Apibay + SolidTorrents + YTS + Nyaa live-action for Movies & Series, Nyaa for Anime, Nyaa Literature + Apibay Comics for Manga) and merges results, deduplicating by info hash and sorting by seeders.
34
+ - **Search by Creator:** Search by the people and companies behind the content instead of by title. After choosing a provider, a "choose how to search" screen offers normal keyword search **plus** by-creator options — **Anime** and **Movies & Series** by **director** or **studio**, **Manga** by **writer** or serialization **magazine**, **Games** by **developer** or **publisher** (kept separate — a company can be both). You type a name, disambiguate between matches, then multi-select which of that creator's titles to include (a paged checklist, 100 per page with `n`/`p`); the app runs a normal torrent search for each picked title and merges the results — so picking still uses all the usual download/stream/episode options. It works **keyless out of the box** (AniList for anime/manga staff, Jikan for manga magazines, Wikidata for movies/games), and an optional **TMDB** key (Movies & Series) or **Twitch/IGDB** credentials (Games) added under **🔑 Credentials** transparently upgrade those two to richer, better-ranked data. Online-Fix is included in the Games developer/publisher results. From the CLI: `--by <role> --name "<creator>"` alongside `-t`, e.g. `torrent -t anime --by director --name "Hayao Miyazaki"`.
35
+ - **Arrow-Key Driven UI:** Fully interactive, flicker-free terminal interface.
36
+ - Utilizes an alternate screen buffer so your scrollback history remains flawlessly clean.
37
+ - **Dynamic Viewport Windowing:** Capable of rendering massive 500+ item checklists (like huge anime seasons) by automatically windowing the active selection while pinning crucial action buttons tightly to the top and bottom of your screen to prevent terminal overflow.
38
+ - **Marquee Scrolling:** Automatically scrolls long torrent names and checklist items that exceed the physical terminal width when hovered over.
39
+ - **Contextual Footers:** Displays dynamic helper text explaining the trade-offs, speeds, and seeding behaviors of different download options as you highlight them.
40
+ - **Advanced Filtering:**
41
+ - Toggle built-in presets (preferred resolutions, known uploaders/repackers, trusted release groups) using an interactive checklist.
42
+ - Toggle individual search engines on and off per provider from the same menu.
43
+ - Add custom include/exclude keywords to quickly find the exact release you want.
44
+ - **Shared keybinds with the episode picker:** `a` select all • `i` invert • `c` clear presets • `w` save • `v` / `Shift+V` visual anchor + range toggle • `Space` toggle current.
45
+ - **Persistent across runs:** engine toggles, active filter presets, search history, usage stats, the quiet-mode flag, the chosen download folder, and the dismissed-warning state all live in `filter_state.json` next to the script, so configuration sticks after you close the program. Mutations are held in an in-memory cache and flushed on exit or after destructive actions (clear history, reset stats, filter-menu Confirm) — no per-event disk hit.
46
+ - **Search History:** Press `H` on the provider screen (or `Tab` then `H` at the search prompt) to browse past searches. Filter by provider (`P`), date range (`D`, today/week/month), and sort order (`S`). Each entry shows the provider, relative timestamp, and the filter presets that were active at search time. Pick an entry to re-run the query; clear history with a confirmation modal.
47
+ - **Usage Stats:** Press `S` on the provider screen (or `Tab` then `S` at the search prompt) to open a scrollable stats page showing session count, total runtime, searches, top queries, torrents picked, method picks vs. completions (with success rate), avg seeders of picks, and preset usage counters. Reset all stats from the same screen, guarded by a confirmation modal.
48
+ - **Confirmation Modals:** Destructive actions (clear history, reset stats) share a unified red Y/N panel so you can't nuke state with a stray keypress.
49
+ - **Dynamic Contextual Tips:** Random hints (`💡 Tip: ...`) are displayed in the provider selector and post-download menus. A searchable tips browser is also available from the provider screen (`T`), the search prompt (`Tab` then `T`), and the post-download menu.
50
+ - **Quiet Mode:** Toggle **🔇 Quiet mode** from the Download Method menu to suppress the native progress UIs of `aria2c`, `webtorrent-cli`, and `peerflix` (full-screen progress bars, peer lists, speed graphs) and replace them with a single minimal spinner. The toggle redraws in place with no flicker and persists across runs (stored as `hide_stream_output` in `filter_state.json`). Episode info, VLC hotkey hints, and `Ctrl+C` all still work.
51
+ - **Flexible Downloading & Streaming:**
52
+ - **System Client:** Automatically send generated magnet links to your default system torrent client (like qBittorrent, Transmission, etc.).
53
+ - **Direct Terminal Download:** Use `aria2c`, `webtorrent-cli`, or `peerflix` integration to download files directly within the terminal, with native progress UIs.
54
+ - **File Browser / Episode Picker (Anime, Movies & Series, Manga):** Open **📂 Browse torrent files…** from the download menu to list every file in the torrent (videos, subs, artwork, .nfo, samples — or individual volumes/chapters for Manga) and pick any subset. Opening it fetches the torrent's file list over DHT via `aria2c`, which can take 30–60s (or stall on low-peer torrents) — press **Esc** during the load to cancel and return to the menu. Features vim-style visual range selection (`v` anchor, `Shift+V` range-toggle) and rapid hotkeys (`a`, `i`, `c`, `w`). **Selection persists across re-entries** — reopening the picker shows your existing checkboxes already ticked, so you can refine without rebuilding from scratch. Confirming with nothing checked clears the selection; `Esc` cancels and keeps the prior picks intact. Only `aria2c` honors strict file selection on download — `webtorrent` and `peerflix` ignore `--select` and pull the whole torrent (the menu warns you when a selection is active). **Streams auto-skip non-video picks** and warn about it, so you can still e.g. download the .srt + .nfo alongside the video without breaking playback. If a stream selection contains zero video files, the stream errors out instead of silently substituting another file.
55
+ - **Torrent Info (from origin):** In the **Torrent & files** section of the download menu, **ℹ Torrent info** fetches details straight from the source page — category, uploader, date, description, and the full file list. Supported sources: Nyaa (scraped), The Pirate Bay (Apibay JSON API) and YTS (API); other engines show "not available". It also reports **whether subtitles are embedded** in the video: a filename/metadata heuristic (e.g. an anime "English-translated" category or a `[Subbed]` tag), upgraded to a definitive answer via `ffprobe` when `ffmpeg` is installed and a copy of the video has already been downloaded — useful to tell a soft-subbed MKV apart from a raw release with no separate `.srt`.
56
+ - **Stream to VLC:** Stream media directly to VLC Media Player using `webtorrent-cli` (default) or `peerflix` (fallback). Both stream and download menus list **webtorrent before peerflix** to match this preference. Press the `v` hotkey at any time during a streaming session to reopen VLC without losing your torrent download/buffering progress. The CLI checks active processes (`tasklist` on Windows, `pgrep -x` on Mac/Linux) and silently ignores the hotkey if VLC is already running, preventing accidental duplicate windows. When an episode is selected, streams that specific file.
57
+ - **Subtitles for streams (auto + manual):** A `📝 Source: <mode>` row in the Download Method menu controls how VLC gets subtitles for the next stream:
58
+ - `auto-detect from torrent` *(default)* — scans the torrent for `.srt/.ass/.ssa/.vtt/.sub` files paired with each video (matched by basename, language tag like `.en.srt`, or a sibling `Subs/` folder with episode-numbered files like `01.ass`). Matches are pre-downloaded via aria2c and attached to VLC via `--sub-file` before playback starts. English subs are prioritized as the primary track when available.
59
+ - `external file` — pick a `.srt/.ass` from a list of recent files in your chosen download folder (defaults to `downloads/`), or type a custom path. The same file is attached to every episode in the session.
60
+ - `off` — stream with no subtitles.
61
+ - After downloading subs via **📝 Search & download subtitles** (the existing subliminal flow), the saved file is auto-promoted to external mode so your next stream just picks it up.
62
+ - **Auto Episode Navigation:** When streaming a torrent with ≥ 2 video files **without** pre-selecting anything, the CLI fetches metadata via `aria2c`, queues every video file in episode order (using filename patterns like `S01E01`, ` - 01`, `[01]`, `Episode 01`, or ` E01` when present; alphabetical fallback otherwise), and enables `n` (next) / `b` (previous) hotkeys so you can jump between episodes mid-session. Single-file movies still stream as-is — no forced picker, no extra wait.
63
+ - **Subtitle Download:** Search and download the best matching subtitles directly from the terminal using `subliminal`. Enter one or more languages separated by commas (e.g. `eng, por` or `pt-BR`) — accepts ISO codes (`eng`/`en`) and regional variants (`pt-BR`, `pt-PT`). Every available language is downloaded, the first in your order becomes the primary VLC track (the rest attach as switchable tracks), and any language it couldn't find is reported. If a matching video has already been downloaded, it hash-matches the real file for frame-accurate sync; otherwise it matches on the release name. Configuring OpenSubtitles.com credentials greatly improves results (see *Subtitle providers* below). For Anime searches, a dedicated **Jimaku** lookup (jimaku.cc) runs first when a `JIMAKU_API_KEY` is set, since the western-TV providers behind subliminal don't index anime fansubs well.
64
+ - **Configurable Download Folder:** A **📁 Save to:** row in the Download Method menu lets you set a persistent default download directory used by `aria2c`, `webtorrent`, `peerflix` downloads and the subtitle downloader. Picker offers `Default (downloads/)`, `~/Downloads`, or a custom path (created on-the-fly if missing). Streams and magnet-to-client handoff are unaffected — they use their own paths.
65
+ - **Clipboard Integration:** Easily copy magnet links directly to your OS clipboard (Windows/macOS/Linux).
66
+ - **Seamless Error Recovery:** If a terminal download fails, lacks dependencies, or is manually forcefully aborted by you (`Ctrl+C`), the CLI intercepts the exit and safely drops you back into the download method selector without losing your active search context.
67
+ - **Network Exposure Warning:** At startup a red panel queries `ip-api.com` and shows your public IP, ISP, ASN, location, plus flags for `proxy` / `hosting` / `mobile`. Gives you a clear go/no-go decision before joining a public swarm.
68
+ - **Update Notice for Git Clones:** When the project is installed from a git clone, the provider screen can show a lightweight update notice when the local branch is behind `origin`.
69
+ - **Pagination & Navigation:** Navigate through large sets of search results cleanly, with the ability to safely go back to your previous search results after viewing download options.
70
+
71
+ ## Prerequisites
72
+
73
+ - **Python 3.10+**
74
+ - (Optional but recommended) **Node.js** & **npm** for installing `webtorrent-cli` or `peerflix`.
75
+ - (Optional) **VLC Media Player** — required for streaming.
76
+ - (Optional) **aria2** — required for the file browser / episode picker, the in-torrent subtitle auto-detect path, auto episode navigation on the peerflix backend, and single-process multi-file downloads. Install with `winget install aria2.aria2` (Windows), `brew install aria2` (macOS), or `apt install aria2` / `dnf install aria2` (Linux).
77
+
78
+ ## Installation
79
+
80
+ ### Clone and install Python dependencies
81
+
82
+ ```bash
83
+ git clone https://github.com/PietroFilippo/movie-finder-cli.git
84
+ cd movie-finder-cli
85
+ python -m pip install -r requirements.txt
86
+ ```
87
+
88
+ ### Optional direct download / streaming tools
89
+
90
+ Install these only if you want terminal-managed downloads or Stream to VLC:
91
+
92
+ ```bash
93
+ npm install -g webtorrent-cli peerflix
94
+ ```
95
+
96
+ `aria2c` is separate from Python/npm and is required for file browsing, strict multi-file selection, in-torrent subtitle extraction, and some auto episode metadata flows.
97
+
98
+ ```bash
99
+ # Windows
100
+ winget install aria2.aria2
101
+
102
+ # macOS
103
+ brew install aria2
104
+
105
+ # Debian/Ubuntu
106
+ sudo apt install aria2
107
+ ```
108
+
109
+ ### Credentials (optional)
110
+
111
+ Several features improve with — or, for RuTracker, require — an account.
112
+ Credentials are read at runtime from environment variables (preferred) or a
113
+ gitignored `subtitle_credentials.json` next to the code — **never commit real
114
+ values**.
115
+
116
+ The easiest way to set them is in-program: on the **Select Provider** screen,
117
+ choose **🔑 Credentials**. For each provider you can view, enter/update,
118
+ or clear its login. Entering opens a single-screen form — edit every field in
119
+ place (Up/Down or Tab to move, Enter to advance, **Esc** to cancel) and Save
120
+ when done. Saved values are verified against the provider (where possible) and
121
+ written to `subtitle_credentials.json`; the view screen masks the password / API
122
+ key with a toggle to reveal them. Environment variables, if set, **override** the
123
+ file (the menu flags this), and **Clear only empties the file** — unset the
124
+ matching environment variables to remove a credential that's set there.
125
+
126
+ - **OpenSubtitles.com** (movies & series): a free account dramatically improves
127
+ results and unlocks hash-accurate matching against a downloaded file.
128
+ - **Addic7ed** (TV series): a free account raises rate limits and quality for
129
+ episodic content. Runs anonymously (limited) when no credentials are set.
130
+ - **Jimaku** (anime): a free API key (jimaku.cc → account settings) enables a
131
+ dedicated anime subtitle lookup that runs before subliminal for Anime
132
+ searches. Without the key, Anime falls back to subliminal automatically.
133
+ - **RuTracker** (the RuTracker provider): a free [rutracker.org](https://rutracker.org)
134
+ account is **required** — the provider logs in to search and returns nothing
135
+ without one. This is the only credential that gates a whole provider rather
136
+ than just enhancing subtitle results.
137
+ - **Online-Fix** (the Online-Fix provider): **optional.** Both search and
138
+ `.torrent` download work anonymously ([online-fix.me](https://online-fix.me)'s
139
+ file host is referer-gated, not login-gated). A login is supported (the site's
140
+ DataLife Engine `authtoken` flow) for completeness but isn't required.
141
+ - **TMDB** (Movies & Series "by director / studio"): **optional.** That search
142
+ already works keyless via Wikidata; a free [TMDB](https://www.themoviedb.org)
143
+ v3 API key (account → Settings → API) upgrades it to richer, better-ranked
144
+ results.
145
+ - **IGDB** (Games "by developer / publisher"): **optional.** That search already
146
+ works keyless via Wikidata; free Twitch/IGDB credentials (register an app at
147
+ [dev.twitch.tv](https://dev.twitch.tv) → Client ID + Client Secret) upgrade it.
148
+
149
+ subliminal queries a curated set of providers — `opensubtitlescom`, `addic7ed`,
150
+ `podnapisi`, `tvsubtitles` — chosen for broad coverage and reliability. The rest
151
+ of subliminal's defaults (defunct legacy APIs, VIP-only variants, and
152
+ single-language scrapers) are skipped.
153
+
154
+ Set them as environment variables:
155
+
156
+ ```powershell
157
+ # Windows (persists for new terminals)
158
+ [Environment]::SetEnvironmentVariable("OPENSUBTITLES_USERNAME", "your_user", "User")
159
+ [Environment]::SetEnvironmentVariable("OPENSUBTITLES_PASSWORD", "your_pass", "User")
160
+ [Environment]::SetEnvironmentVariable("ADDIC7ED_USERNAME", "your_user", "User")
161
+ [Environment]::SetEnvironmentVariable("ADDIC7ED_PASSWORD", "your_pass", "User")
162
+ [Environment]::SetEnvironmentVariable("JIMAKU_API_KEY", "your_key", "User")
163
+ [Environment]::SetEnvironmentVariable("RUTRACKER_USERNAME", "your_user", "User")
164
+ [Environment]::SetEnvironmentVariable("RUTRACKER_PASSWORD", "your_pass", "User")
165
+ [Environment]::SetEnvironmentVariable("ONLINE_FIX_USERNAME", "your_user", "User")
166
+ [Environment]::SetEnvironmentVariable("ONLINE_FIX_PASSWORD", "your_pass", "User")
167
+ [Environment]::SetEnvironmentVariable("TMDB_API_KEY", "your_key", "User")
168
+ [Environment]::SetEnvironmentVariable("IGDB_CLIENT_ID", "your_id", "User")
169
+ [Environment]::SetEnvironmentVariable("IGDB_CLIENT_SECRET", "your_secret", "User")
170
+ ```
171
+
172
+ ```bash
173
+ # macOS / Linux (add to your shell profile)
174
+ export OPENSUBTITLES_USERNAME="your_user"
175
+ export OPENSUBTITLES_PASSWORD="your_pass"
176
+ export ADDIC7ED_USERNAME="your_user"
177
+ export ADDIC7ED_PASSWORD="your_pass"
178
+ export JIMAKU_API_KEY="your_key"
179
+ export RUTRACKER_USERNAME="your_user"
180
+ export RUTRACKER_PASSWORD="your_pass"
181
+ export ONLINE_FIX_USERNAME="your_user"
182
+ export ONLINE_FIX_PASSWORD="your_pass"
183
+ export TMDB_API_KEY="your_key"
184
+ export IGDB_CLIENT_ID="your_id"
185
+ export IGDB_CLIENT_SECRET="your_secret"
186
+ ```
187
+
188
+ Or create `subtitle_credentials.json` (already gitignored) in the repo folder:
189
+
190
+ ```json
191
+ {
192
+ "opensubtitles_username": "your_user",
193
+ "opensubtitles_password": "your_pass",
194
+ "addic7ed_username": "your_user",
195
+ "addic7ed_password": "your_pass",
196
+ "jimaku_api_key": "your_key",
197
+ "rutracker_username": "your_user",
198
+ "rutracker_password": "your_pass",
199
+ "online_fix_username": "your_user",
200
+ "online_fix_password": "your_pass",
201
+ "tmdb_api_key": "your_key",
202
+ "igdb_client_id": "your_id",
203
+ "igdb_client_secret": "your_secret"
204
+ }
205
+ ```
206
+
207
+ Environment variables take precedence over the file. All keys are optional —
208
+ anything unset just falls back to the anonymous provider set.
209
+
210
+ ### Run `torrent` from anywhere on Windows
211
+
212
+ The repository includes `torrent.bat`, which launches `main.py` relative to the repo folder. Add the repo folder to your user `PATH`, then open a new terminal:
213
+
214
+ ```powershell
215
+ # Run from the repository root in PowerShell
216
+ $repo = (Get-Location).Path
217
+ $userPath = [Environment]::GetEnvironmentVariable("Path", "User")
218
+ if (($userPath -split ';') -notcontains $repo) {
219
+ $newPath = @($userPath, $repo) -join ';'
220
+ [Environment]::SetEnvironmentVariable("Path", $newPath.Trim(';'), "User")
221
+ }
222
+ ```
223
+
224
+ After opening a new terminal, this works from any directory:
225
+
226
+ ```bash
227
+ torrent
228
+ torrent -q "The Matrix" -t movie -y
229
+ ```
230
+
231
+ If you do not add the repo folder to `PATH`, run `torrent.bat` or `python main.py` from the repository folder.
232
+
233
+ ## Usage
234
+
235
+ ### Interactive Mode
236
+
237
+ The easiest way to use the CLI is to run it interactively. The arrow-key driven UI will guide you through selecting a category, searching, filtering, and downloading.
238
+
239
+ ```bash
240
+ # If the repo folder is on your PATH (Windows)
241
+ torrent
242
+
243
+ # From the repository folder
244
+ torrent.bat
245
+ python main.py
246
+ ```
247
+
248
+ ### Command Line Arguments
249
+
250
+ ```bash
251
+ # Direct search (defaults to Movies)
252
+ torrent -q "The Matrix"
253
+
254
+ # Specify the search type (movie, game, online-fix, software, mobile, rutracker, anime, manga). `movie` covers both films and series.
255
+ torrent -q "Elden Ring" -t game
256
+
257
+ # Search Online-Fix (co-op / online game cracks from online-fix.me; no account needed)
258
+ torrent -q "Elden Ring" -t online-fix
259
+
260
+ # Search desktop software (The Pirate Bay Applications + SolidTorrents)
261
+ torrent -q "Photoshop" -t software
262
+
263
+ # Search Android apps (The Pirate Bay Android category; Android-only)
264
+ torrent -q "Spotify" -t mobile
265
+
266
+ # Search RuTracker (requires a configured rutracker.org login)
267
+ torrent -q "Photoshop" -t rutracker
268
+
269
+ # Search manga (Nyaa Literature English + Apibay Comics; Raw Nyaa available as a toggle)
270
+ torrent -q "Berserk" -t manga
271
+
272
+ # Apply custom filters (include "1080p", exclude "cam")
273
+ torrent -q "Dune" -t movie -f "1080p" -x "cam"
274
+
275
+ # Search by creator: --by <role> --name "<creator>" with -t. Roles per provider:
276
+ # anime/movie -> director, studio manga -> writer, magazine game -> developer, publisher
277
+ torrent -t anime --by director --name "Hayao Miyazaki"
278
+ torrent -t movie --by studio --name "A24"
279
+ torrent -t game --by developer --name "FromSoftware"
280
+ # Drops you into the disambiguation + title picker; keyless by default,
281
+ # richer with a TMDB key (movies) or IGDB creds (games).
282
+
283
+ # Skip the network exposure warning at startup
284
+ torrent -y
285
+ ```
286
+
287
+ You can also suppress the warning with the environment variable `TORRENT_SKIP_WARNING=1`, or permanently dismiss it from inside the panel itself (see below).
288
+
289
+ If you did not add the repo folder to `PATH`, replace `torrent` with `python main.py` in the examples above.
290
+
291
+ ### Network Exposure Warning
292
+
293
+ On launch you'll see a red panel listing your public IP, ISP, ASN and location, with a verdict line:
294
+
295
+ - ✓ **Proxy/VPN flagged** — detected by the IP database.
296
+ - ✓ **Hosting/datacenter IP** — likely a VPN exit (not a residential ISP).
297
+ - ✓ **VPN provider name detected** — keyword fallback (Mullvad, Proton, Nord, …).
298
+ - ⚠ **Mobile carrier IP** — your carrier and peers will see this IP.
299
+ - ⚠ **Residential ISP IP** — your real IP is visible to every peer and tracker.
300
+
301
+ Controls inside the panel:
302
+
303
+ - **Enter** — acknowledge and continue.
304
+ - **D** — don't show again (saved to `filter_state.json`).
305
+ - **Esc** — abort the program.
306
+
307
+ Even after dismissing, you can re-open the warning at any time from the **Select Provider** screen: scroll to the 🔒 **Network exposure info** item and press Enter.
308
+
309
+ ### Navigating the UI
310
+
311
+ - **Lists & Menus**: Use `Up` and `Down` arrows to navigate.
312
+ - **Select**: Press `Enter` to confirm a choice or open a torrent.
313
+ - **Toggle**: In multi-select menus (like Filters), press `Enter` or `Space` on an item to toggle its checkbox.
314
+ - **Range Selection (Episode Picker)**:
315
+ - `v`: Drop a visual anchor on the current item.
316
+ - `Shift + V`: Instantly mass-toggle all items between the anchor and your cursor.
317
+ - `a` (Select All) • `i` (Invert Selection) • `c` (Clear) • `w` (Save & Continue).
318
+ - **Configure filters from the provider screen**: Press `F` while a provider is highlighted to jump straight into its engines + filter presets menu, then return to the provider list.
319
+ - **Filter menu keybinds**: `a` select all, `i` invert, `c` clear presets, `w` save & confirm, `v` drop anchor, `Shift+V` range toggle between anchor and cursor, `Space` toggle current. The "Clear filters" button clears preset toggles only — your engine selections are preserved.
320
+ - **History / stats / tips / filters**: On the provider screen press `H` (history), `S` (stats), `T` (tips), or `F` (filters). At the search prompt, press `Tab` for the same quick-actions menu (then `F`/`H`/`S`/`T` or arrows) — your in-progress query is preserved. The prompt itself has no single-letter shortcuts, so queries can start with any letter.
321
+ - **Tips browser**: Use `/` to search across categories, tip text, and tags; `C` to cycle categories; `X` to clear the search/filter; and `Esc` to go back.
322
+ - **Cancel / Back**: Press `Esc` to safely cancel an action, close a menu, or go back to the previous screen.
323
+
324
+
325
+ ## Project Architecture
326
+
327
+ The application is structured into a modular, provider-based architecture:
328
+
329
+ - `main.py`: The main entry point and CLI argument parser.
330
+ - `torrent.bat`: Windows launcher. It calls `main.py` relative to the batch file location, so adding the repo folder to `PATH` makes `torrent` usable from any directory.
331
+ - `providers/`: Different search categories (Movies & Series, General games, Online-Fix, Desktop, Mobile, RuTracker, Anime, Manga). The display menu nests some of these under groups — **Games** (General + Online-Fix) and **Software** (Desktop + Mobile + RuTracker) — via `ProviderGroup`, a display-only wrapper that changes menu shape without touching slugs. Each provider declares an immutable `slug` (used for persistence keys + CLI `-t` lookup), a display `name` (free to change), capability flags (`supports_subtitles`, `supports_episode_picker` — gate UI rows), its search engines, default filters, and toggleable presets. Nyaa-backed providers also set `nyaa_category` (the Nyaa `c` filter — e.g. `1_2` anime, `4_1` live-action, `3_1` manga). Providers may also declare a `creator_facets` list to enable search-by-creator (director/studio/writer/magazine/developer/publisher).
332
+ - `resolvers/`: The "search by creator" metadata layer that turns a person/company name into a list of works. `types.py` (`CreatorFacet` / `Entity` / `Work`), `anilist.py` (anime director & studio + manga writer, keyless GraphQL), `jikan.py` (manga serialization magazines, keyless), `wikidata.py` (keyless SPARQL fallback for movie/series director & studio and game developer & publisher), `tmdb.py` (Movies & Series, needs `TMDB_API_KEY`), `igdb.py` (Games, needs Twitch creds), and `movies.py` / `games.py` which dispatch to TMDB/IGDB when a key is configured and Wikidata otherwise. Each facet exposes `search_entities(name)` → candidates and `list_works(entity, page)` → `(works, has_more)`; `creator_search.fan_out()` then runs the normal provider search over each picked title and merges. `main._available_facets` can gate facets behind a credential when there's no keyless fallback.
333
+ - `ui/`: Interactive terminal prompts and rendering using `rich`. `prompts.py` (menus + `confirm_prompt` modal + `subtitle_source_prompt` + `download_dir_prompt` + the per-provider "choose how to search" source screen), `creator.py` (the search-by-creator flow: name → disambiguation → paged title picker with `n`/`p` + background prefetch → fan-out), `selector.py` (reusable arrow-key selector with windowing / marquee), `table.py` (paginated result table), `history.py` (search history browser), `stats.py` (usage stats page), `streaming.py` (themed Panel header + terminal-control primitives for the streaming flow), `tips.py` (categorized tip catalog), and `tips_page.py` (searchable tips browser).
334
+ - `filters.py`: Logic processing for including or excluding keywords.
335
+ - `creator_search.py`: `fan_out()` for search-by-creator — runs the provider's normal `search()` over each picked title concurrently and merges (dedupe by info hash, sort by seeders), tagging each result with the title it came from.
336
+ - `credentials.py`: Reads optional API credentials from environment variables (preferred) or the gitignored `subtitle_credentials.json`; powers the **🔑 Credentials** menu (subtitle logins, RuTracker/Online-Fix, and the TMDB/IGDB creator-search upgrades).
337
+ - `torrent_session.py`: Post-torrent-pick state owner. Holds the picked magnet + user file selection + sub choice, and lazily resolves `files_meta` / `targets` / `stream_indexes` / `download_indexes` / `sub_paths`. Stream adapters consume the session directly; download adapters take `(magnet, indexes)` projections and stay session-unaware.
338
+ - `downloader.py`: Subprocess orchestration — `aria2c` / `webtorrent-cli` / `peerflix` execution, VLC launch + sub injection, quiet-mode plumbing, in-torrent sub batch fetch, and `v` / `n` / `b` hotkey handling. Stream adapters take a `TorrentSession`; download adapters keep an explicit `(magnet, indexes)` signature for reuse outside the menu loop.
339
+ - `subtitles.py`: Logic for searching and downloading subtitles using `subliminal`. Saves into the effective download folder via `constants.get_download_dir()`.
340
+ - `security.py`: Network exposure warning, public-IP/VPN detection via `ip-api.com`.
341
+ - `state.py`: Persists engine toggles, active presets, misc settings (dismissed-warning flag, quiet-mode flag, `download_dir`), and search history to `filter_state.json`. Backed by an in-memory cache: mutations mark dirty, disk write happens at `atexit` and at three destructive sites (`save_state`, `clear_history`, `reset_stats`). Includes a one-shot migration that rewrites legacy display-name keys (e.g. `"Movies & Series"`) to provider slugs.
342
+ - `stats.py`: Usage counter recorders and read helpers; stores under the `stats` subtree, keyed by provider slug. Same in-memory cache flow as `state.py`.
343
+ - `torrent_meta.py`: Fetches a torrent's file list from a magnet via `aria2c`. Helpers for episode-number extraction, video/subtitle classification, multi-episode detection (any torrent with ≥ 2 video files), sub-to-video matching (`match_subtitles_for`), and `--select-file` range formatting.
344
+ - `updates.py`: Lightweight git-clone update notice. It rate-limits remote checks in `filter_state.json` and reports when the local branch is behind `origin`.
345
+ - `constants.py`: Configuration constants, trackers, UI themes, and `get_download_dir()` (returns the user's chosen `download_dir` setting or falls back to `DOWNLOADS_DIR`).
346
+
347
+ ## Security Notes
348
+
349
+ This tool does **not** make torrenting safe. Some things it cannot guarantee:
350
+
351
+ - Your real IP is visible to every peer and tracker in the swarm unless you are behind a VPN.
352
+ - Trackers in `constants.py` are plain UDP — there is no "tracker-over-HTTPS" that hides your IP, since trackers exist to exchange peer IPs.
353
+ - Seed counts, file names, and uploader tags are not safety signals. The "Trusted Uploaders" preset is a convenience filter based on community reputation, not a guarantee of clean content.
354
+ - The startup `ip-api.com` call travels over plain HTTP (free tier limitation). If that matters to you, use `-y` or `TORRENT_SKIP_WARNING=1`.
355
+
356
+ Use a VPN, verify content before running installers, and treat everything in a public swarm as untrusted.