mirror of
https://github.com/revanced/revanced-polling-api.git
synced 2025-05-02 15:44:33 +02:00
feat: add ballot casting endpoint
This commit is contained in:
parent
0b45044649
commit
641bf689a4
36
app/controllers/Ballot.py
Normal file
36
app/controllers/Ballot.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
from redis import asyncio as aioredis
|
||||||
|
import app.utils.Logger as Logger
|
||||||
|
from app.dependencies import load_config
|
||||||
|
from app.utils.RedisConnector import RedisConnector
|
||||||
|
|
||||||
|
config: dict = load_config()
|
||||||
|
|
||||||
|
class Ballot:
|
||||||
|
"""Implements a ballot for ReVanced Polling API."""
|
||||||
|
|
||||||
|
redis = RedisConnector.connect(config['tokens']['database'])
|
||||||
|
|
||||||
|
BallotLogger = Logger.BallotLogger()
|
||||||
|
|
||||||
|
async def store(self, discord_hashed_id: str, ballot: str) -> bool:
|
||||||
|
"""Store a ballot.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
discord_hashed_id (str): Discord hashed ID of the voter
|
||||||
|
ballot (dict): Ballot to store
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if the ballot was stored successfully, False otherwise
|
||||||
|
"""
|
||||||
|
|
||||||
|
stored: bool = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
await self.redis.set(name=discord_hashed_id, value=ballot, nx=True)
|
||||||
|
await self.BallotLogger.log("STORE_BALLOT", None, discord_hashed_id)
|
||||||
|
stored = True
|
||||||
|
except aioredis.RedisError as e:
|
||||||
|
await self.BallotLogger.log("STORE_BALLOT", e)
|
||||||
|
raise e
|
||||||
|
|
||||||
|
return stored
|
@ -1,8 +1,4 @@
|
|||||||
from time import sleep
|
|
||||||
from redis import asyncio as aioredis
|
from redis import asyncio as aioredis
|
||||||
import uvloop
|
|
||||||
|
|
||||||
|
|
||||||
import app.utils.Logger as Logger
|
import app.utils.Logger as Logger
|
||||||
from app.dependencies import load_config
|
from app.dependencies import load_config
|
||||||
from app.utils.RedisConnector import RedisConnector
|
from app.utils.RedisConnector import RedisConnector
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import os
|
import os
|
||||||
import toml
|
|
||||||
import binascii
|
import binascii
|
||||||
from redis import Redis
|
from redis import Redis
|
||||||
|
|
||||||
@ -30,6 +29,7 @@ from app.routers import root
|
|||||||
from app.routers import auth
|
from app.routers import auth
|
||||||
from app.routers import items
|
from app.routers import items
|
||||||
from app.routers import ping
|
from app.routers import ping
|
||||||
|
from app.routers import ballot
|
||||||
|
|
||||||
"""Implements an API for our polling app"""
|
"""Implements an API for our polling app"""
|
||||||
|
|
||||||
@ -64,6 +64,7 @@ app.add_middleware(SlowAPIMiddleware)
|
|||||||
|
|
||||||
app.include_router(root.router)
|
app.include_router(root.router)
|
||||||
app.include_router(items.router)
|
app.include_router(items.router)
|
||||||
|
app.include_router(ballot.router)
|
||||||
app.include_router(auth.router)
|
app.include_router(auth.router)
|
||||||
app.include_router(ping.router)
|
app.include_router(ping.router)
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from app.models.BallotFields import BallotFields
|
|
||||||
|
|
||||||
class BallotModel(BaseModel):
|
class BallotModel(BaseModel):
|
||||||
"""Implements the fields for the ballots.
|
"""Implements the fields for the ballots.
|
||||||
@ -8,5 +7,4 @@ class BallotModel(BaseModel):
|
|||||||
BaseModel (pydantic.BaseModel): BaseModel from pydantic
|
BaseModel (pydantic.BaseModel): BaseModel from pydantic
|
||||||
"""
|
"""
|
||||||
|
|
||||||
discord_id_hash: str
|
vote: str
|
||||||
ballot: str
|
|
||||||
|
@ -3,33 +3,6 @@ import app.models.ResponseFields as ResponseFields
|
|||||||
|
|
||||||
"""Implements pydantic models and model generator for the API's responses."""
|
"""Implements pydantic models and model generator for the API's responses."""
|
||||||
|
|
||||||
class ToolsResponseModel(BaseModel):
|
|
||||||
"""Implements the JSON response model for the /tools endpoint.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
BaseModel (pydantic.BaseModel): BaseModel from pydantic
|
|
||||||
"""
|
|
||||||
|
|
||||||
tools: list[ ResponseFields.ToolsResponseFields ]
|
|
||||||
|
|
||||||
class PatchesResponseModel(BaseModel):
|
|
||||||
"""Implements the JSON response model for the /patches endpoint.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
BaseModel (pydantic.BaseModel): BaseModel from pydantic
|
|
||||||
"""
|
|
||||||
|
|
||||||
__root__: list[ ResponseFields.PatchesResponseFields ]
|
|
||||||
|
|
||||||
class ContributorsResponseModel(BaseModel):
|
|
||||||
"""Implements the JSON response model for the /contributors endpoint.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
BaseModel (pydantic.BaseModel): BaseModel from pydantic
|
|
||||||
"""
|
|
||||||
|
|
||||||
repositories: list[ ResponseFields.ContributorsResponseFields ]
|
|
||||||
|
|
||||||
class PingResponseModel(BaseModel):
|
class PingResponseModel(BaseModel):
|
||||||
"""Implements the JSON response model for the /heartbeat endpoint.
|
"""Implements the JSON response model for the /heartbeat endpoint.
|
||||||
|
|
||||||
@ -40,26 +13,6 @@ class PingResponseModel(BaseModel):
|
|||||||
status: int
|
status: int
|
||||||
detail: str
|
detail: str
|
||||||
|
|
||||||
class ClientDeletedResponse(BaseModel):
|
|
||||||
"""Implements the response fields for deleted clients.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
BaseModel (pydantic.BaseModel): BaseModel from pydantic
|
|
||||||
"""
|
|
||||||
|
|
||||||
id: str
|
|
||||||
deleted: bool
|
|
||||||
|
|
||||||
class ClientSecretUpdatedResponse(BaseModel):
|
|
||||||
"""Implements the response fields for updated client secrets.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
BaseModel (pydantic.BaseModel): BaseModel from pydantic
|
|
||||||
"""
|
|
||||||
|
|
||||||
id: str
|
|
||||||
secret: str
|
|
||||||
|
|
||||||
class ClientAuthTokenResponse(BaseModel):
|
class ClientAuthTokenResponse(BaseModel):
|
||||||
"""Implements the response fields for client auth tokens.
|
"""Implements the response fields for client auth tokens.
|
||||||
|
|
||||||
@ -69,36 +22,6 @@ class ClientAuthTokenResponse(BaseModel):
|
|||||||
|
|
||||||
access_token: str
|
access_token: str
|
||||||
|
|
||||||
class ClientTokenRefreshResponse(BaseModel):
|
|
||||||
"""Implements the response fields for client token refresh.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
BaseModel (pydantic.BaseModel): BaseModel from pydantic
|
|
||||||
"""
|
|
||||||
|
|
||||||
access_token: str
|
|
||||||
|
|
||||||
class ClientStatusResponse(BaseModel):
|
|
||||||
"""Implements the response fields for client status.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
BaseModel (pydantic.BaseModel): BaseModel from pydantic
|
|
||||||
"""
|
|
||||||
|
|
||||||
id: str
|
|
||||||
active: bool
|
|
||||||
|
|
||||||
class ChangelogsResponseModel(BaseModel):
|
|
||||||
"""Implements the JSON response model for the /changelogs endpoint.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
BaseModel (pydantic.BaseModel): BaseModel from pydantic
|
|
||||||
"""
|
|
||||||
|
|
||||||
repository: str
|
|
||||||
path: str
|
|
||||||
commits: list[ ResponseFields.ChangelogsResponseFields ]
|
|
||||||
|
|
||||||
class RevokedTokenResponse(BaseModel):
|
class RevokedTokenResponse(BaseModel):
|
||||||
"""Implements the response fields for token invalidation.
|
"""Implements the response fields for token invalidation.
|
||||||
|
|
||||||
@ -107,3 +30,12 @@ class RevokedTokenResponse(BaseModel):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
revoked: bool
|
revoked: bool
|
||||||
|
|
||||||
|
class BallotCastedResponse(BaseModel):
|
||||||
|
"""Implements the response fields for ballot casted.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
BaseModel (pydantic.BaseModel): BaseModel from pydantic
|
||||||
|
"""
|
||||||
|
|
||||||
|
casted: bool
|
||||||
|
@ -51,28 +51,16 @@ class UserLogger:
|
|||||||
else:
|
else:
|
||||||
logger.info(f"[User] REDIS {operation} {key} - OK")
|
logger.info(f"[User] REDIS {operation} {key} - OK")
|
||||||
|
|
||||||
class AnnouncementsLogger:
|
class BallotLogger:
|
||||||
async def log(self, operation: str, result: RedisError | None = None, key: str = "") -> None:
|
async def log(self, operation: str, result: RedisError | None = None, key: str = "") -> None:
|
||||||
"""Logs internal cache operations
|
"""Logs ballot operations
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
operation (str): Operation name
|
operation (str): Operation name
|
||||||
key (str): Key used in the operation
|
key (str): Key used in the operation
|
||||||
"""
|
"""
|
||||||
if type(result) is RedisError:
|
if type(result) is RedisError:
|
||||||
logger.error(f"[ANNOUNCEMENT] REDIS {operation} - Failed with error: {result}")
|
logger.error(f"[BALLOT] REDIS {operation} - Failed with error: {result}")
|
||||||
else:
|
else:
|
||||||
logger.info(f"[ANNOUNCEMENT] REDIS {operation} {key} - OK")
|
logger.info(f"[BALLOT] REDIS {operation} {key} - OK")
|
||||||
|
|
||||||
class MirrorsLogger:
|
|
||||||
async def log(self, operation: str, result: RedisError | None = None, key: str = "") -> None:
|
|
||||||
"""Logs internal cache operations
|
|
||||||
|
|
||||||
Args:
|
|
||||||
operation (str): Operation name
|
|
||||||
key (str): Key used in the operation
|
|
||||||
"""
|
|
||||||
if type(result) is RedisError:
|
|
||||||
logger.error(f"[MIRRORS] REDIS {operation} - Failed with error: {result}")
|
|
||||||
else:
|
|
||||||
logger.info(f"[MIRRORS] REDIS {operation} {key} - OK")
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user