Claude/plan v3 deployment vp mpw#137
Conversation
…urity, 23 Block 1 fixes Menu lifecycle overhaul: - replyMenu() TTL auto-vanish via ttlMs parameter - clearStaleMenuIds() on startup (24h threshold) - mainMenuSentAt / adminMenuSentAt timestamps on user schema - sendHelpMenu() fixed: bare ctx.reply() → replyMenu() (panel stacking bug) - replaceCallbackPanel() fallback now tracks message ID in user state - Admin mode toggle double-fire fixed Feature upgrades: - User giveaway list: sendUserGiveawaysPage() 5/page + 2-min auto-vanish - Admin giveaway panel: activeGiveawaysKeyboard(page) 5/page pagination - pmenu_referral sub-menu with share deep-link button - Admin stats: active window indicator + Refresh button - Admin health panel: inline memory/errors/users/persist-age/uptime - Broadcast builder: Preview button sends to admin DM before mass send Block 1 security & logic fixes: - getStartAppLink(): encodeURIComponent + regex whitelist - referralShareHTML(): escapeHtml() on code param - unwrapTelegramUrl(): safe fallback, scheme whitelist, www.t.me support - getDiscordLink(): null when not configured (no hardcoded fallback) - evaluatePendingActionTimeout(): >= boundary, NaN guard, no createdAt mutation - getPlayLink(): legacy user.playMode fallback restored - Weighted winner pool: splice-after-pick guarantees termination - deploy_status + logs: exec() → execFile() (no shell spawn) - SSHV: rejects null bytes, backticks, $( and ${ before exec - Startup env warnings: ADMIN_IDS, TELEGRAM_CHANNEL_ID, TELEGRAM_GROUP_ID Centralized helpers: computeParticipantWeight(), getRealGiveaways(), isNewUserPromoEligible() Metrics: added runewager_menu_stale_recoveries, pending_actions_timed_out, uptime_seconds load_tooltips.sh: full rewrite — atomic write, --push/--pull flags, parameterized REPO_DIR, HTML-safe tooltips, --dry-run mode, permission checks, guarded git ops Tests: readdirSync wrapped in try/catch; isCatchAllRegexPattern expanded; extractCommandHandlerNames supports let/var/no-semicolon Infrastructure: pre-deploy-checks gate 3b (menu symbols), CHANGELOG.md created, package.json bumped to 3.0.0 All 60 tests pass. node --check clean. https://claude.ai/code/session_01VijmtzjN63WZJy5gYgJAKs
… during PR merges Restores 12 categories of codex changes that were incorrectly overwritten by "current" (main) when resolving merge conflicts across 6 merge commits. Security / TLS hardening (index.js): - Restore resolveTlsCertPathIfAllowed(): multi-directory fallback for TLS certs (PROJECT_DIR, certs/, /etc/ssl, /etc/letsencrypt) — was collapsed to PROJECT_DIR only - Restore isHealthTlsEnabled() to use resolveTlsCertPathIfAllowed() - Restore requestHealthPayload(): centralized HTTP/HTTPS health fetcher with dynamic protocol detection — was inlined with hardcoded https in two places - Update /health command to use requestHealthPayload() (shows protocol label) - Update pamenu_tools_health to use requestHealthPayload() - Update startHealthServer() TLS cert read to use resolveTlsCertPathIfAllowed() Command injection protection (index.js): - commandNeedsConfirmation(): restore pipe-to-bash/zsh detection, destructive-cmd-piped pattern, redirect pattern — main simplified to only catch "sh" - commandBlocked(): restore explicit pipe-to-shell blocker pattern Race condition fixes (index.js): - deleteEphemeralBonusPrompt(): restore runUserMutation guards for safe read-delete-write of ephemeralBonusMsgId/ChatId - sendEphemeralBonusPrompt(): restore guards (claimedPromo check, active promo lookup), per-user dynamic promo lookup via getActivePromoCodeForUser() (was hardcoded promoStore.code), "I Have Claimed" callback button, mutation-safe writes - Add promo_confirm_claimed_next callback handler (button was added, handler missing) Deploy/runtime hardening (deploy.sh, prod-run.sh, runewager.service): - deploy.sh: restore data/backups/ mkdir, chown -R APP_NAME, chmod 0750/0640/0600 permission hardening after npm install - prod-run.sh: restore chmod 0750 for data/data/backups/logs dirs, chmod 0640 for log+session files, chown -R to service user after dir creation - runewager.service: add UMask=0077 (prevents world-readable files from service) .gitignore: - Restore legacy root-level data file patterns: users.json, giveaways.json, promo.json, env.json, analytics*.json (pre-data/ directory structure) All 60 tests pass. node --check clean. https://claude.ai/code/session_01VijmtzjN63WZJy5gYgJAKs
- TDZ fix: move pendingActionsTimedOut/menuStaleRecoveries declarations
before evaluatePendingActionTimeout to eliminate temporal dead-zone risk
- Timeout boundary: revert < to <= so age exactly equal to 15m is NOT
expired — aligns with /testall check and unit test expectations
- /logs line count: clamp to [1, 200] (adds Math.max(1,...) lower bound
to reject negative/zero values from user input)
- Health panel: fix _errorRate.windowErrors → _errorRate.count (field
did not exist; .count is the correct field on _errorRate object)
- /logs fallback: add execFile('tail') fallback when journalctl errors
with no output (non-systemd systems); uses BOT_LOG_FILE env or default
- executeSshvCommand: fix comment — said "spawn" but code uses exec();
updated to accurately describe exec with shell:true (admin-only)
- load_tooltips.sh: remove || true that defeated diff --cached check,
causing .gitignore changes to never be committed on --push
All 60 tests pass. node --check clean.
https://claude.ai/code/session_01VijmtzjN63WZJy5gYgJAKs
## Helpful Tooltips (was Content Drops) - Rename all UI strings: Content Drops → Helpful Tooltips throughout - New settings panel: interval, silent mode, Link Channel/Group - Target group linking via forwarded message (saves name + ID) - Dashboard footer shows real group name + ID - "Show all Helpful Tooltips (N)" button with dynamic count - Inline button builder: [Label - URL] && [Label2 - URL2] syntax - Multiple buttons per row with &&, new line = new row - [Open Bot] shorthand for standard Open Bot button - Full URL + label validation before save - postTipToConfiguredTarget uses silentMode flag + parsed buttons - tipsStore extended with targetGroupTitle and silentMode fields ## Giveaway v3.0+ - Extracted buildGiveawayAnnouncementText + buildGiveawayAnnouncementKeyboard helpers - scheduleGiveawayRefresh: auto-refresh at 25%, 50%, 75% of duration + re-pin - scheduleGiveawayReminders overhauled: 10m, 5m, 1min, 30sec, 10→1 countdown - HTML results format: @handle, SC WON, (2x boost applied), DM tip - Full admin winner report per winner: TG handle, display name, RW username, prize, boost - "View Results in Group" deep-link button in admin report - Winner DMs include SC amount, boost status, RW username - DM failure tracking with summary count - giveawayPreflightCheck: validates group linked, warns on missing pin permission - gwizStart calls preflight before wizard begins ## Scripts - generate_tooltips.sh: extracts DEFAULT_TIPS_LIST from index.js → data/tooltips.json (atomic, idempotent) - add_tooltip.sh: appends placeholder tooltip entry, outputs new ID - deploy.sh: step 3b auto-runs generate_tooltips.sh before service start - prod-run.sh: step 6b auto-runs generate_tooltips.sh before bot launch ## /testall - Added Helpful Tooltips System checks (tipsStore shape, count, interval, target, parser) - Added Giveaway Extended checks (helpers defined, preflight defined) ## Docs - RUNEWAGER_FUNCTIONALITY_MAP.md: full v3.0+ sync with flowcharts All 60 tests pass. node --check clean. https://claude.ai/code/session_01VijmtzjN63WZJy5gYgJAKs
… linking - Group command guard middleware: bot.use() intercepts all commands in group/supergroup chats and redirects to DM with a deep-link button. Passthrough commands with own group logic: link, linkrunewager, giveaway, start_giveaway, admin. Suppresses handler execution for all others. - Onboarding progress bar: onboardingProgressBar(step) renders ●●○○○ Step N of 5 — Label. showOnboardingPrompt() prepends a Markdown progress header (auto-deletes after 8s) before each step-specific prompt. - Onboarding completion card: shown once (user.onboarding.completionCardShown flag) when user reaches the main menu after completing all 5 steps. Includes feature summary and Open Menu button. - Admin System Tools: added 🔗 Group Linking button to adminSystemToolsKeyboard() with admin_sys_group_linking action handler (renders group linking panel with back-to-system-tools navigation). - Schema: completionCardShown added to onboarding default + migration guard. - Map: RUNEWAGER_FUNCTIONALITY_MAP.md fully updated; todolist.md updated. - All 60 tests pass, node --check clean. https://claude.ai/code/session_01VijmtzjN63WZJy5gYgJAKs
…ates PR #112 review fixes (sourcery-ai): - R1: tips_cmd_import_batch now uses await_tip_import_batch pending type with dedicated JSON-array router handler; proper MarkdownV2 prompt - R2: generate_tooltips.sh fixes command substitution pollution; use RUNEWAGER_APP env var instead of process.argv[1] (undefined in node -) - R3: add_tooltip.sh fixes shell injection; TOOLTIP_TEXT passed via TOOLTIP_TEXT_ENV env var, heredoc uses <<'EOF', process.argv[2] for file - R4: extend catchAllCases array with (.|\n)*, (.|\n)+, (\.|[\s\S])*; add post-whitespace-strip forms to CATCH_ALL_CORES set - R5: extractCommandHandlerNames test now covers let/var declarations and no-semicolon forms (CMD_FOUR/eta, CMD_FIVE/theta) - R6: RUNEWAGER_FUNCTIONALITY_MAP.md typo "auto-deletes 8s" → "after 8s" Codebase audit duplicate removal: - A1: remove dead buildGiveawayAnnouncementText(giveaway, remainingStr) at ~12533; keep dynamic version at ~13795 - A2: remove simplified buildGiveawayAnnouncementKeyboard at ~13817 (wrong tgw_participants_ callback); restore full 5-row version - A3+A4: remove first duplicate bot.action registrations for admin_cat_system and admin_cat_support (identical bodies) All 60 tests pass, node --check clean, bash -n clean on both scripts. https://claude.ai/code/session_01VijmtzjN63WZJy5gYgJAKs
Resolved conflicts in favour of our branch (HEAD) for: - index.js: keep await_tip_import_batch router + handler, keep A1/A2 duplicate-function removal, keep Content Drops branding from main - add_tooltip.sh / generate_tooltips.sh: keep env-var injection fixes - test/smoke.test.js: keep extended catchAllCases + extractCommand fixtures - RUNEWAGER_FUNCTIONALITY_MAP.md / todolist.md: keep our updated content Incoming from origin/main: claude-pr-results-20260228_193756Z.md https://claude.ai/code/session_01VijmtzjN63WZJy5gYgJAKs
…ry bot start Every script that starts/restarts the bot now follows the same safe sequence: 1. git pull origin main (fetch + reset --hard) 2. generate_tooltips.sh (extracts DEFAULT_TIPS_LIST → data/tooltips.json) 3. kill any process blocking PORT (default 3000) 4. start/restart bot Changes per file: - prod-run.sh: add step 9c — free_port_if_conflicted() BEFORE step 10 restart (port-kill was already present in God-Mode Heal but fired after, not before) - deploy.sh: add step 3c — inline lsof/fuser port-kill before systemctl start - start.sh: add git fetch+reset, generate_tooltips, port-kill, stale-PID kill before bot launch; replace refuse-on-duplicate with kill-and-continue - dev-run.sh: add git fetch+reset (best-effort), generate_tooltips, port-kill before exec node - scripts/rollback.sh: add generate_tooltips after npm ci (refreshes from rolled-back index.js), add lsof/fuser port-kill before service start (no git pull — rollback intentionally targets an older commit) https://claude.ai/code/session_01VijmtzjN63WZJy5gYgJAKs
- Escape Markdown special chars in runewagerUsername to prevent parse failures - Add explicit smoke-test assertions for (.|)* and (.|)+ catch-all forms - Strip inline comments from .env PORT values in deploy.sh, dev-run.sh, start.sh (e.g. PORT=3000 # dev now correctly yields 3000) - Fix showOnboardingPrompt JSDoc: steps documented as 1–4 → 1–5 (matches impl) - Upgrade all port-block kill loops to SIGTERM-first then SIGKILL after 2s grace - Add path + shape validation to generate_tooltips.sh Node extraction block (validates RUNEWAGER_APP is absolute .js path; checks array literal size/shape) https://claude.ai/code/session_01VijmtzjN63WZJy5gYgJAKs
- Create docs/INDEX.md: exhaustive cross-reference of all 95 commands, 266 action handlers, and 50+ pending action types mapped to feature docs - Create docs/features/ with 15 per-feature .md files covering every bot subsystem (onboarding, menus, giveaway, bonus, promos, tooltips, referral, SSHV, deploy, user lookup, group linking, bug reports, announcements, misc) - Create docs/TODO_FUNCTIONALITY_UPGRADE.md with 14 open stale-menu and missing-handler items (walkthrough dead-end, clearOldMenus gaps, missing tip_view handler, language stub, broadcastFailedUsers cap) - Update RUNEWAGER_FUNCTIONALITY_MAP.md section 26 with full docs/ table and mandate for future Claude sessions to consult docs/INDEX.md first Future sessions: read docs/INDEX.md → feature .md → index.js (if needed) https://claude.ai/code/session_01VijmtzjN63WZJy5gYgJAKs
… path validation - index.js: keep MarkdownV2 escaping for runewagerUsername (security fix) - generate_tooltips.sh: keep path validation (absolute .js, no traversal) - start.sh / dev-run.sh / scripts/rollback.sh: keep SIGTERM→SIGKILL two-step - start.sh: keep inline comment stripping in PORT parse - test/smoke.test.js: keep (.|)* and (.|)+ catch-all cases https://claude.ai/code/session_01VijmtzjN63WZJy5gYgJAKs
PR review comment fixes: - add_tooltip.sh: validate list is Array, filter non-finite IDs before computing maxId; throw fast on malformed tooltips.json - docs/12-group-linking.md: fix entry points table — admin System Tools uses admin_sys_group_linking, not admin_cat_system - docs/15-misc-commands.md: remove⚠️ walkthrough dead-end note (resolved) T-01 — Walkthrough system hardened: - sendWalkthroughStep(): clearOldMenus() before every step send - Back button disabled on step 1 (first step) - Next replaced with Finish button on last step (step 35) - walk_done on last step: sets started=false, fires walkthrough_completed analytics, answerCbQuery with success toast, returns to main menu - New doc: docs/features/16-walkthrough.md T-02 — clearOldMenus() added to 5 missing locations: - sendOnboardingReferralPrompt() - renderSshvConsole() - renderGroupLinkingTools() - tips_cmd_edit handler - tips_cmd_remove handler (sendGiveawayListPage already used replyMenu() — no change needed) T-03 — Tooltip view flow implemented: - tipsDashboardKeyboard(): "👁 View Tooltip" button added (row 4) - tips_cmd_view handler: clearOldMenus + tipSelectKeyboard('tip_view') - tip_view_{id} handler: preview card with Prev/Next tip navigation, Edit / Toggle / Delete buttons, Back to List, Admin Menu T-15 — Broadcast failure logging made reliable: - Removed 500-item cap from broadcastFailedUsers push and load - Every failure logged via adminLog('broadcast_failure', ...) to data/admin-events.log — no silent drops - /broadcast_failed: chunked output (30/chunk, up to 90 inline); overflow note points to log file - High-failure-rate warning: >20% failure rate sends⚠️ DM to ADMIN_IDS Merge conflicts resolved (PRs #112-114): - index.js: keep MarkdownV2 escaping for runewagerUsername - generate_tooltips.sh: keep path validation (absolute .js, no traversal) - start.sh/dev-run.sh/rollback.sh: keep SIGTERM→SIGKILL two-step - test/smoke.test.js: keep (.|)* and (.|)+ catch-all test cases Tests: 60/60 pass | node --check: clean | bash -n: all scripts OK https://claude.ai/code/session_01VijmtzjN63WZJy5gYgJAKs
Three changes addressing remaining PR #115 review feedback: 1. generate_tooltips.sh — skip guard to preserve runtime tips - Skip regeneration if data/tooltips.json already has entries. - Prevents admin-added tooltips (broadcast every 4h via bot) from being overwritten on every restart or deploy. - Add --force flag to override the guard when intentional reset is needed. - --dry-run still works regardless of the guard. 2. scripts/helpers/free_port.sh — shared SIGTERM→SIGKILL helper - Extracts duplicated port-freeing logic (lsof/fuser, SIGTERM→SIGKILL) from start.sh, dev-run.sh, deploy.sh, and scripts/rollback.sh into a single reusable helper (sourceable or callable directly). - Reduces drift: future tweaks to kill strategy happen in one place. 3. start.sh / dev-run.sh — RUNEWAGER_AUTO_UPDATE gate - git fetch + reset --hard origin/main is now conditional on RUNEWAGER_AUTO_UPDATE env var (default 1 in prod start.sh, default 0 in dev-run.sh). - Prevents silent discard of local/staging uncommitted changes. - Documented in .env.example. https://claude.ai/code/session_01VijmtzjN63WZJy5gYgJAKs
1. generate_tooltips.sh — normalize APP_DIR to absolute path Move helper function definitions (info/warn/error) before variable assignments so error() is available at init time. Normalize RUNEWAGER_DIR → APP_DIR via cd+pwd immediately after assignment so the Node.js absolute-path validation (requires '/'-prefixed path) never fails when a caller passes a relative RUNEWAGER_DIR. 2. scripts/helpers/free_port.sh — re-query port before SIGKILL Extract discovery into _query_port_pids() helper. After the SIGTERM grace period, re-query the port for survivors and only SIGKILL PIDs that are still listening — guards against killing an unrelated process that reused a PID during the 2 s sleep window. 3. dev-run.sh — read RUNEWAGER_AUTO_UPDATE from .env as fallback Parse RUNEWAGER_AUTO_UPDATE from .env before the auto-update guard so the flag works even when .env values have not been exported into the calling shell. Use explicit if/else instead of chained && || for the destructive git reset --hard command. 4. start.sh — same .env-read fix + explicit if/else for git reset Same pattern as dev-run.sh: resolve RUNEWAGER_AUTO_UPDATE from env then .env (default 1 for prod), replace the chained git &&/|| with an explicit if/else block. https://claude.ai/code/session_01VijmtzjN63WZJy5gYgJAKs
1. generate_tooltips.sh — case-based arg parser Replace the for-loop [[]] checks with a case statement that rejects unknown flags (e.g. --froce typo) with a clear error and non-zero exit. 2. generate_tooltips.sh — env-var file paths in Node.js invocations The three inline node -e calls that interpolated $TOOLTIPS_FILE / $TMP_FILE directly into single-quoted JS strings were fragile for paths containing quotes or special characters. All three now pass the path via a dedicated env var (TOOLTIPS_FILE_PATH or VALIDATE_FILE) and read process.env inside the script, matching the existing RUNEWAGER_APP pattern. 3. dev-run.sh — non-fatal free_port.sh invocation free_port.sh can exit non-zero on benign errors (no lsof/fuser, race after SIGTERM) which would abort dev-run.sh under set -eu. Added || echo WARN fallback to mirror the same non-fatal pattern used for the tooltip script invocation directly above. https://claude.ai/code/session_01VijmtzjN63WZJy5gYgJAKs
1. generate_tooltips.sh — trap for TMP_FILE cleanup Register 'trap rm -f TMP_FILE EXIT INT TERM' immediately before the atomic write section so the temp file is always removed on any exit (error, signal, or normal completion). After a successful mv the path no longer exists, so the trap is a safe no-op on the happy path. 2. dev-run.sh — default to merge --ff-only; gate reset --hard behind opt-in Auto-update now runs 'git fetch + merge --ff-only' (non-destructive). 'git reset --hard origin/main' is only executed when RUNEWAGER_FORCE_RESET=1 is set in the environment or .env, satisfying the "confirm destructive operations" guideline. Fast-forward failure emits a clear warning pointing the user to RUNEWAGER_FORCE_RESET. Documented in .env.example. https://claude.ai/code/session_01VijmtzjN63WZJy5gYgJAKs
- Merged main branch: telegramSafe.js, rateLimiter.js, backend.js, runewager-endpoint.service, prod-run.sh rewrite, runewager_redeploy.sh, rw_cpu_guard.sh - Removed dead code: legacy adminKeyboard() function (JSDoc + body, ~32 lines) — no callers, belonged to removed /admin_menu command - RUNEWAGER_FUNCTIONALITY_MAP.md: updated last-audited date, added new module entries (telegramSafe, rateLimiter, backend, service, scripts), added 2026-03-04 audit log entry - todolist.md: updated last-updated date, added fixed adminKeyboard entry - All 60 tests pass post-fix https://claude.ai/code/session_01VijmtzjN63WZJy5gYgJAKs
…mode Three code-review fixes: 1. Section 10 (Safe restart): `|| true` swallowed systemctl failures and left the bot stopped. Replaced with `if ! systemctl restart ...; then` block that falls back to manual kill + nohup when systemd fails. 2. Bare `disown` (non-systemd path, L506): with `set -euo pipefail` a failed `disown` (no job control in non-interactive shells) aborted the script before post-start health checks and Telegram reporting ran. Fixed: `disown || true` in both the fallback and non-systemd paths. 3. Telegram notification: removed `parse_mode=Markdown` (unescaped log content and env values can break Markdown rendering / cause truncation). Switched to plain text with `--data-urlencode` so special chars in the message are safe without manual escaping. Removed unused `_REPORT` variable (log tail was computed but never injected into the message). 60/60 tests pass. https://claude.ai/code/session_01VijmtzjN63WZJy5gYgJAKs
Two related fixes to the group command guard middleware: 1. Skip commands addressed to another bot (@mention): `/warn@otherbot` was previously stripped to `warn` before the check, causing Runewager to reply "This command works in DM" for every other bot's command. Now the @mention is parsed and if it refers to a different bot the message is silently ignored. 2. Add BOT_KNOWN_COMMANDS set: unaddressed commands (e.g. bare `/warn`) in groups are also silently ignored if Runewager has no handler for them. Only commands owned by this bot trigger the DM-redirect reply. 60/60 tests pass. https://claude.ai/code/session_01VijmtzjN63WZJy5gYgJAKs
…remove Added rule to both CLAUDE.md and RUNEWAGER_FUNCTIONALITY_MAP.md §25: Any bot.command() addition or removal in index.js must update the BOT_KNOWN_COMMANDS set in the same change set. The set gates the group command guard — omitting it silently breaks the new command in groups or keeps intercepting a removed one. https://claude.ai/code/session_01VijmtzjN63WZJy5gYgJAKs
|
CodeAnt AI is reviewing your PR. Thanks for using CodeAnt! 🎉We're free for open-source projects. if you're enjoying it, help us grow by sharing. Share on X · |
Reviewer's GuideAdds a centralized BOT_KNOWN_COMMANDS allowlist and tighter group-command parsing/ownership checks, hardens the deploy script’s restart and Telegram notification behavior, removes a dead admin keyboard helper, and updates the audit/docs/todo metadata to reflect the latest v3.1 runtime and tooling layout. Sequence diagram for updated group command guard and BOT_KNOWN_COMMANDS handlingsequenceDiagram
actor User
participant TelegramServer
participant Bot
participant GroupCommandGuardMiddleware
participant CommandHandler
User->>TelegramServer: Send message in group (e.g. /link@runewager_bot arg1)
TelegramServer->>Bot: Deliver update
Bot->>GroupCommandGuardMiddleware: ctx (message.text starts with /)
GroupCommandGuardMiddleware->>GroupCommandGuardMiddleware: Extract cmdToken, rawCmd, mentionedBot
GroupCommandGuardMiddleware->>GroupCommandGuardMiddleware: ourUsername = ctx.botInfo.username
alt Command targets a different bot
GroupCommandGuardMiddleware-->>Bot: return next()
Bot->>CommandHandler: Other middleware or handlers continue
else Command not owned by this bot
GroupCommandGuardMiddleware->>GroupCommandGuardMiddleware: Check BOT_KNOWN_COMMANDS.has(rawCmd)
GroupCommandGuardMiddleware-->>Bot: return next() (ignore unknown command)
else Command is owned by this bot
GroupCommandGuardMiddleware->>GroupCommandGuardMiddleware: Check GROUP_PASSTHROUGH_COMMANDS.has(rawCmd)
alt Group passthrough command
GroupCommandGuardMiddleware-->>Bot: next() (handle in group)
Bot->>CommandHandler: Execute group-aware handler
else Non passthrough command in group
GroupCommandGuardMiddleware-->>Bot: Redirect to DM
Bot->>TelegramServer: Send DM redirect message to user
end
end
Flow diagram for hardened prod-run restart and Telegram notificationflowchart TD
A[Start prod-run.sh deploy] --> B{Existing PID found?}
B -->|Yes| C[Record PID]
B -->|No| D[PID empty]
C --> E{systemctl available and service file exists?}
D --> E
E -->|Yes| F[Attempt systemctl restart runewager.service]
E -->|No| K[Kill existing PID if any]
F -->|Success| G[systemd managed restart]
F -->|Failure| H[Warn and fallback to manual restart]
H --> I[Kill existing PID if any]
I --> J[Sleep 1s and start node index.js via nohup]
J --> L[disown or ignore error]
G --> M[Sleep 3s and refresh PID]
L --> M
K --> N[Start node index.js via nohup]
N --> O[disown or ignore error]
O --> M
M --> P[Run health checks on HEALTH_PORT]
P --> Q[Compute HEALTH_STATUS and SYSTEMD_ACTIVE]
Q --> R{ADMIN_IDS and TELEGRAM_BOT_TOKEN set?}
R -->|No| S[Skip Telegram notification]
R -->|Yes| T[Build plain text message _MSG with health, port, PID, systemd]
T --> U[Loop over each admin id]
U --> V[Send Telegram sendMessage via curl
--data-urlencode chat_id and text
no parse_mode]
V --> W[Ignore curl errors]
S --> X[Deploy script complete]
W --> X
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- The new BOT_KNOWN_COMMANDS list is a single large manual source of truth; consider adding a small runtime guard (e.g., in your bot.command() helper) that asserts each registered command exists in the set so drift is caught immediately rather than relying only on process discipline.
- The command parsing logic in the group guard middleware (extracting rawCmd and mentionedBot) is now non-trivial; if other parts of the code need to interpret commands, consider extracting this into a shared helper to avoid future divergence in how commands and @mentions are parsed.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The new BOT_KNOWN_COMMANDS list is a single large manual source of truth; consider adding a small runtime guard (e.g., in your bot.command() helper) that asserts each registered command exists in the set so drift is caught immediately rather than relying only on process discipline.
- The command parsing logic in the group guard middleware (extracting rawCmd and mentionedBot) is now non-trivial; if other parts of the code need to interpret commands, consider extracting this into a shared helper to avoid future divergence in how commands and @mentions are parsed.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Nitpicks 🔍
|
| # 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)" |
There was a problem hiding this comment.
Suggestion: The deploy notification now reads only TELEGRAM_BOT_TOKEN from .env, but the project treats BOT_TOKEN as the canonical name and TELEGRAM_BOT_TOKEN as a legacy alias, so in environments where only BOT_TOKEN is set (the default), Telegram deploy notifications will silently never send. [logic error]
Severity Level: Major ⚠️
- ⚠️ Prod-run Telegram deploy summaries never send with only BOT_TOKEN.
- ⚠️ Admins lose automated deploy/health visibility; must check logs manually.| _BOT_TOKEN="$(read_env_value TELEGRAM_BOT_TOKEN || true)" | |
| _BOT_TOKEN="$(read_env_value BOT_TOKEN || true)" | |
| [[ -z "$_BOT_TOKEN" ]] && _BOT_TOKEN="$(read_env_value TELEGRAM_BOT_TOKEN || true)" |
Steps of Reproduction ✅
1. Configure `.env` in the project root (`/workspace/Runewager/.env`) using `.env.example`
as a template (`.env.example:12` shows `BOT_TOKEN=`, `:37` shows `TELEGRAM_BOT_TOKEN=`)
and set a valid `BOT_TOKEN` plus a comma‑separated `ADMIN_IDS` (as documented by
`README.md:15` and `:26`), but leave `TELEGRAM_BOT_TOKEN` unset or empty.
2. Run the deployment runner `prod-run.sh` (the main production deploy script whose
post‑deploy health + Telegram reporting logic starts around the `# 11) POST-START HEALTH
CHECK + TELEGRAM REPORT` section in `prod-run.sh`), so it reaches the end of the script
after starting/restarting the bot.
3. At the Telegram notification block in `prod-run.sh` lines `558–563`, `_ADMIN_IDS` is
populated from `.env` via `read_env_value ADMIN_IDS` (line `558`), but `_BOT_TOKEN` is set
only from `read_env_value TELEGRAM_BOT_TOKEN` (line `559`), which returns an empty string
because only `BOT_TOKEN` is defined in `.env`.
4. Because `_BOT_TOKEN` is empty, the guard `if [[ -n "$_BOT_TOKEN" && -n "$_ADMIN_IDS"
]]; then` (line `560`) evaluates to false, the `curl` loop to
`https://api.telegram.org/bot${_BOT_TOKEN}/sendMessage` (lines `564–567`) is never
executed, and no Telegram deploy/health notification is sent to any `ADMIN_IDS`, despite
the project treating `BOT_TOKEN` as canonical (see `index.js:14` and documentation notes
in `CLAUDE_FIX_PR.md:2474–2483`).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 notification now reads only `TELEGRAM_BOT_TOKEN` from `.env`, but the project treats `BOT_TOKEN` as the canonical name and `TELEGRAM_BOT_TOKEN` as a legacy alias, so in environments where only `BOT_TOKEN` is set (the default), Telegram deploy notifications will silently never send.
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.|
CodeAnt AI finished reviewing your PR. |
User description
Summary by Sourcery
Tighten Telegram group command handling and deployment notifications while cleaning up dead code and updating project docs and task tracking.
New Features:
Bug Fixes:
Enhancements:
Build:
Documentation:
Tests:
Chores:
CodeAnt-AI Description
Prevent runewager from responding to other bots in group chats; add restart fallback and plain-text deploy notifications
What Changed
Impact
✅ Fewer mistaken bot replies in shared groups✅ More reliable restarts when systemd restart fails✅ Clearer deploy notifications for admins💡 Usage Guide
Checking Your Pull Request
Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.
Talking to CodeAnt AI
Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:
This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.
Example
Preserve Org Learnings with CodeAnt
You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:
This helps CodeAnt AI learn and adapt to your team's coding style and standards.
Example
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
Check Your Repository Health
To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.