Members area: Circle Method lessons 2-10 + Video 8 gated behind position ownership
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>
This commit is contained in:
@@ -16,3 +16,55 @@ fetch('/api/public/config').then(function(r){return r.json()}).then(function(c){
|
||||
// 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;}
|
||||
}));
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user