feat(web): update SPA to use unified command endpoint

- Session creation uses /session instead of /register
- JOIN/PART via POST /messages with command field
- NICK changes via POST /messages with NICK command
- Messages sent as PRIVMSG commands with body array
- DMs use PRIVMSG command format
This commit is contained in:
clawbot
2026-02-10 17:53:17 -08:00
parent d06bb5334a
commit af3a26fcdf

View File

@@ -51,7 +51,7 @@ function LoginScreen({ onLogin }) {
e.preventDefault(); e.preventDefault();
setError(''); setError('');
try { try {
const res = await api('/register', { const res = await api('/session', {
method: 'POST', method: 'POST',
body: JSON.stringify({ nick: nick.trim() }) body: JSON.stringify({ nick: nick.trim() })
}); });
@@ -201,7 +201,7 @@ function App() {
name = name.trim(); name = name.trim();
if (!name.startsWith('#')) name = '#' + name; if (!name.startsWith('#')) name = '#' + name;
try { try {
await api('/channels/join', { method: 'POST', body: JSON.stringify({ channel: name }) }); await api('/messages', { method: 'POST', body: JSON.stringify({ command: 'JOIN', to: name }) });
setTabs(prev => { setTabs(prev => {
if (prev.find(t => t.type === 'channel' && t.name === name)) return prev; if (prev.find(t => t.type === 'channel' && t.name === name)) return prev;
return [...prev, { type: 'channel', name }]; return [...prev, { type: 'channel', name }];
@@ -215,9 +215,8 @@ function App() {
}; };
const partChannel = async (name) => { const partChannel = async (name) => {
const chName = name.replace('#', '');
try { try {
await api(`/channels/${chName}`, { method: 'DELETE' }); await api('/messages', { method: 'POST', body: JSON.stringify({ command: 'PART', to: name }) });
} catch (err) { /* ignore */ } } catch (err) { /* ignore */ }
setTabs(prev => { setTabs(prev => {
const next = prev.filter(t => !(t.type === 'channel' && t.name === name)); const next = prev.filter(t => !(t.type === 'channel' && t.name === name));
@@ -267,15 +266,21 @@ function App() {
const target = parts[1]; const target = parts[1];
const msg = parts.slice(2).join(' '); const msg = parts.slice(2).join(' ');
try { try {
await api('/messages', { method: 'POST', body: JSON.stringify({ to: target, content: msg }) }); await api('/messages', { method: 'POST', body: JSON.stringify({ command: 'PRIVMSG', to: target, body: [msg] }) });
openDM(target); openDM(target);
} catch (err) { } catch (err) {
addSystemMessage('server', `Failed to send DM: ${err.data?.error || 'error'}`); addSystemMessage('server', `Failed to send DM: ${err.data?.error || 'error'}`);
} }
return; return;
} }
if (cmd === '/nick') { if (cmd === '/nick' && parts[1]) {
addSystemMessage('server', 'Nick changes not yet supported'); try {
await api('/messages', { method: 'POST', body: JSON.stringify({ command: 'NICK', body: [parts[1]] }) });
setNick(parts[1]);
addSystemMessage('server', `Nick changed to ${parts[1]}`);
} catch (err) {
addSystemMessage('server', `Nick change failed: ${err.data?.error || 'error'}`);
}
return; return;
} }
addSystemMessage('server', `Unknown command: ${cmd}`); addSystemMessage('server', `Unknown command: ${cmd}`);
@@ -284,7 +289,7 @@ function App() {
const to = tab.type === 'channel' ? tab.name : tab.name; const to = tab.type === 'channel' ? tab.name : tab.name;
try { try {
await api('/messages', { method: 'POST', body: JSON.stringify({ to, content: text }) }); await api('/messages', { method: 'POST', body: JSON.stringify({ command: 'PRIVMSG', to, body: [text] }) });
} catch (err) { } catch (err) {
addSystemMessage(tab.name, `Send failed: ${err.data?.error || 'error'}`); addSystemMessage(tab.name, `Send failed: ${err.data?.error || 'error'}`);
} }