|
@@ -1,52 +1,77 @@
|
|
from bs4 import BeautifulSoup
|
|
from bs4 import BeautifulSoup
|
|
|
|
+from dotenv import load_dotenv
|
|
import requests
|
|
import requests
|
|
|
|
|
|
-from typing import List
|
|
|
|
|
|
+from typing import List, TypeAlias
|
|
from dataclasses import dataclass
|
|
from dataclasses import dataclass
|
|
import os
|
|
import os
|
|
import re
|
|
import re
|
|
import pickle
|
|
import pickle
|
|
|
|
+import urllib.parse
|
|
|
|
|
|
@dataclass
|
|
@dataclass
|
|
class Torrent:
|
|
class Torrent:
|
|
|
|
+ name: str
|
|
link: str
|
|
link: str
|
|
season_ep: str
|
|
season_ep: str
|
|
season: str
|
|
season: str
|
|
|
|
|
|
|
|
+load_dotenv()
|
|
|
|
+
|
|
|
|
+
|
|
cookies = {
|
|
cookies = {
|
|
- "cf_clereance": "ZN62DXsprSj9LxHcpoQERkOZ3hK4vmGD4lQArmdsing-1679950264-0-150",
|
|
|
|
- "pass": "aefe3fe3c855fdf4dc773f1372ae22a2",
|
|
|
|
- "uid": "1610296"
|
|
|
|
|
|
+ "cf_clereance": os.getenv('CF_CLEREANCE') or "",
|
|
|
|
+ "pass": os.getenv("PASS") or "",
|
|
|
|
+ "uid": os.getenv("UID") or ""
|
|
}
|
|
}
|
|
|
|
|
|
-def search_series(serie_name: str) -> List[Torrent]:
|
|
|
|
|
|
|
|
- base_url = "https://iptorrents.com/"
|
|
|
|
- search_url = f"{base_url}t?q={serie_name}"
|
|
|
|
- response = requests.get(search_url, cookies=cookies)
|
|
|
|
- response.raise_for_status()
|
|
|
|
|
|
|
|
- expr = re.compile(".*((S[0-9]+)E[0-9]+).*(1080p).*")
|
|
|
|
|
|
+def search_series(serie_name: str) -> List[Torrent] | None:
|
|
|
|
+ try:
|
|
|
|
+ torrents = []
|
|
|
|
+ page=1
|
|
|
|
+ valid = True
|
|
|
|
+ while valid:
|
|
|
|
+ valid = False
|
|
|
|
+ base_url = "https://iptorrents.com/"
|
|
|
|
+ search_url = f"{base_url}t?q={urllib.parse.quote(serie_name)};p={page}"
|
|
|
|
+ response = requests.get(search_url, cookies=cookies)
|
|
|
|
+ response.raise_for_status()
|
|
|
|
+ serie_name = serie_name.replace(' ', '.')
|
|
|
|
+ expr = re.compile(f"{serie_name}.*((S[0-9]+)E[0-9]+).*(1080p).*", re.I)
|
|
|
|
|
|
- soup = BeautifulSoup(response.content, 'html.parser')
|
|
|
|
- results = soup.find_all('a', {'class': 'tTipWrap'})
|
|
|
|
- torrents = []
|
|
|
|
-
|
|
|
|
- for result in results:
|
|
|
|
- link = result['href']
|
|
|
|
- m = expr.search(link)
|
|
|
|
- if link.endswith('.torrent') and m is not None:
|
|
|
|
- torrents.append(Torrent(link, m.group(1), season=m.group(2)))
|
|
|
|
- return torrents
|
|
|
|
|
|
+ soup = BeautifulSoup(response.content, 'html.parser')
|
|
|
|
+ results = soup.find_all('a', {'class': 'tTipWrap'})
|
|
|
|
+ for result in results:
|
|
|
|
+ link = result['href']
|
|
|
|
+ m = expr.search(link)
|
|
|
|
+ if link.endswith('.torrent') and m is not None:
|
|
|
|
+ torrents.append(Torrent(serie_name, link, m.group(1), season=m.group(2)))
|
|
|
|
+ valid = True
|
|
|
|
+ if valid:
|
|
|
|
+ page += 1
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ return torrents
|
|
|
|
+ except Exception as e:
|
|
|
|
+ print(f"ERROR: {e}")
|
|
|
|
+ return None
|
|
|
|
|
|
|
|
+OK: TypeAlias = int
|
|
|
|
+
|
|
|
|
+def download_torrent(url: str, file_name: str) -> OK | None:
|
|
|
|
+ try:
|
|
|
|
+ read = requests.get(url, cookies=cookies)
|
|
|
|
+ with open(file_name, 'wb') as f:
|
|
|
|
+ for chunk in read.iter_content(chunk_size=512):
|
|
|
|
+ if chunk:
|
|
|
|
+ f.write(chunk)
|
|
|
|
+ return 1
|
|
|
|
+ except Exception as e:
|
|
|
|
+ print("ERROR: {e}")
|
|
|
|
+ return None
|
|
|
|
|
|
-def download_torrent(url: str, file_name: str) -> None:
|
|
|
|
- read = requests.get(url, cookies=cookies)
|
|
|
|
- with open(file_name, 'wb') as f:
|
|
|
|
- for chunk in read.iter_content(chunk_size=512):
|
|
|
|
- if chunk:
|
|
|
|
- f.write(chunk)
|
|
|
|
- #print(f"Downloaded {file_name} success")
|
|
|
|
|
|
|
|
def main() -> None:
|
|
def main() -> None:
|
|
if os.path.exists("downloaded.bin"):
|
|
if os.path.exists("downloaded.bin"):
|
|
@@ -56,11 +81,14 @@ def main() -> None:
|
|
downloaded = list()
|
|
downloaded = list()
|
|
serie_name = input("Name serie: ")
|
|
serie_name = input("Name serie: ")
|
|
torrents = search_series(serie_name)
|
|
torrents = search_series(serie_name)
|
|
|
|
+ if torrents is None:
|
|
|
|
+ exit(downloaded)
|
|
|
|
+ return
|
|
season = ""
|
|
season = ""
|
|
if len(torrents) <= 0:
|
|
if len(torrents) <= 0:
|
|
print("torrent not found")
|
|
print("torrent not found")
|
|
|
|
+ exit(downloaded)
|
|
return
|
|
return
|
|
- #choice = int(input("Qual serie? "))
|
|
|
|
seasons = set()
|
|
seasons = set()
|
|
for to in torrents:
|
|
for to in torrents:
|
|
seasons.add(to.season)
|
|
seasons.add(to.season)
|
|
@@ -69,22 +97,26 @@ def main() -> None:
|
|
choice = int(input("What season? "))
|
|
choice = int(input("What season? "))
|
|
if 0 <= (choice -1 ) <= len(seasons):
|
|
if 0 <= (choice -1 ) <= len(seasons):
|
|
season = list(seasons)[choice -1]
|
|
season = list(seasons)[choice -1]
|
|
|
|
+ print(f"Selected season: {season}")
|
|
for torrent in torrents:
|
|
for torrent in torrents:
|
|
- if torrent.link.find(season):
|
|
|
|
|
|
+ if torrent.link.find(season) >=0:
|
|
name = os.path.basename(torrent.link)
|
|
name = os.path.basename(torrent.link)
|
|
|
|
|
|
- got = list(filter(lambda x: (x.season_ep in torrent.season_ep), downloaded))
|
|
|
|
|
|
+ got = list(filter(lambda x: (x.name in torrent.name and x.season_ep in torrent.season_ep), downloaded))
|
|
if len(got) == 0:
|
|
if len(got) == 0:
|
|
downloaded.append(torrent)
|
|
downloaded.append(torrent)
|
|
print(f"Downloading {torrent.season} - {torrent.season_ep}")
|
|
print(f"Downloading {torrent.season} - {torrent.season_ep}")
|
|
- download_torrent(f"https://iptorrents.com/t/{torrent.link}", name)
|
|
|
|
|
|
+ if download_torrent(f"https://iptorrents.com/t/{torrent.link}", name) is None:
|
|
|
|
+ print(f"Failed to download {torrent.link}")
|
|
|
|
+
|
|
else:
|
|
else:
|
|
print("Escolha invalida")
|
|
print("Escolha invalida")
|
|
|
|
+ exit(downloaded)
|
|
|
|
+
|
|
|
|
|
|
|
|
+def exit(downloaded: List[Torrent]):
|
|
with open("downloaded.bin", 'wb') as f:
|
|
with open("downloaded.bin", 'wb') as f:
|
|
pickle.dump(downloaded, f, protocol=pickle.HIGHEST_PROTOCOL)
|
|
pickle.dump(downloaded, f, protocol=pickle.HIGHEST_PROTOCOL)
|
|
|
|
|
|
-
|
|
|
|
-
|
|
|
|
if __name__ == '__main__':
|
|
if __name__ == '__main__':
|
|
main()
|
|
main()
|