diff --git a/app/controllers/Ballot.py b/app/controllers/Ballot.py new file mode 100644 index 0000000..1b052b0 --- /dev/null +++ b/app/controllers/Ballot.py @@ -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 diff --git a/app/controllers/Clients.py b/app/controllers/Clients.py index 2e6f850..d161a00 100644 --- a/app/controllers/Clients.py +++ b/app/controllers/Clients.py @@ -1,8 +1,4 @@ -from time import sleep from redis import asyncio as aioredis -import uvloop - - import app.utils.Logger as Logger from app.dependencies import load_config from app.utils.RedisConnector import RedisConnector diff --git a/app/main.py b/app/main.py index 22d6a4d..cfaadf9 100644 --- a/app/main.py +++ b/app/main.py @@ -1,5 +1,4 @@ import os -import toml import binascii from redis import Redis @@ -30,6 +29,7 @@ from app.routers import root from app.routers import auth from app.routers import items from app.routers import ping +from app.routers import ballot """Implements an API for our polling app""" @@ -64,6 +64,7 @@ app.add_middleware(SlowAPIMiddleware) app.include_router(root.router) app.include_router(items.router) +app.include_router(ballot.router) app.include_router(auth.router) app.include_router(ping.router) diff --git a/app/models/BallotModel.py b/app/models/BallotModel.py index 7e05f43..2a3c16d 100644 --- a/app/models/BallotModel.py +++ b/app/models/BallotModel.py @@ -1,5 +1,4 @@ from pydantic import BaseModel -from app.models.BallotFields import BallotFields class BallotModel(BaseModel): """Implements the fields for the ballots. @@ -8,5 +7,4 @@ class BallotModel(BaseModel): BaseModel (pydantic.BaseModel): BaseModel from pydantic """ - discord_id_hash: str - ballot: str + vote: str diff --git a/app/models/ResponseModels.py b/app/models/ResponseModels.py index 1c0d893..c7b77f8 100644 --- a/app/models/ResponseModels.py +++ b/app/models/ResponseModels.py @@ -3,33 +3,6 @@ import app.models.ResponseFields as ResponseFields """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): """Implements the JSON response model for the /heartbeat endpoint. @@ -40,26 +13,6 @@ class PingResponseModel(BaseModel): status: int 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): """Implements the response fields for client auth tokens. @@ -68,36 +21,6 @@ class ClientAuthTokenResponse(BaseModel): """ 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): """Implements the response fields for token invalidation. @@ -107,3 +30,12 @@ class RevokedTokenResponse(BaseModel): """ revoked: bool + +class BallotCastedResponse(BaseModel): + """Implements the response fields for ballot casted. + + Args: + BaseModel (pydantic.BaseModel): BaseModel from pydantic + """ + + casted: bool diff --git a/app/utils/Logger.py b/app/utils/Logger.py index aa6bc1b..551c503 100644 --- a/app/utils/Logger.py +++ b/app/utils/Logger.py @@ -51,28 +51,16 @@ class UserLogger: else: 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: - """Logs internal cache operations + """Logs ballot operations Args: operation (str): Operation name key (str): Key used in the operation """ 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: - 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")