From 9ee7adef52bc9f04453623ad357786ae077c1d79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vi=E1=BB=87t=20Hu=E1=BB=B3nh?= Date: Mon, 11 Dec 2023 19:37:35 +0700 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fix=20Uptodown=20downloader=20(#?= =?UTF-8?q?415)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/downloader/uptodown.py | 64 +++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/src/downloader/uptodown.py b/src/downloader/uptodown.py index 89944dd..79668dc 100644 --- a/src/downloader/uptodown.py +++ b/src/downloader/uptodown.py @@ -2,13 +2,13 @@ from typing import Any, Self import requests -from bs4 import BeautifulSoup +from bs4 import BeautifulSoup, Tag from loguru import logger from src.app import APP from src.downloader.download import Downloader from src.exceptions import UptoDownAPKDownloadError -from src.utils import bs4_parser, handle_request_response, request_header, request_timeout, session +from src.utils import bs4_parser, handle_request_response, request_header, request_timeout class UptoDown(Downloader): @@ -18,24 +18,24 @@ class UptoDown(Downloader): """Extract download link from uptodown url.""" r = requests.get(page, headers=request_header, allow_redirects=True, timeout=request_timeout) handle_request_response(r, page) - soup = BeautifulSoup(r.text, bs4_parser) - download_button = soup.find(id="detail-download-button") - if not download_button: - msg = f"Unable to download {app} from uptodown." - raise UptoDownAPKDownloadError(msg, url=page) - download_url = download_button.get("data-url") # type: ignore[union-attr] - if not download_url: + download_page_url = page.replace("/download", "/post-download") + download_page_html = requests.get(download_page_url, headers=request_header, timeout=request_timeout).text + soup = BeautifulSoup(download_page_html, bs4_parser) + post_download = soup.find("div", class_="post-download") + + if not isinstance(post_download, Tag): msg = f"Unable to download {app} from uptodown." raise UptoDownAPKDownloadError(msg, url=page) + + data_url = post_download.get("data-url") + download_url = f"https://dw.uptodown.com/dwn/{data_url}" file_name = f"{app}.apk" - if isinstance(download_url, str): - self._download(download_url, file_name) - return file_name, download_url - msg = f"Unable to download {app} from uptodown." - raise UptoDownAPKDownloadError(msg, url=page) + self._download(download_url, file_name) + + return file_name, download_url def specific_version(self: Self, app: APP, version: str) -> tuple[str, str]: - """Function to download the specified version of app from apkmirror. + """Function to download the specified version of app from uptodown. :param app: Name of the application :param version: Version of the application to download @@ -43,18 +43,40 @@ class UptoDown(Downloader): """ logger.debug("downloading specified version of app from uptodown.") url = f"{app.download_source}/versions" - html = session.get(url).text + html = requests.get(url, headers=request_header, timeout=request_timeout).text soup = BeautifulSoup(html, bs4_parser) - versions_list = soup.find("section", {"id": "versions"}) + detail_app_name = soup.find("h1", id="detail-app-name") + + if not isinstance(detail_app_name, Tag): + msg = f"Unable to download {app} from uptodown." + raise UptoDownAPKDownloadError(msg, url=url) + + app_code = detail_app_name.get("code") + version_page = 1 download_url = None - for version_item in versions_list.find_all("div", {"data-url": True}): # type: ignore[union-attr] - extracted_version = version_item.find("span", {"class": "version"}).text - if extracted_version == version: - download_url = version_item["data-url"] + version_found = False + + while not version_found: + version_url = f"{app.download_source}/apps/{app_code}/versions/{version_page}" + r = requests.get(version_url, timeout=request_timeout) + handle_request_response(r, version_url) + json = r.json() + + if "data" not in json: break + + for item in json["data"]: + if item["version"] == version: + download_url = item["versionURL"] + version_found = True + break + + version_page += 1 + if download_url is None: msg = f"Unable to download {app.app_name} from uptodown." raise UptoDownAPKDownloadError(msg, url=url) + return self.extract_download_link(download_url, app.app_name) def latest_version(self: Self, app: APP, **kwargs: Any) -> tuple[str, str]: