mirror of
https://github.com/SinTan1729/ReVancedBuilder.git
synced 2025-04-18 23:50:01 -05:00
Compare commits
15 commits
Author | SHA1 | Date | |
---|---|---|---|
4da95d0a7d | |||
c914b920d7 | |||
454db3c28a | |||
3401d50aa6 | |||
b0cedf0486 | |||
5479faed46 | |||
e4694801a5 | |||
2da875f2fd | |||
ee3eef71aa | |||
ad125bfb7b | |||
64ab240a8a | |||
8a3e6fa35f | |||
|
c38881922d | ||
|
25fc3e4310 | ||
8b70217909 |
9 changed files with 798 additions and 254 deletions
44
README.md
44
README.md
|
@ -1,12 +1,16 @@
|
|||
# Revanced Builder
|
||||
This repo will allow one to build [ReVanced](https://github.com/revanced/) apps automatically, send notifications (and possibly share the builds with friends). It uses [Gotify](https://gotify.net), [ntfy.sh](https://ntfy.sh) or [telegram.sh](https://github.com/fabianonline/telegram.sh) to send messages. Make sure that `Java >=17` is installed and selected as default.
|
||||
This repo will allow one to build [ReVanced](https://github.com/revanced/) apps
|
||||
automatically, send notifications (and possibly share the builds with friends).
|
||||
It uses [Gotify](https://gotify.net), [ntfy.sh](https://ntfy.sh) or
|
||||
[telegram.sh](https://github.com/fabianonline/telegram.sh) to send messages.
|
||||
Make sure that `Java >=17` is installed and selected as default.
|
||||
|
||||
## Installation
|
||||
Recommended way is to use [`pipx`](https://github.com/pypa/pipx) to install the program.
|
||||
Recommended way is to use [`uv`](https://github.com/astral-sh/uv) to install the program.
|
||||
```
|
||||
pipx install git+https://github.com/SinTan1729/ReVancedBuilder
|
||||
uv tool install git+https://github.com/SinTan1729/ReVancedBuilder
|
||||
```
|
||||
And then you can update/reinstall the program using `pipx reinstall ReVancedBuilder`.
|
||||
And then you can update/reinstall the program using `uv tool update ReVancedBuilder`.
|
||||
## How to use
|
||||
Just run `ReVancedBuilder <working-directory> (force/experimental/checkonly/buildonly)`.
|
||||
|
||||
|
@ -50,12 +54,28 @@ It might be a good idea to set it up to run periodically. There are a few ways o
|
|||
```
|
||||
|
||||
## Notes
|
||||
- If you installed it using `pipx`, you can figure out the full location of the program by running `which ReVancedBuilder`.
|
||||
- This app needs some config files to run. Download all the config files inside `example_configs` directory, namely `build_config`, `chosen_patches` (optional), and `notification_config` (optional, needed only if you want to send notifications) and move them to your working directory. Then, you should modify these files to your liking.
|
||||
- The script will download the **automatically selected compatible version** (unless version is specified in `build_config`) (using compatibility of patches as listed [here](https://revanced.app/patches)) of Youtube on APKPure, **NOT** latest official version on Google Play.
|
||||
- **Under no circumstances** will any APKs be uploaded to this repository as that might attract legal problems.
|
||||
- If you enable telegram notifications, make sure to fill up the config options inside the `build_config` file. For more information about the config, take at look at the repos of `telegram.sh` and `telegram-upload` provided above.
|
||||
- It can also run a post script (if exists), specified in the `build_config` file. The `timestamp` is passed as `$1`.
|
||||
- In the current configuration, the script only builds YouTube ReVanced and YouTube Music ReVanced (both nonroot), but it's easy to add support for any other ReVanced app using the `build_config` file. The config files are self-explanatory.
|
||||
- All the packages are pulled from [APKPure](https://apkpure.com) and GitHub (the [`revanced/*`](https://github.com/revanced) repos).
|
||||
- If you installed it using `uv`, you can figure out the full location of the
|
||||
program by running `which ReVancedBuilder`.
|
||||
- This app needs some config files to run. Download all the config files inside
|
||||
`example_configs` directory, namely `build_config`, `chosen_patches`
|
||||
(optional), and `notification_config` (optional, needed only if you want to
|
||||
send notifications) and move them to your working directory. Then, you should
|
||||
modify these files to your liking.
|
||||
- The script will download the **automatically selected compatible version**,
|
||||
using compatibility of patches as listed [here](https://revanced.app/patches)
|
||||
of Youtube on APKPure, **NOT** latest official version on Google Play (unless
|
||||
version is specified in `build_config`).
|
||||
- **Under no circumstances** will any APKs be uploaded to this repository as
|
||||
that might attract legal problems.
|
||||
- If you enable telegram notifications, make sure to fill up the config options
|
||||
inside the `build_config` file. For more information about the config, take at
|
||||
look at the repos of `telegram.sh` and `telegram-upload` provided above.
|
||||
- It can also run a post script (if exists), specified in the `build_config`
|
||||
file. The `timestamp` is passed as `$1`.
|
||||
- In the current configuration, the script only builds YouTube ReVanced and
|
||||
YouTube Music ReVanced (both nonroot), but it's easy to add support for any
|
||||
other ReVanced app using the `build_config` file. The config files are
|
||||
self-explanatory.
|
||||
- All the packages are pulled from [APKPure](https://apkpure.com) and GitHub
|
||||
(the [`revanced/*`](https://github.com/revanced) repos).
|
||||
|
||||
|
|
|
@ -23,3 +23,5 @@
|
|||
enabled = false
|
||||
url = url
|
||||
topic = topic
|
||||
token = token
|
||||
|
||||
|
|
|
@ -1,18 +1,14 @@
|
|||
[build-system]
|
||||
requires = ["setuptools"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "ReVancedBuilder"
|
||||
authors = [{ name = "Sayantan Santra", email = "sayantan.santra689@gmail.com" }]
|
||||
description = "A tool to automatically build latest releases of ReVanced apps"
|
||||
license = "GPL-3.0-only"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.6"
|
||||
keywords = ["revanced", "patch"]
|
||||
license = { file = "LICENSE" }
|
||||
classifiers = ["Programming Language :: Python :: 3"]
|
||||
dependencies = ["cloudscraper", "requests", "packaging", "bs4"]
|
||||
version = "1.3"
|
||||
version = "1.4.1"
|
||||
|
||||
[project.scripts]
|
||||
ReVancedBuilder = "ReVancedBuilder:ReVancedBuilder"
|
||||
|
|
108
src/ReVancedBuilder/APKPure_dl.py
Normal file → Executable file
108
src/ReVancedBuilder/APKPure_dl.py
Normal file → Executable file
|
@ -5,61 +5,62 @@
|
|||
|
||||
import os
|
||||
|
||||
from packaging.version import Version
|
||||
import cloudscraper as scraper
|
||||
from bs4 import BeautifulSoup as bs
|
||||
from packaging.version import Version
|
||||
|
||||
from ReVancedBuilder.Cleanup import err_exit
|
||||
|
||||
# Determine the best version available to download
|
||||
|
||||
|
||||
def apkpure_best_match(version, soup):
|
||||
def apkpure_best_match(version, soup, appstate, apk):
|
||||
try:
|
||||
vers_list_str = [x['data-dt-version'] for x in soup.css.select(f"a[data-dt-apkid^=\"b/APK/\"]")]
|
||||
except:
|
||||
err_exit(
|
||||
f" There was some error getting list of versions of {apk}...", appstate)
|
||||
vers_list_str = [
|
||||
x["data-dt-version"] for x in soup.css.select('a[data-dt-apkid^="b/APK/"]')
|
||||
]
|
||||
except Exception as ex:
|
||||
err_exit(f" There was some error getting list of versions of {apk}: {ex}", appstate)
|
||||
|
||||
vers_list = map(lambda x: Version(x), vers_list_str)
|
||||
|
||||
if version != '0':
|
||||
if version != "0":
|
||||
vers_list = filter(lambda x: x <= Version(version), vers_list)
|
||||
|
||||
max_ver = max(vers_list)
|
||||
return next(filter(lambda x: Version(x) == max_ver, vers_list_str))
|
||||
|
||||
|
||||
# Download an apk from apkpure.net
|
||||
|
||||
|
||||
def apkpure_dl(apk, appname, version, hard_version, session, present_vers, flag):
|
||||
def apkpure_dl(apk, appname, version, hard_version, session, present_vers, flag, appstate):
|
||||
res = session.get(f"https://apkpure.com/{appname}/{apk}/versions")
|
||||
res.raise_for_status()
|
||||
soup = bs(res.text, 'html.parser')
|
||||
soup = bs(res.text, "html.parser")
|
||||
|
||||
try:
|
||||
if present_vers[apk] == version and flag != 'force' and os.path.isfile(apk+'.apk'):
|
||||
print(
|
||||
f"Recommended version {version} of {apk} is already present.")
|
||||
if present_vers[apk] == version and flag != "force" and os.path.isfile(apk + ".apk"):
|
||||
print(f"Recommended version {version} of {apk} is already present.")
|
||||
return
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
if not hard_version:
|
||||
apkpure_version = apkpure_best_match(version, soup)
|
||||
if version not in [apkpure_version, '0']:
|
||||
apkpure_version = apkpure_best_match(version, soup, appstate, apk)
|
||||
if version not in [apkpure_version, "0"]:
|
||||
print(
|
||||
f"Required version {version} not found in APKPure, choosing version {apkpure_version} instead.")
|
||||
f"Required version {version} not found in APKPure, choosing version {apkpure_version} instead."
|
||||
)
|
||||
version = apkpure_version
|
||||
try:
|
||||
if present_vers[apk] == version and flag != 'force' and os.path.isfile(apk+'.apk'):
|
||||
print(
|
||||
f"Recommended version {version} of {apk} is already present.")
|
||||
if present_vers[apk] == version and flag != "force" and os.path.isfile(apk + ".apk"):
|
||||
print(f"Recommended version {version} of {apk} is already present.")
|
||||
return
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
if flag == 'checkonly' and present_vers[apk] != version:
|
||||
if flag == "checkonly" and present_vers[apk] != version:
|
||||
print(f"{apk} has an update ({present_vers[apk]} -> {version})")
|
||||
return
|
||||
|
||||
|
@ -67,16 +68,15 @@ def apkpure_dl(apk, appname, version, hard_version, session, present_vers, flag)
|
|||
|
||||
# Get the version code
|
||||
try:
|
||||
ver_code = soup.css.select(
|
||||
f"a[data-dt-version=\"{version}\"][data-dt-apkid^=\"b/APK/\"]")[0]['data-dt-versioncode']
|
||||
except:
|
||||
err_exit(
|
||||
f" There was some error while downloading {apk}...", appname)
|
||||
ver_code = soup.css.select(f'a[data-dt-version="{version}"][data-dt-apkid^="b/APK/"]')[0][
|
||||
"data-dt-versioncode"
|
||||
]
|
||||
except Exception as ex:
|
||||
err_exit(f" There was some error while downloading {apk}: {ex}", appstate)
|
||||
|
||||
res = session.get(
|
||||
f"https://d.apkpure.com/b/APK/{apk}?versionCode={ver_code}", stream=True)
|
||||
res = session.get(f"https://d.apkpure.com/b/APK/{apk}?versionCode={ver_code}", stream=True)
|
||||
res.raise_for_status()
|
||||
with open(apk+'.apk', 'wb') as f:
|
||||
with open(apk + ".apk", "wb") as f:
|
||||
for chunk in res.iter_content(chunk_size=8192):
|
||||
f.write(chunk)
|
||||
print(" Done!")
|
||||
|
@ -84,11 +84,11 @@ def apkpure_dl(apk, appname, version, hard_version, session, present_vers, flag)
|
|||
|
||||
# Download apk files, if needed
|
||||
def get_apks(appstate):
|
||||
present_vers = appstate['present_vers']
|
||||
build_config = appstate['build_config']
|
||||
flag = appstate['flag']
|
||||
present_vers = appstate["present_vers"]
|
||||
build_config = appstate["build_config"]
|
||||
flag = appstate["flag"]
|
||||
|
||||
print('Downloading required apk files from APKPure...')
|
||||
print("Downloading required apk files from APKPure...")
|
||||
|
||||
# Create a cloudscraper session
|
||||
session = scraper.create_scraper()
|
||||
|
@ -96,56 +96,60 @@ def get_apks(appstate):
|
|||
# Get latest patches using the ReVanced API
|
||||
try:
|
||||
# Get the first result
|
||||
patches_json = next(filter(
|
||||
lambda x: x['repository'] == 'revanced/revanced-patches', appstate['tools']))
|
||||
patches = session.get(patches_json['browser_download_url']).json()
|
||||
patches = session.get("https://api.revanced.app/v4/patches/list").json()
|
||||
except session.exceptions.RequestException as e:
|
||||
err_exit(f"Error fetching patches, {e}", appstate)
|
||||
|
||||
for app in build_config:
|
||||
# Check if we need to build an app
|
||||
if not build_config[app].getboolean('build'):
|
||||
if not build_config[app].getboolean("build"):
|
||||
continue
|
||||
|
||||
try:
|
||||
apk = build_config[app]['apk']
|
||||
pretty_name = build_config[app]['pretty_name']
|
||||
apkpure_appname = build_config[app]['apkpure_appname']
|
||||
except:
|
||||
err_exit(f"Invalid config for {app} in build_config!", appstate)
|
||||
apk = build_config[app]["apk"]
|
||||
pretty_name = build_config[app]["pretty_name"]
|
||||
apkpure_appname = build_config[app]["apkpure_appname"]
|
||||
except Exception as ex:
|
||||
err_exit(f"Invalid config for {app} in build_config!: {ex}", appstate)
|
||||
|
||||
print(f"Checking {pretty_name}...")
|
||||
try:
|
||||
required_ver = build_config[app]['version']
|
||||
required_ver = build_config[app]["version"]
|
||||
hard_version = True
|
||||
print(f"Using version {required_ver} of {apk} from build_config.")
|
||||
except:
|
||||
except Exception as ex:
|
||||
print(f"Dealing with exception: {ex}")
|
||||
hard_version = False
|
||||
compatible_vers = []
|
||||
for patch in patches:
|
||||
if patch['compatiblePackages'] is not None:
|
||||
for pkg in patch['compatiblePackages']:
|
||||
if pkg['name'] == apk:
|
||||
try:
|
||||
compatible_vers.append(pkg['versions'][-1])
|
||||
except TypeError:
|
||||
compatible_vers.append(patch["compatiblePackages"][apk][-1])
|
||||
except (KeyError, TypeError):
|
||||
pass
|
||||
|
||||
if not compatible_vers:
|
||||
required_ver = Version('0')
|
||||
required_ver = Version("0")
|
||||
else:
|
||||
required_ver = min(map(lambda x: Version(x), compatible_vers))
|
||||
required_ver = next(filter(lambda x: Version(x) == required_ver, compatible_vers))
|
||||
|
||||
print(f"Chosen required version of {apk} is {required_ver}.")
|
||||
|
||||
if appstate['present_vers'][apk] == required_ver:
|
||||
if apk in appstate["present_vers"] and appstate["present_vers"][apk] == required_ver:
|
||||
print("It's already present on disk, so skipping download.")
|
||||
else:
|
||||
apkpure_dl(apk, apkpure_appname, required_ver,
|
||||
hard_version, session, present_vers, flag)
|
||||
apkpure_dl(
|
||||
apk,
|
||||
apkpure_appname,
|
||||
required_ver,
|
||||
hard_version,
|
||||
session,
|
||||
present_vers,
|
||||
flag,
|
||||
appstate,
|
||||
)
|
||||
|
||||
present_vers.update({apk: required_ver})
|
||||
|
||||
appstate['present_vers'] = present_vers
|
||||
appstate["present_vers"] = present_vers
|
||||
return appstate
|
||||
|
|
28
src/ReVancedBuilder/Cleanup.py
Normal file → Executable file
28
src/ReVancedBuilder/Cleanup.py
Normal file → Executable file
|
@ -13,28 +13,28 @@ from ReVancedBuilder.Notifications import send_notif
|
|||
|
||||
|
||||
def move_apps(appstate):
|
||||
build_config = appstate['build_config']
|
||||
print = appstate['logger'].info
|
||||
build_config = appstate["build_config"]
|
||||
print = appstate["logger"].info
|
||||
|
||||
try:
|
||||
os.mkdir('archive')
|
||||
os.mkdir("archive")
|
||||
except FileExistsError:
|
||||
pass
|
||||
|
||||
for app in build_config:
|
||||
if not build_config[app].getboolean('build'):
|
||||
if not build_config[app].getboolean("build"):
|
||||
continue
|
||||
name = build_config[app]['output_name']
|
||||
name = build_config[app]["output_name"]
|
||||
final_name = f"{name}_{appstate['timestamp']}.apk"
|
||||
|
||||
try:
|
||||
os.rename(name+'.apk', 'archive/'+final_name)
|
||||
os.rename(name + ".apk", "archive/" + final_name)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
# sys.exit('There was an error moving the final apk files!')
|
||||
|
||||
# Do some cleanup, keep only the last 3 build's worth of files and a week worth of logs
|
||||
with os.scandir('archive') as dir:
|
||||
with os.scandir("archive") as dir:
|
||||
files = []
|
||||
for f in dir:
|
||||
if name in f.name:
|
||||
|
@ -43,10 +43,10 @@ def move_apps(appstate):
|
|||
files.reverse()
|
||||
for f in files[3:]:
|
||||
os.remove(f)
|
||||
print('Deleted old build '+f.name)
|
||||
print("Deleted old build " + f.name)
|
||||
|
||||
# Delete logs older than 7 days
|
||||
with os.scandir('logs') as dir:
|
||||
with os.scandir("logs") as dir:
|
||||
now = time.time()
|
||||
for f in dir:
|
||||
if f.stat().st_ctime < now - 7 * 86400:
|
||||
|
@ -54,18 +54,18 @@ def move_apps(appstate):
|
|||
|
||||
|
||||
def err_exit(msg, appstate, code=1):
|
||||
print = appstate['logger'].info
|
||||
print = appstate["logger"].info
|
||||
|
||||
try:
|
||||
appstate['notification_config']
|
||||
if appstate['flag'] != 'checkonly':
|
||||
appstate["notification_config"]
|
||||
if appstate["flag"] != "checkonly":
|
||||
send_notif(appstate, error=True)
|
||||
except:
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
if msg:
|
||||
print(f"ERROR: {msg}")
|
||||
|
||||
# Delete the lockfile
|
||||
os.remove('lockfile')
|
||||
os.remove("lockfile")
|
||||
sys.exit(code)
|
||||
|
|
56
src/ReVancedBuilder/JAVABuilder.py
Normal file → Executable file
56
src/ReVancedBuilder/JAVABuilder.py
Normal file → Executable file
|
@ -3,9 +3,9 @@
|
|||
# SPDX-FileCopyrightText: 2023 Sayantan Santra <sayantan.santra689@gmail.com>
|
||||
# SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
import os
|
||||
import configparser as cp
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from ReVancedBuilder.Cleanup import err_exit
|
||||
|
@ -14,33 +14,33 @@ from ReVancedBuilder.Cleanup import err_exit
|
|||
|
||||
|
||||
def build_apps(appstate):
|
||||
build_config = appstate['build_config']
|
||||
flag = appstate['flag']
|
||||
print = appstate['logger'].info
|
||||
build_config = appstate["build_config"]
|
||||
flag = appstate["flag"]
|
||||
print = appstate["logger"].info
|
||||
|
||||
chosen_patches = cp.ConfigParser()
|
||||
chosen_patches.read('chosen_patches')
|
||||
chosen_patches.read("chosen_patches")
|
||||
|
||||
try:
|
||||
included_patches = json.loads(chosen_patches['patches']['included'])
|
||||
except:
|
||||
included_patches = json.loads(chosen_patches["patches"]["included"])
|
||||
except (KeyError, ValueError):
|
||||
included_patches = []
|
||||
try:
|
||||
excluded_patches = json.loads(chosen_patches['patches']['excluded'])
|
||||
except Exception as e:
|
||||
excluded_patches = json.loads(chosen_patches["patches"]["excluded"])
|
||||
except (KeyError, ValueError):
|
||||
excluded_patches = []
|
||||
|
||||
for app in build_config:
|
||||
# Check if we need to build an app
|
||||
if not build_config[app].getboolean('build'):
|
||||
if not build_config[app].getboolean("build"):
|
||||
continue
|
||||
|
||||
# Build the command to be run
|
||||
cmd = 'java -jar revanced-cli.jar patch -b revanced-patches.jar -m revanced-integrations.apk'
|
||||
cmd = "java -jar revanced-cli.jar patch -p revanced-patches.rvp"
|
||||
|
||||
try:
|
||||
root = build_config[app].getboolean('root')
|
||||
except:
|
||||
root = build_config[app].getboolean("root")
|
||||
except cp.Error:
|
||||
root = False
|
||||
|
||||
if root:
|
||||
|
@ -51,21 +51,21 @@ def build_apps(appstate):
|
|||
for item in excluded_patches:
|
||||
cmd += f" -e {item}"
|
||||
|
||||
if flag == 'experimental':
|
||||
cmd += ' --experimental'
|
||||
if flag == "experimental":
|
||||
cmd += " --experimental"
|
||||
|
||||
try:
|
||||
keystore = build_config[app]['keystore']
|
||||
keystore = build_config[app]["keystore"]
|
||||
if not root:
|
||||
cmd += f" --keystore {keystore} --keystore-entry-alias=alias --keystore-entry-password=ReVanced --keystore-password=ReVanced"
|
||||
except:
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
try:
|
||||
apk = build_config[app]['apk']
|
||||
pretty_name = build_config[app]['pretty_name']
|
||||
output_name = build_config[app]['output_name']
|
||||
except:
|
||||
apk = build_config[app]["apk"]
|
||||
pretty_name = build_config[app]["pretty_name"]
|
||||
output_name = build_config[app]["output_name"]
|
||||
except KeyError:
|
||||
err_exit(f"Invalid config for {app} in build_config!", appstate)
|
||||
|
||||
cmd += f" -o {output_name}.apk {apk}.apk"
|
||||
|
@ -76,17 +76,17 @@ def build_apps(appstate):
|
|||
print(f"Building {pretty_name} (nonroot) using '{cmd}'")
|
||||
|
||||
try:
|
||||
with subprocess.Popen(cmd, shell=True, bufsize=0, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout as output:
|
||||
with subprocess.Popen(
|
||||
cmd, shell=True, bufsize=0, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
||||
).stdout as output:
|
||||
for line in output:
|
||||
line_utf = line.decode('utf-8').strip('\n')
|
||||
line_utf = line.decode("utf-8").strip("\n")
|
||||
if line_utf:
|
||||
print(line_utf)
|
||||
except Exception as e:
|
||||
err_exit(
|
||||
f"There was an error while building {pretty_name}!\n{e}", appstate)
|
||||
err_exit(f"There was an error while building {pretty_name}!\n{e}", appstate)
|
||||
|
||||
try:
|
||||
os.rename(output_name+'.apk', output_name+'.apk')
|
||||
os.rename(output_name + ".apk", output_name + ".apk")
|
||||
except FileNotFoundError:
|
||||
err_exit(
|
||||
f"There was an error while building {pretty_name}!", appstate)
|
||||
err_exit(f"There was an error while building {pretty_name}!", appstate)
|
||||
|
|
109
src/ReVancedBuilder/Notifications.py
Normal file → Executable file
109
src/ReVancedBuilder/Notifications.py
Normal file → Executable file
|
@ -5,92 +5,99 @@
|
|||
|
||||
import json
|
||||
import re
|
||||
import requests as req
|
||||
import subprocess
|
||||
|
||||
import requests as req
|
||||
|
||||
|
||||
def send_notif(appstate, error=False):
|
||||
print = appstate['logger'].info
|
||||
timestamp = appstate['timestamp']
|
||||
print = appstate["logger"].info
|
||||
timestamp = appstate["timestamp"]
|
||||
|
||||
if error:
|
||||
msg = f"There was an error during build! Please check the logs.\nTimestamp: {timestamp}"
|
||||
else:
|
||||
notification_config = appstate['notification_config']
|
||||
build_config = appstate['build_config']
|
||||
present_vers = appstate['present_vers']
|
||||
flag = appstate['flag']
|
||||
build_config = appstate["build_config"]
|
||||
present_vers = appstate["present_vers"]
|
||||
|
||||
msg = json.dumps(present_vers, indent=0)
|
||||
msg = re.sub('("|\{|\}|,)', '', msg).strip('\n')
|
||||
msg = re.sub('("|\{|\}|,)', "", msg).strip("\n")
|
||||
|
||||
msg = msg.replace('revanced-', 'ReVanced ')
|
||||
msg = msg.replace('cli', 'CLI')
|
||||
msg = msg.replace('integrations', 'Integrations')
|
||||
msg = msg.replace('patches', 'Patches')
|
||||
msg = msg.replace("revanced-", "ReVanced ")
|
||||
msg = msg.replace("cli", "CLI")
|
||||
msg = msg.replace("integrations", "Integrations")
|
||||
msg = msg.replace("patches", "Patches")
|
||||
|
||||
for app in build_config:
|
||||
if not build_config[app].getboolean('build'):
|
||||
if not build_config[app].getboolean("build"):
|
||||
continue
|
||||
msg = msg.replace(
|
||||
build_config[app]['apk'], build_config[app]['pretty_name'])
|
||||
msg = msg.replace(build_config[app]["apk"], build_config[app]["pretty_name"])
|
||||
|
||||
msg += '\nTimestamp: ' + timestamp
|
||||
if appstate['gmscore_updated']:
|
||||
msg += '\nGmsCore was updated.'
|
||||
msg += "\nTimestamp: " + timestamp
|
||||
if appstate["gmscore_updated"]:
|
||||
msg += "\nGmsCore was updated."
|
||||
|
||||
config = appstate['notification_config']
|
||||
config = appstate["notification_config"]
|
||||
for entry in config:
|
||||
if not config[entry].getboolean('enabled'):
|
||||
if not config[entry].getboolean("enabled"):
|
||||
continue
|
||||
encoded_title = '⚙⚙⚙ ReVanced Build ⚙⚙⚙'.encode('utf-8')
|
||||
encoded_title = "⚙⚙⚙ ReVanced Build ⚙⚙⚙".encode("utf-8")
|
||||
|
||||
if entry == 'ntfy':
|
||||
print('Sending notification through ntfy.sh...')
|
||||
if entry == "ntfy":
|
||||
print("Sending notification through ntfy.sh...")
|
||||
try:
|
||||
url = config[entry]['url']
|
||||
topic = config[entry]['topic']
|
||||
except:
|
||||
print('URL or TOPIC not provided!')
|
||||
url = config[entry]["url"]
|
||||
topic = config[entry]["topic"]
|
||||
except KeyError:
|
||||
print("URL or TOPIC not provided!")
|
||||
continue
|
||||
headers = {
|
||||
"Icon": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/40/Revanced-logo-round.svg/240px-Revanced-logo-round.svg.png",
|
||||
"Title": encoded_title,
|
||||
}
|
||||
try:
|
||||
token = config[entry]["token"]
|
||||
headers["Authorization"] = "Bearer " + token
|
||||
except KeyError:
|
||||
continue
|
||||
headers = {'Icon': 'https://upload.wikimedia.org/wikipedia/commons/thumb/4/40/Revanced-logo-round.svg/240px-Revanced-logo-round.svg.png',
|
||||
'Title': encoded_title}
|
||||
try:
|
||||
req.post(f"{url}/{topic}", msg, headers=headers)
|
||||
except Exception as e:
|
||||
print('Failed!' + str(e))
|
||||
except Exception as ex:
|
||||
print(f"Failed with exception: {ex}")
|
||||
|
||||
elif entry == 'gotify':
|
||||
print('Sending notification through Gotify...')
|
||||
elif entry == "gotify":
|
||||
print("Sending notification through Gotify...")
|
||||
try:
|
||||
url = config[entry]['url']
|
||||
token = config[entry]['token']
|
||||
except:
|
||||
print('URL or TOKEN not provided!')
|
||||
url = config[entry]["url"]
|
||||
token = config[entry]["token"]
|
||||
except KeyError:
|
||||
print("URL or TOKEN not provided!")
|
||||
continue
|
||||
data = {'Title': encoded_title, 'message': msg, 'priority': '5'}
|
||||
data = {"Title": encoded_title, "message": msg, "priority": "5"}
|
||||
try:
|
||||
req.post(f"{url}/message?token={token}", data)
|
||||
except Exception as e:
|
||||
print('Failed!' + str(e))
|
||||
print("Failed!" + str(e))
|
||||
|
||||
elif entry == 'telegram':
|
||||
print('Sending notification through Telegram...')
|
||||
elif entry == "telegram":
|
||||
print("Sending notification through Telegram...")
|
||||
try:
|
||||
chat = config[entry]['chat']
|
||||
token = config[entry]['token']
|
||||
except:
|
||||
print('CHAT or TOKEN not provided!')
|
||||
chat = config[entry]["chat"]
|
||||
token = config[entry]["token"]
|
||||
except KeyError:
|
||||
print("CHAT or TOKEN not provided!")
|
||||
continue
|
||||
cmd = f"./telegram.sh -t {token} -c {chat} -T {encoded_title} -M \"{msg}\""
|
||||
cmd = f'./telegram.sh -t {token} -c {chat} -T {encoded_title} -M "{msg}"'
|
||||
try:
|
||||
with subprocess.Popen(cmd, shell=True, bufsize=0, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout as output:
|
||||
with subprocess.Popen(
|
||||
cmd, shell=True, bufsize=0, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
||||
).stdout as output:
|
||||
for line in output:
|
||||
line_utf = line.decode('utf-8').strip('\n')
|
||||
line_utf = line.decode("utf-8").strip("\n")
|
||||
if line_utf:
|
||||
print(line_utf)
|
||||
except Exception as e:
|
||||
err_exit(f"Failed!\n{e}", appstate)
|
||||
except Exception as ex:
|
||||
print(f"Failed to send notification with exception: {ex}")
|
||||
|
||||
else:
|
||||
print('Don\'t know how to send notifications to ' + entry)
|
||||
print("Don't know how to send notifications to " + entry)
|
||||
|
|
|
@ -3,93 +3,105 @@
|
|||
# SPDX-FileCopyrightText: 2023 Sayantan Santra <sayantan.santra689@gmail.com>
|
||||
# SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
import sys
|
||||
import os
|
||||
import configparser as cp
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
import requests as req
|
||||
from packaging.version import Version
|
||||
from datetime import datetime
|
||||
|
||||
from ReVancedBuilder.APKPure_dl import get_apks
|
||||
from ReVancedBuilder.Cleanup import err_exit, move_apps, send_notif
|
||||
from ReVancedBuilder.JAVABuilder import build_apps
|
||||
from ReVancedBuilder.Notifications import send_notif
|
||||
from ReVancedBuilder.Cleanup import move_apps, err_exit
|
||||
|
||||
|
||||
# Update the ReVanced tools, if needed
|
||||
def update_tools(appstate):
|
||||
for item in ['revanced-cli', 'revanced-integrations', 'revanced-patches']:
|
||||
for item in ["revanced-cli", "revanced-patches"]:
|
||||
print(f"Checking updates for {item}...")
|
||||
tools = appstate['tools']
|
||||
tool = next(filter(lambda x: x['repository'] == 'revanced/'+item and x['content_type'] not in ['application/pgp-keys', 'application/json'], tools))
|
||||
latest_ver = Version(tool['version'])
|
||||
tools = appstate["tools"]
|
||||
tool = next(
|
||||
filter(
|
||||
lambda x: x["repository"] == "revanced/" + item
|
||||
and x["content_type"] not in ["application/pgp-keys", "application/json"],
|
||||
tools,
|
||||
)
|
||||
)
|
||||
latest_ver = Version(tool["version"])
|
||||
|
||||
try:
|
||||
present_ver = Version(appstate['present_vers'][item])
|
||||
present_ver = Version(appstate["present_vers"][item])
|
||||
except KeyError:
|
||||
present_ver = Version('0')
|
||||
present_ver = Version("0")
|
||||
|
||||
output_file = item+os.path.splitext(tool['name'])[1]
|
||||
if flag == 'force' or not os.path.isfile(output_file) or present_ver < latest_ver:
|
||||
appstate['up-to-date'] = False
|
||||
output_file = item + os.path.splitext(tool["name"])[1]
|
||||
if flag == "force" or not os.path.isfile(output_file) or present_ver < latest_ver:
|
||||
appstate["up-to-date"] = False
|
||||
print(f"{item} has an update ({str(present_ver)} -> {str(latest_ver)})")
|
||||
if flag != 'checkonly':
|
||||
if flag != "checkonly":
|
||||
print(f"Downloading {output_file}...")
|
||||
res = req.get(tool['browser_download_url'], stream=True)
|
||||
res = req.get(tool["browser_download_url"], stream=True)
|
||||
res.raise_for_status()
|
||||
with open(output_file, 'wb') as f:
|
||||
with open(output_file, "wb") as f:
|
||||
for chunk in res.iter_content(chunk_size=8192):
|
||||
f.write(chunk)
|
||||
appstate['present_vers'].update({item: str(latest_ver)})
|
||||
appstate["present_vers"].update({item: str(latest_ver)})
|
||||
print("Done!")
|
||||
|
||||
return appstate
|
||||
|
||||
|
||||
# Update GmsCore, if needed
|
||||
def update_gmscore(appstate):
|
||||
print('Checking updates for GmsCore...')
|
||||
print("Checking updates for GmsCore...")
|
||||
# Pull the latest information using the ReVanced API
|
||||
try:
|
||||
data = req.get('https://api.revanced.app/v2/gmscore/releases/latest').json()['release']
|
||||
data = req.get("https://api.revanced.app/v2/gmscore/releases/latest").json()["release"]
|
||||
except req.exceptions.RequestException as e:
|
||||
err_exit(f"Error fetching GmsCore information, {e}", appstate)
|
||||
|
||||
latest_ver = Version(data['metadata']['tag_name'])
|
||||
latest_ver = Version(data["metadata"]["tag_name"])
|
||||
|
||||
try:
|
||||
present_ver = Version(appstate['present_vers']['GmsCore'])
|
||||
present_ver = Version(appstate["present_vers"]["GmsCore"])
|
||||
except KeyError:
|
||||
present_ver = Version('0')
|
||||
present_ver = Version("0")
|
||||
|
||||
try:
|
||||
variant = appstate['build_config']['gmscore']['variant']
|
||||
variant = appstate["build_config"]["gmscore"]["variant"]
|
||||
except KeyError:
|
||||
variant = "regular"
|
||||
|
||||
if variant == "alt":
|
||||
gmscore_link = next(filter(lambda x: "-hw-" in x['name'], data['assets']))['browser_download_url']
|
||||
gmscore_link = next(filter(lambda x: "-hw-" in x["name"], data["assets"]))[
|
||||
"browser_download_url"
|
||||
]
|
||||
else:
|
||||
gmscore_link = next(filter(lambda x: "-hw-" not in x['name'], data['assets']))['browser_download_url']
|
||||
gmscore_link = next(filter(lambda x: "-hw-" not in x["name"], data["assets"]))[
|
||||
"browser_download_url"
|
||||
]
|
||||
|
||||
if flag == 'force' or not os.path.isfile('GmsCore.apk') or present_ver < latest_ver:
|
||||
appstate['up-to-date'] = False
|
||||
if flag == "force" or not os.path.isfile("GmsCore.apk") or present_ver < latest_ver:
|
||||
appstate["up-to-date"] = False
|
||||
print(f"GmsCore has an update ({str(present_ver)} -> {str(latest_ver)})")
|
||||
if flag != 'checkonly':
|
||||
print(f"Downloading GmsCore...")
|
||||
if flag != "checkonly":
|
||||
print("Downloading GmsCore...")
|
||||
res = req.get(gmscore_link, stream=True)
|
||||
res.raise_for_status()
|
||||
with open('GmsCore.apk', 'wb') as f:
|
||||
with open("GmsCore.apk", "wb") as f:
|
||||
for chunk in res.iter_content(chunk_size=8192):
|
||||
f.write(chunk)
|
||||
appstate['present_vers'].update({'GmsCore': str(latest_ver)})
|
||||
appstate["present_vers"].update({"GmsCore": str(latest_ver)})
|
||||
print("Done!")
|
||||
appstate['gmscore_updated'] = True
|
||||
appstate["gmscore_updated"] = True
|
||||
|
||||
return appstate
|
||||
|
||||
|
||||
# ------------------------------
|
||||
# The main function starts here
|
||||
# ------------------------------
|
||||
|
@ -99,111 +111,116 @@ appstate = {}
|
|||
|
||||
# Get a timestamp
|
||||
time = datetime.now()
|
||||
appstate['timestamp'] = time.strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||
appstate["timestamp"] = time.strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||
|
||||
# Read arguments
|
||||
try:
|
||||
os.chdir(sys.argv[1])
|
||||
except IndexError:
|
||||
sys.exit('Please provide a working directory as argument!')
|
||||
sys.exit("Please provide a working directory as argument!")
|
||||
except FileNotFoundError:
|
||||
sys.exit('Invalid working directory provided!')
|
||||
sys.exit("Invalid working directory provided!")
|
||||
|
||||
# Try to make sure only one instance is running in a given working directory
|
||||
try:
|
||||
if os.path.exists('lockfile'):
|
||||
if os.path.exists("lockfile"):
|
||||
raise FileExistsError
|
||||
with open('tmplockfile', 'x') as f:
|
||||
with open("tmplockfile", "x") as f:
|
||||
f.flush()
|
||||
os.fsync(f.fileno())
|
||||
os.replace('tmplockfile', 'lockfile')
|
||||
os.replace("tmplockfile", "lockfile")
|
||||
except FileExistsError:
|
||||
sys.exit('Another instance is already running in the same working directory!')
|
||||
sys.exit("Another instance is already running in the same working directory!")
|
||||
|
||||
# Set up logging
|
||||
try:
|
||||
os.mkdir('logs')
|
||||
os.mkdir("logs")
|
||||
except FileExistsError:
|
||||
pass
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format='%(message)s')
|
||||
logging.basicConfig(level=logging.INFO, format="%(message)s")
|
||||
logger = logging.getLogger()
|
||||
logger.addHandler(logging.FileHandler(f"logs/{appstate['timestamp']}.log", 'w'))
|
||||
logger.addHandler(logging.FileHandler(f"logs/{appstate['timestamp']}.log", "w"))
|
||||
print = logger.info
|
||||
appstate['logger'] = logger
|
||||
appstate["logger"] = logger
|
||||
|
||||
# Get the flag
|
||||
try:
|
||||
flag = sys.argv[2]
|
||||
except:
|
||||
except IndexError:
|
||||
flag = None
|
||||
|
||||
if flag not in ['buildonly', 'checkonly', 'force', 'experimental', None]:
|
||||
if flag not in ["buildonly", "checkonly", "force", "experimental", None]:
|
||||
err_exit(f"Unknown flag: {flag}", appstate)
|
||||
|
||||
appstate['flag'] = flag
|
||||
appstate['gmscore_updated'] = False
|
||||
appstate["flag"] = flag
|
||||
appstate["gmscore_updated"] = False
|
||||
|
||||
print(f"Started building ReVanced apps at {time.strftime('%d %B, %Y %H:%M:%S')}")
|
||||
print('----------------------------------------------------------------------')
|
||||
print("----------------------------------------------------------------------")
|
||||
|
||||
# Read configs
|
||||
try:
|
||||
appstate['build_config']=cp.ConfigParser()
|
||||
appstate['build_config'].read_file(open('build_config', 'r'))
|
||||
appstate["build_config"] = cp.ConfigParser()
|
||||
appstate["build_config"].read_file(open("build_config", "r"))
|
||||
except FileNotFoundError:
|
||||
err_exit('No build config provided, exiting. Please look at the GitHub page for more information:\n https://github.com/SinTan1729/ReVancedBuilder', appstate)
|
||||
err_exit(
|
||||
"No build config provided, exiting. Please look at the GitHub page for more information:\n https://github.com/SinTan1729/ReVancedBuilder",
|
||||
appstate,
|
||||
)
|
||||
|
||||
appstate['notification_config'] = cp.ConfigParser()
|
||||
appstate['notification_config'].read('notification_config')
|
||||
appstate["notification_config"] = cp.ConfigParser()
|
||||
appstate["notification_config"].read("notification_config")
|
||||
|
||||
# Pull the latest information using the ReVanced API
|
||||
try:
|
||||
tools = req.get('https://api.revanced.app/tools').json()['tools']
|
||||
appstate['tools'] = tools
|
||||
tools = req.get("https://api.revanced.app/tools").json()["tools"]
|
||||
appstate["tools"] = tools
|
||||
except req.exceptions.RequestException as e:
|
||||
err_exit(f"Error fetching patch list, {e}", appstate)
|
||||
|
||||
try:
|
||||
with open('versions.json', 'r') as f:
|
||||
appstate['present_vers'] = json.load(f)
|
||||
except:
|
||||
with open("versions.json", "r") as f:
|
||||
appstate["present_vers"] = json.load(f)
|
||||
except FileNotFoundError:
|
||||
# We'll treat empty as 0 later
|
||||
appstate['present_vers'] = json.loads('{}')
|
||||
appstate["present_vers"] = json.loads("{}")
|
||||
|
||||
appstate['up-to-date'] = True
|
||||
# send_notif(appstate, error=False) # <,,,,,,,,<,,,,,,,,,,,,,
|
||||
if flag != 'buildonly':
|
||||
appstate["up-to-date"] = True
|
||||
|
||||
if flag != "buildonly":
|
||||
appstate = update_tools(appstate)
|
||||
appstate = update_gmscore(appstate)
|
||||
if (not appstate['up-to-date'] and flag != 'checkonly') or flag == 'force':
|
||||
if (not appstate["up-to-date"] and flag != "checkonly") or flag == "force":
|
||||
appstate = get_apks(appstate)
|
||||
|
||||
if (flag != 'checkonly' and not appstate['up-to-date']) or flag in ['force', 'buildonly']:
|
||||
if (flag != "checkonly" and not appstate["up-to-date"]) or flag in ["force", "buildonly"]:
|
||||
build_apps(appstate)
|
||||
move_apps(appstate)
|
||||
|
||||
# Update version numbers in the versions.json file
|
||||
if appstate['up-to-date'] and flag != 'buildonly':
|
||||
print('There\'s nothing to do.')
|
||||
elif flag != 'checkonly':
|
||||
send_notif(appstate)
|
||||
if appstate["up-to-date"] and flag != "buildonly":
|
||||
print("There's nothing to do.")
|
||||
elif flag != "checkonly":
|
||||
try:
|
||||
os.rename('versions.json', 'versions-old.json')
|
||||
os.rename("versions.json", "versions-old.json")
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
if flag != 'buildonly':
|
||||
with open('versions.json', 'w') as f:
|
||||
json.dump(appstate['present_vers'], f, indent=4)
|
||||
if flag != "buildonly":
|
||||
with open("versions.json", "w") as f:
|
||||
json.dump(appstate["present_vers"], f, indent=4)
|
||||
try:
|
||||
cmd = f"{appstate['build_config']['post_script']['file']} {appstate['timestamp']}"
|
||||
print(f"Running the post command '{cmd}'")
|
||||
subprocess.run(cmd, shell=True)
|
||||
except:
|
||||
pass
|
||||
except Exception as ex:
|
||||
print(f"Got exception while running the build: '{ex}'")
|
||||
err_exit("", appstate, 0)
|
||||
|
||||
send_notif(appstate)
|
||||
|
||||
# Delete the lockfile
|
||||
os.remove('lockfile')
|
||||
os.remove("lockfile")
|
||||
|
||||
sys.exit(0)
|
||||
|
|
498
uv.lock
Normal file
498
uv.lock
Normal file
|
@ -0,0 +1,498 @@
|
|||
version = 1
|
||||
revision = 1
|
||||
requires-python = ">=3.6"
|
||||
resolution-markers = [
|
||||
"python_full_version >= '3.9'",
|
||||
"python_full_version == '3.8.*'",
|
||||
"python_full_version == '3.7.*'",
|
||||
"python_full_version >= '3.6.8' and python_full_version < '3.7'",
|
||||
"python_full_version < '3.6.8'",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "beautifulsoup4"
|
||||
version = "4.12.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version >= '3.6.8' and python_full_version < '3.7'",
|
||||
"python_full_version < '3.6.8'",
|
||||
]
|
||||
dependencies = [
|
||||
{ name = "soupsieve", version = "2.3.2.post1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.7'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b3/ca/824b1195773ce6166d388573fc106ce56d4a805bd7427b624e063596ec58/beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051", size = 581181 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/fe/e8c672695b37eecc5cbf43e1d0638d88d66ba3a44c4d321c796f4e59167f/beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed", size = 147925 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "beautifulsoup4"
|
||||
version = "4.13.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version >= '3.9'",
|
||||
"python_full_version == '3.8.*'",
|
||||
"python_full_version == '3.7.*'",
|
||||
]
|
||||
dependencies = [
|
||||
{ name = "soupsieve", version = "2.4.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.7.*'" },
|
||||
{ name = "soupsieve", version = "2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8'" },
|
||||
{ name = "typing-extensions", version = "4.7.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.7.*'" },
|
||||
{ name = "typing-extensions", version = "4.12.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f0/3c/adaf39ce1fb4afdd21b611e3d530b183bb7759c9b673d60db0e347fd4439/beautifulsoup4-4.13.3.tar.gz", hash = "sha256:1bd32405dacc920b42b83ba01644747ed77456a65760e285fbc47633ceddaf8b", size = 619516 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/49/6abb616eb3cbab6a7cca303dc02fdf3836de2e0b834bf966a7f5271a34d8/beautifulsoup4-4.13.3-py3-none-any.whl", hash = "sha256:99045d7d3f08f91f0d656bc9b7efbae189426cd913d830294a15eefa0ea4df16", size = 186015 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bs4"
|
||||
version = "0.0.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "beautifulsoup4", version = "4.12.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.7'" },
|
||||
{ name = "beautifulsoup4", version = "4.13.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.7'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c9/aa/4acaf814ff901145da37332e05bb510452ebed97bc9602695059dd46ef39/bs4-0.0.2.tar.gz", hash = "sha256:a48685c58f50fe127722417bae83fe6badf500d54b55f7e39ffe43b798653925", size = 698 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/51/bb/bf7aab772a159614954d84aa832c129624ba6c32faa559dfb200a534e50b/bs4-0.0.2-py2.py3-none-any.whl", hash = "sha256:abf8742c0805ef7f662dce4b51cca104cffe52b835238afc169142ab9b3fbccc", size = 1189 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2025.1.31"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/1c/ab/c9f1e32b7b1bf505bf26f0ef697775960db7932abeb7b516de930ba2705f/certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", size = 167577 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/38/fc/bce832fd4fd99766c04d1ee0eead6b0ec6486fb100ae5e74c1d91292b982/certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe", size = 166393 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "charset-normalizer"
|
||||
version = "2.0.12"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version >= '3.6.8' and python_full_version < '3.7'",
|
||||
"python_full_version < '3.6.8'",
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/56/31/7bcaf657fafb3c6db8c787a865434290b726653c912085fbd371e9b92e1c/charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597", size = 79105 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/06/b3/24afc8868eba069a7f03650ac750a778862dc34941a4bebeb58706715726/charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df", size = 39623 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "charset-normalizer"
|
||||
version = "3.4.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version >= '3.9'",
|
||||
"python_full_version == '3.8.*'",
|
||||
"python_full_version == '3.7.*'",
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/16/b0/572805e227f01586461c80e0fd25d65a2115599cc9dad142fee4b747c357/charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3", size = 123188 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/58/5580c1716040bc89206c77d8f74418caf82ce519aae06450393ca73475d1/charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de", size = 198013 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d0/11/00341177ae71c6f5159a08168bcb98c6e6d196d372c94511f9f6c9afe0c6/charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176", size = 141285 },
|
||||
{ url = "https://files.pythonhosted.org/packages/01/09/11d684ea5819e5a8f5100fb0b38cf8d02b514746607934134d31233e02c8/charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037", size = 151449 },
|
||||
{ url = "https://files.pythonhosted.org/packages/08/06/9f5a12939db324d905dc1f70591ae7d7898d030d7662f0d426e2286f68c9/charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f", size = 143892 },
|
||||
{ url = "https://files.pythonhosted.org/packages/93/62/5e89cdfe04584cb7f4d36003ffa2936681b03ecc0754f8e969c2becb7e24/charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a", size = 146123 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a9/ac/ab729a15c516da2ab70a05f8722ecfccc3f04ed7a18e45c75bbbaa347d61/charset_normalizer-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a", size = 147943 },
|
||||
{ url = "https://files.pythonhosted.org/packages/03/d2/3f392f23f042615689456e9a274640c1d2e5dd1d52de36ab8f7955f8f050/charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247", size = 142063 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/e3/e20aae5e1039a2cd9b08d9205f52142329f887f8cf70da3650326670bddf/charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408", size = 150578 },
|
||||
{ url = "https://files.pythonhosted.org/packages/8d/af/779ad72a4da0aed925e1139d458adc486e61076d7ecdcc09e610ea8678db/charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb", size = 153629 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/b6/7aa450b278e7aa92cf7732140bfd8be21f5f29d5bf334ae987c945276639/charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d", size = 150778 },
|
||||
{ url = "https://files.pythonhosted.org/packages/39/f4/d9f4f712d0951dcbfd42920d3db81b00dd23b6ab520419626f4023334056/charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807", size = 146453 },
|
||||
{ url = "https://files.pythonhosted.org/packages/49/2b/999d0314e4ee0cff3cb83e6bc9aeddd397eeed693edb4facb901eb8fbb69/charset_normalizer-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f", size = 95479 },
|
||||
{ url = "https://files.pythonhosted.org/packages/2d/ce/3cbed41cff67e455a386fb5e5dd8906cdda2ed92fbc6297921f2e4419309/charset_normalizer-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f", size = 102790 },
|
||||
{ url = "https://files.pythonhosted.org/packages/72/80/41ef5d5a7935d2d3a773e3eaebf0a9350542f2cab4eac59a7a4741fbbbbe/charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125", size = 194995 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7a/28/0b9fefa7b8b080ec492110af6d88aa3dea91c464b17d53474b6e9ba5d2c5/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1", size = 139471 },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/64/d24ab1a997efb06402e3fc07317e94da358e2585165930d9d59ad45fcae2/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3", size = 149831 },
|
||||
{ url = "https://files.pythonhosted.org/packages/37/ed/be39e5258e198655240db5e19e0b11379163ad7070962d6b0c87ed2c4d39/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd", size = 142335 },
|
||||
{ url = "https://files.pythonhosted.org/packages/88/83/489e9504711fa05d8dde1574996408026bdbdbd938f23be67deebb5eca92/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00", size = 143862 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/c7/32da20821cf387b759ad24627a9aca289d2822de929b8a41b6241767b461/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12", size = 145673 },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/85/f4288e96039abdd5aeb5c546fa20a37b50da71b5cf01e75e87f16cd43304/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77", size = 140211 },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/a3/a42e70d03cbdabc18997baf4f0227c73591a08041c149e710045c281f97b/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146", size = 148039 },
|
||||
{ url = "https://files.pythonhosted.org/packages/85/e4/65699e8ab3014ecbe6f5c71d1a55d810fb716bbfd74f6283d5c2aa87febf/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd", size = 151939 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/82/8e9fe624cc5374193de6860aba3ea8070f584c8565ee77c168ec13274bd2/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6", size = 149075 },
|
||||
{ url = "https://files.pythonhosted.org/packages/3d/7b/82865ba54c765560c8433f65e8acb9217cb839a9e32b42af4aa8e945870f/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8", size = 144340 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/b6/9674a4b7d4d99a0d2df9b215da766ee682718f88055751e1e5e753c82db0/charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b", size = 95205 },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/ab/45b180e175de4402dcf7547e4fb617283bae54ce35c27930a6f35b6bef15/charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76", size = 102441 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0a/9a/dd1e1cdceb841925b7798369a09279bd1cf183cef0f9ddf15a3a6502ee45/charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545", size = 196105 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/8c/90bfabf8c4809ecb648f39794cf2a84ff2e7d2a6cf159fe68d9a26160467/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7", size = 140404 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ad/8f/e410d57c721945ea3b4f1a04b74f70ce8fa800d393d72899f0a40526401f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757", size = 150423 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/b8/e6825e25deb691ff98cf5c9072ee0605dc2acfca98af70c2d1b1bc75190d/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa", size = 143184 },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/a2/513f6cbe752421f16d969e32f3583762bfd583848b763913ddab8d9bfd4f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d", size = 145268 },
|
||||
{ url = "https://files.pythonhosted.org/packages/74/94/8a5277664f27c3c438546f3eb53b33f5b19568eb7424736bdc440a88a31f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616", size = 147601 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/5f/6d352c51ee763623a98e31194823518e09bfa48be2a7e8383cf691bbb3d0/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b", size = 141098 },
|
||||
{ url = "https://files.pythonhosted.org/packages/78/d4/f5704cb629ba5ab16d1d3d741396aec6dc3ca2b67757c45b0599bb010478/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d", size = 149520 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c5/96/64120b1d02b81785f222b976c0fb79a35875457fa9bb40827678e54d1bc8/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a", size = 152852 },
|
||||
{ url = "https://files.pythonhosted.org/packages/84/c9/98e3732278a99f47d487fd3468bc60b882920cef29d1fa6ca460a1fdf4e6/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9", size = 150488 },
|
||||
{ url = "https://files.pythonhosted.org/packages/13/0e/9c8d4cb99c98c1007cc11eda969ebfe837bbbd0acdb4736d228ccaabcd22/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1", size = 146192 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/21/2b6b5b860781a0b49427309cb8670785aa543fb2178de875b87b9cc97746/charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35", size = 95550 },
|
||||
{ url = "https://files.pythonhosted.org/packages/21/5b/1b390b03b1d16c7e382b561c5329f83cc06623916aab983e8ab9239c7d5c/charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f", size = 102785 },
|
||||
{ url = "https://files.pythonhosted.org/packages/38/94/ce8e6f63d18049672c76d07d119304e1e2d7c6098f0841b51c666e9f44a0/charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda", size = 195698 },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/2e/dfdd9770664aae179a96561cc6952ff08f9a8cd09a908f259a9dfa063568/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313", size = 140162 },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/4e/f646b9093cff8fc86f2d60af2de4dc17c759de9d554f130b140ea4738ca6/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9", size = 150263 },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/67/2937f8d548c3ef6e2f9aab0f6e21001056f692d43282b165e7c56023e6dd/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b", size = 142966 },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/ed/b7f4f07de100bdb95c1756d3a4d17b90c1a3c53715c1a476f8738058e0fa/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11", size = 144992 },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/2c/d49710a6dbcd3776265f4c923bb73ebe83933dfbaa841c5da850fe0fd20b/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f", size = 147162 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/41/35ff1f9a6bd380303dea55e44c4933b4cc3c4850988927d4082ada230273/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd", size = 140972 },
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/43/c6a0b685fe6910d08ba971f62cd9c3e862a85770395ba5d9cad4fede33ab/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2", size = 149095 },
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/ff/a9a504662452e2d2878512115638966e75633519ec11f25fca3d2049a94a/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886", size = 152668 },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/71/189996b6d9a4b932564701628af5cee6716733e9165af1d5e1b285c530ed/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601", size = 150073 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/93/946a86ce20790e11312c87c75ba68d5f6ad2208cfb52b2d6a2c32840d922/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd", size = 145732 },
|
||||
{ url = "https://files.pythonhosted.org/packages/cd/e5/131d2fb1b0dddafc37be4f3a2fa79aa4c037368be9423061dccadfd90091/charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407", size = 95391 },
|
||||
{ url = "https://files.pythonhosted.org/packages/27/f2/4f9a69cc7712b9b5ad8fdb87039fd89abba997ad5cbe690d1835d40405b0/charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971", size = 102702 },
|
||||
{ url = "https://files.pythonhosted.org/packages/bb/a6/3a22521736a3a75263ce930a2257eb60fd2a6b8fd9293ea1271a074a202f/charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089", size = 135247 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/1e/fa099993d17c00addbb76b3bfcd3ab1692fefc4e193ba738e111c09cfbe2/charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d", size = 144536 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/95/8725b2b2fcb418abe048b5558af42e444161433a76b47759539fe5bb7992/charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf", size = 137661 },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/2f/6e2c727649d5e97ee17230f4c064480c69eb563f52ba87df448647d77a99/charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e", size = 138592 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/1b/0cad3a4f1906dc36a9cc89093d36b134638463e8e43479dbb96fd47d99ef/charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a", size = 141250 },
|
||||
{ url = "https://files.pythonhosted.org/packages/8f/aa/73a89701dd661d9b5d24d0594c42ed0f7a3aed4448cc4f8f7315d0701399/charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd", size = 135234 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a8/00/b8b43690ecac81e5038dc6332681757123ee9c4c15eb4a6ecf0232393f59/charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534", size = 142457 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/a3/2db14427b37cefbf9a9ec3d3c861e1b1721e4d4507536df102c2854966dc/charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e", size = 145967 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0a/97/a183d752295997d95d20f2aa34d66ff6abda5af5482d0e7995dbbc9a753a/charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e", size = 145129 },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/c6/f62d90c0e66525a374c35a1389f4290e5d7a731cd2cfacd9740272f927f9/charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa", size = 138515 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/fe/4ade940a1b4bac031357b4a74fc8406a2ecd9dfc007dea850c5b7ee348de/charset_normalizer-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487", size = 93486 },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/17/74bb34d02d62a21cc626c7d4db475b6f2207980f6beb002051db8342b139/charset_normalizer-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d", size = 100195 },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/bd/6517ea94f2672e801011d50b5d06be2a0deaf566aea27bcdcd47e5195357/charset_normalizer-3.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c", size = 195653 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/0d/815a2ba3f283b4eeaa5ece57acade365c5b4135f65a807a083c818716582/charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9", size = 140701 },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/17/c94be7ee0d142687e047fe1de72060f6d6837f40eedc26e87e6e124a3fc6/charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8", size = 150495 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f7/33/557ac796c47165fc141e4fb71d7b0310f67e05cb420756f3a82e0a0068e0/charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6", size = 142946 },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/0d/38ef4ae41e9248d63fc4998d933cae22473b1b2ac4122cf908d0f5eb32aa/charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c", size = 144737 },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/01/754cdb29dd0560f58290aaaa284d43eea343ad0512e6ad3b8b5c11f08592/charset_normalizer-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a", size = 147471 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ba/cd/861883ba5160c7a9bd242c30b2c71074cda2aefcc0addc91118e0d4e0765/charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd", size = 140801 },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/7f/0c0dad447819e90b93f8ed238cc8f11b91353c23c19e70fa80483a155bed/charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd", size = 149312 },
|
||||
{ url = "https://files.pythonhosted.org/packages/8e/09/9f8abcc6fff60fb727268b63c376c8c79cc37b833c2dfe1f535dfb59523b/charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824", size = 152347 },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/e5/3f363dad2e24378f88ccf63ecc39e817c29f32e308ef21a7a6d9c1201165/charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca", size = 149888 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/10/a78c0e91f487b4ad0ef7480ac765e15b774f83de2597f1b6ef0eaf7a2f99/charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b", size = 145169 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/81/396e7d7f5d7420da8273c91175d2e9a3f569288e3611d521685e4b9ac9cc/charset_normalizer-3.4.1-cp38-cp38-win32.whl", hash = "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e", size = 95094 },
|
||||
{ url = "https://files.pythonhosted.org/packages/40/bb/20affbbd9ea29c71ea123769dc568a6d42052ff5089c5fe23e21e21084a6/charset_normalizer-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4", size = 102139 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7f/c0/b913f8f02836ed9ab32ea643c6fe4d3325c3d8627cf6e78098671cafff86/charset_normalizer-3.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41", size = 197867 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0f/6c/2bee440303d705b6fb1e2ec789543edec83d32d258299b16eed28aad48e0/charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f", size = 141385 },
|
||||
{ url = "https://files.pythonhosted.org/packages/3d/04/cb42585f07f6f9fd3219ffb6f37d5a39b4fd2db2355b23683060029c35f7/charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2", size = 151367 },
|
||||
{ url = "https://files.pythonhosted.org/packages/54/54/2412a5b093acb17f0222de007cc129ec0e0df198b5ad2ce5699355269dfe/charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770", size = 143928 },
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/6d/e2773862b043dcf8a221342954f375392bb2ce6487bcd9f2c1b34e1d6781/charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4", size = 146203 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/f8/ca440ef60d8f8916022859885f231abb07ada3c347c03d63f283bec32ef5/charset_normalizer-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537", size = 148082 },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/d2/42fd330901aaa4b805a1097856c2edf5095e260a597f65def493f4b8c833/charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496", size = 142053 },
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/af/3a97a4fa3c53586f1910dadfc916e9c4f35eeada36de4108f5096cb7215f/charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78", size = 150625 },
|
||||
{ url = "https://files.pythonhosted.org/packages/26/ae/23d6041322a3556e4da139663d02fb1b3c59a23ab2e2b56432bd2ad63ded/charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7", size = 153549 },
|
||||
{ url = "https://files.pythonhosted.org/packages/94/22/b8f2081c6a77cb20d97e57e0b385b481887aa08019d2459dc2858ed64871/charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6", size = 150945 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/0b/c5ec5092747f801b8b093cdf5610e732b809d6cb11f4c51e35fc28d1d389/charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294", size = 146595 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/5a/0b59704c38470df6768aa154cc87b1ac7c9bb687990a1559dc8765e8627e/charset_normalizer-3.4.1-cp39-cp39-win32.whl", hash = "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5", size = 95453 },
|
||||
{ url = "https://files.pythonhosted.org/packages/85/2d/a9790237cb4d01a6d57afadc8573c8b73c609ade20b80f4cda30802009ee/charset_normalizer-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765", size = 102811 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/f6/65ecc6878a89bb1c23a086ea335ad4bf21a588990c3f535a227b9eea9108/charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85", size = 49767 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cloudscraper"
|
||||
version = "1.2.71"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pyparsing", version = "3.0.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.6.8'" },
|
||||
{ name = "pyparsing", version = "3.1.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.6.8' and python_full_version < '3.9'" },
|
||||
{ name = "pyparsing", version = "3.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" },
|
||||
{ name = "requests", version = "2.27.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.7'" },
|
||||
{ name = "requests", version = "2.31.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.7.*'" },
|
||||
{ name = "requests", version = "2.32.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8'" },
|
||||
{ name = "requests-toolbelt" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ac/25/6d0481860583f44953bd791de0b7c4f6d7ead7223f8a17e776247b34a5b4/cloudscraper-1.2.71.tar.gz", hash = "sha256:429c6e8aa6916d5bad5c8a5eac50f3ea53c9ac22616f6cb21b18dcc71517d0d3", size = 93261 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/81/97/fc88803a451029688dffd7eb446dc1b529657577aec13aceff1cc9628c5d/cloudscraper-1.2.71-py2.py3-none-any.whl", hash = "sha256:76f50ca529ed2279e220837befdec892626f9511708e200d48d5bb76ded679b0", size = 99652 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.10"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "21.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version >= '3.6.8' and python_full_version < '3.7'",
|
||||
"python_full_version < '3.6.8'",
|
||||
]
|
||||
dependencies = [
|
||||
{ name = "pyparsing", version = "3.0.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.6.8'" },
|
||||
{ name = "pyparsing", version = "3.1.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.6.8' and python_full_version < '3.7'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/df/9e/d1a7217f69310c1db8fdf8ab396229f55a699ce34a203691794c5d1cad0c/packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb", size = 84848 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/05/8e/8de486cbd03baba4deef4142bd643a3e7bbe954a784dc1bb17142572d127/packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522", size = 40750 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "24.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version == '3.7.*'",
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ee/b5/b43a27ac7472e1818c4bafd44430e69605baefe1f34440593e0332ec8b4d/packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9", size = 147882 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/49/df/1fceb2f8900f8639e278b056416d49134fb8d84c5942ffaa01ad34782422/packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5", size = 53488 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "24.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version >= '3.9'",
|
||||
"python_full_version == '3.8.*'",
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyparsing"
|
||||
version = "3.0.7"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version < '3.6.8'",
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d6/60/9bed18f43275b34198eb9720d4c1238c68b3755620d20df0afd89424d32b/pyparsing-3.0.7.tar.gz", hash = "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea", size = 884709 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/80/c1/23fd82ad3121656b585351aba6c19761926bb0db2ebed9e4ff09a43a3fcc/pyparsing-3.0.7-py3-none-any.whl", hash = "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484", size = 98049 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyparsing"
|
||||
version = "3.1.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version == '3.8.*'",
|
||||
"python_full_version == '3.7.*'",
|
||||
"python_full_version >= '3.6.8' and python_full_version < '3.7'",
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/83/08/13f3bce01b2061f2bbd582c9df82723de943784cf719a35ac886c652043a/pyparsing-3.1.4.tar.gz", hash = "sha256:f86ec8d1a83f11977c9a6ea7598e8c27fc5cddfa5b07ea2241edbbde1d7bc032", size = 900231 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/0c/0e3c05b1c87bb6a1c76d281b0f35e78d2d80ac91b5f8f524cebf77f51049/pyparsing-3.1.4-py3-none-any.whl", hash = "sha256:a6a7ee4235a3f944aa1fa2249307708f893fe5717dc603503c6c7969c070fb7c", size = 104100 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyparsing"
|
||||
version = "3.2.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version >= '3.9'",
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/8b/1a/3544f4f299a47911c2ab3710f534e52fea62a633c96806995da5d25be4b2/pyparsing-3.2.1.tar.gz", hash = "sha256:61980854fd66de3a90028d679a954d5f2623e83144b5afe5ee86f43d762e5f0a", size = 1067694 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/1c/a7/c8a2d361bf89c0d9577c934ebb7421b25dc84bf3a8e3ac0a40aed9acc547/pyparsing-3.2.1-py3-none-any.whl", hash = "sha256:506ff4f4386c4cec0590ec19e6302d3aedb992fdc02c761e90416f158dacf8e1", size = 107716 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.27.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version >= '3.6.8' and python_full_version < '3.7'",
|
||||
"python_full_version < '3.6.8'",
|
||||
]
|
||||
dependencies = [
|
||||
{ name = "certifi", marker = "python_full_version < '3.7'" },
|
||||
{ name = "charset-normalizer", version = "2.0.12", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.7'" },
|
||||
{ name = "idna", marker = "python_full_version < '3.7'" },
|
||||
{ name = "urllib3", version = "1.26.20", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.7'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/60/f3/26ff3767f099b73e0efa138a9998da67890793bfa475d8278f84a30fec77/requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61", size = 106758 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/2d/61/08076519c80041bc0ffa1a8af0cbd3bf3e2b62af10435d269a9d0f40564d/requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d", size = 63133 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.31.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version == '3.7.*'",
|
||||
]
|
||||
dependencies = [
|
||||
{ name = "certifi", marker = "python_full_version == '3.7.*'" },
|
||||
{ name = "charset-normalizer", version = "3.4.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.7.*'" },
|
||||
{ name = "idna", marker = "python_full_version == '3.7.*'" },
|
||||
{ name = "urllib3", version = "2.0.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.7.*'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9d/be/10918a2eac4ae9f02f6cfe6414b7a155ccd8f7f9d4380d62fd5b955065c3/requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1", size = 110794 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f", size = 62574 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.32.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version >= '3.9'",
|
||||
"python_full_version == '3.8.*'",
|
||||
]
|
||||
dependencies = [
|
||||
{ name = "certifi", marker = "python_full_version >= '3.8'" },
|
||||
{ name = "charset-normalizer", version = "3.4.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8'" },
|
||||
{ name = "idna", marker = "python_full_version >= '3.8'" },
|
||||
{ name = "urllib3", version = "2.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.8.*'" },
|
||||
{ name = "urllib3", version = "2.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "requests-toolbelt"
|
||||
version = "1.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "requests", version = "2.27.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.7'" },
|
||||
{ name = "requests", version = "2.31.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.7.*'" },
|
||||
{ name = "requests", version = "2.32.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f3/61/d7545dafb7ac2230c70d38d31cbfe4cc64f7144dc41f6e4e4b78ecd9f5bb/requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6", size = 206888 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", size = 54481 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "revancedbuilder"
|
||||
version = "1.4.1"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "bs4" },
|
||||
{ name = "cloudscraper" },
|
||||
{ name = "packaging", version = "21.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.7'" },
|
||||
{ name = "packaging", version = "24.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.7.*'" },
|
||||
{ name = "packaging", version = "24.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8'" },
|
||||
{ name = "requests", version = "2.27.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.7'" },
|
||||
{ name = "requests", version = "2.31.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.7.*'" },
|
||||
{ name = "requests", version = "2.32.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8'" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "bs4" },
|
||||
{ name = "cloudscraper" },
|
||||
{ name = "packaging" },
|
||||
{ name = "requests" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "soupsieve"
|
||||
version = "2.3.2.post1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version >= '3.6.8' and python_full_version < '3.7'",
|
||||
"python_full_version < '3.6.8'",
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f3/03/bac179d539362319b4779a00764e95f7542f4920084163db6b0fd4742d38/soupsieve-2.3.2.post1.tar.gz", hash = "sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d", size = 102814 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/16/e3/4ad79882b92617e3a4a0df1960d6bce08edfb637737ac5c3f3ba29022e25/soupsieve-2.3.2.post1-py3-none-any.whl", hash = "sha256:3b2503d3c7084a42b1ebd08116e5f81aadfaea95863628c80a3b774a11b7c759", size = 37377 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "soupsieve"
|
||||
version = "2.4.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version == '3.7.*'",
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/47/9e/780779233a615777fbdf75a4dee2af7a345f4bf74b42d4a5f836800b9d91/soupsieve-2.4.1.tar.gz", hash = "sha256:89d12b2d5dfcd2c9e8c22326da9d9aa9cb3dfab0a83a024f05704076ee8d35ea", size = 101278 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/49/37/673d6490efc51ec46d198c75903d99de59baffdd47aea3d071b80a9e4e89/soupsieve-2.4.1-py3-none-any.whl", hash = "sha256:1c1bfee6819544a3447586c889157365a27e10d88cde3ad3da0cf0ddf646feb8", size = 36379 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "soupsieve"
|
||||
version = "2.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version >= '3.9'",
|
||||
"python_full_version == '3.8.*'",
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d7/ce/fbaeed4f9fb8b2daa961f90591662df6a86c1abf25c548329a86920aedfb/soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb", size = 101569 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/c2/fe97d779f3ef3b15f05c94a2f1e3d21732574ed441687474db9d342a7315/soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9", size = 36186 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.7.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version == '3.7.*'",
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/3c/8b/0111dd7d6c1478bf83baa1cab85c686426c7a6274119aceb2bd9d35395ad/typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2", size = 72876 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/6b/63cc3df74987c36fe26157ee12e09e8f9db4de771e0f3404263117e75b95/typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36", size = 33232 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.12.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version >= '3.9'",
|
||||
"python_full_version == '3.8.*'",
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "1.26.20"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version >= '3.6.8' and python_full_version < '3.7'",
|
||||
"python_full_version < '3.6.8'",
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e4/e8/6ff5e6bc22095cfc59b6ea711b687e2b7ed4bdb373f7eeec370a97d7392f/urllib3-1.26.20.tar.gz", hash = "sha256:40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32", size = 307380 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/33/cf/8435d5a7159e2a9c83a95896ed596f68cf798005fe107cc655b5c5c14704/urllib3-1.26.20-py2.py3-none-any.whl", hash = "sha256:0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e", size = 144225 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "2.0.7"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version == '3.7.*'",
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/af/47/b215df9f71b4fdba1025fc05a77db2ad243fa0926755a52c5e71659f4e3c/urllib3-2.0.7.tar.gz", hash = "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84", size = 282546 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/b2/b157855192a68541a91ba7b2bbcb91f1b4faa51f8bae38d8005c034be524/urllib3-2.0.7-py3-none-any.whl", hash = "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e", size = 124213 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "2.2.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version == '3.8.*'",
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ed/63/22ba4ebfe7430b76388e7cd448d5478814d3032121827c12a2cc287e2260/urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9", size = 300677 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac", size = 126338 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "2.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version >= '3.9'",
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/aa/63/e53da845320b757bf29ef6a9062f5c669fe997973f966045cb019c3f4b66/urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d", size = 307268 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/19/4ec628951a74043532ca2cf5d97b7b14863931476d117c471e8e2b1eb39f/urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", size = 128369 },
|
||||
]
|
Loading…
Reference in a new issue