Telegram Mini App v1: initData auth bridge into the existing site

- POST /api/public/tg-webapp-auth: HMAC-verifies WebApp initData against the
  companion bot token (12h freshness, timing-safe), maps chat -> member via
  tg-links.json, mints a message session -> linked members land on /my/<id>
  with zero login
- /app entry page (vendored telegram-web-app.js keeps CSP script-src 'self');
  unlinked users get the one-time wallet-link instructions
- tg-app.js on all pages: no-op in browsers; inside the webview lazy-loads the
  SDK, expands, themes header/background #071421, wires native BackButton
- Bot menu button set programmatically to open /app; /start + help mention it
- Synced chat.js canned answer + AI system prompt (Mini App facts)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-08-23 05:56:51 -05:00
parent 2a666d4063
commit cd361a1eaa
19 changed files with 3567 additions and 19 deletions
+30
View File
@@ -0,0 +1,30 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex"><title>RM Circle</title><link rel="icon" type="image/png" href="/favicon.png"><link rel="stylesheet" href="/styles.css">
<!-- Telegram Mini App entry point. Vendored WebApp JS (CSP: script-src 'self'). -->
<script src="/telegram-web-app.js"></script></head>
<body>
<main class="wrap hero" style="text-align:center;padding-top:14vh">
<div id="st-loading">
<img src="/logo.jpg" alt="RM Circle" style="width:72px;height:72px;border-radius:18px;box-shadow:0 6px 24px rgba(0,0,0,.45)">
<h1 style="font-size:22px;margin:18px 0 6px">Opening your dashboard…</h1>
<p style="color:var(--muted)">Verifying your Telegram link.</p>
</div>
<div id="st-unlinked" style="display:none">
<div class="eyebrow">One-time setup</div>
<h1 style="font-size:22px">Link your position first</h1>
<p style="color:var(--muted);max-width:420px;margin:10px auto">This app shows YOUR live dashboard — payments, team, coaching. To prove a position is yours, link it once with your wallet (a free signature, it can't move funds):</p>
<p style="color:var(--muted);max-width:420px;margin:10px auto;text-align:left">1. Open <b>rmcircle.team/my</b> in your browser<br>2. Enter your member ID → <b>Messages</b> → sign in with your wallet<br>3. Tap <b>“Connect Telegram”</b> — it deep-links right back to this bot</p>
<p style="margin:18px 0 8px"><button id="btn-open-site" class="btn btn-primary">Open the dashboard to link ↗</button></p>
<p><button id="btn-browse" class="btn">Just looking? See how the team works</button></p>
</div>
<div id="st-error" style="display:none">
<h1 style="font-size:22px">Hmm, that didn't verify</h1>
<p id="err-detail" style="color:var(--muted);max-width:420px;margin:10px auto">Could not verify the Telegram launch data.</p>
<p><button id="btn-retry" class="btn btn-primary">Try again</button></p>
</div>
<div id="st-notg" style="display:none">
<h1 style="font-size:22px">This page opens inside Telegram</h1>
<p style="color:var(--muted);max-width:420px;margin:10px auto">It's the RM Circle Mini App — open the companion bot in Telegram and tap the ☰ menu button. In a normal browser, use the regular dashboard instead.</p>
<a class="btn btn-primary" href="/my">Open the dashboard</a>
</div>
</main>
<script src="/app.js"></script></body></html>
+37
View File
@@ -0,0 +1,37 @@
// Telegram Mini App entry: verify initData server-side, then land the linked
// member on THEIR dashboard with a minted session — zero login. Unlinked
// users get the one-time wallet-link instructions instead.
(function () {
'use strict';
var tg = window.Telegram && window.Telegram.WebApp;
function show(id) {
['st-loading', 'st-unlinked', 'st-error', 'st-notg'].forEach(function (x) {
var el = document.getElementById(x); if (el) el.style.display = x === id ? '' : 'none';
});
}
function on(id, fn) { var el = document.getElementById(id); if (el) el.addEventListener('click', fn); }
on('btn-open-site', function () {
var url = location.origin + '/my';
if (tg && tg.openLink) tg.openLink(url); else location.href = url;
});
on('btn-browse', function () { location.href = '/start'; });
on('btn-retry', function () { location.reload(); });
if (!tg || !tg.initData) { show('st-notg'); return; }
// Flag the webview session so tg-app.js activates on every page after this one.
try { sessionStorage.setItem('rmcTg', '1'); } catch (e) {}
tg.ready();
try { tg.expand(); } catch (e) {}
try { tg.setHeaderColor('#071421'); tg.setBackgroundColor('#071421'); } catch (e) {}
fetch('/api/public/tg-webapp-auth', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ initData: tg.initData })
}).then(function (r) { return r.json(); }).then(function (d) {
if (d && d.ok && d.linked) { location.replace('/my/' + d.id); return; }
if (d && d.ok) { show('st-unlinked'); return; }
var el = document.getElementById('err-detail');
if (el && d && d.error) el.textContent = d.error;
show('st-error');
}).catch(function () { show('st-error'); });
})();
+2 -2
View File
@@ -35,8 +35,8 @@
a:()=>`Great question — and we checked it on-chain, not just in theory. The contract needs <strong>no one</strong> to keep it running: joins, upgrades, placement and every payout are fully automatic — no button anyone has to press, no expiry. If the creators walked away, lost their keys, or vanished, member payments keep flowing exactly as coded. We also verified that the founder, development and fee wallets are <strong>ordinary wallets, not programs</strong> — an ordinary wallet always accepts an incoming payment even if its key is lost forever, so a dead admin wallet can't jam a single member payment (at worst the project's <em>own</em> fee sits there uncollected). And the contract holds no stored balance — every payment is delivered in the same transaction. Full write-up in section 6 of <a href="/contract">rmcircle.team/contract</a>.`},
{k:['pyramid','ponzi','pyramid scheme','ponzi scheme','mlm','recruiting scheme','is this a scheme'],
a:()=>`A pyramid or Ponzi scheme funnels everyone's money to a central company and pays earlier joiners out of later joiners' deposits — and you can't verify any of it. This is the opposite: <strong>no company holds the money</strong>. A public smart contract on Polygon sends each payment person-to-person in the same transaction it arrives, and you can read the code and every payout yourself on-chain — nothing pooled, nothing hidden, rules that can't be changed. It <em>is</em> a team build, so it takes real effort and carries real crypto risk — not a passive investment. But you don't have to trust anyone; verify it at <a href="/contract">rmcircle.team/contract</a>. No income is guaranteed.`},
{k:['telegram bot','connect telegram','payout ping','telegram notification','message my downline','contact my downline','reach my downline'],
a:()=>`Link your position to our Telegram companion bot: open your <a href="/my">dashboard</a> → Messages → sign in with your wallet → tap "Connect Telegram". Once linked you get an instant DM whenever your position catches a payment, team messages reach you natively in Telegram (reply right there to answer), you're pinged when someone joins on your link, and "links" gives you all your invite links. Messaging still follows your matrix lines only — same rules as the site.`},
{k:['telegram bot','connect telegram','payout ping','telegram notification','message my downline','contact my downline','reach my downline','mini app','miniapp','telegram app','dashboard in telegram'],
a:()=>`Link your position to our Telegram companion bot: open your <a href="/my">dashboard</a> → Messages → sign in with your wallet → tap "Connect Telegram". Once linked you get an instant DM whenever your position catches a payment, team messages reach you natively in Telegram (reply right there to answer), you're pinged when someone joins on your link, and "links" gives you all your invite links. Linked members can also tap the bot's ☰ menu button to open the <strong>Mini App</strong> — your full live dashboard, promo tools, and the Circle Method right inside Telegram, no login needed. Messaging still follows your matrix lines only — same rules as the site.`},
{k:['cash out','cashout','spend my crypto','withdraw','off ramp','off-ramp','gift card','giftcard','get my money out','turn into cash','convert to dollars'],
a:()=>`Three good paths, easiest first: (1) <strong>E-gift cards</strong> — send POL to CWallet (cwallet.com), swap to a US-dollar token there (their internal swaps are virtually free), and buy gift cards for brands you already use — groceries, gas, Amazon. eGifter (egifter.com) also takes crypto directly. (2) <strong>Straight cash-out</strong> via a regulated exchange in your country (Coinbase, Kraken…): send, sell, withdraw to your bank. (3) <strong>Keep it working</strong> — many members leave catches in the wallet to fund their next level. Full guide: <a href="/training#spending">Spending what you earn</a>. Honest notes: those are independent custodial services — only move what you're about to spend; taxes may apply where you live; not financial advice.`},
{k:['circle method','recruiting course','how do i recruit','recruiting training','get my two','get your two','how to invite','module 1','lessons'],
+1 -1
View File
@@ -30,4 +30,4 @@
</div></section>
</main>
<footer class="wrap disclaimer">This independent team page is educational and is not an earnings guarantee or investment advice. Cryptocurrency and smart-contract participation involve risk, including possible loss of funds. Never use funds you cannot afford to lose.<div class="footer-links"><a href="/">Strategy</a><a href="/start">Getting Started</a><a href="/training">Training</a><a href="/my">Member Dashboard</a><a href="/disclaimer">Disclaimers</a><a href="/how-pay-works">How You Get Paid</a><a href="/tools">Promo Tools</a></div></footer>
<script src="/track.js"></script><script src="/chat.js" defer></script><script src="/translate.js" defer></script></body></html>
<script src="/track.js"></script><script src="/chat.js" defer></script><script src="/translate.js" defer></script><script src="/tg-app.js" defer></script></body></html>
+1 -1
View File
@@ -25,4 +25,4 @@
</div></section>
</main>
<footer class="wrap disclaimer">Independent, unaffiliated team resource. Informational and educational only. Not an offer, solicitation, or guarantee of income. Cryptocurrency participation carries risk of total loss.<div class="footer-links"><a href="/">Home</a><a href="/contract">Contract Security</a><a href="/training">Training</a><a href="/start">Getting Started</a><a href="/how-pay-works">How You Get Paid</a><a href="/tools">Promo Tools</a></div></footer>
<script src="/track.js"></script><script src="/chat.js" defer></script><script src="/translate.js" defer></script></body></html>
<script src="/track.js"></script><script src="/chat.js" defer></script><script src="/translate.js" defer></script><script src="/tg-app.js" defer></script></body></html>
+1 -1
View File
@@ -111,4 +111,4 @@
<script src="/qrlib.js"></script>
<script src="/fast-start.js"></script>
<script src="/chat.js" defer></script>
<script src="/translate.js" defer></script></body></html>
<script src="/translate.js" defer></script><script src="/tg-app.js" defer></script></body></html>
+1 -1
View File
@@ -74,4 +74,4 @@
</div></section>
</main>
<footer class="wrap disclaimer">Independent, unaffiliated team resource. Informational and educational only. No income is guaranteed. Cryptocurrency participation carries risk of total loss.<div class="footer-links"><a href="/">Home</a><a href="/training">Training</a><a href="/contract">Contract Security</a><a href="/disclaimer">Disclaimers</a><a href="/how-pay-works">How You Get Paid</a><a href="/tools">Promo Tools</a></div></footer>
<script src="/track.js"></script><script src="/chat.js" defer></script><script src="/translate.js" defer></script></body></html>
<script src="/track.js"></script><script src="/chat.js" defer></script><script src="/translate.js" defer></script><script src="/tg-app.js" defer></script></body></html>
+1 -1
View File
@@ -23,4 +23,4 @@
<section class="section"><div class="wrap"><div class="card" style="text-align:center;padding:34px"><div class="eyebrow">Ready to start?</div><h2 style="font-size:38px;margin:10px 0">See the current team placement.</h2><p style="max-width:680px;margin:0 auto 20px;color:var(--muted)">The onboarding page automatically shows the sponsor position the team is currently helping. Always use the sponsor shown there instead of an old screenshot or saved link.</p><a class="btn btn-primary" href="/start">Open Getting Started Instructions →</a></div></div></section>
</main>
<footer class="wrap disclaimer">This independent team page is educational and is not an earnings guarantee or investment advice. Cryptocurrency and smart-contract participation involve risk, including possible loss of funds. Never use funds you cannot afford to lose. Results depend on actual participation, qualification, upgrades, smart-contract behavior, and the market value of POL.<div class="footer-links"><a href="/training">Training</a><a href="/start">Getting Started</a><a href="/my">Member Dashboard</a><a href="/contract">Contract Security</a><a href="/admin">Team Admin</a><a href="/disclaimer">Disclaimers</a><a href="/how-pay-works">How You Get Paid</a><a href="/tools">Promo Tools</a></div></footer>
<script src="/track.js"></script><script src="/bridge.js"></script><script src="/payouts.js" defer></script><script src="/chat.js" defer></script><script src="/translate.js" defer></script></body></html>
<script src="/track.js"></script><script src="/bridge.js"></script><script src="/payouts.js" defer></script><script src="/chat.js" defer></script><script src="/translate.js" defer></script><script src="/tg-app.js" defer></script></body></html>
+1 -1
View File
@@ -29,4 +29,4 @@
<div class="callout warning" style="margin-top:12px;max-width:880px;margin-left:auto;margin-right:auto"><strong>Risk reminder:</strong> participation involves cryptocurrency and smart-contract risk. No income is guaranteed. Use only funds you can afford to lose.</div></div></section>
</main><footer class="wrap disclaimer">This independent team page is educational and is not an earnings guarantee or investment advice. Cryptocurrency and smart-contract participation involve risk, including possible loss of funds. Never use funds you cannot afford to lose. Results depend on actual participation, qualification, upgrades, smart-contract behavior, and the market value of POL.<div class="footer-links"><a href="/training">Training</a><a href="/my">Member Dashboard</a><a href="/contract">Contract Security</a><a href="/disclaimer">Disclaimers</a><a href="/tools">Promo Tools</a></div></footer>
<script src="/track.js"></script><script src="/join.js"></script><script src="/payouts.js" defer></script><script src="/chat.js" defer></script><script src="/translate.js" defer></script></body></html>
<script src="/track.js"></script><script src="/join.js"></script><script src="/payouts.js" defer></script><script src="/chat.js" defer></script><script src="/translate.js" defer></script><script src="/tg-app.js" defer></script></body></html>
+1 -1
View File
@@ -31,4 +31,4 @@
</section>
</main>
<footer class="wrap disclaimer">All figures are read live from the RM Circle smart contract on Polygon and are historical facts, not a promise of future results. Participation involves cryptocurrency and smart-contract risk. Never use funds you cannot afford to lose.<div class="footer-links"><a href="/">Home</a><a href="/contract">Contract Security</a><a href="/disclaimer">Disclaimers</a><a href="/tools">Promo Tools</a></div></footer>
<script src="/track.js"></script><script src="/qrlib.js"></script><script src="/rmc-wallet.js"></script><script src="/my.js"></script><script src="/payouts.js" defer></script><script src="/chat.js" defer></script><script src="/translate.js" defer></script></body></html>
<script src="/track.js"></script><script src="/qrlib.js"></script><script src="/rmc-wallet.js"></script><script src="/my.js"></script><script src="/payouts.js" defer></script><script src="/chat.js" defer></script><script src="/translate.js" defer></script><script src="/tg-app.js" defer></script></body></html>
+1 -1
View File
@@ -16,4 +16,4 @@
<div class="callout warning" style="margin-top:12px"><strong>Risk reminder:</strong> participation involves cryptocurrency and smart-contract risk. No income is guaranteed. Use only funds you can afford to lose.</div><div id="supportBox" class="notice" style="margin-top:12px"></div><div id="supportLinkWrap" class="hidden" style="margin-top:10px"><a id="supportLink" class="btn btn-secondary" target="_blank" rel="noopener noreferrer">Open Team Support ↗</a></div></section></div>
<figure class="roadmap-figure"><a href="/roadmap.webp" target="_blank" rel="noopener"><img src="/roadmap.webp" alt="RM Circle Premium Team Build Roadmap — core strategy, step-by-step guide, premium levels, and duplication formula" width="1149" height="1369" loading="lazy"></a><figcaption>This roadmap is the plan every member follows — tap to view full size.</figcaption></figure></div></main>
<footer class="wrap disclaimer">This is an independent RM Circle Team Build onboarding resource, not an owner/principal page. Always confirm transaction details in your wallet before signing. Never disclose your Secret Recovery Phrase.<div class="footer-links"><a href="/my">Already joined? Open your Member Dashboard →</a><a href="/contract">Contract Security</a><a href="/disclaimer">Disclaimers</a><a href="/how-pay-works">How You Get Paid</a><a href="/tools">Promo Tools</a></div></footer>
<script src="/track.js"></script><script src="/start.js"></script><script src="/payouts.js" defer></script><script src="/chat.js" defer></script><script src="/translate.js" defer></script></body></html>
<script src="/track.js"></script><script src="/start.js"></script><script src="/payouts.js" defer></script><script src="/chat.js" defer></script><script src="/translate.js" defer></script><script src="/tg-app.js" defer></script></body></html>
File diff suppressed because it is too large Load Diff
+32
View File
@@ -0,0 +1,32 @@
// In-Telegram polish for every site page. No-ops in a normal browser; inside
// the Mini App webview it lazy-loads the vendored Telegram SDK (CSP stays
// script-src 'self') and wires theme + BackButton so pages feel native.
(function () {
'use strict';
var inTg = false;
try { inTg = sessionStorage.getItem('rmcTg') === '1'; } catch (e) {}
if (!inTg && (window.TelegramWebviewProxy !== undefined || /tgWebApp(Data|Platform)/.test(location.hash))) inTg = true;
if (!inTg) return;
try { sessionStorage.setItem('rmcTg', '1'); } catch (e) {}
function boot() {
var tg = window.Telegram && window.Telegram.WebApp;
if (!tg || !tg.initData) return;
tg.ready();
try { tg.expand(); } catch (e) {}
try { tg.setHeaderColor('#071421'); tg.setBackgroundColor('#071421'); } catch (e) {}
// Back button mirrors webview history: /app enters via location.replace, so
// the landing dashboard has no history and stays clean; any deeper page
// (tools, training, another member view) gets a native back arrow.
var bb = tg.BackButton;
if (bb && history.length > 1) {
bb.show();
bb.onClick(function () { history.back(); });
}
}
if (window.Telegram && window.Telegram.WebApp) { boot(); return; }
var s = document.createElement('script');
s.src = '/telegram-web-app.js';
s.onload = boot;
document.head.appendChild(s);
})();
+1 -1
View File
@@ -372,4 +372,4 @@ Watch the short training, look at the live payment feed, then ask me anything.
</div></section>
</main>
<footer class="wrap disclaimer">Independent RM Circle Team Build team resource. Informational only — not an earnings guarantee or investment advice. Cryptocurrency participation carries risk of loss.<div class="footer-links"><a href="/">Strategy</a><a href="/training">Training</a><a href="/start">Getting Started</a><a href="/how-pay-works">How You Get Paid</a><a href="/disclaimer">Disclaimers</a></div></footer>
<script src="/tools.js"></script><script src="/translate.js" defer></script></body></html>
<script src="/tools.js"></script><script src="/translate.js" defer></script><script src="/tg-app.js" defer></script></body></html>
+1 -1
View File
@@ -83,4 +83,4 @@
</div></section>
</main>
<footer class="wrap disclaimer">This is an independent RM Circle Team Build training resource. Always confirm transaction details in your wallet before signing. Never disclose your Secret Recovery Phrase.<div class="footer-links"><a href="/">Strategy</a><a href="/start">Getting Started</a><a href="/contract">Contract Security</a><a href="/admin">Team Admin</a><a href="/disclaimer">Disclaimers</a><a href="/how-pay-works">How You Get Paid</a><a href="/tools">Promo Tools</a></div></footer>
<script src="/track.js"></script><script src="/training.js"></script><script src="/chat.js" defer></script><script src="/translate.js" defer></script></body></html>
<script src="/track.js"></script><script src="/training.js"></script><script src="/chat.js" defer></script><script src="/translate.js" defer></script><script src="/tg-app.js" defer></script></body></html>
+1 -1
View File
@@ -82,4 +82,4 @@
<script src="/qrlib.js"></script>
<script src="/fast-start.js"></script>
<script src="/chat.js" defer></script>
<script src="/translate.js" defer></script></body></html>
<script src="/translate.js" defer></script><script src="/tg-app.js" defer></script></body></html>