mirror of
https://github.com/sotam0316/docker-py-revanced.git
synced 2026-04-25 03:48:37 +09:00
🎨 Merge APKM bundles to get apk for patching (#297)
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -9,3 +9,4 @@ changelog.md
|
|||||||
.idea
|
.idea
|
||||||
*.json
|
*.json
|
||||||
status.md
|
status.md
|
||||||
|
*.zip
|
||||||
|
|||||||
@@ -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}")
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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."""
|
||||||
|
|||||||
@@ -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
@@ -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,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user