quasarr 1.17.2__tar.gz → 1.17.3__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.

Files changed (70) hide show
  1. {quasarr-1.17.2 → quasarr-1.17.3}/PKG-INFO +1 -1
  2. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/api/captcha/__init__.py +137 -6
  3. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/version.py +1 -1
  4. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr.egg-info/PKG-INFO +1 -1
  5. {quasarr-1.17.2 → quasarr-1.17.3}/LICENSE +0 -0
  6. {quasarr-1.17.2 → quasarr-1.17.3}/README.md +0 -0
  7. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/__init__.py +0 -0
  8. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/api/__init__.py +0 -0
  9. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/api/arr/__init__.py +0 -0
  10. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/api/config/__init__.py +0 -0
  11. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/api/sponsors_helper/__init__.py +0 -0
  12. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/api/statistics/__init__.py +0 -0
  13. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/__init__.py +0 -0
  14. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/linkcrypters/__init__.py +0 -0
  15. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/linkcrypters/al.py +0 -0
  16. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/linkcrypters/filecrypt.py +0 -0
  17. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/linkcrypters/hide.py +0 -0
  18. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/packages/__init__.py +0 -0
  19. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/sources/__init__.py +0 -0
  20. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/sources/al.py +0 -0
  21. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/sources/by.py +0 -0
  22. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/sources/dd.py +0 -0
  23. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/sources/dt.py +0 -0
  24. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/sources/dw.py +0 -0
  25. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/sources/mb.py +0 -0
  26. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/sources/nx.py +0 -0
  27. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/sources/sf.py +0 -0
  28. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/sources/sl.py +0 -0
  29. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/sources/wd.py +0 -0
  30. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/__init__.py +0 -0
  31. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/cloudflare.py +0 -0
  32. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/html_images.py +0 -0
  33. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/html_templates.py +0 -0
  34. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/imdb_metadata.py +0 -0
  35. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/log.py +0 -0
  36. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/myjd_api.py +0 -0
  37. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/notifications.py +0 -0
  38. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/obfuscated.py +0 -0
  39. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/sessions/__init__.py +0 -0
  40. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/sessions/al.py +0 -0
  41. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/sessions/dd.py +0 -0
  42. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/sessions/nx.py +0 -0
  43. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/shared_state.py +0 -0
  44. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/statistics.py +0 -0
  45. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/web_server.py +0 -0
  46. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/__init__.py +0 -0
  47. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/sources/__init__.py +0 -0
  48. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/sources/al.py +0 -0
  49. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/sources/by.py +0 -0
  50. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/sources/dd.py +0 -0
  51. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/sources/dt.py +0 -0
  52. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/sources/dw.py +0 -0
  53. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/sources/fx.py +0 -0
  54. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/sources/mb.py +0 -0
  55. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/sources/nx.py +0 -0
  56. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/sources/sf.py +0 -0
  57. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/sources/sl.py +0 -0
  58. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/sources/wd.py +0 -0
  59. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/storage/__init__.py +0 -0
  60. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/storage/config.py +0 -0
  61. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/storage/setup.py +0 -0
  62. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/storage/sqlite_database.py +0 -0
  63. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr.egg-info/SOURCES.txt +0 -0
  64. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr.egg-info/dependency_links.txt +0 -0
  65. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr.egg-info/entry_points.txt +0 -0
  66. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr.egg-info/not-zip-safe +0 -0
  67. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr.egg-info/requires.txt +0 -0
  68. {quasarr-1.17.2 → quasarr-1.17.3}/quasarr.egg-info/top_level.txt +0 -0
  69. {quasarr-1.17.2 → quasarr-1.17.3}/setup.cfg +0 -0
  70. {quasarr-1.17.2 → quasarr-1.17.3}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quasarr
3
- Version: 1.17.2
3
+ Version: 1.17.3
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
@@ -103,26 +103,40 @@ def setup_captcha_routes(app):
103
103
 
104
104
  def render_bypass_section(url, package_id, title, password):
105
105
  """Render the bypass UI section for both cutcaptcha and circle captcha pages"""
106
+
107
+ # Generate userscript URL with transfer params
108
+ # Get base URL of current request
109
+ base_url = request.urlparts.scheme + '://' + request.urlparts.netloc
110
+ transfer_url = f"{base_url}/captcha/quick-transfer"
111
+
112
+ url_with_quick_transfer_params = (
113
+ f"{url}?"
114
+ f"transfer_url={quote(transfer_url)}&"
115
+ f"pkg_id={quote(package_id)}&"
116
+ f"pkg_title={quote(title)}&"
117
+ f"pkg_pass={quote(password)}"
118
+ )
119
+
106
120
  return f'''
107
121
  <div style="margin-top: 40px; padding-top: 20px; border-top: 2px solid #ccc;">
108
122
  <details id="bypassDetails">
109
123
  <summary id="bypassSummary">Show CAPTCHA Bypass</summary><br>
110
- <strong><a href="{url}" target="_blank">Obtain download links here!</a></strong><br><br>
124
+ <strong><a href="{url_with_quick_transfer_params}" target="_blank">🔗 Obtain the download links here!</a></strong><br><br>
111
125
  <form id="bypass-form" action="/captcha/bypass-submit" method="post" enctype="multipart/form-data">
112
126
  <input type="hidden" name="package_id" value="{package_id}" />
113
127
  <input type="hidden" name="title" value="{title}" />
114
128
  <input type="hidden" name="password" value="{password}" />
115
-
129
+
116
130
  <div>
117
131
  <strong>Paste the download links (one per line):</strong>
118
132
  <textarea id="links-input" name="links" rows="5" style="width: 100%; padding: 8px; font-family: monospace; resize: vertical;"></textarea>
119
133
  </div>
120
-
134
+
121
135
  <div>
122
136
  <strong>Or upload DLC file:</strong><br>
123
137
  <input type="file" id="dlc-file" name="dlc_file" accept=".dlc" />
124
138
  </div>
125
-
139
+
126
140
  <div>
127
141
  {render_button("Submit", "primary", {"type": "submit"})}
128
142
  </div>
@@ -130,10 +144,9 @@ def setup_captcha_routes(app):
130
144
  </details>
131
145
  </div>
132
146
  <script>
133
- // Handle bypass toggle
134
147
  const bypassDetails = document.getElementById('bypassDetails');
135
148
  const bypassSummary = document.getElementById('bypassSummary');
136
-
149
+
137
150
  if (bypassDetails && bypassSummary) {{
138
151
  bypassDetails.addEventListener('toggle', () => {{
139
152
  if (bypassDetails.open) {{
@@ -146,6 +159,124 @@ def setup_captcha_routes(app):
146
159
  </script>
147
160
  '''
148
161
 
162
+ @app.get('/captcha/quick-transfer')
163
+ def handle_quick_transfer():
164
+ """Handle quick transfer from userscript"""
165
+ import zlib
166
+
167
+ try:
168
+ package_id = request.query.get('pkg_id')
169
+ compressed_links = request.query.get('links', '')
170
+
171
+ if not package_id or not compressed_links:
172
+ return render_centered_html(f'''<h1><img src="{images.logo}" type="image/png" alt="Quasarr logo" class="logo"/>Quasarr</h1>
173
+ <p><b>Error:</b> Missing parameters</p>
174
+ <p>
175
+ {render_button("Back", "secondary", {"onclick": "location.href='/captcha'"})}
176
+ </p>''')
177
+
178
+ # Decode the compressed links using urlsafe_b64decode
179
+ # Add padding if needed
180
+ padding = 4 - (len(compressed_links) % 4)
181
+ if padding != 4:
182
+ compressed_links += '=' * padding
183
+
184
+ try:
185
+ decoded = urlsafe_b64decode(compressed_links)
186
+ except Exception as e:
187
+ info(f"Base64 decode error: {e}")
188
+ return render_centered_html(f'''<h1><img src="{images.logo}" type="image/png" alt="Quasarr logo" class="logo"/>Quasarr</h1>
189
+ <p><b>Error:</b> Failed to decode data: {str(e)}</p>
190
+ <p>
191
+ {render_button("Back", "secondary", {"onclick": "location.href='/captcha'"})}
192
+ </p>''')
193
+
194
+ # Decompress using zlib - use raw deflate format (no header)
195
+ try:
196
+ decompressed = zlib.decompress(decoded, -15) # -15 = raw deflate, no zlib header
197
+ except Exception as e:
198
+ info(f"Decompression error: {e}, trying with header...")
199
+ try:
200
+ # Fallback: try with zlib header
201
+ decompressed = zlib.decompress(decoded)
202
+ except Exception as e2:
203
+ info(f"Decompression also failed with header: {e2}")
204
+ return render_centered_html(f'''<h1><img src="{images.logo}" type="image/png" alt="Quasarr logo" class="logo"/>Quasarr</h1>
205
+ <p><b>Error:</b> Failed to decompress data: {str(e)}</p>
206
+ <p>
207
+ {render_button("Back", "secondary", {"onclick": "location.href='/captcha'"})}
208
+ </p>''')
209
+
210
+ links_text = decompressed.decode('utf-8')
211
+
212
+ # Parse links and restore protocols
213
+ raw_links = [link.strip() for link in links_text.split('\n') if link.strip()]
214
+ links = []
215
+ for link in raw_links:
216
+ if not link.startswith(('http://', 'https://')):
217
+ link = 'https://' + link
218
+ links.append(link)
219
+
220
+ info(f"Quick transfer received {len(links)} links for package {package_id}")
221
+
222
+ # Get package info
223
+ raw_data = shared_state.get_db("protected").retrieve(package_id)
224
+ if not raw_data:
225
+ return render_centered_html(f'''<h1><img src="{images.logo}" type="image/png" alt="Quasarr logo" class="logo"/>Quasarr</h1>
226
+ <p><b>Error:</b> Package not found</p>
227
+ <p>
228
+ {render_button("Back", "secondary", {"onclick": "location.href='/captcha'"})}
229
+ </p>''')
230
+
231
+ data = json.loads(raw_data)
232
+ title = data.get("title", "Unknown")
233
+ password = data.get("password", "")
234
+
235
+ # Download the package
236
+ downloaded = shared_state.download_package(links, title, password, package_id)
237
+
238
+ if downloaded:
239
+ StatsHelper(shared_state).increment_package_with_links(links)
240
+ StatsHelper(shared_state).increment_captcha_decryptions_manual()
241
+ shared_state.get_db("protected").delete(package_id)
242
+
243
+ info(f"Quick transfer successful: {len(links)} links processed")
244
+
245
+ # Check if more CAPTCHAs remain
246
+ remaining_protected = shared_state.get_db("protected").retrieve_all_titles()
247
+ has_more_captchas = bool(remaining_protected)
248
+
249
+ if has_more_captchas:
250
+ solve_button = render_button("Solve another CAPTCHA", "primary",
251
+ {"onclick": "location.href='/captcha'"})
252
+ else:
253
+ solve_button = "<b>No more CAPTCHAs</b>"
254
+
255
+ return render_centered_html(f'''<h1><img src="{images.logo}" type="image/png" alt="Quasarr logo" class="logo"/>Quasarr</h1>
256
+ <p><b>✅ Quick Transfer Successful!</b></p>
257
+ <p>Package "{title}" with {len(links)} link(s) submitted to JDownloader.</p>
258
+ <p>
259
+ {solve_button}
260
+ </p>
261
+ <p>
262
+ {render_button("Back", "secondary", {"onclick": "location.href='/'"})}
263
+ </p>''')
264
+ else:
265
+ StatsHelper(shared_state).increment_failed_decryptions_manual()
266
+ return render_centered_html(f'''<h1><img src="{images.logo}" type="image/png" alt="Quasarr logo" class="logo"/>Quasarr</h1>
267
+ <p><b>Error:</b> Failed to submit package to JDownloader</p>
268
+ <p>
269
+ {render_button("Try Again", "secondary", {"onclick": "location.href='/captcha'"})}
270
+ </p>''')
271
+
272
+ except Exception as e:
273
+ info(f"Quick transfer error: {e}")
274
+ return render_centered_html(f'''<h1><img src="{images.logo}" type="image/png" alt="Quasarr logo" class="logo"/>Quasarr</h1>
275
+ <p><b>Error:</b> {str(e)}</p>
276
+ <p>
277
+ {render_button("Back", "secondary", {"onclick": "location.href='/captcha'"})}
278
+ </p>''')
279
+
149
280
  @app.get('/captcha/delete/<package_id>')
150
281
  def delete_captcha_package(package_id):
151
282
  success = delete_package(shared_state, package_id)
@@ -8,7 +8,7 @@ import requests
8
8
 
9
9
 
10
10
  def get_version():
11
- return "1.17.2"
11
+ return "1.17.3"
12
12
 
13
13
 
14
14
  def get_latest_version():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quasarr
3
- Version: 1.17.2
3
+ Version: 1.17.3
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
File without changes
File without changes
File without changes
File without changes
File without changes