diff --git a/src/downloader/apkpure.py b/src/downloader/apkpure.py index c0a5028..8102200 100644 --- a/src/downloader/apkpure.py +++ b/src/downloader/apkpure.py @@ -97,28 +97,52 @@ class ApkPure(Downloader): return file_name, app_dl def specific_version(self: Self, app: APP, version: str) -> tuple[str, str]: - """Function to download the specified version of app from apkpure. + """ + Downloads the specified version of an app from APKPure. - :param app: Name of the application - :param version: Version of the application to download - :return: Tuple of filename and app direct download link + Parameters + ---------- + app : APP + The application object containing metadata. + version : str + The specific version of the application to download. + + Returns + ------- + tuple[str, str] + A tuple containing: + - The filename of the downloaded APK. + - The direct download link of the APK. + + Raises + ------ + APKPureAPKDownloadError + If the specified version is not found. """ self.global_archs_priority = tuple(self._sort_by_priority(app.archs_to_build)) - version_page = app.download_source + "/versions" - r = requests.get(version_page, headers=request_header, timeout=request_timeout) - handle_request_response(r, version_page) - soup = BeautifulSoup(r.text, bs4_parser) - version_box_list = soup.select("ul.ver-wrap > *") - for box in version_box_list: - if ( - (_data := box.select_one("a.ver_download_link")) - and (found_version := _data.get("data-dt-version")) - and found_version == version - ): - download_page = _data.get("href") - file_name, download_source = self.extract_download_link(download_page, app.app_name) # type: ignore # noqa: PGH003 + version_page = f"{app.download_source}/versions" + + response = requests.get(version_page, headers=request_header, timeout=request_timeout) + handle_request_response(response, version_page) + + soup = BeautifulSoup(response.text, bs4_parser) + + for box in soup.select("ul.ver-wrap > *"): + download_link = box.select_one("a.ver_download_link") + if not download_link: + continue + + found_version = download_link.get("data-dt-version") + if found_version == version: + download_page = download_link.get("href") + file_name, download_source = self.extract_download_link( + str(download_page), + app.app_name, + ) + app.app_version = self.app_version logger.info(f"Guessed {app.app_version} for {app.app_name}") + self._download(download_source, file_name) return file_name, download_source msg = f"Unable to find specific version '{version}' for {app} from version list" diff --git a/src/downloader/download.py b/src/downloader/download.py index b3a4059..e5ccbe1 100644 --- a/src/downloader/download.py +++ b/src/downloader/download.py @@ -24,6 +24,8 @@ class Downloader(object): self._QUEUE: PriorityQueue[tuple[float, str]] = PriorityQueue() self._QUEUE_LENGTH = 0 self.config = config + self.global_archs_priority: Any = None + self.app_version: Any = None def _download(self: Self, url: str, file_name: str) -> None: if not url: diff --git a/src/parser.py b/src/parser.py index 8affeab..d553fa5 100644 --- a/src/parser.py +++ b/src/parser.py @@ -37,8 +37,6 @@ class Parser(object): Parameters ---------- - name : str - The `name` parameter is a string that represents the name of the patch to be included. opt : dict[str, Any] The `opt` parameter is a dictionary that represents the key-value pair of options of the patch to be included. @@ -91,7 +89,7 @@ class Parser(object): return self._EXCLUDED def get_all_patches(self: Self) -> list[str]: - """The function "get_all_patches" is a getter method that returns a ist of all patches. + """The function "get_all_patches" is a getter method that returns the list of all patches. Returns ------- @@ -222,8 +220,8 @@ class Parser(object): app.get_output_file_name(), self.KEYSTORE_ARG, app.keystore_name, + exp, ] - args.append(exp) args[1::2] = map(self.config.temp_folder.joinpath, args[1::2]) if app.old_key: # https://github.com/ReVanced/revanced-cli/issues/272#issuecomment-1740587534 diff --git a/src/patches.py b/src/patches.py index 55f4fbe..b781808 100644 --- a/src/patches.py +++ b/src/patches.py @@ -150,25 +150,27 @@ class Patches(object): self.fetch_patches(config, app) def get(self: Self, app: str) -> tuple[list[dict[str, str]], str]: - """The function `get` returns all patches and version for a given application. + """ + Returns all patches and the latest version for a given application. Parameters ---------- app : str - The `app` parameter is a string that represents the name of the application for which you want - to retrieve patches. + The name of the application for which patches need to be retrieved. Returns ------- - a tuple containing two elements. The first element is a list of dictionaries representing - patches for the given app. The second element is a string representing the version of the - patches. + tuple[list[dict[str, str]], str] + A tuple containing: + - A list of dictionaries representing patches for the given app. + - A string representing the latest version of the patches. """ patches = self.patches_dict[app] - version = "latest" + with contextlib.suppress(StopIteration): - version = next(i["version"] for i in patches if i["version"] != "all") - return patches, version + return patches, next(i["version"] for i in patches if i["version"] != "all") + + return patches, "latest" def get_app_configs(self: Self, app: "APP") -> list[dict[str, str]]: """The function `get_app_configs` returns configurations for a given app.