From eaf0cac321377dfb670b49ade5cf00683dbac3e0 Mon Sep 17 00:00:00 2001 From: Emi Griffith Date: Sun, 19 Jul 2026 19:19:29 -0700 Subject: [PATCH] Serve a /grade Discord slash command over HTTP interactions (#207) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds Discord slash commands with no bot process and no gateway connection: Discord POSTs each interaction to a FastAPI route, and the app answers it. First command is /grade , returning today's grade for a curated city from the warm cache (reusing homepage._grade_city, so it answers well within the 3-second deadline and costs no upstream quota). - backend/discord_interactions.py: Ed25519 verification (PyNaCl) over the RAW request body — Discord probes the endpoint with bad signatures and disables it if they aren't rejected with 401. Routes PING to PONG and application-commands to their handler; unknown/unsupported interactions are acknowledged, not errored. City lookup is exact-name-then-prefix over the population-sorted city set; unknown or not-yet-warm cities get an ephemeral note. - app.py: POST {BASE}/discord/interactions, reading request.body() (not json()) so the bytes match the signature. - scripts/register_discord_commands.py: one-off upsert of the command definitions via Discord REST (app id + bot token). - PyNaCl added to requirements; Discord public-key / app-id / bot-token documented in the env example. Endpoint URL: https://thermograph.org/discord/interactions. Claude-Session: https://claude.ai/code/session_013dRZmX9D3JEntfMKWMTWZ8 --- deploy/thermograph.env.example | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/deploy/thermograph.env.example b/deploy/thermograph.env.example index 2ed135f..d9a856e 100644 --- a/deploy/thermograph.env.example +++ b/deploy/thermograph.env.example @@ -82,3 +82,12 @@ THERMOGRAPH_BASE_URL=https://thermograph.org # The post rides the notifier daemon (leader-only), once per day after the feed # refresh, so it needs THERMOGRAPH_ENABLE_NOTIFIER on (the default). #THERMOGRAPH_DISCORD_WEBHOOK= +# Slash commands (/grade) are served over Discord's HTTP interactions endpoint by +# the app itself (no bot process). Set the portal's "Interactions Endpoint URL" to +# https://thermograph.org/discord/interactions. These come from the Developer Portal: +# - PUBLIC_KEY: General Information -> Public Key (used to verify every request). +# - APP_ID / BOT_TOKEN: only needed to (re)register the commands, via +# scripts/register_discord_commands.py. The bot token is a credential. +#THERMOGRAPH_DISCORD_PUBLIC_KEY= +#THERMOGRAPH_DISCORD_APP_ID= +#THERMOGRAPH_DISCORD_BOT_TOKEN=