2.8 KiB
Leaderboard bot integration
The Discord bot owns all writes to user_levels and voice_time. The website only
subscribes to notifications and then reads the committed database state.
Level formula contract
The website's personal profile calculates next-level progress from the bot's stored level and cumulative XP. Both services must use this exact formula:
required(0) = 500
required(level) = required(level - 1) + 100 + (level * 25)
total(0) = 0
total(level) = total(level - 1) + required(level - 1)
required(level) is the XP needed to advance from that level to the next. total(level)
is the cumulative XP needed to reach that level. Level 200 is the maximum; the XP
requirement caps at the level-199 value and the profile does not show next-level
progress at the cap.
Store cumulative XP as an integer value and update xp and level in the same bot
transaction. Changing the formula or maximum level requires a coordinated website
update because the website intentionally does not infer the formula from database
metadata.
Redis channel
Publish leaderboard notifications to exactly:
erika:sse:leaderboards
The bot and website use the same Redis deployment. Do not add Redis credentials to source code or event payloads.
Event envelopes
XP changes use this exact JSON envelope:
{"event":"xp","data":{}}
Voice-time changes use the affected Discord channel ID:
{"event":"vc","data":{"channelId":"123456789012345678"}}
No additional envelope or data fields are accepted. channelId is a Discord
snowflake represented as a decimal string.
Publish ordering
- Start and complete the bot’s database transaction.
- Confirm that the transaction committed successfully.
- Publish the corresponding Redis event or events.
Never publish before commit, from a rollback path, or from a finally block. The
notification tells an open website page to read the database again, so publishing
before commit can produce a stale refresh.
Event cardinality
- Publish one XP event when one transaction changes XP data.
- Publish one VC event per affected channel when one transaction changes voice time.
- When one transaction changes both XP and voice time, publish one XP event and one VC event for each affected channel.
- For a bulk transaction, deduplicate affected scopes and channel IDs. Publish per affected scope/channel, never per user.
Example: a bulk transaction changes XP for 200 users and voice time in channels 111
and 222. After commit, publish three events: one XP event, one VC event for 111,
and one VC event for 222.
Error handling
Publishing is best-effort. Log Redis failures with enough context to identify the event scope, but do not roll back or report a successfully committed database transaction as failed. Open pages recover on SSE reconnection or the next navigation.