diff --git a/sites/shkor-com/api.py b/sites/shkor-com/api.py index 5355721..60b0bdc 100644 --- a/sites/shkor-com/api.py +++ b/sites/shkor-com/api.py @@ -10,7 +10,7 @@ POST /api/account/login JSON email -> magic link by email (only for existing orders) GET /api/account/session?k=|t= -> session cookie (30 days) -> redirect /account/ GET /api/account/me cabinet: order status, workspace, level ladder, project, products, earnings - POST /api/account/{agreement,project,product,product-live,chat,logout} + POST /api/account/{agreement,project,product,product-live,logout} Env: SHKOR_DB sqlite path (default /var/lib/shkor-subscribe/subs.db) @@ -479,8 +479,6 @@ def acc_action(email, action, d, ip): elif action == "product": body.update(name=clean(d, "name", 120), price_usd=d.get("price_usd"), interval=clean(d, "interval", 12), description=clean(d, "description", 300)) - elif action == "chat": - body.update(text=str(d.get("text") or "").strip()[:8000]) elif action == "product-live": body.update(product_id=d.get("product_id"), note=clean(d, "note", 1000)) else: @@ -594,7 +592,7 @@ class H(BaseHTTPRequestHandler): email = acc_email(self.sid()) if not email: return self.reply(401, {"error": "Please sign in."}) - if limited("chat" if action == "chat" else "acc", self.ip(), 1500 if action == "chat" else 120): + if limited("acc", self.ip(), 120): return self.reply(429, {"error": "Too many requests — slow down a little."}) return self.reply(*acc_action(email, action, d, self.ip())) if path in ("/api/autopilot/start", "/api/autopilot/checkout"): diff --git a/sites/shkor-com/v2/account/index.html b/sites/shkor-com/v2/account/index.html index c0f4c6b..7ccd3db 100644 --- a/sites/shkor-com/v2/account/index.html +++ b/sites/shkor-com/v2/account/index.html @@ -42,13 +42,6 @@ .ok-msg{color:var(--acid);font-size:14px;min-height:20px;margin-top:10px} .muted{color:var(--fg-3);font-size:14px} .topbar{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap} -.chat{display:flex;flex-direction:column;gap:10px;max-height:420px;overflow-y:auto;margin-top:14px;padding:14px;border-radius:14px;background:rgba(0,0,0,.25);box-shadow:inset 0 0 0 1px var(--line-2)} -.msg{max-width:82%;padding:10px 14px;border-radius:14px;font-size:15px;line-height:1.5;white-space:pre-wrap;word-wrap:break-word;color:var(--fg)} -.msg.me{align-self:flex-end;background:rgba(198,255,77,.14);box-shadow:inset 0 0 0 1px rgba(198,255,77,.3)} -.msg.ag{align-self:flex-start;background:rgba(255,255,255,.05);box-shadow:inset 0 0 0 1px var(--line-2)} -.msg small{display:block;margin-top:4px;font:11px var(--mono);color:var(--fg-3)} -.chat-in{display:flex;gap:10px;margin-top:12px}.chat-in textarea{flex:1;min-height:50px;max-height:160px;resize:vertical;padding:12px 14px;border:0;border-radius:12px;color:var(--fg);font:15px/1.5 var(--body);background:rgba(255,255,255,.035);box-shadow:inset 0 0 0 1px var(--line-2)} -.chat-in textarea:focus{outline:none;box-shadow:inset 0 0 0 1px var(--acid)}
@@ -124,10 +117,6 @@ } // workspace if (d.panel) h += 'Claude Code (your own Claude account) and OpenCode, both connected to the lab MCP.
Your Simbiot agent runs on your server around the clock. Ask it anything or give it a task — it usually replies within a minute.
' - + 'Loading…
Sales through the cooperative’s payments. The studio share is withheld automatically at each payment.
' @@ -188,28 +177,6 @@ bind(); } - var chatSig = ''; - function drawChat(r) { - var box = document.getElementById('chat'); if (!box) return; - var msgs = (r && r.messages) || [], sig = msgs.length + ':' + (msgs.length ? msgs[msgs.length - 1].id : ''); - if (sig === chatSig) return; chatSig = sig; - var atBottom = box.scrollHeight - box.scrollTop - box.clientHeight < 40; - box.innerHTML = msgs.length ? msgs.map(function (m) { - var t = new Date(m.ts).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); - return 'No messages yet — say hi to your agent.
'; - if (atBottom || msgs.length && msgs[msgs.length - 1].from !== 'agent') box.scrollTop = box.scrollHeight; - } - function chat(text) { - return api('/api/account/chat', text ? { text: text } : {}).then(function (r) { - if (r.status === 401) return loginView('Your session expired — sign in again.'); - var err = document.getElementById('cerr'); - if (!r.ok) { if (err) err.textContent = r.j.error || 'Chat is unavailable right now.'; return; } - if (err) err.textContent = ''; drawChat(r.j); - }); - } - setInterval(function () { if (!document.hidden && document.getElementById('chat')) chat(''); }, 5000); - function act(path, body, form) { var err = form.querySelector('.form-err'), btn = form.querySelector('button[type=submit]'); err.textContent = ''; btn.disabled = true; @@ -233,12 +200,6 @@ var fr = document.getElementById('fr'); if (fr) fr.addEventListener('submit', function (e) { e.preventDefault(); act('product', { name: document.getElementById('rn').value.trim(), price_usd: Number(document.getElementById('rp').value), interval: document.getElementById('ri').value }, fr); }); document.querySelectorAll('.fl').forEach(function (f) { f.addEventListener('submit', function (e) { e.preventDefault(); act('product-live', { product_id: Number(f.dataset.id), note: f.querySelector('.fl-note').value.trim() }, f); }); }); - var cf = document.getElementById('cf'), ct = document.getElementById('ct'); - if (cf) { - chatSig = ''; chat(''); - cf.addEventListener('submit', function (e) { e.preventDefault(); var t = ct.value.trim(); if (!t) return; ct.value = ''; chat(t); }); - ct.addEventListener('keydown', function (e) { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); cf.requestSubmit(); } }); - } document.querySelectorAll('[data-copy]').forEach(function (b) { b.addEventListener('click', function () { navigator.clipboard && navigator.clipboard.writeText(b.dataset.copy); b.textContent = 'Copied'; }); }); }