GoGoDownloader/backend.py

278 lines
9.2 KiB
Python
Raw Normal View History

2022-02-15 10:42:40 +00:00
import re
2022-01-18 20:55:11 +00:00
import requests
import json
import os
from bs4 import BeautifulSoup
from dataclasses import dataclass
from colorama import Fore
from parfive import Downloader
from threading import Semaphore
import logging
logging.basicConfig(
level=logging.INFO,
filename="app.log",
filemode="w",
format="%(name)s - %(levelname)s - %(message)s",
)
2022-01-18 20:55:11 +00:00
OK = f"{Fore.RESET}[{Fore.GREEN}+{Fore.RESET}] "
ERR = f"{Fore.RESET}[{Fore.RED}-{Fore.RESET}] "
IN = f"{Fore.RESET}[{Fore.LIGHTBLUE_EX}>{Fore.RESET}] "
global CONFIG
screenlock = Semaphore(value=1)
def config_check():
2022-01-19 10:29:02 +00:00
"""Check for config.json and check required keys are set
Returns:
[object]: Config object
"""
2022-01-18 20:55:11 +00:00
if os.path.exists("./config.json"):
logging.info("Config.json loaded")
2022-01-18 20:55:11 +00:00
with open("./config.json", "r") as f:
CONFIG = json.load(f)
2022-01-20 14:47:21 +00:00
if not "GoGoAnime_Username" in CONFIG or len(CONFIG["GoGoAnime_Username"]) == 0:
logging.error("GoGoAnime_Username not set in config.json")
2022-01-20 14:47:21 +00:00
print("GoGoAnime_Username not set in config.json")
2022-01-18 20:55:11 +00:00
exit(0)
else:
2022-01-20 14:47:21 +00:00
if (
not "GoGoAnime_Password" in CONFIG
or len(CONFIG["GoGoAnime_Password"]) == 0
):
logging.error("GoGoAnime_Password not set in config.json")
2022-01-20 14:47:21 +00:00
print("GoGoAnime_Password not set in config.json")
exit(0)
else:
logging.info(
"Config loaded and "
+ CONFIG["GoGoAnime_Username"]
+ " username found"
)
2022-01-20 14:47:21 +00:00
return CONFIG
2022-01-18 20:55:11 +00:00
else:
logging.error("config.json not found")
2022-01-18 20:55:11 +00:00
print("config.json file not found")
exit(0)
2022-01-19 10:29:02 +00:00
def max_concurrent_downloads(max_conn: int):
"""Check max_concurrent_downloads value and restrict to below 6
Args:
max_conn (int): Max concurrent downloads to allow
Returns:
[int]: Max concurrent downloads allowed
"""
if max_conn > 6:
return 6
else:
return max_conn
2022-01-18 20:55:11 +00:00
CURRENT_DOMAIN = "film"
@dataclass(init=True)
2022-01-20 14:47:21 +00:00
class gogoanime:
2022-01-19 10:16:34 +00:00
config: object
2022-01-18 20:55:11 +00:00
name: str
episode_quality: str
folder: str
all_episodes: int
episode_start: int
episode_end: int
2022-01-19 10:16:34 +00:00
title: str
2022-01-18 20:55:11 +00:00
printed: bool = False
2022-01-20 14:47:21 +00:00
def get_gogoanime_auth_cookie(self):
session = requests.session()
page = session.get(
f"https://gogoanime.{self.config['CurrentGoGoAnimeDomain']}/login.html"
)
soup = BeautifulSoup(page.content, "html.parser")
meta_path = soup.select('meta[name="csrf-token"]')
csrf_token = meta_path[0].attrs["content"]
url = f"https://gogoanime.{self.config['CurrentGoGoAnimeDomain']}/login.html"
payload = f"email={self.config['GoGoAnime_Username']}&password={self.config['GoGoAnime_Password']}&_csrf={csrf_token}"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36",
"authority": "gogo-cdn.com",
"referer": f"https://gogoanime.{self.config['CurrentGoGoAnimeDomain']}/",
"content-type": "application/x-www-form-urlencoded",
}
session.headers = headers
r = session.post(url, data=payload, headers=headers)
if r.status_code == 200:
return session.cookies.get_dict().get("auth")
else:
print("ldldl")
def user_logged_in_check(
self,
):
page = requests.get(
2022-03-12 14:50:49 -06:00
f"https://gogoanime.{self.config['CurrentGoGoAnimeDomain']}/one-piece-episode-1",
cookies=dict(auth=gogoanime.get_gogoanime_auth_cookie(self)),
)
soup = BeautifulSoup(page.content, "html.parser")
loginCheck = soup(text=re.compile("Logout"))
if len(loginCheck) == 0:
raise Exception(
"User is not logged in, make sure account has been activated"
)
2022-01-18 20:55:11 +00:00
def get_links(self, source=None):
if source is not None:
source_ep = f"https://gogoanime.{self.config['CurrentGoGoAnimeDomain']}/{self.name}-episode-"
episode_links = [
f"{source_ep}{i}"
for i in range(self.episode_start, self.episode_end + 1)
]
episode_links.insert(0, source)
else:
source_ep = f"https://gogoanime.{self.config['CurrentGoGoAnimeDomain']}/{self.name}-episode-"
episode_links = [
f"{source_ep}{i}"
for i in range(self.episode_start, self.episode_end + 1)
]
return episode_links
2022-01-19 10:16:34 +00:00
def get_download_link(self, url):
page = requests.get(
url,
2022-01-20 14:47:21 +00:00
cookies=dict(auth=gogoanime.get_gogoanime_auth_cookie(self)),
2022-01-19 10:16:34 +00:00
)
2022-02-15 10:42:40 +00:00
quality_arr = ["1080", "720", "640", "480"]
2022-01-19 10:16:34 +00:00
soup = BeautifulSoup(page.content, "html.parser")
2022-02-15 10:42:40 +00:00
try:
for link in soup.find_all(
"a", href=True, string=re.compile(self.episode_quality)
):
2022-01-19 10:16:34 +00:00
return link["href"]
2022-02-15 10:42:40 +00:00
else:
ep_num = url.rsplit("-", 1)[1]
print(
f"{self.episode_quality} not found for ep{ep_num} checking for next best"
)
for q in quality_arr:
for link in soup.find_all("a", href=True, string=re.compile(q)):
print(f"{q} found.")
return link["href"]
except:
print("No matching download found")
def file_downloader(self, file_list: dict, overwrite_downloads: bool = None):
"""[summary]
Args:
file_list (dict): [description]
overwrite_downloads (bool, optional): [description]. Defaults to None.
Returns:
[type]: [description]
"""
if overwrite_downloads is None:
overwrite = self.config["OverwriteDownloads"]
else:
overwrite = overwrite_downloads
2022-01-19 10:16:34 +00:00
dl = Downloader(
2022-01-19 10:29:02 +00:00
max_conn=max_concurrent_downloads(self.config["MaxConcurrentDownloads"]),
2022-02-15 10:42:40 +00:00
overwrite=overwrite,
2022-01-19 10:16:34 +00:00
headers=dict(
[
(
"User-Agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36",
),
("authority", "gogo-cdn.com"),
(
"referer",
f"https://gogoanime.{self.config['CurrentGoGoAnimeDomain']}/",
),
]
),
2022-01-18 20:55:11 +00:00
)
2022-01-19 10:16:34 +00:00
for link in file_list:
2022-02-15 10:42:40 +00:00
if link is not None:
dl.enqueue_file(
link,
path=f"./{self.title}",
)
2022-01-19 10:16:34 +00:00
files = dl.download()
return files
2022-01-18 20:55:11 +00:00
2022-06-21 12:08:52 +01:00
def get_show_from_bookmark(self):
bookmarkList = []
a = dict(auth=gogoanime.get_gogoanime_auth_cookie(self))
resp = requests.get(
"https://gogoanime.gg/user/bookmark",
cookies=a,
)
soup = BeautifulSoup(resp.text, "html.parser")
table = soup.find("div", attrs={"class": "article_bookmark"})
splitTableLines = table.text.split("Remove")
for rows in splitTableLines:
fullRow = " ".join(rows.split())
if "Anime name" in fullRow:
fullRow = fullRow.replace("Anime name Latest", "")
splitRow = fullRow.split("Latest")
elif fullRow == "Status":
break
else:
fullRow = fullRow.replace("Status ", "")
splitRow = fullRow.split("Latest")
2022-06-21 12:22:59 +01:00
animeName = splitRow[0].strip().encode("ascii", "ignore").decode()
animeName = re.sub("[^A-Za-z0-9 ]+", "", animeName)
animeDownloadName = animeName.replace(" ", "-").lower()
2022-06-21 12:08:52 +01:00
episodeNum = splitRow[-1].split()[-1]
bookmarkList.append(
{
"showName": animeName,
"latestEpisode": int(episodeNum),
"downloadURL": f"https://gogoanime.{self.config['CurrentGoGoAnimeDomain']}/{animeDownloadName}-episode-{str(episodeNum)}",
}
)
with open("bookmarkList.json", "w") as f:
json.dump(bookmarkList, f)
return bookmarkList
2022-01-18 20:55:11 +00:00
@dataclass(init=True)
class CustomMessage(Exception):
"""Custom message that will accept message as a parameter and it will print it on the console."""
message: str = None
episode_quality: str = None
workingepisode: str = None
def print_error(self):
screenlock.acquire()
print(ERR, self.message, end=" ")
screenlock.release()
def qual_not_found(self):
screenlock.acquire()
print(
f"{ERR}Episode {self.workingepisode} {Fore.LIGHTCYAN_EX}{self.episode_quality}{Fore.RESET} quality not found."
)
screenlock.release()
def use_default_qual(self):
screenlock.acquire()
print(
f"{OK}Trying {Fore.LIGHTCYAN_EX}{self.episode_quality}{Fore.RESET} quality for Episode {self.workingepisode}."
)
screenlock.release()