ca4b5bf34f
The product now has a lid. Server refuses the gated video FILES without a wallet-verified member session (the Mini App bridge session counts, so Telegram members see no locks). Lesson 1, every poster, and all join-funnel and transparency videos stay public: free preview + trust engine. Training page renders locked cards with a one-signature unlock (same SIWE flow as Messages) and a members-unlocked badge. Chatbot: new members-area canned answer, Method answer notes the preview, AI prompt routing rule now answers prospects directly instead of sending locked links; bot lesson command notes the unlock path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
71 lines
4.7 KiB
JavaScript
71 lines
4.7 KiB
JavaScript
(async function(){
|
||
try{
|
||
const r=await fetch('/api/public/config');
|
||
if(!r.ok)return;
|
||
const c=await r.json();
|
||
if(c.siteName){document.title=`Training | ${c.siteName}`;const bn=document.getElementById('brandName');if(bn)bn.textContent=c.siteName}
|
||
}catch(e){}
|
||
})();
|
||
|
||
// live dollar note in the card-buy callout — computed, never hand-written
|
||
fetch('/api/public/config').then(function(r){return r.json()}).then(function(c){
|
||
var el=document.getElementById('fundUsdNote');
|
||
if(el&&c.polUsd>0){var pol=(c.premiumEntryPol||362)+23;el.textContent=' — about $'+Math.round(pol*c.polUsd)+' at today’s price';}
|
||
}).catch(function(){});
|
||
|
||
// carry the member's saved id onto tools links so promo assets arrive personalized
|
||
try{var tid=localStorage.getItem('rmc.toolsId')||localStorage.getItem('ctb.myId');
|
||
if(tid&&/^\d+$/.test(tid))document.querySelectorAll('a[href="/tools"]').forEach(function(a){a.href='/tools?id='+tid;});}catch(e){}
|
||
|
||
// Members area: Circle Method lessons 2-10 + Video 8 are member-only. The
|
||
// SERVER refuses those video files without a session — this makes the page
|
||
// honest about it: locked cards with a one-signature unlock. Members arriving
|
||
// through the Telegram Mini App already carry a session and see no locks.
|
||
(async function(){
|
||
'use strict';
|
||
const gated=[...document.querySelectorAll('video')].filter(v=>{
|
||
const s=v.getAttribute('src')||'';
|
||
return (/\/v\/rmc-method-m\d+l\d+-/.test(s)&&s.indexOf('rmc-method-m1l1-')<0)||s.indexOf('/training/egift_cards.mp4')>=0;
|
||
});
|
||
if(!gated.length)return;
|
||
let member=null;
|
||
try{const r=await fetch('/api/public/msg-me');if(r.ok)member=await r.json();}catch(e){}
|
||
if(member&&member.id){
|
||
const h=document.getElementById('module-1');
|
||
if(h){const b=document.createElement('p');b.className='micro';b.style.cssText='max-width:880px;margin:6px auto 0;color:var(--ok)';b.textContent='✅ Members area unlocked — position #'+member.id;h.after(b);}
|
||
return;
|
||
}
|
||
gated.forEach(v=>{
|
||
const poster=v.getAttribute('poster')||'';
|
||
const box=document.createElement('div');
|
||
box.className='rmc-lock';
|
||
box.style.cssText='position:relative;border-radius:12px;overflow:hidden;aspect-ratio:16/9;display:flex;align-items:center;justify-content:center;background:#08131f center/cover no-repeat';
|
||
if(poster)box.style.backgroundImage="linear-gradient(rgba(4,10,17,.85),rgba(4,10,17,.85)),url('"+poster+"')";
|
||
box.innerHTML='<div style="text-align:center;padding:18px;max-width:460px">'
|
||
+'<div style="font-size:32px">🔒</div>'
|
||
+'<div style="font-weight:800;font-size:17px;margin:6px 0 4px">Members area</div>'
|
||
+'<p class="micro" style="color:var(--muted);margin:0 0 12px">This lesson comes with every team position. Sign in with the wallet that owns your position — one free signature, it can\'t move funds. Linked on Telegram? The ☰ Mini App in @RMCircleBot unlocks everything automatically.</p>'
|
||
+'<button class="btn btn-primary btn-sm rmc-unlock">🔓 I\'m a member — connect & unlock</button> '
|
||
+'<a class="btn btn-secondary btn-sm" href="/start">Not yet? See how to join</a>'
|
||
+'<div class="micro rmc-lock-err" style="color:#ff7b7b;margin-top:8px"></div></div>';
|
||
v.replaceWith(box);
|
||
});
|
||
const UNLOCK_LABEL='🔓 I\'m a member — connect & unlock';
|
||
document.querySelectorAll('button.rmc-unlock').forEach(b=>b.addEventListener('click',async ev=>{
|
||
const btn=ev.currentTarget,err=btn.closest('.rmc-lock').querySelector('.rmc-lock-err');
|
||
btn.disabled=true;btn.textContent='Connecting…';
|
||
try{
|
||
const eth=await window.RMCWallet.pick();
|
||
if(!eth){err.textContent='No wallet in this browser. On a phone, open this page inside your wallet app\'s browser — or use the Telegram Mini App.';btn.disabled=false;btn.textContent=UNLOCK_LABEL;return;}
|
||
const accs=await eth.request({method:'eth_requestAccounts'});const account=accs[0];
|
||
const ch=await(await fetch('/api/public/msg-challenge',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({address:account})})).json();
|
||
if(!ch.message)throw new Error(ch.error||'Could not start sign-in.');
|
||
let hex='0x';for(const b2 of new TextEncoder().encode(ch.message))hex+=b2.toString(16).padStart(2,'0');
|
||
const sig=await eth.request({method:'personal_sign',params:[hex,account]});
|
||
const vr=await(await fetch('/api/public/msg-verify',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({address:account,signature:sig})})).json();
|
||
if(!vr.ok)throw new Error(vr.error||'Verification failed — is this the wallet that owns your position?');
|
||
location.reload();
|
||
}catch(e){err.textContent=e.message||String(e);btn.disabled=false;btn.textContent=UNLOCK_LABEL;}
|
||
}));
|
||
})();
|