diff --git a/Src/Api/Class/EpisodeType.py b/Src/Api/Class/EpisodeType.py index 2b69a3a..fcd20c2 100644 --- a/Src/Api/Class/EpisodeType.py +++ b/Src/Api/Class/EpisodeType.py @@ -58,3 +58,12 @@ class EpisodeManager: int: Number of episodes. """ return len(self.episodes) + + def clear(self) -> None: + """ + This method clears the episodes list. + + Args: + self: The object instance. + """ + self.episodes.clear() diff --git a/Src/Api/Class/SearchType.py b/Src/Api/Class/SearchType.py index 8aaecc8..0d369fc 100644 --- a/Src/Api/Class/SearchType.py +++ b/Src/Api/Class/SearchType.py @@ -77,4 +77,12 @@ class MediaManager: """ return len(self.media_list) + def clear(self) -> None: + """ + This method clears the medias list. + + Args: + self: The object instance. + """ + self.media_list.clear() diff --git a/Src/Api/Class/SeriesType.py b/Src/Api/Class/SeriesType.py index c242e6f..efee669 100644 --- a/Src/Api/Class/SeriesType.py +++ b/Src/Api/Class/SeriesType.py @@ -59,4 +59,13 @@ class TitleManager: Returns: int: Number of titles. """ - return len(self.titles) \ No newline at end of file + return len(self.titles) + + def clear(self) -> None: + """ + This method clears the titles list. + + Args: + self: The object instance. + """ + self.titles.clear() \ No newline at end of file diff --git a/Src/Api/series.py b/Src/Api/series.py index e069b29..327c03d 100644 --- a/Src/Api/series.py +++ b/Src/Api/series.py @@ -5,7 +5,7 @@ from Src.Util.console import console, msg from Src.Util.config import config_manager from Src.Util.table import TVShowManager from Src.Util.message import start_message -from Src.Util.os import remove_special_characters +from Src.Lib.Unidecode import unidecode from Src.Lib.FFmpeg.my_m3u8 import Downloader from .Class import VideoSource @@ -110,7 +110,7 @@ def donwload_video(tv_name: str, index_season_selected: int, index_episode_selec episode_id = video_source.obj_episode_manager.episodes[index_episode_selected - 1].id # Define filename and path for the downloaded video - mp4_name = f"{index_episode_selected}_{remove_special_characters(video_source.obj_episode_manager.episodes[index_episode_selected - 1].name)}.mp4" + mp4_name = f"{index_episode_selected}_{unidecode(video_source.obj_episode_manager.episodes[index_episode_selected - 1].name)}.mp4" mp4_path = os.path.join(ROOT_PATH, SERIES_FOLDER, tv_name, f"S{index_season_selected}") os.makedirs(mp4_path, exist_ok=True) @@ -143,6 +143,9 @@ def donwload_episode(tv_name: str, index_season_selected: int, donwload_all: boo donwload_all (bool): Donwload all seasons episodes """ + # Clean memory of all episodes + video_source.obj_episode_manager.clear() + # Start message and collect information about episodes start_message() video_source.collect_title_season(index_season_selected) diff --git a/Src/Lib/FFmpeg/my_m3u8.py b/Src/Lib/FFmpeg/my_m3u8.py index 51ade46..beeaa58 100644 --- a/Src/Lib/FFmpeg/my_m3u8.py +++ b/Src/Lib/FFmpeg/my_m3u8.py @@ -207,11 +207,11 @@ class M3U8_Segments: return response.content else: - logging.info(f"Skipping invalid URL: {ts_url}") + logging.warn(f"Skipping invalid URL: {ts_url}") return None except requests.exceptions.RequestException as req_err: - logging.error(f"Error occurred during request to {ts_url}: {req_err}") + logging.warn(f"Error occurred during request to {ts_url}: {req_err}") return None except Exception as e: diff --git a/Src/Lib/Unidecode/__init__.py b/Src/Lib/Unidecode/__init__.py new file mode 100644 index 0000000..5633c45 --- /dev/null +++ b/Src/Lib/Unidecode/__init__.py @@ -0,0 +1,138 @@ +# -*- coding: utf-8 -*- +# vi:tabstop=4:expandtab:sw=4 +"""Transliterate Unicode text into plain 7-bit ASCII. + +Example usage: + +>>> from unidecode import unidecode +>>> unidecode("\u5317\u4EB0") +"Bei Jing " + +The transliteration uses a straightforward map, and doesn't have alternatives +for the same character based on language, position, or anything else. + +A standard string object will be returned. If you need bytes, use: + +>>> unidecode("Κνωσός").encode("ascii") +b'Knosos' +""" +import warnings +from typing import Dict, Optional, Sequence + +Cache = {} # type: Dict[int, Optional[Sequence[Optional[str]]]] + +class UnidecodeError(ValueError): + def __init__(self, message: str, index: Optional[int] = None) -> None: + """Raised for Unidecode-related errors. + + The index attribute contains the index of the character that caused + the error. + """ + super(UnidecodeError, self).__init__(message) + self.index = index + + +def unidecode_expect_ascii(string: str, errors: str = 'ignore', replace_str: str = '?') -> str: + """Transliterate an Unicode object into an ASCII string + + >>> unidecode("\u5317\u4EB0") + "Bei Jing " + + This function first tries to convert the string using ASCII codec. + If it fails (because of non-ASCII characters), it falls back to + transliteration using the character tables. + + This is approx. five times faster if the string only contains ASCII + characters, but slightly slower than unicode_expect_nonascii if + non-ASCII characters are present. + + errors specifies what to do with characters that have not been + found in replacement tables. The default is 'ignore' which ignores + the character. 'strict' raises an UnidecodeError. 'replace' + substitutes the character with replace_str (default is '?'). + 'preserve' keeps the original character. + + Note that if 'preserve' is used the returned string might not be + ASCII! + """ + + try: + bytestring = string.encode('ASCII') + except UnicodeEncodeError: + pass + else: + return string + + return _unidecode(string, errors, replace_str) + +def unidecode_expect_nonascii(string: str, errors: str = 'ignore', replace_str: str = '?') -> str: + """Transliterate an Unicode object into an ASCII string + + >>> unidecode("\u5317\u4EB0") + "Bei Jing " + + See unidecode_expect_ascii. + """ + + return _unidecode(string, errors, replace_str) + +unidecode = unidecode_expect_ascii + +def _get_repl_str(char: str) -> Optional[str]: + codepoint = ord(char) + + if codepoint < 0x80: + # Already ASCII + return str(char) + + if codepoint > 0xeffff: + # No data on characters in Private Use Area and above. + return None + + if 0xd800 <= codepoint <= 0xdfff: + warnings.warn( "Surrogate character %r will be ignored. " + "You might be using a narrow Python build." % (char,), + RuntimeWarning, 2) + + section = codepoint >> 8 # Chop off the last two hex digits + position = codepoint % 256 # Last two hex digits + + try: + table = Cache[section] + except KeyError: + try: + mod = __import__('unidecode.x%03x'%(section), globals(), locals(), ['data']) + except ImportError: + # No data on this character + Cache[section] = None + return None + + Cache[section] = table = mod.data + + if table and len(table) > position: + return table[position] + else: + return None + +def _unidecode(string: str, errors: str, replace_str:str) -> str: + retval = [] + + for index, char in enumerate(string): + repl = _get_repl_str(char) + + if repl is None: + if errors == 'ignore': + repl = '' + elif errors == 'strict': + raise UnidecodeError('no replacement found for character %r ' + 'in position %d' % (char, index), index) + elif errors == 'replace': + repl = replace_str + elif errors == 'preserve': + repl = char + else: + raise UnidecodeError('invalid value for errors parameter %r' % (errors,)) + + retval.append(repl) + + return ''.join(retval) diff --git a/Src/Lib/Unidecode/x000.py b/Src/Lib/Unidecode/x000.py new file mode 100644 index 0000000..6b3d1fc --- /dev/null +++ b/Src/Lib/Unidecode/x000.py @@ -0,0 +1,165 @@ +data = ( +# Code points u+007f and below are equivalent to ASCII and are handled by a +# special case in the code. Hence they are not present in this table. +'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', +'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', +'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', +'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', +'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', +'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', +'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', +'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + +'', # 0x80 +'', # 0x81 +'', # 0x82 +'', # 0x83 +'', # 0x84 +'', # 0x85 +'', # 0x86 +'', # 0x87 +'', # 0x88 +'', # 0x89 +'', # 0x8a +'', # 0x8b +'', # 0x8c +'', # 0x8d +'', # 0x8e +'', # 0x8f +'', # 0x90 +'', # 0x91 +'', # 0x92 +'', # 0x93 +'', # 0x94 +'', # 0x95 +'', # 0x96 +'', # 0x97 +'', # 0x98 +'', # 0x99 +'', # 0x9a +'', # 0x9b +'', # 0x9c +'', # 0x9d +'', # 0x9e +'', # 0x9f +' ', # 0xa0 +'!', # 0xa1 +'C/', # 0xa2 + +# Not "GBP" - Pound Sign is used for more than just British Pounds. +'PS', # 0xa3 + +'$?', # 0xa4 +'Y=', # 0xa5 +'|', # 0xa6 +'SS', # 0xa7 +'"', # 0xa8 +'(c)', # 0xa9 +'a', # 0xaa +'<<', # 0xab +'!', # 0xac +'', # 0xad +'(r)', # 0xae +'-', # 0xaf +'deg', # 0xb0 +'+-', # 0xb1 + +# These might be combined with other superscript digits (u+2070 - u+2079) +'2', # 0xb2 +'3', # 0xb3 + +'\'', # 0xb4 +'u', # 0xb5 +'P', # 0xb6 +'*', # 0xb7 +',', # 0xb8 +'1', # 0xb9 +'o', # 0xba +'>>', # 0xbb +' 1/4', # 0xbc +' 1/2', # 0xbd +' 3/4', # 0xbe +'?', # 0xbf +'A', # 0xc0 +'A', # 0xc1 +'A', # 0xc2 +'A', # 0xc3 + +# Not "AE" - used in languages other than German +'A', # 0xc4 + +'A', # 0xc5 +'AE', # 0xc6 +'C', # 0xc7 +'E', # 0xc8 +'E', # 0xc9 +'E', # 0xca +'E', # 0xcb +'I', # 0xcc +'I', # 0xcd +'I', # 0xce +'I', # 0xcf +'D', # 0xd0 +'N', # 0xd1 +'O', # 0xd2 +'O', # 0xd3 +'O', # 0xd4 +'O', # 0xd5 + +# Not "OE" - used in languages other than German +'O', # 0xd6 + +'x', # 0xd7 +'O', # 0xd8 +'U', # 0xd9 +'U', # 0xda +'U', # 0xdb + +# Not "UE" - used in languages other than German +'U', # 0xdc + +'Y', # 0xdd +'Th', # 0xde +'ss', # 0xdf +'a', # 0xe0 +'a', # 0xe1 +'a', # 0xe2 +'a', # 0xe3 + +# Not "ae" - used in languages other than German +'a', # 0xe4 + +'a', # 0xe5 +'ae', # 0xe6 +'c', # 0xe7 +'e', # 0xe8 +'e', # 0xe9 +'e', # 0xea +'e', # 0xeb +'i', # 0xec +'i', # 0xed +'i', # 0xee +'i', # 0xef +'d', # 0xf0 +'n', # 0xf1 +'o', # 0xf2 +'o', # 0xf3 +'o', # 0xf4 +'o', # 0xf5 + +# Not "oe" - used in languages other than German +'o', # 0xf6 + +'/', # 0xf7 +'o', # 0xf8 +'u', # 0xf9 +'u', # 0xfa +'u', # 0xfb + +# Not "ue" - used in languages other than German +'u', # 0xfc + +'y', # 0xfd +'th', # 0xfe +'y', # 0xff +) diff --git a/Src/Upload/update.py b/Src/Upload/update.py index 052da5a..d6c7cac 100644 --- a/Src/Upload/update.py +++ b/Src/Upload/update.py @@ -1,6 +1,7 @@ # 01.03.2023 # Class import +from .version import __version__ from Src.Util.console import console # General import @@ -14,20 +15,6 @@ repo_user = "ghost6446" main = os.path.abspath(os.path.dirname(__file__)) -def get_install_version(): - """ - Get the installed version from the '__version__.py' file. - """ - - about = {} - - version_file_path = os.path.join(main, '__version__.py') - - with open(version_file_path, 'r', encoding='utf-8') as f: - exec(f.read(), about) - - return about['__version__'] - def update(): """ Check for updates on GitHub and display relevant information. @@ -56,10 +43,8 @@ def update(): else: percentual_stars = 0 - installed_version = get_install_version() - # Check installed version - if installed_version != last_version: + if __version__ != last_version: console.print(f"[red]Version: [yellow]{last_version}") else: console.print(f"[red]Everything up to date") diff --git a/Src/Upload/__version__.py b/Src/Upload/version.py similarity index 100% rename from Src/Upload/__version__.py rename to Src/Upload/version.py diff --git a/update.py b/update.py index 3409cc5..4a64cf6 100644 --- a/update.py +++ b/update.py @@ -135,4 +135,5 @@ def main_upload(): main_upload() # win -# pyinstaller --onefile --add-data "./Src/upload/__version__.py;Src/upload" run.py +# pyinstaller --upx-dir="C:\Program Files\upx" --onefile run.py +