Video ads (watch-to-earn): duration-tiered pricing, escape-proof player, per-view charge

- New 'video' campaign type; MP4/WebM upload or direct https link + required-watch tier (10/30/60s → 3/7/12 cr per view; viewer earns 1/2/4)
- Composer: video fields, tier dropdown, live price hint
- Earn credits > Watch videos sub-tab: no-seek player, server-clock watch floor, daily cap, self-exclusion, single-use tokens
- media-src CSP for direct-link/hosted video; video skips frame-check

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-06 08:03:01 -05:00
parent 49508c2a13
commit 860aedabf6
12 changed files with 199 additions and 33 deletions
+40 -5
View File
@@ -4,7 +4,7 @@
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Member area | InstantAdPay</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
<link rel="stylesheet" href="/assets/site.css?v=20260905w">
<link rel="stylesheet" href="/assets/site.css?v=20260905x">
</head>
<body class="bo-body">
@@ -245,6 +245,7 @@
<option value="text">Text ad (per impression)</option>
<option value="login">Login ad (per day)</option>
<option value="solo">Solo ad (inbox delivery)</option>
<option value="video">Video ad (watch to earn)</option>
</select></p>
<p><input id="cName" placeholder="Campaign name" style="width:100%"></p>
<p><input id="cBudget" type="number" placeholder="Budget (credits)" min="10" style="width:100%"></p>
@@ -287,6 +288,17 @@
placeholder="Call-to-action button label (default: Learn more) — the button opens your target URL"></p>
</div>
<p class="small muted" id="cSoloHint" hidden></p>
<div id="cVideoRow" hidden>
<p><input id="cVideoUrl" placeholder="Video URL (direct https link ending .mp4 or .webm)" style="width:100%"></p>
<p><input type="file" id="cVideoFile" accept="video/mp4,video/webm" hidden>
<button type="button" class="btn small sec" id="cVideoUploadBtn">Upload video</button>
<span id="cVideoInfo" class="small muted"></span></p>
<div id="cVideoPrev" hidden style="margin:8px 0"></div>
<p><input id="cVideoTitle" maxlength="80" placeholder="Video title (optional)" style="width:100%"></p>
<p><select id="cWatchSecs" style="width:100%"></select></p>
<p><input id="cVideoCta" maxlength="30" placeholder="Call-to-action label (default: Learn more)" style="width:100%"></p>
<p class="small muted" id="cVideoHint"></p>
</div>
<button class="btn" id="createCampBtn">Launch campaign</button>
</div>
</div>
@@ -294,6 +306,7 @@
<div class="pane" id="pane-earn" hidden>
<div class="subtabs" role="tablist">
<button class="subtab on" data-earn="watch" type="button">Watch ads</button>
<button class="subtab" data-earn="videos" type="button">Watch videos</button>
<button class="subtab" data-earn="inbox" type="button">Inbox<span class="pill" id="inboxBadge2" hidden></span></button>
</div>
@@ -318,6 +331,28 @@
</div>
</div>
<div class="earn-sub" id="earn-videos" hidden>
<div class="card">
<h3>Watch videos, earn credits</h3>
<p class="muted small">Watch a member's video for its required time and earn credits. The player
can't be skipped — the timer runs on our server. You never see your own videos.</p>
<p><span class="badge" id="vidProgress">…</span></p>
<div class="card" style="background:rgba(4,8,7,.5)" id="vidStage">
<div id="vidBox" class="small muted" style="min-height:120px;display:grid;place-items:center">
Press the button to load the first video.</div>
<div id="vidWrap" hidden style="max-width:560px;margin:0 auto">
<video id="vidPlayer" playsinline preload="auto" style="width:100%;border-radius:12px;background:#000"></video>
<p class="small muted" id="vidTimer" style="text-align:center;margin:8px 0 0"></p>
</div>
<p style="margin-top:14px">
<button class="btn" id="vidStartBtn" type="button">Load a video</button>
<a class="btn sec" id="vidCta" target="_blank" rel="noopener nofollow" hidden>Learn more</a>
</p>
<p class="small muted" id="vidHint"></p>
</div>
</div>
</div>
<div class="earn-sub" id="earn-inbox" hidden>
<div class="card" id="inboxListCard">
<h3>Solo ads inbox</h3>
@@ -449,9 +484,9 @@
</div>
</div>
<script src="/assets/common.js?v=20260905w"></script>
<script src="/assets/wallet.js?v=20260905w"></script>
<script src="/assets/my.js?v=20260905w"></script>
<script src="/assets/chat.js?v=20260905w"></script>
<script src="/assets/common.js?v=20260905x"></script>
<script src="/assets/wallet.js?v=20260905x"></script>
<script src="/assets/my.js?v=20260905x"></script>
<script src="/assets/chat.js?v=20260905x"></script>
</body>
</html>