update
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
"""官方寄售缓存、认证失败识别及可选BARK通知。"""
|
||||
|
||||
import asyncio
|
||||
from datetime import datetime, timezone
|
||||
import hashlib
|
||||
import json
|
||||
import logging
|
||||
@@ -14,6 +13,7 @@ import aiohttp
|
||||
from api.core.Gzip import gzip_unzip, gzip_zip
|
||||
from api.types.colg import GOLD_REGION_CODES, OfficialGold
|
||||
from api.utils.thirdpart_gold import RELEASE_LOCK
|
||||
from api.utils.gold_time import UPDATE_LEAD_SECONDS, half_hour_start, refresh_slot
|
||||
from config.main import config
|
||||
|
||||
logger = logging.getLogger('dcalc.official_gold')
|
||||
@@ -43,14 +43,14 @@ def normalize_row(item: dict) -> dict:
|
||||
except (TypeError, ValueError, OverflowError):
|
||||
continue
|
||||
if math.isfinite(price):
|
||||
prices.append(price)
|
||||
prices.append(round(price, 2))
|
||||
ranks[name] = prices
|
||||
ratios = [10000 / price for prices in ranks.values() for price in prices
|
||||
if price > 0 and math.isfinite(10000 / price)]
|
||||
return OfficialGold.model_validate({
|
||||
**item, **ranks,
|
||||
'max': round(max(ratios), 4) if ratios else None,
|
||||
'min': round(min(ratios), 4) if ratios else None,
|
||||
**item, **ranks, 'updataTime': str(half_hour_start(int(item['updataTime']))),
|
||||
'max': round(max(ratios), 2) if ratios else None,
|
||||
'min': round(min(ratios), 2) if ratios else None,
|
||||
}).model_dump()
|
||||
|
||||
|
||||
@@ -64,7 +64,10 @@ def is_auth_failure(payload: dict) -> bool:
|
||||
))
|
||||
|
||||
|
||||
async def fetch_gold() -> list[dict]:
|
||||
async def fetch_gold(*, started_at: float | None = None) -> list[dict]:
|
||||
if started_at is None:
|
||||
started_at = time.time()
|
||||
update_time = str(refresh_slot(started_at))
|
||||
timeout = aiohttp.ClientTimeout(total=10)
|
||||
async with aiohttp.ClientSession(timeout=timeout) as session:
|
||||
async def fetch_region(region):
|
||||
@@ -81,7 +84,7 @@ async def fetch_gold() -> list[dict]:
|
||||
resp.raise_for_status()
|
||||
data = payload['data']
|
||||
return normalize_row({
|
||||
'updataTime': str(int(datetime.now(timezone.utc).timestamp())),
|
||||
'updataTime': update_time,
|
||||
'region': f'跨{region}', 'code': GOLD_REGION_CODES[f'跨{region}'],
|
||||
'goldDealRank': [float(item['price']) for item in data['godDealRank'][:5]],
|
||||
'goldTopDealRank': [float(item['price']) for item in data['godTopDealRank'][:5]],
|
||||
@@ -150,7 +153,7 @@ async def read_cache(redis) -> list[dict]:
|
||||
for item in json.loads(gzip_unzip(value))]
|
||||
if [row['region'] for row in rows] != [f'跨{region}' for region in REGIONS]:
|
||||
return []
|
||||
if any(not 0 <= time.time() - int(row['updataTime']) < RETENTION_SECONDS for row in rows):
|
||||
if any(not -UPDATE_LEAD_SECONDS <= time.time() - int(row['updataTime']) < RETENTION_SECONDS for row in rows):
|
||||
return []
|
||||
return rows
|
||||
except (ValueError, TypeError, KeyError, OSError):
|
||||
@@ -160,7 +163,7 @@ async def read_cache(redis) -> list[dict]:
|
||||
|
||||
def is_fresh(rows: list[dict]) -> bool:
|
||||
return (len(rows) == len(REGIONS)
|
||||
and all(0 <= time.time() - int(row['updataTime']) < FRESH_SECONDS for row in rows))
|
||||
and all(int(row['updataTime']) == refresh_slot() for row in rows))
|
||||
|
||||
|
||||
async def refresh_cache(redis) -> bool:
|
||||
@@ -173,7 +176,7 @@ async def refresh_cache(redis) -> bool:
|
||||
if is_fresh(await read_cache(redis)) or await redis.get(COOLDOWN_KEY):
|
||||
return False
|
||||
try:
|
||||
data = await fetch_gold()
|
||||
data = await fetch_gold(started_at=time.time())
|
||||
except TokenExpired:
|
||||
logger.warning('official gold authentication failed; check HELPER_TOKEN and HELPER_ID')
|
||||
await notify_token_expired(redis)
|
||||
|
||||
Reference in New Issue
Block a user