quasarr 1.17.1__py3-none-any.whl → 1.17.3__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.
Potentially problematic release.
This version of quasarr might be problematic. Click here for more details.
- quasarr/api/captcha/__init__.py +172 -23
- quasarr/providers/version.py +1 -1
- {quasarr-1.17.1.dist-info → quasarr-1.17.3.dist-info}/METADATA +1 -1
- {quasarr-1.17.1.dist-info → quasarr-1.17.3.dist-info}/RECORD +8 -8
- {quasarr-1.17.1.dist-info → quasarr-1.17.3.dist-info}/WHEEL +0 -0
- {quasarr-1.17.1.dist-info → quasarr-1.17.3.dist-info}/entry_points.txt +0 -0
- {quasarr-1.17.1.dist-info → quasarr-1.17.3.dist-info}/licenses/LICENSE +0 -0
- {quasarr-1.17.1.dist-info → quasarr-1.17.3.dist-info}/top_level.txt +0 -0
quasarr/api/captcha/__init__.py
CHANGED
|
@@ -103,32 +103,180 @@ 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
|
-
<
|
|
109
|
-
<
|
|
110
|
-
|
|
111
|
-
<
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
<
|
|
117
|
-
|
|
118
|
-
|
|
122
|
+
<details id="bypassDetails">
|
|
123
|
+
<summary id="bypassSummary">Show CAPTCHA Bypass</summary><br>
|
|
124
|
+
<strong><a href="{url_with_quick_transfer_params}" target="_blank">🔗 Obtain the download links here!</a></strong><br><br>
|
|
125
|
+
<form id="bypass-form" action="/captcha/bypass-submit" method="post" enctype="multipart/form-data">
|
|
126
|
+
<input type="hidden" name="package_id" value="{package_id}" />
|
|
127
|
+
<input type="hidden" name="title" value="{title}" />
|
|
128
|
+
<input type="hidden" name="password" value="{password}" />
|
|
129
|
+
|
|
130
|
+
<div>
|
|
131
|
+
<strong>Paste the download links (one per line):</strong>
|
|
132
|
+
<textarea id="links-input" name="links" rows="5" style="width: 100%; padding: 8px; font-family: monospace; resize: vertical;"></textarea>
|
|
133
|
+
</div>
|
|
119
134
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
135
|
+
<div>
|
|
136
|
+
<strong>Or upload DLC file:</strong><br>
|
|
137
|
+
<input type="file" id="dlc-file" name="dlc_file" accept=".dlc" />
|
|
138
|
+
</div>
|
|
124
139
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
140
|
+
<div>
|
|
141
|
+
{render_button("Submit", "primary", {"type": "submit"})}
|
|
142
|
+
</div>
|
|
143
|
+
</form>
|
|
144
|
+
</details>
|
|
129
145
|
</div>
|
|
146
|
+
<script>
|
|
147
|
+
const bypassDetails = document.getElementById('bypassDetails');
|
|
148
|
+
const bypassSummary = document.getElementById('bypassSummary');
|
|
149
|
+
|
|
150
|
+
if (bypassDetails && bypassSummary) {{
|
|
151
|
+
bypassDetails.addEventListener('toggle', () => {{
|
|
152
|
+
if (bypassDetails.open) {{
|
|
153
|
+
bypassSummary.textContent = 'Hide CAPTCHA Bypass';
|
|
154
|
+
}} else {{
|
|
155
|
+
bypassSummary.textContent = 'Show CAPTCHA Bypass';
|
|
156
|
+
}}
|
|
157
|
+
}});
|
|
158
|
+
}}
|
|
159
|
+
</script>
|
|
130
160
|
'''
|
|
131
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
|
+
|
|
132
280
|
@app.get('/captcha/delete/<package_id>')
|
|
133
281
|
def delete_captcha_package(package_id):
|
|
134
282
|
success = delete_package(shared_state, package_id)
|
|
@@ -285,7 +433,6 @@ def setup_captcha_routes(app):
|
|
|
285
433
|
<div>
|
|
286
434
|
<h1><img src="{images.logo}" type="image/png" alt="Quasarr logo" class="logo"/>Quasarr</h1>
|
|
287
435
|
<p id="package-title" style="max-width: 370px; word-wrap: break-word; overflow-wrap: break-word;"><b>Package:</b> {title}</p>
|
|
288
|
-
<h3>Solve CAPTCHA</h3>
|
|
289
436
|
<div id="captcha-key"></div>
|
|
290
437
|
{link_select}<br><br>
|
|
291
438
|
<input type="hidden" id="link-hidden" value="{prioritized_links[0][0]}" />
|
|
@@ -408,8 +555,11 @@ def setup_captcha_routes(app):
|
|
|
408
555
|
# Process links input
|
|
409
556
|
if links_input:
|
|
410
557
|
info(f"Processing direct links bypass for {title}")
|
|
411
|
-
|
|
412
|
-
|
|
558
|
+
raw_links = [link.strip() for link in links_input.split('\n') if link.strip()]
|
|
559
|
+
links = [l for l in raw_links if l.lower().startswith(("http://", "https://"))]
|
|
560
|
+
|
|
561
|
+
info(f"Received {len(links)} valid direct download links "
|
|
562
|
+
f"(from {len(raw_links)} provided)")
|
|
413
563
|
|
|
414
564
|
# Process DLC file
|
|
415
565
|
elif dlc_upload:
|
|
@@ -590,7 +740,6 @@ def setup_captcha_routes(app):
|
|
|
590
740
|
<body>
|
|
591
741
|
<h1><img src="{images.logo}" type="image/png" alt="Quasarr logo" class="logo"/>Quasarr</h1>
|
|
592
742
|
<p><b>Package:</b> {title}</p>
|
|
593
|
-
<h3>Solve CAPTCHA</h3>
|
|
594
743
|
<form action="/captcha/decrypt-filecrypt-circle?url={url}&session_id={session_id}&package_id={package_id}" method="post">
|
|
595
744
|
<input type="image" src="/captcha/circle.php?url={url}&session_id={session_id}" name="button" alt="Circle CAPTCHA">
|
|
596
745
|
</form>
|
quasarr/providers/version.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
quasarr/__init__.py,sha256=_WoDFvqXXilQynsiPrY-SXyADy1OwhAjQkdaJFqqHo0,17873
|
|
2
2
|
quasarr/api/__init__.py,sha256=9Y_DTNYsHeimrXL3mAli8OUg0zqo7QGLF2ft40d3R-c,6822
|
|
3
3
|
quasarr/api/arr/__init__.py,sha256=HrzyavxsCmQkdV2SMqQSoJq3KgrsPBnQJdo5iyovmG8,16626
|
|
4
|
-
quasarr/api/captcha/__init__.py,sha256=
|
|
4
|
+
quasarr/api/captcha/__init__.py,sha256=axEcvs0SRExxmqsJVxqglDkSRIVcEjG_8zFR7rrQ6zY,40056
|
|
5
5
|
quasarr/api/config/__init__.py,sha256=0K7zqC9dt39Ul1RIJt0zNVdh1b9ARnfC6QFPa2D9FCw,819
|
|
6
6
|
quasarr/api/sponsors_helper/__init__.py,sha256=kAZabPlplPYRG6Uw7ZHTk5uypualwvhs-NoTOjQhhhA,6369
|
|
7
7
|
quasarr/api/statistics/__init__.py,sha256=NrBAjjHkIUE95HhPUGIfNqh2IqBqJ_zm00S90Y-Qnus,7038
|
|
@@ -33,7 +33,7 @@ quasarr/providers/notifications.py,sha256=bohT-6yudmFnmZMc3BwCGX0n1HdzSVgQG_LDZm
|
|
|
33
33
|
quasarr/providers/obfuscated.py,sha256=XfiEblJizqixUoA4MIsillr5Nh1dwFqCgLvBQWM7Lwo,193865
|
|
34
34
|
quasarr/providers/shared_state.py,sha256=4nswf5AuA4c1DWqSXsX0HXwlDt5e-UUUvQSy-vryCRE,28987
|
|
35
35
|
quasarr/providers/statistics.py,sha256=cEQixYnDMDqtm5wWe40E_2ucyo4mD0n3SrfelhQi1L8,6452
|
|
36
|
-
quasarr/providers/version.py,sha256=
|
|
36
|
+
quasarr/providers/version.py,sha256=iSqVO9atbE1bV6mc5sYLwCy9Q9-zrXejNWE1div7aYc,4004
|
|
37
37
|
quasarr/providers/web_server.py,sha256=XPj98T-axxgotovuB-rVw1IPCkJiNdXBlEeFvM_zSlM,1432
|
|
38
38
|
quasarr/providers/sessions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
39
|
quasarr/providers/sessions/al.py,sha256=mlP6SWfCY2HyOSV40uyotQ5T4eSBNYG9A5GWOEAdz-c,9589
|
|
@@ -56,9 +56,9 @@ quasarr/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
56
56
|
quasarr/storage/config.py,sha256=ISZXh9gHiBu5mYhHGYx8nZ8JyMYuSFqfVl52DiUDJec,5994
|
|
57
57
|
quasarr/storage/setup.py,sha256=gpHOsc5qtt-M72saZoMJFLE2YlCrjv7FWZknh-iVKsk,17766
|
|
58
58
|
quasarr/storage/sqlite_database.py,sha256=yMqFQfKf0k7YS-6Z3_7pj4z1GwWSXJ8uvF4IydXsuTE,3554
|
|
59
|
-
quasarr-1.17.
|
|
60
|
-
quasarr-1.17.
|
|
61
|
-
quasarr-1.17.
|
|
62
|
-
quasarr-1.17.
|
|
63
|
-
quasarr-1.17.
|
|
64
|
-
quasarr-1.17.
|
|
59
|
+
quasarr-1.17.3.dist-info/licenses/LICENSE,sha256=QQFCAfDgt7lSA8oSWDHIZ9aTjFbZaBJdjnGOHkuhK7k,1060
|
|
60
|
+
quasarr-1.17.3.dist-info/METADATA,sha256=rKqtvnroDMJIn9VERTBYRgX4xgvwMaJETnzlt8LaL-c,12249
|
|
61
|
+
quasarr-1.17.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
62
|
+
quasarr-1.17.3.dist-info/entry_points.txt,sha256=gXi8mUKsIqKVvn-bOc8E5f04sK_KoMCC-ty6b2Hf-jc,40
|
|
63
|
+
quasarr-1.17.3.dist-info/top_level.txt,sha256=dipJdaRda5ruTZkoGfZU60bY4l9dtPlmOWwxK_oGSF0,8
|
|
64
|
+
quasarr-1.17.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|