13 KiB
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.) |
Adding a New Economy Command
Checklist - do all of these, in order:
economy.py- add thedo_<cmd>async function with cooldown check, logic,_commit, and_txnloggingeconomy.py- add the cooldown toCOOLDOWNSdict if it has oneeconomy.py- add the EXP reward toEXP_REWARDSdict- PocketBase - if the function stores new fields, add them manually in the PB admin UI at
http://127.0.0.1:8090/_/. Fields not in the PB schema are silently dropped on PATCH. strings.pyCMD- add the slash command descriptionstrings.pyOPT- add any parameter descriptionsstrings.pyTITLE- add embed title(s) for success/fail statesstrings.pyERR- add any error messages (banned, cooldown usesCD_MSG, jailed usesCD_MSG["jailed"])strings.pyCD_MSG- add cooldown message if command has a cooldownstrings.pyHELP_CATEGORIES["tipibot"]["fields"]- add the command to the help embedbot.py- implement thecmd_<name>function, handle allres["reason"]casesbot.py- call_maybe_remindif the command has a cooldown and reminders make sensebot.py- call_award_exp(interaction, economy.EXP_REWARDS["<cmd>"])on successstrings.pyREMINDER_OPTS- add a reminder option if the command needs onebot.py_maybe_remindand_restore_reminders- if item-modified cooldown, addelifbranchbot.py_REMINDER_COOLDOWN_KEYS- add"cmd": "last_cmd"mapping if reminder-capable
Adding a New Shop Item
Checklist:
economy.pySHOP- add the item dict{name, emoji, cost, description: strings.ITEM_DESCRIPTIONS["key"]}economy.pySHOP_TIERS- add the key to the correct tier list (1/2/3)economy.pySHOP_LEVEL_REQ- add minimum level if it is T2 (≥10) or T3 (≥20)strings.pyITEM_DESCRIPTIONS- add the item description (Estonian flavour + English effect)strings.pyHELP_CATEGORIES["shop"]["fields"]- add display entry (sorted by cost)- If the item modifies a cooldown:
economy.py- add theif "item" in user["items"]branch in the relevantdo_<cmd>functionbot.py_maybe_remind- addelif cmd == "<cmd>" and "<item>" in items:branch with the new delaybot.py_restore_reminders- add the sameelifbranchbot.pycmd_cooldowns- add the item annotation to the relevant status line
Adding a New Level Role
economy.pyLEVEL_ROLES- add(min_level, "RoleName")in descending level order (highest first)bot.py_ensure_level_role- no changes needed (usesLEVEL_ROLESdynamically)- Run
/economysetupin the server to create the role and set its position
Adding a New Admin Command
strings.pyCMD- add"[Admin] ..."descriptionstrings.pyOPT- add parameter descriptionsstrings.pyADMIN- add response and DM stringsstrings.pyHELP_CATEGORIES["admin"]["fields"]- add the entryeconomy.py- adddo_admin_<name>functionbot.py- add command with@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; prestige daily_plus adds +20% per level |
/work |
1h (40min w/ monitor) | 15-75⬡ | ×1.5 w/ gaming_hiir, ×1.25 w/ reguleeritav_laud, ×3 30% chance w/ energiajook; prestige work_plus +20%/level |
/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 | 10–25% of target | 45% success (60% w/ jellyfin); fail = fine; cannot rob TipiBOT directly |
/heist |
4h personal + 1h global | 20–55% of house / n players | solo allowed, max 8; 35%+5%/player success (cap 65%); fail = 3h jail + ~15% balance fine |
/fish |
2min (90s w/ ussipurk) | varies by fish rarity | Interactive minigame; catches go to inventory; sell with /fishsell |
/slots |
- | varies | pair=+0.5× bet; triple tiered; karikas jackpot ×25; ×1.5 w/ monitor_360; miss=lose bet |
/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 |
Fishing System
/fish- interactive minigame: cast → wait 5–15s for bite → press button within 2s (3s w/ echolood) → keep or sell- Fish stored in
fish_inventory(list of{fish_id, weight, value}objects) /fishbook- paginated fish collection showing caught species and inventory counts/fishsell- sell all fish from inventory at oncefish_inventoryandfish_booksurvive prestige resetskalavork(T3, 5000⬡): bumps all caught fish up one rarity tierussipurk(T2, 3500⬡): cooldown 2min → 90secholood(T3, 8000⬡): bite window 2s → 3s
Prestige System
- Requires level 30 (9000 EXP)
- Resets: balance, EXP, items, cooldowns, jail
- Preserves: fish_book, fish_inventory, lifetime stats, prestige_points, season_total_exp, prestige_upgrades
- Awards prestige_points = max(1, exp ÷ 1000) at time of prestige
- Each prestige increments
prestige_levelcounter - Prestige coin/exp multipliers apply to all earned values
Prestige Shop (PRESTIGE_SHOP in economy.py):
| Upgrade | Max Level | Cost/level | Effect |
|---|---|---|---|
coin_mult |
5 | 5 PP | +8% coin multiplier per level |
exp_mult |
5 | 5 PP | +8% EXP multiplier per level |
daily_plus |
3 | 7 PP | +20% daily base reward per level |
work_plus |
3 | 7 PP | +20% work earnings per level |
"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⬡)
karikasitem: 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 single-button dice rolls (both dice at once), need doubles to escape free. Animated reveal with TipiDICE emoji. On fail after 3 tries - bail = 20-30% of balance, min 350⬡. If balance < 350⬡, stay 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.
Fish EXP is awarded per catch (varies by rarity, defined in FISH_CATALOGUE). Prestige exp_mult upgrade applies to fish EXP.
Admin Commands Reference
| Command | What it does |
|---|---|
/pause |
Toggle maintenance mode - blocks all non-admin commands |
/admincoins @user <amount> <reason> |
Give/take coins (positive/negative). DMs user. |
/adminexp @user <amount> <reason> |
Give/take EXP (positive/negative). Auto-applies level roles on change. DMs user. |
/adminitem @user <item_id> <anna|eemalda> |
Give or remove any shop item for free. DMs user. |
/adminjail @user <minutes> <reason> |
Manually jail a user. DMs user. |
/adminunjail @user |
Remove jail from a user. |
/adminban @user <reason> |
Ban from all economy commands. DMs user. |
/adminunban @user |
Lift economy ban. |
/adminreset @user <reason> |
Wipe balance, EXP, items, streak. DMs user. |
/adminview @user |
Full profile: balance, EXP/level, streak, prestige, fish stats, items, timestamps. |
/adminseason <top_n> |
End season: DM top N players, reset all EXP. |
All admin commands require Manage Guild permission and work in any channel (bypass pause and channel restrictions).
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 /adminexp: automatically re-applies level roles if level changes
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, ussipurk |
| T3 | 20 | monitor_360, karikas, gaming_tool, kalavork, echolood |
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"] |
| Fish UI | FISH_UI["key"] |
/fish, /fishbook, /fishsell |
| Fish names | FISH_NAMES["fish_id"] |
Fish display name |
| Admin responses | ADMIN["key"] |
Admin command success/DM messages |
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 |
FISH_CATALOGUE |
economy.py |
All fish species (rarity, weight, coins, exp) |
PRESTIGE_SHOP |
economy.py |
Prestige upgrade definitions |
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 investmentgaming_laptop(1500⬡) 5% interest, capped 500⬡/day - snowballs with large balanceanticheatis consumable (2 uses) - only item that can be re-boughtkarikas(T3) is the only item that preserves a daily streak across missed daysreguleeritav_laud(T2) stacks withgaming_hiir: combined ×1.5 × ×1.25 = ×1.875- Fishing is a steady passive income;
kalavork(T3) dramatically increases fish value by bumping rarity