Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
c3ce323
feat(v3.0): full production upgrade — menu lifecycle, pagination, sec…
claude Feb 28, 2026
1c1d19c
Merge remote-tracking branch 'origin/main' into claude/plan-v3-deploy…
claude Feb 28, 2026
92e93e6
fix(codex-recovery): restore missing codex branch changes overwritten…
claude Feb 28, 2026
3d4befe
fix(pr110): address all reviewer comments from PR #110
claude Feb 28, 2026
41c2083
feat(vnext): Helpful Tooltips overhaul, giveaway v3.0+ upgrades
claude Feb 28, 2026
c279f5f
feat(v3.1): group command guard, onboarding progress bar, admin group…
claude Feb 28, 2026
81ff2af
fix(pr112+audit): address all 6 PR review comments and 4 audit duplic…
claude Feb 28, 2026
86a6e1d
merge: sync with origin/main; keep PR #112 fixes over regressed versions
claude Feb 28, 2026
b6e211c
feat(scripts): auto git-pull + tooltip-refresh + port-free before eve…
claude Feb 28, 2026
5c27692
fix(pr113): resolve all PR #113 review comments
claude Feb 28, 2026
efe20d6
docs: add per-feature documentation system and central index
claude Mar 1, 2026
6ab6734
merge: sync with origin/main (PRs #112-114); keep SIGTERM→SIGKILL and…
claude Mar 1, 2026
49efa74
fix(pr115): resolve 3 review comments + implement T-01/T-02/T-03/T-15
claude Mar 1, 2026
ee1184c
fix(pr115): tooltip skip guard, shared port helper, gated auto-update
claude Mar 1, 2026
ad306be
fix(pr115): address 4 reviewer hardening findings
claude Mar 1, 2026
c865189
fix(pr115): 3 nitpick hardening fixes
claude Mar 1, 2026
f0f53aa
fix(pr115): temp-file trap + non-destructive git update path
claude Mar 1, 2026
9108134
Merge remote-tracking branch 'origin/main' into claude/plan-v3-deploy…
claude Mar 4, 2026
8307907
fix(audit): remove dead adminKeyboard() + merge main + docs sync
claude Mar 4, 2026
f0bcd13
fix(prod-run): fallback on systemctl failure, fix disown, drop parse_…
claude Mar 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions RUNEWAGER_FUNCTIONALITY_MAP.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# RUNEWAGER_FUNCTIONALITY_MAP.md

_Last audited: 2026-02-28 (v3.1 pass)_
_Last audited: 2026-03-04 (/runewager-audit pass — 0 critical, 0 warnings after fix)_
_Source of truth files: `index.js`, `test/*.test.js`, scripts under `scripts/`, deployment/runtime docs in repo root._

---
Expand Down Expand Up @@ -288,10 +288,14 @@ Pending-action timeout handling is enforced in the text input router: each pendi
## 22. Internal Utilities & Shared Modules

Repo modules:
- `index.js` main app.
- `index.js` main app (15,148 lines after v3.1 merge).
- `telegramSafe.js` — rate-limited Telegram API wrapper; patches `bot.telegram` on init.
- `rateLimiter.js` — global (~28 req/sec) + per-chat (1 msg/sec) queue enforcer.
- `backend.js` — companion HTTP service on port 3001: autofix webhook, admin bridge, `/health/full`.
- `promo-message.js` promo copy helper.
- `scripts/*.sh` deployment/runtime ops (backup, restore, smoke, rollback, diagnostics).
- `scripts/*.sh` deployment/runtime ops (backup, restore, smoke, rollback, diagnostics, redeploy, cpu-guard).
- `test/*.test.js` smoke/unit/runtime tests.
- `runewager-endpoint.service` — systemd unit for `backend.js` (separate from `runewager.service`).

Key shared helper families in `index.js`:
- Markdown escape helpers.
Expand Down Expand Up @@ -402,6 +406,8 @@ Mandatory rules for any AI agent touching this repo:
- 2026-02-27: Added QA tester scaffolding (`qa/context/bot_capabilities.json`, `qa/context/repo_info.json`, `qa/state/provider_status.json`, `qa/README_QA.md`), with runtime refresh via `/qa_*` commands and 10-minute provider cooldown reset.
- 2026-02-27: Hardened SSHV Run prompt flow so admin text in private DM executes against active SSHV sessions if pending state desynchronizes.
- 2026-02-28: v3.1 — added group command guard middleware (`GROUP_PASSTHROUGH_COMMANDS` + `bot.use` interceptor); added `onboardingProgressBar()` and progress header on each onboarding step prompt (auto-deletes after 8s); added one-time onboarding completion card (tracked via `user.onboarding.completionCardShown`); added `🔗 Group Linking` to Admin System Tools keyboard (`admin_sys_group_linking` callback with back-to-system-tools navigation).
- 2026-03-04: Merged main branch additions — `telegramSafe.js` (global rate-limit patch via `telegramSafe.init(bot)`), `rateLimiter.js` (per-chat + global Telegram API rate limiter), `backend.js` (companion HTTP service on port 3001, `runewager-endpoint.service` systemd unit), updated `prod-run.sh`, `scripts/runewager_redeploy.sh`, `scripts/rw_cpu_guard.sh`.
- 2026-03-04: /runewager-audit — 17-phase full audit. Findings: 0 critical, 1 warning resolved (dead `adminKeyboard()` function removed — legacy promo keyboard with no callers). Auto-fix applied. 60/60 tests pass post-fix.
- 2026-03-01: Created `docs/` feature documentation system — 15 per-feature `.md` files, central `docs/INDEX.md` with full callback + pending-action cross-reference, and `docs/TODO_FUNCTIONALITY_UPGRADE.md` tracking 14 open upgrade/stale-menu items. Future Claude sessions must consult `docs/INDEX.md` first, then the relevant feature `.md`, before reading `index.js`.
- 2026-03-01: Phase implementation — resolved T-01/T-02/T-03/T-15 from TODO list. (1) Walkthrough: `sendWalkthroughStep()` upgraded with `clearOldMenus()`, Back disabled on step 1, Finish on last step, `walk_done` on last step returns to main menu. New doc: `16-walkthrough.md`. (2) Menu stacking: `clearOldMenus()` added to `sendOnboardingReferralPrompt`, `renderSshvConsole`, `renderGroupLinkingTools`, `tips_cmd_edit`, `tips_cmd_remove`. (3) Tooltip view: `tips_cmd_view` selector + `tip_view_{id}` handler with Prev/Next/Edit/Toggle/Delete/Back/AdminMenu — "👁 View Tooltip" button added to dashboard. (4) Broadcast failures: 500-item cap removed; all failures logged via `adminLog()`; `/broadcast_failed` shows chunks of 30 with overflow note; >20% failure rate triggers admin DM warnings. PR comments fixed: `add_tooltip.sh` array validation hardened; `docs/12-group-linking.md` entry-point callback corrected to `admin_sys_group_linking`; merge conflicts (PRs #112-114) resolved keeping SIGTERM→SIGKILL safety improvements. 60/60 tests pass.
- 2026-02-28: PR #112 review + audit pass — fixed 10 issues: (R1) `await_tip_import_batch` dedicated pending type with JSON-array router; (R2) `generate_tooltips.sh` command-substitution pollution fixed via `RUNEWAGER_APP` env var; (R3) `add_tooltip.sh` shell-injection fixed via `TOOLTIP_TEXT_ENV`/`TOOLTIP_TMP_FILE` env vars and `<<'EOF'`; (R4) `catchAllCases` test extended with multiline patterns + `CATCH_ALL_CORES` updated; (R5) `extractCommandHandlerNames` test extended with `let`/`var`/no-semicolon fixtures; (R6) typo "auto-deletes 8s" → "auto-deletes after 8s"; (A1) dead `buildGiveawayAnnouncementText(giveaway,remainingStr)` removed; (A2) simplified `buildGiveawayAnnouncementKeyboard` with wrong callback removed; (A3+A4) duplicate `bot.action('admin_cat_system')` and `bot.action('admin_cat_support')` first registrations removed. All 60 tests pass.
Expand Down
32 changes: 0 additions & 32 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2944,38 +2944,6 @@ function linkPrefKeyboard() {
]);
}

/**

* adminKeyboard executes its scoped Runewager logic and participates in menu/command or utility flow composition.

* Parameters: See the function signature for exact argument names and accepted values.

* Returns: Returns the computed value or a Promise resolving to the operation result; may return void for side-effect handlers.

* Side effects: May mutate runtime stores, pendingAction state, menu state, persistence files, logs, and callback progression.

* Validation/safety: Uses existing guard utilities (admin checks, input checks, path checks, cooldown checks) where applicable.

* Timeouts/fallbacks: Timeout and fallback behavior are controlled by the calling flow and global handler/state machine conventions.

* Errors: Surfaces user-facing error replies and/or logs when inputs, permissions, or dependencies are invalid.

* System fit: This function is part of the Runewager command/callback/state orchestration pipeline.

*/

function adminKeyboard() {
return Markup.inlineKeyboard([
[Markup.button.callback('📄 View Promo', 'admin_view')],
[Markup.button.callback('✏️ Edit Promo Code', 'admin_edit_code')],
[Markup.button.callback('💰 Edit SC Amount', 'admin_edit_amount')],
[Markup.button.callback('🔢 Edit Claim Limit', 'admin_edit_limit')],
[Markup.button.callback('⏸ Pause Promo', 'admin_pause')],
[Markup.button.callback('▶️ Unpause Promo', 'admin_unpause')],
[Markup.button.callback('🗑 Remove Promo', 'admin_remove')],
[Markup.button.callback('📢 Push Update to Users', 'admin_broadcast')],
]);
}

/**

Expand Down
24 changes: 16 additions & 8 deletions prod-run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -499,11 +499,18 @@ if [[ -n "$PID" ]]; then
say "Safe restart of running bot (PID: $PID)"
fi
if command -v systemctl >/dev/null 2>&1 && [[ -f "$SERVICE_FILE" ]]; then
systemctl restart "${APP_NAME}.service" 2>/dev/null || true
if ! systemctl restart "${APP_NAME}.service" 2>/dev/null; then
warn "systemctl restart failed — falling back to manual kill+nohup"
[[ -n "$PID" ]] && kill "$PID" 2>/dev/null || true
sleep 1
nohup node "$PROJECT_DIR/index.js" >> "$MAIN_LOG" 2>> "$ERROR_LOG" < /dev/null &
disown || true
say "Bot started via nohup fallback"
fi
else
[[ -n "$PID" ]] && kill "$PID" 2>/dev/null || true
nohup node "$PROJECT_DIR/index.js" >> "$MAIN_LOG" 2>> "$ERROR_LOG" < /dev/null &
disown
disown || true
fi
# Always refresh PID after restart so step 11 knows the live process
sleep 3
Expand Down Expand Up @@ -546,17 +553,18 @@ fi

is_port_listening "$HEALTH_PORT" && PORT_STATUS="listening"

# Telegram admin notification
# Telegram admin notification (plain text — no parse_mode to avoid Markdown rendering issues
# with unescaped log content or special chars in env values)
_ADMIN_IDS="$(read_env_value ADMIN_IDS || true)"
_BOT_TOKEN="$(read_env_value TELEGRAM_BOT_TOKEN || true)"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: The deploy-complete Telegram notification only reads the legacy TELEGRAM_BOT_TOKEN from .env and ignores the canonical BOT_TOKEN (and any exported BOT_TOKEN env var), so on setups that follow the documented convention of using BOT_TOKEN only, the health summary message will never be sent even though the bot runs correctly. [logic error]

Severity Level: Major ⚠️
- ⚠️ prod-run.sh post-deploy Telegram summary skipped with BOT_TOKEN-only.
- ⚠️ Ops lose automatic health summary after each deployment.
Suggested change
_BOT_TOKEN="$(read_env_value TELEGRAM_BOT_TOKEN || true)"
# Prefer canonical BOT_TOKEN (env or .env), fall back to legacy TELEGRAM_BOT_TOKEN alias
_BOT_TOKEN="${BOT_TOKEN:-$(read_env_value BOT_TOKEN || read_env_value TELEGRAM_BOT_TOKEN || true)}"
Steps of Reproduction ✅
1. Configure the bot using the documented canonical token: in `/workspace/Runewager/.env`,
set `BOT_TOKEN=...` and `ADMIN_IDS=...` while leaving `TELEGRAM_BOT_TOKEN` unset or empty
(README recommends `BOT_TOKEN` at `README.md:15` and `.env.example` declares `BOT_TOKEN`
as the canonical name at `CLAUDE_FIX_PR.md:2474`).

2. Start the bot normally (e.g., via systemd using the unit generated by `prod-run.sh`)
and confirm it runs: `index.js:14` defines `const BOT_TOKEN = process.env.BOT_TOKEN ||
process.env.TELEGRAM_BOT_TOKEN;`, so with only `BOT_TOKEN` set the application starts
successfully and serves the health endpoint.

3. Run the deployment runner `prod-run.sh` from `/workspace/Runewager` as intended for
production deployments; it performs the restart and post-start health check (section 10
and 11, `prod-run.sh:496-553`), and the health check succeeds so the script reaches the
Telegram notification block at `prod-run.sh:556-569`.

4. In that notification block, `_ADMIN_IDS` is populated from `.env`, but `_BOT_TOKEN` is
set only via `read_env_value TELEGRAM_BOT_TOKEN` (`prod-run.sh:558-559`), which returns
empty when `TELEGRAM_BOT_TOKEN` is not configured; the condition `[[ -n "$_BOT_TOKEN" &&
-n "$_ADMIN_IDS" ]]` at `prod-run.sh:560` fails, so the `curl` loop at
`prod-run.sh:563-567` never executes and no "Deploy complete" Telegram messages are sent,
despite the bot and health checks working correctly with `BOT_TOKEN`.
Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** prod-run.sh
**Line:** 559:559
**Comment:**
	*Logic Error: The deploy-complete Telegram notification only reads the legacy `TELEGRAM_BOT_TOKEN` from `.env` and ignores the canonical `BOT_TOKEN` (and any exported `BOT_TOKEN` env var), so on setups that follow the documented convention of using `BOT_TOKEN` only, the health summary message will never be sent even though the bot runs correctly.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
👍 | 👎

if [[ -n "$_BOT_TOKEN" && -n "$_ADMIN_IDS" ]]; then
_REPORT="$(( tail -n 30 "$MAIN_LOG"; tail -n 20 "$ERROR_LOG" ) 2>/dev/null \
| sed 's/"/\\"/g' | head -c 3500)"
_HEALTH_LABEL="$( [[ "$HEALTH_STATUS" == healthy ]] && echo OK || echo FAILED )"
_MSG="Deploy complete: Health ${_HEALTH_LABEL} | Port: ${HEALTH_PORT} | PID: ${PID:-none} | Systemd: ${SYSTEMD_ACTIVE}"
for _AID in ${_ADMIN_IDS//,/ }; do
curl -s -X POST "https://api.telegram.org/bot${_BOT_TOKEN}/sendMessage" \
-d chat_id="$_AID" \
-d parse_mode="Markdown" \
-d text="Deploy complete: Health $( [[ "$HEALTH_STATUS" == healthy ]] && echo OK || echo FAILED) Port: $HEALTH_PORT PID: ${PID:-none}" >/dev/null 2>&1 || true
--data-urlencode "chat_id=${_AID}" \
--data-urlencode "text=${_MSG}" \
>/dev/null 2>&1 || true
done
fi

Expand Down
5 changes: 4 additions & 1 deletion todolist.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Runewager Bot — Improvement Task Board

_Last updated: 2026-02-28PR #112 review fixes + codebase audit pass_
_Last updated: 2026-03-04/runewager-audit pass + merge main (backend.js, rateLimiter.js, telegramSafe.js, prod-run.sh, scripts)_

---

Expand All @@ -11,6 +11,9 @@ _Last updated: 2026-02-28 — PR #112 review fixes + codebase audit pass_

## BUGS (confirmed code defects)

- [x] **Dead code: `adminKeyboard()` function** `index.js`
- Fixed: 2026-03-04. Legacy promo keyboard function with no callers (belonged to removed `/admin_menu` command). Deleted entire block (JSDoc + function body). All 60 tests pass.

- [x] **`gw.endsAt` / `endTime` field inconsistency** `index.js`
- Fixed: all three occurrences replaced with `gw.endTime`; extend action now calls `resetGiveawayTimer(gw)` to re-arm the timer.
- Also fixed `gw.winnersCount` → `gw.maxWinners` in the admin panel display.
Expand Down