Skip to content

Commit

Permalink
add handling at both API and DB levels
Browse files Browse the repository at this point in the history
  • Loading branch information
Xlitoni authored and ctmbl committed Oct 27, 2024
1 parent 236c721 commit 4b72f13
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 10 deletions.
30 changes: 25 additions & 5 deletions src/api/rootme_api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import logging

from os import getenv
from api.rate_limiter import RateLimiter
from api.rate_limiter import RLRequestFailed, RateLimiter

class RootMeAPIError(Exception):
def __init__(self, *args: object) -> None:
super().__init__(*args)

class RootMeAPIManager:
"""
Expand All @@ -18,6 +23,7 @@ def __init__(self, rate_limiter: RateLimiter):
else:
raise RuntimeError("API_URL is not set.")
self.rate_limiter = rate_limiter
self.logger = logging.getLogger(__name__)

def get_rate_limiter(self):
return self.rate_limiter
Expand All @@ -28,11 +34,17 @@ async def get_challenge_by_id(self, _id):
-> returns the raw json for now
"""
# use the api_key in the cookies
request_url = f"{self.API_URL}/challenges/{_id}"
cookies = {"api_key": self.API_KEY.strip('"')}
request_method = "GET"
# ask the rate limiter for the request
data = await self.rate_limiter.make_request(
f"{self.API_URL}/challenges/{_id}", cookies, "GET"
)
try:
data = await self.rate_limiter.make_request(
request_url, cookies, request_method
)
except RLRequestFailed as exc:
self.logger.error("%s Request to get challenge %s failed.", request_method, request_url)
raise RootMeAPIError() # Handle the fact the request is wrong
return data

async def get_user_by_id(self, _id):
Expand All @@ -41,7 +53,15 @@ async def get_user_by_id(self, _id):
-> returns the raw json for now
"""
# use the api_key in the cookies
request_url = f"{self.API_URL}/auteurs/{_id}"
cookies = {"api_key": self.API_KEY.strip('"')}
request_method = "GET"
# ask the rate limiter for the request
data = await self.rate_limiter.make_request(f"{self.API_URL}/auteurs/{_id}", cookies, "GET")
try:
data = await self.rate_limiter.make_request(
request_url, cookies, request_method
)
except RLRequestFailed as exc:
self.logger.error("%s Request to get user %s failed.", request_method, request_url)
raise RootMeAPIError()
return data
24 changes: 19 additions & 5 deletions src/database/db_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import sqlite3
from os import getenv, path

from api.rootme_api import RootMeAPIError, RootMeAPIManager
from database.db_structure import (
sql_create_user_table,
sql_add_user,
Expand Down Expand Up @@ -31,7 +32,7 @@ def __init__(self, idx=None, message=None):


class DatabaseManager:
def __init__(self, api_manager):
def __init__(self, api_manager: RootMeAPIManager):
self.logger = logging.getLogger(__name__)

self.DB_FOLDER = getenv("DB_FOLDER")
Expand Down Expand Up @@ -64,8 +65,11 @@ async def add_user(self, idx):
if self.has_user(idx):
return None

# Retreive information from RootMe API
raw_user_data = await self.api_manager.get_user_by_id(idx)
# Retrieve information from RootMe API
try:
raw_user_data = await self.api_manager.get_user_by_id(idx)
except RootMeAPIError:
return None
user = User(raw_user_data)

cur.execute(sql_add_user, user.to_tuple())
Expand Down Expand Up @@ -102,15 +106,25 @@ async def fetch_user_new_solves(self, idx):
if user is None:
raise InvalidUser(idx, "DatabaseManager.fetch_user_new_solves: User %s not in database")

raw_user_data = await self.api_manager.get_user_by_id(idx)
try:
raw_user_data = await self.api_manager.get_user_by_id(idx)
except RootMeAPIError:
# If for some reason we can get the user on this iteration
# we will get him next time maybe ...
self.logger.error("User %s could not be fetch from the API, yet we keep running", idx)
return
user.update_new_solves(raw_user_data)
if not user.has_new_solves():
self.logger.debug("'%s' hasn't any new solves", user)
return

self.logger.info("'%s' has %s new solves", user, user.nb_new_solves)
for challenge_id in user.yield_new_solves(raw_user_data):
challenge_data = await self.api_manager.get_challenge_by_id(challenge_id)
try:
challenge_data = await self.api_manager.get_challenge_by_id(challenge_id)
except RootMeAPIError:
# If we can't fetch the challenge, sadly there is not much we can do
continue
challenge = Challenge(challenge_id, challenge_data)
self.logger.debug("'%s' solved '%s'", repr(user), repr(challenge))
yield challenge

0 comments on commit 4b72f13

Please sign in to comment.