| |
| import aiohttp |
| from bs4 import BeautifulSoup |
| from typing import List, Dict |
|
|
| GENSHIN_API = ( |
| "https://genshin-impact.fandom.com/api.php" |
| "?action=parse" |
| "&page=Promotional_Code" |
| "&prop=text" |
| "&format=json" |
| ) |
|
|
| class GenshinCodeLogic: |
| def __init__(self): |
| self.session: aiohttp.ClientSession | None = None |
|
|
| async def start(self): |
| if not self.session: |
| self.session = aiohttp.ClientSession( |
| headers={"User-Agent": "Mozilla/5.0 (GenshinCodeBot)"} |
| ) |
|
|
| async def stop(self): |
| if self.session: |
| await self.session.close() |
| self.session = None |
|
|
| async def fetch_codes(self) -> Dict: |
| async with self.session.get( |
| GENSHIN_API, |
| timeout=aiohttp.ClientTimeout(total=20) |
| ) as resp: |
| if resp.status != 200: |
| return {"count": 0, "cards": []} |
|
|
| data = await resp.json() |
|
|
| html = data.get("parse", {}).get("text", {}).get("*") |
| if not html: |
| return {"count": 0, "cards": []} |
|
|
| soup = BeautifulSoup(html, "html.parser") |
|
|
| cards: List[Dict] = [] |
|
|
| for row in soup.select("table.wikitable tbody tr"): |
| tds = row.find_all("td") |
| if len(tds) < 3: |
| continue |
|
|
| code_els = tds[0].find_all("code") |
| if not code_els: |
| continue |
|
|
| codes = [c.get_text(strip=True) for c in code_els] |
|
|
| server = tds[1].get_text(" ", strip=True) |
|
|
| rewards = [] |
| for item in tds[2].select(".item-text"): |
| text = item.get_text(" ", strip=True) |
| if text: |
| rewards.append(text) |
|
|
| validity = ( |
| tds[3].get_text(" ", strip=True) |
| if len(tds) >= 4 else None |
| ) |
|
|
| cards.append({ |
| "codes": codes, |
| "server": server, |
| "rewards": rewards, |
| "validity": validity |
| }) |
|
|
| return { |
| "count": sum(len(card["codes"]) for card in cards), |
| "cards": cards |
| } |