forked from sass/tipibot
feat(economy): persist interactive-game stakes so a restart can't eat them
Blackjack and RPS PvP deduct a stake up front and held it only in an in-memory View - a restart mid-hand lost the coins. Now the stake is escrowed on the user record (new pending_wager JSON field) in the SAME commit as the deduction, and: - do_blackjack_bet accumulates the escrow (covers double/split); do_blackjack_payout clears it on settlement (incl. the 0-payout loss/timeout paths). - do_rps_pvp_deposit records it; do_rps_pvp_payout/refund clear it, and a new do_rps_pvp_forfeit clears the loser's marker (their stake went to the winner). - reconcile_pending_wagers() runs on startup (on_ready) and refunds any stake left escrowed by an interrupted game. It's idempotent and locks per user. Schema: pending_wager auto-types as json via sync_pb_schema. Tests cover the full escrow lifecycle, loser forfeit, and idempotent reconciliation. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013VbAVsrZuYesea99mPMmPT
This commit is contained in:
10
bot.py
10
bot.py
@@ -441,6 +441,16 @@ async def on_ready():
|
||||
# Re-schedule any reminder tasks lost on restart
|
||||
await _restore_reminders()
|
||||
|
||||
# Refund stakes escrowed by interactive games (blackjack/RPS PvP) that a
|
||||
# restart interrupted, so a mid-hand crash never eats a player's coins.
|
||||
try:
|
||||
refunded = await economy.reconcile_pending_wagers()
|
||||
if refunded:
|
||||
total = sum(amt for _, amt, _ in refunded)
|
||||
log.info("Reconciled %d interrupted wager(s), refunded %d coins", len(refunded), total)
|
||||
except Exception:
|
||||
log.exception("Pending-wager reconciliation failed")
|
||||
|
||||
# Notify the channel where /restart was triggered
|
||||
if _RESTART_FILE.exists():
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user