82 lines
2 KiB
TypeScript
82 lines
2 KiB
TypeScript
import { buildCommand, type Command, type BaseCommand, parseCommand } from "./commandBuilder.ts";
|
|
|
|
type GetSong = () => string | null;
|
|
export type Song = {
|
|
name: string;
|
|
uri: string;
|
|
artists: string[];
|
|
album: {
|
|
name: string;
|
|
coverUrl: string | undefined;
|
|
};
|
|
};
|
|
|
|
export class SpotifyWS {
|
|
public ws: WebSocket;
|
|
private queryList: {
|
|
[x: string]: (value: Song[] | PromiseLike<Song[]>) => void;
|
|
} = {};
|
|
|
|
constructor(ws: WebSocket) {
|
|
this.ws = ws;
|
|
|
|
this.onMessage = this.onMessage.bind(this);
|
|
this.onClose = this.onClose.bind(this);
|
|
this.ws.addEventListener("message", this.onMessage);
|
|
this.ws.addEventListener("close", this.onClose);
|
|
}
|
|
|
|
public search(query: string): Promise<Song[]> {
|
|
return new Promise<Song[]>((resolve, reject) => {
|
|
if (this.ws.readyState != this.ws.OPEN) reject("WS Isn't connected.");
|
|
|
|
const id = crypto.randomUUID();
|
|
this.send(buildCommand("search", { query, id }));
|
|
this.queryList[id] = resolve;
|
|
|
|
setTimeout(() => {
|
|
reject("Timeout.");
|
|
delete this.queryList[id];
|
|
}, 3000);
|
|
});
|
|
}
|
|
|
|
public sendSong(uri?: string) {
|
|
const song = uri ?? playerManager.getNext()?.uri;
|
|
if (!song) return;
|
|
|
|
this.send(buildCommand("next_song", { song }));
|
|
}
|
|
|
|
private send(data: string) {
|
|
if (this.ws.readyState != this.ws.OPEN) return;
|
|
this.ws.send(data);
|
|
}
|
|
|
|
private onClose() {
|
|
globalThis.spotify = undefined;
|
|
}
|
|
private onMessage(msg: MessageEvent<string>) {
|
|
const text = msg.data;
|
|
const parsed = parseCommand(text);
|
|
|
|
if (parsed === null) return;
|
|
|
|
switch (parsed.c) {
|
|
case "next_song":
|
|
this.sendSong();
|
|
break;
|
|
|
|
case "search": {
|
|
if (!parsed.d || !parsed.d.id || !parsed.d.results) break;
|
|
const cmd = parsed as Command<{id: string, results: Song[]}>
|
|
|
|
const { id, results } = cmd.d;
|
|
if (!(id in this.queryList)) break;
|
|
|
|
this.queryList[id](results);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|