diff --git a/package.json b/package.json index f3a18b8..d0bf445 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "homepage": "https://github.com/Mastermindzh/tidal-hifi", "license": "MIT", "dependencies": { + "discord-rpc": "^3.2.0", "electron-store": "^5.1.1", "express": "^4.17.1", "hotkeys-js": "^3.7.6", diff --git a/src/constants/settings.js b/src/constants/settings.js index 593e9f8..f8ec0f0 100644 --- a/src/constants/settings.js +++ b/src/constants/settings.js @@ -20,6 +20,7 @@ const settings = { mpris: "mpris", enableCustomHotkeys: "enableCustomHotkeys", trayIcon: "trayIcon", + enableDiscord: "enableDiscord", windowBounds: { root: "windowBounds", width: "windowBounds.width", diff --git a/src/main.js b/src/main.js index 686844c..28ca3c7 100644 --- a/src/main.js +++ b/src/main.js @@ -9,14 +9,15 @@ const { } = require("./scripts/settings"); const { addTray, refreshTray } = require("./scripts/tray"); const { addMenu } = require("./scripts/menu"); - const path = require("path"); const tidalUrl = "https://listen.tidal.com"; const expressModule = require("./scripts/express"); const mediaKeys = require("./constants/mediaKeys"); const mediaInfoModule = require("./scripts/mediaInfo"); +const discordModule = require("./scripts/discord"); const globalEvents = require("./constants/globalEvents"); + let mainWindow; let icon = path.join(__dirname, "../assets/icon.png"); @@ -85,6 +86,7 @@ app.on("ready", () => { addGlobalShortcuts(); store.get(settings.trayIcon) && addTray({ icon }) && refreshTray(); store.get(settings.api) && expressModule.run(mainWindow); + store.get(settings.enableDiscord) && discordModule.initRPC(); }); app.on("activate", function () { @@ -113,6 +115,12 @@ ipcMain.on(globalEvents.updateStatus, (event, arg) => { }); ipcMain.on(globalEvents.storeChanged, (event, arg) => { mainWindow.setMenuBarVisibility(store.get(settings.menuBar)); + + if(store.get(settings.enableDiscord) && !discordModule.rpc) { + discordModule.initRPC(); + } else if(!store.get(settings.enableDiscord) && discordModule.rpc) { + discordModule.unRPC(); + } }); ipcMain.on(globalEvents.error, (event, arg) => { diff --git a/src/pages/settings/preload.js b/src/pages/settings/preload.js index 588e609..1a00065 100644 --- a/src/pages/settings/preload.js +++ b/src/pages/settings/preload.js @@ -20,6 +20,7 @@ function refreshSettings() { trayIcon.checked = store.get(settings.trayIcon); mpris.checked = store.get(settings.mpris); enableCustomHotkeys.checked = store.get(settings.enableCustomHotkeys); + enableDiscord.checked = store.get(settings.enableDiscord); } /** @@ -81,6 +82,7 @@ window.addEventListener("DOMContentLoaded", () => { trayIcon = get("trayIcon"); mpris = get("mprisCheckbox"); enableCustomHotkeys = get("enableCustomHotkeys"); + enableDiscord = get("enableDiscord"); refreshSettings(); @@ -92,4 +94,5 @@ window.addEventListener("DOMContentLoaded", () => { addInputListener(trayIcon, settings.trayIcon); addInputListener(mpris, settings.mpris); addInputListener(enableCustomHotkeys, settings.enableCustomHotkeys); + addInputListener(enableDiscord, settings.enableDiscord); }); diff --git a/src/pages/settings/settings.html b/src/pages/settings/settings.html index 6ff5252..124675a 100644 --- a/src/pages/settings/settings.html +++ b/src/pages/settings/settings.html @@ -141,6 +141,16 @@ +
+

Discord RPC

+

+ Show what you're listening to on Discord +

+ +
diff --git a/src/preload.js b/src/preload.js index 3f74362..3598013 100644 --- a/src/preload.js +++ b/src/preload.js @@ -12,13 +12,14 @@ const notificationPath = `${app.getPath("userData")}/notification.jpg`; let currentSong = ""; let player; + const elements = { play: '*[data-test="play"]', pause: '*[data-test="pause"]', next: '*[data-test="next"]', previous: 'button[data-test="previous"]', title: '*[data-test^="footer-track-title"]', - artists: '*[class^="mediaArtists"]', + artists: '*[class^="css-14o5h2y"]', home: '*[data-test="menu--home"]', back: '[class^="backwardButton"]', forward: '[class^="forwardButton"]', @@ -30,6 +31,7 @@ const elements = { settings: '*[data-test^="open-settings"]', media: '*[data-test="current-media-imagery"]', image: "img", + url: 'a[href*="/track/"]', /** * Get an element from the dom @@ -223,6 +225,7 @@ function updateStatus() { */ setInterval(function () { const title = elements.getText("title"); + const url = elements.get("url").href.replace(/[^0-9]/g, ''); const artists = elements.getText("artists"); const songDashArtistTitle = `${title} - ${artists}`; @@ -238,6 +241,7 @@ setInterval(function () { const options = { title, message: artists, + url: `https://tidal.com/browse/track/${url}` }; new Promise((resolve, reject) => { if (image.startsWith("http")) { diff --git a/src/scripts/discord.js b/src/scripts/discord.js new file mode 100644 index 0000000..cee1485 --- /dev/null +++ b/src/scripts/discord.js @@ -0,0 +1,52 @@ +const discordrpc = require("discord-rpc"); +const clientId = '833617820704440341'; +const mediaInfoModule = require("./mediaInfo"); + +const discordModule = []; + +let discord; +let rpc; + +const idleStatus = { + details: `Browsing Tidal`, + largeImageKey: 'tidal-hifi-icon', + largeImageText: 'Tidal HiFi 2.0.0', + instance: false, +} + +discordModule.initRPC = function () { + rpc = new discordrpc.Client({ transport: 'ipc' }); + rpc.login({ clientId }).catch(console.error); + discordModule.rpc = rpc; + + rpc.on('ready', () => { + rpc.setActivity(idleStatus); + }) + + discord = setInterval(() => { + if (mediaInfoModule.mediaInfo.status == 'paused' && rpc) { + rpc.setActivity(idleStatus); + } else if (rpc) { + rpc.setActivity({ + details: `Listening to ${mediaInfoModule.mediaInfo.title}`, + state: mediaInfoModule.mediaInfo.artist, + largeImageKey: 'tidal-hifi-icon', + largeImageText: 'Tidal HiFi 2.0.0', + buttons: [ + { label: "Play on Tidal", url: mediaInfoModule.mediaInfo.url } + ], + instance: false, + }); + } + }, 15e3); +} + +discordModule.unRPC = function () { + clearInterval(discord); + rpc.clearActivity(); + rpc.destroy(); + rpc = false; + discordModule.rpc = rpc; +} + +module.exports = discordModule; \ No newline at end of file diff --git a/src/scripts/mediaInfo.js b/src/scripts/mediaInfo.js index 79f6dc4..9641e14 100644 --- a/src/scripts/mediaInfo.js +++ b/src/scripts/mediaInfo.js @@ -5,6 +5,7 @@ const mediaInfo = { artist: "", icon: "", status: statuses.paused, + url: "" }; const mediaInfoModule = { mediaInfo, @@ -17,6 +18,7 @@ mediaInfoModule.update = function(arg) { mediaInfo.title = propOrDefault(arg.title); mediaInfo.artist = propOrDefault(arg.message); mediaInfo.icon = propOrDefault(arg.icon); + mediaInfo.url = propOrDefault(arg.url); }; /** diff --git a/src/scripts/settings.js b/src/scripts/settings.js index e04f4c5..d706810 100644 --- a/src/scripts/settings.js +++ b/src/scripts/settings.js @@ -17,6 +17,7 @@ const store = new Store({ trayIcon: true, mpris: false, enableCustomHotkeys: false, + enableDiscord: false, windowBounds: { width: 800, height: 600 }, }, });