39 Commits

Author SHA1 Message Date
myron 43ef4c9699 fix: remove parkerslingshot from repoMap — replaced by parkerslingshotrentals.com 2026-06-23 18:05:40 +00:00
myron 222ad7513c fix: populate repoMap with all 6 website repos; remove dead __NOVACPX_VM__ branch; dedupe date() call 2026-06-23 16:29:35 +00:00
myron 9435f5d189 sync: add deploy webhook 2026-06-21 03:46:46 +00:00
myron 3e642b97a7 Add mouse drag, wheel, and arrow buttons to token package pill scroller
- Click-drag: grab cursor, drag left/right to scroll
- Mouse wheel: vertical scroll converts to horizontal pan
- Arrow buttons (< >) appear at edges when more pills are off-screen,
  hide when scrolled to the end

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 11:30:45 +00:00
myron 3610187699 Fix token package pill scroller not swiping
- pay-form: overflow:hidden -> overflow:visible so it no longer blocks
  horizontal touch events on the pkg-scroll child
- pay-form-header: gets its own top border-radius to maintain visual
  corner clipping without relying on parent overflow:hidden
- pkg-scroll: added touch-action:pan-x so browser hands horizontal
  swipe gestures to this element rather than the page scroll

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 11:28:39 +00:00
myron cc49a381c6 Fix platform card clicks; revert onboarding to request-only flow
- Platform cards: replaced inline onclick with data attributes + event
  listeners to avoid JSON double-quote quoting bug that broke clicks
- Onboarding: reverted to original yes/no -> request accounts flow,
  removed alias-entry step that didn't work

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 11:23:30 +00:00
myron 5c19a6cf42 Keep request step after alias entry in onboarding
After saving aliases, flow continues to account request step so players
can also request logins for platforms they don't have yet.
'Done' button on alias step still allows early exit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 11:20:09 +00:00
myron 02dbda7c74 Clean up alias UX: remove duplicate Play Now, add alias step to onboarding
- Removed Play Now (▶) button from profile aliases tab — Play Now section
  on home page is the one place to launch platforms
- Onboarding: "Yes I have existing logins" now leads to a new alias-entry
  step where the player enters their username per active platform; saved
  on submit, dismisses onboarding
- "No, I want new logins" still goes to the account-request step
- Back arrow on each step returns to the opening question
- obHideAll/obGoBack helpers keep step transitions clean

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 11:19:42 +00:00
myron 483026fd07 Pass saved alias to platform on launch; copy to clipboard
- platforms table gets url_alias_param column (configurable per platform)
- Admin game form has new "Username URL Param" field — leave blank if platform
  doesn't support it, or set to e.g. "username" if it does
- Platform cards now use onclick openPlatform() instead of plain href:
  copies player's saved alias to clipboard on every click, and if
  url_alias_param is set appends ?param=alias to the launch URL
- Toast notification confirms "Alias copied — paste into login"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 11:13:45 +00:00
myron 44a98eba15 Shade disabled payout methods when admin turns them off
- payout_methods list now includes admin_enabled flag via JOIN on admin_payout_settings
- Disabled methods appear at 45% opacity with UNAVAILABLE/DISABLED BY ADMIN badge
  in both the cashout radio list and profile payout tab; radio is disabled so they
  can't be selected, but the delete button remains
- Set Default button hidden on disabled methods
- cashout.php server-side guard rejects submissions using a disabled method type

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 11:04:18 +00:00
myron 428bc86eb7 Filter player payout types by admin-enabled methods
cashout_method_types list now JOINs admin_payout_settings so the
player's profile payout dropdown only shows types the admin can
actually process.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 10:58:12 +00:00
myron be70abf11f Fix platforms/payment methods not rendering due to Cloudflare Rocket Loader
Rocket Loader defers our main script, causing DOMContentLoaded to fire
before our listener is registered — so buildPlatforms(), buildPaymentMethods()
etc. never run. Adding Cache-Control: no-transform tells Cloudflare not to
rewrite the response, disabling Rocket Loader for this page.

Also adds buildPaymentMethods() to showApp() alongside buildPlatforms() so
payment methods are guaranteed to render when the user logs in, regardless
of fetch timing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 10:38:10 +00:00
myron 8c1332c0c6 Fix platform grid not showing for logged-in regular users
Two issues:
1. Race condition: me.php resolves before the platforms fetch, so
   showApp() runs with an empty CFG.platforms and the grid stays
   blank until the Promise.all resolves. Fixed by calling
   buildPlatforms() inside showApp() when platforms are already
   loaded, guaranteeing the grid renders when the app becomes visible.
2. Stale placeholder: 'links' platform (is_active=1) was polluting
   the grid with a "Platform Links coming..." card. Disabled in DB
   (is_active=0).

Also hardened buildPlatforms/buildCashoutPlatforms: null-guard on
selects, early return when CFG.platforms is empty, and clear select
options before re-populating to prevent duplicates on re-call.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 10:29:27 +00:00
myron 8238db3026 Add URL-based referral share verification with auto-scraper
Players now paste the URL of their post instead of just clicking a
platform button. The server fetches the URL and looks for the player's
referral code in the page content. If found, the share is auto-approved
and tokens are awarded immediately. If not (login wall, private page,
code missing), it falls into the pending queue with a reason so admins
can click the link directly for manual review.

- api/referrals.php: replace submit_share with URL-accepting version;
  add scrapeForReferralCode() (SSRF-guarded cURL, 8s timeout, 512KB cap)
  and inferPlatformFromUrl() helpers
- db/schema.sql: add share_url, auto_verified, verify_result columns
- index.php: replace platform buttons with URL input form; show auto-
  verify result inline; shares list shows URL and auto-verify badge
- admin/index.php: share cards show clickable URL, auto-check result
  label, and auto-verified tag

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 10:16:45 +00:00
myron f96c1b33c0 Fix referral list race condition causing entries to flash and disappear
Two concurrent loadAdminReferrals() calls shared the same DOM container,
so whichever fetch resolved last would overwrite the other's result.
Added a request ID counter (_refListReqId) so stale responses are
discarded rather than applied.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 10:05:24 +00:00
myron 8d27290831 Fix 6 code review findings: auth, mysqldump stderr, dead code, audit logs
- backup.php: replace manual admin check with requireAdmin(); suppress
  mysqldump password warning (2>&1 → 2>/dev/null) to prevent corrupt dumps
- ttg-backup.sh: same mysqldump stderr fix
- admin.php toggle_user: fix undefined $adminId/$userId in logAdminAction
  call — use $_SESSION['user_id'] and $uid instead
- admin.php chat_clear_all: wrap in try/catch and add logAdminAction audit
- admin.php: delete unreachable broadcast query block after break statement
- admin/index.php: fix cashouts_total formatted as currency — use parseInt
  (tokens are whole numbers, not dollars)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 10:02:07 +00:00
myron 9470b021b6 Fix bogus $sent check on 20 non-email actions in admin.php
Every case that wasn't actually sending email had copy-pasted the
email-send result check, causing all those actions (delete_pending,
payment_settings_update, etc.) to always return 'Failed to send reset
email' even on success.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 09:04:16 +00:00
myron f5a72c55f5 Add automated backup system
- api/backup.php: list/create/download/delete backups; streams zip directly
  for downloads; 7-backup rolling prune on each create
- Each backup is a single zip containing all of public_html + a full
  mysqldump of tomt_ttg_db
- Cron at 2 AM daily via /usr/local/bin/ttg-backup.sh (already installed)
- Admin UI: 💾 Backups nav item under System section; shows backup list
  with date/size, Download + Delete per row; Create Backup Now button
  with live status; auto-loads when section is opened

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 22:14:32 +00:00
myron c9cf26edca Show dollar/token totals on platform cards instead of counts
Purchases shows sum of amount_cents as dollars, cashouts shows sum
of tokens with coin icon.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 22:08:31 +00:00
myron 253cd0a743 Fix platform_stats returning Forbidden — $isAdmin undefined in admin.php
requireAdmin() already guards the whole file; the extra check was
referencing an undefined variable that always evaluated false.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 22:06:48 +00:00
myron d8202427ae Add platform credit overview to dashboard
New section below pending purchases/cashouts: one square card per
active platform showing net credit balance, completed purchase count,
and sent cashout count. Loads on page load alongside other dashboard
data. Credits turn yellow below 100 and red at/below 0 with a warning.
Clicking a card jumps to Game Management and opens that platform's
credit modal.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 22:03:38 +00:00
myron f54cdb11db Auto-debit platform credits when purchase is approved
When a pending purchase is resolved as completed:
- Inserts a debit row into platform_credits for the matching platform
  (joins token_purchases.platform_id slug → platforms.id)
- Debit notes include purchase #, player name, username, token count, amount, method
- Total shown in credit modal now subtracts debits from credits (net balance)

Credit history table updates:
- CREDIT/DEBIT type badges, debit rows tinted red with − prefix
- Debit rows show "Purchase #X ↗" button that closes modal, jumps to
  the Purchases section (all tab), and highlights that purchase row
- Edit/delete buttons hidden on auto-generated debit rows

Also fixes: resolve_purchase was echoing $sent (undefined variable bug)
Also fixes: purchaseCard div now has id="pr-N" so jump-highlight works

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 21:38:03 +00:00
myron 1367fa334b Fix credit accounting popup sending to wrong API endpoint
saveCreditEntry and deleteCreditEntry were using apiFetch() which routes
to /api/admin.php, but credits_create/update/delete only exist in
/api/platforms.php — causing the Unknown action error on every save.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 21:27:53 +00:00
myron b6adb7a3f0 Blur credentials for non-master admins in game management
- Game list cards: login/password fields blurred with user-select/pointer-events
  disabled for non-master admins; URLs and guide remain readable
- View-only edit panel: credential fields blurred, copy button hidden for creds;
  URL fields retain open + copy buttons

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 18:58:12 +00:00
myron 90b497dae5 Increase admin font sizes by 1px for readability
- CSS vars: xs 11→12, sm 13→14, base 15→16, md 16→17, lg 18→19, xl 20→21, 2xl 24→25
- Body font-size: 16→17px
- Input/control CSS classes: 16→17px

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 18:56:12 +00:00
myron 56ea742495 Fix add new game: reset form on section load, add prominent Add New Game button
- resetGameForm() now called every time Game Management section is opened,
  preventing stuck edit state (disabled slug, wrong form title)
- Added prominent Add New Game button at top of section (master admin only)
- DOMContentLoaded init ensures form state is correct on page load

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 18:49:57 +00:00
myron 0c96b0ad7c Game Management: soft-delete, slug reuse, new game form fix, master-admin gating
- DB: added is_deleted, deleted_at columns to platforms table
- Soft delete: archive button moves games to archived section instead of hard delete
- Archived section: master admin can restore (reactivates) or permanently delete
- Slug reuse: creating a game with an archived slug reactivates the old record
- New game form: master admin always sees add form + agent info; other admins hidden
- Edit: non-master admins have form card revealed on edit
- Delete/Add buttons: only visible to master admin
- api/platforms.php: public and admin_list queries exclude archived games
- api/admin.php: platforms_archived, platforms_restore, platforms_purge actions added

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 18:45:31 +00:00
myron 185c27f6b4 Fix game management save/retrieve; add last-edited to game cards
Root cause: saves went through admin.php which still used old console_url column
and had broken response using undefined $sent variable (always returned error).

- api/admin.php: platforms_create/update/delete fully rewritten with all agent
  fields, master-admin gating, and correct json_encode responses
- api/admin.php: update now sets updated_at=NOW() on save
- admin/index.php: game cards show last-edited date (✏️ from updated_at)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 18:15:55 +00:00
myron 7eade583f7 Restrict Agent Info and Credit Accounting to master admin only; protect master admin account
- Agent Info: master admin sees full edit form; other admins see view-only panel with Copy and Open URL buttons
- Credit Accounting: master admin can manage entries; other admins see total only (Manage Credits button hidden)
- API: credits_create/update/delete require master admin; platform update strips agent fields for non-master
- Players: suspend/delete buttons disabled when viewing master admin account (UI + JS guards)
- URL fields (Agent Link, Games Link): open-in-new-tab arrow button added in both edit and view modes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 18:06:17 +00:00
myron f50d1d481d Add Credit Accounting section to game management
- New table: platform_credits (id, platform_id, credits_purchased, credit_date, payment_method, notes)
- API: credits_list, credits_create, credits_update, credits_delete actions (admin-only)
- Admin form: Credit Accounting box showing Available Credits total; Manage Credits button opens modal
- Modal: Total Credits header, add/edit/delete entries with credits, date, payment method, notes
- Game list cards: show live credit total per game (cyan, loads async)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 18:00:15 +00:00
myron 99079340cb Add sub-account and cashier credential fields to game management
- DB: added sub_agent_login, sub_agent_password, cashier_login, cashier_password to platforms table
- API: create/update handle all 4 new fields
- Admin: Sub-Account and Cashier sections added inside Agent Info box; game list cards display all new fields

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 17:51:37 +00:00
myron 0aec13daf4 Add agent fields to game management
- DB: renamed console_url to agent_link, added agent_login, agent_password, games_link, agent_guide to platforms table
- api/platforms.php: create/update now handles all 5 agent fields (admin-only)
- admin/index.php: game form has new Agent Info section (purple, admin-only styling); game list cards show all agent fields inline; JS saveGame/editGame/resetGameForm updated

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 17:39:48 +00:00
myron 497071e1b7 Fix pending_signups stat pollution and use branded reset email
- pending_signups stat and list queries now filter username != __reset__
  so active password-reset rows no longer inflate the signup counter or
  appear in the admin pending-signups list
- send_password_reset now calls sendPasswordResetEmail() from mailer.php
  instead of building a plain-text cybermailSend() call inline; the
  wrapper sends a branded dark-theme HTML email matching the verification
  email style
2026-06-03 06:01:49 +00:00
myron 5b364db2a5 Surface cybermailSend failure to admin on password reset
Previously the endpoint always returned success:true regardless of
whether the email was actually delivered. Now captures the bool return
value and returns success:false with an error message if CyberMail
fails, so the admin knows to retry rather than assuming delivery.
2026-06-03 03:57:22 +00:00
myron 9815db29d0 Add reset_password.php — password reset redemption page
Handles the /reset_password.php?token=... URL generated by the
admin send_password_reset action. Flow:
- GET: validates token against pending_registrations (username=__reset__,
  not expired), shows set-new-password form
- POST: re-validates token, enforces 6-char min + confirm match,
  bcrypt-hashes the new password, updates users.password by email,
  deletes the pending row to prevent reuse
- Invalid/expired token shows a clear error with link back to home

Matches the dark gaming aesthetic of verify.php.
2026-06-03 03:56:17 +00:00
myron 18ec3a7143 Fix broken password reset INSERT — SQL syntax error and wrong token value
The INSERT had two compounding bugs:
1. ".?" in the VALUES clause — a PHP dot inside a double-quoted string
   is a literal character, not concatenation. MySQL saw it as a syntax
   error and the INSERT always failed silently (no try/catch).
2. The token column had the literal string __reset__ hardcoded instead
   of a ? placeholder, so even if the INSERT had run, the real random
   token would never have been stored — the reset link always invalid.

Fix: VALUES ("__reset__","",?,?,?,?) with execute(alias,email,token,exp)
giving 4 placeholders for 4 params, all columns correctly bound.
2026-06-03 03:54:16 +00:00
myron ad57071f97 Add DB schema (22 tables) and vhost config 2026-05-25 13:52:18 +00:00
myron 894392065c Security: remove test/debug/install files from production 2026-05-22 13:05:18 +00:00
myron 2e587941c2 Initial commit 2026-05-22 12:52:50 +00:00