Commit Graph

70 Commits

Author SHA1 Message Date
Rene Arumetsa
ce1ed28904 refactor(teams): move team-role sync to the economy/community bot
The team-role feature was aimed at the wrong bot. Tournament participants
live in the economy/community guild, but team-role sync had been bolted onto
the dev bot's roster sync (sync_member), which bails out for anyone missing
from the internal member sheet - so it could never reach its actual audience.

Decouple it: keep the (roster-independent) team-sheet parsing, pull the team
wiring off the dev/member-sync path, and re-home it on the economy bot.

- core/member_sync: revert sync_member to add-only (drop team block +
  SyncResult.roles_removed); add roster-independent sync_team_role and a
  whole-guild sync_all_team_roles returning a reporting summary. Still only
  ever touches role NAMES present in the team sheet.
- commands/economy_team_commands: new admin-only /teamsync command.
- bot.py: hourly team_sync_hourly task (economy-only, no-op unless
  TEAM_SHEET_ID is set; first tick at boot covers startup load); register
  /teamsync under the economy profile; drop the dev-side startup load.
- commands/dev_member_commands: /check no longer refreshes teams or reports
  removed roles.
- strings + .env.example: TEAMSYNC_UI, CMD[teamsync], document TEAM_SHEET_ID.
- tests: retarget sync tests to sync_team_role; add sync_all_team_roles case.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R6JZkyszyDFuFtk25WBbcR
2026-08-28 15:04:23 +03:00
Rene Arumetsa
52002c37fc feat(members): assign team roles from the tournament registration sheet
Match members by Discord username against the lineup nicknames in the
separate registration spreadsheet (TEAM_SHEET_ID) and give each their
team's role. One team per person: switching teams removes the old team
role, and a team with no Discord role yet is auto-created. Only role
names present in the sheet are ever touched, so organisation/field/base
roles are never at risk; the feature is a no-op when TEAM_SHEET_ID is
unset.

The sheet is not a single table (merged rows, stacked CS2/LoL sections
with different layouts), so it is parsed via raw-row scanning rather than
get_all_records. Citizenship markers like "(EST)" are used only as
player delimiters and discarded.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-28 14:01:22 +03:00
567a82b9f2 Merge pull request 'feat(economy): add /consumables shop of repeatable, expiring boosts' (#5) from fix/economy-money-safety into master
All checks were successful
Test & Deploy / test (push) Successful in 5s
Test & Deploy / deploy (push) Successful in 6s
Reviewed-on: #5
2026-08-19 17:53:12 +00:00
f3c69738ef Merge pull request 'fix/economy-money-safety' (#4) from fix/economy-money-safety into master
All checks were successful
Test & Deploy / test (push) Successful in 5s
Test & Deploy / deploy (push) Successful in 7s
Reviewed-on: #4
2026-08-19 17:36:16 +00:00
Rene Arumetsa
a2e1601d0e feat(economy): add /consumables shop of repeatable, expiring boosts
The economy had many coin faucets but almost no sinks: the /shop is
one-time ownership, and gambling/rob fines route to the house (which
players drain back via jackpots and heists), so they recirculate rather
than destroy coins. Result: steady inflation.

Add a consumables shop as a true recurring sink - buying destroys the
coins and grants a temporary boost, so there's always something to spend
on after gear is maxed:

  - Energiajook XL (500) - 1h of 2x earnings on /work, /beg, /crime
  - XP jook (500)        - 1h of 2x EXP
  - Kohv (300)           - instantly clears all cooldowns

Timed buffs live in a new active_buffs field ({kind: expiry_iso}), pruned
on read; rebuying extends the timer. Effects hook where they belong:
earn_mult in income.do_work/do_beg/do_crime, exp_buff_mult in
levels.award_exp; kohv is self-contained. New /consumables command browses
the menu (with active buffs) or buys a boost. Covered by 9 tests.

Note: active_buffs is a new PocketBase field - run
scripts/sync_pb_schema.py before deploying or buffs won't persist.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-19 20:32:36 +03:00
Rene Arumetsa
b9b4c7c4c7 test(strings): guard that every string is re-exported from the package
strings/ is split into domain submodules whose names are re-exported from
strings/__init__.py. Adding a constant to a submodule and forgetting to
re-export it - or shadowing a name across two submodules - would only
surface as a runtime crash in a command. This test asserts every submodule
__all__ entry is reachable as strings.NAME, that no name is defined twice,
and that strings.__all__ matches the union of the submodules. Submodules
are auto-discovered, so a new one is covered without editing the test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-19 20:02:55 +03:00
Rene Arumetsa
254992c642 docs: point core/economy references at the package submodules
core/economy has long been a package (store/income/gambling/shop/levels/
jail/heist/prestige/fishing/quests/leaderboards/house/admin) rather than a
single core/economy.py, but README.md and docs/DEV_NOTES.md still described
it as one file in ~27 places. Point every reference at the real submodule,
add a "Defined in" column to the constants quick-reference and a Module
column to the strings table, and fix the stale FISH -> FISH_CATALOGUE name.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-19 20:02:47 +03:00
Rene Arumetsa
191726721c Update docs 2026-08-19 19:53:04 +03:00
Rene Arumetsa
0ea5580e15 Refactor strings.py into modules 2026-08-19 19:12:48 +03:00
Rene Arumetsa
738144ccfa Refacotr strings.py into modules 2026-08-19 19:12:21 +03:00
Rene Arumetsa
cec5ac01a0 Fix give coins, now actually gives rewards
All checks were successful
Test & Deploy / test (push) Successful in 4s
Test & Deploy / deploy (push) Successful in 6s
2026-08-17 19:29:15 +03:00
Rene Arumetsa
3b35f82d80 Fix RequestView over-funding reentrancy (do_give double-transfer)
A follow-up reentrancy sweep of the five remaining money-moving views found
one more instance of the same bug class. The other four (quests, prestige,
fish, shop) verified clean - their underlying do_* functions are idempotent.

RequestView / FundModal (commands/economy_support_commands.py):
- on_submit read self._view.remaining, then awaited do_give, then decremented
  remaining. Because discord.py dispatches each modal submit as its own task
  and do_give is a plain non-idempotent transfer, a funder could open two
  modals and submit both before the first resolved: both read the same
  pre-decrement remaining, both passed the range check, and both transferred
  `amount` - over-funding the request (remaining goes negative) and moving up
  to the funder's whole balance.
- Fix: reserve the amount synchronously (decrement remaining BEFORE the do_give
  await, with no await in between - atomic under asyncio), and roll the
  reservation back if the transfer fails. The second concurrent submit now
  sees the reduced remaining and is rejected. Added a cheap _fund guard
  (remaining<=0 / is_finished) so a click on a funded request doesn't open a
  dead modal.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-10 18:49:25 +03:00
5e303fe36f Merge pull request 'Fix money-safety bugs in economy (heist, blackjack, bail)' (#3) from fix/economy-money-safety into master
All checks were successful
Test & Deploy / test (push) Successful in 6s
Test & Deploy / deploy (push) Successful in 8s
Reviewed-on: #3
2026-08-10 15:35:46 +00:00
Rene Arumetsa
968356f925 Fix money-safety bugs in economy (heist, blackjack, bail)
Multi-agent audit of the money-moving economy modules surfaced three
confirmed correctness bugs. All three are fixed here with regression tests.

heist (core/economy/heist.py):
- `house = await get_user(house.HOUSE_ID)` shadowed the imported `house`
  module for the whole function, so `house.HOUSE_ID` raised UnboundLocalError
  on every successful heist (win payout was entirely dead) and on the
  fail-path compensation branch. Rename the local to `house_rec`.
- Un-shadowing exposed a latent mint: the pot was floored at 300 but the
  house was debited only min(total, balance), so a poor house paid out more
  than it lost. Cap the pot at the balance and debit exactly what is paid
  (house debit == sum of payouts). No mint, no leak.
- Add the missing `_is_jailed` import (do_heist_check referenced it unimported).

blackjack (commands/economy_games_commands.py):
- Button callbacks had no reentrancy guard; discord.py dispatches each click
  as its own task, so double-clicking Stand within the dealer-reveal window
  paid out twice (mint), and double-clicking Double/Split deducted the extra
  bet twice. Add a synchronous `_busy` guard (matching the existing RpsGame
  idiom) on all four callbacks plus a `_resolved` idempotency flag on
  settlement, so a game can only pay out once.

bail (core/economy/jail.py, commands/economy_extra_commands.py):
- do_bail only checked balance, never jail state; a double-click or a stale
  BailView from a re-run /jailbreak charged bail twice, destroying coins (bail
  is a pure sink). Make do_bail a no-op when the user is not jailed, and add a
  UI reentrancy guard + "already free" message.

Tests: 47 passed (4 new regression tests covering heist coin-conservation and
bail idempotency).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-10 18:31:46 +03:00
Rene Arumetsa
8d16da268d Fix eco bot service
All checks were successful
Test & Deploy / test (push) Successful in 21s
Test & Deploy / deploy (push) Successful in 7s
2026-07-27 15:52:51 +03:00
Rene Arumetsa
4dd7379e03 Fix workflow
Some checks failed
Test & Deploy / test (push) Successful in 22s
Test & Deploy / deploy (push) Failing after 7s
2026-07-27 15:22:56 +03:00
Rene Arumetsa
7fc0ccc77f Fix deploy.yml
Some checks failed
Test & Deploy / test (push) Successful in 57s
Test & Deploy / deploy (push) Failing after 5s
2026-07-27 01:04:26 +03:00
Rene Arumetsa
83a60cda55 Refator eco code. Split into modules
Some checks failed
Test & Deploy / test (push) Has been cancelled
Test & Deploy / deploy (push) Has been cancelled
2026-07-27 00:49:34 +03:00
Rene Arumetsa
d89383ee20 CI test
Some checks failed
Test & Deploy / test (push) Failing after 12m44s
Test & Deploy / deploy (push) Has been cancelled
2026-07-27 00:25:25 +03:00
Rene Arumetsa
8884cce9b5 Added a runner, ci/cd 2026-07-26 21:45:23 +03:00
Rene Arumetsa
94fe57a596 Add startup scheme 2026-07-26 21:36:26 +03:00
Rene Arumetsa
c40c871a4b Sync pb 2026-07-26 21:29:35 +03:00
Rene Arumetsa
5ba5642694 Added tests, fix README. 2026-07-26 20:32:13 +03:00
Rene Arumetsa
cb18d9b882 Added quests 2026-07-26 20:11:14 +03:00
Rene Arumetsa
0cdd8dac63 Update env variables 2026-06-21 22:49:46 +03:00
Rene Arumetsa
6101a278e7 Admin check now a dict 2026-06-21 22:40:57 +03:00
Rene Arumetsa
1e9ec56761 Update tipidice emoij to be animated 2026-06-03 18:50:06 +03:00
Rene Arumetsa
a96488fe9e Added eco server emoij ID 2026-06-03 18:45:46 +03:00
Rene Arumetsa
25cf60d2e1 Fix conflict 2026-06-03 18:38:40 +03:00
Rene Arumetsa
3939c879c9 Refacor emoijs to use application emoijs 2026-06-03 18:34:29 +03:00
Rene Arumetsa
42f7bae681 Edit discord role rights 2026-06-01 22:19:12 +03:00
Rene Arumetsa
b0e23c1a17 Change admin command permissions 2026-06-01 22:11:44 +03:00
Rene Arumetsa
24de79c503 Edit discord interaction, seems to cause a trouble 2026-05-25 17:51:33 +03:00
Rene Arumetsa
ee4e639c30 Remove custom_id from shop, which causes bug of tiers not working 2026-05-25 17:44:43 +03:00
Rene Arumetsa
48cc8398ec Rename logger to include bot profiles 2026-05-20 17:48:44 +03:00
Rene Arumetsa
b83b347d6a Fix shop interation 2026-05-19 18:37:42 +03:00
Rene Arumetsa
8d7ac504ca Change exp leveling system 2026-05-13 22:43:34 +03:00
Rene Arumetsa
15e3121d55 Fix birthday bug 2026-05-11 22:28:21 +03:00
Rene Arumetsa
b0a3dcb03b Document cleanup 2026-05-04 20:50:30 +03:00
Rene Arumetsa
0e617d87a2 Merge branch 'master' of ssh://git.lapikud.ee:202/renkar/tipibot 2026-05-04 20:18:31 +03:00
Rene Arumetsa
2c2621d24e Make exp gains less grindy 2026-05-04 17:48:55 +03:00
Rene Arumetsa
192888625e Refactor db error catch to one helper 2026-05-04 17:31:16 +03:00
Rene Arumetsa
6d344a47f4 Fix 403 auth error 2026-05-04 17:14:21 +03:00
Rene Arumetsa
07e7f5e0b2 More bug fixes 2026-05-03 15:11:32 +03:00
Rene Arumetsa
d65173fbe9 Some bug updates 2026-05-03 14:45:42 +03:00
Rene Arumetsa
58684d5f34 Add patch notes to bot 2026-05-03 12:02:19 +03:00
Rene Arumetsa
8529706809 Remove docker support 2026-05-03 09:21:39 +03:00
Rene Arumetsa
173e2564f1 Add missing import 2026-05-01 10:52:48 +03:00
Rene Arumetsa
93f4d471dc Add db error in functions 2026-04-29 00:04:24 +03:00
Rene Arumetsa
de7cfce833 Lower pb token timeout 2026-04-29 00:00:18 +03:00