mirror of
https://github.com/revanced/revanced-api.git
synced 2025-04-29 22:24:31 +02:00
Merge pull request #126 from ReVanced/dev
feat: manager endpoints and more
This commit is contained in:
commit
71f81f7f20
@ -12,7 +12,7 @@ repos:
|
||||
- id: check-toml
|
||||
- id: check-merge-conflict
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 23.9.1
|
||||
rev: 23.11.0
|
||||
hooks:
|
||||
- id: black
|
||||
language_version: python3.11
|
||||
|
9
.vscode/settings.json
vendored
9
.vscode/settings.json
vendored
@ -1,3 +1,10 @@
|
||||
{
|
||||
"python.analysis.typeCheckingMode": "off"
|
||||
"python.analysis.typeCheckingMode": "off",
|
||||
"spellright.language": [
|
||||
"pt"
|
||||
],
|
||||
"spellright.documentTypes": [
|
||||
"markdown",
|
||||
"latex"
|
||||
]
|
||||
}
|
||||
|
@ -1,7 +1,10 @@
|
||||
FROM python:3.11-slim
|
||||
|
||||
ARG GITHUB_TOKEN
|
||||
ARG SENTRY_DSN
|
||||
|
||||
ENV GITHUB_TOKEN $GITHUB_TOKEN
|
||||
ENV SENTRY_DSN $SENTRY_DSN
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
|
@ -1,25 +1,27 @@
|
||||
# api/__init__.py
|
||||
from sanic import Blueprint
|
||||
import importlib
|
||||
import pkgutil
|
||||
from api.utils.versioning import get_version
|
||||
|
||||
from api.github import github
|
||||
from api.ping import ping
|
||||
from api.socials import socials
|
||||
from api.info import info
|
||||
from api.compat import github as compat
|
||||
from api.donations import donations
|
||||
from api.announcements import announcements
|
||||
from api.login import login
|
||||
from api.robots import robots
|
||||
# Dynamically import all modules in the 'api' package, excluding subdirectories
|
||||
versioned_blueprints = {}
|
||||
for finder, module_name, ispkg in pkgutil.iter_modules(["api"]):
|
||||
if not ispkg:
|
||||
# Import the module
|
||||
module = importlib.import_module(f"api.{module_name}")
|
||||
|
||||
api = Blueprint.group(
|
||||
login,
|
||||
ping,
|
||||
github,
|
||||
info,
|
||||
socials,
|
||||
donations,
|
||||
announcements,
|
||||
compat,
|
||||
robots,
|
||||
url_prefix="/",
|
||||
)
|
||||
# Add the module's blueprint to the versioned list, if it exists
|
||||
if hasattr(module, module_name):
|
||||
blueprint = getattr(module, module_name)
|
||||
version = get_version(module_name)
|
||||
versioned_blueprints.setdefault(version, []).append(blueprint)
|
||||
|
||||
# Create Blueprint groups for each version
|
||||
api = []
|
||||
for version, blueprints in versioned_blueprints.items():
|
||||
if version == "old":
|
||||
group = Blueprint.group(*blueprints, url_prefix="/")
|
||||
else:
|
||||
group = Blueprint.group(*blueprints, version=version, url_prefix="/")
|
||||
api.append(group)
|
||||
|
@ -10,6 +10,7 @@ Routes:
|
||||
- DELETE /announcements/<announcement_id:int>: Delete an announcement.
|
||||
"""
|
||||
|
||||
import os
|
||||
import datetime
|
||||
from sanic import Blueprint, Request
|
||||
from sanic.response import JSONResponse, json
|
||||
@ -20,10 +21,9 @@ from data.models import AnnouncementDbModel, AttachmentDbModel
|
||||
import sanic_beskar
|
||||
|
||||
from api.models.announcements import AnnouncementResponseModel
|
||||
from config import api_version
|
||||
from limiter import limiter
|
||||
from api.utils.limiter import limiter
|
||||
|
||||
announcements: Blueprint = Blueprint("announcements", version=api_version)
|
||||
announcements: Blueprint = Blueprint(os.path.basename(__file__).strip(".py"))
|
||||
|
||||
|
||||
@announcements.get("/announcements")
|
||||
|
32
api/apkdl.py
32
api/apkdl.py
@ -1,32 +0,0 @@
|
||||
"""
|
||||
This module provides a blueprint for the app endpoint.
|
||||
|
||||
Routes:
|
||||
- GET /app/info: Get app info.
|
||||
"""
|
||||
|
||||
from sanic import Blueprint, Request
|
||||
from sanic.response import JSONResponse, json
|
||||
from sanic_ext import openapi
|
||||
|
||||
from api.backends.apkdl import ApkDl
|
||||
from api.backends.entities import AppInfo
|
||||
from api.models.appinfo import AppInfoModel
|
||||
|
||||
from config import api_version
|
||||
|
||||
apkdl: Blueprint = Blueprint("app", version=api_version)
|
||||
|
||||
apkdl_backend: ApkDl = ApkDl()
|
||||
|
||||
|
||||
@apkdl.get("/app/info/<app_id:str>")
|
||||
@openapi.definition(
|
||||
summary="Get information about an app",
|
||||
response=[AppInfoModel],
|
||||
)
|
||||
async def root(request: Request, app_id: str) -> JSONResponse:
|
||||
data: dict[str, AppInfo] = {
|
||||
"app_info": await apkdl_backend.get_app_info(package_name=app_id)
|
||||
}
|
||||
return json(data, status=200)
|
@ -1,64 +0,0 @@
|
||||
from base64 import b64encode
|
||||
|
||||
from aiohttp import ClientResponse
|
||||
from bs4 import BeautifulSoup
|
||||
from sanic import SanicException
|
||||
from toolz.functoolz import compose
|
||||
|
||||
from api.backends.backend import AppInfoProvider
|
||||
from api.backends.entities import AppInfo
|
||||
from api.utils.http_utils import http_get
|
||||
|
||||
name: str = "apkdl"
|
||||
base_url: str = "https://apk-dl.com"
|
||||
|
||||
|
||||
class ApkDl(AppInfoProvider):
|
||||
def __init__(self):
|
||||
super().__init__(name, base_url)
|
||||
|
||||
async def get_app_info(self, package_name: str) -> AppInfo:
|
||||
"""Fetches information about an Android app from the ApkDl website.
|
||||
|
||||
Args:
|
||||
package_name (str): The package name of the app to fetch.
|
||||
|
||||
Returns:
|
||||
AppInfo: An AppInfo object containing the name, category, and logo of the app.
|
||||
|
||||
Raises:
|
||||
SanicException: If the HTTP request fails or the app data is incomplete or not found.
|
||||
"""
|
||||
app_url: str = f"{base_url}/{package_name}"
|
||||
response: ClientResponse = await http_get(headers={}, url=app_url)
|
||||
if response.status != 200:
|
||||
raise SanicException(
|
||||
f"ApkDl: {response.status}", status_code=response.status
|
||||
)
|
||||
page = BeautifulSoup(await response.read(), "lxml")
|
||||
find_div_text = compose(
|
||||
lambda d: d.find_next_sibling("div"),
|
||||
lambda d: page.find("div", text=d),
|
||||
)
|
||||
fetch_logo_url = compose(
|
||||
lambda div: div.img["src"],
|
||||
lambda _: page.find("div", {"class": "logo"}),
|
||||
)
|
||||
logo_response: ClientResponse = await http_get(
|
||||
headers={}, url=fetch_logo_url(None)
|
||||
)
|
||||
logo: str = (
|
||||
f"data:image/png;base64,{b64encode(await logo_response.content.read()).decode('utf-8')}"
|
||||
if logo_response.status == 200
|
||||
else ""
|
||||
)
|
||||
app_data = dict(
|
||||
name=find_div_text("App Name").text,
|
||||
category=find_div_text("Category").text,
|
||||
logo=logo,
|
||||
)
|
||||
if not all(app_data.values()):
|
||||
raise SanicException(
|
||||
"ApkDl: App data incomplete or not found", status_code=500
|
||||
)
|
||||
return AppInfo(**app_data)
|
@ -1,5 +1,4 @@
|
||||
import asyncio
|
||||
from json import loads
|
||||
import os
|
||||
from operator import eq
|
||||
from typing import Optional
|
||||
@ -7,9 +6,9 @@ from typing import Optional
|
||||
import ujson
|
||||
from aiohttp import ClientResponse
|
||||
from sanic import SanicException
|
||||
from toolz import filter, map, partial
|
||||
from toolz.dicttoolz import get_in, keyfilter
|
||||
from toolz.itertoolz import mapcat, pluck
|
||||
from cytoolz import filter, map, partial, curry, pipe
|
||||
from cytoolz.dicttoolz import get_in, keyfilter
|
||||
from cytoolz.itertoolz import mapcat, pluck
|
||||
|
||||
from api.backends.backend import Backend, Repository
|
||||
from api.backends.entities import *
|
||||
@ -396,3 +395,46 @@ class Github(Backend):
|
||||
)
|
||||
|
||||
return list(map(lambda pair: transform(*pair), zip(results, repositories)))
|
||||
|
||||
async def generate_custom_sources(
|
||||
self, repositories: list[GithubRepository], dev: bool
|
||||
) -> dict[str, dict[str, str]]:
|
||||
"""Generate a custom sources dictionary for a set of repositories.
|
||||
|
||||
Args:
|
||||
repositories (list[GithubRepository]): The repositories for which to generate the sources.
|
||||
dev (bool): If we should get the latest pre-release instead.
|
||||
|
||||
Returns:
|
||||
dict[str, dict[str, str]]: A dictionary containing the custom sources.
|
||||
"""
|
||||
|
||||
# Helper functions
|
||||
filter_by_name = curry(lambda name, item: name in item["name"])
|
||||
filter_patches_jar = curry(
|
||||
lambda item: "patches" in item["name"] and item["name"].endswith(".jar")
|
||||
)
|
||||
get_fields = curry(
|
||||
lambda fields, item: {field: item[field] for field in fields}
|
||||
)
|
||||
rename_key = curry(
|
||||
lambda old, new, d: {new if k == old else k: v for k, v in d.items()}
|
||||
)
|
||||
|
||||
sources = await self.compat_get_tools(repositories, dev)
|
||||
|
||||
patches = pipe(
|
||||
sources,
|
||||
lambda items: next(filter(filter_patches_jar, items), None),
|
||||
get_fields(["version", "browser_download_url"]),
|
||||
rename_key("browser_download_url", "url"),
|
||||
)
|
||||
|
||||
integrations = pipe(
|
||||
sources,
|
||||
lambda items: next(filter(filter_by_name("integrations"), items), None),
|
||||
get_fields(["version", "browser_download_url"]),
|
||||
rename_key("browser_download_url", "url"),
|
||||
)
|
||||
|
||||
return {"patches": patches, "integrations": integrations}
|
||||
|
@ -9,8 +9,7 @@ Routes:
|
||||
- GET /patches/<tag:str>: Retrieve a list of patches for a given release tag.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
import os
|
||||
from sanic import Blueprint, Request
|
||||
from sanic.response import JSONResponse, json
|
||||
from sanic_ext import openapi
|
||||
@ -20,12 +19,12 @@ from api.models.github import *
|
||||
from api.models.compat import ToolsResponseModel, ContributorsResponseModel
|
||||
from config import compat_repositories, owner
|
||||
|
||||
github: Blueprint = Blueprint("old")
|
||||
compat: Blueprint = Blueprint(os.path.basename(__file__).strip(".py"))
|
||||
|
||||
github_backend: Github = Github()
|
||||
|
||||
|
||||
@github.get("/tools")
|
||||
@compat.get("/tools")
|
||||
@openapi.definition(
|
||||
summary="Get patching tools' latest version.", response=[ToolsResponseModel]
|
||||
)
|
||||
@ -62,7 +61,7 @@ async def tools(request: Request) -> JSONResponse:
|
||||
return json(data, status=200)
|
||||
|
||||
|
||||
@github.get("/contributors")
|
||||
@compat.get("/contributors")
|
||||
@openapi.definition(
|
||||
summary="Get organization-wise contributors.", response=[ContributorsResponseModel]
|
||||
)
|
||||
|
@ -5,14 +5,16 @@ Routes:
|
||||
- GET /donations: Get ReVanced donation links and wallets.
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from sanic import Blueprint, Request
|
||||
from sanic.response import JSONResponse, json
|
||||
from sanic_ext import openapi
|
||||
|
||||
from api.models.donations import DonationsResponseModel
|
||||
from config import api_version, wallets, links
|
||||
from config import wallets, links
|
||||
|
||||
donations: Blueprint = Blueprint("donations", version=api_version)
|
||||
donations: Blueprint = Blueprint(os.path.basename(__file__).strip(".py"))
|
||||
|
||||
|
||||
@donations.get("/donations")
|
||||
|
@ -10,6 +10,7 @@ Routes:
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
from sanic import Blueprint, Request
|
||||
from sanic.response import JSONResponse, json
|
||||
from sanic_ext import openapi
|
||||
@ -17,9 +18,9 @@ from sanic_ext import openapi
|
||||
from api.backends.entities import Release, Contributor
|
||||
from api.backends.github import Github, GithubRepository
|
||||
from api.models.github import *
|
||||
from config import owner, default_repository, api_version
|
||||
from config import owner, default_repository
|
||||
|
||||
github: Blueprint = Blueprint("github", version=api_version)
|
||||
github: Blueprint = Blueprint(os.path.basename(__file__).strip(".py"))
|
||||
|
||||
github_backend: Github = Github()
|
||||
|
||||
|
@ -5,14 +5,15 @@ Routes:
|
||||
- GET /info: Get info about the owner of the API.
|
||||
"""
|
||||
|
||||
import os
|
||||
from sanic import Blueprint, Request
|
||||
from sanic.response import JSONResponse, json
|
||||
from sanic_ext import openapi
|
||||
|
||||
from api.models.info import InfoResponseModel
|
||||
from config import api_version, default_info
|
||||
from config import default_info
|
||||
|
||||
info: Blueprint = Blueprint("info", version=api_version)
|
||||
info: Blueprint = Blueprint(os.path.basename(__file__).strip(".py"))
|
||||
|
||||
|
||||
@info.get("/info")
|
||||
|
10
api/login.py
10
api/login.py
@ -5,18 +5,16 @@ Routes:
|
||||
- POST /login: Login to the API
|
||||
"""
|
||||
|
||||
import os
|
||||
from sanic import Blueprint, Request
|
||||
from sanic.response import JSONResponse, json
|
||||
from sanic_ext import openapi
|
||||
from sanic_beskar.exceptions import AuthenticationError
|
||||
|
||||
from auth import beskar
|
||||
from limiter import limiter
|
||||
from api.utils.auth import beskar
|
||||
from api.utils.limiter import limiter
|
||||
|
||||
from config import api_version
|
||||
|
||||
|
||||
login: Blueprint = Blueprint("login", version=api_version)
|
||||
login: Blueprint = Blueprint(os.path.basename(__file__).strip(".py"))
|
||||
|
||||
|
||||
@login.post("/login")
|
||||
|
61
api/manager.py
Normal file
61
api/manager.py
Normal file
@ -0,0 +1,61 @@
|
||||
"""
|
||||
This module provides ReVanced Manager specific endpoints.
|
||||
|
||||
Routes:
|
||||
- GET /manager/bootstrap: Get a list of the main ReVanced tools.
|
||||
- GET /manager/sources: Get a list of ReVanced sources.
|
||||
"""
|
||||
|
||||
import os
|
||||
from sanic import Blueprint, Request
|
||||
from sanic.response import JSONResponse, json
|
||||
from sanic_ext import openapi
|
||||
|
||||
from api.backends.github import GithubRepository, Github
|
||||
|
||||
from api.models.manager import BootsrapResponseModel, CustomSourcesResponseModel
|
||||
from config import compat_repositories, owner
|
||||
|
||||
manager: Blueprint = Blueprint(os.path.basename(__file__).strip(".py"))
|
||||
|
||||
github_backend: Github = Github()
|
||||
|
||||
|
||||
@manager.get("/manager/bootstrap")
|
||||
@openapi.definition(
|
||||
summary="Get a list of the main ReVanced tools",
|
||||
response=[BootsrapResponseModel],
|
||||
)
|
||||
async def bootstrap(request: Request) -> JSONResponse:
|
||||
"""
|
||||
Returns a JSONResponse with a list of the main ReVanced tools.
|
||||
|
||||
**Returns:**
|
||||
- JSONResponse: A Sanic JSONResponse instance containing a list with the tool names.
|
||||
"""
|
||||
data: dict[str, dict] = {"tools": compat_repositories}
|
||||
return json(data, status=200)
|
||||
|
||||
|
||||
@manager.get("/manager/custom-source")
|
||||
@openapi.definition(
|
||||
summary="Get a list of ReVanced sources",
|
||||
response=[CustomSourcesResponseModel],
|
||||
)
|
||||
async def custom_sources(request: Request) -> JSONResponse:
|
||||
"""
|
||||
Returns a JSONResponse with a list of the main ReVanced sources.
|
||||
|
||||
**Returns:**
|
||||
- JSONResponse: A Sanic JSONResponse instance containing a list with the source names.
|
||||
"""
|
||||
data = await github_backend.generate_custom_sources(
|
||||
repositories=[
|
||||
GithubRepository(owner=owner, name=repo)
|
||||
for repo in compat_repositories
|
||||
if "patches" in repo or "integrations" in repo
|
||||
],
|
||||
dev=True if request.args.get("dev") else False,
|
||||
)
|
||||
|
||||
return json(data, status=200)
|
@ -1,19 +0,0 @@
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class AppInfoFields(BaseModel):
|
||||
"""
|
||||
Fields for the AppInfo endpoint.
|
||||
"""
|
||||
|
||||
name: str
|
||||
category: str
|
||||
logo: str
|
||||
|
||||
|
||||
class AppInfoModel(BaseModel):
|
||||
"""
|
||||
Response model app info.
|
||||
"""
|
||||
|
||||
app_info: AppInfoFields
|
32
api/models/manager.py
Normal file
32
api/models/manager.py
Normal file
@ -0,0 +1,32 @@
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class BootsrapResponseModel(BaseModel):
|
||||
"""
|
||||
A Pydantic BaseModel that represents a list of available tools.
|
||||
"""
|
||||
|
||||
tools: list[str]
|
||||
"""
|
||||
A list of available tools.
|
||||
"""
|
||||
|
||||
|
||||
class CustomSourcesFields(BaseModel):
|
||||
"""
|
||||
Implements the fields for a source.
|
||||
"""
|
||||
|
||||
url: str
|
||||
preferred: bool
|
||||
|
||||
|
||||
class CustomSourcesResponseModel(BaseModel):
|
||||
"""
|
||||
A Pydantic BaseModel that represents a list of available sources.
|
||||
"""
|
||||
|
||||
_: dict[str, CustomSourcesFields]
|
||||
"""
|
||||
A list of available sources.
|
||||
"""
|
@ -5,11 +5,11 @@ Routes:
|
||||
- HEAD /ping: Ping the API.
|
||||
"""
|
||||
|
||||
import os
|
||||
from sanic import Blueprint, HTTPResponse, Request, response
|
||||
from sanic_ext import openapi
|
||||
from config import api_version
|
||||
|
||||
ping: Blueprint = Blueprint("ping", version=api_version)
|
||||
ping: Blueprint = Blueprint(os.path.basename(__file__).strip(".py"))
|
||||
|
||||
|
||||
@ping.head("/ping")
|
||||
|
@ -1,8 +1,9 @@
|
||||
import os
|
||||
from sanic import Blueprint
|
||||
from sanic.response import text
|
||||
|
||||
|
||||
robots: Blueprint = Blueprint("robots")
|
||||
robots: Blueprint = Blueprint(os.path.basename(__file__).strip(".py"))
|
||||
|
||||
|
||||
@robots.get("/robots.txt")
|
||||
|
@ -5,14 +5,15 @@ Routes:
|
||||
- GET /socials: Get ReVanced socials.
|
||||
"""
|
||||
|
||||
import os
|
||||
from sanic import Blueprint, Request
|
||||
from sanic.response import JSONResponse, json
|
||||
from sanic_ext import openapi
|
||||
|
||||
from api.models.socials import SocialsResponseModel
|
||||
from config import social_links, api_version
|
||||
from config import social_links
|
||||
|
||||
socials: Blueprint = Blueprint("socials", version=api_version)
|
||||
socials: Blueprint = Blueprint(os.path.basename(__file__).strip(".py"))
|
||||
|
||||
|
||||
@socials.get("/socials")
|
||||
|
8
api/utils/versioning.py
Normal file
8
api/utils/versioning.py
Normal file
@ -0,0 +1,8 @@
|
||||
from cytoolz import keyfilter
|
||||
from config import api_versions
|
||||
|
||||
|
||||
def get_version(value: str) -> str:
|
||||
result = keyfilter(lambda key: value in api_versions[key], api_versions)
|
||||
|
||||
return list(result.keys())[0] if result else "v0"
|
48
app.py
48
app.py
@ -1,19 +1,34 @@
|
||||
# app.py
|
||||
from sanic import Sanic
|
||||
|
||||
import os
|
||||
from typing import Any
|
||||
|
||||
from sanic import HTTPResponse, Sanic
|
||||
import sanic.response
|
||||
from sanic_ext import Config
|
||||
|
||||
from api import api
|
||||
from config import *
|
||||
from config import openapi_title, openapi_version, openapi_description, hostnames
|
||||
|
||||
from limiter import configure_limiter
|
||||
from auth import configure_auth
|
||||
from api.utils.limiter import configure_limiter
|
||||
from api.utils.auth import configure_auth
|
||||
|
||||
import sentry_sdk
|
||||
|
||||
if os.environ.get("SENTRY_DSN"):
|
||||
sentry_sdk.init(
|
||||
dsn=os.environ["SENTRY_DSN"],
|
||||
enable_tracing=True,
|
||||
traces_sample_rate=1.0,
|
||||
)
|
||||
else:
|
||||
print("WARNING: Sentry DSN not set, not enabling Sentry")
|
||||
|
||||
REDIRECTS = {
|
||||
"/": "/docs/swagger",
|
||||
}
|
||||
|
||||
app = Sanic("ReVanced-API")
|
||||
app = Sanic("revanced-api")
|
||||
app.extend(config=Config(oas_ignore_head=False))
|
||||
app.ext.openapi.describe(
|
||||
title=openapi_title,
|
||||
@ -39,7 +54,7 @@ app.blueprint(api)
|
||||
# https://sanic.dev/en/guide/how-to/static-redirects.html
|
||||
|
||||
|
||||
def get_static_function(value):
|
||||
def get_static_function(value) -> Any:
|
||||
return lambda *_, **__: value
|
||||
|
||||
|
||||
@ -47,13 +62,26 @@ for src, dest in REDIRECTS.items():
|
||||
app.route(src)(get_static_function(sanic.response.redirect(dest)))
|
||||
|
||||
|
||||
@app.middleware("response")
|
||||
async def add_cache_control(request, response):
|
||||
@app.on_request
|
||||
async def domain_check(request) -> HTTPResponse:
|
||||
if request.host not in hostnames:
|
||||
return sanic.response.redirect(f"https://api.revanced.app/{request.path}")
|
||||
|
||||
|
||||
@app.on_response
|
||||
async def add_cache_control(_, response):
|
||||
response.headers["Cache-Control"] = "public, max-age=300"
|
||||
|
||||
|
||||
@app.middleware("response")
|
||||
async def add_csp(request, response):
|
||||
@app.on_response
|
||||
async def add_csp(_, response):
|
||||
response.headers[
|
||||
"Content-Security-Policy"
|
||||
] = "default-src * 'unsafe-inline' 'unsafe-eval' data: blob:;"
|
||||
|
||||
|
||||
app.static(
|
||||
"/favicon.ico",
|
||||
"static/img/favicon.ico",
|
||||
name="favicon",
|
||||
)
|
||||
|
20
config.py
20
config.py
@ -2,6 +2,12 @@
|
||||
|
||||
backend: str = "github"
|
||||
redis: dict[str, str | int] = {"host": "localhost", "port": 6379}
|
||||
hostnames: list[str] = [
|
||||
"api.revanced.app",
|
||||
"deimos.revanced.app",
|
||||
"localhost:8000",
|
||||
"127.0.0.1:8000",
|
||||
]
|
||||
|
||||
# GitHub Backend Configuration
|
||||
|
||||
@ -10,6 +16,20 @@ default_repository: str = ".github"
|
||||
|
||||
# API Versioning
|
||||
|
||||
api_versions: dict[str, list[str]] = {
|
||||
"old": ["compat"],
|
||||
"v2": [
|
||||
"announcements",
|
||||
"donations",
|
||||
"github",
|
||||
"info",
|
||||
"login",
|
||||
"ping",
|
||||
"socials",
|
||||
"manager",
|
||||
],
|
||||
}
|
||||
|
||||
api_version: str = "v2"
|
||||
openapi_version: str = "2.0.0"
|
||||
openapi_title: str = "ReVanced API"
|
||||
|
1437
poetry.lock
generated
1437
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
@ -15,25 +15,26 @@ asyncstdlib = "^3.10.9"
|
||||
pydantic = "^1.10.13"
|
||||
cytoolz = "^0.12.2"
|
||||
beautifulsoup4 = "^4.12.2"
|
||||
setuptools = "^68.1.2"
|
||||
setuptools = "^69.0.2"
|
||||
lxml = "^4.9.3"
|
||||
mypy = "^1.6.1"
|
||||
mypy = "^1.7.0"
|
||||
types-ujson = "^5.8.0.1"
|
||||
types-aiofiles = "^23.2.0.0"
|
||||
sanic-testing = "^23.6.0"
|
||||
pytest-asyncio = "^0.21.1"
|
||||
types-beautifulsoup4 = "^4.12.0.6"
|
||||
types-beautifulsoup4 = "^4.12.0.7"
|
||||
pytest-md = "^0.2.0"
|
||||
pytest-emoji = "^0.2.0"
|
||||
coverage = "^7.3.2"
|
||||
pytest-cov = "^4.1.0"
|
||||
pytest = "^7.4.0"
|
||||
sqlalchemy = "^2.0.22"
|
||||
pytest = "^7.4.3"
|
||||
sqlalchemy = "^2.0.23"
|
||||
sanic-beskar = "^2.2.12"
|
||||
bson = "^0.5.10"
|
||||
fastpbkdf2 = "^0.2"
|
||||
cryptography = "^41.0.4"
|
||||
cryptography = "^41.0.5"
|
||||
sanic-limiter = { git = "https://github.com/Omegastick/sanic-limiter" }
|
||||
sentry-sdk = { extras = ["sanic"], version = "^1.35.0" }
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
asyncio_mode = "auto"
|
||||
|
@ -1,35 +1,34 @@
|
||||
aiodns==3.1.1 ; python_version >= "3.11" and python_version < "4.0"
|
||||
aiodns==3.1.1 ; (sys_platform == "linux" or sys_platform == "darwin") and python_version >= "3.11" and python_version < "4.0"
|
||||
aiofiles==23.2.1 ; python_version >= "3.11" and python_version < "4.0"
|
||||
aiohttp[speedups]==3.8.6 ; python_version >= "3.11" and python_version < "4.0"
|
||||
aiohttp[speedups]==3.9.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
aiosignal==1.3.1 ; python_version >= "3.11" and python_version < "4.0"
|
||||
anyio==4.0.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
argon2-cffi==23.1.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
argon2-cffi-bindings==21.2.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
async-timeout==4.0.3 ; python_version >= "3.11" and python_version < "4.0"
|
||||
asyncstdlib==3.10.9 ; python_version >= "3.11" and python_version < "4.0"
|
||||
attrs==23.1.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
beautifulsoup4==4.12.2 ; python_version >= "3.11" and python_version < "4.0"
|
||||
brotli==1.1.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
brotli==1.1.0 ; platform_python_implementation == "CPython" and python_version >= "3.11" and python_version < "4.0"
|
||||
brotlicffi==1.1.0.0 ; platform_python_implementation != "CPython" and python_version >= "3.11" and python_version < "4.0"
|
||||
bson==0.5.10 ; python_version >= "3.11" and python_version < "4.0"
|
||||
certifi==2023.7.22 ; python_version >= "3.11" and python_version < "4.0"
|
||||
certifi==2023.11.17 ; python_version >= "3.11" and python_version < "4.0"
|
||||
cffi==1.16.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
charset-normalizer==3.3.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
colorama==0.4.6 ; python_version >= "3.11" and python_version < "4.0" and sys_platform == "win32"
|
||||
coverage==7.3.2 ; python_version >= "3.11" and python_version < "4.0"
|
||||
coverage[toml]==7.3.2 ; python_version >= "3.11" and python_version < "4.0"
|
||||
cryptography==41.0.4 ; python_version >= "3.11" and python_version < "4.0"
|
||||
cryptography==41.0.5 ; python_version >= "3.11" and python_version < "4.0"
|
||||
cytoolz==0.12.2 ; python_version >= "3.11" and python_version < "4.0"
|
||||
deprecated==1.2.14 ; python_version >= "3.11" and python_version < "4.0"
|
||||
fastpbkdf2==0.2 ; python_version >= "3.11" and python_version < "4.0"
|
||||
frozenlist==1.4.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
greenlet==3.0.0 ; python_version >= "3.11" and python_version < "4.0" and platform_machine == "aarch64" or python_version >= "3.11" and python_version < "4.0" and platform_machine == "ppc64le" or python_version >= "3.11" and python_version < "4.0" and platform_machine == "x86_64" or python_version >= "3.11" and python_version < "4.0" and platform_machine == "amd64" or python_version >= "3.11" and python_version < "4.0" and platform_machine == "AMD64" or python_version >= "3.11" and python_version < "4.0" and platform_machine == "win32" or python_version >= "3.11" and python_version < "4.0" and platform_machine == "WIN32"
|
||||
greenlet==3.0.1 ; python_version >= "3.11" and python_version < "4.0" and platform_machine == "aarch64" or python_version >= "3.11" and python_version < "4.0" and platform_machine == "ppc64le" or python_version >= "3.11" and python_version < "4.0" and platform_machine == "x86_64" or python_version >= "3.11" and python_version < "4.0" and platform_machine == "amd64" or python_version >= "3.11" and python_version < "4.0" and platform_machine == "AMD64" or python_version >= "3.11" and python_version < "4.0" and platform_machine == "win32" or python_version >= "3.11" and python_version < "4.0" and platform_machine == "WIN32"
|
||||
h11==0.14.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
html5tagger==1.3.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
httpcore==0.18.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
httpcore==1.0.2 ; python_version >= "3.11" and python_version < "4.0"
|
||||
httptools==0.6.1 ; python_version >= "3.11" and python_version < "4.0"
|
||||
httpx==0.25.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
httpx==0.25.1 ; python_version >= "3.11" and python_version < "4.0"
|
||||
idna==3.4 ; python_version >= "3.11" and python_version < "4.0"
|
||||
importlib-resources==6.1.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
importlib-resources==6.1.1 ; python_version >= "3.11" and python_version < "4.0"
|
||||
iniconfig==2.0.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
iso8601==2.1.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
jinja2==3.1.2 ; python_version >= "3.11" and python_version < "4.0"
|
||||
@ -37,20 +36,20 @@ limits==3.6.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
lxml==4.9.3 ; python_version >= "3.11" and python_version < "4.0"
|
||||
markupsafe==2.1.3 ; python_version >= "3.11" and python_version < "4.0"
|
||||
multidict==6.0.4 ; python_version >= "3.11" and python_version < "4.0"
|
||||
mypy==1.6.1 ; python_version >= "3.11" and python_version < "4.0"
|
||||
mypy==1.7.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
mypy-extensions==1.0.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
packaging==23.2 ; python_version >= "3.11" and python_version < "4.0"
|
||||
passlib==1.7.4 ; python_version >= "3.11" and python_version < "4.0"
|
||||
pendulum==2.1.2 ; python_version >= "3.11" and python_version < "4.0"
|
||||
pluggy==1.3.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
py-buzz==4.1.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
pycares==4.4.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
pycares==4.4.0 ; (sys_platform == "linux" or sys_platform == "darwin") and python_version >= "3.11" and python_version < "4.0"
|
||||
pycparser==2.21 ; python_version >= "3.11" and python_version < "4.0"
|
||||
pycryptodomex==3.19.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
pydantic==1.10.13 ; python_version >= "3.11" and python_version < "4.0"
|
||||
pyjwt==2.8.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
pyseto==1.7.5 ; python_version >= "3.11" and python_version < "4.0"
|
||||
pytest==7.4.2 ; python_version >= "3.11" and python_version < "4.0"
|
||||
pyseto==1.7.6 ; python_version >= "3.11" and python_version < "4.0"
|
||||
pytest==7.4.3 ; python_version >= "3.11" and python_version < "4.0"
|
||||
pytest-asyncio==0.21.1 ; python_version >= "3.11" and python_version < "4.0"
|
||||
pytest-cov==4.1.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
pytest-emoji==0.2.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
@ -65,20 +64,22 @@ sanic-limiter @ git+https://github.com/Omegastick/sanic-limiter ; python_version
|
||||
sanic-routing==23.6.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
sanic-testing==23.6.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
sanic[ext]==23.6.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
sentry-sdk[sanic]==1.36.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
setuptools==68.2.2 ; python_version >= "3.11" and python_version < "4.0"
|
||||
six==1.16.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
sniffio==1.3.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
soupsieve==2.5 ; python_version >= "3.11" and python_version < "4.0"
|
||||
sqlalchemy==2.0.22 ; python_version >= "3.11" and python_version < "4.0"
|
||||
sqlalchemy==2.0.23 ; python_version >= "3.11" and python_version < "4.0"
|
||||
toolz==0.12.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
tracerite==1.1.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
tracerite==1.1.1 ; python_version >= "3.11" and python_version < "4.0"
|
||||
types-aiofiles==23.2.0.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
types-beautifulsoup4==4.12.0.6 ; python_version >= "3.11" and python_version < "4.0"
|
||||
types-beautifulsoup4==4.12.0.7 ; python_version >= "3.11" and python_version < "4.0"
|
||||
types-html5lib==1.1.11.15 ; python_version >= "3.11" and python_version < "4.0"
|
||||
types-ujson==5.8.0.1 ; python_version >= "3.11" and python_version < "4.0"
|
||||
typing-extensions==4.8.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
ujson==5.8.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
uvloop==0.18.0 ; sys_platform != "win32" and implementation_name == "cpython" and python_version >= "3.11" and python_version < "4.0"
|
||||
websockets==11.0.3 ; python_version >= "3.11" and python_version < "4.0"
|
||||
wrapt==1.15.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
yarl==1.9.2 ; python_version >= "3.11" and python_version < "4.0"
|
||||
urllib3==2.1.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
uvloop==0.19.0 ; sys_platform != "win32" and implementation_name == "cpython" and python_version >= "3.11" and python_version < "4.0"
|
||||
websockets==12.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
wrapt==1.16.0 ; python_version >= "3.11" and python_version < "4.0"
|
||||
yarl==1.9.3 ; python_version >= "3.11" and python_version < "4.0"
|
||||
|
BIN
static/img/favicon.ico
Normal file
BIN
static/img/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
Loading…
x
Reference in New Issue
Block a user