Earn viewer v2: full-screen URL visits with countdown, human check, explicit return

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-05 07:23:30 -05:00
parent fee86d296a
commit 15b036b940
7 changed files with 238 additions and 47 deletions
+10 -1
View File
@@ -139,6 +139,10 @@ const J = {
this.save();
return c.targetUrl;
},
async targetOf(id) { // resolve without counting a click (earn-view frames the real url)
const c = this.db.campaigns.find(x => x.id === Number(id));
return c ? c.targetUrl : null;
},
async dailySweep() {
const r = rates();
const today = new Date().toISOString().slice(0, 10);
@@ -242,6 +246,10 @@ const D = {
await db.q('UPDATE campaigns SET clicks=clicks+1 WHERE id=?', [Number(id)]);
return rows[0].target_url;
},
async targetOf(id) { // resolve without counting a click (earn-view frames the real url)
const rows = await db.q('SELECT target_url FROM campaigns WHERE id=?', [Number(id)]);
return rows.length ? rows[0].target_url : null;
},
async dailySweep() {
const r = rates();
const today = new Date().toISOString().slice(0, 10);
@@ -415,10 +423,11 @@ async function setStatus(owner, id, status) {
}
async function serve(type, opts) { return TYPES.includes(type) ? impl().serve(type, opts) : null; }
async function click(id) { return impl().click(id); }
async function targetOf(id) { return impl().targetOf(id); }
async function dailySweep() { return impl().dailySweep(); }
async function pendingBurns() { return impl().pendingBurns(); }
async function markBurned(id, tx) { return impl().markBurned(id, tx); }
module.exports = { init, rates, setRates, createCampaign, listCampaigns, setStatus,
serve, click, dailySweep, availableCredits, earnedBalance, grantWelcome,
serve, click, targetOf, dailySweep, availableCredits, earnedBalance, grantWelcome,
viewStatus, recordView, claimDaily, pendingBurns, markBurned };