mirror of
https://github.com/myronblair/tomtomgames
synced 2026-06-30 17:51:08 -05:00
Add URL-based referral share verification with auto-scraper
Players now paste the URL of their post instead of just clicking a platform button. The server fetches the URL and looks for the player's referral code in the page content. If found, the share is auto-approved and tokens are awarded immediately. If not (login wall, private page, code missing), it falls into the pending queue with a reason so admins can click the link directly for manual review. - api/referrals.php: replace submit_share with URL-accepting version; add scrapeForReferralCode() (SSRF-guarded cURL, 8s timeout, 512KB cap) and inferPlatformFromUrl() helpers - db/schema.sql: add share_url, auto_verified, verify_result columns - index.php: replace platform buttons with URL input form; show auto- verify result inline; shares list shows URL and auto-verify badge - admin/index.php: share cards show clickable URL, auto-check result label, and auto-verified tag Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+22
-7
@@ -2601,14 +2601,29 @@ async function loadAdminShares(status, btn) {
|
||||
const el = document.getElementById('ref-shares-admin-list');
|
||||
const d = await fetch('/api/referrals.php?action=admin_shares&status='+status).then(r=>r.json());
|
||||
if (!d.success||!d.shares.length) { el.innerHTML='<div class="empty" style="padding:20px;text-align:center">No '+status+' shares.</div>'; return; }
|
||||
const verifyLabels = {
|
||||
code_found: '✅ Code found in page',
|
||||
login_required: '🔒 Login required',
|
||||
unreachable: '⚠️ URL unreachable',
|
||||
not_found: '❌ Code not in page',
|
||||
site_found_no_code: '⚠️ Site mentioned, code missing',
|
||||
invalid_url: '❌ Invalid URL',
|
||||
};
|
||||
el.innerHTML = d.shares.map(s => {
|
||||
const btns = status==='pending' ?
|
||||
'<div style="display:flex;gap:6px">'+
|
||||
'<button data-sid="'+s.id+'" onclick="resolveShare(this.dataset.sid,"approved")" class="btn btn-green" style="font-size:14px;padding:7px 12px">Approve</button>'+
|
||||
'<button data-sid="'+s.id+'" onclick="resolveShare(this.dataset.sid,"denied")" class="btn btn-red" style="font-size:14px;padding:7px 12px">Deny</button></div>' : '';
|
||||
return '<div class="card" style="margin-bottom:8px;display:flex;align-items:center;gap:12px">'+
|
||||
'<div style="flex:1"><div style="font-size:15px;font-weight:700">'+escHtmlA(s.alias||s.username)+' | <span style="color:var(--cyan)">'+escHtmlA(s.platform)+'</span></div>'+
|
||||
'<div style="font-size:15px;color:var(--text2)">'+(s.created_at||'').substring(0,16)+' | Bonus: '+s.bonus_tokens+' tokens</div></div>'+btns+'</div>';
|
||||
const autoTag = parseInt(s.auto_verified) ? '<span style="font-size:12px;color:var(--green);margin-left:6px">⚡ auto-verified</span>' : '';
|
||||
const verifyNote = s.verify_result && !parseInt(s.auto_verified)
|
||||
? '<div style="font-size:13px;color:var(--text2);margin-top:2px">Auto-check: '+(verifyLabels[s.verify_result]||s.verify_result)+'</div>' : '';
|
||||
const urlLink = s.share_url
|
||||
? '<div style="margin-top:4px"><a href="'+escHtmlA(s.share_url)+'" target="_blank" rel="noopener" style="color:var(--cyan);font-size:13px;word-break:break-all">🔗 '+escHtmlA(s.share_url.length>70?s.share_url.substring(0,70)+'…':s.share_url)+'</a></div>'
|
||||
: '<div style="font-size:13px;color:var(--text2);margin-top:2px;font-style:italic">No URL submitted</div>';
|
||||
const btns = status==='pending'
|
||||
? '<div style="display:flex;gap:6px;margin-top:8px">'+
|
||||
'<button data-sid="'+s.id+'" onclick="resolveShare(this.dataset.sid,"approved")" class="btn btn-green" style="font-size:14px;padding:7px 12px">Approve</button>'+
|
||||
'<button data-sid="'+s.id+'" onclick="resolveShare(this.dataset.sid,"denied")" class="btn btn-red" style="font-size:14px;padding:7px 12px">Deny</button></div>' : '';
|
||||
return '<div class="card" style="margin-bottom:8px">'+
|
||||
'<div style="font-size:15px;font-weight:700">'+escHtmlA(s.alias||s.username)+' | <span style="color:var(--cyan)">'+escHtmlA(s.platform)+'</span>'+autoTag+'</div>'+
|
||||
'<div style="font-size:14px;color:var(--text2);margin-top:2px">'+(s.created_at||'').substring(0,16)+' | Bonus: '+s.bonus_tokens+' tokens</div>'+
|
||||
urlLink+verifyNote+btns+'</div>';
|
||||
}).join('');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user