""" Diagnostic: figure out why /meta shows no points per player. Compares Guild_Metas userIDs against the uid keys returned by obtain_clan_new_points() for the guild's bound squadron, and reports each plausible failure mode (missing Guilds row, empty API response, uid format mismatch, squadron-name mismatch). Usage (on the server): cd ~/SREBOT/SREBOT_MEOW source .venv/bin/activate python scripts/diag_meta_points.py 1378960248118841507 """ from __future__ import annotations import asyncio import sys from pathlib import Path import aiosqlite ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT)) from BOT.game_api import ClanInfoError, obtain_clan_new_points from BOT.utils import STORAGE_DIR async def diag(guild_id: str) -> None: meta_db = STORAGE_DIR / "Meta.db" print(f"== Meta.db: {meta_db} (exists={meta_db.exists()})") if not meta_db.exists(): print("Meta.db missing — wrong STORAGE_DIR?") return async with aiosqlite.connect(meta_db) as db: cur = await db.execute( "SELECT squadron_name, squadron_clanID FROM Guilds WHERE guild_id=?", (guild_id,), ) guilds_row = await cur.fetchone() print(f"== Guilds row for {guild_id}: {guilds_row}") cur = await db.execute( "SELECT COUNT(*) FROM Guild_Metas WHERE guild_id=?", (guild_id,) ) gm_count_row = await cur.fetchone() gm_count = gm_count_row[0] if gm_count_row else 0 print(f"== Guild_Metas count for {guild_id}: {gm_count}") cur = await db.execute( "SELECT userID, nick, clanName FROM Guild_Metas " "WHERE guild_id=? ORDER BY nick LIMIT 5", (guild_id,), ) gm_rows = await cur.fetchall() print("== Guild_Metas sample:") for uid, nick, clan in gm_rows: print(f" uid={uid!r} type={type(uid).__name__} nick={nick!r} clan={clan!r}") if not guilds_row: print("\nNo Guilds row — /meta-management was never run for this guild.") return sq_name = guilds_row[0] print(f"\n== Calling obtain_clan_new_points({sq_name!r})...") try: members, total = await obtain_clan_new_points(sq_name) except ClanInfoError as e: print(f" ClanInfoError: {e}") return except Exception as e: print(f" {type(e).__name__}: {e}") return print(f"== API returned: {len(members)} members, total_score={total}") if not members: print(" Empty members dict — JWT was likely refreshed; rerun the script.") return sample = list(members.items())[:3] print("== API sample:") for uid, info in sample: print(f" uid={uid!r} type={type(uid).__name__} info={info}") gm_rows_list = list(gm_rows) if gm_rows_list: gm_uid = gm_rows_list[0][0] print( f"\n== Membership test for first Guild_Metas uid {gm_uid!r}:\n" f" raw in api_map -> {gm_uid in members}\n" f" str(uid) in api_map -> {str(gm_uid) in members}" ) api_uids = set(members.keys()) gm_uids_all = set() async with aiosqlite.connect(meta_db) as db: cur = await db.execute( "SELECT userID FROM Guild_Metas WHERE guild_id=?", (guild_id,) ) gm_uids_all = {str(r[0]) for r in await cur.fetchall()} api_uids_str = {str(u) for u in api_uids} overlap = gm_uids_all & api_uids_str only_gm = gm_uids_all - api_uids_str only_api = api_uids_str - gm_uids_all print( f"\n== Set overlap (str-cast both sides):\n" f" in both: {len(overlap)}\n" f" only in Guild_Metas: {len(only_gm)} (left squadron / wrong sq_name?)\n" f" only in API: {len(only_api)} (never bulk-added)" ) def main() -> None: if len(sys.argv) != 2: print("Usage: python scripts/diag_meta_points.py ") sys.exit(2) asyncio.run(diag(sys.argv[1])) if __name__ == "__main__": main()