Files
docker-py-revanced/src/downloader/github.py
T
2023-08-10 21:47:53 +05:30

105 lines
3.8 KiB
Python

"""Github Downloader."""
import re
from typing import Dict, Tuple
from urllib.parse import urlparse
import requests
from loguru import logger
from src.config import RevancedConfig
from src.downloader.download import Downloader
from src.utils import handle_github_response, update_changelog
class Github(Downloader):
"""Files downloader."""
def latest_version(self, app: str, **kwargs: Dict[str, str]) -> None:
"""Function to download files from GitHub repositories.
:param app: App to download
"""
logger.debug(f"Trying to download {app} from github")
if self.config.dry_run or app == "microg":
logger.debug(
f"Skipping download of {app}. File already exists or dry running."
)
return
owner = str(kwargs["owner"])
repo_name = str(kwargs["name"])
repo_url = f"https://api.github.com/repos/{owner}/{repo_name}/releases/latest"
headers = {
"Content-Type": "application/vnd.github.v3+json",
}
if self.config.personal_access_token:
logger.debug("Using personal access token")
headers["Authorization"] = f"token {self.config.personal_access_token}"
response = requests.get(repo_url, headers=headers)
handle_github_response(response)
if repo_name == "revanced-patches":
download_url = response.json()["assets"][1]["browser_download_url"]
else:
download_url = response.json()["assets"][0]["browser_download_url"]
update_changelog(f"{owner}/{repo_name}", response.json())
self._download(download_url, file_name=app)
@staticmethod
def _extract_repo_owner_and_tag(url: str) -> Tuple[str, str, str]:
"""Extract repo owner and url from github url."""
parsed_url = urlparse(url)
path_segments = parsed_url.path.strip("/").split("/")
github_repo_owner = path_segments[0]
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"
),
"latest",
)
return github_repo_owner, github_repo_name, release_tag
@staticmethod
def _get_release_assets(
github_repo_owner: str,
github_repo_name: str,
release_tag: str,
asset_filter: str,
config: RevancedConfig,
) -> str:
"""Get assets from given tag."""
api_url = f"https://api.github.com/repos/{github_repo_owner}/{github_repo_name}/releases/{release_tag}"
headers = {
"Content-Type": "application/vnd.github.v3+json",
}
if config.personal_access_token:
headers["Authorization"] = f"token {config.personal_access_token}"
response = requests.get(api_url, headers=headers)
handle_github_response(response)
assets = response.json()["assets"]
try:
filter_pattern = re.compile(asset_filter)
except re.error:
logger.error("Invalid regex pattern provided.")
raise Exception()
for asset in assets:
assets_url = asset["browser_download_url"]
assets_name = asset["name"]
if match := filter_pattern.search(assets_url):
logger.debug(f"Found {assets_name} to be downloaded from {assets_url}")
return match.group()
return ""
@staticmethod
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
)