mirror of
				https://github.com/karl0ss/GoGoDownloader.git
				synced 2025-10-31 14:44:18 +00:00 
			
		
		
		
	clean repo
This commit is contained in:
		
							parent
							
								
									1fa2e28b70
								
							
						
					
					
						commit
						3262b2c69e
					
				
							
								
								
									
										138
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										138
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,138 +0,0 @@ | ||||
| # Byte-compiled / optimized / DLL files | ||||
| __pycache__/ | ||||
| *.py[cod] | ||||
| *$py.class | ||||
| 
 | ||||
| # C extensions | ||||
| *.so | ||||
| 
 | ||||
| # Distribution / packaging | ||||
| .Python | ||||
| build/ | ||||
| develop-eggs/ | ||||
| dist/ | ||||
| downloads/ | ||||
| eggs/ | ||||
| .eggs/ | ||||
| lib/ | ||||
| lib64/ | ||||
| parts/ | ||||
| sdist/ | ||||
| var/ | ||||
| wheels/ | ||||
| share/python-wheels/ | ||||
| *.egg-info/ | ||||
| .installed.cfg | ||||
| *.egg | ||||
| MANIFEST | ||||
| 
 | ||||
| # PyInstaller | ||||
| #  Usually these files are written by a python script from a template | ||||
| #  before PyInstaller builds the exe, so as to inject date/other infos into it. | ||||
| *.manifest | ||||
| *.spec | ||||
| 
 | ||||
| # Installer logs | ||||
| pip-log.txt | ||||
| pip-delete-this-directory.txt | ||||
| 
 | ||||
| # Unit test / coverage reports | ||||
| htmlcov/ | ||||
| .tox/ | ||||
| .nox/ | ||||
| .coverage | ||||
| .coverage.* | ||||
| .cache | ||||
| nosetests.xml | ||||
| coverage.xml | ||||
| *.cover | ||||
| *.py,cover | ||||
| .hypothesis/ | ||||
| .pytest_cache/ | ||||
| cover/ | ||||
| 
 | ||||
| # Translations | ||||
| *.mo | ||||
| *.pot | ||||
| 
 | ||||
| # Django stuff: | ||||
| *.log | ||||
| local_settings.py | ||||
| db.sqlite3 | ||||
| db.sqlite3-journal | ||||
| 
 | ||||
| # Flask stuff: | ||||
| instance/ | ||||
| .webassets-cache | ||||
| 
 | ||||
| # Scrapy stuff: | ||||
| .scrapy | ||||
| 
 | ||||
| # Sphinx documentation | ||||
| docs/_build/ | ||||
| 
 | ||||
| # PyBuilder | ||||
| .pybuilder/ | ||||
| target/ | ||||
| 
 | ||||
| # Jupyter Notebook | ||||
| .ipynb_checkpoints | ||||
| 
 | ||||
| # IPython | ||||
| profile_default/ | ||||
| ipython_config.py | ||||
| 
 | ||||
| # pyenv | ||||
| #   For a library or package, you might want to ignore these files since the code is | ||||
| #   intended to run in multiple environments; otherwise, check them in: | ||||
| # .python-version | ||||
| 
 | ||||
| # pipenv | ||||
| #   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. | ||||
| #   However, in case of collaboration, if having platform-specific dependencies or dependencies | ||||
| #   having no cross-platform support, pipenv may install dependencies that don't work, or not | ||||
| #   install all needed dependencies. | ||||
| #Pipfile.lock | ||||
| 
 | ||||
| # PEP 582; used by e.g. github.com/David-OConnor/pyflow | ||||
| __pypackages__/ | ||||
| 
 | ||||
| # Celery stuff | ||||
| celerybeat-schedule | ||||
| celerybeat.pid | ||||
| 
 | ||||
| # SageMath parsed files | ||||
| *.sage.py | ||||
| 
 | ||||
| # Environments | ||||
| .env | ||||
| .venv | ||||
| env/ | ||||
| venv/ | ||||
| ENV/ | ||||
| env.bak/ | ||||
| venv.bak/ | ||||
| 
 | ||||
| # Spyder project settings | ||||
| .spyderproject | ||||
| .spyproject | ||||
| 
 | ||||
| # Rope project settings | ||||
| .ropeproject | ||||
| 
 | ||||
| # mkdocs documentation | ||||
| /site | ||||
| 
 | ||||
| # mypy | ||||
| .mypy_cache/ | ||||
| .dmypy.json | ||||
| dmypy.json | ||||
| 
 | ||||
| # Pyre type checker | ||||
| .pyre/ | ||||
| 
 | ||||
| # pytype static type analyzer | ||||
| .pytype/ | ||||
| 
 | ||||
| # Cython debug symbols | ||||
| cython_debug/ | ||||
							
								
								
									
										55
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										55
									
								
								README.md
									
									
									
									
									
								
							| @ -1,55 +0,0 @@ | ||||
| <div align="center"> | ||||
|   <img | ||||
|     style="width: 165px; height: 165px" | ||||
|     src="https://i.postimg.cc/VkSMVQrg/ba-logo.png" | ||||
|     title="BitAnime" | ||||
|     alt="BitAnime" | ||||
|   /> | ||||
|   <h3>BitAnime</h3> | ||||
|   <p> | ||||
|     A Python script that allows you to download all of an anime's episodes at once. | ||||
|   </p> | ||||
|   <a href="https://github.com/Arctic4161/BitAnime/releases"> <strong>· Download executable version ·</strong></a> | ||||
| </div> | ||||
| 
 | ||||
| ## About BitAnime | ||||
| 
 | ||||
| **BitAnime** is a python script that allows you to download anime in large batches. It can also be used to download anime films. **BitAnime** gets its content from [gogoanime](https://gogoanime.pe/). If you get a **404** error, please look up the correct anime name on [gogoanime](https://gogoanime.pe/). The application will let you download all the episodes, or you can choose how many episodes you want to download. | ||||
| 
 | ||||
| ## Installation | ||||
| 
 | ||||
| ```console | ||||
| git clone https://github.com/Arctic4161/BitAnime.git | ||||
| ``` | ||||
| 
 | ||||
| ## Screenshot | ||||
| 
 | ||||
| <div align="center"> | ||||
|   <img style="height:386px; width:688px;" src="https://i.postimg.cc/cLgf8994/ba-screenshot.png" | ||||
|   title="BitAnime in action" alt="BitAnime Screenshot"> | ||||
|   <img style="height:386px; width:688px;" src="https://i.postimg.cc/G2qGDpfV/downloade.png" title="Katekyo Hitman Reborn" alt="Downloaded anime with BitAnime"> | ||||
| </div> | ||||
| 
 | ||||
| ## Dependencies | ||||
| 
 | ||||
| **BitAnime** is highly reliant on the python modules `requests`, `colorama`, `tqdm`, and `BeautifulSoup`. | ||||
| 
 | ||||
| ```console | ||||
| pip install -r requirements.txt | ||||
| ``` | ||||
| 
 | ||||
| ## Usage | ||||
| 
 | ||||
| The anime name is separated by "-". You can either type it manually, or go to [gogoanime.pe](https://gogoanime.pe/) and search for the anime you want to download and copy the name from the URL. | ||||
| 
 | ||||
| ### Examples | ||||
| 
 | ||||
| ##### One word title | ||||
| 
 | ||||
| - https://gogoanime.pe/category/bakemonogatari >> bakemonogatari | ||||
| - https://gogoanime.pe/category/steinsgate >> steinsgate | ||||
| 
 | ||||
| ##### Multiple word title | ||||
| 
 | ||||
| - https://gogoanime.pe/category/shadows-house >> shadows-house | ||||
| - https://gogoanime.pe/category/kono-subarashii-sekai-ni-shukufuku-wo- >> kono-subarashii-sekai-ni-shukufuku-wo- | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 26 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 27 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 652 KiB | 
							
								
								
									
										
											BIN
										
									
								
								requirements.txt
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								requirements.txt
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										223
									
								
								src/backend.py
									
									
									
									
									
								
							
							
						
						
									
										223
									
								
								src/backend.py
									
									
									
									
									
								
							| @ -1,223 +0,0 @@ | ||||
| # Dependencies | ||||
| import requests as req | ||||
| import shutil | ||||
| import re | ||||
| import os | ||||
| from bs4 import BeautifulSoup | ||||
| from dataclasses import dataclass | ||||
| from colorama import Fore | ||||
| from random import choice | ||||
| from requests.exceptions import Timeout | ||||
| import time | ||||
| from threading import Semaphore | ||||
| 
 | ||||
| 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}] " | ||||
| 
 | ||||
| screenlock = Semaphore(value=1) | ||||
| 
 | ||||
| 
 | ||||
| def random_headers(): | ||||
|     desktop_agents = [ | ||||
|         "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36 Edg/94.0.992.47", | ||||
|         'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36', | ||||
|         'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36', | ||||
|         'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36', | ||||
|         'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36', | ||||
|         'Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36', | ||||
|         'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36', | ||||
|         'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'] | ||||
|     return { "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", | ||||
|             "Accept-Language": "en-US,en;q=0.5", | ||||
|             "Accept-Encoding": "gzip, deflate, br", | ||||
|             "Connection": "keep-alive", | ||||
|             "Referer": "https://gogoplay1.com/", | ||||
|             'User-Agent': choice(desktop_agents)} | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| def get_download_links(episode_link): | ||||
|     with req.get(episode_link) as res: | ||||
|         soup = BeautifulSoup(res.content, "html.parser") | ||||
|         exist = soup.find("h1", {"class": "entry-title"}) | ||||
|         workinglinkis = episode_link.split('-') | ||||
|         if exist is None: | ||||
|             # Episode link == 200 | ||||
|             episode_link = soup.find("li", {"class": "dowloads"}) | ||||
|             return [workinglinkis[-1], episode_link.a.get("href")] | ||||
|         else: | ||||
|             # Episode link == 404 | ||||
|             episode_link = f"{episode_link}-" | ||||
|             with req.get(episode_link) as find: | ||||
|                 soup = BeautifulSoup(find.content, "html.parser") | ||||
|                 exist = soup.find("h1", {"class": "entry-title"}) | ||||
|                 if exist is None: | ||||
|                     episode_link = soup.find("li", {"class": "dowloads"}) | ||||
|                     return [workinglinkis[-1], episode_link.a.get("href")] | ||||
|                 else: | ||||
|                     return None | ||||
| 
 | ||||
| 
 | ||||
| @dataclass(init=True) | ||||
| class Download: | ||||
|     name: str | ||||
|     episode_quality: str | ||||
|     folder: str | ||||
|     all_episodes: int | ||||
|     episode_start: int | ||||
|     episode_end: int | ||||
|     printed: bool = False | ||||
| 
 | ||||
|     def get_links(self, source=None): | ||||
|         if source is not None: | ||||
|             source_ep = f"https://gogoanime.wiki/{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.wiki/{self.name}-episode-" | ||||
|             episode_links = [ | ||||
|                 f"{source_ep}{i}" | ||||
|                 for i in range(self.episode_start, self.episode_end + 1) | ||||
|             ] | ||||
|         return episode_links | ||||
| 
 | ||||
|     def get_download_urls(self, download_link): | ||||
|         episode_quality = self.episode_quality | ||||
|         workingepisode = download_link[0] | ||||
|         if episode_quality == "FullHDP": | ||||
|             episode_quality = "1080P - mp4" | ||||
|         elif episode_quality == "HDP": | ||||
|             episode_quality = "720P - mp4" | ||||
|         elif episode_quality == "SHD": | ||||
|             episode_quality = "480P - mp4" | ||||
|         elif episode_quality == "SDP": | ||||
|             episode_quality = "360P - mp4" | ||||
|         else: | ||||
|             episode_quality = "1080P - mp4" | ||||
|         with req.get(download_link[1], headers=random_headers(), timeout=3) as res: | ||||
|             soup = BeautifulSoup(res.content, "html.parser") | ||||
|             link = soup.find("div", {"class": "dowload"}, text=re.compile(episode_quality)) | ||||
|             if link is None: | ||||
|                 pass | ||||
|             else: | ||||
|                 try: | ||||
|                     with req.get(link.a.get("href"), headers=random_headers(), stream=True, | ||||
|                                  timeout=3) as workingit: | ||||
|                         if workingit.status_code != 200: | ||||
|                             link = None | ||||
|                         elif workingit.headers['Content-Type'] != 'video/mp4': | ||||
|                             link = None | ||||
|                 except Timeout: | ||||
|                     link = None | ||||
|             if link is None: | ||||
|                 if episode_quality == "1080P - mp4": | ||||
|                     episode_quality = "FullHDP" | ||||
|                     time.sleep(1) | ||||
|                     CustomMessage('None', episode_quality, workingepisode).qual_not_found() | ||||
|                     episode_quality = "HDP" | ||||
|                     time.sleep(1) | ||||
|                     CustomMessage('None', episode_quality, workingepisode).use_default_qual() | ||||
|                     episode_quality = "720P - mp4" | ||||
|                 link = soup.find("div", {"class": "dowload"}, text=re.compile(episode_quality)) | ||||
|                 if link is None: | ||||
|                     pass | ||||
|                 else: | ||||
|                     try: | ||||
|                         with req.get(link.a.get("href"), headers=random_headers(), stream=True, | ||||
|                                      timeout=3) as workingit: | ||||
|                             if workingit.status_code != 200: | ||||
|                                 link = None | ||||
|                             elif workingit.headers['Content-Type'] != 'video/mp4': | ||||
|                                 link = None | ||||
|                     except Timeout: | ||||
|                         link = None | ||||
|                 if link is None: | ||||
|                     if episode_quality == "720P - mp4": | ||||
|                         episode_quality = "HDP" | ||||
|                         time.sleep(1) | ||||
|                         CustomMessage('None', episode_quality, workingepisode).qual_not_found() | ||||
|                         episode_quality = "SHD" | ||||
|                         time.sleep(1) | ||||
|                         CustomMessage('None', episode_quality, workingepisode).use_default_qual() | ||||
|                         episode_quality = "480P - mp4" | ||||
|                     link = soup.find("div", {"class": "dowload"}, text=re.compile(episode_quality)) | ||||
|                     if link is None: | ||||
|                         pass | ||||
|                     else: | ||||
|                         try: | ||||
|                             with req.get(link.a.get("href"), headers=random_headers(), stream=True, | ||||
|                                          timeout=3) as workingit: | ||||
|                                 if workingit.status_code != 200: | ||||
|                                     link = None | ||||
|                                 elif workingit.headers['Content-Type'] != 'video/mp4': | ||||
|                                     link = None | ||||
|                         except Timeout: | ||||
|                             link = None | ||||
|                     if link is None: | ||||
|                         if episode_quality == "480P - mp4": | ||||
|                             episode_quality = "SHD" | ||||
|                             time.sleep(1) | ||||
|                             CustomMessage('None', episode_quality, workingepisode).qual_not_found() | ||||
|                             episode_quality = "SDP" | ||||
|                             time.sleep(1) | ||||
|                             CustomMessage('None', episode_quality, workingepisode).use_default_qual() | ||||
|                             episode_quality = "360P - mp4" | ||||
|                         link = soup.find("div", {"class": "dowload"}, text=re.compile(episode_quality)) | ||||
|                     else: | ||||
|                         pass | ||||
|         return [download_link[1].split("+")[-1], link.a.get("href")] | ||||
| 
 | ||||
|     def download_episodes(self, url): | ||||
|         with req.get(url[1], headers=random_headers(), stream=True, timeout=10, | ||||
|                      allow_redirects=True) as workingurl: | ||||
|             episode_name = "EP." + url[0] + ".mp4" | ||||
|             file_loc = os.path.join(self.folder, episode_name) | ||||
|             with open(file_loc, "w+b") as file: | ||||
|                 shutil.copyfileobj(workingurl.raw, file, 8192) | ||||
| 
 | ||||
|         size = os.stat(file_loc).st_size | ||||
|         count = 0 | ||||
|         while int(size) < 5 and count < 5: | ||||
|             with req.get(url[1], headers=random_headers(), stream=True, timeout=10, | ||||
|                          allow_redirects=True) as workingurl: | ||||
|                 episode_name = "EP." + url[0] + ".mp4" | ||||
|                 file_loc = os.path.join(self.folder, episode_name) | ||||
|                 with open(file_loc, "w+b") as file: | ||||
|                     shutil.copyfileobj(workingurl.raw, file, 8192) | ||||
|             count += 1 | ||||
|             size = os.stat(file_loc).st_size | ||||
|         size = os.stat(file_loc).st_size | ||||
|         if int(size) < 5: | ||||
|             print("\n") | ||||
|             CustomMessage('Could not download episode ' + url[0]).print_error() | ||||
|             os.remove(file_loc) | ||||
| 
 | ||||
| 
 | ||||
| @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() | ||||
							
								
								
									
										167
									
								
								src/bitanime.py
									
									
									
									
									
								
							
							
						
						
									
										167
									
								
								src/bitanime.py
									
									
									
									
									
								
							| @ -1,167 +0,0 @@ | ||||
| import requests as req | ||||
| import ctypes | ||||
| import os | ||||
| import concurrent.futures | ||||
| from backend import Download, CustomMessage, get_download_links | ||||
| from tqdm.contrib.concurrent import thread_map | ||||
| from bs4 import BeautifulSoup | ||||
| from colorama import Fore | ||||
| import sys | ||||
| import subprocess | ||||
| 
 | ||||
| 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}] " | ||||
| CURRENT_DOMAIN = "film" | ||||
| try: | ||||
|     ctypes.windll.kernel32.SetConsoleTitleW("BitAnime") | ||||
| except AttributeError: | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| def bitanime(): | ||||
|     os.system("cls") | ||||
|     while True: | ||||
|         print( | ||||
|             f""" {Fore.LIGHTBLUE_EX} | ||||
|                    ____  _ _      _          _ | ||||
|                   | __ )(_) |_   / \   _ __ (_)_ __ ___   ___ | ||||
|                   |  _ \| | __| / _ \ | '_ \| | '_ ` _ \ / _ \\ | ||||
|                   | |_) | | |_ / ___ \| | | | | | | | | |  __/ | ||||
|                   |____/|_|\__/_/   \_\_| |_|_|_| |_| |_|\___| | ||||
|                               {Fore.LIGHTYELLOW_EX} | ||||
|                                   By: sh1nobu | ||||
|                   Github: https://github.com/sh1nobuu/BitAnime | ||||
|     """ | ||||
|         ) | ||||
|         while True: | ||||
|             name = input(f"{IN}Enter anime name > ").lower() | ||||
|             if "-" in name: | ||||
|                 title = name.replace("-", " ").title().strip() | ||||
|             else: | ||||
|                 title = name.title().strip() | ||||
|             source = f"https://gogoanime.{CURRENT_DOMAIN}/category/{name}" | ||||
|             with req.get(source) as res: | ||||
|                 if res.status_code == 200: | ||||
|                     soup = BeautifulSoup(res.content, "html.parser") | ||||
|                     all_episodes = soup.find("ul", {"id": "episode_page"}) | ||||
|                     all_episodes = int(all_episodes.get_text().split("-")[-1].strip()) | ||||
|                     break | ||||
|                 else: | ||||
|                     print(f"{ERR}Error 404: Anime not found. Please try again.") | ||||
|         while True: | ||||
|             quality = input( | ||||
|                 f"{IN}Enter episode quality (1.SD/360P|2.SD/480P|3.HD/720P|4.FULLHD/1080P) > " | ||||
|             ) | ||||
|             if quality == "1" or quality == "": | ||||
|                 episode_quality = "SDP" | ||||
|                 break | ||||
|             elif quality == "2": | ||||
|                 episode_quality = "SHD" | ||||
|                 break | ||||
|             elif quality == "3": | ||||
|                 episode_quality = "HDP" | ||||
|                 break | ||||
|             elif quality == "4": | ||||
|                 episode_quality = "FullHDP" | ||||
|                 break | ||||
|             else: | ||||
|                 print(f"{ERR}Invalid input. Please try again.") | ||||
|         print(f"{OK}Title: {Fore.LIGHTCYAN_EX}{title}") | ||||
|         print(f"{OK}Episode/s: {Fore.LIGHTCYAN_EX}{all_episodes}") | ||||
|         print(f"{OK}Quality: {Fore.LIGHTCYAN_EX}{episode_quality}") | ||||
|         print(f"{OK}Link: {Fore.LIGHTCYAN_EX}{source}") | ||||
| 
 | ||||
|         folder = os.path.join(os.getcwd(), title) | ||||
|         if not os.path.exists(folder): | ||||
|             os.mkdir(folder) | ||||
| 
 | ||||
|         choice = "y" | ||||
| 
 | ||||
|         if all_episodes != 1: | ||||
|             while True: | ||||
|                 choice = input( | ||||
|                     f"{IN}Do you want to download all episode? (y/n) > " | ||||
|                 ).lower() | ||||
|                 if choice in ["y", "n"]: | ||||
|                     break | ||||
|                 else: | ||||
|                     print(f"{ERR}Invalid input. Please try again.") | ||||
| 
 | ||||
|         episode_start = None | ||||
|         episode_end = None | ||||
| 
 | ||||
|         if choice == "n": | ||||
|             while True: | ||||
|                 try: | ||||
|                     episode_start = int(input(f"{IN}Episode start > ")) | ||||
|                     episode_end = int(input(f"{IN}Episode end > ")) | ||||
|                     if episode_start <= 0 or episode_end <= 0: | ||||
|                         CustomMessage( | ||||
|                             f"{ERR}episode_start or episode_end cannot be less than or equal to 0" | ||||
|                         ).print_error() | ||||
|                     elif episode_start >= all_episodes or episode_end > all_episodes: | ||||
|                         CustomMessage( | ||||
|                             f"{ERR}episode_start or episode_end cannot be more than {all_episodes}" | ||||
|                         ).print_error() | ||||
|                     elif episode_end <= episode_start: | ||||
|                         CustomMessage( | ||||
|                             f"{ERR}episode_end cannot be less than or equal to episode_start" | ||||
|                         ).print_error() | ||||
|                     else: | ||||
|                         break | ||||
|                 except ValueError: | ||||
|                     print(f"{ERR}Invalid input. Please try again.") | ||||
| 
 | ||||
|         if episode_start is not None: | ||||
|             pass | ||||
|         else: | ||||
|             episode_start = 1 | ||||
|         if episode_end is not None: | ||||
|             pass | ||||
|         else: | ||||
|             episode_end = all_episodes | ||||
| 
 | ||||
|         download = Download( | ||||
|             name, episode_quality, folder, all_episodes, episode_start, episode_end | ||||
|         ) | ||||
| 
 | ||||
|         source = f"https://gogoanime.{CURRENT_DOMAIN}/{name}" | ||||
|         with req.get(source) as res: | ||||
|             soup = BeautifulSoup(res.content, "html.parser") | ||||
|             episode_zero = soup.find("h1", {"class": "entry-title"})  # value: 404 | ||||
| 
 | ||||
|         if choice == "n" or episode_zero is not None: | ||||
|             source = None | ||||
| 
 | ||||
|         episode_links = download.get_links(source) | ||||
|         with concurrent.futures.ThreadPoolExecutor() as executor: | ||||
|             download_links = list(executor.map(get_download_links, episode_links)) | ||||
|             download_urls = list( | ||||
|                 executor.map(download.get_download_urls, download_links) | ||||
|             ) | ||||
|         print( | ||||
|             f"{OK}Downloading {Fore.LIGHTCYAN_EX}{len(download_urls)}{Fore.RESET} episode/s" | ||||
|         ) | ||||
|         thread_map( | ||||
|             download.download_episodes, | ||||
|             download_urls, | ||||
|             ncols=75, | ||||
|             total=len(download_urls), | ||||
|         ) | ||||
| 
 | ||||
|         try: | ||||
|             os.startfile(folder) | ||||
|         except AttributeError: | ||||
|             opener = "open" if sys.platform == "darwin" else "xdg-open" | ||||
|             subprocess.call([opener, folder]) | ||||
|         print("\n") | ||||
|         use_again = input(f"{IN}Do you want to use the app again? (y|n) > ").lower() | ||||
|         if use_again == "y": | ||||
|             os.system("cls") | ||||
|         else: | ||||
|             break | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
|     bitanime() | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user