refactor and reorganize!!
This commit is contained in:
1 parent
e7f10c4f59
commit
832122e63c
11 files changed
+1082
-283
No files matched your search
+110
-1
@@ -8,7 +8,8 @@ import os
|
||||
import aiohttp
|
||||
import json
|
||||
import dotenv
|
||||
from typing import Dict, Any
|
||||
from typing import Dict, Any, Optional
|
||||
from datetime import datetime, timedelta
|
||||
from . import throttler
|
||||
|
||||
Throttler = throttler.GlobalThrottler
|
||||
@@ -29,6 +30,104 @@ class AsyncBricksetAPI:
|
||||
self.user_hash = None
|
||||
self.logger = logger
|
||||
|
||||
# API usage tracking
|
||||
self.daily_requests_used: Optional[int] = None
|
||||
self.daily_requests_limit = 1000
|
||||
self.usage_last_checked: Optional[datetime] = None
|
||||
self.usage_check_interval = timedelta(hours=1) # Check usage every hour
|
||||
|
||||
async def get_key_usage_stats(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Fetch API key usage statistics from Brickset.
|
||||
|
||||
Returns:
|
||||
dict: Usage stats including dateStamp and apiCalls
|
||||
"""
|
||||
url = "https://brickset.com/api/v3.asmx/getKeyUsageStats"
|
||||
params = {"apiKey": self.api_key}
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(
|
||||
url, params=params, headers=self.headers
|
||||
) as response:
|
||||
if response.status == 200:
|
||||
data = await response.read()
|
||||
result = json.loads(data.decode("utf-8"))
|
||||
|
||||
if self.debug:
|
||||
print(f"[@DEBUG] API usage stats: {result}")
|
||||
if self.logger:
|
||||
self.logger.debug(f"API usage stats: {result}")
|
||||
|
||||
return result
|
||||
else:
|
||||
error_msg = f"Failed to get usage stats: HTTP {response.status}"
|
||||
if self.logger:
|
||||
self.logger.error(error_msg)
|
||||
raise Exception(error_msg)
|
||||
|
||||
async def check_and_update_usage(self) -> bool:
|
||||
"""
|
||||
Check current API usage and update internal counter.
|
||||
Automatically called before each request if needed.
|
||||
|
||||
Returns:
|
||||
bool: True if under limit, False if at/over limit
|
||||
"""
|
||||
now = datetime.now()
|
||||
|
||||
# Check usage if we haven't checked yet or if it's been over an hour
|
||||
should_check = (
|
||||
self.daily_requests_used is None
|
||||
or self.usage_last_checked is None
|
||||
or (now - self.usage_last_checked) > self.usage_check_interval
|
||||
)
|
||||
|
||||
if should_check:
|
||||
try:
|
||||
stats = await self.get_key_usage_stats()
|
||||
# Brickset returns {"status": "success", "apiKeyUsage": [...]}
|
||||
usage_array = stats.get("apiKeyUsage", [])
|
||||
if usage_array and len(usage_array) > 0:
|
||||
today_stats = usage_array[0] # Most recent day
|
||||
self.daily_requests_used = today_stats.get("count", 0)
|
||||
self.usage_last_checked = now
|
||||
|
||||
if self.logger:
|
||||
self.logger.info(
|
||||
f"API usage: {self.daily_requests_used}/{self.daily_requests_limit}"
|
||||
)
|
||||
|
||||
if self.debug:
|
||||
print(
|
||||
f"[@DEBUG] API usage: {self.daily_requests_used}/{self.daily_requests_limit}"
|
||||
)
|
||||
except Exception as e:
|
||||
if self.logger:
|
||||
self.logger.warning(f"Failed to check API usage: {e}")
|
||||
# Don't block requests if usage check fails
|
||||
return True
|
||||
|
||||
# Check if we're over the limit
|
||||
if self.daily_requests_used is not None:
|
||||
if self.daily_requests_used >= self.daily_requests_limit:
|
||||
error_msg = f"Daily API limit reached: {self.daily_requests_used}/{self.daily_requests_limit}"
|
||||
if self.logger:
|
||||
self.logger.error(error_msg)
|
||||
if self.debug:
|
||||
print(f"[@ERROR] {error_msg}")
|
||||
return False
|
||||
|
||||
# Warn when approaching limit
|
||||
if self.daily_requests_used >= self.daily_requests_limit * 0.9:
|
||||
warning_msg = f"Approaching daily API limit: {self.daily_requests_used}/{self.daily_requests_limit}"
|
||||
if self.logger:
|
||||
self.logger.warning(warning_msg)
|
||||
if self.debug:
|
||||
print(f"[@WARNING] {warning_msg}")
|
||||
|
||||
return True
|
||||
|
||||
async def login(self) -> Dict[str, Any]:
|
||||
"""Asynchronously authenticate with Brickset API"""
|
||||
url = "https://brickset.com/api/v3.asmx/login"
|
||||
@@ -64,7 +163,17 @@ class AsyncBricksetAPI:
|
||||
|
||||
Returns:
|
||||
Dict containing set information
|
||||
|
||||
Raises:
|
||||
Exception: If daily API limit exceeded or API error
|
||||
"""
|
||||
# Check API usage before making request
|
||||
if not await self.check_and_update_usage():
|
||||
raise Exception(
|
||||
f"Brickset API daily limit reached ({self.daily_requests_limit} requests/day). "
|
||||
"Please try again tomorrow."
|
||||
)
|
||||
|
||||
if not self.user_hash:
|
||||
await self.login()
|
||||
|
||||
|
||||
Reference in new issue
Block a user