Compare commits

..

No commits in common. "22ee445b7eb12f6eed8d23f9d161a2fefdfd00d1" and "aade02d7634788b0da861fa5f088aff66fe709d1" have entirely different histories.

11 changed files with 27 additions and 339 deletions

4
.gitmodules vendored
View File

@ -1,4 +0,0 @@
[submodule "AniWorld-Downloader"]
path = AniWorld-Downloader
url = https://github.com/lukaspupkalipinski/AniWorld-Downloader.git
branch = next

@ -1 +0,0 @@
Subproject commit 94e332f37b3f037d175e579ea370ab2be90534e4

View File

@ -11,7 +11,7 @@ from aniworld.parser import arguments
timeout = int(os.getenv("DOWNLOAD_TIMEOUT", 600))
download_error_logger = logging.getLogger("DownloadErrors")
download_error_handler = logging.FileHandler("../download_errors.log")
download_error_handler = logging.FileHandler("download_errors.log")
download_error_handler.setLevel(logging.ERROR)
download_error_logger.addHandler(download_error_handler)
@ -40,7 +40,7 @@ def download(anime: Anime): # pylint: disable=too-many-branches
"yt-dlp",
episode.get_direct_link(anime.provider, anime.language),
"--fragment-retries", "infinite",
#"--concurrent-fragments", "4",
"--concurrent-fragments", "4",
"-o", output_path,
"--quiet",
"--no-warnings"

Binary file not shown.

View File

@ -1,12 +1,14 @@
import sys
import os
import traceback
import re
import logging
from concurrent.futures import ThreadPoolExecutor
from collections import defaultdict
from aniworld.models import Anime, Episode
from aniworld.common import get_season_episode_count
from aniworld.common import get_season_episode_count, get_movie_episode_count
from aniworld.search import search_anime
from src.Loader import download
from Loader import download
# Configure logging
@ -22,17 +24,17 @@ logging.getLogger('charset_normalizer').setLevel(logging.INFO)
logging.getLogger().setLevel(logging.INFO)
error_logger = logging.getLogger("ErrorLog")
error_handler = logging.FileHandler("../errors.log")
error_handler = logging.FileHandler("errors.log")
error_handler.setLevel(logging.ERROR)
error_logger.addHandler(error_handler)
noKeyFound_logger = logging.getLogger("NoKeyFound")
noKeyFound_handler = logging.FileHandler("../NoKeyFound.log")
noKeyFound_handler = logging.FileHandler("NoKeyFound.log")
noKeyFound_handler.setLevel(logging.ERROR)
noKeyFound_logger.addHandler(noKeyFound_handler)
noGerFound_logger = logging.getLogger("noGerFound")
noGerFound_handler = logging.FileHandler("../noGerFound.log")
noGerFound_handler = logging.FileHandler("noGerFound.log")
noGerFound_handler.setLevel(logging.ERROR)
noGerFound_logger.addHandler(noGerFound_handler)
@ -165,23 +167,26 @@ class Loader:
except Exception as e:
logging.error(f"Error downloading episode {episode} of season {season} for anime {key}: {e}")
for folder, mp4_files in result:
try:
key = self.__check_and_generate_key(folder)
missings = self.__GetMissingEpisodesAndSeason(key, mp4_files)
for season, missing_episodes in missings:
logging.info(f"Missing episodes for {key}\nSeason {str(season)}: Episodes: " + ",".join(f"{''.join(str(v))}" for v in missing_episodes))
for episode in missing_episodes:
download_episode(folder, season, episode, key)
except NoKeyFoundException as nkfe:
noKeyFound_logger.error(f"Error processing folder '{folder}': {nkfe}")
except Exception as e:
error_logger.error(f"Unexpected error processing folder '{folder}': {e} \n {traceback.format_exc()}")
continue
# Using ThreadPoolExecutor to run downloads in parallel
with ThreadPoolExecutor(max_workers=2) as executor: # Adjust number of workers as needed
for folder, mp4_files in result:
try:
key = self.__check_and_generate_key(folder)
missings = self.__GetMissingEpisodesAndSeason(key, mp4_files)
for season, missing_episodes in missings:
logging.info(f"Missing episodes for {key}\nSeason {str(season)}: Episodes: " + ",".join(f"{''.join(str(v))}" for v in missing_episodes))
for episode in missing_episodes:
executor.submit(download_episode, folder, season, episode, key)
#download_episode(folder, season, episode, key)
except NoKeyFoundException as nkfe:
noKeyFound_logger.error(f"Error processing folder '{folder}': {nkfe}")
except Exception as e:
error_logger.error(f"Unexpected error processing folder '{folder}': {e} \n {traceback.format_exc()}")
continue
# Read the base directory from an environment variable
directory_to_search = os.getenv("ANIME_DIRECTORY", "\\\\sshfs.r\\ubuntu@192.168.178.43\\media\\serien\\Serien")
#directory_to_search = os.getenv("ANIME_DIRECTORY", "D:\\sss")
#directory_to_search = os.getenv("ANIME_DIRECTORY", "D:\sss")
loader = Loader(directory_to_search)
loader.LoadMissing()

View File

@ -1,3 +1,4 @@
aniworld
requests
beautifulsoup4
lxml

View File

@ -1,7 +0,0 @@
class NoKeyFoundException(Exception):
"""Exception raised when an anime key cannot be found."""
pass
class MatchNotFoundError(Exception):
"""Exception raised when an anime key cannot be found."""
pass

View File

@ -1,160 +0,0 @@
import os
import re
import logging
from collections import defaultdict
import pickle
from Serie import Serie
import json
import traceback
from GlobalLogger import setupLogger, error_logger, noKeyFound_logger, noGerFound_logger
from Exceptions import NoKeyFoundException, MatchNotFoundError
import requests
from aniworld.common import get_season_episode_count
class FolderLookup:
def __init__(self, basePath: str):
self.directory = basePath
self.folderDict = dict[str, list[Serie]]
logging.info(f"Initialized Loader with base path: {self.directory}")
self.__init()
def is_null_or_whitespace(self, s):
return s is None or s.strip() == ""
def __init(self):
logging.info("Starting process to load missing episodes")
result = self.__find_mp4_files()
for folder, mp4_files in result:
try:
serie = self.__ReadDataFromFile(folder)
if (serie != None and not self.is_null_or_whitespace(serie.key)):
missings, site = self.__GetMissingEpisodesAndSeason(serie.key, mp4_files)
serie.episodeDict = missings
self.__SaveData(serie, folder)
if folder not in self.folderDict:
self.folderDict[folder] = []
self.folderDict[folder].append(serie)
except NoKeyFoundException as nkfe:
noKeyFound_logger.error(f"Error processing folder '{folder}': {nkfe}")
except Exception as e:
error_logger.error(f"Unexpected error processing folder '{folder}': {e} \n {traceback.format_exc()}")
continue
def __find_mp4_files(self):
logging.info("Scanning for .mp4 files")
for root_folder_name in os.listdir(self.directory):
folder_data = defaultdict(list) # Dictionary to store MP4 files per folder
folder = os.path.join(self.directory, root_folder_name)
logging.info(f"Processing folder: {root_folder_name}")
# First pass: Scan all folders and collect MP4 file data
for root, dirs, files in os.walk(folder):
mp4_files = [file for file in files if file.endswith('.mp4')]
if mp4_files:
folder_data[root_folder_name].extend(mp4_files)
yield root_folder_name, folder_data[root_folder_name]
for dir in self.__find_empty_folders():
logging.info(f"Found no .mp4 files in {dir}")
yield dir, []
def __find_empty_folders(self):
"""Yield folder names that do not contain any mp4 files in a given directory."""
for folder in os.listdir(self.directory):
folder_path = os.path.join(self.directory, folder)
if os.path.isdir(folder_path): # Ensure it's a directory
has_mp4 = any(file.endswith(".mp4") for file in os.listdir(folder_path))
if not has_mp4:
yield folder # Yield the folder name if no mp4 files found
def __remove_year(self, input_string: str):
cleaned_string = re.sub(r'\(\d{4}\)', '', input_string).strip()
logging.debug(f"Removed year from '{input_string}' -> '{cleaned_string}'")
return cleaned_string
def __ReadDataFromFile(self, folder_name: str):
folder_path = os.path.join(self.directory, folder_name)
key = None
key_file = os.path.join(folder_path, 'key')
serie_file = os.path.join(folder_path, 'data')
if os.path.exists(key_file):
with open(key_file, 'r') as file:
logging.info(f"Key found for folder '{folder_name}': {key}")
key = file.read().strip()
return Serie(key, "", "aniworld.to" ,folder_name)
if os.path.exists(serie_file):
with open(serie_file, "rb") as file:
logging.info(f"load serie_file from '{folder_name}': {serie_file}")
return pickle.load(file)
return None
def __SaveData(self, serie: Serie, folder_name: str):
"""Saves a Serie object to a file using JSON."""
folder_path = os.path.join(self.directory, folder_name)
serie_file = os.path.join(folder_path, 'data')
with open(serie_file, "w", encoding="utf-8") as file:
json.dump(serie, file, indent=4)
def __GetEpisodeAndSeason(self, filename: str):
pattern = r'S(\d+)E(\d+)'
match = re.search(pattern, filename)
if match:
season = match.group(1)
episode = match.group(2)
logging.debug(f"Extracted season {season}, episode {episode} from '{filename}'")
return int(season), int(episode)
else:
logging.error(f"Failed to find season/episode pattern in '{filename}'")
raise MatchNotFoundError("Season and episode pattern not found in the filename.")
def __GetEpisodesAndSeasons(self, mp4_files: []):
episodes_dict = {}
for file in mp4_files:
season, episode = self.__GetEpisodeAndSeason(file)
if season in episodes_dict:
episodes_dict[season].append(episode)
else:
episodes_dict[season] = [episode]
return episodes_dict
def __GetMissingEpisodesAndSeason(self, key: str, mp4_files: []):
expected_dict = get_season_episode_count(key) # key season , value count of episodes
filedict = self.__GetEpisodesAndSeasons(mp4_files)
episodes_dict = {}
for season, expected_count in expected_dict.items():
existing_episodes = filedict.get(season, [])
missing_episodes = [ep for ep in range(1, expected_count + 1) if ep not in existing_episodes]
if missing_episodes:
episodes_dict[season] = [missing_episodes]
return episodes_dict, "aniworld.to"
#gg = FolderLookup("\\\\sshfs.r\\ubuntu@192.168.178.43\\media\\serien\\Serien")
base_url = f"https://aniworld.to/anime/stream/aico-incarnation"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
"Accept": "*/*",
"Referer": "https://www.example.com"
}
session = requests.Session()
response = requests.get(base_url, headers=headers, timeout=30)
c = response.content;

View File

@ -1,40 +0,0 @@
import logging
console_handler = None
error_logger = None
noKeyFound_logger = None
noGerFound_logger = None
def setupLogger():
global console_handler, error_logger, noKeyFound_logger, noGerFound_logger
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(funcName)s - %(message)s')
if (console_handler is None):
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
console_handler.setFormatter(logging.Formatter(
"%(asctime)s - %(levelname)s - %(funcName)s - %(message)s")
)
logging.getLogger().addHandler(console_handler)
logging.getLogger("urllib3.connectionpool").setLevel(logging.INFO)
logging.getLogger('charset_normalizer').setLevel(logging.INFO)
logging.getLogger().setLevel(logging.INFO)
if (error_logger is None):
error_logger = logging.getLogger("ErrorLog")
error_handler = logging.FileHandler("../errors.log")
error_handler.setLevel(logging.ERROR)
error_logger.addHandler(error_handler)
if (noKeyFound_logger is None):
noKeyFound_logger = logging.getLogger("NoKeyFound")
noKeyFound_handler = logging.FileHandler("../NoKeyFound.log")
noKeyFound_handler.setLevel(logging.ERROR)
noKeyFound_logger.addHandler(noKeyFound_handler)
if (noGerFound_logger is None):
noGerFound_logger = logging.getLogger("noGerFound")
noGerFound_handler = logging.FileHandler("../noGerFound.log")
noGerFound_handler.setLevel(logging.ERROR)
noGerFound_logger.addHandler(noGerFound_handler)
setupLogger()

View File

@ -1,47 +0,0 @@
class Serie:
def __init__(self, key: str, name: str, site: str, folder: str):
self._key = key
self._name = name
self._site = site
self._folder = folder
self._episodeDict = dict[int, list[int]]
@property
def key(self) -> str:
return self._key
@key.setter
def key(self, value: str):
self._key = value
@property
def name(self) -> str:
return self._name
@name.setter
def name(self, value: str):
self._name = value
@property
def site(self) -> str:
return self._site
@site.setter
def site(self, value: str):
self._site = value
@property
def folder(self) -> str:
return self._folder
@folder.setter
def folder(self, value: str):
self._folder = value
@property
def episodeDict(self) -> dict[int, list[int]]:
return self._episodeDict
@episodeDict.setter
def episodeDict(self, value: dict[int, list[int]]):
self._episodeDict = value

View File

@ -1,59 +0,0 @@
import sys
import os
import traceback
import re
import logging
from concurrent.futures import ThreadPoolExecutor
from collections import defaultdict
from aniworld.models import Anime, Episode
from aniworld.common import get_season_episode_count, get_movie_episode_count
from aniworld.search import search_anime
from Loader import download
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(funcName)s - %(message)s')
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
console_handler.setFormatter(logging.Formatter(
"%(asctime)s - %(levelname)s - %(funcName)s - %(message)s")
)
logging.getLogger().addHandler(console_handler)
logging.getLogger("urllib3.connectionpool").setLevel(logging.INFO)
logging.getLogger('charset_normalizer').setLevel(logging.INFO)
logging.getLogger().setLevel(logging.INFO)
error_logger = logging.getLogger("ErrorLog")
error_handler = logging.FileHandler("../errors.log")
error_handler.setLevel(logging.ERROR)
error_logger.addHandler(error_handler)
noKeyFound_logger = logging.getLogger("NoKeyFound")
noKeyFound_handler = logging.FileHandler("../NoKeyFound.log")
noKeyFound_handler.setLevel(logging.ERROR)
noKeyFound_logger.addHandler(noKeyFound_handler)
noGerFound_logger = logging.getLogger("noGerFound")
noGerFound_handler = logging.FileHandler("../noGerFound.log")
noGerFound_handler.setLevel(logging.ERROR)
noGerFound_logger.addHandler(noGerFound_handler)
class NoKeyFoundException(Exception):
"""Exception raised when an anime key cannot be found."""
pass
class MatchNotFoundError(Exception):
"""Exception raised when an anime key cannot be found."""
pass
class ConsoleLoader:
def __init__(self, basePath: str):
self.directory = basePath
logging.info(f"Initialized Loader with base path: {self.directory}")
# Read the base directory from an environment variable
directory_to_search = os.getenv("ANIME_DIRECTORY", "\\\\sshfs.r\\ubuntu@192.168.178.43\\media\\serien\\Serien")
loader = Loader(directory_to_search)
loader.LoadMissing()