storage / strings.html
mrpoddaa's picture
Upload 4 files
8af9fb7 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>TG Store · Add Session</title>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--bg: #0d1117; --surface: #161b22; --border: #30363d;
--accent: #2f81f7; --accent2: #388bfd; --text: #e6edf3;
--muted: #8b949e; --success: #3fb950; --error: #f85149;
}
body {
background: var(--bg); color: var(--text);
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
min-height: 100vh; display: flex; align-items: center;
justify-content: center; padding: 24px;
}
.card {
background: var(--surface); border: 1px solid var(--border);
border-radius: 10px; padding: 36px 40px;
width: 100%; max-width: 460px; box-shadow: 0 8px 32px #0009;
}
.logo { display: flex; align-items: center; gap: 12px; margin-bottom: 28px; }
.logo svg { color: var(--accent); flex-shrink: 0; }
.logo h1 { font-size: 1.25rem; font-weight: 700; }
.logo span { color: var(--muted); font-weight: 400; }
.steps { display: flex; gap: 8px; margin-bottom: 28px; }
.step { height: 4px; flex: 1; background: var(--border); border-radius: 2px; transition: background .3s; }
.step.on { background: var(--accent); }
label {
display: block; font-size: .78rem; color: var(--muted);
text-transform: uppercase; letter-spacing: .06em;
margin-bottom: 6px; margin-top: 18px;
}
input {
width: 100%; background: var(--bg); border: 1px solid var(--border);
border-radius: 6px; color: var(--text); padding: 10px 14px;
font-size: .95rem; outline: none; transition: border-color .2s;
}
input:focus { border-color: var(--accent); }
button {
margin-top: 22px; width: 100%; background: var(--accent);
color: #fff; border: none; border-radius: 6px; padding: 11px;
font-size: .98rem; font-weight: 600; cursor: pointer;
transition: background .2s, opacity .2s;
}
button:hover { background: var(--accent2); }
button:disabled { opacity: .45; cursor: not-allowed; }
.msg {
margin-top: 14px; padding: 11px 14px; border-radius: 6px;
font-size: .88rem; display: none;
}
.msg.ok { background:#1a3a2a; border:1px solid #2d6040; color:var(--success); display:block; }
.msg.err { background:#3b1a1a; border:1px solid #7a2828; color:var(--error); display:block; }
.session-out {
margin-top: 12px; background: var(--bg); border: 1px solid var(--border);
border-radius: 6px; padding: 10px 14px; font-size: .72rem;
font-family: monospace; color: var(--muted); word-break: break-all;
}
.hidden { display: none !important; }
footer { margin-top: 28px; font-size: .76rem; color: var(--muted); text-align: center; }
</style>
</head>
<body>
<div class="card">
<div class="logo">
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/>
</svg>
<h1>TG Store <span>· Add Session</span></h1>
</div>
<div class="steps">
<div class="step on" id="s1"></div>
<div class="step" id="s2"></div>
<div class="step" id="s3"></div>
</div>
<!-- Step 1 -->
<div id="p1">
<label>API ID</label>
<input id="apiId" type="number" placeholder="12345678" />
<label>API Hash</label>
<input id="apiHash" type="text" placeholder="0123456789abcdef..." />
<label>Phone Number (with country code)</label>
<input id="phone" type="tel" placeholder="+1 555 000 0000" />
<button id="btnCode">Send OTP →</button>
<div class="msg" id="m1"></div>
</div>
<!-- Step 2 -->
<div id="p2" class="hidden">
<p style="color:var(--muted);font-size:.88rem;line-height:1.5">
Check your Telegram app or SMS for the one-time code.
</p>
<label>OTP Code</label>
<input id="otp" type="text" placeholder="12345" maxlength="12" />
<div id="twoFAWrap" class="hidden">
<label>Two-Factor Password</label>
<input id="twoFA" type="password" placeholder="Cloud password" />
</div>
<button id="btnVerify">Verify &amp; Save →</button>
<div class="msg" id="m2"></div>
</div>
<!-- Step 3 -->
<div id="p3" class="hidden">
<p style="color:var(--success);font-weight:700;font-size:1.05rem">✓ Session saved!</p>
<p style="color:var(--muted);font-size:.88rem;margin-top:8px;line-height:1.5">
This account is now in the upload pool and will be used for file uploads.
</p>
<label style="margin-top:20px">String Session (store safely)</label>
<div class="session-out" id="sessionOut"></div>
<button onclick="location.reload()"
style="margin-top:18px;background:#21262d;border:1px solid var(--border)">
+ Add Another Account
</button>
</div>
<footer>Powered by GramJS · Node.js · MongoDB</footer>
</div>
<script>
const $ = id => document.getElementById(id);
function setStep(n) {
['p1','p2','p3'].forEach((id,i) => $(id).classList.toggle('hidden', i+1 !== n));
['s1','s2','s3'].forEach((id,i) => $(id).classList.toggle('on', i < n));
}
function msg(id, text, type) {
const el = $(id);
el.textContent = text;
el.className = 'msg ' + (type === 'ok' ? 'ok' : 'err');
}
let pendingPhone = '';
$('btnCode').addEventListener('click', async () => {
const btn = $('btnCode');
btn.disabled = true; btn.textContent = 'Sending…';
msg('m1', '', '');
const body = {
apiId: $('apiId').value.trim(),
apiHash: $('apiHash').value.trim(),
phone: $('phone').value.trim(),
};
if (!body.apiId || !body.apiHash || !body.phone) {
msg('m1', 'All three fields are required.', 'err');
btn.disabled = false; btn.textContent = 'Send OTP →';
return;
}
try {
const r = await fetch('/strings/send-code', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
const d = await r.json();
if (!r.ok) throw new Error(d.error);
pendingPhone = body.phone;
setStep(2);
} catch(e) {
msg('m1', e.message, 'err');
btn.disabled = false; btn.textContent = 'Send OTP →';
}
});
$('btnVerify').addEventListener('click', async () => {
const btn = $('btnVerify');
btn.disabled = true; btn.textContent = 'Verifying…';
msg('m2', '', '');
const body = { phone: pendingPhone, code: $('otp').value.trim() };
const pw = $('twoFA').value.trim();
if (pw) body.password = pw;
try {
const r = await fetch('/strings/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
const d = await r.json();
if (d.twoFA) {
$('twoFAWrap').classList.remove('hidden');
msg('m2', '2FA required — enter your cloud password above and try again.', 'err');
btn.disabled = false; btn.textContent = 'Verify & Save →';
return;
}
if (!r.ok) throw new Error(d.error);
$('sessionOut').textContent = d.session || '';
setStep(3);
} catch(e) {
msg('m2', e.message, 'err');
btn.disabled = false; btn.textContent = 'Verify & Save →';
}
});
</script>
</body>
</html>