website/src/models/Lanyard.ts
2025-04-19 23:51:55 -05:00

77 lines
No EOL
1.6 KiB
TypeScript

import type {
AnyLanyardPayload,
LanyardInitStatePayload,
LanyardPayload,
LanyardPresence,
LanyardPresenceUpdatePayload
} from "types/lanyard";
export class Lanyard {
private socket: WebSocket;
private readonly userId: string;
private readonly updateCallback: (presence: LanyardPresence) => void;
private heartbeatInterval?: number;
constructor(
userId: string,
updateCallback: (presence: LanyardPresence) => void
) {
this.userId = userId;
this.updateCallback = updateCallback;
this.socket = new WebSocket("wss://api.lanyard.rest/socket");
this.initialize();
}
private send(data: AnyLanyardPayload) {
this.socket.send(JSON.stringify(data));
}
private initialize() {
this.socket.onmessage = event => {
const payload: LanyardPayload = JSON.parse(event.data);
switch (payload.op) {
case 1: {
// Initialize
this.send({
op: 2,
d: {
subscribe_to_ids: [this.userId]
}
});
this.send({ op: 3 });
const interval =
"heartbeat_interval" in payload.d
? payload.d.heartbeat_interval
: 30000;
this.heartbeatInterval = window.setInterval(() => {
this.send({ op: 3 });
}, interval);
break;
}
case 0: {
const typedPayload = payload as
| LanyardInitStatePayload
| LanyardPresenceUpdatePayload;
const presence =
typedPayload.t === "INIT_STATE"
? typedPayload.d[this.userId]
: typedPayload.d;
this.updateCallback(presence);
break;
}
}
};
}
public close() {
if (this.heartbeatInterval) {
clearInterval(this.heartbeatInterval);
}
this.socket.close();
}
}