mirror of
https://github.com/tiennm99/store-scraper-bot.git
synced 2026-10-11 03:13:50 +00:00
Refactors source to be Worker-shaped. No live deploy yet — sister deploy plan
runs Atlas provisioning + smoke later.
- wrangler.toml with nodejs_compat_v2, daily UTC 0 cron (= 7am Asia/Ho_Chi_Minh)
- package.json: drop node-telegram-bot-api, node-cron, dotenv, pino,
pino-pretty; add wrangler devDep; bump to 0.2.0
- src/bot/telegram-api.js: raw fetch wrapper for Telegram Bot API
- src/bot/dispatch.js: per-message dispatcher extracted from polling loop
- src/repository/mongodb.js: memoized MongoClient per warm isolate, typed
MongoUnavailable error, fast-fail timeouts
- src/repository/store.js: factory binding env once
- All 4 repositories converted to factory shape
- src/api/{apple,google}-scraper.js: take store instead of importing repos
- src/index.js: Worker entry exporting { fetch, scheduled }; webhook validates
X-Telegram-Bot-Api-Secret-Token; ack-then-waitUntil pattern
- src/scheduler/scheduler.js: trimmed; runDailyCheck only (no node-cron)
- src/config.js, src/logger.js: env-driven, console.log JSON output
- scripts/register-webhook.js: setWebhook + setMyCommands; --dry-run supported
- scripts/check-secret-leaks.js: lint blocks console.log(env.<SECRET>)
- plans/260426-2015-cloudflare-worker-code-port: this code port plan
- plans/260426-2327-cloudflare-deploy-and-smoke: sister deploy plan
Validated via node --check on all 32 source files; lint clean. Real deploy
gates (bundle size, cold-start CPU) run in deploy plan.
4.5 KiB
4.5 KiB
Phase 05 — Webhook Register Script (Write Only)
Context Links
- Telegram
setWebhook: https://core.telegram.org/bots/api#setwebhook - miti99bot register pattern:
/config/workspace/tiennm99/miti99bot/scripts/register.js
Overview
- Priority: P1
- Status: pending
- Description: Write
scripts/register-webhook.js. Do not run it — that's the deploy plan's job. This phase only ensures the script exists and--dry-runworks locally.
Key Insights
- The dry-run path doesn't call Telegram, so it's safe to invoke during code-only work.
--env-file=.env.deployrequires Node ≥20.6; project already requires Node ≥20.
Requirements
Functional
scripts/register-webhook.jswritten. ReadsTELEGRAM_BOT_TOKEN,TELEGRAM_WEBHOOK_SECRET,WORKER_URLfrom env.--dry-runprintssetWebhook+setMyCommandspayloads without HTTP calls.- 13-command list embedded with descriptions.
Non-functional
- Script logs Telegram response; never prints token.
- Exit 1 on missing env or non-
okresponse.
Related Code Files
CREATE
scripts/register-webhook.js
MODIFY
- (none —
package.jsonalready hasregister+register:dryscripts from Phase 01)
Implementation Steps
-
Write
scripts/register-webhook.js:#!/usr/bin/env node const TOKEN = process.env.TELEGRAM_BOT_TOKEN; const SECRET = process.env.TELEGRAM_WEBHOOK_SECRET; const URL_ = process.env.WORKER_URL; const DRY = process.argv.includes('--dry-run'); for (const [k, v] of Object.entries({ TELEGRAM_BOT_TOKEN: TOKEN, TELEGRAM_WEBHOOK_SECRET: SECRET, WORKER_URL: URL_, })) { if (!v) { console.error(`${k} is required`); process.exit(1); } } const COMMANDS = [ { command: 'info', description: 'Show this group ID' }, { command: 'addgroup', description: '[admin] Authorize a group' }, { command: 'delgroup', description: '[admin] Deauthorize a group' }, { command: 'listgroup', description: '[admin] List authorized groups' }, { command: 'addapple', description: 'Track an Apple App Store app' }, { command: 'delapple', description: 'Stop tracking an Apple app' }, { command: 'addgoogle', description: 'Track a Google Play app' }, { command: 'delgoogle', description: 'Stop tracking a Google app' }, { command: 'listapp', description: 'List tracked apps in this group' }, { command: 'checkapp', description: 'Check update status of tracked apps' }, { command: 'checkappscore', description: 'Check scores + ratings of tracked apps' }, { command: 'rawappleapp', description: 'Dump raw Apple API JSON for an app' }, { command: 'rawgoogleapp', description: 'Dump raw Google API JSON for an app' }, ]; async function tg(method, payload) { if (DRY) { console.log(`[dry-run] ${method}`, JSON.stringify(payload, null, 2)); return { ok: true, result: '(dry)' }; } const res = await fetch(`https://api.telegram.org/bot${TOKEN}/${method}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }); const body = await res.json(); if (!body.ok) { console.error(`${method} failed`, body); process.exit(1); } return body; } await tg('setWebhook', { url: URL_, secret_token: SECRET, allowed_updates: ['message'] }); await tg('setMyCommands', { commands: COMMANDS }); const info = await tg('getWebhookInfo', {}); console.log('Webhook state:', JSON.stringify(info.result, null, 2)); -
Local dry-run smoke (using fake env):
TELEGRAM_BOT_TOKEN=fake TELEGRAM_WEBHOOK_SECRET=fake WORKER_URL=https://example.test \ node scripts/register-webhook.js --dry-runExpect both payloads printed, exit 0.
Todo List
scripts/register-webhook.jswritten- Local dry-run smoke passes
node --check scripts/register-webhook.jspasses
Success Criteria
- Script runs in dry-run mode without env file (env injected on the command line).
getWebhookInfois the third call, aftersetWebhookandsetMyCommands.
Risk Assessment
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Top-level await rejected by older Node | L | Low | Engines >=20; top-level await fine |
Command list drifts from src/bot/bot.js map |
M | Medium | Both list 13 commands; cross-reference at smoke |
Next Steps
- Blocks: Deploy plan Phase 03 (uses this script).
- Unblocks: end of code plan.