🎨 Merge APKM bundles to get apk for patching (#297)

This commit is contained in:
Nikhil Badyal
2023-08-22 11:05:01 +00:00
committed by GitHub
parent 4e22efda31
commit 70dbea76c9
15 changed files with 148 additions and 108 deletions
-2
View File
@@ -13,8 +13,6 @@ concurrency:
jobs: jobs:
build-apk-pr-check: build-apk-pr-check:
uses: ./.github/workflows/build-artifact.yml uses: ./.github/workflows/build-artifact.yml
with:
FILES_TO_EXPECT: 2
secrets: secrets:
ENVS: | ENVS: |
CI_TEST=True CI_TEST=True
+1
View File
@@ -9,3 +9,4 @@ changelog.md
.idea .idea
*.json *.json
status.md status.md
*.zip
+1 -1
View File
@@ -34,7 +34,7 @@ def main() -> None:
downloader = DownloaderFactory.create_downloader( downloader = DownloaderFactory.create_downloader(
app=app.app_name, patcher=patcher, config=config app=app.app_name, patcher=patcher, config=config
) )
downloader.download(app.app_version, app.app_name) app.download_file_name = downloader.download(app.app_version, app.app_name)
parser.patch_app(app) parser.patch_app(app)
except AppNotFound as e: except AppNotFound as e:
logger.info(f"Invalid app requested to build {e}") logger.info(f"Invalid app requested to build {e}")
+1 -1
View File
@@ -48,7 +48,7 @@ def apkmirror_scrapper(package_name: str) -> str:
def _extracted_from_apkmirror_scrapper(search_url: str) -> str: def _extracted_from_apkmirror_scrapper(search_url: str) -> str:
r = requests.get(search_url, headers=headers, timeout=10) r = requests.get(search_url, headers=headers, timeout=60)
soup = BeautifulSoup(r.text, bs4_parser) soup = BeautifulSoup(r.text, bs4_parser)
sub_url = soup.select_one("div.bubble-wrap > img")["src"] sub_url = soup.select_one("div.bubble-wrap > img")["src"]
new_width = 500 new_width = 500
+1
View File
@@ -39,6 +39,7 @@ class APP(object):
self.archs_to_build = config.env.list( self.archs_to_build = config.env.list(
f"{app_name}_ARCHS_TO_BUILD".upper(), config.global_archs_to_build f"{app_name}_ARCHS_TO_BUILD".upper(), config.global_archs_to_build
) )
self.download_file_name = None
self.download_patch_resources(config) self.download_patch_resources(config)
def get_output_file_name(self) -> str: def get_output_file_name(self) -> str:
+5 -3
View File
@@ -5,8 +5,6 @@ from typing import List
from environs import Env from environs import Env
from requests import Session from requests import Session
from src.downloader.sources import apk_sources
default_cli = "https://github.com/revanced/revanced-cli/releases/latest" default_cli = "https://github.com/revanced/revanced-cli/releases/latest"
default_patches = "https://github.com/revanced/revanced-patches/releases/latest" default_patches = "https://github.com/revanced/revanced-patches/releases/latest"
default_patches_json = default_patches default_patches_json = default_patches
@@ -28,7 +26,7 @@ class RevancedConfig(object):
self.ci_test = env.bool("CI_TEST", False) self.ci_test = env.bool("CI_TEST", False)
self.apps = env.list( self.apps = env.list(
"PATCH_APPS", "PATCH_APPS",
list(apk_sources.keys()) if self.ci_test else default_build, default_build,
) )
self.rip_libs_apps: List[str] = [] self.rip_libs_apps: List[str] = []
self.existing_downloaded_apks = env.list("EXISTING_DOWNLOADED_APKS", []) self.existing_downloaded_apks = env.list("EXISTING_DOWNLOADED_APKS", [])
@@ -47,3 +45,7 @@ class RevancedConfig(object):
) )
self.global_archs_to_build = env.list("GLOBAL_ARCHS_TO_BUILD", []) self.global_archs_to_build = env.list("GLOBAL_ARCHS_TO_BUILD", [])
self.extra_download_files: List[str] = env.list("EXTRA_FILES", []) self.extra_download_files: List[str] = env.list("EXTRA_FILES", [])
self.apk_editor = "apkeditor-output.jar"
self.extra_download_files.append(
"https://github.com/REAndroid/APKEditor@apkeditor.jar"
)
+32 -32
View File
@@ -1,5 +1,5 @@
"""Downloader Class.""" """Downloader Class."""
from typing import Any from typing import Any, Dict
import requests import requests
from bs4 import BeautifulSoup, Tag from bs4 import BeautifulSoup, Tag
@@ -9,35 +9,37 @@ from scripts.status_check import headers
from src.downloader.download import Downloader from src.downloader.download import Downloader
from src.downloader.sources import APK_MIRROR_BASE_URL, apk_sources from src.downloader.sources import APK_MIRROR_BASE_URL, apk_sources
from src.exceptions import APKMirrorAPKDownloadFailure from src.exceptions import APKMirrorAPKDownloadFailure
from src.utils import bs4_parser from src.utils import bs4_parser, contains_any_word
class ApkMirror(Downloader): class ApkMirror(Downloader):
"""Files downloader.""" """Files downloader."""
def _extract_force_download_link(self, link: str, app: str) -> None: def _extract_force_download_link(self, link: str, app: str) -> str:
"""Extract force download link.""" """Extract force download link."""
notes_divs = self._extracted_search_div(link, "tab-pane") 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") possible_links = notes_divs.find_all("a")
for possible_link in possible_links: for possible_link in possible_links:
if possible_link.get("href") and "download.php?id=" in possible_link.get( if possible_link.get("href") and "download.php?id=" in possible_link.get(
"href" "href"
): ):
return self._download( file_name = f"{app}.{extension}"
APK_MIRROR_BASE_URL + possible_link["href"], f"{app}.apk" self._download(APK_MIRROR_BASE_URL + possible_link["href"], file_name)
) return file_name
raise APKMirrorAPKDownloadFailure( raise APKMirrorAPKDownloadFailure(
f"Unable to extract force download for {app}", url=link f"Unable to extract force download for {app}", url=link
) )
def extract_download_link(self, main_page: str, app: str) -> None: def extract_download_link(self, page: str, app: str) -> str:
"""Function to extract the download link from apkmirror html page. """Function to extract the download link from apkmirror html page.
:param main_page: Url of the page :param page: Url of the page
:param app: Name of the app :param app: Name of the app
""" """
logger.debug(f"Extracting download link from\n{main_page}") logger.debug(f"Extracting download link from\n{page}")
download_button = self._extracted_search_div(main_page, "center") download_button = self._extracted_search_div(page, "center")
download_links = download_button.find_all("a") download_links = download_button.find_all("a")
if final_download_link := next( if final_download_link := next(
( (
@@ -48,13 +50,12 @@ class ApkMirror(Downloader):
), ),
None, None,
): ):
self._extract_force_download_link( return self._extract_force_download_link(
APK_MIRROR_BASE_URL + final_download_link, app APK_MIRROR_BASE_URL + final_download_link, app
) )
else: raise APKMirrorAPKDownloadFailure(
raise APKMirrorAPKDownloadFailure( f"Unable to extract link from {app} version list", url=page
f"Unable to extract link from {app} version list", url=main_page )
)
def get_download_page(self, main_page: str) -> str: def get_download_page(self, main_page: str) -> str:
"""Function to get the download page in apk_mirror. """Function to get the download page in apk_mirror.
@@ -64,27 +65,26 @@ class ApkMirror(Downloader):
""" """
list_widget = self._extracted_search_div(main_page, "listWidget") list_widget = self._extracted_search_div(main_page, "listWidget")
table_rows = list_widget.find_all(class_="table-row") table_rows = list_widget.find_all(class_="table-row")
sub_url = None links: Dict[str, str] = {}
apk_archs = ["arm64-v8a", "universal", "noarch"]
for row in table_rows: for row in table_rows:
if row.find(class_="accent_color"): if row.find(class_="accent_color"):
apk_type = row.find(class_="apkm-badge").get_text() apk_type = row.find(class_="apkm-badge").get_text()
if apk_type == "APK" and ( sub_url = row.find(class_="accent_color")["href"]
"arm64-v8a" in row.text.strip() text = row.text.strip()
or "universal" in row.text.strip() if apk_type == "APK" and (not contains_any_word(text, apk_archs)):
or "noarch" in row.text.strip() continue
): links[apk_type] = f"{APK_MIRROR_BASE_URL}{sub_url}"
sub_url = row.find(class_="accent_color")["href"] if preferred_link := links.get("APK", links.get("BUNDLE")):
break return preferred_link
if not sub_url: raise APKMirrorAPKDownloadFailure(
raise APKMirrorAPKDownloadFailure( "Unable to extract download page", url=main_page
"Unable to extract download page", url=main_page )
)
return f"{APK_MIRROR_BASE_URL}{sub_url}"
@staticmethod @staticmethod
def _extracted_search_div(url: str, search_class: str) -> Tag: def _extracted_search_div(url: str, search_class: str) -> Tag:
"""Extract search div.""" """Extract search div."""
r = requests.get(url, headers=headers, timeout=10) r = requests.get(url, headers=headers, timeout=60)
if r.status_code != 200: if r.status_code != 200:
raise APKMirrorAPKDownloadFailure( raise APKMirrorAPKDownloadFailure(
f"Unable to connect with {url} on ApkMirror. Are you blocked by APKMirror or abused apkmirror " f"Unable to connect with {url} on ApkMirror. Are you blocked by APKMirror or abused apkmirror "
@@ -94,7 +94,7 @@ class ApkMirror(Downloader):
soup = BeautifulSoup(r.text, bs4_parser) soup = BeautifulSoup(r.text, bs4_parser)
return soup.find(class_=search_class) return soup.find(class_=search_class)
def specific_version(self, app: str, version: str, main_page: str = "") -> None: def specific_version(self, app: str, version: str, main_page: str = "") -> str:
"""Function to download the specified version of app from apkmirror. """Function to download the specified version of app from apkmirror.
:param app: Name of the application :param app: Name of the application
@@ -108,9 +108,9 @@ class ApkMirror(Downloader):
version_page = apk_main_page + apk_main_page.split("/")[-2] version_page = apk_main_page + apk_main_page.split("/")[-2]
main_page = f"{version_page}-{version}-release/" main_page = f"{version_page}-{version}-release/"
download_page = self.get_download_page(main_page) download_page = self.get_download_page(main_page)
self.extract_download_link(download_page, app) return self.extract_download_link(download_page, app)
def latest_version(self, app: str, **kwargs: Any) -> None: def latest_version(self, app: str, **kwargs: Any) -> str:
"""Function to download whatever the latest version of app from """Function to download whatever the latest version of app from
apkmirror. apkmirror.
+4 -5
View File
@@ -1,8 +1,6 @@
"""APK Pure Downloader Class.""" """APK Pure Downloader Class."""
from typing import Any from typing import Any
from loguru import logger
from src.downloader.download import Downloader from src.downloader.download import Downloader
from src.downloader.sources import apk_sources from src.downloader.sources import apk_sources
from src.patches import Patches from src.patches import Patches
@@ -11,7 +9,7 @@ from src.patches import Patches
class ApkPure(Downloader): class ApkPure(Downloader):
"""Files downloader.""" """Files downloader."""
def latest_version(self, app: str, **kwargs: Any) -> None: def latest_version(self, app: str, **kwargs: Any) -> str:
"""Function to download whatever the latest version of app from """Function to download whatever the latest version of app from
apkmirror. apkmirror.
@@ -20,5 +18,6 @@ class ApkPure(Downloader):
""" """
package_name = Patches.get_package_name(app) package_name = Patches.get_package_name(app)
download_url = apk_sources[app].format(package_name) download_url = apk_sources[app].format(package_name)
self._download(download_url, f"{app}.apk") file_name = f"{app}.apk"
logger.debug(f"Downloaded {app} apk from apk_pure_downloader") self._download(download_url, file_name)
return file_name
+6 -4
View File
@@ -14,7 +14,7 @@ from src.utils import bs4_parser
class ApkSos(Downloader): class ApkSos(Downloader):
"""Files downloader.""" """Files downloader."""
def extract_download_link(self, page: str, app: str) -> None: def extract_download_link(self, page: str, app: str) -> str:
"""Function to extract the download link from apkmirror html page. """Function to extract the download link from apkmirror html page.
:param page: Url of the page :param page: Url of the page
@@ -26,10 +26,12 @@ class ApkSos(Downloader):
possible_links = download_button.find_all("a") possible_links = download_button.find_all("a")
for possible_link in possible_links: for possible_link in possible_links:
if possible_link.get("href"): if possible_link.get("href"):
return self._download(possible_link["href"], f"{app}.apk") file_name = f"{app}.apk"
self._download(possible_link["href"], file_name)
return file_name
raise APKSosAPKDownloadFailure(f"Unable to download {app}", url=page) raise APKSosAPKDownloadFailure(f"Unable to download {app}", url=page)
def latest_version(self, app: str, **kwargs: Any) -> None: def latest_version(self, app: str, **kwargs: Any) -> str:
"""Function to download whatever the latest version of app from """Function to download whatever the latest version of app from
apkmirror. apkmirror.
@@ -38,4 +40,4 @@ class ApkSos(Downloader):
""" """
package_name = self.patcher.get_package_name(app) package_name = self.patcher.get_package_name(app)
download_url = apk_sources[app].format(package_name) download_url = apk_sources[app].format(package_name)
self.extract_download_link(download_url, app) return self.extract_download_link(download_url, app)
+40 -8
View File
@@ -1,5 +1,6 @@
"""Downloader Class.""" """Downloader Class."""
import os import os
import subprocess
from pathlib import Path from pathlib import Path
from queue import PriorityQueue from queue import PriorityQueue
from time import perf_counter from time import perf_counter
@@ -71,11 +72,11 @@ class Downloader(object):
self._QUEUE.put((perf_counter() - start, file_name)) self._QUEUE.put((perf_counter() - start, file_name))
logger.debug(f"Downloaded {file_name}") logger.debug(f"Downloaded {file_name}")
def extract_download_link(self, page: str, app: str) -> None: def extract_download_link(self, page: str, app: str) -> str:
"""Extract download link from web page.""" """Extract download link from web page."""
raise NotImplementedError(implement_method) raise NotImplementedError(implement_method)
def specific_version(self, app: str, version: str) -> None: def specific_version(self, app: str, version: str) -> str:
"""Function to download the specified version of app from apkmirror. """Function to download the specified version of app from apkmirror.
:param app: Name of the application :param app: Name of the application
@@ -84,7 +85,7 @@ class Downloader(object):
""" """
raise NotImplementedError(implement_method) raise NotImplementedError(implement_method)
def latest_version(self, app: str, **kwargs: Any) -> None: def latest_version(self, app: str, **kwargs: Any) -> str:
"""Function to download the latest version of app. """Function to download the latest version of app.
:param app: Name of the application :param app: Name of the application
@@ -92,21 +93,52 @@ class Downloader(object):
""" """
raise NotImplementedError(implement_method) raise NotImplementedError(implement_method)
def download(self, version: str, app: str, **kwargs: Any) -> None: def convert_to_apk(self, file_name: str) -> str:
"""Convert apks to apk."""
if file_name.endswith(".apk"):
return file_name
output_apk_file = self.replace_file_extension(file_name, ".apk")
output_path = f"{self.config.temp_folder}/{output_apk_file}"
Path(output_path).unlink(missing_ok=True)
subprocess.run(
[
"java",
"-jar",
f"{self.config.temp_folder}/{self.config.apk_editor}",
"m",
"-i",
f"{self.config.temp_folder}/{file_name}",
"-o",
output_path,
],
capture_output=True,
check=True,
)
logger.info("Converted zip to apk.")
return output_apk_file
@staticmethod
def replace_file_extension(filename: str, new_extension: str) -> str:
"""Replace the extension of a file."""
base_name, _ = os.path.splitext(filename)
return base_name + new_extension
def download(self, version: str, app: str, **kwargs: Any) -> str:
"""Public function to download apk to patch. """Public function to download apk to patch.
:param version: version to download :param version: version to download
:param app: App to download :param app: App to download
""" """
if self.config.dry_run: if self.config.dry_run:
return return ""
if app in self.config.existing_downloaded_apks: if app in self.config.existing_downloaded_apks:
logger.debug(f"Will not download {app} -v{version} from the internet.") logger.debug(f"Will not download {app} -v{version} from the internet.")
return return app
if version and version != "latest": if version and version != "latest":
self.specific_version(app, version) file_name = self.specific_version(app, version)
else: else:
self.latest_version(app, **kwargs) file_name = self.latest_version(app, **kwargs)
return self.convert_to_apk(file_name)
def direct_download(self, dl: str, file_name: str) -> None: def direct_download(self, dl: str, file_name: str) -> None:
"""Download from DL.""" """Download from DL."""
+5 -4
View File
@@ -15,7 +15,7 @@ from src.utils import handle_github_response, update_changelog
class Github(Downloader): class Github(Downloader):
"""Files downloader.""" """Files downloader."""
def latest_version(self, app: str, **kwargs: Dict[str, str]) -> None: def latest_version(self, app: str, **kwargs: Dict[str, str]) -> str:
"""Function to download files from GitHub repositories. """Function to download files from GitHub repositories.
:param app: App to download :param app: App to download
@@ -25,7 +25,7 @@ class Github(Downloader):
logger.debug( logger.debug(
f"Skipping download of {app}. File already exists or dry running." f"Skipping download of {app}. File already exists or dry running."
) )
return return app
owner = str(kwargs["owner"]) owner = str(kwargs["owner"])
repo_name = str(kwargs["name"]) repo_name = str(kwargs["name"])
repo_url = f"https://api.github.com/repos/{owner}/{repo_name}/releases/latest" repo_url = f"https://api.github.com/repos/{owner}/{repo_name}/releases/latest"
@@ -35,7 +35,7 @@ class Github(Downloader):
if self.config.personal_access_token: if self.config.personal_access_token:
logger.debug("Using personal access token") logger.debug("Using personal access token")
headers["Authorization"] = f"token {self.config.personal_access_token}" headers["Authorization"] = f"token {self.config.personal_access_token}"
response = requests.get(repo_url, headers=headers) response = requests.get(repo_url, headers=headers, timeout=60)
handle_github_response(response) handle_github_response(response)
if repo_name == "revanced-patches": if repo_name == "revanced-patches":
download_url = response.json()["assets"][1]["browser_download_url"] download_url = response.json()["assets"][1]["browser_download_url"]
@@ -43,6 +43,7 @@ class Github(Downloader):
download_url = response.json()["assets"][0]["browser_download_url"] download_url = response.json()["assets"][0]["browser_download_url"]
update_changelog(f"{owner}/{repo_name}", response.json()) update_changelog(f"{owner}/{repo_name}", response.json())
self._download(download_url, file_name=app) self._download(download_url, file_name=app)
return app
@staticmethod @staticmethod
def _extract_repo_owner_and_tag(url: str) -> Tuple[str, str, str]: def _extract_repo_owner_and_tag(url: str) -> Tuple[str, str, str]:
@@ -78,7 +79,7 @@ class Github(Downloader):
} }
if config.personal_access_token: if config.personal_access_token:
headers["Authorization"] = f"token {config.personal_access_token}" headers["Authorization"] = f"token {config.personal_access_token}"
response = requests.get(api_url, headers=headers) response = requests.get(api_url, headers=headers, timeout=60)
handle_github_response(response) handle_github_response(response)
assets = response.json()["assets"] assets = response.json()["assets"]
try: try:
+31 -31
View File
@@ -5,43 +5,43 @@ APK_PURE_URL = "https://d.apkpure.com/b/APK/{}?version=latest"
APK_SOS_URL = "https://apksos.com/download-app/{}" APK_SOS_URL = "https://apksos.com/download-app/{}"
GITHUB_BASE_URL = "https://github.com" GITHUB_BASE_URL = "https://github.com"
apk_sources = { apk_sources = {
"backdrops": f"{APK_MIRROR_BASE_APK_URL}/backdrops/backdrops-wallpapers/",
"bacon": f"{APK_MIRROR_BASE_APK_URL}/onelouder-apps/baconreader-for-reddit/",
"boost": f"{APK_MIRROR_BASE_APK_URL}/ruben-mayayo/boost-for-reddit/",
"candyvpn": f"{APK_MIRROR_BASE_APK_URL}/liondev-io/candylink-vpn/",
"icon_pack_studio": f"{APK_MIRROR_BASE_APK_URL}/smart-launcher-team/icon-pack-studio/",
"infinity": f"{APK_MIRROR_BASE_APK_URL}/docile-alligator/infinity-for-reddit/",
"inshorts": f"{APK_MIRROR_BASE_APK_URL}/inshorts-formerly-news-in-shorts/inshorts-news-in-60-words-2/",
"instagram": f"{APK_MIRROR_BASE_APK_URL}/instagram/instagram-instagram/",
"irplus": f"{APK_MIRROR_BASE_APK_URL}/binarymode/irplus-infrared-remote/",
"meme-generator-free": f"{APK_MIRROR_BASE_APK_URL}/zombodroid/meme-generator-free/",
"messenger": f"{APK_MIRROR_BASE_APK_URL}/facebook-2/messenger/",
"netguard": f"{APK_MIRROR_BASE_APK_URL}/marcel-bokhorst/netguard-no-root-firewall/",
"nova_launcher": f"{APK_MIRROR_BASE_APK_URL}/teslacoil-software/nova-launcher/",
"nyx-music-player": f"{APK_MIRROR_BASE_APK_URL}/awedea/nyx-music-player/",
"pixiv": f"{APK_MIRROR_BASE_APK_URL}/pixiv-inc/pixiv/",
"reddit": f"{APK_MIRROR_BASE_APK_URL}/redditinc/reddit/", "reddit": f"{APK_MIRROR_BASE_APK_URL}/redditinc/reddit/",
"twitter": f"{APK_MIRROR_BASE_APK_URL}/x-corp/twitter/", "relay": f"{APK_MIRROR_BASE_APK_URL}/dbrady/relay-for-reddit-2/",
"rif": f"{APK_MIRROR_BASE_APK_URL}/talklittle/reddit-is-fun/",
"slide": f"{APK_MIRROR_BASE_APK_URL}/haptic-apps/slide-for-reddit/",
"sonyheadphone": f"{APK_MIRROR_BASE_APK_URL}/sony-corporation/sony-headphones-connect/",
"sync": f"{APK_MIRROR_BASE_APK_URL}/red-apps-ltd/sync-for-reddit/",
"tasker": f"{APK_MIRROR_BASE_APK_URL}/joaomgcd/tasker-crafty-apps-eu/",
"ticktick": f"{APK_MIRROR_BASE_APK_URL}/appest-inc/ticktick-to-do-list-with-reminder-day-planner/",
"tiktok": f"{APK_MIRROR_BASE_APK_URL}/tiktok-pte-ltd/tik-tok-including-musical-ly/", "tiktok": f"{APK_MIRROR_BASE_APK_URL}/tiktok-pte-ltd/tik-tok-including-musical-ly/",
"trakt": f"{APK_MIRROR_BASE_APK_URL}/trakt/trakt/",
"twitch": f"{APK_MIRROR_BASE_APK_URL}/twitch-interactive-inc/twitch/",
"twitter": f"{APK_MIRROR_BASE_APK_URL}/x-corp/twitter/",
"vsco": f"{APK_MIRROR_BASE_APK_URL}/vsco/vsco-cam/",
"warnwetter": f"{APK_MIRROR_BASE_APK_URL}/deutscher-wetterdienst/warnwetter/", "warnwetter": f"{APK_MIRROR_BASE_APK_URL}/deutscher-wetterdienst/warnwetter/",
"windy": f"{APK_MIRROR_BASE_APK_URL}/windy-weather-world-inc/windy-wind-weather-forecast/",
"youtube": f"{APK_MIRROR_BASE_APK_URL}/google-inc/youtube/", "youtube": f"{APK_MIRROR_BASE_APK_URL}/google-inc/youtube/",
"youtube_music": f"{APK_MIRROR_BASE_APK_URL}/google-inc/youtube-music/", "youtube_music": f"{APK_MIRROR_BASE_APK_URL}/google-inc/youtube-music/",
"ticktick": f"{APK_MIRROR_BASE_APK_URL}/appest-inc/ticktick-to-do-list-with-reminder-day-planner/", "yuka": f"{APK_MIRROR_BASE_APK_URL}/yuka-apps/yuka-food-cosmetic-scan/",
"icon_pack_studio": f"{APK_MIRROR_BASE_APK_URL}/smart-launcher-team/icon-pack-studio/",
"windy": f"{APK_MIRROR_BASE_APK_URL}/windy-weather-world-inc/windy-wind-weather-forecast/",
"tasker": f"{APK_MIRROR_BASE_APK_URL}/joaomgcd/tasker-crafty-apps-eu/",
"vsco": f"{APK_MIRROR_BASE_APK_URL}/vsco/vsco-cam/",
"nova_launcher": f"{APK_MIRROR_BASE_APK_URL}/teslacoil-software/nova-launcher/",
"netguard": f"{APK_MIRROR_BASE_APK_URL}/marcel-bokhorst/netguard-no-root-firewall/",
"instagram": f"{APK_MIRROR_BASE_APK_URL}/instagram/instagram-instagram/",
"inshorts": f"{APK_MIRROR_BASE_APK_URL}/inshorts-formerly-news-in-shorts/",
"messenger": f"{APK_MIRROR_BASE_APK_URL}/facebook-2/messenger/",
"trakt": f"{APK_MIRROR_BASE_APK_URL}/trakt/trakt/",
"candyvpn": f"{APK_MIRROR_BASE_APK_URL}/liondev-io/candylink-vpn/",
"sonyheadphone": f"{APK_MIRROR_BASE_APK_URL}/sony-corporation/sony-headphones-connect/",
"boost": f"{APK_MIRROR_BASE_APK_URL}/ruben-mayayo/boost-for-reddit/",
"rif": f"{APK_MIRROR_BASE_APK_URL}/talklittle/reddit-is-fun/",
"sync": f"{APK_MIRROR_BASE_APK_URL}/red-apps-ltd/sync-for-reddit/",
"infinity": f"{APK_MIRROR_BASE_APK_URL}/docile-alligator/infinity-for-reddit/",
"slide": f"{APK_MIRROR_BASE_APK_URL}/haptic-apps/slide-for-reddit/",
"bacon": f"{APK_MIRROR_BASE_APK_URL}/onelouder-apps/baconreader-for-reddit/",
"pixiv": f"{APK_MIRROR_BASE_APK_URL}/pixiv-inc/pixiv/",
"spotify": UPTODOWN_BASE_URL.format("spotify"),
"nyx-music-player": UPTODOWN_BASE_URL.format("nyx-music-player"),
"my-expenses": UPTODOWN_BASE_URL.format("my-expenses"),
"backdrops": UPTODOWN_BASE_URL.format("backdrops"),
"twitch": UPTODOWN_BASE_URL.format("twitch"),
"irplus": UPTODOWN_BASE_URL.format("irplus"),
"meme-generator-free": UPTODOWN_BASE_URL.format("meme-generator-free"),
"yuka": UPTODOWN_BASE_URL.format("yuka"),
"relay": UPTODOWN_BASE_URL.format("relay"),
"grecorder": UPTODOWN_BASE_URL.format("opnemer"), "grecorder": UPTODOWN_BASE_URL.format("opnemer"),
"hex-editor": APK_PURE_URL, "my-expenses": UPTODOWN_BASE_URL.format("my-expenses"),
"spotify": UPTODOWN_BASE_URL.format("spotify"),
"androidtwelvewidgets": APK_PURE_URL, "androidtwelvewidgets": APK_PURE_URL,
"expensemanager": APK_SOS_URL, "expensemanager": APK_SOS_URL,
"hex-editor": APK_PURE_URL,
} }
+9 -9
View File
@@ -15,8 +15,8 @@ from src.utils import bs4_parser
class UptoDown(Downloader): class UptoDown(Downloader):
"""Files downloader.""" """Files downloader."""
def extract_download_link(self, page: str, app: str) -> None: def extract_download_link(self, page: str, app: str) -> str:
r = requests.get(page, headers=headers, allow_redirects=True) r = requests.get(page, headers=headers, allow_redirects=True, timeout=60)
soup = BeautifulSoup(r.text, bs4_parser) soup = BeautifulSoup(r.text, bs4_parser)
soup = soup.find(id="detail-download-button") soup = soup.find(id="detail-download-button")
download_url = soup.get("data-url") download_url = soup.get("data-url")
@@ -24,10 +24,11 @@ class UptoDown(Downloader):
raise UptoDownAPKDownloadFailure( raise UptoDownAPKDownloadFailure(
f"Unable to download {app} from uptodown.", url=page f"Unable to download {app} from uptodown.", url=page
) )
self._download(download_url, f"{app}.apk") file_name = f"{app}.apk"
logger.debug(f"Downloaded {app} apk from upto_down_downloader in rt") self._download(download_url, file_name)
return file_name
def specific_version(self, app: str, version: str) -> None: def specific_version(self, app: str, version: str) -> str:
"""Function to download the specified version of app from apkmirror. """Function to download the specified version of app from apkmirror.
:param app: Name of the application :param app: Name of the application
@@ -49,9 +50,8 @@ class UptoDown(Downloader):
raise UptoDownAPKDownloadFailure( raise UptoDownAPKDownloadFailure(
f"Unable to download {app} from uptodown.", url=url f"Unable to download {app} from uptodown.", url=url
) )
self.extract_download_link(download_url, app) return self.extract_download_link(download_url, app)
logger.debug(f"Downloaded {app} apk from upto_down_downloader in rt")
def latest_version(self, app: str, **kwargs: Any) -> None: def latest_version(self, app: str, **kwargs: Any) -> str:
page = f"{apk_sources[app]}/download" page = f"{apk_sources[app]}/download"
self.extract_download_link(page, app) return self.extract_download_link(page, app)
+1 -1
View File
@@ -89,7 +89,7 @@ class Parser(object):
self.CLI_JAR, self.CLI_JAR,
app.resource["cli"], app.resource["cli"],
self.APK_ARG, self.APK_ARG,
f"{app.app_name}.apk", app.download_file_name,
self.PATCHES_ARG, self.PATCHES_ARG,
app.resource["patches"], app.resource["patches"],
self.INTEGRATIONS_ARG, self.INTEGRATIONS_ARG,
+11 -7
View File
@@ -2,7 +2,7 @@
import os import os
import re import re
import subprocess import subprocess
from typing import Any, Dict from typing import Any, Dict, List
import requests import requests
from loguru import logger from loguru import logger
@@ -123,13 +123,13 @@ def extra_downloads(config: RevancedConfig) -> None:
for extra in config.extra_download_files: for extra in config.extra_download_files:
url, file_name = extra.split("@") url, file_name = extra.split("@")
file_name_without_extension, file_extension = os.path.splitext(file_name) file_name_without_extension, file_extension = os.path.splitext(file_name)
if file_extension.lower() != ".apk":
logger.info(f"Only .apk extensions are allowed {file_name}.")
continue
new_file_name = f"{file_name_without_extension}-output{file_extension}" new_file_name = f"{file_name_without_extension}-output{file_extension}"
APP.download(url, config, assets_filter=".*apk", file_name=new_file_name) APP.download(
url,
config,
assets_filter=f".*{file_extension}",
file_name=new_file_name,
)
except (ValueError, IndexError): except (ValueError, IndexError):
logger.info( logger.info(
"Unable to download extra file. Provide input in url@name.apk format." "Unable to download extra file. Provide input in url@name.apk format."
@@ -149,3 +149,7 @@ def apkmirror_status_check(package_name: str) -> Any:
body = {"pnames": [package_name]} body = {"pnames": [package_name]}
response = requests.post(api_url, json=body, headers=apk_mirror_header) response = requests.post(api_url, json=body, headers=apk_mirror_header)
return response.json() return response.json()
def contains_any_word(string: str, words: List[str]) -> bool:
return any(word in string for word in words)