qBitrr2 4.10.9__py3-none-any.whl → 5.4.5__py3-none-any.whl

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 (59) hide show
  1. qBitrr/arss.py +2165 -889
  2. qBitrr/auto_update.py +382 -0
  3. qBitrr/bundled_data.py +3 -2
  4. qBitrr/config.py +20 -3
  5. qBitrr/db_lock.py +79 -0
  6. qBitrr/env_config.py +19 -7
  7. qBitrr/gen_config.py +287 -26
  8. qBitrr/logger.py +87 -3
  9. qBitrr/main.py +453 -101
  10. qBitrr/search_activity_store.py +88 -0
  11. qBitrr/static/assets/ArrView.js +2 -0
  12. qBitrr/static/assets/ArrView.js.map +1 -0
  13. qBitrr/static/assets/ConfigView.js +4 -0
  14. qBitrr/static/assets/ConfigView.js.map +1 -0
  15. qBitrr/static/assets/LogsView.js +230 -0
  16. qBitrr/static/assets/LogsView.js.map +1 -0
  17. qBitrr/static/assets/ProcessesView.js +2 -0
  18. qBitrr/static/assets/ProcessesView.js.map +1 -0
  19. qBitrr/static/assets/app.css +1 -0
  20. qBitrr/static/assets/app.js +11 -0
  21. qBitrr/static/assets/app.js.map +1 -0
  22. qBitrr/static/assets/build.svg +3 -0
  23. qBitrr/static/assets/check-mark.svg +5 -0
  24. qBitrr/static/assets/close.svg +4 -0
  25. qBitrr/static/assets/download.svg +5 -0
  26. qBitrr/static/assets/gear.svg +5 -0
  27. qBitrr/static/assets/lidarr.svg +1 -0
  28. qBitrr/static/assets/live-streaming.svg +8 -0
  29. qBitrr/static/assets/log.svg +3 -0
  30. qBitrr/static/assets/plus.svg +4 -0
  31. qBitrr/static/assets/process.svg +15 -0
  32. qBitrr/static/assets/react-select.esm.js +14 -0
  33. qBitrr/static/assets/react-select.esm.js.map +1 -0
  34. qBitrr/static/assets/refresh-arrow.svg +3 -0
  35. qBitrr/static/assets/table.js +23 -0
  36. qBitrr/static/assets/table.js.map +1 -0
  37. qBitrr/static/assets/trash.svg +8 -0
  38. qBitrr/static/assets/up-arrow.svg +3 -0
  39. qBitrr/static/assets/useInterval.js +2 -0
  40. qBitrr/static/assets/useInterval.js.map +1 -0
  41. qBitrr/static/assets/vendor.js +33 -0
  42. qBitrr/static/assets/vendor.js.map +1 -0
  43. qBitrr/static/assets/visibility.svg +9 -0
  44. qBitrr/static/index.html +47 -0
  45. qBitrr/static/manifest.json +23 -0
  46. qBitrr/static/sw.js +105 -0
  47. qBitrr/static/vite.svg +1 -0
  48. qBitrr/tables.py +44 -0
  49. qBitrr/utils.py +82 -15
  50. qBitrr/versioning.py +136 -0
  51. qBitrr/webui.py +2612 -0
  52. qbitrr2-5.4.5.dist-info/METADATA +1116 -0
  53. qbitrr2-5.4.5.dist-info/RECORD +61 -0
  54. {qBitrr2-4.10.9.dist-info → qbitrr2-5.4.5.dist-info}/WHEEL +1 -1
  55. qBitrr2-4.10.9.dist-info/METADATA +0 -233
  56. qBitrr2-4.10.9.dist-info/RECORD +0 -19
  57. {qBitrr2-4.10.9.dist-info → qbitrr2-5.4.5.dist-info}/entry_points.txt +0 -0
  58. {qBitrr2-4.10.9.dist-info → qbitrr2-5.4.5.dist-info/licenses}/LICENSE +0 -0
  59. {qBitrr2-4.10.9.dist-info → qbitrr2-5.4.5.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,1116 @@
1
+ Metadata-Version: 2.4
2
+ Name: qBitrr2
3
+ Version: 5.4.5
4
+ Summary: Intelligent automation for qBittorrent and *Arr apps (Radarr/Sonarr/Lidarr) - health monitoring, instant imports, quality upgrades, request integration
5
+ Home-page: https://github.com/Feramance/qBitrr
6
+ Author: Feramance
7
+ Author-email: fera@fera.wtf
8
+ License: MIT
9
+ Project-URL: Homepage, https://github.com/Feramance/qBitrr
10
+ Project-URL: Documentation, https://github.com/Feramance/qBitrr/blob/master/API_DOCUMENTATION.md
11
+ Project-URL: Issue Tracker, https://github.com/Feramance/qBitrr/issues
12
+ Project-URL: Source Code, https://github.com/Feramance/qBitrr
13
+ Project-URL: Changelog, https://github.com/Feramance/qBitrr/blob/master/CHANGELOG.md
14
+ Project-URL: Docker Hub, https://hub.docker.com/r/feramance/qbitrr
15
+ Project-URL: PyPI, https://pypi.org/project/qBitrr2/
16
+ Project-URL: Systemd Guide, https://github.com/Feramance/qBitrr/blob/master/SYSTEMD_SERVICE.md
17
+ Keywords: qbittorrent,radarr,sonarr,lidarr,arr,automation,torrent,media,plex,jellyfin,overseerr,ombi
18
+ Classifier: Development Status :: 5 - Production/Stable
19
+ Classifier: Intended Audience :: Developers
20
+ Classifier: Intended Audience :: End Users/Desktop
21
+ Classifier: Intended Audience :: System Administrators
22
+ Classifier: License :: OSI Approved :: MIT License
23
+ Classifier: Natural Language :: English
24
+ Classifier: Operating System :: MacOS :: MacOS X
25
+ Classifier: Operating System :: Microsoft :: Windows
26
+ Classifier: Operating System :: POSIX :: Linux
27
+ Classifier: Programming Language :: Python :: 3 :: Only
28
+ Classifier: Programming Language :: Python :: 3.12
29
+ Classifier: Programming Language :: Python :: Implementation :: CPython
30
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
31
+ Classifier: Topic :: Communications
32
+ Classifier: Topic :: Internet
33
+ Classifier: Topic :: Multimedia :: Video
34
+ Classifier: Topic :: System :: Monitoring
35
+ Classifier: Topic :: Terminals
36
+ Classifier: Topic :: Utilities
37
+ Classifier: Typing :: Typed
38
+ Requires-Python: <4,>=3.12
39
+ Description-Content-Type: text/markdown
40
+ License-File: LICENSE
41
+ Requires-Dist: cachetools
42
+ Requires-Dist: colorama
43
+ Requires-Dist: coloredlogs
44
+ Requires-Dist: flask
45
+ Requires-Dist: environ-config
46
+ Requires-Dist: ffmpeg-python
47
+ Requires-Dist: jaraco.docker
48
+ Requires-Dist: packaging
49
+ Requires-Dist: pathos
50
+ Requires-Dist: peewee
51
+ Requires-Dist: ping3
52
+ Requires-Dist: pyarr
53
+ Requires-Dist: qbittorrent-api
54
+ Requires-Dist: requests
55
+ Requires-Dist: tomlkit
56
+ Requires-Dist: waitress
57
+ Requires-Dist: croniter
58
+ Provides-Extra: dev
59
+ Requires-Dist: black==24.3.0; extra == "dev"
60
+ Requires-Dist: bump2version==1.0.1; extra == "dev"
61
+ Requires-Dist: isort==5.10.1; extra == "dev"
62
+ Requires-Dist: pip-tools==7.3.0; extra == "dev"
63
+ Requires-Dist: pre-commit==3.3.3; extra == "dev"
64
+ Requires-Dist: pyinstaller==5.13.1; extra == "dev"
65
+ Requires-Dist: pyupgrade==2.31.0; extra == "dev"
66
+ Requires-Dist: twine==3.7.1; extra == "dev"
67
+ Requires-Dist: ujson==5.10.0; extra == "dev"
68
+ Requires-Dist: upgrade-pip==0.1.4; extra == "dev"
69
+ Provides-Extra: fast
70
+ Requires-Dist: ujson==5.10.0; extra == "fast"
71
+ Provides-Extra: all
72
+ Requires-Dist: black==24.3.0; extra == "all"
73
+ Requires-Dist: bump2version==1.0.1; extra == "all"
74
+ Requires-Dist: isort==5.10.1; extra == "all"
75
+ Requires-Dist: pip-tools==7.3.0; extra == "all"
76
+ Requires-Dist: pre-commit==3.3.3; extra == "all"
77
+ Requires-Dist: pyinstaller==5.13.1; extra == "all"
78
+ Requires-Dist: pyupgrade==2.31.0; extra == "all"
79
+ Requires-Dist: twine==3.7.1; extra == "all"
80
+ Requires-Dist: ujson==5.10.0; extra == "all"
81
+ Requires-Dist: upgrade-pip==0.1.4; extra == "all"
82
+ Requires-Dist: ujson==5.10.0; extra == "all"
83
+ Dynamic: license-file
84
+
85
+ # qBitrr
86
+
87
+ [![PyPI](https://img.shields.io/pypi/v/qBitrr2?label=PyPI)](https://pypi.org/project/qBitrr2/)
88
+ [![Downloads](https://img.shields.io/pypi/dm/qBitrr2)](https://pypi.org/project/qBitrr2/)
89
+ [![Docker Pulls](https://img.shields.io/docker/pulls/feramance/qbitrr.svg)](https://hub.docker.com/r/feramance/qbitrr)
90
+ [![CodeQL](https://github.com/Feramance/qBitrr/actions/workflows/codeql.yml/badge.svg?branch=master)](https://github.com/Feramance/qBitrr/actions/workflows/codeql.yml)
91
+ [![Nightly Build](https://github.com/Feramance/qBitrr/actions/workflows/nightly.yml/badge.svg?branch=master)](https://github.com/Feramance/qBitrr/actions/workflows/nightly.yml)
92
+ [![pre-commit.ci](https://results.pre-commit.ci/badge/github/Feramance/qBitrr/master.svg)](https://results.pre-commit.ci/latest/github/Feramance/qBitrr/master)
93
+ [![License: MIT](https://img.shields.io/pypi/l/qbitrr)](LICENSE)
94
+
95
+ > 🧩 qBitrr keeps qBittorrent, Radarr, Sonarr, Lidarr, and your request tools chatting happily so downloads finish, import, and clean up without babysitting.
96
+
97
+ ## 📚 What's Inside
98
+ - [Overview](#-overview)
99
+ - [Core Features](#-core-features)
100
+ - [State of the Project](#-state-of-the-project)
101
+ - [Quickstart](#-quickstart)
102
+ - [Install with pip](#install-with-pip)
103
+ - [Run with Docker](#run-with-docker)
104
+ - [Native Systemd Service](#native-systemd-service)
105
+ - [Configuration](#-configuration)
106
+ - [Feature Deep Dive](#-feature-deep-dive)
107
+ - [Torrent Health Monitoring](#-torrent-health-monitoring)
108
+ - [Automated Search & Requests](#-automated-search--requests)
109
+ - [Quality Management](#-quality-management)
110
+ - [Seeding & Tracker Control](#-seeding--tracker-control)
111
+ - [Disk Space Management](#-disk-space-management)
112
+ - [Auto-Updates & Restarts](#-auto-updates--restarts)
113
+ - [Built-in Web UI](#-built-in-web-ui)
114
+ - [Day-to-day Operations](#-day-to-day-operations)
115
+ - [Troubleshooting](#-troubleshooting)
116
+ - [Contributing](#-contributing)
117
+ - [Support](#-support)
118
+ - [License](#-license)
119
+
120
+ ## 🧠 Overview
121
+ qBitrr is the intelligent glue between qBittorrent and the *Arr ecosystem (Radarr, Sonarr, Lidarr). It monitors torrent health, triggers instant imports when downloads complete, automates quality upgrades, manages disk space, integrates with request systems (Overseerr/Ombi), and provides a modern React dashboard for complete visibility and control.
122
+
123
+ ## ✨ Core Features
124
+
125
+ ### 🚑 Torrent Health & Import Management
126
+ - **Instant imports** – trigger `DownloadedMoviesScan`/`DownloadedEpisodesScan` the moment torrents finish
127
+ - **Stalled torrent detection** – identify and handle stuck/slow downloads with configurable thresholds
128
+ - **Failed download handling** – automatically blacklist failed torrents in Arr instances and trigger re-searches
129
+ - **FFprobe verification** – validate media files are playable before import (auto-downloads FFprobe binary)
130
+ - **Smart file filtering** – exclude samples, extras, trailers via regex and extension allowlists
131
+
132
+ ### 🔍 Automated Search & Request Integration
133
+ - **Missing media search** – automatically search for missing movies/episodes/albums on schedules
134
+ - **Quality upgrade search** – find better releases for existing media based on quality profiles
135
+ - **Custom format scoring** – search for releases meeting minimum custom format scores
136
+ - **Overseerr/Ombi integration** – auto-pull and prioritize user requests from request management tools
137
+ - **Smart search modes** – series-level or episode-level search for TV shows based on context
138
+ - **Temporary quality profiles** – use lower quality profiles for missing items, upgrade later
139
+
140
+ ### 📊 Quality & Metadata Management
141
+ - **RSS sync automation** – schedule periodic RSS feed refreshes across all Arr instances
142
+ - **Queue management** – auto-refresh download queues to keep Arr instances in sync
143
+ - **Custom format enforcement** – automatically remove torrents not meeting minimum CF scores
144
+ - **Quality profile switching** – dynamically change profiles for missing vs. upgrade searches
145
+ - **Year-based search ordering** – prioritize searches by release date (newest first or reverse)
146
+
147
+ ### 🌱 Seeding & Tracker Control
148
+ - **Per-tracker settings** – configure MaxETA, ratios, seeding time per tracker
149
+ - **Global seeding limits** – set upload/download rate limits, max ratios, and seeding times
150
+ - **Automatic removal** – remove torrents based on ratio, time, or both
151
+ - **Dead tracker cleanup** – auto-remove trackers with specific error messages
152
+ - **Tracker injection** – add missing trackers or remove existing ones per torrent
153
+ - **Super seed mode** – enable super seeding for specific trackers
154
+ - **Tag management** – auto-tag torrents by tracker or custom rules
155
+
156
+ ### 💾 Disk Space & Resource Management
157
+ - **Free space monitoring** – pause all torrents when disk space falls below threshold
158
+ - **Auto pause/resume** – intelligently manage torrent activity based on disk availability
159
+ - **Configurable thresholds** – set limits in KB, MB, GB, or TB
160
+ - **Path-specific monitoring** – watch specific directories for space issues
161
+
162
+ ### 🔄 Auto-Updates & Self-Healing
163
+ - **GitHub release-based updates** – automatically checks for published (non-draft) releases via GitHub API
164
+ - **Scheduled auto-updates** – update qBitrr on a cron schedule (default: weekly Sunday 3 AM)
165
+ - **Manual update trigger** – one-click updates from WebUI
166
+ - **Installation-aware updates** – detects git/pip/binary installs and uses appropriate update method
167
+ - **Version verification** – confirms installed version matches target before restart
168
+ - **Smart restart mechanism** – uses `os.execv()` for true in-place restarts (no supervisor needed)
169
+ - **Cross-platform compatibility** – works in Docker, systemd, native installs, Windows, Linux, macOS
170
+ - **Graceful shutdown** – cleanly closes databases, flushes logs, terminates child processes
171
+
172
+ ### 💻 First-Party Web UI
173
+ - **Live process monitoring** – see all running Arr managers and their current activity
174
+ - **Log viewer** – tail logs in real-time with filtering and search
175
+ - **Arr insights** – view movies, series, albums with filtering by year, quality, status
176
+ - **Config editor** – edit configuration directly from the UI
177
+ - **Restart controls** – restart individual processes or the entire application
178
+ - **Dark/light theme** – customizable UI appearance
179
+ - **Token authentication** – optional API protection with bearer tokens
180
+
181
+ ## 📌 State of the Project
182
+ The long-term plan is still to ship a C# rewrite, but the Python edition isn't going anywhere—it gets regular fixes and features, and the Web UI is now production-ready. Ideas and PRs are welcome! Head over to the [issue templates](.github/ISSUE_TEMPLATE) or the [PR checklist](.github/pull_request_template.md) to get started.
183
+
184
+ ## ⚡ Quickstart
185
+ qBitrr supports Python 3.12+ on Linux, macOS, and Windows. Run it natively or in Docker—whatever fits your stack.
186
+
187
+ ### 🐍 Install with pip
188
+ ```bash
189
+ python -m venv .venv
190
+ source .venv/bin/activate # Windows: .venv\Scripts\activate
191
+ python -m pip install --upgrade pip
192
+ python -m pip install qBitrr2
193
+
194
+ # First run creates ~/config/config.toml
195
+ qBitrr2
196
+ ```
197
+
198
+ **Update later:**
199
+ ```bash
200
+ python -m pip install --upgrade qBitrr2
201
+ ```
202
+
203
+ **Or enable auto-updates** in `config.toml`:
204
+ ```toml
205
+ [Settings]
206
+ AutoUpdateEnabled = true
207
+ AutoUpdateCron = "0 3 * * 0" # Weekly on Sunday at 3 AM
208
+ ```
209
+
210
+ > 📝 **Note:** Auto-updates check GitHub releases for new versions. Only published (non-draft) releases trigger updates. Binary installations receive update notifications but require manual download.
211
+
212
+ ### 🐳 Run with Docker
213
+ **Minimal setup:**
214
+ ```bash
215
+ docker run -d \
216
+ --name qbitrr \
217
+ --tty \
218
+ -e TZ=Europe/London \
219
+ -p 6969:6969 \
220
+ -v /etc/localtime:/etc/localtime:ro \
221
+ -v /path/to/appdata/qbitrr:/config \
222
+ -v /path/to/completed/downloads:/completed_downloads:rw \
223
+ --restart unless-stopped \
224
+ feramance/qbitrr:latest
225
+ ```
226
+
227
+ The container automatically binds its WebUI to `0.0.0.0`; exposing `6969` makes the dashboard reachable at `http://<host>:6969/ui`.
228
+
229
+ **Docker Compose example:**
230
+ ```yaml
231
+ services:
232
+ qbitrr:
233
+ image: feramance/qbitrr:latest
234
+ container_name: qbitrr
235
+ user: 1000:1000
236
+ restart: unless-stopped
237
+ tty: true
238
+ environment:
239
+ TZ: Europe/London
240
+ ports:
241
+ - "6969:6969"
242
+ volumes:
243
+ - /etc/localtime:/etc/localtime:ro
244
+ - /path/to/appdata/qbitrr:/config
245
+ - /path/to/completed/downloads:/completed_downloads:rw
246
+ logging:
247
+ driver: json-file
248
+ options:
249
+ max-size: 50m
250
+ max-file: "3"
251
+ depends_on:
252
+ - qbittorrent
253
+ - radarr
254
+ - sonarr
255
+ ```
256
+
257
+ > ℹ️ On first boot the container writes `config.toml` under `/config`. Update the values to match your mounts and restart the container.
258
+
259
+ ### ⚙️ Native Systemd Service
260
+ For Linux users running qBitrr natively (non-Docker), you can set up automatic startup and restart management using systemd.
261
+
262
+ **Quick setup:**
263
+ ```bash
264
+ # Install qBitrr
265
+ pip install qBitrr2
266
+
267
+ # Copy systemd service file
268
+ sudo cp qbitrr.service /etc/systemd/system/qbitrr.service
269
+
270
+ # Enable and start
271
+ sudo systemctl enable qbitrr
272
+ sudo systemctl start qbitrr
273
+
274
+ # Check status
275
+ sudo systemctl status qbitrr
276
+ ```
277
+
278
+ **Benefits:**
279
+ - ✅ Auto-start on boot
280
+ - ✅ Automatic restarts after crashes or updates
281
+ - ✅ Integrated logging with `journalctl`
282
+ - ✅ Resource limits and security hardening
283
+ - ✅ Works seamlessly with qBitrr's auto-update feature
284
+
285
+ **See the full guide:** [SYSTEMD_SERVICE.md](SYSTEMD_SERVICE.md) for detailed setup instructions, troubleshooting, and security hardening options.
286
+
287
+ ## 🛠️ Configuration
288
+
289
+ ### 📂 Config Location
290
+ - **Native install:** `~/config/config.toml`
291
+ - **Docker:** `/config/config.toml`
292
+ - **First run:** Auto-generates a template config file
293
+ - **Manual generation:** `qbitrr --gen-config`
294
+
295
+ ### 🔧 Essential Setup
296
+ 1. **Configure qBittorrent connection** in `[qBit]` section:
297
+ - Set `Host`, `Port`, `UserName`, `Password`
298
+ - qBittorrent 5.x requires `Version5 = true` (4.6.7 is the latest validated 4.x build)
299
+
300
+ 2. **Configure Arr instances** (Radarr/Sonarr/Lidarr):
301
+ - Each instance needs: `URI`, `APIKey`, `Category`
302
+ - **Important:** Use matching categories in Arr's download client settings
303
+ - **Tagging:** Ensure Arr instances tag their downloads so qBitrr can track them
304
+
305
+ 3. **Set completed download folder:**
306
+ ```toml
307
+ [Settings]
308
+ CompletedDownloadFolder = "/path/to/completed"
309
+ ```
310
+
311
+ 4. **Enable logging** for troubleshooting:
312
+ ```toml
313
+ [Settings]
314
+ Logging = true
315
+ ConsoleLevel = "INFO" # or DEBUG for verbose output
316
+ ```
317
+
318
+ ### 📖 Configuration Reference
319
+ See [`config.example.toml`](config.example.toml) for comprehensive documentation of all settings, including:
320
+ - Torrent health check thresholds
321
+ - Search automation options
322
+ - Seeding limits and tracker rules
323
+ - Request system integration
324
+ - WebUI settings
325
+ - File filtering and exclusion rules
326
+
327
+ ## 🎯 Feature Deep Dive
328
+
329
+ ### 🚑 Torrent Health Monitoring
330
+
331
+ qBitrr continuously monitors your torrents and takes intelligent action when problems arise.
332
+
333
+ **Stalled Torrent Detection:**
334
+ ```toml
335
+ [Radarr-Movies.Torrent]
336
+ StalledDelay = 15 # Minutes before considering a torrent stalled
337
+ ReSearchStalled = true # Re-search before removing stalled torrents
338
+ MaximumETA = 604800 # Max ETA in seconds (7 days)
339
+ IgnoreTorrentsYoungerThan = 600 # Grace period for new torrents (10 min)
340
+ ```
341
+
342
+ **Automatic Blacklisting:**
343
+ When torrents fail or stall beyond thresholds, qBitrr:
344
+ 1. ✅ Marks the release as failed in the Arr instance
345
+ 2. ✅ Blacklists the release to prevent re-download
346
+ 3. ✅ Optionally triggers an automatic re-search
347
+ 4. ✅ Removes the failed torrent from qBittorrent
348
+
349
+ **Smart Completion Rules:**
350
+ ```toml
351
+ [Radarr-Movies.Torrent]
352
+ MaximumDeletablePercentage = 0.99 # Don't delete torrents >99% complete
353
+ DoNotRemoveSlow = true # Protect slow but active torrents
354
+ ```
355
+
356
+ **File Verification:**
357
+ ```toml
358
+ [Settings]
359
+ FFprobeAutoUpdate = true # Auto-download FFprobe binary
360
+ ```
361
+ - Validates media files are playable before import
362
+ - Detects corrupted or fake files
363
+ - Prevents broken media from being imported into Arr
364
+
365
+ **Error Code Handling:**
366
+ ```toml
367
+ [Radarr-Movies]
368
+ ArrErrorCodesToBlocklist = [
369
+ "Not an upgrade for existing movie file(s)",
370
+ "Unable to determine if file is a sample"
371
+ ]
372
+ ```
373
+ Automatically handle specific Arr error messages by removing failed files and triggering re-searches.
374
+
375
+ ---
376
+
377
+ ### 🔍 Automated Search & Requests
378
+
379
+ **Missing Media Search:**
380
+ ```toml
381
+ [Radarr-Movies.EntrySearch]
382
+ SearchMissing = true # Enable automated searching
383
+ SearchLimit = 5 # Max concurrent searches
384
+ SearchByYear = true # Order by release year
385
+ SearchInReverse = false # Newest first (true = oldest first)
386
+ SearchRequestsEvery = 300 # Delay between searches (seconds)
387
+ SearchAgainOnSearchCompletion = true # Loop continuously
388
+ ```
389
+
390
+ **Quality Upgrade Search:**
391
+ ```toml
392
+ [Radarr-Movies.EntrySearch]
393
+ DoUpgradeSearch = true # Search for better quality versions
394
+ QualityUnmetSearch = true # Search for unmet quality profiles
395
+ CustomFormatUnmetSearch = true # Search for better custom format scores
396
+ ForceMinimumCustomFormat = true # Auto-remove torrents below CF threshold
397
+ ```
398
+
399
+ **Overseerr Integration:**
400
+ ```toml
401
+ [Radarr-Movies.EntrySearch.Overseerr]
402
+ SearchOverseerrRequests = true
403
+ OverseerrURI = "http://overseerr:5055"
404
+ OverseerrAPIKey = "your-api-key"
405
+ ApprovedOnly = true # Only process approved requests
406
+ Is4K = false # Set true for 4K Arr instances
407
+ ```
408
+
409
+ **Ombi Integration:**
410
+ ```toml
411
+ [Radarr-Movies.EntrySearch.Ombi]
412
+ SearchOmbiRequests = true
413
+ OmbiURI = "http://ombi:3579"
414
+ OmbiAPIKey = "your-api-key"
415
+ ApprovedOnly = true
416
+ ```
417
+
418
+ **Smart Search Modes (Sonarr):**
419
+ ```toml
420
+ [Sonarr-TV.EntrySearch]
421
+ SearchBySeries = "smart" # auto | true (series) | false (episode)
422
+ # smart: Series search for full seasons, episode search for singles
423
+ PrioritizeTodaysReleases = true # Search today's episodes first (RSS-like)
424
+ AlsoSearchSpecials = false # Include season 00 episodes
425
+ Unmonitored = false # Include unmonitored items
426
+ ```
427
+
428
+ **Temporary Quality Profiles:**
429
+ ```toml
430
+ [Radarr-Movies.EntrySearch]
431
+ UseTempForMissing = true
432
+ KeepTempProfile = false
433
+ MainQualityProfile = ["Ultra-HD", "HD-1080p"]
434
+ TempQualityProfile = ["Web-DL", "HDTV-720p"]
435
+ # Searches missing items with temp profile, switches back after import
436
+ ```
437
+
438
+ ---
439
+
440
+ ### 📊 Quality Management
441
+
442
+ **RSS Sync Automation:**
443
+ ```toml
444
+ [Radarr-Movies]
445
+ RssSyncTimer = 5 # Minutes between RSS feed refreshes (0 = disabled)
446
+ ```
447
+ Keeps Arr instances checking indexers for new releases regularly.
448
+
449
+ **Queue Refresh:**
450
+ ```toml
451
+ [Radarr-Movies]
452
+ RefreshDownloadsTimer = 5 # Minutes between queue updates (0 = disabled)
453
+ ```
454
+ Ensures Arr instances stay in sync with qBittorrent's download state.
455
+
456
+ **Import Mode:**
457
+ ```toml
458
+ [Radarr-Movies]
459
+ importMode = "Auto" # Auto | Move | Copy
460
+ ```
461
+ - **Auto:** Let Arr decide based on its settings
462
+ - **Move:** Move files from download folder to library
463
+ - **Copy:** Copy files (preserves seeding torrents)
464
+
465
+ **Custom Format Score Enforcement:**
466
+ When `ForceMinimumCustomFormat = true`, qBitrr automatically removes torrents that don't meet the minimum custom format score defined in your Arr quality profile.
467
+
468
+ ---
469
+
470
+ ### 🌱 Seeding & Tracker Control
471
+
472
+ **Global Seeding Limits:**
473
+ ```toml
474
+ [Radarr-Movies.Torrent.SeedingMode]
475
+ DownloadRateLimitPerTorrent = -1 # -1 = unlimited, or KB/s
476
+ UploadRateLimitPerTorrent = -1 # -1 = unlimited, or KB/s
477
+ MaxUploadRatio = 2.0 # Stop seeding at 2.0 ratio
478
+ MaxSeedingTime = 604800 # Stop after 7 days (seconds)
479
+ RemoveTorrent = 3 # 1=ratio, 2=time, 3=either, 4=both, -1=never
480
+ ```
481
+
482
+ **Per-Tracker Settings:**
483
+ ```toml
484
+ [[Radarr-Movies.Torrent.Trackers]]
485
+ Name = "MyTracker"
486
+ Priority = 10 # Higher = processed first
487
+ URI = "https://tracker.example/announce"
488
+ MaximumETA = 18000 # Override global MaxETA for this tracker
489
+ DownloadRateLimit = 5000 # KB/s limit for this tracker
490
+ UploadRateLimit = 1000 # KB/s limit for this tracker
491
+ MaxUploadRatio = 1.5 # Tracker-specific ratio limit
492
+ MaxSeedingTime = 86400 # Tracker-specific time limit (1 day)
493
+ AddTrackerIfMissing = true # Inject this tracker into matching torrents
494
+ RemoveIfExists = false # Remove this tracker if found
495
+ SuperSeedMode = true # Enable super seeding for this tracker
496
+ AddTags = ["private", "MyTracker"] # Auto-tag matching torrents
497
+ ```
498
+
499
+ **Tracker Cleanup:**
500
+ ```toml
501
+ [Radarr-Movies.Torrent.SeedingMode]
502
+ RemoveDeadTrackers = true
503
+ RemoveTrackerWithMessage = [
504
+ "skipping tracker announce (unreachable)",
505
+ "No such host is known",
506
+ "unsupported URL protocol"
507
+ ]
508
+ ```
509
+
510
+ **File Filtering:**
511
+ ```toml
512
+ [Radarr-Movies.Torrent]
513
+ CaseSensitiveMatches = false
514
+ FolderExclusionRegex = ["\\bextras?\\b", "\\bsamples?\\b", "\\bfeaturettes?\\b"]
515
+ FileNameExclusionRegex = ["\\bsample\\b", "\\btrailer\\b"]
516
+ FileExtensionAllowlist = [".mp4", ".mkv", ".avi", ".sub", ".srt"]
517
+ AutoDelete = false # Auto-delete non-playable files (.exe, .png, etc.)
518
+ ```
519
+
520
+ ---
521
+
522
+ ### 💾 Disk Space Management
523
+
524
+ **Free Space Monitoring:**
525
+ ```toml
526
+ [Settings]
527
+ FreeSpace = "50G" # Pause when <50GB free (K/M/G/T units)
528
+ FreeSpaceFolder = "/downloads" # Path to monitor
529
+ AutoPauseResume = true # Required for FreeSpace to work
530
+ ```
531
+
532
+ **How it works:**
533
+ 1. 📊 Continuously monitors specified folder
534
+ 2. ⏸️ Pauses **all** torrents when space falls below threshold
535
+ 3. ▶️ Auto-resumes when space is reclaimed
536
+ 4. 🔔 Logs warnings when approaching limit
537
+
538
+ **Disable monitoring:**
539
+ ```toml
540
+ [Settings]
541
+ ### 🔄 Auto-Updates & Restarts
542
+
543
+ qBitrr can automatically update itself by checking GitHub releases for new versions. The update behavior varies by installation type.
544
+
545
+ #### 🔍 How Updates Work
546
+
547
+ **Update Detection:**
548
+ 1. 📡 Queries GitHub API for latest **published** (non-draft) release
549
+ 2. 🔢 Compares release version with current version using semantic versioning
550
+ 3. ⏩ Skips prereleases (beta, rc, alpha) by default
551
+ 4. 📦 Only updates when a newer **stable** version is available
552
+
553
+ **Installation Types:**
554
+
555
+ | Type | Detection | Update Method | Version Control |
556
+ |------|-----------|---------------|-----------------|
557
+ | **Git** | `.git` directory exists | `git checkout <tag>` or `git pull` | Checks out specific release tag |
558
+ | **PyPI** | Installed via pip | `pip install qBitrr2==<version>` | Installs exact version from PyPI |
559
+ | **Binary** | PyInstaller executable | Notification only | Logs download URL for manual update |
560
+
561
+ **Why different methods?**
562
+ - **Git installations** can checkout specific tags for precise version control
563
+ - **PyPI installations** can pin to exact versions for reliability
564
+ - **Binary installations** cannot self-update (would require replacing running executable), so qBitrr logs the download URL and version info for manual update
565
+
566
+ ---
567
+
568
+ #### ⚙️ Configuration
569
+
570
+ **Basic Setup:**
571
+ ```toml
572
+ [Settings]
573
+ AutoUpdateEnabled = true
574
+ AutoUpdateCron = "0 3 * * 0" # Cron expression (default: Sunday 3 AM)
575
+ ```
576
+
577
+ **Cron Expression Examples:**
578
+ ```toml
579
+ "0 3 * * 0" # Every Sunday at 3:00 AM
580
+ "0 */6 * * *" # Every 6 hours
581
+ "0 0 * * *" # Daily at midnight
582
+ "0 2 * * 1-5" # Weekdays at 2:00 AM
583
+ ```
584
+
585
+ ---
586
+
587
+ #### 📋 Update Process Flow
588
+
589
+ **For Git & PyPI Installations:**
590
+
591
+ 1. **Check Phase:**
592
+ - Fetch latest release from GitHub API
593
+ - Validate release is not draft or prerelease
594
+ - Compare versions (semantic versioning)
595
+ - Skip if already on latest version
596
+
597
+ 2. **Download Phase:**
598
+ - **Git:** `git fetch --tags && git checkout v<version>`
599
+ - **PyPI:** `pip install --upgrade qBitrr2==<version>`
600
+
601
+ 3. **Verification Phase:**
602
+ - Reload version information
603
+ - Verify installed version matches target
604
+ - Log warning if mismatch
605
+
606
+ 4. **Restart Phase:**
607
+ - Gracefully shutdown (close DBs, flush logs)
608
+ - Terminate child processes
609
+ - Execute in-place restart via `os.execv()`
610
+ - Maintain same PID (systemd-friendly)
611
+
612
+ **For Binary Installations:**
613
+
614
+ 1. **Check Phase:** Same as above
615
+ 2. **Notification:** Logs message with download URL and instructions
616
+ 3. **Manual Update:** User downloads new binary from GitHub releases
617
+ 4. **No Auto-Restart:** User manually restarts after replacing binary
618
+
619
+ Example binary update log:
620
+ ```
621
+ [INFO] Update available: v5.4.2 -> v5.4.3
622
+ [INFO] Binary installation detected - manual update required
623
+ [INFO] Download: https://github.com/Feramance/qBitrr/releases/latest
624
+ [INFO] Instructions:
625
+ 1. Download the binary for your platform
626
+ 2. Extract the archive
627
+ 3. Replace current executable with new binary
628
+ 4. Restart qBitrr
629
+ ```
630
+
631
+ ---
632
+
633
+ #### 🔧 Manual Updates
634
+
635
+ **Via WebUI:**
636
+ - Navigate to **Config tab**
637
+ - Click **"Check for Updates"** to see available version
638
+ - Click **"Update Now"** button
639
+ - Confirm when prompted
640
+ - Application restarts automatically (git/pip only)
641
+
642
+ **Via Command Line:**
643
+
644
+ ```bash
645
+ # Git installation
646
+ cd /path/to/qBitrr
647
+ git fetch --tags
648
+ git checkout v5.4.3 # or: git pull
649
+ qbitrr # restart
650
+
651
+ # PyPI installation
652
+ pip install --upgrade qBitrr2
653
+ # or: pip install qBitrr2==5.4.3 # specific version
654
+ qbitrr # restart
655
+
656
+ # Binary installation
657
+ # Download from: https://github.com/Feramance/qBitrr/releases/latest
658
+ # Extract and replace binary, then restart
659
+
660
+ # Docker installation
661
+ docker pull feramance/qbitrr:latest
662
+ docker restart qbitrr
663
+ # or: docker-compose pull && docker-compose up -d
664
+ ```
665
+
666
+ ---
667
+
668
+ #### 🔐 Security & Reliability
669
+
670
+ **GitHub API Dependency:**
671
+ - Auto-update requires GitHub API access
672
+ - Rate limit: 60 requests/hour (unauthenticated)
673
+ - Cron schedule should account for rate limits
674
+ - Failures are logged but don't crash the application
675
+
676
+ **Version Verification:**
677
+ - After update, qBitrr verifies installed version
678
+ - Helps catch failed updates or PyPI lag issues
679
+ - Logs warning if version mismatch detected
680
+
681
+ **Draft & Prerelease Handling:**
682
+ - Draft releases are **always skipped** (unpublished)
683
+ - Prereleases (beta/rc/alpha) are skipped by default
684
+ - Useful for testing but not recommended for production
685
+
686
+ **Rollback:**
687
+ - Git installations: `git checkout <previous-tag>`
688
+ - PyPI installations: `pip install qBitrr2==<previous-version>`
689
+ - Binary installations: Keep backup of previous binary
690
+ - No automatic rollback (manual intervention required)
691
+
692
+ ---
693
+
694
+ #### 🚀 Restart Mechanism
695
+
696
+ **How it Works:**
697
+ ```python
698
+ os.execv(sys.executable, [sys.executable] + sys.argv)
699
+ ```
700
+
701
+ **Benefits:**
702
+ - ✅ **Same PID** – systemd doesn't detect a restart
703
+ - ✅ **No supervisor** – doesn't require external process manager
704
+ - ✅ **Clean state** – fresh Python interpreter, no memory leaks
705
+ - ✅ **Fast** – near-instant restart (< 1 second)
706
+
707
+ **Supported Environments:**
708
+ - 🐳 **Docker** – container stays running, process restarts
709
+ - ⚙️ **systemd** – service remains "active", no restart count increment
710
+ - 💻 **Native** – works on Linux, macOS, Windows
711
+ - 🪟 **Windows** – handles different executable extensions (.exe, .cmd)
712
+
713
+ **Graceful Shutdown:**
714
+ 1. Stop all Arr manager child processes
715
+ 2. Close database connections
716
+ 3. Flush log buffers to disk
717
+ 4. Release file locks
718
+ 5. Execute in-place restart
719
+
720
+ ---
721
+
722
+ #### 🛠️ Restart via API
723
+
724
+ **Restart entire application:**
725
+ ```bash
726
+ curl -X POST http://localhost:6969/api/restart
727
+
728
+ # With authentication
729
+ curl -X POST http://localhost:6969/api/restart \
730
+ -H "Authorization: Bearer your-token"
731
+ ```
732
+
733
+ **Restart specific Arr manager:**
734
+ ```bash
735
+ curl -X POST http://localhost:6969/api/arr/radarr-movies/restart
736
+ ```
737
+
738
+ ---
739
+
740
+ #### ⚠️ Troubleshooting Updates
741
+
742
+ **Update not triggering:**
743
+ - ✅ Check `AutoUpdateEnabled = true` in config
744
+ - ✅ Verify cron expression is valid (use [crontab.guru](https://crontab.guru))
745
+ - ✅ Check `Main.log` for GitHub API errors
746
+ - ✅ Ensure internet connectivity to api.github.com
747
+ - ✅ Check if already on latest version
748
+
749
+ **Version mismatch after update:**
750
+ - ✅ Review logs for pip/git errors
751
+ - ✅ Manually verify installation: `pip show qBitrr2` or `git describe`
752
+ - ✅ Check if PyPI is behind GitHub releases (can take hours)
753
+ - ✅ Try manual update to force correct version
754
+
755
+ **Binary updates not working:**
756
+ - ℹ️ **Expected behavior** – binaries cannot auto-update
757
+ - ✅ Check logs for download URL
758
+ - ✅ Download matching binary for your platform
759
+ - ✅ Extract and replace current executable
760
+ - ✅ Ensure new binary has execute permissions (Unix)
761
+
762
+ **Restart fails:**
763
+ - ✅ Check file permissions on qBitrr installation
764
+ - ✅ Review systemd journal if using systemd
765
+ - ✅ Verify no file locks preventing restart
766
+ - ✅ Check disk space for logs and databases
767
+ - ✅ Manual restart: Stop service, start again
768
+
769
+ **For systemd users:** See [SYSTEMD_SERVICE.md](SYSTEMD_SERVICE.md) for automatic restart configuration with `Restart=always`.
770
+
771
+ ---
772
+
773
+ curl -X POST http://localhost:6969/api/arr/radarr-movies/restart
774
+ ```
775
+
776
+ **For systemd users:** See [SYSTEMD_SERVICE.md](SYSTEMD_SERVICE.md) for automatic restart configuration.
777
+
778
+ ---
779
+
780
+ ## 🖥️ Built-in Web UI
781
+ The React + Vite dashboard provides complete visibility and control over your qBitrr instance.
782
+
783
+ ### 🌐 Access & Authentication
784
+ - **Default URL:** `http://<host>:6969/ui`
785
+ - **Custom host/port:** Configure in `config.toml`:
786
+ ```toml
787
+ [WebUI]
788
+ Host = "0.0.0.0" # Bind address (0.0.0.0 for all interfaces)
789
+ Port = 6969 # Web server port
790
+ ```
791
+ - **Authentication:** Protect API endpoints with bearer token:
792
+ ```toml
793
+ [WebUI]
794
+ Token = "your-secret-token"
795
+ ```
796
+ When set, all `/api/*` endpoints require `Authorization: Bearer <token>` header.
797
+ The UI itself uses unauthenticated `/web/*` endpoints.
798
+
799
+ ### 🗂️ Dashboard Tabs
800
+
801
+ **📊 Processes Tab:**
802
+ - View all running Arr manager processes
803
+ - See current activity and search status
804
+ - Monitor queue counts and metrics
805
+ - Restart individual processes or all at once
806
+
807
+ **📝 Logs Tab:**
808
+ - Real-time log viewer with filtering
809
+ - View `Main.log`, `WebUI.log`, and per-Arr logs
810
+ - Search and navigate large log files
811
+ - Download logs for troubleshooting
812
+
813
+ **🎬 Radarr/Sonarr/Lidarr Tabs:**
814
+ - Browse your media library with advanced filtering
815
+ - Filter by year range, quality status, monitored state
816
+ - See custom format scores and upgrade availability
817
+ - Identify missing media and quality issues
818
+ - View request status for Overseerr/Ombi items
819
+
820
+ **⚙️ Config Tab:**
821
+ - Edit configuration directly in the UI
822
+ - Trigger manual updates
823
+ - View version and changelog
824
+ - Rebuild Arr metadata
825
+ - Restart application
826
+
827
+ ### 🎨 Customization
828
+ ```toml
829
+ [WebUI]
830
+ Theme = "dark" # or "light"
831
+ LiveArr = true # Enable live updates for Arr views
832
+ GroupSonarr = true # Group episodes by series
833
+ GroupLidarr = true # Group albums by artist
834
+ ```
835
+
836
+ ### 🧪 Development
837
+ The WebUI source lives in `webui/`:
838
+ ```bash
839
+ cd webui
840
+ npm ci # Install dependencies
841
+ npm run dev # Dev server with HMR at localhost:5173
842
+ npm run lint # ESLint check
843
+ npm run build # Build for production
844
+ ```
845
+ Build outputs to `webui/dist/`, which gets bundled into `qBitrr/static/`.
846
+
847
+ **API Documentation:** See [API_DOCUMENTATION.md](API_DOCUMENTATION.md) for complete API reference.
848
+
849
+ ---
850
+
851
+ ## 🔁 Day-to-day Operations
852
+
853
+ ### 🔄 Restart & Rebuild
854
+ - **Restart application:** WebUI → Config tab → "Restart All" button
855
+ - **Restart individual Arr manager:** WebUI → Processes tab → Click restart icon
856
+ - **Rebuild Arr metadata:** WebUI → Config tab → "Rebuild Arrs" button
857
+ - **API endpoints:**
858
+ ```bash
859
+ POST /api/restart # Restart qBitrr
860
+ POST /api/arr/<category>/restart # Restart specific manager
861
+ POST /api/arr/rebuild # Rebuild all Arr caches
862
+ ```
863
+
864
+ ### 📋 Monitoring
865
+ - **Logs location:** `~/logs/` (native) or `/config/logs` (Docker)
866
+ - **Log files:**
867
+ - `Main.log` – Main application logs
868
+ - `WebUI.log` – Web interface logs
869
+ - `<CategoryName>.log` – Per-Arr instance logs
870
+ - **View in UI:** WebUI → Logs tab → Select log file
871
+ - **View in terminal:**
872
+ ```bash
873
+ # Native
874
+ tail -f ~/logs/Main.log
875
+
876
+ # Docker
877
+ docker logs -f qbitrr
878
+ docker exec qbitrr tail -f /config/logs/Main.log
879
+
880
+ # Systemd
881
+ sudo journalctl -u qbitrr -f
882
+ ```
883
+
884
+ ### 🔍 Request Integration
885
+ Once configured, qBitrr automatically:
886
+ 1. 📥 Polls Overseerr/Ombi for new requests
887
+ 2. 🔍 Searches requested items in Arr instances
888
+ 3. ⭐ Prioritizes requests over general missing media searches
889
+ 4. 📊 Identifies requests in WebUI Arr tabs with `isRequest` flag
890
+
891
+ ### 🛠️ Special Categories
892
+ qBitrr monitors special qBittorrent categories for manual intervention:
893
+
894
+ **Failed Category:**
895
+ ```toml
896
+ [Settings]
897
+ FailedCategory = "failed"
898
+ ```
899
+ Manually move torrents here to mark them as failed and trigger blacklisting + re-search.
900
+
901
+ **Recheck Category:**
902
+ ```toml
903
+ [Settings]
904
+ RecheckCategory = "recheck"
905
+ ```
906
+ Manually move torrents here to trigger a proper recheck operation.
907
+
908
+ ### 🏷️ Tagless Operation
909
+ ```toml
910
+ [Settings]
911
+ Tagless = true
912
+ ```
913
+ Run qBitrr without requiring Arr instances to tag their torrents. Less precise but works without Arr configuration changes.
914
+
915
+ ---
916
+
917
+ ## 🆘 Troubleshooting
918
+
919
+ ### 🐛 Common Issues
920
+
921
+ **Torrents not being processed:**
922
+ 1. ✅ Verify Arr instance is using the correct **category** in download client settings
923
+ 2. ✅ Ensure Arr instance **tags** match qBitrr's category configuration
924
+ 3. ✅ Check `IgnoreTorrentsYoungerThan` – new torrents have a grace period
925
+ 4. ✅ Enable debug logging: `ConsoleLevel = "DEBUG"`
926
+ 5. ✅ Check category-specific log file in `~/logs/` or `/config/logs/`
927
+
928
+ **Imports not triggering:**
929
+ 1. ✅ Verify `CompletedDownloadFolder` path is correct and accessible
930
+ 2. ✅ Check file extensions against `FileExtensionAllowlist`
931
+ 3. ✅ Review `FolderExclusionRegex` and `FileNameExclusionRegex` for over-matching
932
+ 4. ✅ Enable FFprobe logging to see media validation results
933
+ 5. ✅ Check Arr instance has proper path mappings (especially in Docker)
934
+
935
+ **Search not finding releases:**
936
+ 1. ✅ Verify `SearchMissing = true` in the EntrySearch section
937
+ 2. ✅ Check `SearchLimit` isn't too low for your queue
938
+ 3. ✅ Review `SearchByYear` and `SearchInReverse` settings
939
+ 4. ✅ Ensure Arr instance has indexers configured and working
940
+ 5. ✅ Check for rate limiting in Arr instance logs
941
+
942
+ **High CPU/memory usage:**
943
+ 1. ✅ Reduce `SearchLimit` to lower concurrent searches
944
+ 2. ✅ Increase `LoopSleepTimer` to slow down processing
945
+ 3. ✅ Disable `DoUpgradeSearch` if not needed
946
+ 4. ✅ Set `LiveArr = false` in WebUI config to reduce refresh overhead
947
+
948
+ **Docker path issues:**
949
+ 1. ✅ Ensure volume mounts match between qBittorrent, Arr, and qBitrr
950
+ 2. ✅ Use consistent paths across all containers
951
+ 3. ✅ Example: All containers should see `/downloads` as the same physical path
952
+
953
+ **Updates failing:**
954
+ 1. ✅ Check internet connectivity
955
+ 2. ✅ Verify pip/Python installation is writable
956
+ 3. ✅ Review update logs in `Main.log` or `WebUI.log`
957
+ 4. ✅ Manual update: `pip install --upgrade qBitrr2` (native) or pull new Docker image
958
+
959
+ ### 📊 Enable Debug Logging
960
+ ```toml
961
+ [Settings]
962
+ Logging = true
963
+ ConsoleLevel = "DEBUG" # TRACE for even more detail
964
+ ```
965
+ Logs output to:
966
+ - **Native:** `~/logs/`
967
+ - **Docker:** `/config/logs/`
968
+ - **Systemd:** `sudo journalctl -u qbitrr -n 100`
969
+
970
+ ### 🐞 Reporting Issues
971
+ When reporting bugs:
972
+
973
+ 1. **Enable file logging** and reproduce the issue
974
+ 2. **Collect information:**
975
+ - qBitrr version: `qBitrr2 --version` or Docker tag
976
+ - OS and deployment method (Docker/native/systemd)
977
+ - qBittorrent version and API version (4.x vs 5.x)
978
+ - Arr instance versions (Radarr/Sonarr/Lidarr)
979
+ - Request tool versions (Overseerr/Ombi) if applicable
980
+ 3. **Grab relevant log snippets** (scrub API keys and tokens!)
981
+ 4. **Open an issue** using the [bug report template](.github/ISSUE_TEMPLATE/bug_report.yml)
982
+ 5. **Include:**
983
+ - Clear reproduction steps
984
+ - Expected vs. actual behavior
985
+ - Relevant config sections (with secrets removed)
986
+ - Error messages and stack traces
987
+
988
+ ### 💡 Feature Requests
989
+ Have an idea? Submit it via the [feature request template](.github/ISSUE_TEMPLATE/feature_request.yml)!
990
+
991
+ ### 📚 Additional Resources
992
+ - **API Documentation:** [API_DOCUMENTATION.md](API_DOCUMENTATION.md)
993
+ - **Systemd Setup:** [SYSTEMD_SERVICE.md](SYSTEMD_SERVICE.md)
994
+ - **Example Config:** [config.example.toml](config.example.toml)
995
+ - **GitHub Issues:** [Search existing issues](https://github.com/Feramance/qBitrr/issues)
996
+
997
+ ---
998
+
999
+ ## 🤝 Contributing
1000
+
1001
+ We welcome contributions from the community! Whether it's code, documentation, bug reports, or feature ideas, your help makes qBitrr better.
1002
+
1003
+ ### 🔧 Development Setup
1004
+
1005
+ **Python Backend:**
1006
+ ```bash
1007
+ # Clone the repo
1008
+ git clone https://github.com/Feramance/qBitrr.git
1009
+ cd qBitrr
1010
+
1011
+ # Create virtual environment
1012
+ make newenv
1013
+ # or: python -m venv .venv && source .venv/bin/activate
1014
+
1015
+ # Install dependencies
1016
+ make syncenv
1017
+ # or: pip install -e .[all]
1018
+
1019
+ # Run linting and formatting
1020
+ make reformat
1021
+ # or: pre-commit run --all-files
1022
+ ```
1023
+
1024
+ **TypeScript/React WebUI:**
1025
+ ```bash
1026
+ cd webui
1027
+ npm ci # Install exact versions from package-lock.json
1028
+ npm run dev # Dev server at localhost:5173
1029
+ npm run lint # ESLint check
1030
+ npm run build # Build for production
1031
+ ```
1032
+
1033
+ ### 📝 Before Submitting a PR
1034
+
1035
+ 1. ✅ Read the [pull request template](.github/pull_request_template.md)
1036
+ 2. ✅ **Format code:**
1037
+ - Python: `make reformat` or `pre-commit run --all-files`
1038
+ - TypeScript: `npm run lint` in `webui/`
1039
+ 3. ✅ **Test your changes:**
1040
+ - Run against live qBittorrent + Arr instances
1041
+ - Test in both Docker and native environments if possible
1042
+ 4. ✅ **Update documentation:**
1043
+ - Add/update relevant sections in README.md
1044
+ - Update `config.example.toml` if adding config options
1045
+ - Document API changes in `API_DOCUMENTATION.md`
1046
+ 5. ✅ **Clean commit history:**
1047
+ - Use descriptive commit messages
1048
+ - Follow [conventional commits](https://www.conventionalcommits.org/) format
1049
+ - Squash WIP commits before submitting
1050
+
1051
+ ### 💡 Contribution Ideas
1052
+
1053
+ - 🐛 **Bug fixes** – check [open issues](https://github.com/Feramance/qBitrr/issues)
1054
+ - ✨ **Features** – see [feature requests](https://github.com/Feramance/qBitrr/labels/enhancement)
1055
+ - 📚 **Documentation** – improve guides, add examples, fix typos
1056
+ - 🌍 **Translations** – help internationalize the WebUI
1057
+ - 🧪 **Testing** – add test coverage, validate edge cases
1058
+
1059
+ **Unsure if an idea fits?** Open a [feature request](.github/ISSUE_TEMPLATE/feature_request.yml) first and let's discuss!
1060
+
1061
+ ### 📜 Code Guidelines
1062
+
1063
+ See [CONTRIBUTION.md](CONTRIBUTION.md) for comprehensive coding standards and architecture details.
1064
+
1065
+ **Quick summary:**
1066
+ - **Python:** Black formatting (99 chars), type hints required, PEP 8 naming
1067
+ - **TypeScript:** ESLint strict mode, explicit types, functional components only
1068
+ - **Commits:** LF line endings, no trailing whitespace, EOF newline required
1069
+ - **Errors:** Inherit from `qBitManagerError`, provide actionable messages
1070
+
1071
+ ---
1072
+
1073
+ ## ❤️ Support
1074
+
1075
+ ### 🌟 Show Your Support
1076
+ - ⭐ **Star the repo** – helps others discover qBitrr
1077
+ - 🐛 **Report bugs** – attach logs so we can fix issues faster
1078
+ - 💬 **Share feedback** – tell us what works and what doesn't
1079
+ - 🛠️ **Contribute** – code, docs, translations, or just good vibes
1080
+
1081
+ ### 💰 Sponsor Development
1082
+ If qBitrr saves you time and headaches, consider supporting its development:
1083
+
1084
+ - 🎨 [Patreon](https://patreon.com/qBitrr) – monthly support
1085
+ - 💸 [PayPal](https://www.paypal.me/feramance) – one-time donations
1086
+
1087
+ Your support keeps qBitrr maintained, updated, and improving. Thank you! 🙏
1088
+
1089
+ ---
1090
+
1091
+ ## 📄 License
1092
+
1093
+ qBitrr is released under the [MIT License](LICENSE).
1094
+
1095
+ **TL;DR:** Use it, modify it, share it—commercially or personally. Just keep the copyright notice and don't blame us if things break. 😊
1096
+
1097
+ ---
1098
+
1099
+ ## 🔗 Quick Links
1100
+
1101
+ - 📦 [PyPI Package](https://pypi.org/project/qBitrr2/)
1102
+ - 🐳 [Docker Hub](https://hub.docker.com/r/feramance/qbitrr)
1103
+ - 📚 [API Documentation](API_DOCUMENTATION.md)
1104
+ - ⚙️ [Systemd Setup Guide](SYSTEMD_SERVICE.md)
1105
+ - 📝 [Example Configuration](config.example.toml)
1106
+ - 🐛 [Report a Bug](.github/ISSUE_TEMPLATE/bug_report.yml)
1107
+ - ✨ [Request a Feature](.github/ISSUE_TEMPLATE/feature_request.yml)
1108
+ - 💬 [Discussions](https://github.com/Feramance/qBitrr/discussions)
1109
+
1110
+ ---
1111
+
1112
+ <div align="center">
1113
+
1114
+ **Made with ❤️ by the qBitrr community**
1115
+
1116
+ </div>