🚨 Updated lints (#308)

This commit is contained in:
Nikhil Badyal
2023-08-25 15:36:50 +05:30
committed by GitHub
parent 09b815cb21
commit 77377cdd48
26 changed files with 404 additions and 487 deletions
+1
View File
@@ -0,0 +1 @@
"""Downloader files."""
+25 -40
View File
@@ -1,5 +1,5 @@
"""Downloader Class."""
from typing import Any, Dict, Tuple
from typing import Any, Dict, Self, Tuple
import requests
from bs4 import BeautifulSoup, Tag
@@ -8,31 +8,29 @@ from loguru import logger
from src.app import APP
from src.downloader.download import Downloader
from src.downloader.sources import APK_MIRROR_BASE_URL
from src.exceptions import APKMirrorAPKDownloadFailure
from src.downloader.utils import status_code_200
from src.exceptions import APKMirrorAPKDownloadError
from src.utils import bs4_parser, contains_any_word, request_header
class ApkMirror(Downloader):
"""Files downloader."""
def _extract_force_download_link(self, link: str, app: str) -> Tuple[str, str]:
def _extract_force_download_link(self: Self, link: str, app: str) -> Tuple[str, str]:
"""Extract force download link."""
notes_divs = self._extracted_search_div(link, "tab-pane")
apk_type = self._extracted_search_div(link, "apkm-badge").get_text()
extension = "zip" if apk_type == "BUNDLE" else "apk"
possible_links = notes_divs.find_all("a")
for possible_link in possible_links:
if possible_link.get("href") and "download.php?id=" in possible_link.get(
"href"
):
if possible_link.get("href") and "download.php?id=" in possible_link.get("href"):
file_name = f"{app}.{extension}"
self._download(APK_MIRROR_BASE_URL + possible_link["href"], file_name)
return file_name, APK_MIRROR_BASE_URL + possible_link["href"]
raise APKMirrorAPKDownloadFailure(
f"Unable to extract force download for {app}", url=link
)
msg = f"Unable to extract force download for {app}"
raise APKMirrorAPKDownloadError(msg, url=link)
def extract_download_link(self, page: str, app: str) -> Tuple[str, str]:
def extract_download_link(self: Self, page: str, app: str) -> Tuple[str, str]:
"""Function to extract the download link from apkmirror html page.
:param page: Url of the page
@@ -45,19 +43,15 @@ class ApkMirror(Downloader):
(
download_link["href"]
for download_link in download_links
if download_link.get("href")
and "download/?key=" in download_link.get("href")
if download_link.get("href") and "download/?key=" in download_link.get("href")
),
None,
):
return self._extract_force_download_link(
APK_MIRROR_BASE_URL + final_download_link, app
)
raise APKMirrorAPKDownloadFailure(
f"Unable to extract link from {app} version list", url=page
)
return self._extract_force_download_link(APK_MIRROR_BASE_URL + final_download_link, app)
msg = f"Unable to extract link from {app} version list"
raise APKMirrorAPKDownloadError(msg, url=page)
def get_download_page(self, main_page: str) -> str:
def get_download_page(self: Self, main_page: str) -> str:
"""Function to get the download page in apk_mirror.
:param main_page: Main Download Page in APK mirror(Index)
@@ -77,26 +71,23 @@ class ApkMirror(Downloader):
links[apk_type] = f"{APK_MIRROR_BASE_URL}{sub_url}"
if preferred_link := links.get("APK", links.get("BUNDLE")):
return preferred_link
raise APKMirrorAPKDownloadFailure(
"Unable to extract download page", url=main_page
)
msg = "Unable to extract download page"
raise APKMirrorAPKDownloadError(msg, url=main_page)
@staticmethod
def _extracted_search_div(url: str, search_class: str) -> Tag:
"""Extract search div."""
r = requests.get(url, headers=request_header, timeout=60)
if r.status_code != 200:
raise APKMirrorAPKDownloadFailure(
f"Unable to connect with {url} on ApkMirror. Are you blocked by APKMirror or abused apkmirror "
f"?.Reason - {r.text}",
if r.status_code != status_code_200:
msg = f"Unable to connect with {url}. Are you blocked by APKMirror or abused apkmirror ?.Reason - {r.text}"
raise APKMirrorAPKDownloadError(
msg,
url=url,
)
soup = BeautifulSoup(r.text, bs4_parser)
return soup.find(class_=search_class)
return soup.find(class_=search_class) # type: ignore[return-value]
def specific_version(
self, app: APP, version: str, main_page: str = ""
) -> Tuple[str, str]:
def specific_version(self: Self, app: APP, version: str, main_page: str = "") -> Tuple[str, str]:
"""Function to download the specified version of app from apkmirror.
:param app: Name of the application
@@ -112,18 +103,14 @@ class ApkMirror(Downloader):
download_page = self.get_download_page(main_page)
return self.extract_download_link(download_page, app.app_name)
def latest_version(self, app: APP, **kwargs: Any) -> Tuple[str, str]:
"""Function to download whatever the latest version of app from
apkmirror.
def latest_version(self: Self, app: APP, **kwargs: Any) -> Tuple[str, str]:
"""Function to download whatever the latest version of app from apkmirror.
:param app: Name of the application
:return: Version of downloaded apk
"""
app_main_page = app.download_source
versions_div = self._extracted_search_div(
app_main_page, "listWidget p-relative"
)
versions_div = self._extracted_search_div(app_main_page, "listWidget p-relative")
app_rows = versions_div.find_all(class_="appRow")
version_urls = [
app_row.find(class_="downloadLink")["href"]
@@ -131,6 +118,4 @@ class ApkMirror(Downloader):
if "beta" not in app_row.find(class_="appRowTitle").get_text().lower()
and "alpha" not in app_row.find(class_="appRowTitle").get_text().lower()
]
return self.specific_version(
app, "latest", APK_MIRROR_BASE_URL + max(version_urls)
)
return self.specific_version(app, "latest", APK_MIRROR_BASE_URL + max(version_urls))
+3 -4
View File
@@ -1,5 +1,5 @@
"""APK Pure Downloader Class."""
from typing import Any, Tuple
from typing import Any, Self, Tuple
from src.app import APP
from src.downloader.download import Downloader
@@ -8,9 +8,8 @@ from src.downloader.download import Downloader
class ApkPure(Downloader):
"""Files downloader."""
def latest_version(self, app: APP, **kwargs: Any) -> Tuple[str, str]:
"""Function to download whatever the latest version of app from
apkmirror.
def latest_version(self: Self, app: APP, **kwargs: Any) -> Tuple[str, str]:
"""Function to download whatever the latest version of app from apkmirror.
:param app: Name of the application
:return: Version of downloaded apk
+9 -9
View File
@@ -1,38 +1,38 @@
"""APK SOS Downloader Class."""
from typing import Any, Tuple
from typing import Any, Self, Tuple
import requests
from bs4 import BeautifulSoup
from src.app import APP
from src.downloader.download import Downloader
from src.exceptions import APKSosAPKDownloadFailure
from src.exceptions import APKSosAPKDownloadError
from src.utils import bs4_parser, request_header
class ApkSos(Downloader):
"""Files downloader."""
def extract_download_link(self, page: str, app: str) -> Tuple[str, str]:
def extract_download_link(self: Self, page: str, app: str) -> Tuple[str, str]:
"""Function to extract the download link from apkmirror html page.
:param page: Url of the page
:param app: Name of the app
"""
r = requests.get(page, headers=request_header, allow_redirects=True)
r = requests.get(page, headers=request_header, allow_redirects=True, timeout=60)
soup = BeautifulSoup(r.text, bs4_parser)
download_button = soup.find(class_="col-sm-12 col-md-8 text-center")
possible_links = download_button.find_all("a")
possible_links = download_button.find_all("a") # type: ignore[union-attr]
for possible_link in possible_links:
if possible_link.get("href"):
file_name = f"{app}.apk"
self._download(possible_link["href"], file_name)
return file_name, possible_link["href"]
raise APKSosAPKDownloadFailure(f"Unable to download {app}", url=page)
msg = f"Unable to download {app}"
raise APKSosAPKDownloadError(msg, url=page)
def latest_version(self, app: APP, **kwargs: Any) -> Tuple[str, str]:
"""Function to download whatever the latest version of app from
apkmirror.
def latest_version(self: Self, app: APP, **kwargs: Any) -> Tuple[str, str]:
"""Function to download whatever the latest version of app from apkmirror.
:param app: Name of the application
:return: Version of downloaded apk
+16 -28
View File
@@ -4,7 +4,7 @@ import subprocess
from pathlib import Path
from queue import PriorityQueue
from time import perf_counter
from typing import Any, Tuple
from typing import Any, Self, Tuple
from loguru import logger
from tqdm import tqdm
@@ -12,35 +12,25 @@ from tqdm import tqdm
from src.app import APP
from src.config import RevancedConfig
from src.downloader.utils import implement_method
from src.exceptions import DownloadFailure
from src.exceptions import DownloadError
from src.utils import handle_request_response
class Downloader(object):
class Downloader:
"""Files downloader."""
def __init__(self, config: RevancedConfig):
def __init__(self: Self, config: RevancedConfig) -> None:
self._CHUNK_SIZE = 10485760
self._QUEUE: PriorityQueue[Tuple[float, str]] = PriorityQueue()
self._QUEUE_LENGTH = 0
self.config = config
@staticmethod
def file_status_check(file_name: Path, dry_run: bool, url: str) -> bool:
"""Check if file already exists."""
if os.path.exists(file_name) or dry_run:
logger.debug(
f"Skipping download of {file_name} from {url}. File already exists or dry running."
)
return True
return False
def _download(self, url: str, file_name: str) -> None:
def _download(self: Self, url: str, file_name: str) -> None:
if not url:
raise DownloadFailure("No url provided to download")
if self.file_status_check(
self.config.temp_folder.joinpath(file_name), self.config.dry_run, url
):
msg = "No url provided to download"
raise DownloadError(msg)
if self.config.dry_run or Path(file_name).exists():
logger.debug(f"Skipping download of {file_name} from {url}. File already exists or dry running.")
return
logger.info(f"Trying to download {file_name} from {url}")
self._QUEUE_LENGTH += 1
@@ -71,11 +61,11 @@ class Downloader(object):
self._QUEUE.put((perf_counter() - start, file_name))
logger.debug(f"Downloaded {file_name}")
def extract_download_link(self, page: str, app: str) -> Tuple[str, str]:
def extract_download_link(self: Self, page: str, app: str) -> Tuple[str, str]:
"""Extract download link from web page."""
raise NotImplementedError(implement_method)
def specific_version(self, app: APP, version: str) -> Tuple[str, str]:
def specific_version(self: Self, app: APP, version: str) -> Tuple[str, str]:
"""Function to download the specified version of app from apkmirror.
:param app: Name of the application
@@ -84,7 +74,7 @@ class Downloader(object):
"""
raise NotImplementedError(implement_method)
def latest_version(self, app: APP, **kwargs: Any) -> Tuple[str, str]:
def latest_version(self: Self, app: APP, **kwargs: Any) -> Tuple[str, str]:
"""Function to download the latest version of app.
:param app: Name of the application
@@ -92,7 +82,7 @@ class Downloader(object):
"""
raise NotImplementedError(implement_method)
def convert_to_apk(self, file_name: str) -> str:
def convert_to_apk(self: Self, file_name: str) -> str:
"""Convert apks to apk."""
if file_name.endswith(".apk"):
return file_name
@@ -122,7 +112,7 @@ class Downloader(object):
base_name, _ = os.path.splitext(filename)
return base_name + new_extension
def download(self, version: str, app: APP, **kwargs: Any) -> Tuple[str, str]:
def download(self: Self, version: str, app: APP, **kwargs: Any) -> Tuple[str, str]:
"""Public function to download apk to patch.
:param version: version to download
@@ -131,9 +121,7 @@ class Downloader(object):
if self.config.dry_run:
return "", ""
if app in self.config.existing_downloaded_apks:
logger.debug(
f"Will not download {app.app_name} -v{version} from the internet."
)
logger.debug(f"Will not download {app.app_name} -v{version} from the internet.")
return app.app_name, f"local://{app.app_name}"
if version and version != "latest":
file_name, app_dl = self.specific_version(app, version)
@@ -141,6 +129,6 @@ class Downloader(object):
file_name, app_dl = self.latest_version(app, **kwargs)
return self.convert_to_apk(file_name), app_dl
def direct_download(self, dl: str, file_name: str) -> None:
def direct_download(self: Self, dl: str, file_name: str) -> None:
"""Download from DL."""
self._download(dl, file_name)
+12 -17
View File
@@ -5,37 +5,32 @@ from src.downloader.apkpure import ApkPure
from src.downloader.apksos import ApkSos
from src.downloader.download import Downloader
from src.downloader.github import Github
from src.downloader.sources import (
APK_MIRROR_BASE_URL,
APK_PURE_BASE_URL,
APKS_SOS_BASE_URL,
GITHUB_BASE_URL,
)
from src.downloader.sources import APK_MIRROR_BASE_URL, APK_PURE_BASE_URL, APKS_SOS_BASE_URL, GITHUB_BASE_URL
from src.downloader.uptodown import UptoDown
from src.exceptions import DownloadFailure
from src.exceptions import DownloadError
class DownloaderFactory(object):
class DownloaderFactory:
"""Downloader Factory."""
@staticmethod
def create_downloader(config: RevancedConfig, apk_source: str) -> Downloader:
"""Returns appropriate downloader.
Parameters
----------
app : App Name
config : Config
apk_source : Source URL for APK
Args:
----
config : Config
apk_source : Source URL for APK
"""
if apk_source.startswith(GITHUB_BASE_URL):
return Github(config)
if apk_source.startswith(APK_PURE_BASE_URL):
return ApkPure(config)
elif apk_source.startswith(APKS_SOS_BASE_URL):
if apk_source.startswith(APKS_SOS_BASE_URL):
return ApkSos(config)
elif apk_source.endswith("en.uptodown.com/android"):
if apk_source.endswith("en.uptodown.com/android"):
return UptoDown(config)
elif apk_source.startswith(APK_MIRROR_BASE_URL):
if apk_source.startswith(APK_MIRROR_BASE_URL):
return ApkMirror(config)
raise DownloadFailure("No download factory found.")
msg = "No download factory found."
raise DownloadError(msg)
+9 -20
View File
@@ -1,6 +1,6 @@
"""Github Downloader."""
import re
from typing import Dict, Tuple
from typing import Dict, Self, Tuple
from urllib.parse import urlparse
import requests
@@ -9,23 +9,21 @@ from loguru import logger
from src.app import APP
from src.config import RevancedConfig
from src.downloader.download import Downloader
from src.exceptions import DownloadFailure
from src.exceptions import DownloadError
from src.utils import handle_request_response, update_changelog
class Github(Downloader):
"""Files downloader."""
def latest_version(self, app: APP, **kwargs: Dict[str, str]) -> Tuple[str, str]:
def latest_version(self: Self, app: APP, **kwargs: Dict[str, str]) -> Tuple[str, str]:
"""Function to download files from GitHub repositories.
:param app: App to download
"""
logger.debug(f"Trying to download {app.app_name} from github")
if self.config.dry_run:
logger.debug(
f"Skipping download of {app.app_name}. File already exists or dry running."
)
logger.debug(f"Skipping download of {app.app_name}. File already exists or dry running.")
return app.app_name, f"local://{app.app_name}"
owner = str(kwargs["owner"])
repo_name = str(kwargs["name"])
@@ -56,11 +54,7 @@ class Github(Downloader):
github_repo_name = path_segments[1]
release_tag = next(
(
f"tags/{path_segments[i + 1]}"
for i, segment in enumerate(path_segments)
if segment == "tag"
),
(f"tags/{path_segments[i + 1]}" for i, segment in enumerate(path_segments) if segment == "tag"),
"latest",
)
return github_repo_owner, github_repo_name, release_tag
@@ -86,9 +80,8 @@ class Github(Downloader):
try:
filter_pattern = re.compile(asset_filter)
except re.error as e:
raise DownloadFailure(
f"Invalid regex {asset_filter} pattern provided."
) from e
msg = f"Invalid regex {asset_filter} pattern provided."
raise DownloadError(msg) from e
for asset in assets:
assets_url = asset["browser_download_url"]
assets_name = asset["name"]
@@ -98,11 +91,7 @@ class Github(Downloader):
return ""
@staticmethod
def patch_resource(
repo_url: str, assets_filter: str, config: RevancedConfig
) -> str:
def patch_resource(repo_url: str, assets_filter: str, config: RevancedConfig) -> str:
"""Fetch patch resource from repo url."""
repo_owner, repo_name, tag = Github._extract_repo_owner_and_tag(repo_url)
return Github._get_release_assets(
repo_owner, repo_name, tag, assets_filter, config
)
return Github._get_release_assets(repo_owner, repo_name, tag, assets_filter, config)
+1
View File
@@ -1,3 +1,4 @@
"""APK Sources used."""
APK_MIRROR_BASE_URL = "https://www.apkmirror.com"
APK_MIRROR_BASE_APK_URL = f"{APK_MIRROR_BASE_URL}/apk"
UPTODOWN_BASE_URL = "https://{}.en.uptodown.com/android"
+23 -16
View File
@@ -1,5 +1,5 @@
"""Upto Down Downloader."""
from typing import Any, Tuple
from typing import Any, Self, Tuple
import requests
from bs4 import BeautifulSoup
@@ -7,27 +7,33 @@ from loguru import logger
from src.app import APP
from src.downloader.download import Downloader
from src.exceptions import UptoDownAPKDownloadFailure
from src.exceptions import UptoDownAPKDownloadError
from src.utils import bs4_parser, request_header
class UptoDown(Downloader):
"""Files downloader."""
def extract_download_link(self, page: str, app: str) -> Tuple[str, str]:
def extract_download_link(self: Self, page: str, app: str) -> Tuple[str, str]:
"""Extract download link from uptodown url."""
r = requests.get(page, headers=request_header, allow_redirects=True, timeout=60)
soup = BeautifulSoup(r.text, bs4_parser)
soup = soup.find(id="detail-download-button")
download_url = soup.get("data-url")
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:
raise UptoDownAPKDownloadFailure(
f"Unable to download {app} from uptodown.", url=page
)
msg = f"Unable to download {app} from uptodown."
raise UptoDownAPKDownloadError(msg, url=page)
file_name = f"{app}.apk"
self._download(download_url, file_name)
return file_name, download_url
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)
def specific_version(self, app: APP, version: str) -> Tuple[str, str]:
def specific_version(self: Self, app: APP, version: str) -> Tuple[str, str]:
"""Function to download the specified version of app from apkmirror.
:param app: Name of the application
@@ -40,17 +46,18 @@ class UptoDown(Downloader):
soup = BeautifulSoup(html, bs4_parser)
versions_list = soup.find("section", {"id": "versions"})
download_url = None
for version_item in versions_list.find_all("div", {"data-url": True}):
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"]
break
if download_url is None:
raise UptoDownAPKDownloadFailure(
f"Unable to download {app.app_name} from uptodown.", url=url
)
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, app: APP, **kwargs: Any) -> Tuple[str, str]:
def latest_version(self: Self, app: APP, **kwargs: Any) -> Tuple[str, str]:
"""Function to download the latest version of app from uptodown."""
logger.debug("downloading latest version of app from uptodown.")
page = f"{app.download_source}/download"
return self.extract_download_link(page, app.app_name)
+1 -1
View File
@@ -1,4 +1,4 @@
"""Utility class."""
implement_method = "Please implement the method"
status_code_200 = 200