forked from sass/tipibot
feat(economy): add /lottery - daily draw, weighted winner takes the pot
Buy tickets (200 coins each, max 100/draw); one winner is drawn daily at 21:00 Tallinn time weighted by ticket count and credited the whole pot. Coin-conserving by design: each ticket's cost is deducted at purchase and the winner is minted exactly the sum of all ticket spend - no shared pot record, so no cross-period race. Ticket state lives per-user keyed by draw period (full scan only at draw time and for the pot view). - New lottery.py: TICKET_COST/MAX_TICKETS/DRAW_HOUR, pure period_for, and do_buy_ticket / get_lottery_state / do_lottery_draw. New lottery_tickets + lottery_period schema fields (period added to _TEXT_FIELDS). - /lottery [kogus] command (view or buy) with full failure handling. - Scheduled lottery_draw_daily loop in bot.py (both profiles; each draws its own collection), announcing to the optional LOTTERY_CHANNEL_ID (config + .env). 14 tests: period boundary, buy/accumulate/reset/caps/guards, pot state, draw payout with coin conservation, and the more-tickets-wins-more weighting. 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:
@@ -42,6 +42,15 @@ BIRTHDAY_CHANNEL_ID = (
|
||||
BIRTHDAY_WINDOW_DAYS = int(os.getenv("BIRTHDAY_WINDOW_DAYS", "7"))
|
||||
BASE_ROLE_IDS: list[int] = [1478304631930228779, 1478302278862766190]
|
||||
|
||||
# Channel where the daily lottery draw result is announced. Optional - if unset,
|
||||
# the draw still runs and pays the winner, it just isn't announced.
|
||||
_LEGACY_LOTTERY_CHANNEL_ID = _env_int("LOTTERY_CHANNEL_ID", 0)
|
||||
LOTTERY_CHANNEL_ID_DEV = _env_int("LOTTERY_CHANNEL_ID_DEV", _LEGACY_LOTTERY_CHANNEL_ID)
|
||||
LOTTERY_CHANNEL_ID_ECONOMY = _env_int("LOTTERY_CHANNEL_ID_ECONOMY", 0)
|
||||
LOTTERY_CHANNEL_ID = (
|
||||
LOTTERY_CHANNEL_ID_ECONOMY if BOT_PROFILE == "economy" else LOTTERY_CHANNEL_ID_DEV
|
||||
)
|
||||
|
||||
|
||||
def _parse_admin_roles(raw: str) -> dict[int, set[int]]:
|
||||
"""Parse DISCORD_ADMIN_ROLES env var as "guild_id:role_id[:role_id...],guild_id:role_id...".
|
||||
|
||||
Reference in New Issue
Block a user