diff options
| author | Elvis Claros Castro <elvis@claros.ar> | 2026-09-26 19:26:33 -0300 |
|---|---|---|
| committer | Elvis Claros Castro <elvis@claros.ar> | 2026-09-26 19:26:33 -0300 |
| commit | d80640d01eeb84907e36ff4af33add9081eda17c (patch) | |
| tree | 27698b34e06e28d111c2196700015d9c82f78274 /src/api/session.js | |
| download | wa-cli-d80640d01eeb84907e36ff4af33add9081eda17c.tar.gz wa-cli-d80640d01eeb84907e36ff4af33add9081eda17c.zip | |
Diffstat (limited to 'src/api/session.js')
| -rw-r--r-- | src/api/session.js | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/src/api/session.js b/src/api/session.js new file mode 100644 index 0000000..7def14d --- /dev/null +++ b/src/api/session.js @@ -0,0 +1,77 @@ +// auth.*, daemon.*, events.*: they work even when the session is not ready. + +import { WaError } from '../rpc.js'; + +export const EVENTS = [ + 'qr', 'code', 'authenticated', 'auth_failure', 'ready', 'disconnected', 'change_state', 'loading_screen', + 'message', 'message_create', 'message_ack', 'message_edit', 'message_revoke_everyone', 'message_revoke_me', + 'message_reaction', 'media_uploaded', 'unread_count', 'chat_archived', 'chat_removed', 'contact_changed', + 'group_join', 'group_leave', 'group_update', 'group_admin_changed', 'group_membership_request', + 'call', 'vote_update', +]; + +export default { + 'auth.status': { + description: 'WhatsApp session state (qr, code, authenticated, ready, ...) and linked account.', + ready: false, + handler: async (ctx) => ctx.status(), + }, + + 'auth.pair': { + description: 'Requests a pairing code by phone number (alternative to the QR). ' + + 'Enter it on the phone: Linked devices > Link with phone number instead.', + ready: false, + params: { + phone: { type: 'string', required: true, description: 'Number in international format, digits only (e.g. 5491122334455)' }, + notify: { type: 'boolean', default: true, description: 'Show a notification on the phone' }, + }, + handler: async (ctx, p) => { + const st = ctx.status().state; + if (st === 'ready' || st === 'authenticated') { + throw new WaError('EINVAL', 'the session is already linked'); + } + await ctx.waitState(['qr', 'code'], 60000); + const code = await ctx.client.requestPairingCode(p.phone.replace(/\D/g, ''), p.notify); + return { code }; + }, + }, + + 'auth.logout': { + description: 'Logs out (unlinks this device) and deletes the local session.', + handler: async (ctx) => { + await ctx.client.logout(); + return { ok: true }; + }, + }, + + 'daemon.status': { + description: 'Daemon process information.', + ready: false, + handler: async (ctx) => ctx.daemonInfo(), + }, + + 'daemon.stop': { + description: 'Stops the daemon (closes the browser; the session stays saved).', + ready: false, + handler: async (ctx) => { + setImmediate(() => ctx.shutdown('daemon.stop')); + return { ok: true }; + }, + }, + + 'events.watch': { + description: 'Real-time event stream (NDJSON). Each event: {event, account, time, data}.', + ready: false, + stream: true, + params: { + events: { type: 'array', default: ['message'], description: `Eventos a escuchar, o ["all"]. Disponibles: ${EVENTS.join(', ')}` }, + replay: { type: 'boolean', default: false, description: 'On connect, resend the current state (last qr/code, ready)' }, + }, + handler: async (ctx, p, conn) => { + const unknown = p.events.filter((e) => e !== 'all' && !EVENTS.includes(e)); + if (unknown.length) throw new WaError('EINVAL', `eventos desconocidos: ${unknown.join(', ')}`); + ctx.subscribe(conn, p.events.includes('all') ? null : new Set(p.events), p.replay); + return ctx.STREAM; + }, + }, +}; |