Daily growth snapshot to the Telegram payments feed and shared topic (sign-ups, purchases, POL paid, campaigns, viewing, lifetime totals); admin preview/send-now routes and settings

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-15 12:43:19 -05:00
parent 8ca019a5b3
commit 92e7304882
3 changed files with 103 additions and 1 deletions
+13
View File
@@ -36,6 +36,7 @@ const updates = require('./updates');
const audit = require('./audit'); // counter audit: views vs delivery logs, charges vs shows (Marty, 2026-09-15) // member update emails from Admin > Releases (Marty, 2026-09-14)
const leaderboard = require('./leaderboard');
const toolkit = require('./toolkit');
const snapshot = require('./snapshot'); // daily growth snapshot -> Telegram payments feed (Marty, 2026-09-15)
const pipeline = require('./pipeline'); // sponsor follow-up board (coming soon until site setting pipelineMode = on) (Marty, 2026-09-15)
const videomaker = require('./videomaker'); // Circuit tool: promo videos with the member's own end card (ffmpeg in the image) // badge-gated promo toolkit + AI Copy Engine (Surge and up) (Marty, 2026-09-14) // referral contest: /leaderboard, Overview card, weekly + monthly winners (Marty, 2026-09-14) // release notes + roadmap: /whats-new, Overview card, Admin > Releases (Marty, 2026-09-14) // blog -> Blotato -> X + Instagram on publish (Marty, 2026-09-13) // admin member card: search, drilldown, edits (Marty, 2026-09-13) // admin-written coaching articles, server-rendered public /blog with SEO metadata (Marty, 2026-09-12)
const TRAFFIC_PAGES = new Set(['/', '/ledger', '/contract', '/shorts', '/plays', '/wallets', '/launch', '/partners', '/earning', '/blog', '/whats-new', '/leaderboard']);
@@ -371,6 +372,8 @@ async function boot() {
// follow-up email sequence: send whatever came due (every 10 min, first pass shortly after boot)
coach.init({ dataDir: DATA_DIR, chain, accounts, mailer, ads, tank, lb: () => leaderboard, siteConfig });
pipeline.init({ dataDir: DATA_DIR, accounts, coach, chain });
snapshot.init({ dataDir: DATA_DIR, db, chain, siteConfig, send: async (c, t, th) => { await telegramSend(c, t, th); return true; } });
setInterval(() => snapshot.tick().catch(e => console.error('snapshot', e.message)), 10 * 60 * 1000);
tank.init({ dataDir: DATA_DIR, chain, accounts, messages, mailer, site: 'https://instantadpay.com' });
legacy.init({ dataDir: DATA_DIR });
traffic.init({ dataDir: DATA_DIR });
@@ -423,6 +426,7 @@ function siteConfig() {
telegramAdminChatId: '', // private chat for admin alerts (sign-up guard bursts); falls back to ADMIN_EMAIL
launchAt: '', // public launch moment, ISO 8601 with offset (e.g. 2026-09-18T19:00:00-05:00): countdown on /launch + dashboard mark
aiCreditsPerGen: 10, aiFreeSurge: 20, aiFreeCircuit: 60, aiFreeNexus: 150, // AI Copy Engine: free generations per month by badge, then credits per generation
snapshotEnabled: '1', snapshotHourUtc: '14', snapshotTargets: 'feed,echo', // daily growth snapshot: 14 UTC = 9 AM Central; feed = proof channel, echo = shared payments topic
pipelineMode: 'off', // Pipeline board: off = 'coming soon' card, preview = only the admin account sees the live board, on = everyone (Marty, 2026-09-15)
pipelineEta: 'Sep 28', // what the coming-soon card and the roadmap promise
memberWeeklyEmail: '0', // 1 = the weekly 'Your week on InstantAdPay' email goes to every active member, not only sponsors with a line
@@ -2549,6 +2553,15 @@ const server = http.createServer(async (req, res) => {
if (out.length) fs.writeFileSync(file, JSON.stringify(out, null, 2)); else { try { fs.unlinkSync(file); } catch (e) {} }
return json(res, 200, { ok: true, ads: out, usingDefaults: !out.length });
}
// -- growth snapshot: preview the post, or send it now
if (p === '/api/admin/snapshot' && req.method === 'GET') {
if (!isAdmin(req)) return json(res, 401, { error: 'auth' });
return json(res, 200, { text: await snapshot.preview() });
}
if (p === '/api/admin/snapshot/send' && req.method === 'POST') {
if (!isAdmin(req)) return json(res, 401, { error: 'auth' });
const r = await snapshot.post(); return json(res, r.error ? 400 : 200, r);
}
if (p === '/api/admin/site' && req.method === 'GET') {
if (!isAdmin(req)) return json(res, 401, { error: 'auth' });
return json(res, 200, { site: siteConfig() });