From d1808188495e5e65008253a314d381d437743d9c Mon Sep 17 00:00:00 2001 From: MainKronos Date: Sun, 9 Oct 2022 17:28:32 +0200 Subject: [PATCH] Aggiornamento funzione download --- animeworld/episodio.py | 14 ++-- animeworld/exceptions.py | 6 ++ animeworld/server.py | 145 +++++++++++++++++++++++---------------- documentation/example.py | 6 +- setup.py | 2 +- 5 files changed, 104 insertions(+), 69 deletions(-) diff --git a/animeworld/episodio.py b/animeworld/episodio.py index fe8f6f0..c190dd7 100644 --- a/animeworld/episodio.py +++ b/animeworld/episodio.py @@ -97,7 +97,7 @@ def fileInfo(self) -> Dict[str,str]: raise err - def download(self, title: Optional[str]=None, folder: str='', hook: Callable[[Dict], None] = lambda *args:None) -> Optional[str]: # Scarica l'episodio con il primo link nella lista + def download(self, title: Optional[str]=None, folder: str='', *, hook: Callable[[Dict], None]=lambda *args:None, opt: List[str]=[]) -> Optional[str]: # Scarica l'episodio con il primo link nella lista """ Scarica l'episodio dal primo server funzionante della lista links. @@ -110,8 +110,10 @@ def download(self, title: Optional[str]=None, folder: str='', hook: Callable[[Di - `speed`: Velocità di download (byte/s) - `elapsed`: Tempo trascorso dall'inizio del download. - `eta`: Tempo stimato rimanente per fine del download. - - `status`: 'downloading' | 'finished' + - `status`: 'downloading' | 'finished' | 'aborted' - `filename`: Nome del file in download. + - `opt`: Lista per delle opzioni aggiuntive. + - `'abort'`: Ferma forzatamente il download. ``` return str # File scaricato @@ -122,11 +124,9 @@ def download(self, title: Optional[str]=None, folder: str='', hook: Callable[[Di err = None for server in self.links: try: - file = server.download(title,folder,hook) - except ServerNotSupported: - pass - except requests.exceptions.RequestException as exc: - err = exc + file = server.download(title,folder,hook=hook,opt=opt) + except (ServerNotSupported, requests.exceptions.RequestException) as e: + err = e else: return file diff --git a/animeworld/exceptions.py b/animeworld/exceptions.py index 23f4f9d..436c06d 100644 --- a/animeworld/exceptions.py +++ b/animeworld/exceptions.py @@ -31,3 +31,9 @@ def __init__(self, file, funName, line): self.line = line self.message = f"Il sito è cambiato, di conseguenza la libreria è DEPRECATA. -> [File {file} in {funName} - {line}]" super().__init__(self.message) + +class HardStoppedDownload(Exception): + """Il file in download è stato forsatamente interrotto.""" + def __init__(self): + self.message = "Il file in download è stato forsatamente interrotto." + super().__init__(self.message) \ No newline at end of file diff --git a/animeworld/server.py b/animeworld/server.py index ce815f7..4b5ea1b 100644 --- a/animeworld/server.py +++ b/animeworld/server.py @@ -10,7 +10,7 @@ from datetime import datetime from .utility import HealthCheck, SES -from .exceptions import ServerNotSupported +from .exceptions import ServerNotSupported, HardStoppedDownload class Server: @@ -128,7 +128,7 @@ def error(self, msg): } - def download(self, title: Optional[str]=None, folder: str='', hook: Callable[[Dict], None] = lambda *args:None) -> Optional[str]: + def download(self, title: Optional[str]=None, folder: str='', *, hook: Callable[[Dict], None]=lambda *args:None, opt: List[str]=[]) -> Optional[str]: """ Scarica l'episodio. @@ -141,8 +141,10 @@ def download(self, title: Optional[str]=None, folder: str='', hook: Callable[[Di - `speed`: Velocità di download (byte/s) - `elapsed`: Tempo trascorso dall'inizio del download. - `eta`: Tempo stimato rimanente per fine del download. - - `status`: 'downloading' | 'finished' + - `status`: 'downloading' | 'finished' | 'aborted' - `filename`: Nome del file in download. + - `opt`: Lista per delle opzioni aggiuntive. + - `'abort'`: Ferma forzatamente il download. ``` return str # File scaricato @@ -151,7 +153,8 @@ def download(self, title: Optional[str]=None, folder: str='', hook: Callable[[Di raise ServerNotSupported(self.name) # Protected - def _downloadIn(self, title: str, folder: str, hook: Callable[[Dict], None]) -> bool: # Scarica l'episodio + def _downloadIn(self, title: str, folder: str, *, hook: Callable[[Dict], None], opt: List[str]) -> Optional[str]: # Scarica l'episodio + """ Scarica il file utilizzando requests. @@ -164,11 +167,13 @@ def _downloadIn(self, title: str, folder: str, hook: Callable[[Dict], None]) -> - `speed`: Velocità di download (byte/s) - `elapsed`: Tempo trascorso dall'inizio del download. - `eta`: Tempo stimato rimanente per fine del download. - - `status`: 'downloading' | 'finished' + - `status`: 'downloading' | 'finished' | 'aborted' - `filename`: Nome del file in download. + - `opt`: Lista per delle opzioni aggiuntive. + - `'abort'`: Ferma forzatamente il download. ``` - return bool # File scaricato + return str # File scaricato ``` """ with SES.get(self._getFileLink(), stream = True) as r: @@ -182,43 +187,48 @@ def _downloadIn(self, title: str, folder: str, hook: Callable[[Dict], None]) -> start = time.time() step = time.time() - with open(f"{os.path.join(folder,file)}", 'wb') as f: - for chunk in r.iter_content(chunk_size = 524288): - if chunk: - f.write(chunk) - f.flush() - - current_lenght += len(chunk) - + try: + with open(f"{os.path.join(folder,file)}", 'wb') as f: + for chunk in r.iter_content(chunk_size = 524288): + if chunk: + f.write(chunk) + f.flush() + + current_lenght += len(chunk) + + hook({ + 'total_bytes': total_length, + 'downloaded_bytes': current_lenght, + 'percentage': current_lenght/total_length, + 'speed': len(chunk) / (time.time() - step) if (time.time() - step) != 0 else 0, + 'elapsed': time.time() - start, + 'filename': file, + 'eta': ((total_length - current_lenght) / len(chunk)) * (time.time() - step), + 'status': 'downloading' if "abort" not in opt else "aborted" + }) + + if "abort" in opt: raise HardStoppedDownload() + + step = time.time() + + else: hook({ 'total_bytes': total_length, - 'downloaded_bytes': current_lenght, - 'percentage': current_lenght/total_length, - 'speed': len(chunk) / (time.time() - step) if (time.time() - step) != 0 else 0, + 'downloaded_bytes': total_length, + 'percentage': 1, + 'speed': 0, 'elapsed': time.time() - start, - 'filename': file, - 'eta': ((total_length - current_lenght) / len(chunk)) * (time.time() - step), - 'status': 'downloading' + 'eta': 0, + 'status': 'finished' }) - step = time.time() - - else: - hook({ - 'total_bytes': total_length, - 'downloaded_bytes': total_length, - 'percentage': 1, - 'speed': 0, - 'elapsed': time.time() - start, - 'eta': 0, - 'status': 'finished' - }) - - return file # Se il file è stato scaricato correttamente - return None # Se è accaduto qualche imprevisto + return file # Se il file è stato scaricato correttamente + except HardStoppedDownload: + os.remove(f"{os.path.join(folder,file)}") + return None # Protected - def _dowloadEx(self, title: str, folder: str, hook: Callable[[Dict], None]) -> Optional[str]: + def _dowloadEx(self, title: str, folder: str, *, hook: Callable[[Dict], None], opt: List[str]) -> Optional[str]: """ Scarica il file utilizzando yutube_dl. @@ -231,9 +241,11 @@ def _dowloadEx(self, title: str, folder: str, hook: Callable[[Dict], None]) -> O - `speed`: Velocità di download (byte/s) - `elapsed`: Tempo trascorso dall'inizio del download. - `eta`: Tempo stimato rimanente per fine del download. - - `status`: 'downloading' | 'finished' + - `status`: 'downloading' | 'finished' | 'aborted' - `filename`: Nome del file in download. - + - `opt`: Lista per delle opzioni aggiuntive. + - `'abort'`: Ferma forzatamente il download. + ``` return str # File scaricato ``` @@ -249,6 +261,7 @@ def error(self, msg): return False def my_hook(d): + hook({ 'total_bytes': int(d['total_bytes_estimate']), 'downloaded_bytes': int(d['downloaded_bytes']), @@ -257,10 +270,10 @@ def my_hook(d): 'elapsed': float(d['elapsed']), 'filename': d['filename'], 'eta': int(d['eta']), - 'status': d['status'] + 'status': d['status'] if "abort" not in opt else "aborted" }) - if d['status'] == 'finished': - return True + + if "abort" in opt: raise HardStoppedDownload() ydl_opts = { 'outtmpl': f"{os.path.join(folder,title)}.%(ext)s", @@ -271,7 +284,11 @@ def my_hook(d): url = self._getFileLink() info = ydl.extract_info(url, download=False) filename = ydl.prepare_filename(info) - ydl.download([url]) + try: + ydl.download([url]) + except HardStoppedDownload: + os.remove(f"{os.path.join(folder,filename)}") + return None return filename @@ -300,7 +317,7 @@ def fileInfo(self) -> Dict[str,str]: return self._fileInfoIn() - def download(self, title: Optional[str]=None, folder: str='', hook: Callable[[Dict], None] = lambda *args:None) -> bool: + def download(self, title: Optional[str]=None, folder: str='', *, hook: Callable[[Dict], None]=lambda *args:None, opt: List[str]=[]) -> Optional[str]: """ Scarica l'episodio. @@ -313,16 +330,18 @@ def download(self, title: Optional[str]=None, folder: str='', hook: Callable[[Di - `speed`: Velocità di download (byte/s) - `elapsed`: Tempo trascorso dall'inizio del download. - `eta`: Tempo stimato rimanente per fine del download. - - `status`: 'downloading' | 'finished' + - `status`: 'downloading' | 'finished' | 'aborted' - `filename`: Nome del file in download. + - `opt`: Lista per delle opzioni aggiuntive. + - `'abort'`: Ferma forzatamente il download. ``` - return bool # File scaricato + return str # File scaricato ``` """ if title is None: title = self._defTitle else: title = self._sanitize(title) - return self._downloadIn(title,folder,hook) + return self._downloadIn(title,folder,hook=hook,opt=opt) class VVVVID(Server): # Protected @@ -360,7 +379,7 @@ def fileInfo(self) -> Dict[str,str]: return self._fileInfoEx() - def download(self, title: Optional[str]=None, folder: str='', hook: Callable[[Dict], None] = lambda *args:None) -> bool: + def download(self, title: Optional[str]=None, folder: str='', *, hook: Callable[[Dict], None]=lambda *args:None, opt: List[str]=[]) -> Optional[str]: """ Scarica l'episodio. @@ -373,16 +392,22 @@ def download(self, title: Optional[str]=None, folder: str='', hook: Callable[[Di - `speed`: Velocità di download (byte/s) - `elapsed`: Tempo trascorso dall'inizio del download. - `eta`: Tempo stimato rimanente per fine del download. - - `status`: 'downloading' | 'finished' + - `status`: 'downloading' | 'finished' | 'aborted' - `filename`: Nome del file in download. + - `opt`: Lista per delle opzioni aggiuntive. + - `'abort'`: Ferma forzatamente il download. ``` - return bool # File scaricato + return str # File scaricato ``` """ + + # TODO: Il download usando VVVVID non funziona don youtube-dl + raise ServerNotSupported(self.name) + if title is None: title = self._defTitle else: title = self._sanitize(title) - return self._dowloadEx(title,folder,hook) + return self._dowloadEx(title,folder,hook=hook,opt=opt) class YouTube(Server): @@ -423,7 +448,7 @@ def fileInfo(self) -> Dict[str,str]: return self._fileInfoEx() - def download(self, title: Optional[str]=None, folder: str='', hook: Callable[[Dict], None] = lambda *args:None) -> bool: + def download(self, title: Optional[str]=None, folder: str='', *, hook: Callable[[Dict], None]=lambda *args:None, opt: List[str]=[]) -> Optional[str]: """ Scarica l'episodio. @@ -436,16 +461,18 @@ def download(self, title: Optional[str]=None, folder: str='', hook: Callable[[Di - `speed`: Velocità di download (byte/s) - `elapsed`: Tempo trascorso dall'inizio del download. - `eta`: Tempo stimato rimanente per fine del download. - - `status`: 'downloading' | 'finished' + - `status`: 'downloading' | 'finished' | 'aborted' - `filename`: Nome del file in download. + - `opt`: Lista per delle opzioni aggiuntive. + - `'abort'`: Ferma forzatamente il download. ``` - return bool # File scaricato + return str # File scaricato ``` """ if title is None: title = self._defTitle else: title = self._sanitize(title) - return self._dowloadEx(title,folder,hook) + return self._dowloadEx(title,folder,hook=hook,opt=opt) class Streamtape(Server): # Protected @@ -489,7 +516,7 @@ def fileInfo(self) -> Dict[str,str]: return self._fileInfoIn() - def download(self, title: Optional[str]=None, folder: str='', hook: Callable[[Dict], None] = lambda *args:None) -> bool: + def download(self, title: Optional[str]=None, folder: str='', *, hook: Callable[[Dict], None]=lambda *args:None, opt: List[str]=[]) -> Optional[str]: """ Scarica l'episodio. @@ -502,13 +529,15 @@ def download(self, title: Optional[str]=None, folder: str='', hook: Callable[[Di - `speed`: Velocità di download (byte/s) - `elapsed`: Tempo trascorso dall'inizio del download. - `eta`: Tempo stimato rimanente per fine del download. - - `status`: 'downloading' | 'finished' + - `status`: 'downloading' | 'finished' | 'aborted' - `filename`: Nome del file in download. + - `opt`: Lista per delle opzioni aggiuntive. + - `'abort'`: Ferma forzatamente il download. ``` - return bool # File scaricato + return str # File scaricato ``` """ if title is None: title = self._defTitle else: title = self._sanitize(title) - return self._downloadIn(title,folder,hook) \ No newline at end of file + return self._downloadIn(title,folder,hook=hook,opt=opt) \ No newline at end of file diff --git a/documentation/example.py b/documentation/example.py index 0d809d8..8ecc18b 100644 --- a/documentation/example.py +++ b/documentation/example.py @@ -22,7 +22,7 @@ def my_hook(d): try: - anime = aw.Anime(link="https://www.animeworld.tv/play/summertime-render.GDU38") + anime = aw.Anime(link="https://www.animeworld.tv/play/summertime-render.GDU38/") print("Titolo:", anime.getName()) # Titolo dell'anime @@ -41,7 +41,7 @@ def my_hook(d): print("Episodi:") try: episodi = anime.getEpisodes() - except (aw.ServerNotSupported, aw.AnimeNotAvailable) as error: + except aw.AnimeNotAvailable as error: print("Errore:", error) else: for x in episodi: @@ -53,5 +53,5 @@ def my_hook(d): print("\n\tFile info: {\n\t\t" + "\n\t\t".join("{}: {}".format(k, v) for k, v in x.fileInfo().items()) + "\n\t}") x.download(hook=my_hook) break -except (aw.DeprecatedLibrary, aw.Error404) as error: +except (aw.DeprecatedLibrary, aw.Error404, aw.ServerNotSupported) as error: print(error) diff --git a/setup.py b/setup.py index cad96f6..08e6355 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="animeworld", - version="1.4.19", + version="1.4.20", author="MainKronos", description="AnimeWorld UNOFFICIAL API", long_description=long_description,