feat: manager-related endpoints

This commit is contained in:
Alexandre Teles 2023-11-22 11:43:57 -03:00 committed by Alexandre Teles (afterSt0rm)
parent a8126d785f
commit 3a128c4661
7 changed files with 150 additions and 50 deletions

View File

@ -6,7 +6,7 @@ from typing import Optional
import ujson
from aiohttp import ClientResponse
from sanic import SanicException
from cytoolz import filter, map, partial
from cytoolz import filter, map, partial, curry, pipe
from cytoolz.dicttoolz import get_in, keyfilter
from cytoolz.itertoolz import mapcat, pluck
@ -395,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}

View File

@ -1,32 +0,0 @@
"""
This module provides a blueprint for the connections endpoint.
Routes:
- GET /connections: Get ReVanced connection links.
"""
import os
from sanic import Blueprint, Request
from sanic.response import JSONResponse, json
from sanic_ext import openapi
from api.models.socials import ConnectionsResponseModel
from config import social_links
connections: Blueprint = Blueprint(os.path.basename(__file__).strip(".py"))
@connections.get("/connections")
@openapi.definition(
summary="Get ReVanced connection links",
response=[ConnectionsResponseModel],
)
async def root(request: Request) -> JSONResponse:
"""
Returns a JSONResponse with a dictionary containing ReVanced connection links.
**Returns:**
- JSONResponse: A Sanic JSONResponse instance containing a dictionary with the connection links.
"""
data: dict[str, dict] = {"connections": social_links}
return json(data, status=200)

61
api/manager.py Normal file
View 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)

32
api/models/manager.py Normal file
View 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.
"""

View File

@ -11,7 +11,7 @@ class SocialFields(BaseModel):
preferred: bool
class ConnectionsResponseModel(BaseModel):
class SocialsResponseModel(BaseModel):
"""
A Pydantic BaseModel that represents a dictionary of social links.
"""
@ -21,15 +21,3 @@ class ConnectionsResponseModel(BaseModel):
A dictionary where the keys are the names of the social networks, and
the values are the links to the profiles or pages.
"""
class ConnectionsResponseModel(BaseModel):
"""
A Pydantic BaseModel that represents a dictionary of connection links.
"""
connections: list[SocialFields]
"""
A dictionary where the keys are the names of the social networks, and
the values are the links to the profiles or pages.
"""

View File

@ -10,7 +10,7 @@ from sanic import Blueprint, Request
from sanic.response import JSONResponse, json
from sanic_ext import openapi
from api.models.socials import ConnectionsResponseModel
from api.models.socials import SocialsResponseModel
from config import social_links
socials: Blueprint = Blueprint(os.path.basename(__file__).strip(".py"))
@ -19,7 +19,7 @@ socials: Blueprint = Blueprint(os.path.basename(__file__).strip(".py"))
@socials.get("/socials")
@openapi.definition(
summary="Get ReVanced socials",
response=[ConnectionsResponseModel],
response=[SocialsResponseModel],
)
async def root(request: Request) -> JSONResponse:
"""

View File

@ -18,8 +18,16 @@ default_repository: str = ".github"
api_versions: dict[str, list[str]] = {
"old": ["compat"],
"v2": ["announcements", "donations", "github", "info", "login", "ping", "socials"],
"v3": ["connections"],
"v2": [
"announcements",
"donations",
"github",
"info",
"login",
"ping",
"socials",
"manager",
],
}
api_version: str = "v2"