quasarr 1.20.8__py3-none-any.whl → 1.21.0__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.
@@ -0,0 +1,342 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Quasarr
3
+ # Project by https://github.com/rix1337
4
+
5
+ import html
6
+ import time
7
+ import traceback
8
+ import warnings
9
+ from base64 import urlsafe_b64encode
10
+ from datetime import datetime
11
+
12
+ import requests
13
+ from bs4 import BeautifulSoup
14
+ from bs4 import XMLParsedAsHTMLWarning
15
+
16
+ from quasarr.providers.imdb_metadata import get_localized_title
17
+ from quasarr.providers.log import info, debug
18
+
19
+ warnings.filterwarnings("ignore", category=XMLParsedAsHTMLWarning) # we dont want to use lxml
20
+
21
+ hostname = "wx"
22
+ supported_mirrors = []
23
+
24
+
25
+ def wx_feed(shared_state, start_time, request_from, mirror=None):
26
+ """
27
+ Fetch latest releases from RSS feed.
28
+ """
29
+ releases = []
30
+ host = shared_state.values["config"]("Hostnames").get(hostname)
31
+
32
+ if "lazylibrarian" in request_from.lower():
33
+ debug(f'Skipping {request_from} search on "{hostname.upper()}" (unsupported media type)!')
34
+ return releases
35
+
36
+ rss_url = f'https://{host}/rss'
37
+ headers = {
38
+ 'User-Agent': shared_state.values["user_agent"],
39
+ }
40
+
41
+ try:
42
+ response = requests.get(rss_url, headers=headers, timeout=10)
43
+
44
+ if response.status_code != 200:
45
+ info(f"{hostname.upper()}: RSS feed returned status {response.status_code}")
46
+ return releases
47
+
48
+ soup = BeautifulSoup(response.content, 'html.parser')
49
+ items = soup.find_all('entry')
50
+
51
+ if not items:
52
+ items = soup.find_all('item')
53
+
54
+ if not items:
55
+ debug(f"{hostname.upper()}: No entries found in RSS feed")
56
+ return releases
57
+
58
+ max_releases = 100
59
+ if len(items) > max_releases:
60
+ debug(f"{hostname.upper()}: Found {len(items)} entries, limiting to {max_releases}")
61
+ items = items[:max_releases]
62
+ else:
63
+ debug(f"{hostname.upper()}: Found {len(items)} entries in RSS feed")
64
+
65
+ for item in items:
66
+ try:
67
+ title_tag = item.find('title')
68
+ if not title_tag:
69
+ continue
70
+
71
+ title = title_tag.get_text(strip=True)
72
+ if not title:
73
+ continue
74
+
75
+ title = html.unescape(title)
76
+ title = title.replace(']]>', '').replace('<![CDATA[', '')
77
+ title = title.replace(' ', '.')
78
+
79
+ link_tag = item.find('link', rel='alternate')
80
+ if link_tag and link_tag.has_attr('href'):
81
+ source = link_tag['href']
82
+ else:
83
+ link_tag = item.find('link')
84
+ if not link_tag:
85
+ continue
86
+ source = link_tag.get_text(strip=True)
87
+
88
+ if not source:
89
+ continue
90
+
91
+ pub_date = item.find('updated') or item.find('pubDate')
92
+ if pub_date:
93
+ published = pub_date.get_text(strip=True)
94
+ else:
95
+ # Fallback: use current time if no pubDate found
96
+ published = datetime.now().strftime("%a, %d %b %Y %H:%M:%S +0000")
97
+
98
+ mb = 0
99
+ size = 0
100
+ imdb_id = None
101
+ password = host.upper()
102
+
103
+ payload = urlsafe_b64encode(
104
+ f"{title}|{source}|{mirror}|{mb}|{password}|{imdb_id or ''}".encode("utf-8")
105
+ ).decode("utf-8")
106
+ link = f"{shared_state.values['internal_address']}/download/?payload={payload}"
107
+
108
+ releases.append({
109
+ "details": {
110
+ "title": title,
111
+ "hostname": hostname,
112
+ "imdb_id": imdb_id,
113
+ "link": link,
114
+ "mirror": mirror,
115
+ "size": size,
116
+ "date": published,
117
+ "source": source
118
+ },
119
+ "type": "protected"
120
+ })
121
+
122
+ except Exception as e:
123
+ debug(f"{hostname.upper()}: error parsing RSS entry: {e}")
124
+ continue
125
+
126
+ except Exception as e:
127
+ info(f"Error loading {hostname.upper()} feed: {e}")
128
+ return releases
129
+
130
+ elapsed_time = time.time() - start_time
131
+ debug(f"Time taken: {elapsed_time:.2f}s ({hostname})")
132
+
133
+ return releases
134
+
135
+
136
+ def wx_search(shared_state, start_time, request_from, search_string, mirror=None, season=None, episode=None):
137
+ """
138
+ Search using internal API.
139
+ """
140
+ releases = []
141
+ host = shared_state.values["config"]("Hostnames").get(hostname)
142
+
143
+ if "lazylibrarian" in request_from.lower():
144
+ debug(f'Skipping {request_from} search on "{hostname.upper()}" (unsupported media type)!')
145
+ return releases
146
+
147
+ imdb_id = shared_state.is_imdb_id(search_string)
148
+ if imdb_id:
149
+ info(f"{hostname.upper()}: Received IMDb ID: {imdb_id}")
150
+ title = get_localized_title(shared_state, imdb_id, 'de')
151
+ if not title:
152
+ info(f"{hostname.upper()}: no title for IMDb {imdb_id}")
153
+ return releases
154
+ info(f"{hostname.upper()}: Translated IMDb {imdb_id} to German title: '{title}'")
155
+ search_string = html.unescape(title)
156
+ else:
157
+ info(f"{hostname.upper()}: Using search string directly: '{search_string}'")
158
+
159
+ api_url = f'https://api.{host}/start/search'
160
+
161
+ headers = {
162
+ 'User-Agent': shared_state.values["user_agent"],
163
+ 'Accept': 'application/json, text/plain, */*',
164
+ 'Referer': f'https://{host}/search'
165
+ }
166
+
167
+ params = {
168
+ '__LOAD_P': '',
169
+ 'per_page': 50,
170
+ 'q': search_string,
171
+ 'selectedTypes': '',
172
+ 'selectedGenres': '',
173
+ 'types': 'movie,series,anime',
174
+ 'genres': '',
175
+ 'years': '',
176
+ 'ratings': '',
177
+ 'page': 1,
178
+ 'sortBy': 'latest',
179
+ 'sortOrder': 'desc'
180
+ }
181
+
182
+ if "sonarr" in request_from.lower():
183
+ params['types'] = 'series,anime'
184
+ elif "radarr" in request_from.lower():
185
+ params['types'] = 'movie'
186
+
187
+ info(f"{hostname.upper()}: Searching: '{search_string}'")
188
+
189
+ try:
190
+ response = requests.get(api_url, headers=headers, params=params, timeout=10)
191
+
192
+ if response.status_code != 200:
193
+ info(f"{hostname.upper()}: Search API returned status {response.status_code}")
194
+ return releases
195
+
196
+ data = response.json()
197
+
198
+ if 'items' in data and 'data' in data['items']:
199
+ items = data['items']['data']
200
+ elif 'data' in data:
201
+ items = data['data']
202
+ elif 'results' in data:
203
+ items = data['results']
204
+ else:
205
+ items = data if isinstance(data, list) else []
206
+
207
+ info(f"{hostname.upper()}: Found {len(items)} items in search results")
208
+
209
+ for item in items:
210
+ try:
211
+ uid = item.get('uid')
212
+ if not uid:
213
+ debug(f"{hostname.upper()}: Item has no UID, skipping")
214
+ continue
215
+
216
+ info(f"{hostname.upper()}: Fetching details for UID: {uid}")
217
+
218
+ detail_url = f'https://api.{host}/start/d/{uid}'
219
+ detail_response = requests.get(detail_url, headers=headers, timeout=10)
220
+
221
+ if detail_response.status_code != 200:
222
+ debug(f"{hostname.upper()}: Detail API returned {detail_response.status_code} for {uid}")
223
+ continue
224
+
225
+ detail_data = detail_response.json()
226
+
227
+ if 'item' in detail_data:
228
+ detail_item = detail_data['item']
229
+ else:
230
+ detail_item = detail_data
231
+
232
+ item_imdb_id = imdb_id
233
+ if not item_imdb_id:
234
+ item_imdb_id = detail_item.get('imdb_id') or detail_item.get('imdbid')
235
+ if not item_imdb_id and 'options' in detail_item:
236
+ item_imdb_id = detail_item['options'].get('imdb_id')
237
+
238
+ source = f"https://{host}/detail/{uid}"
239
+
240
+ main_title = detail_item.get('fulltitle') or detail_item.get('title') or detail_item.get('name')
241
+ if main_title:
242
+ title = html.unescape(main_title)
243
+ title = title.replace(' ', '.')
244
+
245
+ if shared_state.is_valid_release(title, request_from, search_string, season, episode):
246
+ published = detail_item.get('updated_at') or detail_item.get('created_at')
247
+ if not published:
248
+ published = datetime.now().strftime("%a, %d %b %Y %H:%M:%S +0000")
249
+ password = f"www.{host}"
250
+
251
+ payload = urlsafe_b64encode(
252
+ f"{title}|{source}|{mirror}|0|{password}|{item_imdb_id or ''}".encode("utf-8")
253
+ ).decode("utf-8")
254
+ link = f"{shared_state.values['internal_address']}/download/?payload={payload}"
255
+
256
+ releases.append({
257
+ "details": {
258
+ "title": title,
259
+ "hostname": hostname,
260
+ "imdb_id": item_imdb_id,
261
+ "link": link,
262
+ "mirror": mirror,
263
+ "size": 0,
264
+ "date": published,
265
+ "source": source
266
+ },
267
+ "type": "protected"
268
+ })
269
+
270
+ if 'releases' in detail_item and isinstance(detail_item['releases'], list):
271
+ info(f"{hostname.upper()}: Found {len(detail_item['releases'])} releases for {uid}")
272
+
273
+ for release in detail_item['releases']:
274
+ try:
275
+ release_title = release.get('fulltitle')
276
+ if not release_title:
277
+ continue
278
+
279
+ release_title = html.unescape(release_title)
280
+ release_title = release_title.replace(' ', '.')
281
+
282
+ if not shared_state.is_valid_release(release_title, request_from, search_string, season,
283
+ episode):
284
+ debug(f"{hostname.upper()}: ✗ Release filtered out: {release_title}")
285
+ continue
286
+
287
+ release_uid = release.get('uid')
288
+ if release_uid:
289
+ release_source = f"https://{host}/detail/{uid}?release={release_uid}"
290
+ else:
291
+ release_source = source
292
+
293
+ release_published = release.get('updated_at') or release.get(
294
+ 'created_at') or detail_item.get('updated_at')
295
+ if not release_published:
296
+ release_published = datetime.now().strftime("%a, %d %b %Y %H:%M:%S +0000")
297
+ release_size = release.get('size', 0)
298
+ password = f"www.{host}"
299
+
300
+ payload = urlsafe_b64encode(
301
+ f"{release_title}|{release_source}|{mirror}|{release_size}|{password}|{item_imdb_id or ''}".encode(
302
+ "utf-8")
303
+ ).decode("utf-8")
304
+ link = f"{shared_state.values['internal_address']}/download/?payload={payload}"
305
+
306
+ releases.append({
307
+ "details": {
308
+ "title": release_title,
309
+ "hostname": hostname,
310
+ "imdb_id": item_imdb_id,
311
+ "link": link,
312
+ "mirror": mirror,
313
+ "size": release_size,
314
+ "date": release_published,
315
+ "source": release_source
316
+ },
317
+ "type": "protected"
318
+ })
319
+
320
+ except Exception as e:
321
+ debug(f"{hostname.upper()}: Error parsing release: {e}")
322
+ continue
323
+ else:
324
+ debug(f"{hostname.upper()}: No releases array found for {uid}")
325
+
326
+ except Exception as e:
327
+ debug(f"{hostname.upper()}: Error processing item: {e}")
328
+ debug(f"{hostname.upper()}: {traceback.format_exc()}")
329
+ continue
330
+
331
+ info(f"{hostname.upper()}: Returning {len(releases)} total releases")
332
+
333
+ except Exception as e:
334
+ info(f"Error in {hostname.upper()} search: {e}")
335
+
336
+ debug(f"{hostname.upper()}: {traceback.format_exc()}")
337
+ return releases
338
+
339
+ elapsed_time = time.time() - start_time
340
+ debug(f"Time taken: {elapsed_time:.2f}s ({hostname})")
341
+
342
+ return releases
quasarr/storage/config.py CHANGED
@@ -30,6 +30,7 @@ class Config(object):
30
30
  ("by", "secret", ""),
31
31
  ("dd", "secret", ""),
32
32
  ("dj", "secret", ""),
33
+ ("dl", "secret", ""),
33
34
  ("dt", "secret", ""),
34
35
  ("dw", "secret", ""),
35
36
  ("fx", "secret", ""),
@@ -40,7 +41,8 @@ class Config(object):
40
41
  ("sf", "secret", ""),
41
42
  ("sj", "secret", ""),
42
43
  ("sl", "secret", ""),
43
- ("wd", "secret", "")
44
+ ("wd", "secret", ""),
45
+ ("wx", "secret", "")
44
46
  ],
45
47
  'FlareSolverr': [
46
48
  ("url", "str", ""),
@@ -53,6 +55,10 @@ class Config(object):
53
55
  ("user", "secret", ""),
54
56
  ("password", "secret", "")
55
57
  ],
58
+ 'DL': [
59
+ ("user", "secret", ""),
60
+ ("password", "secret", "")
61
+ ],
56
62
  'NX': [
57
63
  ("user", "secret", ""),
58
64
  ("password", "secret", "")
quasarr/storage/setup.py CHANGED
@@ -12,6 +12,7 @@ import quasarr
12
12
  import quasarr.providers.html_images as images
13
13
  import quasarr.providers.sessions.al
14
14
  import quasarr.providers.sessions.dd
15
+ import quasarr.providers.sessions.dl
15
16
  import quasarr.providers.sessions.nx
16
17
  from quasarr.providers.html_templates import render_button, render_form, render_success, render_fail
17
18
  from quasarr.providers.log import info
@@ -263,14 +264,21 @@ def hostname_credentials_config(shared_state, shorthand, domain):
263
264
  if quasarr.providers.sessions.al.create_and_persist_session(shared_state):
264
265
  quasarr.providers.web_server.temp_server_success = True
265
266
  return render_success(f"{sh} credentials set successfully", 5)
266
- if sh.lower() == "dd":
267
+ elif sh.lower() == "dd":
267
268
  if quasarr.providers.sessions.dd.create_and_persist_session(shared_state):
268
269
  quasarr.providers.web_server.temp_server_success = True
269
270
  return render_success(f"{sh} credentials set successfully", 5)
270
- if sh.lower() == "nx":
271
+ elif sh.lower() == "dl":
272
+ if quasarr.providers.sessions.dl.create_and_persist_session(shared_state):
273
+ quasarr.providers.web_server.temp_server_success = True
274
+ return render_success(f"{sh} credentials set successfully", 5)
275
+ elif sh.lower() == "nx":
271
276
  if quasarr.providers.sessions.nx.create_and_persist_session(shared_state):
272
277
  quasarr.providers.web_server.temp_server_success = True
273
278
  return render_success(f"{sh} credentials set successfully", 5)
279
+ else:
280
+ quasarr.providers.web_server.temp_server_success = False
281
+ return render_fail(f"Unknown site shorthand! ({sh})")
274
282
 
275
283
  config.save("user", "")
276
284
  config.save("password", "")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quasarr
3
- Version: 1.20.8
3
+ Version: 1.21.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
@@ -151,6 +151,7 @@ docker run -d \
151
151
  -e 'HOSTNAMES'='https://pastebin.com/raw/eX4Mpl3'
152
152
  -e 'SILENT'='True' \
153
153
  -e 'DEBUG'='' \
154
+ -e 'TZ'='Europe/Berlin' \
154
155
  ghcr.io/rix1337/quasarr:latest
155
156
  ```
156
157
 
@@ -163,6 +164,7 @@ docker run -d \
163
164
  * Must contain at least one valid Hostname per line `ab = xyz`
164
165
  * `SILENT` is optional and silences all discord notifications except for error messages from SponsorsHelper if `True`.
165
166
  * `DEBUG` is optional and enables debug logging if `True`.
167
+ * `TZ` is optional, wrong timezone can cause HTTPS/SSL issues
166
168
 
167
169
  # Manual setup
168
170
 
@@ -1,11 +1,11 @@
1
- quasarr/__init__.py,sha256=_WoDFvqXXilQynsiPrY-SXyADy1OwhAjQkdaJFqqHo0,17873
1
+ quasarr/__init__.py,sha256=4-EVvIdDjMqidqp3xpXfcDl-fSe0J_B415ueZDAKBss,18137
2
2
  quasarr/api/__init__.py,sha256=9Y_DTNYsHeimrXL3mAli8OUg0zqo7QGLF2ft40d3R-c,6822
3
- quasarr/api/arr/__init__.py,sha256=HrzyavxsCmQkdV2SMqQSoJq3KgrsPBnQJdo5iyovmG8,16626
3
+ quasarr/api/arr/__init__.py,sha256=Un2mi_z8aHHhE8ks4Dq50FO3PFHUmBWggrDvU39TVaU,16711
4
4
  quasarr/api/captcha/__init__.py,sha256=2qlcJn_Kp_PWP8-_MJvIlPkRlZitH4B58QbdcFZ6xqU,49765
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
8
- quasarr/downloads/__init__.py,sha256=2jveOXh165lb-W1CesdS_CVDlrtDV66Gx11OMGTHPXI,11254
8
+ quasarr/downloads/__init__.py,sha256=AGZcafQG7ZKLadYaWmR0HR3lljt-l00llWw3G39Y9vA,13345
9
9
  quasarr/downloads/linkcrypters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  quasarr/downloads/linkcrypters/al.py,sha256=pM3NDan8x0WU8OS1GV3HuuV4B6Nm0a-ATrVORvLHt9M,8487
11
11
  quasarr/downloads/linkcrypters/filecrypt.py,sha256=GT51x_MG_hW4IpOF6OvL5r-2mTnMijI8K7_1D5Bfn4U,18884
@@ -16,6 +16,7 @@ quasarr/downloads/sources/al.py,sha256=Ulc4fTuX8_gOHeTJzZYEAgUCiFPoyczIdbZh6qA3j
16
16
  quasarr/downloads/sources/by.py,sha256=VzytGYyy81vjsvNJabohoK8PkjYTKCwXM1TjeD3Ker0,3695
17
17
  quasarr/downloads/sources/dd.py,sha256=EQ823wrVusVCVJhh9Rdf67-Yae9XYio8Uj_HW_y5qO0,2841
18
18
  quasarr/downloads/sources/dj.py,sha256=b_RR_dqd4Zc9lbZbZbwZijDkXCb42OaU7eOAI4lX9EE,214
19
+ quasarr/downloads/sources/dl.py,sha256=nCSDQpa3X7b6Q1M7sxv6GgZ7FJQfJ50dWv43u8ozdjc,7475
19
20
  quasarr/downloads/sources/dt.py,sha256=fzAyJy8nmqTAFRObvaRbvsXdBkCo5JuojCJYQMYuPOs,2108
20
21
  quasarr/downloads/sources/dw.py,sha256=15UH-kBZt06GS5CDi-TTJGV_H59mQO0Nl-y3nYA5kOk,2504
21
22
  quasarr/downloads/sources/he.py,sha256=EZ42WIHE8rwvpvwesaWeG__1dUBq75OQzJ1n7Lgrx1g,3450
@@ -26,29 +27,32 @@ quasarr/downloads/sources/sf.py,sha256=PDBuWgJmEYmD1b-5blS3YWgrqIhJjfwz91IuiMy6r
26
27
  quasarr/downloads/sources/sj.py,sha256=d2HC52SFYXUXAr7AIaipthVvL-WpvJaD-8AuN-5Z-I8,214
27
28
  quasarr/downloads/sources/sl.py,sha256=w6Mo1dphrZRlXfhBfAhFV8KcPfHINuTiFSNu3BYd46k,2851
28
29
  quasarr/downloads/sources/wd.py,sha256=NOilEZIF9rumU2LMtfRfXyet3Mzn2shCs8NFCEC3CHY,3747
30
+ quasarr/downloads/sources/wx.py,sha256=lufMZYNniKWj2x2mfYsEkGw_Qqi3TWg66EgU3uP9TiI,4769
29
31
  quasarr/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
32
  quasarr/providers/cloudflare.py,sha256=mJxTYM7JjwIjdO6U_GyVj-dyug6XdD0-ObkYTaPtFVg,7028
31
- quasarr/providers/html_images.py,sha256=ZvSzG5Mbjol1I_exFHcb4BZ2eUQ3CqquY_MwRBlr-HU,45609
33
+ quasarr/providers/html_images.py,sha256=CvJgBs_M5ziTI-ccSQheI7FC1pZWY52R9Elq5WuBwfY,46481
32
34
  quasarr/providers/html_templates.py,sha256=90O9RGwlpJB7jC8NZ0ggh9aD6LNM34IRSVsHCa9vSls,7825
33
35
  quasarr/providers/imdb_metadata.py,sha256=10L4kZkt6Fg0HGdNcc6KCtIQHRYEqdarLyaMVN6mT8w,4843
34
36
  quasarr/providers/log.py,sha256=_g5RwtfuksARXnvryhsngzoJyFcNzj6suqd3ndqZM0Y,313
35
- quasarr/providers/myjd_api.py,sha256=vPiX-kOQk19ugciefw9wm_hw8djbT4o-Gk9w2XEBeI4,32707
37
+ quasarr/providers/myjd_api.py,sha256=Z3PEiO3c3UfDSr4Up5rgwTAnjloWHb-H1RkJ6BLKZv8,34140
36
38
  quasarr/providers/notifications.py,sha256=bohT-6yudmFnmZMc3BwCGX0n1HdzSVgQG_LDZm_38dI,4630
37
39
  quasarr/providers/obfuscated.py,sha256=YydQJHrZ485pHaXK0DHHRW3eLZygGr6c0xnUKD6mcCE,236502
38
- quasarr/providers/shared_state.py,sha256=4nswf5AuA4c1DWqSXsX0HXwlDt5e-UUUvQSy-vryCRE,28987
40
+ quasarr/providers/shared_state.py,sha256=1NUKtm9YXWPvN64By2O2OYH5ke5TmBkJSbSxiNczgtU,29849
39
41
  quasarr/providers/statistics.py,sha256=cEQixYnDMDqtm5wWe40E_2ucyo4mD0n3SrfelhQi1L8,6452
40
- quasarr/providers/version.py,sha256=9Qj2WKI6t9PhJ-I5iwExX3pOFRYnxcHmCX97EiV4xsw,4004
42
+ quasarr/providers/version.py,sha256=8JL_ohKOlHRsgfE_9gi7SYPfyd2pMk1L1sREQrMUV6I,4004
41
43
  quasarr/providers/web_server.py,sha256=XPj98T-axxgotovuB-rVw1IPCkJiNdXBlEeFvM_zSlM,1432
42
44
  quasarr/providers/sessions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
45
  quasarr/providers/sessions/al.py,sha256=mlP6SWfCY2HyOSV40uyotQ5T4eSBNYG9A5GWOEAdz-c,9589
44
46
  quasarr/providers/sessions/dd.py,sha256=JdXjqmjuyY32w0cIlwphRm8Sy43EK8nEEFwyXUkEGb4,2596
47
+ quasarr/providers/sessions/dl.py,sha256=8toAHn5C9FbjHuhjfQEeKR1Fz5tRENrIgFxdjUuXCIU,5381
45
48
  quasarr/providers/sessions/nx.py,sha256=qfW12AB_0nNsAoKOaSF4z0T9DCxMQleWCYf3fqJtF2A,2688
46
- quasarr/search/__init__.py,sha256=yDk_Mx4QEBLODqfFZaRBfbiOGlntuVb22VN63EJdRrk,5367
49
+ quasarr/search/__init__.py,sha256=V59LIiC75mQvasDdTjiWZRbPD1jXO1lhXlKeNVX0iOc,5726
47
50
  quasarr/search/sources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
51
  quasarr/search/sources/al.py,sha256=yr6wx-VcSOFYK_o3N1bepC4t6Gvt9eDvcG9fQBFg0bg,17203
49
52
  quasarr/search/sources/by.py,sha256=OPoAqS5kSSNrRVsPlALhX59h3lEZWGA7LlFfL4vH2-o,7914
50
53
  quasarr/search/sources/dd.py,sha256=pVpdHLZlw2CYklBf_YLkeDWbCNsDLR2iecccR2c2RyI,4889
51
54
  quasarr/search/sources/dj.py,sha256=2HIdg5ddXP4DtjHlyXmuQ8QVhOPt3Hh2kL4uxhFJK-8,7074
55
+ quasarr/search/sources/dl.py,sha256=-CY3dSbzGwZ4t1Z0B0Q1dBQg1jStrUpqF6jG_-BytSs,11379
52
56
  quasarr/search/sources/dt.py,sha256=m1kQ7mC43QlWZyVIkw-OXJGjWiT9IbQuFtHWiR8CjhA,9580
53
57
  quasarr/search/sources/dw.py,sha256=-daUTBTA5izeatrE7TITVlnzNCQ5HfovYMMZ8UTM-2o,7636
54
58
  quasarr/search/sources/fx.py,sha256=JAyD727yDAFIP14bzfi2SkX9paysXGkQdIybShYtdko,8596
@@ -60,13 +64,14 @@ quasarr/search/sources/sf.py,sha256=3z_fvcafOh7U4D_vgq9yC8ktKeazI9fiAi96hCeXb5Q,
60
64
  quasarr/search/sources/sj.py,sha256=JRzoCDohClmGH7aXOz82KVUt6pZsZoBDBXvwvQrAijM,7074
61
65
  quasarr/search/sources/sl.py,sha256=5e5S7JvdbNOc2EthyOkfC4aTpG8O7fn4WS2O3_EXjnM,9463
62
66
  quasarr/search/sources/wd.py,sha256=O02j3irSlVw2qES82g_qHuavAk-njjSRH1dHSCnOUas,7540
67
+ quasarr/search/sources/wx.py,sha256=B6Ra0Wie9Ii96Kiz4Zdpb_qUmBwWkyA0rIoA7XdNNYo,13118
63
68
  quasarr/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
- quasarr/storage/config.py,sha256=a0JAeiSqMQYBvfZTyYtOxDZvuLGP5lZhMHb7nX9azPc,6130
65
- quasarr/storage/setup.py,sha256=gpHOsc5qtt-M72saZoMJFLE2YlCrjv7FWZknh-iVKsk,17766
69
+ quasarr/storage/config.py,sha256=hOI7vvIo1YaML3dtAkTmp0HSedWF6brVhRk3d8pJtXI,6300
70
+ quasarr/storage/setup.py,sha256=Sv5piyCnCfAfOLErHQGZS91HwTgbmLcW7K51kR6235g,18255
66
71
  quasarr/storage/sqlite_database.py,sha256=yMqFQfKf0k7YS-6Z3_7pj4z1GwWSXJ8uvF4IydXsuTE,3554
67
- quasarr-1.20.8.dist-info/licenses/LICENSE,sha256=QQFCAfDgt7lSA8oSWDHIZ9aTjFbZaBJdjnGOHkuhK7k,1060
68
- quasarr-1.20.8.dist-info/METADATA,sha256=hXb-QMlycS1yTS_rn8fXB6FlLXH094aZ2Wl3ASi-dag,12653
69
- quasarr-1.20.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
70
- quasarr-1.20.8.dist-info/entry_points.txt,sha256=gXi8mUKsIqKVvn-bOc8E5f04sK_KoMCC-ty6b2Hf-jc,40
71
- quasarr-1.20.8.dist-info/top_level.txt,sha256=dipJdaRda5ruTZkoGfZU60bY4l9dtPlmOWwxK_oGSF0,8
72
- quasarr-1.20.8.dist-info/RECORD,,
72
+ quasarr-1.21.0.dist-info/licenses/LICENSE,sha256=QQFCAfDgt7lSA8oSWDHIZ9aTjFbZaBJdjnGOHkuhK7k,1060
73
+ quasarr-1.21.0.dist-info/METADATA,sha256=Nsl4ztdogzEu2h9xb6T7dSIGWitdMAmskj0Xt4vxl8M,12743
74
+ quasarr-1.21.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
75
+ quasarr-1.21.0.dist-info/entry_points.txt,sha256=gXi8mUKsIqKVvn-bOc8E5f04sK_KoMCC-ty6b2Hf-jc,40
76
+ quasarr-1.21.0.dist-info/top_level.txt,sha256=dipJdaRda5ruTZkoGfZU60bY4l9dtPlmOWwxK_oGSF0,8
77
+ quasarr-1.21.0.dist-info/RECORD,,