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:
@@ -969,14 +969,13 @@ body::before{content:'';position:fixed;inset:0;background-image:linear-gradient(
|
||||
|
||||
<!-- Social share -->
|
||||
<div class="card" style="margin-bottom:12px">
|
||||
<div style="font-size:14px;font-weight:700;color:var(--text2);margin-bottom:8px;text-transform:uppercase;letter-spacing:1px">Social Share Bonus</div>
|
||||
<div style="font-size:14px;color:var(--text2);margin-bottom:10px;line-height:1.5">Share TomTomGames on social media and earn bonus tokens when approved by our team.</div>
|
||||
<div style="display:flex;gap:8px;flex-wrap:wrap" id="ref-share-btns">
|
||||
<button onclick="submitShare('facebook')" class="ref-share-btn" style="background:rgba(24,119,242,.15);border:1px solid rgba(24,119,242,.3);color:#1877f2">📘 Facebook</button>
|
||||
<button onclick="submitShare('twitter')" class="ref-share-btn" style="background:rgba(29,161,242,.15);border:1px solid rgba(29,161,242,.3);color:#1da1f2">🐦 Twitter/X</button>
|
||||
<button onclick="submitShare('instagram')" class="ref-share-btn" style="background:rgba(225,48,108,.15);border:1px solid rgba(225,48,108,.3);color:#e1306c">📸 Instagram</button>
|
||||
<button onclick="submitShare('tiktok')" class="ref-share-btn" style="background:rgba(0,0,0,.3);border:1px solid rgba(255,255,255,.15);color:#fff">🎵 TikTok</button>
|
||||
<div style="font-size:14px;font-weight:700;color:var(--text2);margin-bottom:6px;text-transform:uppercase;letter-spacing:1px">Share & Earn Bonus Tokens</div>
|
||||
<div style="font-size:14px;color:var(--text2);margin-bottom:12px;line-height:1.5">Share your referral link anywhere — Reddit, Twitter/X, a forum, your blog. Paste the link to your post below and we'll try to verify it automatically.</div>
|
||||
<div style="display:flex;gap:8px;align-items:center;margin-bottom:6px">
|
||||
<input class="fi" id="share-url-input" type="url" placeholder="https://reddit.com/r/gaming/comments/…" style="flex:1;font-size:14px">
|
||||
<button onclick="submitShareUrl()" style="background:var(--gold);border:none;color:#000;border-radius:8px;padding:10px 16px;font-size:14px;font-weight:700;cursor:pointer;white-space:nowrap">🔍 Submit</button>
|
||||
</div>
|
||||
<div style="font-size:13px;color:var(--text2)">Public posts (Reddit, forums, blogs) verify instantly. Facebook/Instagram/TikTok need manual review.</div>
|
||||
<div id="ref-share-alert" class="alert" style="margin-top:8px"></div>
|
||||
<div id="ref-shares-list" style="margin-top:10px"></div>
|
||||
</div>
|
||||
@@ -2277,9 +2276,23 @@ async function loadReferralDashboard() {
|
||||
|
||||
// Social shares
|
||||
const sharesList = document.getElementById('ref-shares-list');
|
||||
if (sharesList && (d.social_shares||[]).length) {
|
||||
sharesList.innerHTML = '<div style="font-size:15px;font-weight:700;color:var(--text2);margin-bottom:6px">Submitted Shares:</div>' +
|
||||
d.social_shares.map(s => `<div style="font-size:14px;margin-bottom:4px">${escHtml(s.platform)} — <span class="ref-status-${s.status}">${s.status}</span>${s.status==='approved'?' (+'+s.bonus_tokens+' tokens)':''}</div>`).join('');
|
||||
if (sharesList) {
|
||||
const shares = d.social_shares || [];
|
||||
if (!shares.length) {
|
||||
sharesList.innerHTML = '';
|
||||
} else {
|
||||
sharesList.innerHTML = '<div style="font-size:13px;font-weight:700;color:var(--text2);margin-bottom:6px;text-transform:uppercase;letter-spacing:.5px">Your Submitted Shares</div>' +
|
||||
shares.map(s => {
|
||||
const autoTag = parseInt(s.auto_verified) ? ' <span style="font-size:12px;background:rgba(0,255,128,.1);border:1px solid rgba(0,255,128,.2);color:var(--green);border-radius:4px;padding:1px 5px">⚡ auto</span>' : '';
|
||||
const urlFrag = s.share_url
|
||||
? `<div style="margin-top:3px"><a href="${escHtml(s.share_url)}" target="_blank" rel="noopener" style="color:var(--cyan);font-size:12px;word-break:break-all">${escHtml(s.share_url.length>60?s.share_url.substring(0,60)+'…':s.share_url)}</a></div>`
|
||||
: '';
|
||||
return `<div style="padding:8px 0;border-bottom:1px solid var(--border)">
|
||||
<div style="font-size:14px"><strong>${escHtml(s.platform)}</strong> — <span class="ref-status-${s.status}">${s.status}</span>${autoTag}${s.status==='approved'?' <span style="color:var(--green)">+'+s.bonus_tokens+' tokens</span>':''}</div>
|
||||
${urlFrag}
|
||||
</div>`;
|
||||
}).join('');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2293,14 +2306,20 @@ function copyReferralLink() {
|
||||
if (msg) { msg.style.display='block'; setTimeout(()=>msg.style.display='none', 2000); }
|
||||
}
|
||||
|
||||
async function submitShare(platform) {
|
||||
const al = document.getElementById('ref-share-alert');
|
||||
const d = await api('/api/referrals.php?action=submit_share', { platform });
|
||||
async function submitShareUrl() {
|
||||
const al = document.getElementById('ref-share-alert');
|
||||
const inp = document.getElementById('share-url-input');
|
||||
const url = inp?.value.trim();
|
||||
if (!url) { showAlert(al, 'Please paste the URL of your post.', 'error'); return; }
|
||||
showAlert(al, '🔍 Checking your post…', 'info');
|
||||
const d = await api('/api/referrals.php?action=submit_share', { url });
|
||||
if (d.success) {
|
||||
showAlert(al, '✓ Share submitted for ' + platform + '! Our team will review and award your bonus tokens.', 'success');
|
||||
setTimeout(() => { al.className='alert'; al.textContent=''; }, 5000);
|
||||
showAlert(al, d.message, d.auto_verified ? 'success' : 'info');
|
||||
if (inp) inp.value = '';
|
||||
loadReferralDashboard();
|
||||
} else showAlert(al, d.error || 'Error', 'error');
|
||||
} else {
|
||||
showAlert(al, d.error || 'Error submitting share.', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// Pass referral code during registration
|
||||
|
||||
Reference in New Issue
Block a user