fully implements redis cache functionality

This commit is contained in:
Alexandre Teles 2022-08-31 23:12:37 -03:00
parent ae423dc2fa
commit 231ce565d9
6 changed files with 72 additions and 19 deletions

View File

@ -1,16 +1,16 @@
# ReVanced Releases API
![License: AGPLv3](https://img.shields.io/github/license/alexandreteles/revanced-releases-api)
![GitHub last commit](https://img.shields.io/github/last-commit/alexandreteles/revanced-releases-api)
![GitHub Workflow Status](https://img.shields.io/github/workflow/status/alexandreteles/revanced-releases-api/Main%20build)
# ReVanced Releases API
This is a simple API that returns the latest ReVanced releases.
## Usage
The API is available at [https://revanced-releases-api.afterst0rm.xyz/](https://revanced-releases-api.afterst0rm.xyz/).
For development purposes, you can run the API locally by cloning this repository and running `docker-compose up` or `docker-compose up --build` if you want to rebuild the image. Optionally you can run the application without Docker by running `pip -U install -r ./requirements.txt` and `python ./main.py`. Remember to set the environment variable `GITHUB_TOKEN` to a valid token if you want to run the API locally.
For development purposes, you can run the API locally by cloning this repository and running `docker-compose up` or `docker-compose up --build` if you want to rebuild the image. Optionally you can run the application without Docker by running `pip -U install -r ./requirements.txt` and `python ./main.py`. Remember to set the environment variable `GITHUB_TOKEN` to a valid token if you want to run the API locally and make sure to have a `redis` instance running.
### API Endpoints

View File

@ -8,15 +8,22 @@ Changelogs are not included but can be found on the [ReVanced Repositories](http
The team also have a [Discord Server](https://revanced.app/discord) if you need help.
### API Endpoints
## API Endpoints
* [apps](/apps) - Returns all currently patchable apps
* [tools](/tools) - Returns the latest version of all ReVanced tools and Vanced MicroG
* [patches](/patches) - Returns the latest version of all ReVanced patches
There is no cache on this API because we trust our fellow developers to implement a cache on their end.
## Additional Information
So please be kind and don't blow up the API with requests or we will have to block your IP address.
* Rate Limiting - 15 requests per minute
* Cache - 1 minute
## Important Notes
1. Although we will try to avoid breaking changes, we can't guarantee that it won't happen.
2. Okay, the api is now cached and rate limited (per endpoint). But please don't abuse it, we don't want to have to block you.
3. Make sure to implement a cache system on your end to avoid unnecessary requests.
Godspeed 💀
@ -37,6 +44,9 @@ port = 8000
limit = "15/minute"
[cache]
expire = 60
[app]
repositories = ["TeamVanced/VancedMicroG", "revanced/revanced-cli", "revanced/revanced-patches", "revanced/revanced-integrations"]

View File

@ -1,7 +1,27 @@
version: "3.8"
services:
redis:
container_name: revanced-releases-api-redis
image: redis:latest
volumes:
- redis-data:/data
networks:
- infra
restart: always
revanced-releases-api:
container_name: revanced-releases-api
image: alexandreteles/revanced-releases-api:latest
restart: always
environment:
- REDIS_HOST=revanced-releases-api-redis
- REDIS_PORT=6379
- GITHUB_TOKEN=YOUR_GITHUB_TOKEN
ports:
- 127.0.0.1:7934:8000
networks:
- infra
restart: unless-stopped
networks:
infra:
external: true

28
main.py
View File

@ -1,7 +1,9 @@
#!/usr/bin/env python3
import os
import toml
import uvicorn
import aioredis
from fastapi import FastAPI, Request, Response
from modules.Releases import Releases
from fastapi.responses import RedirectResponse
@ -12,13 +14,20 @@ from slowapi.errors import RateLimitExceeded
from fastapi_cache import FastAPICache
from fastapi_cache.backends.redis import RedisBackend
from fastapi_cache.decorator import cache
import aioredis
"""Get latest ReVanced releases from GitHub API."""
# Load config
config = toml.load("config.toml")
config: dict = toml.load("config.toml")
# Redis connection parameters
redis_config: dict[ str, str | int ] = {
"url": f"redis://{os.environ['REDIS_URL']}",
"port": os.environ['REDIS_PORT'],
"collection": 0
}
# Create releases instance
@ -42,7 +51,7 @@ app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
# Setup cache
@cache()
async def get_cache():
async def get_cache() -> int:
return 1
# Routes
@ -59,7 +68,7 @@ async def root(request: Request, response: Response) -> RedirectResponse:
@app.get('/tools', response_model=ResponseModels.ToolsResponseModel)
@limiter.limit(config['slowapi']['limit'])
@cache(expire=60)
@cache(config['cache']['expire'])
async def tools(request: Request, response: Response) -> dict:
"""Get patching tools' latest version.
@ -70,7 +79,7 @@ async def tools(request: Request, response: Response) -> dict:
@app.get('/apps', response_model=ResponseModels.AppsResponseModel)
@limiter.limit(config['slowapi']['limit'])
@cache(expire=60)
@cache(config['cache']['expire'])
async def apps(request: Request, response: Response) -> dict:
"""Get patchable apps.
@ -81,7 +90,7 @@ async def apps(request: Request, response: Response) -> dict:
@app.get('/patches', response_model=ResponseModels.PatchesResponseModel)
@limiter.limit(config['slowapi']['limit'])
@cache(expire=60)
@cache(config['cache']['expire'])
async def patches(request: Request, response: Response) -> dict:
"""Get latest patches.
@ -92,9 +101,12 @@ async def patches(request: Request, response: Response) -> dict:
return await releases.get_patches_json()
@app.on_event("startup")
async def startup():
redis = aioredis.from_url("redis://localhost", encoding="utf8", decode_responses=True)
async def startup() -> None:
redis_url = f"{redis_config['url']}:{redis_config['port']}/{redis_config['collection']}"
redis = aioredis.from_url(redis_url, encoding="utf8", decode_responses=True)
FastAPICache.init(RedisBackend(redis), prefix="fastapi-cache")
return None
# Run app
if __name__ == '__main__':

View File

@ -18,7 +18,7 @@ class CompatiblePackagesResponseFields(BaseModel):
BaseModel (pydantic.BaseModel): BaseModel from pydantic
"""
name: str
verstions: list[ str ] | None
versions: list[ str ] | None
class PatchesResponseFields(BaseModel):
"""Implements the fields for the /patches endpoint.

View File

@ -1,13 +1,24 @@
---
version: "3.8"
services:
redis:
container_name: revanced-releases-api-redis
image: redis:latest
volumes:
- redis-data:/data
networks:
- infra
restart: always
revanced-releases-api:
image: alexandreteles/revanced-releases-api:latest
container_name: revanced-releases-api
image: alexandreteles/revanced-releases-api:latest
environment:
- GITHUB_TOKEN=
- REDIS_HOST=revanced-releases-api-redis
- REDIS_PORT=6379
- GITHUB_TOKEN=YOUR_GITHUB_TOKEN
ports:
- 127.0.0.1:8000:8000
- 127.0.0.1:7934:8000
networks:
- infra
restart: unless-stopped