quasarr 2.0.0__tar.gz → 2.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.
Potentially problematic release.
This version of quasarr might be problematic. Click here for more details.
- {quasarr-2.0.0 → quasarr-2.1.0}/PKG-INFO +36 -23
- {quasarr-2.0.0 → quasarr-2.1.0}/README.md +35 -22
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/api/__init__.py +3 -3
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/api/arr/__init__.py +56 -20
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/api/config/__init__.py +1 -1
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/api/packages/__init__.py +115 -54
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/downloads/__init__.py +96 -8
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/downloads/linkcrypters/filecrypt.py +1 -1
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/providers/html_templates.py +65 -10
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/providers/version.py +1 -1
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/search/sources/al.py +1 -1
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/search/sources/by.py +1 -1
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/search/sources/dd.py +2 -1
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/search/sources/dj.py +2 -2
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/search/sources/dl.py +8 -2
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/search/sources/dt.py +1 -1
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/search/sources/dw.py +6 -7
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/search/sources/fx.py +4 -4
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/search/sources/he.py +1 -1
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/search/sources/mb.py +1 -1
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/search/sources/nk.py +1 -1
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/search/sources/nx.py +1 -1
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/search/sources/sf.py +4 -2
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/search/sources/sj.py +2 -2
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/search/sources/sl.py +3 -3
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/search/sources/wd.py +1 -1
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/search/sources/wx.py +4 -3
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr.egg-info/PKG-INFO +36 -23
- {quasarr-2.0.0 → quasarr-2.1.0}/LICENSE +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/__init__.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/api/captcha/__init__.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/api/sponsors_helper/__init__.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/api/statistics/__init__.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/downloads/linkcrypters/__init__.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/downloads/linkcrypters/al.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/downloads/linkcrypters/hide.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/downloads/packages/__init__.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/downloads/sources/__init__.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/downloads/sources/al.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/downloads/sources/by.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/downloads/sources/dd.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/downloads/sources/dj.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/downloads/sources/dl.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/downloads/sources/dt.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/downloads/sources/dw.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/downloads/sources/he.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/downloads/sources/mb.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/downloads/sources/nk.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/downloads/sources/nx.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/downloads/sources/sf.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/downloads/sources/sj.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/downloads/sources/sl.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/downloads/sources/wd.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/downloads/sources/wx.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/providers/__init__.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/providers/auth.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/providers/cloudflare.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/providers/html_images.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/providers/imdb_metadata.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/providers/jd_cache.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/providers/log.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/providers/myjd_api.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/providers/notifications.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/providers/obfuscated.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/providers/sessions/__init__.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/providers/sessions/al.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/providers/sessions/dd.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/providers/sessions/dl.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/providers/sessions/nx.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/providers/shared_state.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/providers/statistics.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/providers/utils.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/providers/web_server.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/search/__init__.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/search/sources/__init__.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/storage/__init__.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/storage/config.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/storage/setup.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr/storage/sqlite_database.py +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr.egg-info/SOURCES.txt +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr.egg-info/dependency_links.txt +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr.egg-info/entry_points.txt +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr.egg-info/not-zip-safe +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr.egg-info/requires.txt +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/quasarr.egg-info/top_level.txt +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/setup.cfg +0 -0
- {quasarr-2.0.0 → quasarr-2.1.0}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: quasarr
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: Quasarr connects JDownloader with Radarr, Sonarr and LazyLibrarian. It also decrypts links protected by CAPTCHAs.
|
|
5
5
|
Home-page: https://github.com/rix1337/Quasarr
|
|
6
6
|
Author: rix1337
|
|
@@ -25,7 +25,7 @@ Dynamic: license-file
|
|
|
25
25
|
Dynamic: requires-dist
|
|
26
26
|
Dynamic: summary
|
|
27
27
|
|
|
28
|
-
#
|
|
28
|
+
#
|
|
29
29
|
|
|
30
30
|
<img src="https://raw.githubusercontent.com/rix1337/Quasarr/main/Quasarr.png" data-canonical-src="https://raw.githubusercontent.com/rix1337/Quasarr/main/Quasarr.png" width="64" height="64" />
|
|
31
31
|
|
|
@@ -41,7 +41,8 @@ indexers. It simply does not know what NZB files are.
|
|
|
41
41
|
Quasarr includes a solution to quickly and easily decrypt protected links.
|
|
42
42
|
[Active monthly Sponsors get access to SponsorsHelper to do so automatically.](https://github.com/rix1337/Quasarr?tab=readme-ov-file#sponsorshelper)
|
|
43
43
|
Alternatively, follow the link from the console output (or discord notification) to solve CAPTCHAs manually.
|
|
44
|
-
Quasarr will confidently handle the rest. Some CAPTCHA types require [Tampermonkey](https://www.tampermonkey.net/) to be
|
|
44
|
+
Quasarr will confidently handle the rest. Some CAPTCHA types require [Tampermonkey](https://www.tampermonkey.net/) to be
|
|
45
|
+
installed in your browser.
|
|
45
46
|
|
|
46
47
|
# Instructions
|
|
47
48
|
|
|
@@ -56,9 +57,11 @@ Quasarr will confidently handle the rest. Some CAPTCHA types require [Tampermonk
|
|
|
56
57
|
|
|
57
58
|
## FlareSolverr (Optional)
|
|
58
59
|
|
|
59
|
-
FlareSolverr is **optional** but **required for some sites** (e.g., AL) that use Cloudflare protection. You can skip
|
|
60
|
+
FlareSolverr is **optional** but **required for some sites** (e.g., AL) that use Cloudflare protection. You can skip
|
|
61
|
+
FlareSolverr during setup and configure it later via the web UI.
|
|
60
62
|
|
|
61
63
|
If using FlareSolverr, provide your URL including the version path:
|
|
64
|
+
|
|
62
65
|
```
|
|
63
66
|
http://192.168.1.1:8191/v1
|
|
64
67
|
```
|
|
@@ -69,11 +72,13 @@ http://192.168.1.1:8191/v1
|
|
|
69
72
|
|
|
70
73
|
## Quasarr
|
|
71
74
|
|
|
72
|
-
> ⚠️ Quasarr requires at least one valid hostname to start. It does not provide or endorse any specific sources, but
|
|
75
|
+
> ⚠️ Quasarr requires at least one valid hostname to start. It does not provide or endorse any specific sources, but
|
|
76
|
+
> community-maintained lists are available:
|
|
73
77
|
|
|
74
78
|
🔗 **[https://quasarr-host.name](https://quasarr-host.name)** — community guide for finding hostnames
|
|
75
79
|
|
|
76
|
-
📋 Alternatively, browse community suggestions via [pastebin search](https://pastebin.com/search?q=hostnames+quasarr) (
|
|
80
|
+
📋 Alternatively, browse community suggestions via [pastebin search](https://pastebin.com/search?q=hostnames+quasarr) (
|
|
81
|
+
login required).
|
|
77
82
|
|
|
78
83
|
> Authentication is optional but strongly recommended.
|
|
79
84
|
>
|
|
@@ -84,8 +89,9 @@ http://192.168.1.1:8191/v1
|
|
|
84
89
|
|
|
85
90
|
## JDownloader
|
|
86
91
|
|
|
87
|
-
> ⚠️ If using Docker:
|
|
88
|
-
> JDownloader's download path must be available to Radarr/Sonarr/LazyLibrarian with **identical internal and external
|
|
92
|
+
> ⚠️ If using Docker:
|
|
93
|
+
> JDownloader's download path must be available to Radarr/Sonarr/LazyLibrarian with **identical internal and external
|
|
94
|
+
path mappings**!
|
|
89
95
|
> Matching only the external path is not sufficient.
|
|
90
96
|
|
|
91
97
|
1. Start and connect JDownloader to [My JDownloader](https://my.jdownloader.org)
|
|
@@ -94,7 +100,8 @@ http://192.168.1.1:8191/v1
|
|
|
94
100
|
<details>
|
|
95
101
|
<summary>Fresh install recommended</summary>
|
|
96
102
|
|
|
97
|
-
Consider setting up a fresh JDownloader instance. Quasarr will modify JDownloader's settings to enable
|
|
103
|
+
Consider setting up a fresh JDownloader instance. Quasarr will modify JDownloader's settings to enable
|
|
104
|
+
Radarr/Sonarr/LazyLibrarian integration.
|
|
98
105
|
|
|
99
106
|
</details>
|
|
100
107
|
|
|
@@ -102,7 +109,8 @@ Consider setting up a fresh JDownloader instance. Quasarr will modify JDownloade
|
|
|
102
109
|
|
|
103
110
|
## Radarr / Sonarr
|
|
104
111
|
|
|
105
|
-
> ⚠️ **Sonarr users:** Set all shows (including anime) to the **Standard** series type. Quasarr cannot find releases for
|
|
112
|
+
> ⚠️ **Sonarr users:** Set all shows (including anime) to the **Standard** series type. Quasarr cannot find releases for
|
|
113
|
+
> shows set to Anime/Absolute.
|
|
106
114
|
|
|
107
115
|
|
|
108
116
|
Add Quasarr as both a **Newznab Indexer** and **SABnzbd Download Client** using your Quasarr URL and API Key.
|
|
@@ -118,9 +126,11 @@ Add Quasarr as both a **Newznab Indexer** and **SABnzbd Download Client** using
|
|
|
118
126
|
<summary>Restrict results to a specific mirror</summary>
|
|
119
127
|
|
|
120
128
|
Append the mirror name to your Newznab URL:
|
|
129
|
+
|
|
121
130
|
```
|
|
122
131
|
/api/dropbox/
|
|
123
132
|
```
|
|
133
|
+
|
|
124
134
|
Only releases with `dropbox` in a link will be returned. If the mirror isn't available, the release will fail.
|
|
125
135
|
|
|
126
136
|
</details>
|
|
@@ -136,27 +146,29 @@ Only releases with `dropbox` in a link will be returned. If the mirror isn't ava
|
|
|
136
146
|
|
|
137
147
|
### SABnzbd+ Downloader
|
|
138
148
|
|
|
139
|
-
| Setting
|
|
140
|
-
|
|
149
|
+
| Setting | Value |
|
|
150
|
+
|----------|----------------------------|
|
|
141
151
|
| URL/Port | Your Quasarr host and port |
|
|
142
|
-
| API Key
|
|
143
|
-
| Category | `docs`
|
|
152
|
+
| API Key | Your Quasarr API Key |
|
|
153
|
+
| Category | `docs` |
|
|
144
154
|
|
|
145
155
|
### Newznab Provider
|
|
146
156
|
|
|
147
|
-
| Setting | Value
|
|
148
|
-
|
|
149
|
-
| URL
|
|
150
|
-
| API
|
|
157
|
+
| Setting | Value |
|
|
158
|
+
|---------|----------------------|
|
|
159
|
+
| URL | Your Quasarr URL |
|
|
160
|
+
| API | Your Quasarr API Key |
|
|
151
161
|
|
|
152
162
|
### Fix Import & Processing
|
|
153
163
|
|
|
154
164
|
**Importing:**
|
|
165
|
+
|
|
155
166
|
- Enable `OpenLibrary api for book/author information`
|
|
156
167
|
- Set Primary Information Source to `OpenLibrary`
|
|
157
168
|
- Add to Import languages: `, Unknown` (German users: `, de, ger, de-DE`)
|
|
158
169
|
|
|
159
170
|
**Processing → Folders:**
|
|
171
|
+
|
|
160
172
|
- Add your Quasarr download path (typically `/downloads/Quasarr/`)
|
|
161
173
|
|
|
162
174
|
</details>
|
|
@@ -236,7 +248,8 @@ Most feature requests can be satisfied by:
|
|
|
236
248
|
- There are no hostname integrations in active development unless you see an open pull request
|
|
237
249
|
[here](https://github.com/rix1337/Quasarr/pulls).
|
|
238
250
|
- **Pull requests are welcome!** Especially for popular hostnames.
|
|
239
|
-
- A short guide to set up required dev services is found
|
|
251
|
+
- A short guide to set up required dev services is found
|
|
252
|
+
in [/docker/dev-setup.md](https://github.com/rix1337/Quasarr/blob/main/docker/dev-setup.md)
|
|
240
253
|
- Always reach out on Discord before starting work on a new feature to prevent waste of time.
|
|
241
254
|
- Please follow the existing code style and project structure.
|
|
242
255
|
- Anti-bot measures must be circumvented fully by Quasarr. Thus, you will need to provide a working solution for new
|
|
@@ -258,11 +271,11 @@ Image access is limited to [active monthly GitHub sponsors](https://github.com/u
|
|
|
258
271
|
|
|
259
272
|
1. Start your [sponsorship](https://github.com/users/rix1337/sponsorship) first.
|
|
260
273
|
2. Open [GitHub Classic Token Settings](https://github.com/settings/tokens/new?type=classic)
|
|
261
|
-
3. Name it (e.g., `SponsorsHelper`) and choose unlimited expiration
|
|
274
|
+
3. Name it (e.g., `SponsorsHelper`) and choose unlimited expiration
|
|
262
275
|
4. Enable these scopes:
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
276
|
+
- `read:packages`
|
|
277
|
+
- `read:user`
|
|
278
|
+
- `read:org`
|
|
266
279
|
5. Click **Generate token** and copy it for the next steps
|
|
267
280
|
|
|
268
281
|
---
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
#
|
|
2
2
|
|
|
3
3
|
<img src="https://raw.githubusercontent.com/rix1337/Quasarr/main/Quasarr.png" data-canonical-src="https://raw.githubusercontent.com/rix1337/Quasarr/main/Quasarr.png" width="64" height="64" />
|
|
4
4
|
|
|
@@ -14,7 +14,8 @@ indexers. It simply does not know what NZB files are.
|
|
|
14
14
|
Quasarr includes a solution to quickly and easily decrypt protected links.
|
|
15
15
|
[Active monthly Sponsors get access to SponsorsHelper to do so automatically.](https://github.com/rix1337/Quasarr?tab=readme-ov-file#sponsorshelper)
|
|
16
16
|
Alternatively, follow the link from the console output (or discord notification) to solve CAPTCHAs manually.
|
|
17
|
-
Quasarr will confidently handle the rest. Some CAPTCHA types require [Tampermonkey](https://www.tampermonkey.net/) to be
|
|
17
|
+
Quasarr will confidently handle the rest. Some CAPTCHA types require [Tampermonkey](https://www.tampermonkey.net/) to be
|
|
18
|
+
installed in your browser.
|
|
18
19
|
|
|
19
20
|
# Instructions
|
|
20
21
|
|
|
@@ -29,9 +30,11 @@ Quasarr will confidently handle the rest. Some CAPTCHA types require [Tampermonk
|
|
|
29
30
|
|
|
30
31
|
## FlareSolverr (Optional)
|
|
31
32
|
|
|
32
|
-
FlareSolverr is **optional** but **required for some sites** (e.g., AL) that use Cloudflare protection. You can skip
|
|
33
|
+
FlareSolverr is **optional** but **required for some sites** (e.g., AL) that use Cloudflare protection. You can skip
|
|
34
|
+
FlareSolverr during setup and configure it later via the web UI.
|
|
33
35
|
|
|
34
36
|
If using FlareSolverr, provide your URL including the version path:
|
|
37
|
+
|
|
35
38
|
```
|
|
36
39
|
http://192.168.1.1:8191/v1
|
|
37
40
|
```
|
|
@@ -42,11 +45,13 @@ http://192.168.1.1:8191/v1
|
|
|
42
45
|
|
|
43
46
|
## Quasarr
|
|
44
47
|
|
|
45
|
-
> ⚠️ Quasarr requires at least one valid hostname to start. It does not provide or endorse any specific sources, but
|
|
48
|
+
> ⚠️ Quasarr requires at least one valid hostname to start. It does not provide or endorse any specific sources, but
|
|
49
|
+
> community-maintained lists are available:
|
|
46
50
|
|
|
47
51
|
🔗 **[https://quasarr-host.name](https://quasarr-host.name)** — community guide for finding hostnames
|
|
48
52
|
|
|
49
|
-
📋 Alternatively, browse community suggestions via [pastebin search](https://pastebin.com/search?q=hostnames+quasarr) (
|
|
53
|
+
📋 Alternatively, browse community suggestions via [pastebin search](https://pastebin.com/search?q=hostnames+quasarr) (
|
|
54
|
+
login required).
|
|
50
55
|
|
|
51
56
|
> Authentication is optional but strongly recommended.
|
|
52
57
|
>
|
|
@@ -57,8 +62,9 @@ http://192.168.1.1:8191/v1
|
|
|
57
62
|
|
|
58
63
|
## JDownloader
|
|
59
64
|
|
|
60
|
-
> ⚠️ If using Docker:
|
|
61
|
-
> JDownloader's download path must be available to Radarr/Sonarr/LazyLibrarian with **identical internal and external
|
|
65
|
+
> ⚠️ If using Docker:
|
|
66
|
+
> JDownloader's download path must be available to Radarr/Sonarr/LazyLibrarian with **identical internal and external
|
|
67
|
+
path mappings**!
|
|
62
68
|
> Matching only the external path is not sufficient.
|
|
63
69
|
|
|
64
70
|
1. Start and connect JDownloader to [My JDownloader](https://my.jdownloader.org)
|
|
@@ -67,7 +73,8 @@ http://192.168.1.1:8191/v1
|
|
|
67
73
|
<details>
|
|
68
74
|
<summary>Fresh install recommended</summary>
|
|
69
75
|
|
|
70
|
-
Consider setting up a fresh JDownloader instance. Quasarr will modify JDownloader's settings to enable
|
|
76
|
+
Consider setting up a fresh JDownloader instance. Quasarr will modify JDownloader's settings to enable
|
|
77
|
+
Radarr/Sonarr/LazyLibrarian integration.
|
|
71
78
|
|
|
72
79
|
</details>
|
|
73
80
|
|
|
@@ -75,7 +82,8 @@ Consider setting up a fresh JDownloader instance. Quasarr will modify JDownloade
|
|
|
75
82
|
|
|
76
83
|
## Radarr / Sonarr
|
|
77
84
|
|
|
78
|
-
> ⚠️ **Sonarr users:** Set all shows (including anime) to the **Standard** series type. Quasarr cannot find releases for
|
|
85
|
+
> ⚠️ **Sonarr users:** Set all shows (including anime) to the **Standard** series type. Quasarr cannot find releases for
|
|
86
|
+
> shows set to Anime/Absolute.
|
|
79
87
|
|
|
80
88
|
|
|
81
89
|
Add Quasarr as both a **Newznab Indexer** and **SABnzbd Download Client** using your Quasarr URL and API Key.
|
|
@@ -91,9 +99,11 @@ Add Quasarr as both a **Newznab Indexer** and **SABnzbd Download Client** using
|
|
|
91
99
|
<summary>Restrict results to a specific mirror</summary>
|
|
92
100
|
|
|
93
101
|
Append the mirror name to your Newznab URL:
|
|
102
|
+
|
|
94
103
|
```
|
|
95
104
|
/api/dropbox/
|
|
96
105
|
```
|
|
106
|
+
|
|
97
107
|
Only releases with `dropbox` in a link will be returned. If the mirror isn't available, the release will fail.
|
|
98
108
|
|
|
99
109
|
</details>
|
|
@@ -109,27 +119,29 @@ Only releases with `dropbox` in a link will be returned. If the mirror isn't ava
|
|
|
109
119
|
|
|
110
120
|
### SABnzbd+ Downloader
|
|
111
121
|
|
|
112
|
-
| Setting
|
|
113
|
-
|
|
122
|
+
| Setting | Value |
|
|
123
|
+
|----------|----------------------------|
|
|
114
124
|
| URL/Port | Your Quasarr host and port |
|
|
115
|
-
| API Key
|
|
116
|
-
| Category | `docs`
|
|
125
|
+
| API Key | Your Quasarr API Key |
|
|
126
|
+
| Category | `docs` |
|
|
117
127
|
|
|
118
128
|
### Newznab Provider
|
|
119
129
|
|
|
120
|
-
| Setting | Value
|
|
121
|
-
|
|
122
|
-
| URL
|
|
123
|
-
| API
|
|
130
|
+
| Setting | Value |
|
|
131
|
+
|---------|----------------------|
|
|
132
|
+
| URL | Your Quasarr URL |
|
|
133
|
+
| API | Your Quasarr API Key |
|
|
124
134
|
|
|
125
135
|
### Fix Import & Processing
|
|
126
136
|
|
|
127
137
|
**Importing:**
|
|
138
|
+
|
|
128
139
|
- Enable `OpenLibrary api for book/author information`
|
|
129
140
|
- Set Primary Information Source to `OpenLibrary`
|
|
130
141
|
- Add to Import languages: `, Unknown` (German users: `, de, ger, de-DE`)
|
|
131
142
|
|
|
132
143
|
**Processing → Folders:**
|
|
144
|
+
|
|
133
145
|
- Add your Quasarr download path (typically `/downloads/Quasarr/`)
|
|
134
146
|
|
|
135
147
|
</details>
|
|
@@ -209,7 +221,8 @@ Most feature requests can be satisfied by:
|
|
|
209
221
|
- There are no hostname integrations in active development unless you see an open pull request
|
|
210
222
|
[here](https://github.com/rix1337/Quasarr/pulls).
|
|
211
223
|
- **Pull requests are welcome!** Especially for popular hostnames.
|
|
212
|
-
- A short guide to set up required dev services is found
|
|
224
|
+
- A short guide to set up required dev services is found
|
|
225
|
+
in [/docker/dev-setup.md](https://github.com/rix1337/Quasarr/blob/main/docker/dev-setup.md)
|
|
213
226
|
- Always reach out on Discord before starting work on a new feature to prevent waste of time.
|
|
214
227
|
- Please follow the existing code style and project structure.
|
|
215
228
|
- Anti-bot measures must be circumvented fully by Quasarr. Thus, you will need to provide a working solution for new
|
|
@@ -231,11 +244,11 @@ Image access is limited to [active monthly GitHub sponsors](https://github.com/u
|
|
|
231
244
|
|
|
232
245
|
1. Start your [sponsorship](https://github.com/users/rix1337/sponsorship) first.
|
|
233
246
|
2. Open [GitHub Classic Token Settings](https://github.com/settings/tokens/new?type=classic)
|
|
234
|
-
3. Name it (e.g., `SponsorsHelper`) and choose unlimited expiration
|
|
247
|
+
3. Name it (e.g., `SponsorsHelper`) and choose unlimited expiration
|
|
235
248
|
4. Enable these scopes:
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
249
|
+
- `read:packages`
|
|
250
|
+
- `read:user`
|
|
251
|
+
- `read:org`
|
|
239
252
|
5. Click **Generate token** and copy it for the next steps
|
|
240
253
|
|
|
241
254
|
---
|
|
@@ -66,7 +66,7 @@ def get_api(shared_state_dict, shared_state_lock):
|
|
|
66
66
|
# JDownloader status
|
|
67
67
|
jd_status = f"""
|
|
68
68
|
<div class="status-bar">
|
|
69
|
-
<span class="status-
|
|
69
|
+
<span class="status-pill {'success' if jd_connected else 'error'}">
|
|
70
70
|
{'✅' if jd_connected else '❌'} JDownloader {'Connected' if jd_connected else 'Disconnected'}
|
|
71
71
|
</span>
|
|
72
72
|
</div>
|
|
@@ -389,8 +389,8 @@ def get_api(shared_state_dict, shared_state_lock):
|
|
|
389
389
|
</script>
|
|
390
390
|
"""
|
|
391
391
|
# Add logout link for form auth
|
|
392
|
-
logout_html = '<
|
|
393
|
-
return render_centered_html(info
|
|
392
|
+
logout_html = '<a href="/logout">Logout</a>' if show_logout_link() else ''
|
|
393
|
+
return render_centered_html(info, footer_content=logout_html)
|
|
394
394
|
|
|
395
395
|
@app.get('/regenerate-api-key')
|
|
396
396
|
def regenerate_api_key():
|
|
@@ -34,18 +34,57 @@ def require_api_key(func):
|
|
|
34
34
|
return decorated
|
|
35
35
|
|
|
36
36
|
|
|
37
|
+
def parse_payload(payload_str):
|
|
38
|
+
"""
|
|
39
|
+
Parse the base64-encoded payload string into its components.
|
|
40
|
+
|
|
41
|
+
Supports both legacy 6-field format and new 7-field format:
|
|
42
|
+
- Legacy (6 fields): title|url|mirror|size_mb|password|imdb_id
|
|
43
|
+
- New (7 fields): title|url|mirror|size_mb|password|imdb_id|source_key
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
dict with keys: title, url, mirror, size_mb, password, imdb_id, source_key
|
|
47
|
+
"""
|
|
48
|
+
decoded = urlsafe_b64decode(payload_str.encode()).decode()
|
|
49
|
+
parts = decoded.split("|")
|
|
50
|
+
|
|
51
|
+
if len(parts) == 6:
|
|
52
|
+
# Legacy format - no source_key provided
|
|
53
|
+
title, url, mirror, size_mb, password, imdb_id = parts
|
|
54
|
+
source_key = None
|
|
55
|
+
elif len(parts) == 7:
|
|
56
|
+
# New format with source_key
|
|
57
|
+
title, url, mirror, size_mb, password, imdb_id, source_key = parts
|
|
58
|
+
else:
|
|
59
|
+
raise ValueError(f"expected 6 or 7 fields, got {len(parts)}")
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
"title": title,
|
|
63
|
+
"url": url,
|
|
64
|
+
"mirror": None if mirror == "None" else mirror,
|
|
65
|
+
"size_mb": size_mb,
|
|
66
|
+
"password": password if password else None,
|
|
67
|
+
"imdb_id": imdb_id if imdb_id else None,
|
|
68
|
+
"source_key": source_key if source_key else None
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
37
72
|
def setup_arr_routes(app):
|
|
38
73
|
@app.get('/download/')
|
|
39
74
|
def fake_nzb_file():
|
|
40
75
|
payload = request.query.payload
|
|
41
76
|
decoded_payload = urlsafe_b64decode(payload).decode("utf-8").split("|")
|
|
77
|
+
|
|
78
|
+
# Support both 6 and 7 field formats
|
|
42
79
|
title = decoded_payload[0]
|
|
43
80
|
url = decoded_payload[1]
|
|
44
81
|
mirror = decoded_payload[2]
|
|
45
82
|
size_mb = decoded_payload[3]
|
|
46
83
|
password = decoded_payload[4]
|
|
47
84
|
imdb_id = decoded_payload[5]
|
|
48
|
-
|
|
85
|
+
source_key = decoded_payload[6] if len(decoded_payload) > 6 else ""
|
|
86
|
+
|
|
87
|
+
return f'<nzb><file title="{title}" url="{url}" mirror="{mirror}" size_mb="{size_mb}" password="{password}" imdb_id="{imdb_id}" source_key="{source_key}"/></nzb>'
|
|
49
88
|
|
|
50
89
|
@app.post('/api')
|
|
51
90
|
@require_api_key
|
|
@@ -65,10 +104,12 @@ def setup_arr_routes(app):
|
|
|
65
104
|
size_mb = root.find(".//file").attrib["size_mb"]
|
|
66
105
|
password = root.find(".//file").attrib.get("password")
|
|
67
106
|
imdb_id = root.find(".//file").attrib.get("imdb_id")
|
|
107
|
+
source_key = root.find(".//file").attrib.get("source_key") or None
|
|
68
108
|
|
|
69
109
|
info(f'Attempting download for "{title}"')
|
|
70
110
|
request_from = request.headers.get('User-Agent')
|
|
71
|
-
downloaded = download(shared_state, request_from, title, url, mirror, size_mb, password, imdb_id
|
|
111
|
+
downloaded = download(shared_state, request_from, title, url, mirror, size_mb, password, imdb_id,
|
|
112
|
+
source_key)
|
|
72
113
|
try:
|
|
73
114
|
success = downloaded["success"]
|
|
74
115
|
package_id = downloaded["package_id"]
|
|
@@ -166,37 +207,31 @@ def setup_arr_routes(app):
|
|
|
166
207
|
if not payload:
|
|
167
208
|
abort(400, "missing 'payload' parameter in URL")
|
|
168
209
|
|
|
169
|
-
title = url = mirror = size_mb = password = imdb_id = None
|
|
170
210
|
try:
|
|
171
|
-
|
|
172
|
-
parts = decoded.split("|")
|
|
173
|
-
if len(parts) != 6:
|
|
174
|
-
raise ValueError(f"expected 6 fields, got {len(parts)}")
|
|
175
|
-
title, url, mirror, size_mb, password, imdb_id = parts
|
|
211
|
+
parsed_payload = parse_payload(payload)
|
|
176
212
|
except Exception as e:
|
|
177
213
|
abort(400, f"invalid payload format: {e}")
|
|
178
214
|
|
|
179
|
-
mirror = None if mirror == "None" else mirror
|
|
180
|
-
|
|
181
215
|
nzo_ids = []
|
|
182
|
-
info(f'Attempting download for "{title}"')
|
|
216
|
+
info(f'Attempting download for "{parsed_payload["title"]}"')
|
|
183
217
|
request_from = "lazylibrarian"
|
|
184
218
|
|
|
185
219
|
downloaded = download(
|
|
186
220
|
shared_state,
|
|
187
221
|
request_from,
|
|
188
|
-
title,
|
|
189
|
-
url,
|
|
190
|
-
mirror,
|
|
191
|
-
size_mb,
|
|
192
|
-
password
|
|
193
|
-
imdb_id
|
|
222
|
+
parsed_payload["title"],
|
|
223
|
+
parsed_payload["url"],
|
|
224
|
+
parsed_payload["mirror"],
|
|
225
|
+
parsed_payload["size_mb"],
|
|
226
|
+
parsed_payload["password"],
|
|
227
|
+
parsed_payload["imdb_id"],
|
|
228
|
+
parsed_payload["source_key"],
|
|
194
229
|
)
|
|
195
230
|
|
|
196
231
|
try:
|
|
197
232
|
success = downloaded["success"]
|
|
198
233
|
package_id = downloaded["package_id"]
|
|
199
|
-
title = downloaded.get("title", title)
|
|
234
|
+
title = downloaded.get("title", parsed_payload["title"])
|
|
200
235
|
|
|
201
236
|
if success:
|
|
202
237
|
info(f'"{title}" added successfully!')
|
|
@@ -204,7 +239,7 @@ def setup_arr_routes(app):
|
|
|
204
239
|
info(f'"{title}" added unsuccessfully! See log for details.')
|
|
205
240
|
nzo_ids.append(package_id)
|
|
206
241
|
except KeyError:
|
|
207
|
-
info(f'Failed to download "{title}" - no package_id returned')
|
|
242
|
+
info(f'Failed to download "{parsed_payload["title"]}" - no package_id returned')
|
|
208
243
|
|
|
209
244
|
return {
|
|
210
245
|
"status": True,
|
|
@@ -353,7 +388,8 @@ def setup_arr_routes(app):
|
|
|
353
388
|
<enclosure url="{release.get("link", "")}" length="{release.get("size", 0)}" type="application/x-nzb" />
|
|
354
389
|
</item>'''
|
|
355
390
|
|
|
356
|
-
requires_placeholder_item = not getattr(request.query, 'imdbid', '') and not getattr(request.query,
|
|
391
|
+
requires_placeholder_item = not getattr(request.query, 'imdbid', '') and not getattr(request.query,
|
|
392
|
+
'q', '')
|
|
357
393
|
if requires_placeholder_item and not items:
|
|
358
394
|
items = f'''
|
|
359
395
|
<item>
|