mirror of
https://github.com/tiennm99/store-scraper-bot.git
synced 2026-09-05 12:17:14 +00:00
refactor: dispatcher pre-parses args, drop arg helpers + info.js
The dispatcher now extracts both the command name and its arguments once and passes the args array to handlers via a 3rd parameter. Each command file drops its splitArgs(getCommandArguments(msg.text)) call and the corresponding imports. command-utils.js loses the now-unused arg helpers (only auth helpers remain). info.js — a 12-line file with one sendMessage — folds into bot.js's commands map.
This commit is contained in:
+7
-4
@@ -1,5 +1,4 @@
|
||||
import { createTelegramApi } from './telegram-api.js';
|
||||
import { createInfoCommand } from './commands/info.js';
|
||||
import { createAddGroupCommand } from './commands/add-group.js';
|
||||
import { createDeleteGroupCommand } from './commands/delete-group.js';
|
||||
import { createListGroupCommand } from './commands/list-group.js';
|
||||
@@ -13,7 +12,6 @@ import { createCheckAppScoresCommand } from './commands/check-app-scores.js';
|
||||
import { createRawAppleAppCommand } from './commands/raw-apple-app.js';
|
||||
import { createRawGoogleAppCommand } from './commands/raw-google-app.js';
|
||||
|
||||
// HTML parse mode for all messages (Java parity).
|
||||
const PARSE_MODE = 'HTML';
|
||||
|
||||
export function createBot(config, store, appleScraper, googleScraper) {
|
||||
@@ -51,9 +49,14 @@ export function createBot(config, store, appleScraper, googleScraper) {
|
||||
},
|
||||
};
|
||||
|
||||
// Java command identifiers — keep names matching exactly.
|
||||
const commands = {
|
||||
info: createInfoCommand(),
|
||||
info: async (msg, sender, args) => {
|
||||
if (args.length !== 0) {
|
||||
await sender.sendMessage(msg.chat.id, 'Invalid arguments');
|
||||
return;
|
||||
}
|
||||
await sender.sendMessage(msg.chat.id, `Id của nhóm là <code>${msg.chat.id}</code>\n`);
|
||||
},
|
||||
addgroup: createAddGroupCommand(config, store),
|
||||
delgroup: createDeleteGroupCommand(config, store),
|
||||
listgroup: createListGroupCommand(config, store),
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { buildAppleRequestByBundleId, buildAppleRequestByTrackId } from '../../api/apple-scraper.js';
|
||||
import { authorizeGroup, getCommandArguments, splitArgs } from './command-utils.js';
|
||||
import { authorizeGroup } from './command-utils.js';
|
||||
|
||||
// /addapple <id|appId> [country=vn] — Java AddAppleAppCommand.
|
||||
// /addapple <id|appId> [country=vn]
|
||||
export function createAddAppleAppCommand(store, appleScraper) {
|
||||
return async (msg, sender) => {
|
||||
return async (msg, sender, args) => {
|
||||
if (!(await authorizeGroup(msg.chat.id, store, sender))) return;
|
||||
const args = splitArgs(getCommandArguments(msg.text));
|
||||
if (args.length < 1 || args.length > 2) {
|
||||
await sender.sendMessage(msg.chat.id, 'Invalid arguments');
|
||||
return;
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { buildGoogleRequest } from '../../api/google-scraper.js';
|
||||
import { authorizeGroup, getCommandArguments, splitArgs } from './command-utils.js';
|
||||
import { authorizeGroup } from './command-utils.js';
|
||||
|
||||
// /addgoogle <appId> [country=vn] — Java AddGoogleAppCommand.
|
||||
// /addgoogle <appId> [country=vn]
|
||||
export function createAddGoogleAppCommand(store, googleScraper) {
|
||||
return async (msg, sender) => {
|
||||
return async (msg, sender, args) => {
|
||||
if (!(await authorizeGroup(msg.chat.id, store, sender))) return;
|
||||
const args = splitArgs(getCommandArguments(msg.text));
|
||||
if (args.length < 1 || args.length > 2) {
|
||||
await sender.sendMessage(msg.chat.id, 'Invalid arguments');
|
||||
return;
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { getCommandArguments, requireAdminUser, splitArgs } from './command-utils.js';
|
||||
import { requireAdminUser } from './command-utils.js';
|
||||
|
||||
// /addgroup [groupId] — Java AddGroupCommand. Admin-only.
|
||||
// /addgroup [groupId] — admin-only. Defaults to current chat.
|
||||
export function createAddGroupCommand(config, store) {
|
||||
return async (msg, sender) => {
|
||||
return async (msg, sender, args) => {
|
||||
if (!(await requireAdminUser(msg.from.id, msg.chat.id, config, sender))) return;
|
||||
const args = splitArgs(getCommandArguments(msg.text));
|
||||
if (args.length > 1) {
|
||||
await sender.sendMessage(msg.chat.id, 'Invalid arguments');
|
||||
return;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { buildTable } from '../../util/table.js';
|
||||
import { authorizeGroup, getCommandArguments, splitArgs } from './command-utils.js';
|
||||
import { authorizeGroup } from './command-utils.js';
|
||||
|
||||
// /checkappscore — Java CheckAppScoreCommand. Reports score + ratings.
|
||||
// Score rounded to 1 decimal (Java Precision.round(score, 1) parity).
|
||||
// /checkappscore — reports score + ratings. Score rounded to 1 decimal.
|
||||
export function createCheckAppScoresCommand(store, appleScraper, googleScraper) {
|
||||
return async (msg, sender) => {
|
||||
return async (msg, sender, args) => {
|
||||
if (!(await authorizeGroup(msg.chat.id, store, sender))) return;
|
||||
if (splitArgs(getCommandArguments(msg.text)).length !== 0) {
|
||||
if (args.length !== 0) {
|
||||
await sender.sendMessage(msg.chat.id, 'Invalid arguments');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { buildTable } from '../../util/table.js';
|
||||
import { daysBetween, formatDateInTz } from '../../util/time.js';
|
||||
import { authorizeGroup, getCommandArguments, splitArgs } from './command-utils.js';
|
||||
import { authorizeGroup } from './command-utils.js';
|
||||
|
||||
// /checkapp — Java CheckAppCommand. Reports update status per app, per store.
|
||||
// /checkapp — reports update status per app, per store.
|
||||
export function createCheckAppCommand(config, store, appleScraper, googleScraper) {
|
||||
return async (msg, sender) => {
|
||||
return async (msg, sender, args) => {
|
||||
if (!(await authorizeGroup(msg.chat.id, store, sender))) return;
|
||||
if (splitArgs(getCommandArguments(msg.text)).length !== 0) {
|
||||
if (args.length !== 0) {
|
||||
await sender.sendMessage(msg.chat.id, 'Invalid arguments');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
export function splitArgs(text) {
|
||||
if (!text) return [];
|
||||
return text.trim().split(/\s+/).filter((s) => s.length > 0);
|
||||
}
|
||||
|
||||
// Strips the "/<cmd>" or "/<cmd>@botname" prefix from message.text.
|
||||
export function getCommandArguments(text) {
|
||||
if (!text) return '';
|
||||
const trimmed = text.trim();
|
||||
const space = trimmed.indexOf(' ');
|
||||
if (space < 0) return '';
|
||||
return trimmed.slice(space + 1).trim();
|
||||
}
|
||||
|
||||
export async function authorizeGroup(chatId, store, sender) {
|
||||
try {
|
||||
const ok = await store.admin.hasGroup(chatId);
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { authorizeGroup, getCommandArguments, splitArgs } from './command-utils.js';
|
||||
import { authorizeGroup } from './command-utils.js';
|
||||
|
||||
// /delapple <appId> — Java DeleteAppleAppCommand.
|
||||
// /delapple <appId>
|
||||
export function createDeleteAppleAppCommand(store) {
|
||||
return async (msg, sender) => {
|
||||
return async (msg, sender, args) => {
|
||||
if (!(await authorizeGroup(msg.chat.id, store, sender))) return;
|
||||
const args = splitArgs(getCommandArguments(msg.text));
|
||||
if (args.length !== 1) {
|
||||
await sender.sendMessage(msg.chat.id, 'Invalid arguments');
|
||||
return;
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { authorizeGroup, getCommandArguments, splitArgs } from './command-utils.js';
|
||||
import { authorizeGroup } from './command-utils.js';
|
||||
|
||||
// /delgoogle <appId> — Java DeleteGoogleAppCommand.
|
||||
// /delgoogle <appId>
|
||||
export function createDeleteGoogleAppCommand(store) {
|
||||
return async (msg, sender) => {
|
||||
return async (msg, sender, args) => {
|
||||
if (!(await authorizeGroup(msg.chat.id, store, sender))) return;
|
||||
const args = splitArgs(getCommandArguments(msg.text));
|
||||
if (args.length !== 1) {
|
||||
await sender.sendMessage(msg.chat.id, 'Invalid arguments');
|
||||
return;
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { getCommandArguments, requireAdminUser, splitArgs } from './command-utils.js';
|
||||
import { requireAdminUser } from './command-utils.js';
|
||||
|
||||
// /delgroup [groupId] — Java DeleteGroupCommand. Admin-only.
|
||||
// /delgroup [groupId] — admin-only.
|
||||
export function createDeleteGroupCommand(config, store) {
|
||||
return async (msg, sender) => {
|
||||
return async (msg, sender, args) => {
|
||||
if (!(await requireAdminUser(msg.from.id, msg.chat.id, config, sender))) return;
|
||||
const args = splitArgs(getCommandArguments(msg.text));
|
||||
if (args.length > 1) {
|
||||
await sender.sendMessage(msg.chat.id, 'Invalid arguments');
|
||||
return;
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
import { getCommandArguments, splitArgs } from './command-utils.js';
|
||||
|
||||
// /info — Java InfoCommand. Reports the chat (group) ID.
|
||||
export function createInfoCommand() {
|
||||
return async (msg, sender) => {
|
||||
if (splitArgs(getCommandArguments(msg.text)).length !== 0) {
|
||||
await sender.sendMessage(msg.chat.id, 'Invalid arguments');
|
||||
return;
|
||||
}
|
||||
await sender.sendMessage(msg.chat.id, `Id của nhóm là <code>${msg.chat.id}</code>\n`);
|
||||
};
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import { buildTable } from '../../util/table.js';
|
||||
import { authorizeGroup, getCommandArguments, splitArgs } from './command-utils.js';
|
||||
import { authorizeGroup } from './command-utils.js';
|
||||
|
||||
// /listapp — Java ListAppCommand. Two tables (Apple / Google) of tracked apps.
|
||||
// /listapp — two tables (Apple / Google) of tracked apps.
|
||||
export function createListAppCommand(store) {
|
||||
return async (msg, sender) => {
|
||||
return async (msg, sender, args) => {
|
||||
if (!(await authorizeGroup(msg.chat.id, store, sender))) return;
|
||||
if (splitArgs(getCommandArguments(msg.text)).length !== 0) {
|
||||
if (args.length !== 0) {
|
||||
await sender.sendMessage(msg.chat.id, 'Invalid arguments');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { getCommandArguments, requireAdminUser, splitArgs } from './command-utils.js';
|
||||
import { requireAdminUser } from './command-utils.js';
|
||||
|
||||
// /listgroup — Java ListGroupCommand. Admin-only.
|
||||
// /listgroup — admin-only.
|
||||
export function createListGroupCommand(config, store) {
|
||||
return async (msg, sender) => {
|
||||
return async (msg, sender, args) => {
|
||||
if (!(await requireAdminUser(msg.from.id, msg.chat.id, config, sender))) return;
|
||||
if (splitArgs(getCommandArguments(msg.text)).length !== 0) {
|
||||
if (args.length !== 0) {
|
||||
await sender.sendMessage(msg.chat.id, 'Invalid arguments');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import { buildAppleRequestByBundleId, buildAppleRequestByTrackId } from '../../api/apple-scraper.js';
|
||||
import { getCommandArguments, splitArgs } from './command-utils.js';
|
||||
|
||||
// /rawappleapp <id|appId> [country=vn] — Java RawAppleAppCommand.
|
||||
// Sends raw upstream JSON as a Telegram document attachment.
|
||||
// /rawappleapp <id|appId> [country=vn] — sends raw upstream JSON as a document.
|
||||
export function createRawAppleAppCommand(appleScraper) {
|
||||
return async (msg, sender) => {
|
||||
const args = splitArgs(getCommandArguments(msg.text));
|
||||
return async (msg, sender, args) => {
|
||||
if (args.length < 1 || args.length > 2) {
|
||||
await sender.sendMessage(msg.chat.id, 'Invalid arguments');
|
||||
return;
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { buildGoogleRequest } from '../../api/google-scraper.js';
|
||||
import { getCommandArguments, splitArgs } from './command-utils.js';
|
||||
|
||||
// /rawgoogleapp <appId> [country=vn] — Java RawGoogleAppCommand.
|
||||
// /rawgoogleapp <appId> [country=vn]
|
||||
export function createRawGoogleAppCommand(googleScraper) {
|
||||
return async (msg, sender) => {
|
||||
const args = splitArgs(getCommandArguments(msg.text));
|
||||
return async (msg, sender, args) => {
|
||||
if (args.length < 1 || args.length > 2) {
|
||||
await sender.sendMessage(msg.chat.id, 'Invalid arguments');
|
||||
return;
|
||||
|
||||
+21
-12
@@ -4,8 +4,9 @@ export async function dispatch(message, deps) {
|
||||
const { sender, commands, config, logger } = deps;
|
||||
if (!message?.text || message.text[0] !== '/') return;
|
||||
|
||||
const name = parseCommandName(message.text, config.telegramBotUsername);
|
||||
if (!name) return;
|
||||
const parsed = parseCommand(message.text, config.telegramBotUsername);
|
||||
if (!parsed) return;
|
||||
const { name, args } = parsed;
|
||||
|
||||
const handler = commands[name];
|
||||
if (!handler) {
|
||||
@@ -18,7 +19,7 @@ export async function dispatch(message, deps) {
|
||||
'Executing command',
|
||||
);
|
||||
try {
|
||||
await handler(message, sender);
|
||||
await handler(message, sender, args);
|
||||
} catch (err) {
|
||||
logger.error({ err: err.message, command: name }, 'command failed');
|
||||
try {
|
||||
@@ -29,14 +30,22 @@ export async function dispatch(message, deps) {
|
||||
}
|
||||
}
|
||||
|
||||
// Extracts "info" from "/info", "/info arg", "/info@bot", "/info@bot arg".
|
||||
function parseCommandName(text, botUsername) {
|
||||
const space = text.indexOf(' ');
|
||||
const head = space < 0 ? text.slice(1) : text.slice(1, space);
|
||||
// Extracts name + args from "/cmd", "/cmd arg", "/cmd@bot", "/cmd@bot arg".
|
||||
// Returns null if the @bot suffix targets a different bot.
|
||||
function parseCommand(text, botUsername) {
|
||||
const trimmed = text.trim();
|
||||
const space = trimmed.indexOf(' ');
|
||||
const head = space < 0 ? trimmed.slice(1) : trimmed.slice(1, space);
|
||||
const argText = space < 0 ? '' : trimmed.slice(space + 1).trim();
|
||||
|
||||
const at = head.indexOf('@');
|
||||
if (at < 0) return head;
|
||||
const cmd = head.slice(0, at);
|
||||
const target = head.slice(at + 1);
|
||||
if (botUsername && target && target.toLowerCase() !== botUsername.toLowerCase()) return null;
|
||||
return cmd;
|
||||
let name = head;
|
||||
if (at >= 0) {
|
||||
name = head.slice(0, at);
|
||||
const target = head.slice(at + 1);
|
||||
if (botUsername && target && target.toLowerCase() !== botUsername.toLowerCase()) return null;
|
||||
}
|
||||
|
||||
const args = argText ? argText.split(/\s+/) : [];
|
||||
return { name, args };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user