quasarr 1.18.0__py3-none-any.whl → 1.20.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.

Potentially problematic release.


This version of quasarr might be problematic. Click here for more details.

@@ -0,0 +1,213 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Quasarr
3
+ # Project by https://github.com/rix1337
4
+
5
+ import json
6
+ import re
7
+ import time
8
+ from base64 import urlsafe_b64encode
9
+ from datetime import datetime, timedelta
10
+
11
+ import requests
12
+ from bs4 import BeautifulSoup
13
+
14
+ from quasarr.providers.imdb_metadata import get_localized_title
15
+ from quasarr.providers.log import info, debug
16
+
17
+ hostname = "sj"
18
+
19
+
20
+ def convert_to_rss_date(date_str):
21
+ try:
22
+ return datetime.fromisoformat(
23
+ date_str.replace("Z", "+00:00")
24
+ ).strftime("%a, %d %b %Y %H:%M:%S +0000")
25
+ except Exception:
26
+ return ""
27
+
28
+
29
+ def sj_feed(shared_state, start_time, request_from, mirror=None):
30
+ releases = []
31
+
32
+ if "sonarr" not in request_from.lower():
33
+ debug(f'Skipping {request_from} search on "{hostname.upper()}" (unsupported media type)!')
34
+ return releases
35
+
36
+ sj_host = shared_state.values["config"]("Hostnames").get(hostname)
37
+ password = sj_host
38
+
39
+ url = f"https://{sj_host}/api/releases/latest/0"
40
+ headers = {"User-Agent": shared_state.values["user_agent"]}
41
+
42
+ try:
43
+ r = requests.get(url, headers=headers, timeout=10)
44
+ data = json.loads(r.content)
45
+ except Exception as e:
46
+ info(f"{hostname.upper()}: feed load error: {e}")
47
+ return releases
48
+
49
+ for release in data:
50
+ try:
51
+ title = release.get("name").rstrip(".")
52
+ if not title:
53
+ continue
54
+
55
+ published = convert_to_rss_date(release.get("createdAt"))
56
+ if not published:
57
+ continue
58
+
59
+ media = release.get("_media", {})
60
+ slug = media.get("slug")
61
+ if not slug:
62
+ continue
63
+
64
+ series_url = f"https://{sj_host}/serie/{slug}"
65
+
66
+ mb = 0
67
+ size = 0
68
+ imdb_id = None
69
+
70
+ payload = urlsafe_b64encode(
71
+ f"{title}|{series_url}|{mirror}|{mb}|{password}|{imdb_id}".encode("utf-8")
72
+ ).decode("utf-8")
73
+
74
+ link = f"{shared_state.values['internal_address']}/download/?payload={payload}"
75
+
76
+ releases.append({
77
+ "details": {
78
+ "title": title,
79
+ "hostname": hostname,
80
+ "imdb_id": imdb_id,
81
+ "link": link,
82
+ "mirror": mirror,
83
+ "size": size,
84
+ "date": published,
85
+ "source": series_url
86
+ },
87
+ "type": "protected"
88
+ })
89
+
90
+ except Exception as e:
91
+ debug(f"{hostname.upper()}: feed parse error: {e}")
92
+ continue
93
+
94
+ debug(f"Time taken: {time.time() - start_time:.2f}s ({hostname})")
95
+ return releases
96
+
97
+
98
+ def sj_search(shared_state, start_time, request_from, search_string, mirror=None, season=None, episode=None):
99
+ releases = []
100
+
101
+ if "sonarr" not in request_from.lower():
102
+ debug(f'Skipping {request_from} search on "{hostname.upper()}" (unsupported media type)!')
103
+ return releases
104
+
105
+ sj_host = shared_state.values["config"]("Hostnames").get(hostname)
106
+ password = sj_host
107
+
108
+ imdb_id = shared_state.is_imdb_id(search_string)
109
+ if not imdb_id:
110
+ return releases
111
+
112
+ localized_title = get_localized_title(shared_state, imdb_id, "de")
113
+ if not localized_title:
114
+ info(f"{hostname.upper()}: no localized title for IMDb {imdb_id}")
115
+ return releases
116
+
117
+ headers = {"User-Agent": shared_state.values["user_agent"]}
118
+ search_url = f"https://{sj_host}/serie/search"
119
+ params = {"q": localized_title}
120
+
121
+ try:
122
+ r = requests.get(search_url, headers=headers, params=params, timeout=10)
123
+ soup = BeautifulSoup(r.content, "html.parser")
124
+ results = soup.find_all("a", href=re.compile(r"^/serie/"))
125
+ except Exception as e:
126
+ info(f"{hostname.upper()}: search load error: {e}")
127
+ return releases
128
+
129
+ one_hour_ago = (datetime.now() - timedelta(hours=1)).strftime('%Y-%m-%d %H:%M:%S')
130
+ sanitized_search_string = shared_state.sanitize_string(localized_title)
131
+
132
+ for result in results:
133
+ try:
134
+ result_title = result.get_text(strip=True)
135
+
136
+ sanitized_title = shared_state.sanitize_string(result_title)
137
+
138
+ if not re.search(
139
+ rf"\b{re.escape(sanitized_search_string)}\b",
140
+ sanitized_title
141
+ ):
142
+ debug(
143
+ f"Search string '{localized_title}' doesn't match '{result_title}'"
144
+ )
145
+ continue
146
+
147
+ debug(
148
+ f"Matched search string '{localized_title}' with result '{result_title}'"
149
+ )
150
+
151
+ series_url = f"https://{sj_host}{result['href']}"
152
+
153
+ r = requests.get(series_url, headers=headers, timeout=10)
154
+ media_id_match = re.search(r'data-mediaid="([^"]+)"', r.text)
155
+ if not media_id_match:
156
+ debug(f"{hostname.upper()}: no media id for {result_title}")
157
+ continue
158
+
159
+ media_id = media_id_match.group(1)
160
+ api_url = f"https://{sj_host}/api/media/{media_id}/releases"
161
+
162
+ r = requests.get(api_url, headers=headers, timeout=10)
163
+ data = json.loads(r.content)
164
+
165
+ for season_block in data.values():
166
+ for item in season_block.get("items", []):
167
+ title = item.get("name").rstrip(".")
168
+ if not title:
169
+ continue
170
+
171
+ if not shared_state.is_valid_release(
172
+ title,
173
+ request_from,
174
+ search_string,
175
+ season,
176
+ episode
177
+ ):
178
+ continue
179
+
180
+ published = convert_to_rss_date(item.get("createdAt"))
181
+ if not published:
182
+ debug(f"{hostname.upper()}: no published date for {title}")
183
+ published = one_hour_ago
184
+
185
+ mb = 0
186
+ size = 0
187
+
188
+ payload = urlsafe_b64encode(
189
+ f"{title}|{series_url}|{mirror}|{mb}|{password}|{imdb_id}".encode("utf-8")
190
+ ).decode("utf-8")
191
+
192
+ link = f"{shared_state.values['internal_address']}/download/?payload={payload}"
193
+
194
+ releases.append({
195
+ "details": {
196
+ "title": title,
197
+ "hostname": hostname,
198
+ "imdb_id": imdb_id,
199
+ "link": link,
200
+ "mirror": mirror,
201
+ "size": size,
202
+ "date": published,
203
+ "source": series_url
204
+ },
205
+ "type": "protected"
206
+ })
207
+
208
+ except Exception as e:
209
+ debug(f"{hostname.upper()}: search parse error: {e}")
210
+ continue
211
+
212
+ debug(f"Time taken: {time.time() - start_time:.2f}s ({hostname})")
213
+ return releases
quasarr/storage/config.py CHANGED
@@ -29,13 +29,16 @@ class Config(object):
29
29
  ("al", "secret", ""),
30
30
  ("by", "secret", ""),
31
31
  ("dd", "secret", ""),
32
+ ("dj", "secret", ""),
32
33
  ("dt", "secret", ""),
33
34
  ("dw", "secret", ""),
34
35
  ("fx", "secret", ""),
36
+ ("he", "secret", ""),
35
37
  ("mb", "secret", ""),
36
38
  ("nk", "secret", ""),
37
39
  ("nx", "secret", ""),
38
40
  ("sf", "secret", ""),
41
+ ("sj", "secret", ""),
39
42
  ("sl", "secret", ""),
40
43
  ("wd", "secret", "")
41
44
  ],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quasarr
3
- Version: 1.18.0
3
+ Version: 1.20.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
@@ -1,11 +1,11 @@
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=E1ZiQ93315c_KioDW2QvvcZuQ98M0O_b9LzqqQmUF-o,42977
4
+ quasarr/api/captcha/__init__.py,sha256=GSxwqS-Hle3B_RkJa4iXueRHw5MlaniXyexsMt0lOX4,49501
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=o_tA8scQmJUsj6JaIbo1S4cMAbeVk0uPj6jMIEOr5Cs,10679
8
+ quasarr/downloads/__init__.py,sha256=2jveOXh165lb-W1CesdS_CVDlrtDV66Gx11OMGTHPXI,11254
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
@@ -15,52 +15,58 @@ quasarr/downloads/sources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
15
15
  quasarr/downloads/sources/al.py,sha256=Ulc4fTuX8_gOHeTJzZYEAgUCiFPoyczIdbZh6qA3jzM,26180
16
16
  quasarr/downloads/sources/by.py,sha256=VzytGYyy81vjsvNJabohoK8PkjYTKCwXM1TjeD3Ker0,3695
17
17
  quasarr/downloads/sources/dd.py,sha256=EQ823wrVusVCVJhh9Rdf67-Yae9XYio8Uj_HW_y5qO0,2841
18
+ quasarr/downloads/sources/dj.py,sha256=b_RR_dqd4Zc9lbZbZbwZijDkXCb42OaU7eOAI4lX9EE,214
18
19
  quasarr/downloads/sources/dt.py,sha256=fzAyJy8nmqTAFRObvaRbvsXdBkCo5JuojCJYQMYuPOs,2108
19
20
  quasarr/downloads/sources/dw.py,sha256=15UH-kBZt06GS5CDi-TTJGV_H59mQO0Nl-y3nYA5kOk,2504
21
+ quasarr/downloads/sources/he.py,sha256=EZ42WIHE8rwvpvwesaWeG__1dUBq75OQzJ1n7Lgrx1g,3450
20
22
  quasarr/downloads/sources/mb.py,sha256=IS5_RdACD3yterFEAj_N7RIH4TVK-VEauZqfya23hmA,1411
21
- quasarr/downloads/sources/nk.py,sha256=b2NOHdrcxIx2xbMB07LKqAwCrlFm3GfHe2cQ8LVwIxw,1567
23
+ quasarr/downloads/sources/nk.py,sha256=rFdAf9ewfl5ELIFtlZWQ8Z3VjyCSxGwLX92szzwjvz0,1429
22
24
  quasarr/downloads/sources/nx.py,sha256=nI0c-oM1g_EyW06_o2wFgn_jm_Zh1XMy3kbRCN0hw1E,3211
23
25
  quasarr/downloads/sources/sf.py,sha256=PDBuWgJmEYmD1b-5blS3YWgrqIhJjfwz91IuiMy6rX8,6224
26
+ quasarr/downloads/sources/sj.py,sha256=d2HC52SFYXUXAr7AIaipthVvL-WpvJaD-8AuN-5Z-I8,214
24
27
  quasarr/downloads/sources/sl.py,sha256=w6Mo1dphrZRlXfhBfAhFV8KcPfHINuTiFSNu3BYd46k,2851
25
28
  quasarr/downloads/sources/wd.py,sha256=NOilEZIF9rumU2LMtfRfXyet3Mzn2shCs8NFCEC3CHY,3747
26
29
  quasarr/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
30
  quasarr/providers/cloudflare.py,sha256=mJxTYM7JjwIjdO6U_GyVj-dyug6XdD0-ObkYTaPtFVg,7028
28
- quasarr/providers/html_images.py,sha256=ro7T7vdGHoFXknOuC_W-Bs1W-fwvmhjZKhOWY-B95GI,43539
29
- quasarr/providers/html_templates.py,sha256=hAwHCq-FkM27W4ZOj_Yu3ic-OKRC7GIYgQkUeMCBNJo,7853
31
+ quasarr/providers/html_images.py,sha256=ZvSzG5Mbjol1I_exFHcb4BZ2eUQ3CqquY_MwRBlr-HU,45609
32
+ quasarr/providers/html_templates.py,sha256=90O9RGwlpJB7jC8NZ0ggh9aD6LNM34IRSVsHCa9vSls,7825
30
33
  quasarr/providers/imdb_metadata.py,sha256=10L4kZkt6Fg0HGdNcc6KCtIQHRYEqdarLyaMVN6mT8w,4843
31
34
  quasarr/providers/log.py,sha256=_g5RwtfuksARXnvryhsngzoJyFcNzj6suqd3ndqZM0Y,313
32
35
  quasarr/providers/myjd_api.py,sha256=1R4uL8Zb8wp1VGcvaO0yMXt2NVGmu6Kn9-GIF4x7vU0,32054
33
36
  quasarr/providers/notifications.py,sha256=bohT-6yudmFnmZMc3BwCGX0n1HdzSVgQG_LDZm_38dI,4630
34
- quasarr/providers/obfuscated.py,sha256=Gy8FjKiHNmmjDJalOTDM8zHlLqB19ArsHlN07qTy9Z8,211613
37
+ quasarr/providers/obfuscated.py,sha256=YydQJHrZ485pHaXK0DHHRW3eLZygGr6c0xnUKD6mcCE,236502
35
38
  quasarr/providers/shared_state.py,sha256=4nswf5AuA4c1DWqSXsX0HXwlDt5e-UUUvQSy-vryCRE,28987
36
39
  quasarr/providers/statistics.py,sha256=cEQixYnDMDqtm5wWe40E_2ucyo4mD0n3SrfelhQi1L8,6452
37
- quasarr/providers/version.py,sha256=BUukq06r4JaxR9TUuIzO8VSJ3eTxq1oig2UTcRkr7YU,4004
40
+ quasarr/providers/version.py,sha256=hICLetkRcBjcm_DHSkjerq19eYDlz2XV7GoVJ2gfrZ8,4004
38
41
  quasarr/providers/web_server.py,sha256=XPj98T-axxgotovuB-rVw1IPCkJiNdXBlEeFvM_zSlM,1432
39
42
  quasarr/providers/sessions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
43
  quasarr/providers/sessions/al.py,sha256=mlP6SWfCY2HyOSV40uyotQ5T4eSBNYG9A5GWOEAdz-c,9589
41
44
  quasarr/providers/sessions/dd.py,sha256=JdXjqmjuyY32w0cIlwphRm8Sy43EK8nEEFwyXUkEGb4,2596
42
45
  quasarr/providers/sessions/nx.py,sha256=qfW12AB_0nNsAoKOaSF4z0T9DCxMQleWCYf3fqJtF2A,2688
43
- quasarr/search/__init__.py,sha256=OQnzxvJsv38bdmC1EvFqI1oYUr5VZRtQTLi4SLXDHL0,4866
46
+ quasarr/search/__init__.py,sha256=yDk_Mx4QEBLODqfFZaRBfbiOGlntuVb22VN63EJdRrk,5367
44
47
  quasarr/search/sources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
48
  quasarr/search/sources/al.py,sha256=yr6wx-VcSOFYK_o3N1bepC4t6Gvt9eDvcG9fQBFg0bg,17203
46
49
  quasarr/search/sources/by.py,sha256=OPoAqS5kSSNrRVsPlALhX59h3lEZWGA7LlFfL4vH2-o,7914
47
50
  quasarr/search/sources/dd.py,sha256=pVpdHLZlw2CYklBf_YLkeDWbCNsDLR2iecccR2c2RyI,4889
51
+ quasarr/search/sources/dj.py,sha256=2HIdg5ddXP4DtjHlyXmuQ8QVhOPt3Hh2kL4uxhFJK-8,7074
48
52
  quasarr/search/sources/dt.py,sha256=m1kQ7mC43QlWZyVIkw-OXJGjWiT9IbQuFtHWiR8CjhA,9580
49
53
  quasarr/search/sources/dw.py,sha256=-daUTBTA5izeatrE7TITVlnzNCQ5HfovYMMZ8UTM-2o,7636
50
54
  quasarr/search/sources/fx.py,sha256=JAyD727yDAFIP14bzfi2SkX9paysXGkQdIybShYtdko,8596
55
+ quasarr/search/sources/he.py,sha256=ieBVlpd4nRonZyocV1kDlxIjgfWspspbspLS04PDQkQ,6503
51
56
  quasarr/search/sources/mb.py,sha256=owwH5T0Yh7dwYRqMVQ0ecAdDlQ5CwLwWkTcig2ePggI,7749
52
- quasarr/search/sources/nk.py,sha256=4_KqpWKTR-hCH69eL-3oqGtkDCWY2QsNyAjGwzin9RA,6439
57
+ quasarr/search/sources/nk.py,sha256=x84zckK8eG64X3oaPHYhNbK0aoSuVW8xp_n_mlE__NI,6427
53
58
  quasarr/search/sources/nx.py,sha256=JdRLA2pWS05m5_ARU-RxAoaBW-8YWEoUN2RebyD2ejo,6981
54
59
  quasarr/search/sources/sf.py,sha256=3z_fvcafOh7U4D_vgq9yC8ktKeazI9fiAi96hCeXb5Q,14869
60
+ quasarr/search/sources/sj.py,sha256=JRzoCDohClmGH7aXOz82KVUt6pZsZoBDBXvwvQrAijM,7074
55
61
  quasarr/search/sources/sl.py,sha256=5e5S7JvdbNOc2EthyOkfC4aTpG8O7fn4WS2O3_EXjnM,9463
56
62
  quasarr/search/sources/wd.py,sha256=O02j3irSlVw2qES82g_qHuavAk-njjSRH1dHSCnOUas,7540
57
63
  quasarr/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
- quasarr/storage/config.py,sha256=84DRau7Mto4BFDBCY0viMxXCXE-kLS2PFUT3PnPey_s,6028
64
+ quasarr/storage/config.py,sha256=a0JAeiSqMQYBvfZTyYtOxDZvuLGP5lZhMHb7nX9azPc,6130
59
65
  quasarr/storage/setup.py,sha256=gpHOsc5qtt-M72saZoMJFLE2YlCrjv7FWZknh-iVKsk,17766
60
66
  quasarr/storage/sqlite_database.py,sha256=yMqFQfKf0k7YS-6Z3_7pj4z1GwWSXJ8uvF4IydXsuTE,3554
61
- quasarr-1.18.0.dist-info/licenses/LICENSE,sha256=QQFCAfDgt7lSA8oSWDHIZ9aTjFbZaBJdjnGOHkuhK7k,1060
62
- quasarr-1.18.0.dist-info/METADATA,sha256=haodoIUXRcHCQ44NVwXC26iHjyqJqKUqkEXBeXH3uws,12249
63
- quasarr-1.18.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
64
- quasarr-1.18.0.dist-info/entry_points.txt,sha256=gXi8mUKsIqKVvn-bOc8E5f04sK_KoMCC-ty6b2Hf-jc,40
65
- quasarr-1.18.0.dist-info/top_level.txt,sha256=dipJdaRda5ruTZkoGfZU60bY4l9dtPlmOWwxK_oGSF0,8
66
- quasarr-1.18.0.dist-info/RECORD,,
67
+ quasarr-1.20.0.dist-info/licenses/LICENSE,sha256=QQFCAfDgt7lSA8oSWDHIZ9aTjFbZaBJdjnGOHkuhK7k,1060
68
+ quasarr-1.20.0.dist-info/METADATA,sha256=AbZO84u4V8ndc4_3p-gVhYaJUTogndLIe7BaboozfRE,12249
69
+ quasarr-1.20.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
70
+ quasarr-1.20.0.dist-info/entry_points.txt,sha256=gXi8mUKsIqKVvn-bOc8E5f04sK_KoMCC-ty6b2Hf-jc,40
71
+ quasarr-1.20.0.dist-info/top_level.txt,sha256=dipJdaRda5ruTZkoGfZU60bY4l9dtPlmOWwxK_oGSF0,8
72
+ quasarr-1.20.0.dist-info/RECORD,,