Telegram: echo payouts into a shared cross-program topic

telegramOnEvent now builds the line once per target: the existing proof feed
(telegramChatId) and a new echo target (telegramEchoChatId + telegramEchoTopicId,
telegramEchoEvents). AwardPaid events are now posted too. Echo lines carry an
InstantAdPay prefix since RM Circle shares the topic. Admin labels added.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-11 18:51:03 -05:00
parent 024027a2da
commit 1fd61eca56
2 changed files with 14 additions and 6 deletions
+13 -5
View File
@@ -339,6 +339,7 @@ function siteConfig() {
rehearsal: true, // shows the testnet banner; flipped off at mainnet launch
// payment-proof Telegram feed (blank = off) and the P&L pane's fixed monthly cost
telegramBotToken: '', telegramChatId: '', telegramTopicId: '', telegramEvents: 'payouts', telegramCtaUrl: 'https://instantadpay.com/',
telegramEchoChatId: '', telegramEchoTopicId: '', telegramEchoEvents: 'payouts', // shared cross-program payments topic
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
geoTier1: '', // comma-separated ISO country codes; empty = built-in default (US, CA, GB, AU, NZ, IE, DE, FR, NL, SE, NO, DK, FI, CH, AT, BE)
@@ -526,22 +527,29 @@ async function emailOnEvent(ev) {
// payment-proof Telegram feed (same pattern as the RM Circle proof channel): one compact
// line per event, admin-configured under Settings > Site (telegramBotToken, telegramChatId,
// optional telegramTopicId, telegramEvents = payouts | payouts+purchases | all, telegramCtaUrl)
// A second target, telegramEchoChatId + telegramEchoTopicId (+ telegramEchoEvents), echoes
// the same lines into a shared cross-program payments topic that RM Circle also posts to,
// so every line there carries the program name.
async function telegramOnEvent(ev) {
const sc = siteConfig();
if (!sc.telegramBotToken || !sc.telegramChatId || !ev) return;
const mode = String(sc.telegramEvents || 'payouts');
if (!sc.telegramBotToken || !ev) return;
if (!sc.telegramChatId && !sc.telegramEchoChatId) return;
const names = await accounts.namesForMembers([ev.recipientId, ev.buyerId, ev.sponsorId, ev.newBuyerId, ev.id].filter(Boolean)).catch(() => ({}));
const who = id => '#' + id + (names[id] ? ' @' + names[id] : '');
const cc = chain.getConfig();
const tx = (cc.explorer ? cc.explorer.replace(/\/+$/, '') : 'https://polygonscan.com') + '/tx/' + ev.tx;
const build = (mode) => {
let line = null;
if (ev.type === 'TierPaid') line = '\u{1F4B8} Level ' + ev.tier + ' payout: <b>' + weiToPol(ev.amountWei) + ' POL</b> \u2192 ' + who(ev.recipientId);
else if (ev.type === 'BuyerCounted' && mode !== 'payouts') line = '\u2B50 ' + who(ev.sponsorId) + ' now has <b>' + ev.newCount + '</b> qualifying buyer' + (ev.newCount === 1 ? '' : 's') + (ev.newCount === 2 ? ' \u00b7 level 2 open' : ev.newCount === 5 ? ' \u00b7 level 3 open' : '');
else if (ev.type === 'Purchase' && mode !== 'payouts') line = '\u{1F9FE} ' + who(ev.buyerId) + ' bought a $' + Math.round(ev.priceCents / 100) + ' package';
else if (ev.type === 'AwardPaid') line = '\u{1F4B8} Award payout: <b>' + weiToPol(ev.amountWei) + ' POL</b> \u2192 ' + who(ev.toId);
else if (ev.type === 'MemberActivated' && mode === 'all') line = '\u{1F91D} ' + who(ev.id) + ' switched on payouts';
if (!line) return;
const text = line + ' \u00b7 <a href="' + tx + '">verify</a>' + (sc.telegramCtaUrl ? '\n<a href="' + sc.telegramCtaUrl + '">Join free</a>' : '');
await telegramSend(sc.telegramChatId, text, sc.telegramTopicId);
if (!line) return null;
return line + ' \u00b7 <a href="' + tx + '">verify</a>' + (sc.telegramCtaUrl ? '\n<a href="' + sc.telegramCtaUrl + '">Join free</a>' : '');
};
if (sc.telegramChatId) { const t = build(String(sc.telegramEvents || 'payouts')); if (t) await telegramSend(sc.telegramChatId, t, sc.telegramTopicId); }
if (sc.telegramEchoChatId) { const t = build(String(sc.telegramEchoEvents || 'payouts')); if (t) await telegramSend(sc.telegramEchoChatId, '\u{1F7E0} <b>InstantAdPay</b> \u00b7 ' + t, sc.telegramEchoTopicId); }
}
// one sendMessage call; never throws, never logs the token
async function telegramSend(chatId, text, threadId) {