diff --git a/snapshot.js b/snapshot.js index b85e770..97a2499 100644 --- a/snapshot.js +++ b/snapshot.js @@ -53,18 +53,37 @@ async function gather(now = Date.now()) { return s; } +// One block per subject, a blank line between them, and no line long enough for a phone to wrap it +// into a wall of text (Marty, 2026-09-22 — the single-paragraph version was unreadable on mobile). function compose(s, cta) { - const trend = (cur, prev, what) => cur > prev ? ' (up from ' + n(prev) + ' ' + what + ')' : cur < prev ? ' (' + n(prev) + ' ' + what + ')' : ''; - const L = []; - L.push('\u{1F4C8} InstantAdPay · 24-hour snapshot'); - L.push('\u{1F465} Sign-ups: ' + n(s.signups) + '' + trend(s.signups, s.signupsPrior, 'the day before') + ' · ' + n(s.activations) + ' switched on payouts'); - L.push('\u{1F9FE} Purchases: ' + n(s.buys) + ' for $' + n(Math.round(s.usd)) + trend(s.buys, s.buysPrior, 'the day before') + ' · ' + pol(s.paidWei) + ' POL paid to members in the same transactions'); - L.push('\u{1F4E3} Campaigns: ' + n(s.campaigns) + ' posted by ' + n(s.advertisers) + ' advertiser' + (s.advertisers === 1 ? '' : 's') + ' · ' + n(s.active) + ' running now · ' + n(s.imps) + ' ad impressions served'); - L.push('\u{1F440} Earning: ' + n(s.viewers) + ' members viewed ads today · ' + n(s.seen24h) + ' signed in'); - L.push('\u{1F4B3} Credits: ' + n(s.creditsHandedOut) + ' handed out · ' + n(s.creditsEarned) + ' earned by viewing · ' + n(s.creditsSpent) + ' spent on ads'); - L.push('\u{1F3C1} So far: ' + n(s.members) + ' members · ' + n(s.wallets) + ' wallets linked · ' + n(s.payoutsOn) + ' with payouts on · ' + n(s.lifeBuys) + ' purchases · ' + pol(s.lifePaidWei) + ' POL paid out in ' + n(s.lifePayouts) + ' payouts, every one on the public ledger'); - L.push('Live ledger' + (cta ? ' · Join free' : '')); - return L.join('\n'); + const up = (cur, prev) => cur > prev ? ', up from ' + n(prev) + ' yesterday' + : cur < prev ? ', down from ' + n(prev) + ' yesterday' : ''; + const plural = (c, word) => n(c) + ' ' + word + (Number(c) === 1 ? '' : 's'); + const day = new Date().toLocaleDateString('en-US', { timeZone: 'America/Chicago', weekday: 'long', month: 'long', day: 'numeric' }); + const B = []; + B.push('\u{1F4C8} InstantAdPay · 24-hour snapshot\n' + day + ''); + B.push('\u{1F465} Sign-ups\n' + + '' + n(s.signups) + ' new' + up(s.signups, s.signupsPrior) + '\n' + + n(s.activations) + ' switched on payouts'); + B.push('\u{1F9FE} Purchases\n' + + '' + n(s.buys) + ' for $' + n(Math.round(s.usd)) + '' + up(s.buys, s.buysPrior) + '\n' + + '' + pol(s.paidWei) + ' POL paid to members\nin the same transactions'); + B.push('\u{1F4E3} Campaigns\n' + + '' + n(s.campaigns) + ' posted by ' + plural(s.advertisers, 'advertiser') + '\n' + + n(s.active) + ' running · ' + n(s.imps) + ' impressions'); + B.push('\u{1F440} Earning\n' + + '' + n(s.viewers) + ' members viewed ads today\n' + + n(s.seen24h) + ' signed in'); + B.push('\u{1F4B3} Credits\n' + + '' + n(s.creditsHandedOut) + ' handed out · ' + n(s.creditsEarned) + ' earned\n' + + n(s.creditsSpent) + ' spent on ads'); + B.push('\u{1F3C1} So far\n' + + '' + n(s.members) + ' members · ' + n(s.wallets) + ' wallets linked\n' + + n(s.payoutsOn) + ' with payouts on · ' + n(s.lifeBuys) + ' buys\n' + + '' + pol(s.lifePaidWei) + ' POL paid in ' + n(s.lifePayouts) + ' payouts\n' + + 'All of it on the public ledger.'); + B.push('Live ledger' + (cta ? ' · Join free' : '')); + return B.join('\n\n'); } async function post() {