quasarr 1.17.2__py3-none-any.whl → 1.18.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.

@@ -13,6 +13,7 @@ from quasarr.search.sources.dt import dt_feed, dt_search
13
13
  from quasarr.search.sources.dw import dw_feed, dw_search
14
14
  from quasarr.search.sources.fx import fx_feed, fx_search
15
15
  from quasarr.search.sources.mb import mb_feed, mb_search
16
+ from quasarr.search.sources.nk import nk_feed, nk_search
16
17
  from quasarr.search.sources.nx import nx_feed, nx_search
17
18
  from quasarr.search.sources.sf import sf_feed, sf_search
18
19
  from quasarr.search.sources.sl import sl_feed, sl_search
@@ -34,6 +35,7 @@ def get_search_results(shared_state, request_from, imdb_id="", search_phrase="",
34
35
  dw = shared_state.values["config"]("Hostnames").get("dw")
35
36
  fx = shared_state.values["config"]("Hostnames").get("fx")
36
37
  mb = shared_state.values["config"]("Hostnames").get("mb")
38
+ nk = shared_state.values["config"]("Hostnames").get("nk")
37
39
  nx = shared_state.values["config"]("Hostnames").get("nx")
38
40
  sf = shared_state.values["config"]("Hostnames").get("sf")
39
41
  sl = shared_state.values["config"]("Hostnames").get("sl")
@@ -52,6 +54,7 @@ def get_search_results(shared_state, request_from, imdb_id="", search_phrase="",
52
54
  (dw, dw_search),
53
55
  (fx, fx_search),
54
56
  (mb, mb_search),
57
+ (nk, nk_search),
55
58
  (nx, nx_search),
56
59
  (sf, sf_search),
57
60
  (sl, sl_search),
@@ -76,6 +79,7 @@ def get_search_results(shared_state, request_from, imdb_id="", search_phrase="",
76
79
  (dw, dw_feed),
77
80
  (fx, fx_feed),
78
81
  (mb, mb_feed),
82
+ (nk, nk_feed),
79
83
  (nx, nx_feed),
80
84
  (sf, sf_feed),
81
85
  (sl, sl_feed),
@@ -0,0 +1,189 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Quasarr
3
+ # Project by https://github.com/rix1337
4
+
5
+ import re
6
+ import time
7
+ from base64 import urlsafe_b64encode
8
+ from datetime import datetime
9
+ from html import unescape
10
+ from urllib.parse import urljoin
11
+
12
+ from bs4 import BeautifulSoup
13
+ import requests
14
+
15
+ from quasarr.providers.imdb_metadata import get_localized_title
16
+ from quasarr.providers.log import info, debug
17
+
18
+ hostname = "nk"
19
+ supported_mirrors = ["rapidgator", "ddownload"]
20
+
21
+
22
+ def convert_to_rss_date(date_str: str) -> str:
23
+ date_str = date_str.strip()
24
+ for fmt in ("%d. %B %Y / %H:%M", "%d.%m.%Y / %H:%M", "%d.%m.%Y - %H:%M", "%Y-%m-%d %H:%M"):
25
+ try:
26
+ dt = datetime.strptime(date_str, fmt)
27
+ return dt.strftime("%a, %d %b %Y %H:%M:%S +0000")
28
+ except Exception:
29
+ continue
30
+ return ""
31
+
32
+
33
+ def extract_size(text: str) -> dict:
34
+ match = re.search(r"(\d+(?:[\.,]\d+)?)\s*([A-Za-z]+)", text)
35
+ if match:
36
+ size = match.group(1).replace(',', '.')
37
+ unit = match.group(2)
38
+ return {"size": size, "sizeunit": unit}
39
+ return {"size": "0", "sizeunit": "MB"}
40
+
41
+
42
+ def get_release_field(res, label):
43
+ for li in res.select('ul.release-infos li'):
44
+ sp = li.find('span')
45
+ if not sp:
46
+ return ''
47
+ if sp.get_text(strip=True).lower() == label.lower():
48
+ txt = li.get_text(' ', strip=True)
49
+ return txt[len(sp.get_text(strip=True)):].strip()
50
+ return ''
51
+
52
+
53
+ def nk_feed(*args, **kwargs):
54
+ return nk_search(*args, **kwargs)
55
+
56
+
57
+ def nk_search(shared_state, start_time, request_from, search_string="", mirror=None, season=None, episode=None):
58
+ releases = []
59
+ host = shared_state.values["config"]("Hostnames").get(hostname)
60
+
61
+ if not "arr" in request_from.lower():
62
+ debug(f'Skipping {request_from} search on "{hostname.upper()}" (unsupported media type)!')
63
+ return releases
64
+
65
+ if mirror and mirror not in supported_mirrors:
66
+ debug(f'Mirror "{mirror}" not supported by {hostname}.')
67
+ return releases
68
+
69
+
70
+ source_search = ""
71
+ if search_string != "":
72
+ imdb_id = shared_state.is_imdb_id(search_string)
73
+ if imdb_id:
74
+ local_title = get_localized_title(shared_state, imdb_id, 'de')
75
+ if not local_title:
76
+ info(f"{hostname}: no title for IMDb {imdb_id}")
77
+ return releases
78
+ source_search = local_title
79
+ else:
80
+ return releases
81
+ source_search = unescape(source_search)
82
+ else:
83
+ imdb_id = None
84
+
85
+ url = f'https://{host}/search'
86
+ headers = {"User-Agent": shared_state.values["user_agent"]}
87
+ data = {"search": source_search}
88
+
89
+ try:
90
+ r = requests.post(url, headers=headers, data=data, timeout=20)
91
+ soup = BeautifulSoup(r.content, 'html.parser')
92
+ results = soup.find_all('div', class_='article-right')
93
+ except Exception as e:
94
+ info(f"{hostname}: search load error: {e}")
95
+ return releases
96
+
97
+
98
+ if not results:
99
+ return releases
100
+
101
+ for result in results:
102
+ try:
103
+ imdb_a = result.select_one('a.imdb')
104
+ if imdb_a and imdb_a.get('href'):
105
+ try:
106
+ release_imdb_id = re.search(r'tt\d+', imdb_a['href']).group()
107
+ if imdb_id:
108
+ if release_imdb_id != imdb_id:
109
+ debug(f"{hostname}: IMDb ID mismatch: expected {imdb_id}, found {release_imdb_id}")
110
+ continue
111
+ except Exception:
112
+ debug(f"{hostname}: could not extract IMDb ID")
113
+ continue
114
+ else:
115
+ debug(f"{hostname}: could not extract IMDb ID")
116
+ continue
117
+
118
+ a = result.find('a', class_='release-details', href=True)
119
+ if not a:
120
+ continue
121
+
122
+ sub_title = result.find('span', class_='subtitle')
123
+ if sub_title:
124
+ title = sub_title.get_text(strip=True)
125
+ else:
126
+ continue
127
+
128
+ if not shared_state.is_valid_release(title, request_from, search_string, season, episode):
129
+ continue
130
+
131
+ source = urljoin(f'https://{host}', a['href'])
132
+
133
+ mb = 0
134
+ size_text = get_release_field(result, 'Größe')
135
+ if size_text:
136
+ size_item = extract_size(size_text)
137
+ mb = shared_state.convert_to_mb(size_item)
138
+
139
+ if season != "" and episode == "":
140
+ mb = 0 # Size unknown for season packs
141
+
142
+ size = mb * 1024 * 1024
143
+
144
+ password = ''
145
+ mirrors_p = result.find('p', class_='mirrors')
146
+ if mirrors_p:
147
+ strong = mirrors_p.find('strong')
148
+ if strong and strong.get_text(strip=True).lower().startswith('passwort'):
149
+ nxt = strong.next_sibling
150
+ if nxt:
151
+ val = str(nxt).strip()
152
+ if val:
153
+ password = val.split()[0]
154
+
155
+ date_text = ''
156
+ p_meta = result.find('p', class_='meta')
157
+ if p_meta:
158
+ spans = p_meta.find_all('span')
159
+ if len(spans) >= 2:
160
+ date_part = spans[0].get_text(strip=True)
161
+ time_part = spans[1].get_text(strip=True).replace('Uhr', '').strip()
162
+ date_text = f"{date_part} / {time_part}"
163
+
164
+ published = convert_to_rss_date(date_text) if date_text else ""
165
+
166
+ payload = urlsafe_b64encode(f"{title}|{source}|{mirror}|{mb}|{password}|{release_imdb_id}".encode("utf-8")).decode()
167
+ link = f"{shared_state.values['internal_address']}/download/?payload={payload}"
168
+
169
+ releases.append({
170
+ "details": {
171
+ "title": title,
172
+ "hostname": hostname,
173
+ "imdb_id": release_imdb_id,
174
+ "link": link,
175
+ "mirror": mirror,
176
+ "size": size,
177
+ "date": published,
178
+ "source": source
179
+ },
180
+ "type": "protected"
181
+ })
182
+ except Exception as e:
183
+ info(e)
184
+ debug(f"{hostname}: error parsing search result: {e}")
185
+ continue
186
+
187
+ elapsed = time.time() - start_time
188
+ debug(f"Time taken: {elapsed:.2f}s ({hostname})")
189
+ return releases
quasarr/storage/config.py CHANGED
@@ -33,6 +33,7 @@ class Config(object):
33
33
  ("dw", "secret", ""),
34
34
  ("fx", "secret", ""),
35
35
  ("mb", "secret", ""),
36
+ ("nk", "secret", ""),
36
37
  ("nx", "secret", ""),
37
38
  ("sf", "secret", ""),
38
39
  ("sl", "secret", ""),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quasarr
3
- Version: 1.17.2
3
+ Version: 1.18.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=1-P9MXoYDu1EQuEt6rpsIM4sRPbSXIrT30f_ChAKaHk,33818
4
+ quasarr/api/captcha/__init__.py,sha256=E1ZiQ93315c_KioDW2QvvcZuQ98M0O_b9LzqqQmUF-o,42977
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=rRAkr0Kpk30HOvZ2AFt1ujiVPV_-qf7MSN4ytsHb9jE,10488
8
+ quasarr/downloads/__init__.py,sha256=o_tA8scQmJUsj6JaIbo1S4cMAbeVk0uPj6jMIEOr5Cs,10679
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
@@ -18,28 +18,29 @@ quasarr/downloads/sources/dd.py,sha256=EQ823wrVusVCVJhh9Rdf67-Yae9XYio8Uj_HW_y5q
18
18
  quasarr/downloads/sources/dt.py,sha256=fzAyJy8nmqTAFRObvaRbvsXdBkCo5JuojCJYQMYuPOs,2108
19
19
  quasarr/downloads/sources/dw.py,sha256=15UH-kBZt06GS5CDi-TTJGV_H59mQO0Nl-y3nYA5kOk,2504
20
20
  quasarr/downloads/sources/mb.py,sha256=IS5_RdACD3yterFEAj_N7RIH4TVK-VEauZqfya23hmA,1411
21
+ quasarr/downloads/sources/nk.py,sha256=b2NOHdrcxIx2xbMB07LKqAwCrlFm3GfHe2cQ8LVwIxw,1567
21
22
  quasarr/downloads/sources/nx.py,sha256=nI0c-oM1g_EyW06_o2wFgn_jm_Zh1XMy3kbRCN0hw1E,3211
22
23
  quasarr/downloads/sources/sf.py,sha256=PDBuWgJmEYmD1b-5blS3YWgrqIhJjfwz91IuiMy6rX8,6224
23
24
  quasarr/downloads/sources/sl.py,sha256=w6Mo1dphrZRlXfhBfAhFV8KcPfHINuTiFSNu3BYd46k,2851
24
25
  quasarr/downloads/sources/wd.py,sha256=NOilEZIF9rumU2LMtfRfXyet3Mzn2shCs8NFCEC3CHY,3747
25
26
  quasarr/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
27
  quasarr/providers/cloudflare.py,sha256=mJxTYM7JjwIjdO6U_GyVj-dyug6XdD0-ObkYTaPtFVg,7028
27
- quasarr/providers/html_images.py,sha256=6HBIo9KKLCgPNyBF2gjZRKEjvQEPdVNIFWWEm3j3P2Q,41749
28
+ quasarr/providers/html_images.py,sha256=ro7T7vdGHoFXknOuC_W-Bs1W-fwvmhjZKhOWY-B95GI,43539
28
29
  quasarr/providers/html_templates.py,sha256=hAwHCq-FkM27W4ZOj_Yu3ic-OKRC7GIYgQkUeMCBNJo,7853
29
30
  quasarr/providers/imdb_metadata.py,sha256=10L4kZkt6Fg0HGdNcc6KCtIQHRYEqdarLyaMVN6mT8w,4843
30
31
  quasarr/providers/log.py,sha256=_g5RwtfuksARXnvryhsngzoJyFcNzj6suqd3ndqZM0Y,313
31
32
  quasarr/providers/myjd_api.py,sha256=1R4uL8Zb8wp1VGcvaO0yMXt2NVGmu6Kn9-GIF4x7vU0,32054
32
33
  quasarr/providers/notifications.py,sha256=bohT-6yudmFnmZMc3BwCGX0n1HdzSVgQG_LDZm_38dI,4630
33
- quasarr/providers/obfuscated.py,sha256=XfiEblJizqixUoA4MIsillr5Nh1dwFqCgLvBQWM7Lwo,193865
34
+ quasarr/providers/obfuscated.py,sha256=Gy8FjKiHNmmjDJalOTDM8zHlLqB19ArsHlN07qTy9Z8,211613
34
35
  quasarr/providers/shared_state.py,sha256=4nswf5AuA4c1DWqSXsX0HXwlDt5e-UUUvQSy-vryCRE,28987
35
36
  quasarr/providers/statistics.py,sha256=cEQixYnDMDqtm5wWe40E_2ucyo4mD0n3SrfelhQi1L8,6452
36
- quasarr/providers/version.py,sha256=Gk8Sp06635dN-u-8VTsGTVfWc9xrPgLsMxUxCHP5rvI,4004
37
+ quasarr/providers/version.py,sha256=BUukq06r4JaxR9TUuIzO8VSJ3eTxq1oig2UTcRkr7YU,4004
37
38
  quasarr/providers/web_server.py,sha256=XPj98T-axxgotovuB-rVw1IPCkJiNdXBlEeFvM_zSlM,1432
38
39
  quasarr/providers/sessions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
40
  quasarr/providers/sessions/al.py,sha256=mlP6SWfCY2HyOSV40uyotQ5T4eSBNYG9A5GWOEAdz-c,9589
40
41
  quasarr/providers/sessions/dd.py,sha256=JdXjqmjuyY32w0cIlwphRm8Sy43EK8nEEFwyXUkEGb4,2596
41
42
  quasarr/providers/sessions/nx.py,sha256=qfW12AB_0nNsAoKOaSF4z0T9DCxMQleWCYf3fqJtF2A,2688
42
- quasarr/search/__init__.py,sha256=DvqRopdDNT0lPXHIfLmoEgtJwA7iILCCMLfSnmDNGkQ,4699
43
+ quasarr/search/__init__.py,sha256=OQnzxvJsv38bdmC1EvFqI1oYUr5VZRtQTLi4SLXDHL0,4866
43
44
  quasarr/search/sources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
45
  quasarr/search/sources/al.py,sha256=yr6wx-VcSOFYK_o3N1bepC4t6Gvt9eDvcG9fQBFg0bg,17203
45
46
  quasarr/search/sources/by.py,sha256=OPoAqS5kSSNrRVsPlALhX59h3lEZWGA7LlFfL4vH2-o,7914
@@ -48,17 +49,18 @@ quasarr/search/sources/dt.py,sha256=m1kQ7mC43QlWZyVIkw-OXJGjWiT9IbQuFtHWiR8CjhA,
48
49
  quasarr/search/sources/dw.py,sha256=-daUTBTA5izeatrE7TITVlnzNCQ5HfovYMMZ8UTM-2o,7636
49
50
  quasarr/search/sources/fx.py,sha256=JAyD727yDAFIP14bzfi2SkX9paysXGkQdIybShYtdko,8596
50
51
  quasarr/search/sources/mb.py,sha256=owwH5T0Yh7dwYRqMVQ0ecAdDlQ5CwLwWkTcig2ePggI,7749
52
+ quasarr/search/sources/nk.py,sha256=4_KqpWKTR-hCH69eL-3oqGtkDCWY2QsNyAjGwzin9RA,6439
51
53
  quasarr/search/sources/nx.py,sha256=JdRLA2pWS05m5_ARU-RxAoaBW-8YWEoUN2RebyD2ejo,6981
52
54
  quasarr/search/sources/sf.py,sha256=3z_fvcafOh7U4D_vgq9yC8ktKeazI9fiAi96hCeXb5Q,14869
53
55
  quasarr/search/sources/sl.py,sha256=5e5S7JvdbNOc2EthyOkfC4aTpG8O7fn4WS2O3_EXjnM,9463
54
56
  quasarr/search/sources/wd.py,sha256=O02j3irSlVw2qES82g_qHuavAk-njjSRH1dHSCnOUas,7540
55
57
  quasarr/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
- quasarr/storage/config.py,sha256=ISZXh9gHiBu5mYhHGYx8nZ8JyMYuSFqfVl52DiUDJec,5994
58
+ quasarr/storage/config.py,sha256=84DRau7Mto4BFDBCY0viMxXCXE-kLS2PFUT3PnPey_s,6028
57
59
  quasarr/storage/setup.py,sha256=gpHOsc5qtt-M72saZoMJFLE2YlCrjv7FWZknh-iVKsk,17766
58
60
  quasarr/storage/sqlite_database.py,sha256=yMqFQfKf0k7YS-6Z3_7pj4z1GwWSXJ8uvF4IydXsuTE,3554
59
- quasarr-1.17.2.dist-info/licenses/LICENSE,sha256=QQFCAfDgt7lSA8oSWDHIZ9aTjFbZaBJdjnGOHkuhK7k,1060
60
- quasarr-1.17.2.dist-info/METADATA,sha256=on2aTl3bjogO2QeTapHj9_NVwmQlagIRZ7vmqSGcR-g,12249
61
- quasarr-1.17.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
62
- quasarr-1.17.2.dist-info/entry_points.txt,sha256=gXi8mUKsIqKVvn-bOc8E5f04sK_KoMCC-ty6b2Hf-jc,40
63
- quasarr-1.17.2.dist-info/top_level.txt,sha256=dipJdaRda5ruTZkoGfZU60bY4l9dtPlmOWwxK_oGSF0,8
64
- quasarr-1.17.2.dist-info/RECORD,,
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,,