Discord picker: per-bot permission status + owner's preferred bot (#225 S4) — merge after S3 #250

Merged
logan merged 2 commits from feat/225-s4-picker-ui into main 2026-10-05 02:38:56 -04:00
2 changed files with 48 additions and 1 deletions
Showing only changes of commit ec90a3f97c - Show all commits
+11 -1
View File
@@ -87,6 +87,16 @@ def _channel_state(rows: list[dict], enabled: bool) -> str:
return "no_bot"
def _checked_at(snaps: dict) -> str:
"""When Discord was last actually asked: the OLDEST cached snapshot behind
this answer (a denied result is cached for 10 min), so the picker's
"Permissions checked N ago" never calls a stale answer fresh (server-26#225
S4). No snapshot (check off, no member bots) = now."""
times = [s.fetched_at for s in snaps.values() if s is not None and getattr(s, "fetched_at", None)]
ts = min(times) if times else time.time()
return datetime.fromtimestamp(ts, timezone.utc).isoformat()
async def voice_check(*, guild_id: str, org_id: Optional[str], node_id: Optional[str],
channels: list[dict], channel_id: Optional[str], refresh: bool,
with_token_ids: bool) -> dict:
@@ -171,7 +181,7 @@ async def voice_check(*, guild_id: str, org_id: Optional[str], node_id: Optional
"guild_id": guild_id,
"node_id": node_id,
"enabled": enabled,
"checked_at": datetime.now(timezone.utc).isoformat(),
"checked_at": _checked_at(snaps),
"refreshed": refresh,
"channels": out_channels,
"invite": invite,
+37
View File
@@ -0,0 +1,37 @@
"""
voice-check's ``checked_at`` is when Discord was last asked — the oldest
cached snapshot behind the answer — not the time of the HTTP response, so the
picker's "Permissions checked N ago" footer never calls a 10-minute-old
denied result fresh (server-26#225 S4).
"""
import time
from datetime import datetime
from app.internal import discord_rest
from app.routers import discord_checks as checks
from tests.test_discord_perm_check import GUILD, OWNER, _snap, _token, fs, run # noqa: F401 (fs = fixture)
def _age(out) -> float:
return time.time() - datetime.fromisoformat(out["checked_at"]).timestamp()
def test_checked_at_is_the_oldest_snapshot_not_now(fs, monkeypatch):
_token(fs, "t1"); _token(fs, "t2")
ages = {"t1": 30, "t2": 420}
async def _old(token_doc, guild_id, *, refresh=False):
s = _snap(token_doc["token_id"])
s.fetched_at = time.time() - (0 if refresh else ages[token_doc["token_id"]])
return s
monkeypatch.setattr(discord_rest, "guild_snapshot", _old)
out = run(checks.node_voice_check("n1", GUILD, refresh=0, channel_id=None, decoded=OWNER))
assert 415 <= _age(out) <= 430
out = run(checks.node_voice_check("n1", GUILD, refresh=1, channel_id=None, decoded=OWNER))
assert _age(out) < 5
def test_checked_at_without_snapshots_is_now(fs):
out = run(checks.node_voice_check("n1", GUILD, refresh=0, channel_id=None, decoded=OWNER)) # no bots
assert _age(out) < 5