Onsite solo ads: inbox delivery with read rewards, composer, homepage format live
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -392,6 +392,7 @@ const server = http.createServer(async (req, res) => {
|
||||
refCode: (acct && acct.code) || null, credits: 0, buyerCount: 0,
|
||||
earnedWei: '0', earnCount: 0, referrals: [], welcomeCredits: 0 };
|
||||
if (out.email) out.welcomeCredits = await ads.grantWelcome(out.email); // idempotent lazy grant
|
||||
if (out.email) out.inboxUnread = await ads.unreadCount(out.email); // delivers pending solos too
|
||||
if (memberId) {
|
||||
try {
|
||||
const mm = await chain.member(memberId);
|
||||
@@ -504,6 +505,35 @@ const server = http.createServer(async (req, res) => {
|
||||
const r = await ads.claimDaily(s.email);
|
||||
return json(res, r.error ? 400 : 200, r);
|
||||
}
|
||||
// -- onsite solo ads: member inbox with read rewards
|
||||
if (p === '/api/my/inbox' && req.method === 'GET') {
|
||||
const s = await auth.fromRequest(req);
|
||||
if (!s || !s.email) return json(res, 401, { error: 'Sign in first.' });
|
||||
const r = await ads.inboxList(s.email);
|
||||
const names = await accounts.namesForMembers([...new Set(r.items.map(i => i.fromMemberId).filter(Boolean))]);
|
||||
for (const i of r.items) i.fromName = (i.fromMemberId && names[i.fromMemberId]) ? '@' + names[i.fromMemberId]
|
||||
: i.fromMemberId ? 'member #' + i.fromMemberId : 'a member';
|
||||
return json(res, 200, r);
|
||||
}
|
||||
m = /^\/api\/my\/inbox\/(\d+)$/.exec(p);
|
||||
if (m && req.method === 'GET') {
|
||||
const s = await auth.fromRequest(req);
|
||||
if (!s || !s.email) return json(res, 401, { error: 'Sign in first.' });
|
||||
const r = await ads.inboxOpen(s.email, m[1]);
|
||||
if (!r.error) {
|
||||
const names = r.fromMemberId ? await accounts.namesForMembers([r.fromMemberId]) : {};
|
||||
r.fromName = (r.fromMemberId && names[r.fromMemberId]) ? '@' + names[r.fromMemberId]
|
||||
: r.fromMemberId ? 'member #' + r.fromMemberId : 'a member';
|
||||
}
|
||||
return json(res, r.error ? 404 : 200, r);
|
||||
}
|
||||
m = /^\/api\/my\/inbox\/(\d+)\/claim$/.exec(p);
|
||||
if (m && req.method === 'POST') {
|
||||
const s = await auth.fromRequest(req);
|
||||
if (!s || !s.email) return json(res, 401, { error: 'Sign in first.' });
|
||||
const r = await ads.claimSoloRead(s.email, m[1]);
|
||||
return json(res, r.error ? 400 : 200, r);
|
||||
}
|
||||
if (p === '/api/my/activity' && req.method === 'GET') {
|
||||
const s = await auth.fromRequest(req);
|
||||
if (!s) return json(res, 401, { error: 'Sign in first.' });
|
||||
@@ -545,7 +575,7 @@ const server = http.createServer(async (req, res) => {
|
||||
if (!s || !s.email) return json(res, 401, { error: 'Sign in first.' });
|
||||
const memberId = await auth.refreshMemberId(s); // 0 is fine: earned credits fund banner/text
|
||||
const b = await readBody(req);
|
||||
if (b.type !== 'login') { // surf views frame the target: catch frame-breakers at the door
|
||||
if (!['login', 'solo'].includes(String(b.type || ''))) { // surf views frame the target: catch frame-breakers at the door (login + solo are click-through only)
|
||||
const fc = await frameCheck(b.targetUrl);
|
||||
if (!fc.ok) return json(res, 400, { error: fc.reason });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user