Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
194 changes: 98 additions & 96 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4171,6 +4171,26 @@ function escapeMarkdownFull(text) {
return String(text).replace(/[_*[\]()~`>#+\-=|{}.!\\]/g, '\\$&');
}

/**

* ensureDataDir 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.

*/

/**

* ensureDataDir executes its scoped Runewager logic and participates in menu/command or utility flow composition.
Expand Down Expand Up @@ -7745,6 +7765,63 @@ bot.action('admin_cat_support', async (ctx) => {
});


/**


* adminTestsToolsKeyboard 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 adminTestsToolsKeyboard() {
return Markup.inlineKeyboard([
[Markup.button.callback('🧪 Run TestAll', 'admin_cmd_testall'), Markup.button.callback('🎁 Test Giveaway', 'admin_cmd_testgiveaway')],
[Markup.button.callback('🐛 View Bug Reports', 'admin_cmd_viewbugs'), Markup.button.callback('📤 Export Bugs', 'admin_cmd_exportbugs')],
[Markup.button.callback('✅ Resolve Bug', 'admin_cmd_resolvebug_prompt'), Markup.button.callback('🧪 Test Content Drop', 'admin_cmd_tiptest')],
[Markup.button.callback('📟 Open SSHV Console', 'sshv_open')],
[Markup.button.callback('⬅️ Admin Dashboard', 'open_admin_dashboard')],
]);
}

bot.action('admin_cat_tests', async (ctx) => {
if (!requireAdmin(ctx)) return;
await ctx.answerCbQuery();
await replaceCallbackPanel(ctx,
`🧪 *Tests & Bug Tools*

Use this menu for diagnostics, bug workflows, and test sends.

• TestAll = full sanity check
• Test Giveaway = simulated giveaway flow
• Test Content Drop = sends one random drop to current target
• SSHV = VPS console tools`,
{ parse_mode: 'Markdown', ...adminTestsToolsKeyboard() },
);
});


/**


Expand Down Expand Up @@ -8288,6 +8365,26 @@ bot.action('menu_giveaways', async (ctx) => {
await sendGiveawayListPage(ctx, 1);
});

/**

* sendGiveawayListPage 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.

*/

/**

* sendGiveawayListPage executes its scoped Runewager logic and participates in menu/command or utility flow composition.
Expand Down Expand Up @@ -9957,8 +10054,7 @@ bot.action('announce_send_all', async (ctx) => {
await ctx.reply('Legacy "Send All" mapped to the new broadcast flow. Tap "Send Broadcast Now" after reviewing toggles.');
});

// Legacy aliases
bot.action('announce_send_all', async (ctx) => {
bot.action('announce_send_channel', async (ctx) => {
if (!requireAdmin(ctx)) return;
const user = getUser(ctx);
const action = user.pendingAction;
Expand All @@ -9975,100 +10071,6 @@ bot.action('announce_send_all', async (ctx) => {
// Content Drops System — scheduler + admin commands + callbacks
// =========================

async function resolveTipTargetChatId(rawTarget) {
const t = String(rawTarget || '').trim();
if (!t) return null;
if (/^-?\d+$/.test(t)) return Number(t);
if (t.startsWith('@')) return t;
return `@${t}`;
}

async function postTipToConfiguredTarget(tip, telegram) {
const primaryTarget = await resolveTipTargetChatId(tipsStore.targetGroup || broadcastConfigStore.targetGroup);
const fallbackTarget = approvedGroupsStore.size ? Array.from(approvedGroupsStore)[0] : null;
const candidates = [primaryTarget, fallbackTarget].filter(Boolean);
let lastErr = null;
for (const target of candidates) {
try {
// eslint-disable-next-line no-await-in-loop
await telegram.sendMessage(target, formatTipForHtml(tip.text), { parse_mode: 'HTML', disable_notification: true });
tipsStore.targetGroup = String(target);
broadcastConfigStore.targetGroup = String(target);
return { ok: true, target };
} catch (e) {
lastErr = e;
}
}
return { ok: false, error: lastErr };
}

/**

* resolveTipTargetChatId 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.

*/

async function resolveTipTargetChatId(rawTarget) {
const t = String(rawTarget || '').trim();
if (!t) return null;
if (/^-?\d+$/.test(t)) return Number(t);
if (t.startsWith('@')) return t;
return `@${t}`;
}

/**

* postTipToConfiguredTarget 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.

*/

async function postTipToConfiguredTarget(tip, telegram) {
const primaryTarget = await resolveTipTargetChatId(tipsStore.targetGroup || broadcastConfigStore.targetGroup);
const fallbackTarget = approvedGroupsStore.size ? Array.from(approvedGroupsStore)[0] : null;
const candidates = [primaryTarget, fallbackTarget].filter(Boolean);
let lastErr = null;
for (const target of candidates) {
try {
// eslint-disable-next-line no-await-in-loop
await telegram.sendMessage(target, formatTipForHtml(tip.text), { parse_mode: 'HTML', disable_notification: true });
tipsStore.targetGroup = String(target);
broadcastConfigStore.targetGroup = String(target);
return { ok: true, target };
} catch (e) {
lastErr = e;
}
}
return { ok: false, error: lastErr };
}

/**

* resolveTipTargetChatId executes its scoped Runewager logic and participates in menu/command or utility flow composition.
Expand Down
6 changes: 3 additions & 3 deletions test/smoke.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ function parseRegexLiteral(source, slashIndex) {
if (i >= source.length) return null;
const patternSource = source.slice(slashIndex + 1, i);
let j = i + 1;
while (j < source.length && /[a-z]/i.test(source[j])) j += 1;
while (j < source.length && /[dgimsuvy]/.test(source[j])) j += 1;
const flags = source.slice(i + 1, j);
return { patternSource, flags, end: j };
}
Expand Down Expand Up @@ -286,8 +286,8 @@ function extractRegisteredCommands(source) {
const idx = source.indexOf(marker);
if (idx === -1) return null;

const setIdx = source.indexOf('new Set', idx);
const arrOpen = source.indexOf('[', setIdx);
// Allow formatting variants (new Set([...]) or plain array/object assignment) by scanning for the first array literal after the marker.
const arrOpen = source.indexOf('[', idx);
if (arrOpen === -1) return null;

let depth = 0;
Expand Down
Loading