Spaces:
Paused
Paused
Download web/src/ws.js from secutorpro/dispatch-console: direct link, hf CLI and curl.
- Browser
- Download file 2.51 kB
-
https://huggingface.co/spaces/secutorpro/dispatch-console/resolve/main/web/src/ws.js
- Command line
-
hf download hf://spaces/secutorpro/dispatch-console/web/src/ws.js
-
curl -L -o ws.js https://huggingface.co/spaces/secutorpro/dispatch-console/resolve/main/web/src/ws.js
2.51 kB
| import { getToken } from './api.js'; | |
| const HDR = 9; // type(1) + groupId(4) + memberId(4) | |
| const AUDIO = 0x01; | |
| export class DispatchSocket { | |
| constructor(handlers) { | |
| this.handlers = handlers; | |
| this.closed = false; | |
| this.retries = 0; | |
| this.connect(); | |
| } | |
| connect() { | |
| const proto = location.protocol === 'https:' ? 'wss' : 'ws'; | |
| this.ws = new WebSocket(`${proto}://${location.host}/ws`); | |
| this.ws.binaryType = 'arraybuffer'; | |
| this.ws.onopen = () => { | |
| this.retries = 0; | |
| this.ws.send(JSON.stringify({ type: 'auth', token: getToken() })); | |
| this.handlers.onStatus?.(true); | |
| }; | |
| this.ws.onmessage = (ev) => { | |
| if (typeof ev.data === 'string') { | |
| let msg; | |
| try { msg = JSON.parse(ev.data); } catch { return; } | |
| switch (msg.type) { | |
| case 'welcome': this.handlers.onWelcome?.(msg); break; | |
| case 'members': this.handlers.onMembers?.(msg.members); break; | |
| case 'groups': this.handlers.onGroups?.(msg.groups); break; | |
| case 'sos_new': this.handlers.onSosNew?.(msg.alert); break; | |
| case 'sos_update': this.handlers.onSosUpdate?.(msg.alert); break; | |
| case 'floor': this.handlers.onFloor?.(msg); break; | |
| case 'error': console.warn('[ws]', msg.message); break; | |
| } | |
| } else if (ev.data instanceof ArrayBuffer && ev.data.byteLength > HDR) { | |
| const dv = new DataView(ev.data); | |
| if (dv.getUint8(0) !== AUDIO) return; | |
| this.handlers.onAudio?.({ | |
| groupId: dv.getUint32(1), | |
| memberId: dv.getUint32(5), | |
| pcm: ev.data.slice(HDR), | |
| }); | |
| } | |
| }; | |
| this.ws.onclose = () => { | |
| this.handlers.onStatus?.(false); | |
| if (this.closed) return; | |
| const delay = Math.min(10000, 500 * 2 ** this.retries++); | |
| setTimeout(() => this.connect(), delay); | |
| }; | |
| this.ws.onerror = () => this.ws.close(); | |
| } | |
| send(obj) { | |
| if (this.ws?.readyState === WebSocket.OPEN) this.ws.send(JSON.stringify(obj)); | |
| } | |
| sendAudio(groupId, memberId, int16buffer) { | |
| if (this.ws?.readyState !== WebSocket.OPEN) return; | |
| const head = new Uint8Array(HDR); | |
| const dv = new DataView(head.buffer); | |
| dv.setUint8(0, AUDIO); | |
| dv.setUint32(1, groupId); | |
| dv.setUint32(5, memberId); | |
| const body = new Uint8Array(int16buffer); | |
| const out = new Uint8Array(HDR + body.byteLength); | |
| out.set(head); | |
| out.set(body, HDR); | |
| this.ws.send(out); | |
| } | |
| close() { | |
| this.closed = true; | |
| this.ws?.close(); | |
| } | |
| } |