Merge branch 'dev' into feat/contributors/contributions

This commit is contained in:
Alexandre Teles 2022-12-26 17:44:22 -03:00 committed by GitHub
commit 279a2bcbef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 662 additions and 496 deletions

View File

@ -1,4 +1,4 @@
ARG VARIANT="3.10-bullseye"
ARG VARIANT="3.11-bullseye"
FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT}
ARG NODE_VERSION="none"

View File

@ -9,7 +9,7 @@
// Update 'VARIANT' to pick a Python version: 3, 3.10, 3.9, 3.8, 3.7, 3.6
// Append -bullseye or -buster to pin to an OS version.
// Use -bullseye variants on local on arm64/Apple Silicon.
"VARIANT": "3.10-bullseye",
"VARIANT": "3.11-bullseye",
// Options
"NODE_VERSION": "lts/*"
}

View File

@ -35,7 +35,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10.7'
python-version: '3.11.0'
- name: Install dependencies
run: |
python -m pip install --upgrade pip

View File

@ -12,7 +12,7 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: 3.10.8
python-version: 3.11.0
architecture: x64
- name: Checkout
uses: actions/checkout@v3

View File

@ -1,4 +1,4 @@
FROM python:3.10-slim
FROM python:3.11-slim
ARG GITHUB_TOKEN
ENV GITHUB_TOKEN $GITHUB_TOKEN

View File

@ -1,4 +1,4 @@
import toml
from redis import asyncio as aioredis
import app.utils.Logger as Logger
@ -6,7 +6,9 @@ from app.utils.Generators import Generators
from app.models.AnnouncementModels import AnnouncementCreateModel
from app.utils.RedisConnector import RedisConnector
config: dict = toml.load("config.toml")
from app.dependencies import load_config
config: dict = load_config()
class Announcements:
"""Implements the announcements class for the ReVanced API"""

View File

@ -1,11 +1,13 @@
from datetime import timedelta
import os
import toml
from datetime import timedelta
from pydantic import BaseModel
from fastapi_paseto_auth import AuthPASETO
config: dict = toml.load("config.toml")
from app.dependencies import load_config
config: dict = load_config()
class PasetoSettings(BaseModel):
authpaseto_secret_key: str = os.environ['SECRET_KEY']

View File

@ -1,5 +1,5 @@
from time import sleep
import toml
import orjson
from typing import Optional
import argon2
@ -12,7 +12,9 @@ from app.utils.Generators import Generators
from app.models.ClientModels import ClientModel
from app.utils.RedisConnector import RedisConnector
config: dict = toml.load("config.toml")
from app.dependencies import load_config
config: dict = load_config()
class Clients:

View File

@ -1,10 +1,12 @@
import toml
from redis import asyncio as aioredis
import app.utils.Logger as Logger
from app.models.MirrorModels import MirrorModel, MirrorStoreModel
from app.utils.RedisConnector import RedisConnector
config: dict = toml.load("config.toml")
from app.dependencies import load_config
config: dict = load_config()
class Mirrors:
"""Implements the Mirror class for the ReVanced API"""

View File

@ -3,6 +3,7 @@ import uvloop
import orjson
from base64 import b64decode
from toolz.dicttoolz import keyfilter
import asyncstdlib.builtins as a
from app.utils.HTTPXClient import HTTPXClient
class Releases:
@ -32,7 +33,7 @@ class Releases:
release_tarball: str = response.json()['tarball_url']
release_timestamp: str = response.json()['published_at']
def get_asset_data(asset: dict) -> dict:
async def get_asset_data(asset: dict) -> dict:
return {'repository': repository,
'version': release_version,
'timestamp': asset['updated_at'],
@ -42,16 +43,16 @@ class Releases:
'content_type': asset['content_type']
}
no_release_assets_data: dict = {'repository': repository,
'version': release_version,
'timestamp': release_timestamp,
'name': f"{repository.split('/')[1]}-{release_version}.tar.gz",
'browser_download_url': release_tarball,
'content_type': 'application/gzip'
}
if release_assets:
assets = [get_asset_data(asset) for asset in release_assets]
assets = await asyncio.gather(*[get_asset_data(asset) for asset in release_assets])
else:
no_release_assets_data: dict = {'repository': repository,
'version': release_version,
'timestamp': release_timestamp,
'name': f"{repository.split('/')[1]}-{release_version}.tar.gz",
'browser_download_url': release_tarball,
'content_type': 'application/gzip'
}
assets.append(no_release_assets_data)
return assets
@ -139,7 +140,7 @@ class Releases:
results: list[dict] = await asyncio.gather(*[self.__get_contributors(repository) for repository in revanced_repositories])
for key, value in zip(revanced_repositories, results):
async for key, value in a.zip(revanced_repositories, results):
data = {'name': key, 'contributors': value}
contributors['repositories'].append(data)
@ -172,25 +173,35 @@ class Releases:
f"https://api.github.com/repos/{org}/{repository}/releases?per_page=2"
)
releases = _releases.json()
if _releases.status_code == 200:
releases = _releases.json()
if any(releases):
since = releases[1]['created_at']
until = releases[0]['created_at']
else:
raise ValueError("No releases found")
since = releases[1]['created_at']
until = releases[0]['created_at']
_response = await self.httpx_client.get(
f"https://api.github.com/repos/{org}/{repository}/commits?path={path}&since={since}&until={until}"
)
if _response.status_code == 200:
response = _response.json()
_response = await self.httpx_client.get(
f"https://api.github.com/repos/{org}/{repository}/commits?path={path}&since={since}&until={until}"
)
response = _response.json()
for commit in response:
data: dict[str, str] = {}
data["sha"] = commit["sha"]
data["author"] = commit["commit"]["author"]["name"]
data["message"] = commit["commit"]["message"]
data["html_url"] = commit["html_url"]
payload['commits'].append(data)
return payload
async def get_commit_data(commit: dict) -> dict:
return {'sha': commit['sha'],
'author': commit['commit']['author']['name'],
'date': commit['commit']['author']['date'],
'message': commit['commit']['message'],
'url': commit['html_url']
}
data: list = await asyncio.gather(*[get_commit_data(commit) for commit in response])
payload['commits'].append(data)
else:
raise ValueError("Error retrieving commits")
else:
raise Exception("Invalid organization.")
raise ValueError("Invalid organization.")
return payload

View File

@ -0,0 +1,18 @@
from app.dependencies import load_config
config: dict = load_config()
class Socials:
"""Implements the code infrastructure for the socials page."""
async def get_socials(self) -> dict:
"""Get socials from config.toml.
Returns:
dict: A dictionary containing socials from config.toml
"""
socials: dict = config['socials']
return socials

View File

@ -1,4 +1,4 @@
import toml
import tomllib as toml
def load_config() -> dict:
"""Loads the config.toml file.
@ -6,4 +6,7 @@ def load_config() -> dict:
Returns:
dict: the config.toml file as a dict
"""
return toml.load("config.toml")
with open('config.toml', 'rb') as config_file:
return toml.load(config_file)

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3
import os
import toml
import binascii
from redis import Redis
@ -34,15 +34,18 @@ from app.routers import tools
from app.routers import clients
from app.routers import patches
from app.routers import mirrors
from app.routers import socials
from app.routers import changelogs
from app.routers import contributors
from app.routers import announcement
from app.dependencies import load_config
"""Get latest ReVanced releases from GitHub API."""
# Load config
config: dict = toml.load("config.toml")
config: dict = load_config()
# Create FastAPI instance
@ -74,6 +77,7 @@ app.include_router(tools.router)
app.include_router(patches.router)
app.include_router(contributors.router)
app.include_router(changelogs.router)
app.include_router(socials.router)
app.include_router(auth.router)
app.include_router(clients.router)
app.include_router(announcement.router)

View File

@ -107,3 +107,12 @@ class RevokedTokenResponse(BaseModel):
"""
revoked: bool
class SocialsResponseModel(BaseModel):
"""Implements the JSON response model for the /socials endpoint.
Args:
BaseModel (pydantic.BaseModel): BaseModel from pydantic
"""
__root__: dict[ str, str ]

24
app/routers/socials.py Normal file
View File

@ -0,0 +1,24 @@
from fastapi_cache.decorator import cache
from fastapi import APIRouter, Request, Response
import app.models.ResponseModels as ResponseModels
from app.controllers.Socials import Socials
from app.dependencies import load_config
router = APIRouter()
socials = Socials()
config: dict = load_config()
@router.get('/socials', response_model=ResponseModels.SocialsResponseModel, tags=['ReVanced Socials'])
@cache(config['cache']['expire'])
async def get_socials(request: Request, response: Response) -> dict:
"""Get ReVanced social links.
Returns:
json: dictionary of ReVanced social links
"""
return await socials.get_socials()

View File

@ -1,10 +1,12 @@
import os
import toml
from redis import asyncio as aioredis
from app.dependencies import load_config
# Load config
config: dict = toml.load("config.toml")
config: dict = load_config()
# Redis connection parameters

View File

@ -1,5 +1,4 @@
[docs]
title = "ReVanced Releases API"
description = """
## The official JSON API for ReVanced Releases 🚀
@ -22,10 +21,9 @@ description = """
3. Abuse of the API will result in IP blocks
"""
version = "1.0.0"
version = "1.1.0"
[license]
name = "AGPL-3.0"
url = "https://www.gnu.org/licenses/agpl-3.0.en.html"
@ -57,6 +55,13 @@ database = 5
access_token_expires = false
[app]
repositories = ["TeamVanced/VancedMicroG", "revanced/revanced-cli", "revanced/revanced-patcher", "revanced/revanced-patches", "revanced/revanced-integrations", "revanced/revanced-manager", "revanced/revanced-website", "revanced/revanced-releases-api"]
[socials]
website = "https://revanced.app"
github = "https://github.com/revanced"
twitter = "https://twitter.com/revancedapp"
discord = "https://revanced.app/discord"
reddit = "https://www.reddit.com/r/revancedapp"
telegram = "https://t.me/app_revanced"
youtube = "https://www.youtube.com/@ReVanced"

View File

@ -1,5 +1,5 @@
[mypy]
python_version = 3.10
python_version = 3.11
pretty = true
follow_imports = normal
namespace_packages = true
@ -75,4 +75,8 @@ ignore_missing_imports = True
[mypy-asgiref.*]
# No stubs available
ignore_missing_imports = True
ignore_missing_imports = True
[mypy-tomllib.*]
# No stubs available
ignore_missing_imports = True

824
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,12 @@
[tool.poetry]
name = "revanced-releases-api"
version = "0.1.0"
version = "1.1.0"
description = "JSON API for ReVanced Releases"
authors = ["Alexandre Teles <alexandre.teles@ufba.br>"]
license = "AGPLv3"
[tool.poetry.dependencies]
python = "^3.10"
python = "^3.11"
fastapi = ">=0.85.0"
httpx = {version = ">=0.23.0", extras = ["http2"]}
httpx-cache = ">=0.6.0"
@ -18,7 +18,7 @@ redis = ">=4.3.4"
loguru = ">=0.6.0"
sentry-sdk = ">=1.9.8"
argon2-cffi = ">=21.3.0"
hypercorn = {extras = ["uvloop"], version = ">=0.14.3"}
uvloop = ">=0.17.0"
cytoolz = ">=0.12.0"
fastapi-paseto-auth = "^0.6.0"
ujson = ">=5.5.0"

View File

@ -1,63 +1,61 @@
aiofiles==22.1.0 ; python_version >= "3.10" and python_version < "4.0"
aiorwlock==1.3.0 ; python_version >= "3.10" and python_version < "4.0"
anyio==3.6.2 ; python_version >= "3.10" and python_version < "4.0"
argon2-cffi-bindings==21.2.0 ; python_version >= "3.10" and python_version < "4.0"
argon2-cffi==21.3.0 ; python_version >= "3.10" and python_version < "4.0"
async-timeout==4.0.2 ; python_version >= "3.10" and python_version < "4.0"
asyncstdlib==3.10.5 ; python_version >= "3.10" and python_version < "4.0"
attrs==21.4.0 ; python_version >= "3.10" and python_version < "4.0"
certifi==2022.9.24 ; python_version >= "3.10" and python_version < "4.0"
cffi==1.15.1 ; python_version >= "3.10" and python_version < "4.0"
click==8.1.3 ; python_version >= "3.10" and python_version < "4.0"
colorama==0.4.6 ; python_version >= "3.10" and python_version < "4.0" and sys_platform == "win32" or python_version >= "3.10" and python_version < "4.0" and platform_system == "Windows"
cryptography==37.0.4 ; python_version >= "3.10" and python_version < "4.0"
cytoolz==0.12.0 ; python_version >= "3.10" and python_version < "4.0"
fastapi-cache2==0.1.9 ; python_version >= "3.10" and python_version < "4.0"
fastapi-paseto-auth==0.6.0 ; python_version >= "3.10" and python_version < "4.0"
fastapi==0.85.0 ; python_version >= "3.10" and python_version < "4.0"
fasteners==0.17.3 ; python_version >= "3.10" and python_version < "4.0"
gunicorn==20.1.0 ; python_version >= "3.10" and python_version < "4.0"
h11==0.14.0 ; python_version >= "3.10" and python_version < "4.0"
h2==4.1.0 ; python_version >= "3.10" and python_version < "4.0"
hiredis==2.0.0 ; python_version >= "3.10" and python_version < "4.0"
hpack==4.0.0 ; python_version >= "3.10" and python_version < "4.0"
httpcore==0.16.2 ; python_version >= "3.10" and python_version < "4.0"
httpx-cache==0.6.1 ; python_version >= "3.10" and python_version < "4.0"
httpx==0.23.1 ; python_version >= "3.10" and python_version < "4.0"
httpx[http2]==0.23.1 ; python_version >= "3.10" and python_version < "4.0"
hypercorn[uvloop]==0.14.3 ; python_version >= "3.10" and python_version < "4.0"
hyperframe==6.0.1 ; python_version >= "3.10" and python_version < "4.0"
idna==3.4 ; python_version >= "3.10" and python_version < "4.0"
iso8601==1.1.0 ; python_version >= "3.10" and python_version < "4.0"
limits==1.6 ; python_version >= "3.10" and python_version < "4.0"
loguru==0.6.0 ; python_version >= "3.10" and python_version < "4.0"
msgpack==1.0.4 ; python_version >= "3.10" and python_version < "4.0"
orjson==3.8.2 ; python_version >= "3.10" and python_version < "4.0"
packaging==21.3 ; python_version >= "3.10" and python_version < "4.0"
passlib[argon2]==1.7.4 ; python_version >= "3.10" and python_version < "4.0"
pendulum==2.1.2 ; python_version >= "3.10" and python_version < "4.0"
priority==2.0.0 ; python_version >= "3.10" and python_version < "4.0"
pycparser==2.21 ; python_version >= "3.10" and python_version < "4.0"
pycryptodomex==3.16.0 ; python_version >= "3.10" and python_version < "4.0"
pydantic==1.10.2 ; python_version >= "3.10" and python_version < "4.0"
pyparsing==3.0.9 ; python_version >= "3.10" and python_version < "4.0"
pyseto==1.6.10 ; python_version >= "3.10" and python_version < "4.0"
python-dateutil==2.8.2 ; python_version >= "3.10" and python_version < "4.0"
pytzdata==2020.1 ; python_version >= "3.10" and python_version < "4.0"
redis==4.3.5 ; python_version >= "3.10" and python_version < "4.0"
rfc3986[idna2008]==1.5.0 ; python_version >= "3.10" and python_version < "4.0"
sentry-sdk==1.11.1 ; python_version >= "3.10" and python_version < "4.0"
setuptools==65.6.3 ; python_version >= "3.10" and python_version < "4.0"
six==1.16.0 ; python_version >= "3.10" and python_version < "4.0"
slowapi==0.1.6 ; python_version >= "3.10" and python_version < "4.0"
sniffio==1.3.0 ; python_version >= "3.10" and python_version < "4.0"
starlette==0.20.4 ; python_version >= "3.10" and python_version < "4.0"
toml==0.10.2 ; python_version >= "3.10" and python_version < "4.0"
toolz==0.12.0 ; python_version >= "3.10" and python_version < "4.0"
typing-extensions==4.4.0 ; python_version >= "3.10" and python_version < "4.0"
ujson==5.5.0 ; python_version >= "3.10" and python_version < "4.0"
urllib3==1.26.13 ; python_version >= "3.10" and python_version < "4.0"
uvicorn==0.20.0 ; python_version >= "3.10" and python_version < "4.0"
uvloop==0.17.0 ; platform_system != "Windows" and python_version >= "3.10" and python_version < "4.0"
win32-setctime==1.1.0 ; python_version >= "3.10" and python_version < "4.0" and sys_platform == "win32"
wsproto==1.2.0 ; python_version >= "3.10" and python_version < "4.0"
aiofiles==22.1.0 ; python_version >= "3.11" and python_version < "4.0"
aiorwlock==1.3.0 ; python_version >= "3.11" and python_version < "4.0"
anyio==3.6.2 ; python_version >= "3.11" and python_version < "4.0"
argon2-cffi-bindings==21.2.0 ; python_version >= "3.11" and python_version < "4.0"
argon2-cffi==21.3.0 ; python_version >= "3.11" and python_version < "4.0"
async-timeout==4.0.2 ; python_version >= "3.11" and python_version < "4.0"
asyncstdlib==3.10.5 ; python_version >= "3.11" and python_version < "4.0"
attrs==22.2.0 ; python_version >= "3.11" and python_version < "4.0"
certifi==2022.12.7 ; python_version >= "3.11" and python_version < "4.0"
cffi==1.15.1 ; python_version >= "3.11" and python_version < "4.0"
click==8.1.3 ; 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" or python_version >= "3.11" and python_version < "4.0" and platform_system == "Windows"
cryptography==37.0.4 ; python_version >= "3.11" and python_version < "4.0"
cytoolz==0.12.1 ; python_version >= "3.11" and python_version < "4.0"
deprecated==1.2.13 ; python_version >= "3.11" and python_version < "4.0"
fastapi-cache2==0.1.9 ; python_version >= "3.11" and python_version < "4.0"
fastapi-paseto-auth==0.6.0 ; python_version >= "3.11" and python_version < "4.0"
fastapi==0.85.0 ; python_version >= "3.11" and python_version < "4.0"
fasteners==0.17.3 ; python_version >= "3.11" and python_version < "4.0"
gunicorn==20.1.0 ; python_version >= "3.11" and python_version < "4.0"
h11==0.14.0 ; python_version >= "3.11" and python_version < "4.0"
h2==4.1.0 ; python_version >= "3.11" and python_version < "4.0"
hiredis==2.1.0 ; python_version >= "3.11" and python_version < "4.0"
hpack==4.0.0 ; python_version >= "3.11" and python_version < "4.0"
httpcore==0.16.3 ; python_version >= "3.11" and python_version < "4.0"
httpx-cache==0.7.0 ; python_version >= "3.11" and python_version < "4.0"
httpx==0.23.1 ; python_version >= "3.11" and python_version < "4.0"
httpx[http2]==0.23.1 ; python_version >= "3.11" and python_version < "4.0"
hyperframe==6.0.1 ; python_version >= "3.11" and python_version < "4.0"
idna==3.4 ; python_version >= "3.11" and python_version < "4.0"
iso8601==1.1.0 ; python_version >= "3.11" and python_version < "4.0"
limits==2.8.0 ; python_version >= "3.11" and python_version < "4.0"
loguru==0.6.0 ; python_version >= "3.11" and python_version < "4.0"
msgpack==1.0.4 ; python_version >= "3.11" and python_version < "4.0"
orjson==3.8.3 ; python_version >= "3.11" and python_version < "4.0"
packaging==22.0 ; python_version >= "3.11" and python_version < "4.0"
passlib[argon2]==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"
pycparser==2.21 ; python_version >= "3.11" and python_version < "4.0"
pycryptodomex==3.16.0 ; python_version >= "3.11" and python_version < "4.0"
pydantic==1.10.2 ; python_version >= "3.11" and python_version < "4.0"
pyseto==1.6.10 ; python_version >= "3.11" and python_version < "4.0"
python-dateutil==2.8.2 ; python_version >= "3.11" and python_version < "4.0"
pytzdata==2020.1 ; python_version >= "3.11" and python_version < "4.0"
redis==4.4.0 ; python_version >= "3.11" and python_version < "4.0"
rfc3986[idna2008]==1.5.0 ; python_version >= "3.11" and python_version < "4.0"
sentry-sdk==1.12.1 ; python_version >= "3.11" and python_version < "4.0"
setuptools==65.6.3 ; python_version >= "3.11" and python_version < "4.0"
six==1.16.0 ; python_version >= "3.11" and python_version < "4.0"
slowapi==0.1.7 ; python_version >= "3.11" and python_version < "4.0"
sniffio==1.3.0 ; python_version >= "3.11" and python_version < "4.0"
starlette==0.20.4 ; python_version >= "3.11" and python_version < "4.0"
toml==0.10.2 ; python_version >= "3.11" and python_version < "4.0"
toolz==0.12.0 ; python_version >= "3.11" and python_version < "4.0"
typing-extensions==4.4.0 ; python_version >= "3.11" and python_version < "4.0"
ujson==5.6.0 ; python_version >= "3.11" and python_version < "4.0"
urllib3==1.26.13 ; python_version >= "3.11" and python_version < "4.0"
uvicorn==0.20.0 ; python_version >= "3.11" and python_version < "4.0"
uvloop==0.17.0 ; python_version >= "3.11" and python_version < "4.0"
win32-setctime==1.1.0 ; python_version >= "3.11" and python_version < "4.0" and sys_platform == "win32"
wrapt==1.14.1 ; python_version >= "3.11" and python_version < "4.0"

8
run.py
View File

@ -1,13 +1,13 @@
import os
import sys
import toml
import logging
import sentry_sdk
from app.main import app
from loguru import logger
from fastapi import FastAPI
from types import FrameType
from typing import Any, Optional
from typing import Any
from multiprocessing import cpu_count
from gunicorn.glogging import Logger
from gunicorn.app.base import BaseApplication
@ -15,7 +15,9 @@ from sentry_sdk.integrations.redis import RedisIntegration
from sentry_sdk.integrations.httpx import HttpxIntegration
from sentry_sdk.integrations.gnu_backtrace import GnuBacktraceIntegration
config: dict = toml.load("config.toml")
from app.dependencies import load_config
config: dict = load_config()
# Enable sentry logging