diff --git a/extension/spotiqueue.js b/extension/spotiqueue.js
index bad7d01..da999b1 100644
--- a/extension/spotiqueue.js
+++ b/extension/spotiqueue.js
@@ -1,5 +1,4 @@
-const DEFAULT_WS_URL =
- localStorage.getItem("spotiqueueUrl") ?? "ws://localhost:8000/ws/spotify";
+const DEFAULT_WS_URL = "ws://localhost:8000/ws/spotify";
const DEFAULT_RECONNECT_MS = 1000;
class SpotiQueue {
@@ -73,16 +72,14 @@ class SpotiQueue {
this.socket = null;
}
- if (this.button) this.button.style.color = "#e22134";
console.log("[SpotiQueue] Disconnecting from server, Bye!");
}
send(objOrString) {
if (!this.socket || this.socket.readyState !== WebSocket.OPEN) return;
- const payload =
- typeof objOrString === "string"
- ? objOrString
- : JSON.stringify(objOrString);
+ const payload = (typeof objOrString === "string")
+ ? objOrString
+ : JSON.stringify(objOrString);
try {
this.socket.send(payload);
} catch (err) {
@@ -114,19 +111,14 @@ class SpotiQueue {
return;
}
- if (data.c === "next_song") {
- if (data.d && data.d.song) {
- try {
- Spicetify.Player.playUri(data.d.song);
- Spicetify.Player.setRepeat(false);
- this.startedPlaying = true;
- console.log("[SpotiQueue] New song received!");
- } catch (err) {
- console.error("[SpotiQueue] Error playing received song:", err);
- }
- } else {
- Spicetify.Player.play();
+ if (data.c === "next_song" && data.d && data.d.song) {
+ try {
+ Spicetify.Player.playUri(data.d.song);
+ Spicetify.Player.setRepeat(false);
this.startedPlaying = true;
+ console.log("[SpotiQueue] New song received!");
+ } catch (err) {
+ console.error("[SpotiQueue] Error playing received song:", err);
}
}
@@ -149,6 +141,7 @@ class SpotiQueue {
includeAuthors: true,
});
+ console.log(data)
songs = data.searchV2.tracksV2.items.reduce((o, c) => {
const item = c.item.data;
@@ -158,12 +151,14 @@ class SpotiQueue {
o.push({
name: item.name,
uri: item.uri,
- artists: item.artists.items.map((v) => v.profile?.name),
+ artists: item.artists.items.map(v => v.profile?.name),
album: {
name: album.name,
- coverUrl: album.coverArt.sources
- .sort((a, b) => b.height - a.height)
- .map((v) => v.url)[0],
+ coverUrl: album.coverArt.sources.sort((a, b) =>
+ b.height - a.height
+ ).map((v) =>
+ v.url
+ )[0],
},
});
@@ -176,17 +171,16 @@ class SpotiQueue {
console.log("[SpotiQueue] Found", songs);
this.send({
- c: "search",
- d: {
- id: id,
- results: songs,
+ "c": "search",
+ "d": {
+ "id": id,
+ "results": songs,
},
});
}
}
- _onError(e) {
+ _onError() {
try {
- console.log(e);
if (this.socket) this.socket.close();
} catch {
// ignore
@@ -199,7 +193,6 @@ class SpotiQueue {
this.reconnectInterval,
this.closing,
);
-
if (!this.reconnectInterval && !this.closing) {
this.reconnectInterval = setInterval(
() => this.connect(),
@@ -207,68 +200,35 @@ class SpotiQueue {
);
}
- if (this.button && !this.closing) {
- this.button.style.color = "";
- }
-
+ if (this.button) this.button.style.color = "";
this.closing = false;
}
initUi() {
- const btn = new Spicetify.Topbar.Button("SpotiQueue", "enhance", () => {});
+ const btn = new Spicetify.Topbar.Button(
+ "SpotiQueue",
+ `
hi
`, // SVG icon or markup
+ () => {
+ if (!this.socket) {
+ if (Spicetify.GraphQL.Definitions.searchDesktop === undefined) {
+ Spicetify.showNotification("Please search something (e.g a song) before trying to use SpotiQueue. This will load required dependencies.")
+ return
+ }
+ this.connect();
+ this.button.innerText = "bye";
+ } else {
+ this.stop();
+ this.button.innerText = "hi";
+ }
+ },
+ );
this.button = btn.button;
- this.button.style.color = "#e22134";
- this.button.addEventListener("click", (e) => {
- console.log(e.pointerId);
- if (this.socket) {
- this.stop();
- return;
- }
-
- if (Spicetify.GraphQL.Definitions.searchDesktop === undefined) {
- Spicetify.Platform.History.push("/search/");
- setTimeout(() => {
- this.button.click();
- Spicetify.Platform.History.goBack();
- }, 200);
- return;
- }
-
- this.closing = false;
- this.button.style.color = "";
- this.connect();
- });
- this.button.addEventListener("contextmenu", (e) => {
- e.preventDefault();
-
- const div = document.createElement("div");
- div.innerHTML = `
-
-
-
-
- `;
- Spicetify.PopupModal.display({ title: "WebSocket URL", content: div });
-
- div.querySelector("input").value = this.wsUrl
- div.querySelector("button").onclick = () => {
- const newUrl = div.querySelector("input").value.trim();
- if (!newUrl) return;
-
- localStorage.setItem("spotiqueueUrl", newUrl);
- this.wsUrl = newUrl;
- this.stop();
- Spicetify.PopupModal.hide();
- Spicetify.showNotification("Saved!");
- };
- });
Spicetify.Player.addEventListener("songchange", (info) => {
console.log(info);
if (
- this.socket &&
- this.socket.readyState === WebSocket.OPEN &&
+ this.socket && this.socket.readyState === WebSocket.OPEN &&
!this.startedPlaying
) {
Spicetify.Player.pause();
@@ -282,17 +242,14 @@ class SpotiQueue {
(function init() {
if (
- !Spicetify.Player ||
- !Spicetify.Platform ||
- !Spicetify.GraphQL ||
- !Spicetify.GraphQL.Request ||
- !Spicetify.GraphQL.Definitions
+ !Spicetify.Player || !Spicetify.Platform || !Spicetify.GraphQL ||
+ !Spicetify.GraphQL.Request || !Spicetify.GraphQL.Definitions
) {
setTimeout(init, 100);
console.log("[SpotiQueue] loading extension... ");
return;
}
- globalThis.spotiQueue = new SpotiQueue();
- globalThis.spotiQueue.initUi();
+ const client = new SpotiQueue();
+ client.initUi();
})();
diff --git a/src/main.ts b/src/main.ts
index 55eb43c..e82b581 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,11 +1,12 @@
import { SpotifyWS } from "./spotify.ts"
import { HeartbeatWS } from "./heartbeat.ts";
import { PlayerManager } from "./playerManager.ts";
-import { serveDir } from "@std/http/file-server";
+import { serveFile } from "@std/http/file-server";
import { UserWS } from "./user.ts";
const USER_PATTERN = new URLPattern({pathname: "/ws/user"})
const SPOTIFY_PATTERN = new URLPattern({pathname: "/ws/spotify"})
+const song = "spotify:track:2VxJVGiTsK6UyrxPJJ2lR9";
function commonWs(req: Request) {
const { socket, response } = Deno.upgradeWebSocket(req);
@@ -32,11 +33,11 @@ Deno.serve((req) => {
const spState = spotify?.ws.readyState;
if (spState !== undefined && spState !== WebSocket.CLOSED) spotify?.ws.close();
- new SpotifyWS(socket);
+ spotify = new SpotifyWS(socket, () => song);
new HeartbeatWS(socket);
return response
}
- return serveDir(req, {fsRoot: "./static", urlRoot: ""})
+ return serveFile(req, "./static/index.html")
})
diff --git a/src/playerManager.ts b/src/playerManager.ts
index acfee68..0b404bd 100644
--- a/src/playerManager.ts
+++ b/src/playerManager.ts
@@ -58,11 +58,6 @@ export class PlayerManager {
return song.song;
}
- public broadcastStatus() {
- for (const user of Object.values(this.userQueue)) {
- user.userWS.updateStatus();
- }
- }
public updateMergedQueue() {
this.generateMergedQueue();
this.broadcastMergedQueue();
@@ -74,7 +69,7 @@ export class PlayerManager {
}
private broadcastMergedQueue() {
for (const user of Object.values(this.userQueue)) {
- user.userWS.updateQueue();
+ user.userWS.broadcastQueue(this.mergedQueue);
}
}
diff --git a/src/spotify.ts b/src/spotify.ts
index 9611c16..d224219 100644
--- a/src/spotify.ts
+++ b/src/spotify.ts
@@ -22,10 +22,7 @@ export class SpotifyWS {
this.onMessage = this.onMessage.bind(this);
this.onClose = this.onClose.bind(this);
- this.onOpen = this.onOpen.bind(this);
-
this.ws.addEventListener("message", this.onMessage);
- this.ws.addEventListener("open", this.onOpen);
this.ws.addEventListener("close", this.onClose);
}
@@ -46,10 +43,7 @@ export class SpotifyWS {
public sendSong(uri?: string) {
const song = uri ?? playerManager.getNext()?.uri;
- if (!song) {
- this.send(buildCommand("next_song"));
- return
- };
+ if (!song) return;
this.send(buildCommand("next_song", { song }));
}
@@ -59,13 +53,8 @@ export class SpotifyWS {
this.ws.send(data);
}
- private onOpen() {
- globalThis.spotify = this;
- playerManager.broadcastStatus();
- }
private onClose() {
globalThis.spotify = undefined;
- playerManager.broadcastStatus();
}
private onMessage(msg: MessageEvent) {
const text = msg.data;
diff --git a/src/user.ts b/src/user.ts
index 4d52667..47448fc 100644
--- a/src/user.ts
+++ b/src/user.ts
@@ -23,23 +23,24 @@ export class UserWS {
this.ws.send(buildCommand("logout"))
this.ws.close();
}
+ public broadcastQueue(queue: MergedQueue) {
+ this.ws.send(buildCommand("updatemergedqueue", {queue}))
+ }
public updateQueue() {
const queue = this.playerQueue?.queue;
if (!queue) return;
- this.ws.send(buildCommand("getqueue", {personal: queue, merged: playerManager.mergedQueue }))
- }
- public updateStatus() {
- this.ws.send(buildCommand("status", {status: spotify !== undefined}))
+ this.ws.send(buildCommand("getqueue", {queue}))
}
+ private spotifyConnected(): boolean {
+ return spotify === undefined;
+ }
private login(name: string) {
this.name = name;
this.loggedIn = true;
this.playerQueue = playerManager.login(name, this);
- this.updateQueue();
- this.updateStatus();
}
private async onMessage(msg: MessageEvent) {
const command = parseCommand(msg.data);
@@ -72,11 +73,12 @@ export class UserWS {
const cmd = command as Command<{query: string}>;
- let songs = await spotify?.search(cmd.d.query).catch(_ => console.log("Failed to search..."))
+ const songs = await spotify?.search(cmd.d.query)
if (songs === undefined) {
- songs = []
- }
- this.ws.send(buildCommand("search", {songs}))
+ this.ws.send(buildCommand("search", {songs: [], connected: false}))
+ } else {
+ this.ws.send(buildCommand("search", {songs, connected: true}))
+ }
break
}
@@ -102,11 +104,6 @@ export class UserWS {
this.playerQueue.queue.push(cmd.d.song);
playerManager.updateMergedQueue();
- break
- }
- case "status": {
- this.updateStatus();
- break
}
}
}
diff --git a/static/index.html b/static/index.html
index 6f37483..bca5d1a 100644
--- a/static/index.html
+++ b/static/index.html
@@ -1,543 +1,352 @@
-
+
-
- SpotiQueue
-
-
+ Spotify Queue
+
-
-
-
+
+
Enter your name
+
+
-
-
-
-
-
-
+
+
+ Spotify Queue
+
+
-
-
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
My Queue
+
-
-
-
-
-
-