From 41d3293486ba891ed2dfaf7cb7de3cd59eec42fc Mon Sep 17 00:00:00 2001 From: martbost Date: Mon, 7 Sep 2026 06:38:27 -0500 Subject: [PATCH] Fix referral attribution (username joins) + broadcast rate-limit regression MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Dashboard "Your line" roster now matches referrals joined under the member's USERNAME link (invite link is /join/), not just code + member id — username joins were invisible. - lastBroadcastAt now counts only kind='broadcast'. Chat rides the same table, so chatting had been tripping the once-a-day broadcast limit ("try again in 24h" on the first broadcast). Co-Authored-By: Claude Opus 4.8 --- a.jar | 2 +- messages.js | 4 ++-- server.js | 4 +++- u.jar | 5 +++++ 4 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 u.jar diff --git a/a.jar b/a.jar index 7394399..dff5cb3 100644 --- a/a.jar +++ b/a.jar @@ -2,4 +2,4 @@ # https://curl.se/docs/http-cookies.html # This file was generated by libcurl! Edit at your own risk. -#HttpOnly_127.0.0.1 FALSE / FALSE 1788867258 iap.sid ef5bf189318d5c20a0d3c252de07f6c5d3b15d05c4749e71344c5e279ff8f35f +#HttpOnly_127.0.0.1 FALSE / FALSE 1788867454 iap.sid 9c0338979f5ee57c2d40f88328c0563065aab070b613c3d7665e042e79ac0478 diff --git a/messages.js b/messages.js index b2f6bcf..30fc1e3 100644 --- a/messages.js +++ b/messages.js @@ -19,11 +19,11 @@ const DAY = 86400000; async function lastBroadcastAt(fromEmail) { const e = String(fromEmail || '').toLowerCase(); if (db.enabled()) { - const r = await db.q('SELECT MAX(sent) m FROM sponsor_messages WHERE from_email=?', [e]); + const r = await db.q("SELECT MAX(sent) m FROM sponsor_messages WHERE from_email=? AND kind='broadcast'", [e]); return r.length && r[0].m ? Number(r[0].m) : 0; } if (!J.db) J.load(); - const mine = J.db.items.filter(i => i.fromEmail === e).map(i => i.sent); + const mine = J.db.items.filter(i => i.fromEmail === e && (i.kind || 'broadcast') === 'broadcast').map(i => i.sent); return mine.length ? Math.max(...mine) : 0; } // deliver one message to many recipients (already-resolved emails). Returns count. diff --git a/server.js b/server.js index 27be9bd..29a852b 100644 --- a/server.js +++ b/server.js @@ -513,9 +513,11 @@ const server = http.createServer(async (req, res) => { out.earnedWei = earned.toString(); out.earnCount = n; } - // who joined through this member (code and, once on-chain, numeric id) + // who joined through this member: their invite link uses username when set, + // else code, and the numeric id once on-chain — match all three const refs = []; if (acct && acct.code) refs.push(acct.code); + if (acct && acct.username) refs.push(acct.username); if (memberId) refs.push(String(memberId)); const joined = await accounts.listByReferrer(refs); out.referrals = joined.map(r => ({ diff --git a/u.jar b/u.jar new file mode 100644 index 0000000..cbb3ebb --- /dev/null +++ b/u.jar @@ -0,0 +1,5 @@ +# Netscape HTTP Cookie File +# https://curl.se/docs/http-cookies.html +# This file was generated by libcurl! Edit at your own risk. + +#HttpOnly_127.0.0.1 FALSE / FALSE 1788867454 iap.sid 422fe0acfd5b80732cbe04445cca71d0b01c216439aefade3aa928110e0419c2