From 02e550585ca84a35b940fb948db83d8b09dea59e Mon Sep 17 00:00:00 2001 From: Nikhil Badyal <59223300+nikhilbadyal@users.noreply.github.com> Date: Thu, 17 Aug 2023 21:09:42 +0530 Subject: [PATCH] =?UTF-8?q?=F0=9F=A5=85=20Exception=20handling=20(#290)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.py | 4 +-- scripts/status_check.py | 2 +- src/downloader/apkmirror.py | 22 +++++++++---- src/downloader/apkpure.py | 10 ++---- src/downloader/apksos.py | 4 +-- src/downloader/download.py | 4 +-- src/downloader/github.py | 6 ++-- src/downloader/uptodown.py | 10 ++++-- src/exceptions.py | 66 +++++++++++++++++++++++++++++++++++-- src/patches.py | 8 ++--- src/utils.py | 4 +-- 11 files changed, 105 insertions(+), 35 deletions(-) diff --git a/main.py b/main.py index d43d01d..bdbf950 100644 --- a/main.py +++ b/main.py @@ -6,7 +6,7 @@ from loguru import logger from src.config import RevancedConfig from src.downloader.factory import DownloaderFactory -from src.exceptions import AppNotFound, PatchesJsonFailed, PatchingFailed +from src.exceptions import AppNotFound, PatchesJsonLoadFailed, PatchingFailed from src.parser import Parser from src.patches import Patches from src.utils import check_java, extra_downloads @@ -38,7 +38,7 @@ def main() -> None: parser.patch_app(app) except AppNotFound as e: logger.info(f"Invalid app requested to build {e}") - except PatchesJsonFailed: + except PatchesJsonLoadFailed: logger.exception("Patches.json not found") except PatchingFailed as e: logger.exception(e) diff --git a/scripts/status_check.py b/scripts/status_check.py index eaa6d35..e05817b 100644 --- a/scripts/status_check.py +++ b/scripts/status_check.py @@ -93,7 +93,7 @@ def generate_markdown_table(data: List[List[str]]) -> str: ) for row in data: if len(row) != 6: - raise ValueError("Each row must contain 4 columns of data.") + raise ValueError("Each row must contain 6 columns of data.") table += f"| {row[0]} | {row[1]} | {row[2]} | {row[3]} |{row[4]} |{row[5]} |\n" diff --git a/src/downloader/apkmirror.py b/src/downloader/apkmirror.py index 667ea7c..5759fcf 100644 --- a/src/downloader/apkmirror.py +++ b/src/downloader/apkmirror.py @@ -7,7 +7,7 @@ from loguru import logger from scripts.status_check import headers from src.downloader.download import Downloader -from src.exceptions import AppNotFound +from src.exceptions import APKMirrorAPKDownloadFailure, APKMirrorAPKNotFound from src.utils import apkmirror_status_check, bs4_parser @@ -25,7 +25,9 @@ class ApkMirror(Downloader): return self._download( self.config.apk_mirror + possible_link["href"], f"{app}.apk" ) - raise AppNotFound(f"Unable to download apk from {link}") + raise APKMirrorAPKDownloadFailure( + f"Unable to extract force download for {app}", url=link + ) def extract_download_link(self, main_page: str, app: str) -> None: """Function to extract the download link from apkmirror html page. @@ -49,7 +51,9 @@ class ApkMirror(Downloader): self.config.apk_mirror + final_download_link, app ) else: - raise AppNotFound(f"Unable to download apk from {main_page}") + raise APKMirrorAPKDownloadFailure( + f"Unable to extract link from {app} version list", url=main_page + ) def get_download_page(self, main_page: str) -> str: """Function to get the download page in apk_mirror. @@ -67,7 +71,9 @@ class ApkMirror(Downloader): sub_url = row.find(class_="accent_color")["href"] break if not sub_url: - raise AppNotFound("Unable to download apk from APKMirror.") + raise APKMirrorAPKDownloadFailure( + "Unable to extract download page", url=main_page + ) return f"{self.config.apk_mirror}{sub_url}" @staticmethod @@ -75,7 +81,11 @@ class ApkMirror(Downloader): """Extract search div.""" r = requests.get(url, headers=headers) if r.status_code != 200: - raise AppNotFound(f"Unable to connect with {url} on ApkMirror.") + raise APKMirrorAPKDownloadFailure( + f"Unable to connect with {url} on ApkMirror. Are you blocked by APKMirror or abused apkmirror " + f"?.Reason - {r.text}", + url=url, + ) soup = BeautifulSoup(r.text, bs4_parser) return soup.find(class_=search_class) @@ -108,4 +118,4 @@ class ApkMirror(Downloader): f"Trying to download {app}'s latest version({version}) from apkmirror" ) return self.specific_version(app, version) - raise AppNotFound("App not found on apkmirror.") + raise APKMirrorAPKNotFound("App not found on apkmirror.") diff --git a/src/downloader/apkpure.py b/src/downloader/apkpure.py index 5fa3f77..b771613 100644 --- a/src/downloader/apkpure.py +++ b/src/downloader/apkpure.py @@ -4,7 +4,7 @@ from typing import Any from loguru import logger from src.downloader.download import Downloader -from src.exceptions import AppNotFound +from src.patches import Patches class ApkPure(Downloader): @@ -17,13 +17,7 @@ class ApkPure(Downloader): :param app: Name of the application :return: Version of downloaded apk """ - package_name = None - for package, app_tuple in self.patcher.revanced_app_ids.items(): - if app_tuple[0] == app: - package_name = package - if not package_name: - logger.info("Unable to download from apkpure") - raise AppNotFound() + package_name = Patches.get_package_name(app) download_url = f"https://d.apkpure.com/b/APK/{package_name}?version=latest" self._download(download_url, f"{app}.apk") logger.debug(f"Downloaded {app} apk from apk_pure_downloader in rt") diff --git a/src/downloader/apksos.py b/src/downloader/apksos.py index 7848d12..465b463 100644 --- a/src/downloader/apksos.py +++ b/src/downloader/apksos.py @@ -6,7 +6,7 @@ from bs4 import BeautifulSoup from scripts.status_check import headers from src.downloader.download import Downloader -from src.exceptions import AppNotFound +from src.exceptions import APKSosAPKDownloadFailure from src.utils import bs4_parser @@ -26,7 +26,7 @@ class ApkSos(Downloader): for possible_link in possible_links: if possible_link.get("href"): return self._download(possible_link["href"], f"{app}.apk") - raise AppNotFound("Unable to download apk from apk_combo") + raise APKSosAPKDownloadFailure(f"Unable to download {app}", url=page) def latest_version(self, app: str, **kwargs: Any) -> None: """Function to download whatever the latest version of app from diff --git a/src/downloader/download.py b/src/downloader/download.py index c0e560b..82e0897 100644 --- a/src/downloader/download.py +++ b/src/downloader/download.py @@ -10,7 +10,7 @@ from tqdm import tqdm from src.config import RevancedConfig from src.downloader.utils import implement_method -from src.exceptions import PatchingFailed +from src.exceptions import DownloadFailure from src.patches import Patches from src.utils import handle_github_response @@ -37,7 +37,7 @@ class Downloader(object): def _download(self, url: str, file_name: str) -> None: if not url: - raise PatchingFailed("No download to download") + raise DownloadFailure("No url provided to download") if self.file_status_check( self.config.temp_folder.joinpath(file_name), self.config.dry_run, url ): diff --git a/src/downloader/github.py b/src/downloader/github.py index 6321940..ff3af41 100644 --- a/src/downloader/github.py +++ b/src/downloader/github.py @@ -8,7 +8,7 @@ from loguru import logger from src.config import RevancedConfig from src.downloader.download import Downloader -from src.exceptions import PatchingFailed +from src.exceptions import DownloadFailure from src.utils import handle_github_response, update_changelog @@ -84,7 +84,9 @@ class Github(Downloader): try: filter_pattern = re.compile(asset_filter) except re.error as e: - raise PatchingFailed("Invalid regex pattern provided.") from e + raise DownloadFailure( + f"Invalid regex {asset_filter} pattern provided." + ) from e for asset in assets: assets_url = asset["browser_download_url"] assets_name = asset["name"] diff --git a/src/downloader/uptodown.py b/src/downloader/uptodown.py index 30d8240..9587fd4 100644 --- a/src/downloader/uptodown.py +++ b/src/downloader/uptodown.py @@ -7,7 +7,7 @@ from loguru import logger from scripts.status_check import headers from src.downloader.download import Downloader -from src.exceptions import AppNotFound +from src.exceptions import UptoDownAPKDownloadFailure from src.utils import bs4_parser @@ -20,7 +20,9 @@ class UptoDown(Downloader): soup = soup.find(id="detail-download-button") download_url = soup.get("data-url") if not download_url: - raise AppNotFound("Unable to download from uptodown.") + raise UptoDownAPKDownloadFailure( + f"Unable to download {app} from uptodown.", url=page + ) self._download(download_url, f"{app}.apk") logger.debug(f"Downloaded {app} apk from upto_down_downloader in rt") @@ -45,7 +47,9 @@ class UptoDown(Downloader): download_url = version_item["data-url"] break if download_url is None: - raise AppNotFound(f"Unable to get download url for {app}") + raise UptoDownAPKDownloadFailure( + f"Unable to download {app} from uptodown.", url=url + ) self.extract_download_link(download_url, app) logger.debug(f"Downloaded {app} apk from upto_down_downloader in rt") diff --git a/src/exceptions.py b/src/exceptions.py index 035be80..475ba1e 100644 --- a/src/exceptions.py +++ b/src/exceptions.py @@ -16,6 +16,57 @@ class APKMirrorIconScrapFailure(Exception): self.url = kwargs.get("url", None) +class DownloadFailure(Exception): + """Generic Download failure.""" + + def __init__(self, *args: Any, **kwargs: Any) -> None: + """Initialize the APKMirrorAPKDownloadFailure exception. + + Args: + *args: Variable length argument list. + **kwargs: Arbitrary keyword arguments. + url (str, optional): The URL of the failed icon scraping. Defaults to None. + """ + super().__init__(*args) + self.url = kwargs.get("url", None) + + +class APKDownloadFailure(DownloadFailure): + """Exception raised when the apk cannot be scraped.""" + + pass + + +class APKMirrorAPKDownloadFailure(APKDownloadFailure): + """Exception raised when downloading an APK from apkmirror failed.""" + + pass + + +class APKMirrorAPKNotFound(APKDownloadFailure): + """Exception raised when apk doesn't exist on APKMirror.""" + + pass + + +class UptoDownAPKDownloadFailure(APKDownloadFailure): + """Exception raised when downloading an APK from uptodown failed.""" + + pass + + +class APKPureAPKDownloadFailure(APKDownloadFailure): + """Exception raised when downloading an APK from apkpure failed.""" + + pass + + +class APKSosAPKDownloadFailure(APKDownloadFailure): + """Exception raised when downloading an APK from apksos failed.""" + + pass + + class PatchingFailed(Exception): """Patching Failed.""" @@ -28,7 +79,16 @@ class AppNotFound(ValueError): pass -class PatchesJsonFailed(ValueError): - """Patches failed.""" +class PatchesJsonLoadFailed(ValueError): + """Failed to load patches json.""" - pass + def __init__(self, *args: Any, **kwargs: Any) -> None: + """Initialize the PatchesJsonLoadFailed exception. + + Args: + *args: Variable length argument list. + **kwargs: Arbitrary keyword arguments. + file_name (str, optional): The name of json file. Defaults to None. + """ + super().__init__(*args) + self.file_name = kwargs.get("file_name", None) diff --git a/src/patches.py b/src/patches.py index af82134..952bf8c 100644 --- a/src/patches.py +++ b/src/patches.py @@ -8,7 +8,7 @@ from loguru import logger from src.app import APP from src.config import RevancedConfig -from src.exceptions import AppNotFound, PatchesJsonFailed +from src.exceptions import AppNotFound, PatchesJsonLoadFailed class Patches(object): @@ -66,7 +66,7 @@ class Patches(object): for package, app_tuple in Patches.revanced_app_ids.items(): if app_tuple[0] == app: return package - raise AppNotFound("App Not Found.") + raise AppNotFound(f"App {app} not supported yet.") @staticmethod def support_app() -> Dict[str, str]: @@ -113,7 +113,7 @@ class Patches(object): app_names = {value[0]: value[1] for value in self.revanced_app_ids.values()} if not (app_name := app_names.get(app)): - raise AppNotFound(f"App '{app}' not found in the supported apps.") + raise AppNotFound(f"App {app} not supported yet.") patches = getattr(self, app_name) version = "latest" @@ -176,4 +176,4 @@ class PatchLoader: patches = json.load(f) return patches except FileNotFoundError as e: - raise PatchesJsonFailed() from e + raise PatchesJsonLoadFailed("File not found", file_name=file_name) from e diff --git a/src/utils.py b/src/utils.py index 6cb6038..e4b3ee3 100644 --- a/src/utils.py +++ b/src/utils.py @@ -9,7 +9,7 @@ from loguru import logger from requests import Response from src.config import RevancedConfig -from src.exceptions import PatchingFailed +from src.exceptions import DownloadFailure default_build = [ "youtube", @@ -71,7 +71,7 @@ def handle_github_response(response: Response) -> None: """Handle Get Request Response.""" response_code = response.status_code if response_code != 200: - raise PatchingFailed( + raise DownloadFailure( f"Unable to downloaded assets from GitHub. Reason - {response.text}" )