Skip to content

Commit c8573c2

Browse files
committed
feat: switch RNG to secrets module, reduce instant win chance to 1%
Replace Python's random (Mersenne Twister) with secrets (os.urandom) for all randomness: instant win rolls, daily draw, winner selection. Cryptographically secure RNG for a play-money lottery bot — overkill, but correct. Instant win chance reduced from 2.5% to 1% per entry (~once every 5 days with 20 entries/day, down from once every 2 days).
1 parent 459398a commit c8573c2

1 file changed

Lines changed: 7 additions & 7 deletions

File tree

luckypot/game.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import asyncio
2-
import random
2+
import secrets
33
from collections import defaultdict
44
from functools import partial
55
from typing import Any, Callable, Awaitable
@@ -12,7 +12,7 @@
1212

1313
POT_ENTRY_COST = 5
1414
DAILY_DRAW_CHANCE = 0.95
15-
RANDOM_WIN_CHANCE = 0.025
15+
RANDOM_WIN_CHANCE = 0.01
1616
AUTO_ENTER_DELAY_SECONDS = 30
1717

1818
# Per-guild lock to serialize pot mutations (entries, instant wins, draws).
@@ -80,7 +80,7 @@ async def enter_pot(
8080
# Roll for instant win BEFORE creating a payment request.
8181
# An instant win skips payment entirely — the user wins the
8282
# current pot for free and the pot ends immediately.
83-
if random.random() < RANDOM_WIN_CHANCE:
83+
if secrets.randbelow(10000) < RANDOM_WIN_CHANCE * 10000:
8484
participants = db.get_pot_participants(conn, pot_id)
8585
total_pot = sum(p["amount"] for p in participants)
8686
logger.info(
@@ -213,7 +213,7 @@ def select_random_winner(participants: list[dict]) -> dict | None:
213213
return None
214214

215215
total_weight = sum(max(p["amount"], POT_ENTRY_COST) for p in participants)
216-
roll = random.uniform(0, total_weight)
216+
roll = secrets.randbelow(total_weight + 1)
217217
cumulative = 0
218218
for p in participants:
219219
cumulative += max(p["amount"], POT_ENTRY_COST)
@@ -436,10 +436,10 @@ async def daily_pot_draw(
436436
async with _guild_locks[guild_id]:
437437
conn = db.get_connection()
438438
try:
439-
roll = random.random()
440-
if roll < DAILY_DRAW_CHANCE:
439+
roll = secrets.randbelow(10000)
440+
if roll < DAILY_DRAW_CHANCE * 10000:
441441
logger.info(
442-
f"Daily draw triggered for guild {guild_id} (roll={roll:.3f})"
442+
f"Daily draw triggered for guild {guild_id} (roll={roll}/10000)"
443443
)
444444
guild_announce = partial(announce, guild_id) if announce else None
445445
guild_edit = (

0 commit comments

Comments
 (0)