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.
- {quasarr-1.17.2 → quasarr-1.17.3}/PKG-INFO +1 -1
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/api/captcha/__init__.py +137 -6
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/version.py +1 -1
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr.egg-info/PKG-INFO +1 -1
- {quasarr-1.17.2 → quasarr-1.17.3}/LICENSE +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/README.md +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/__init__.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/api/__init__.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/api/arr/__init__.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/api/config/__init__.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/api/sponsors_helper/__init__.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/api/statistics/__init__.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/__init__.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/linkcrypters/__init__.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/linkcrypters/al.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/linkcrypters/filecrypt.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/linkcrypters/hide.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/packages/__init__.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/sources/__init__.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/sources/al.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/sources/by.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/sources/dd.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/sources/dt.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/sources/dw.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/sources/mb.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/sources/nx.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/sources/sf.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/sources/sl.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/downloads/sources/wd.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/__init__.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/cloudflare.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/html_images.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/html_templates.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/imdb_metadata.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/log.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/myjd_api.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/notifications.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/obfuscated.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/sessions/__init__.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/sessions/al.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/sessions/dd.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/sessions/nx.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/shared_state.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/statistics.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/providers/web_server.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/__init__.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/sources/__init__.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/sources/al.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/sources/by.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/sources/dd.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/sources/dt.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/sources/dw.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/sources/fx.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/sources/mb.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/sources/nx.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/sources/sf.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/sources/sl.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/search/sources/wd.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/storage/__init__.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/storage/config.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/storage/setup.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr/storage/sqlite_database.py +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr.egg-info/SOURCES.txt +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr.egg-info/dependency_links.txt +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr.egg-info/entry_points.txt +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr.egg-info/not-zip-safe +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr.egg-info/requires.txt +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/quasarr.egg-info/top_level.txt +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/setup.cfg +0 -0
- {quasarr-1.17.2 → quasarr-1.17.3}/setup.py +0 -0
|
@@ -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="{
|
|
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)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|