/// declare const PluginBase: IPluginBase; const SpotifyPlayerUrl = "https://play.spotify.com/"; const SpotifyPlayerUrlMatch = "*://*.spotify.com/*"; const SpotifyPlayerUrlRegexMatch = /.*\.spotify\.com/; const enum SpotifyControlButtons { Next = 'button[data-testid="control-button-skip-forward"]', Play = 'button[data-testid="control-button-play"]', Previous = 'button[data-testid="control-button-skip-back"]', Pause = 'button[data-testid="control-button-pause"]', } function clickButton(selector: string): void { const btn = document.querySelector(selector); if (btn) btn.click(); } async function findSpotifyPlayerTabAsync(): Promise { return new Promise((res) => { return chrome.tabs.query({ url: SpotifyPlayerUrlMatch }, (tabs) => { res(tabs.length ? tabs[0] : null); }); }); } async function createSpotifyPlayerTabAsync(): Promise { return new Promise((res) => { return chrome.tabs.create({ url: SpotifyPlayerUrl }, (tab) => { return res(tab); }); }); } async function sendSpotifyControlMessage( control: SpotifyControlButtons, _tab: chrome.tabs.Tab | null = null ): Promise { const tab = _tab || (await findSpotifyPlayerTabAsync()); return new Promise((resolve) => { if (tab && tab.id) { return chrome.tabs.sendMessage( tab.id, { type: "postMessage", control }, () => { resolve(true); } ); } resolve(false); }); } export default { ...PluginBase, ...{ niceName: "Spotify", description: "An experimental plugin for spotify.com", match: SpotifyPlayerUrlRegexMatch, version: "0.0.9", apiVersion: 2, authors: "Ahmed Kamal", init: function () { if (SpotifyPlayerUrlRegexMatch.test(window.location.origin)) { chrome.runtime.onMessage.addListener((msg, _, sendResponse) => { if (msg.type === "postMessage") { switch (msg.control) { case SpotifyControlButtons.Play: { clickButton(SpotifyControlButtons.Play); break; } case SpotifyControlButtons.Pause: clickButton(SpotifyControlButtons.Pause); break; case SpotifyControlButtons.Next: clickButton(SpotifyControlButtons.Next); break; case SpotifyControlButtons.Previous: clickButton(SpotifyControlButtons.Previous); break; default: break; } sendResponse(null); } }); } }, commands: [ { name: "spotify play", description: "Play the Spotify web player.", global: true, match: "spotify play", fn: async function () { let tab = await findSpotifyPlayerTabAsync(); if (!tab) { const msg = "Spotify player seems to be closed, do you want me to open it?"; if (prompt(msg, "yes") === "yes") { tab = await createSpotifyPlayerTabAsync(); } } await sendSpotifyControlMessage(SpotifyControlButtons.Play, tab); }, }, { name: "spotify pause", description: "Pause the Spotify web player.", global: true, match: "spotify pause", fn: async function () { await sendSpotifyControlMessage(SpotifyControlButtons.Pause); }, }, { name: "spotify next", description: "Moves to the next song on the Spotify web player.", global: true, match: "spotify next", fn: async function () { await sendSpotifyControlMessage(SpotifyControlButtons.Next); }, }, { name: "spotify previous", description: "Moves to the previous song on the Spotify web player.", global: true, match: "spotify previous", fn: async function () { await sendSpotifyControlMessage(SpotifyControlButtons.Previous); }, }, ], }, };