Files
tipibot/DEV_NOTES.md
2026-03-20 17:35:35 +02:00

9.7 KiB
Raw Permalink Blame History

TipiLAN Bot - Developer Reference

File Structure

File Purpose
bot.py All Discord commands, views (UI components), event handlers, reminder system
economy.py All economy logic, data model, constants (SHOP, COOLDOWNS, LEVEL_ROLES, etc.)
pb_client.py Async PocketBase REST client - auth token cache, CRUD on economy_users collection
strings.py Single source of truth for all user-facing text. Edit here to change any message.
sheets.py Google Sheets integration (member sync)
member_sync.py Birthday/member sync background task
config.py Environment variables (TOKEN, GUILD_ID, PB_URL, etc.)
migrate_to_pb.py One-time utility: migrate data/economy.json → PocketBase
add_stats_fields.py Schema migration: add new fields to economy_users PocketBase collection

Adding a New Economy Command

Checklist - do all of these, in order:

  1. economy.py - add the do_<cmd> async function with cooldown check, logic, _commit, and _txn logging
  2. economy.py - add the cooldown to COOLDOWNS dict if it has one
  3. economy.py - add the EXP reward to EXP_REWARDS dict 3a. PocketBase - if the function stores new fields, add them as columns via python scripts/add_stats_fields.py (or manually in the PB admin UI at http://127.0.0.1:8090/_/). Fields not in the PB schema are silently dropped on PATCH.
  4. strings.py CMD - add the slash command description
  5. strings.py OPT - add any parameter descriptions
  6. strings.py TITLE - add embed title(s) for success/fail states
  7. strings.py ERR - add any error messages (banned, cooldown uses CD_MSG, jailed uses CD_MSG["jailed"])
  8. strings.py CD_MSG - add cooldown message if command has a cooldown
  9. strings.py HELP_CATEGORIES["tipibot"]["fields"] - add the command to the help embed
  10. bot.py - implement the cmd_<name> function, handle all res["reason"] cases
  11. bot.py - call _maybe_remind if the command has a cooldown and reminders make sense
  12. bot.py - call _award_exp(interaction, economy.EXP_REWARDS["<cmd>"]) on success
  13. strings.py REMINDER_OPTS - add a reminder option if the command needs one
  14. bot.py _maybe_remind - if the command has an item-modified cooldown, add an elif branch

Adding a New Shop Item

Checklist:

  1. economy.py SHOP - add the item dict {name, emoji, cost, description: strings.ITEM_DESCRIPTIONS["key"]}
  2. economy.py SHOP_TIERS - add the key to the correct tier list (1/2/3)
  3. economy.py SHOP_LEVEL_REQ - add minimum level if it is T2 (≥10) or T3 (≥20)
  4. strings.py ITEM_DESCRIPTIONS - add the item description (Estonian flavour + English effect)
  5. strings.py HELP_CATEGORIES["shop"]["fields"] - add display entry (sorted by cost)
  6. If the item modifies a cooldown:
    • economy.py - add the if "item" in user["items"] branch in the relevant do_<cmd> function
    • bot.py _maybe_remind - add elif cmd == "<cmd>" and "<item>" in items: branch with the new delay
    • bot.py cmd_cooldowns - add the item annotation to the relevant status line

Adding a New Level Role

  1. economy.py LEVEL_ROLES - add (min_level, "RoleName") in descending level order (highest first)
  2. bot.py _ensure_level_role - no changes needed (uses LEVEL_ROLES dynamically)
  3. Run /economysetup in the server to create the role and set its position

Adding a New Admin Command

  1. strings.py CMD - add "[Admin] ..." description
  2. strings.py HELP_CATEGORIES["admin"]["fields"] - add the entry
  3. bot.py - add @app_commands.default_permissions(manage_guild=True) and @app_commands.guild_only()

Economy System Design

Storage

All economy state is stored in PocketBase (economy_users collection). pb_client.py owns all reads/writes. Each do_* function in economy.py calls get_user() → mutates the local dict → calls _commit(). _commit does a PATCH to PocketBase.

Currency & Income Sources

Command Cooldown Base Earn Notes
/daily 20h (18h w/ korvaklapid) 150⬡ ×streak multiplier, ×2 w/ lan_pass, +5% interest w/ gaming_laptop
/work 1h (40min w/ monitor) 15-75⬡ ×1.5 w/ gaming_hiir, ×1.25 w/ reguleeritav_laud, ×3 30% chance w/ energiajook
/beg 5min (3min w/ hiirematt) 10-40⬡ ×2 w/ klaviatuur
/crime 2h 200-500⬡ win 60% success (75% w/ cat6), +30% w/ mikrofon; fail = fine + jail
/rob 2h 1025% of target 45% success (60% w/ jellyfin); fail = fine; cannot rob TipiBOT
/heist 4h personal + 1h global 2055% of house / n players solo allowed, max 8; 35%+5%/player success (cap 65%); fail = 3h jail + ~15% balance fine
/slots - varies pair=+0.5× bet; triple tiered: heart×4, fire×5, troll×7, cry×10, skull×15, karikas×25 (jackpot); ×1.5 w/ monitor_360; miss=lose bet; house edge ~5%
/roulette - 2× red/black, 14× green 1/37 green chance
/blackjack - 1:1 win, 3:2 BJ, 2:1 double Dealer stands on 17+; double down on first action only

"all" Keyword

Commands that accept a coin amount (/give, /roulette, /rps, /slots, /blackjack) accept "all" to mean the user's full current balance. Parsed by _parse_amount(value, balance) in bot.py.

Daily Streak Multipliers

  • 1-2 days: ×1.0 (150⬡)
  • 3-6 days: ×1.5 (225⬡)
  • 7-13 days: ×2.0 (300⬡)
  • 14+ days: ×3.0 (450⬡)
  • karikas item: streak survives missed days

Jail

  • Normal duration: 30 minutes (JAIL_DURATION)
  • Heist fail duration: 3 hours (HEIST_JAIL) + fine 15% of balance (min 150⨡, max 1000⨡)
  • gaming_tool: prevents jail on crime fail
  • /jailbreak: 3 dice rolls, need doubles to escape free. On fail - bail = 20-30% of balance, min 350⬡. If balance < 350⬡, player stays jailed until timer.

EXP Rewards (from EXP_REWARDS in economy.py)

EXP is awarded on every successful command use. Level formula: floor(sqrt(exp / 10)), so Level 5 = 250 EXP, Level 10 = 1000, Level 20 = 4000, Level 30 = 9000.


Role Hierarchy (Discord)

Order top to bottom in server roles:

[Bot managed role]  ← bot's own role, always at top of our stack
ECONOMY             ← given to everyone who uses any economy command
TipiLEGEND          ← level 30+
TipiCHAD            ← level 20+
TipiHUSTLER         ← level 10+
TipiGRINDER         ← level 5+
TipiNOOB            ← level 1+

Run /economysetup to auto-create all roles and set their positions. The command is idempotent - safe to run multiple times.

Role assignment:

  • ECONOMY role: given automatically on first EXP award (i.e. first successful economy command)
  • Level roles: given/swapped automatically on level-up; synced on /rank

Shop Tiers & Level Requirements

Tier Level Required Items
T1 0 (any) gaming_hiir, hiirematt, korvaklapid, lan_pass, anticheat, energiajook, gaming_laptop
T2 10 reguleeritav_laud, jellyfin, mikrofon, klaviatuur, monitor, cat6
T3 20 monitor_360, karikas, gaming_tool

Shop display is sorted by cost (ascending) within each tier. The SHOP_LEVEL_REQ dict in economy.py controls per-item lock thresholds.


strings.py Organisation

Section Dict Usage in bot.py
Flavour text WORK_JOBS, BEG_LINES, CRIME_WIN, CRIME_LOSE Randomised descriptions
Command descriptions CMD["key"] @tree.command(description=S.CMD["key"])
Parameter descriptions OPT["key"] @app_commands.describe(param=S.OPT["key"])
Help embed HELP_CATEGORIES["cat"] cmd_help
Banned message MSG_BANNED All banned checks
Reminder options REMINDER_OPTS RemindersSelect dropdown
Slots outcomes SLOTS_TIERS["tier"](title, color) cmd_slots
Embed titles TITLE["key"] discord.Embed(title=S.TITLE["key"])
Error messages ERR["key"] send_message(S.ERR["key"]) - use .format(**kwargs) for dynamic parts
Cooldown messages CD_MSG["cmd"].format(ts=_cd_ts(...)) Cooldown responses
Shop UI SHOP_UI["key"] _shop_embed
Item descriptions ITEM_DESCRIPTIONS["item_key"] economy.SHOP[key]["description"]

Constants Location Quick-Reference

Constant File Description
SHOP economy.py All shop items (name, emoji, cost, description)
SHOP_TIERS economy.py Which items are in T1/T2/T3
SHOP_LEVEL_REQ economy.py Min level per item
COOLDOWNS economy.py Base cooldown per command
JAIL_DURATION economy.py How long jail lasts
LEVEL_ROLES economy.py [(min_level, "RoleName"), ...] highest first
ECONOMY_ROLE economy.py Name of the base economy participation role
EXP_REWARDS economy.py EXP per command
HOUSE_ID economy.py Bot's user ID (house account for /rob)
MIN_BAIL economy.py Minimum bail payment (350⬡)
COIN economy.py The coin emoji string

Balance Notes (as of current version)

  • Beg is most efficient for active players (3min cooldown + 2× multiplier w/ klaviatuur = high ⬡/hr)
  • Work is best for passive players (1h cooldown, fire and forget)
  • Crime is high risk/reward - best with cat6 + mikrofon
  • lan_pass (1200⬡) doubles daily - good long-term investment
  • gaming_laptop (1500⬡) 5% interest, capped 500⬡/day - snowballs with large balance
  • anticheat is consumable (2 uses) - only item that can be re-bought
  • karikas (T3) is the only item that preserves a daily streak across missed days
  • reguleeritav_laud (T2) stacks with gaming_hiir: combined ×1.5 × ×1.25 = ×1.875