mirror of
https://github.com/Mastermindzh/tidal-hifi.git
synced 2024-11-22 21:42:46 +01:00
Merge pull request #42 from Mastermindzh/feature/improving-discord-integration-with-maroxy
Discord improvements with Mar0xy
This commit is contained in:
commit
148d1746ad
@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## 2.1.1
|
||||||
|
|
||||||
|
- The discord integration now doesn't send an update every 15 seconds it sends an update whenever the media info changes
|
||||||
|
- consolidated updating the media info changes with the status changes into a single global event
|
||||||
|
|
||||||
## 2.1.0
|
## 2.1.0
|
||||||
|
|
||||||
- [Mar0xy](https://github.com/Mar0xy) added Discord integration.
|
- [Mar0xy](https://github.com/Mar0xy) added Discord integration.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "tidal-hifi",
|
"name": "tidal-hifi",
|
||||||
"version": "2.1.0",
|
"version": "2.1.1",
|
||||||
"description": "Tidal on Electron with widevine(hifi) support",
|
"description": "Tidal on Electron with widevine(hifi) support",
|
||||||
"main": "src/main.js",
|
"main": "src/main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -7,7 +7,6 @@ const globalEvents = {
|
|||||||
updateInfo: "update-info",
|
updateInfo: "update-info",
|
||||||
hideSettings: "hideSettings",
|
hideSettings: "hideSettings",
|
||||||
showSettings: "showSettings",
|
showSettings: "showSettings",
|
||||||
updateStatus: "update-status",
|
|
||||||
storeChanged: "storeChanged",
|
storeChanged: "storeChanged",
|
||||||
error: "error",
|
error: "error",
|
||||||
};
|
};
|
||||||
|
@ -17,7 +17,6 @@ const mediaInfoModule = require("./scripts/mediaInfo");
|
|||||||
const discordModule = require("./scripts/discord");
|
const discordModule = require("./scripts/discord");
|
||||||
const globalEvents = require("./constants/globalEvents");
|
const globalEvents = require("./constants/globalEvents");
|
||||||
|
|
||||||
|
|
||||||
let mainWindow;
|
let mainWindow;
|
||||||
let icon = path.join(__dirname, "../assets/icon.png");
|
let icon = path.join(__dirname, "../assets/icon.png");
|
||||||
|
|
||||||
@ -98,7 +97,6 @@ app.on("activate", function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// IPC
|
// IPC
|
||||||
|
|
||||||
ipcMain.on(globalEvents.updateInfo, (event, arg) => {
|
ipcMain.on(globalEvents.updateInfo, (event, arg) => {
|
||||||
mediaInfoModule.update(arg);
|
mediaInfoModule.update(arg);
|
||||||
});
|
});
|
||||||
@ -110,15 +108,12 @@ ipcMain.on(globalEvents.showSettings, (event, arg) => {
|
|||||||
showSettingsWindow();
|
showSettingsWindow();
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on(globalEvents.updateStatus, (event, arg) => {
|
|
||||||
mediaInfoModule.updateStatus(arg);
|
|
||||||
});
|
|
||||||
ipcMain.on(globalEvents.storeChanged, (event, arg) => {
|
ipcMain.on(globalEvents.storeChanged, (event, arg) => {
|
||||||
mainWindow.setMenuBarVisibility(store.get(settings.menuBar));
|
mainWindow.setMenuBarVisibility(store.get(settings.menuBar));
|
||||||
|
|
||||||
if(store.get(settings.enableDiscord) && !discordModule.rpc) {
|
if (store.get(settings.enableDiscord) && !discordModule.rpc) {
|
||||||
discordModule.initRPC();
|
discordModule.initRPC();
|
||||||
} else if(!store.get(settings.enableDiscord) && discordModule.rpc) {
|
} else if (!store.get(settings.enableDiscord) && discordModule.rpc) {
|
||||||
discordModule.unRPC();
|
discordModule.unRPC();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
112
src/preload.js
112
src/preload.js
@ -1,4 +1,4 @@
|
|||||||
const { setTitle, getTitle } = require("./scripts/window-functions");
|
const { setTitle } = require("./scripts/window-functions");
|
||||||
const { dialog, process } = require("electron").remote;
|
const { dialog, process } = require("electron").remote;
|
||||||
const { store, settings } = require("./scripts/settings");
|
const { store, settings } = require("./scripts/settings");
|
||||||
const { ipcRenderer } = require("electron");
|
const { ipcRenderer } = require("electron");
|
||||||
@ -11,6 +11,7 @@ const notifier = require("node-notifier");
|
|||||||
const notificationPath = `${app.getPath("userData")}/notification.jpg`;
|
const notificationPath = `${app.getPath("userData")}/notification.jpg`;
|
||||||
let currentSong = "";
|
let currentSong = "";
|
||||||
let player;
|
let player;
|
||||||
|
let currentPlayStatus = statuses.paused;
|
||||||
|
|
||||||
const elements = {
|
const elements = {
|
||||||
play: '*[data-test="play"]',
|
play: '*[data-test="play"]',
|
||||||
@ -18,7 +19,7 @@ const elements = {
|
|||||||
next: '*[data-test="next"]',
|
next: '*[data-test="next"]',
|
||||||
previous: 'button[data-test="previous"]',
|
previous: 'button[data-test="previous"]',
|
||||||
title: '*[data-test^="footer-track-title"]',
|
title: '*[data-test^="footer-track-title"]',
|
||||||
artists: '*[class^="css-14o5h2y"]',
|
artists: '*[data-test^="grid-item-detail-text-title-artist"]',
|
||||||
home: '*[data-test="menu--home"]',
|
home: '*[data-test="menu--home"]',
|
||||||
back: '[class^="backwardButton"]',
|
back: '[class^="backwardButton"]',
|
||||||
forward: '[class^="forwardButton"]',
|
forward: '[class^="forwardButton"]',
|
||||||
@ -200,9 +201,9 @@ function addIPCEventListeners() {
|
|||||||
/**
|
/**
|
||||||
* Update the current status of tidal (e.g playing or paused)
|
* Update the current status of tidal (e.g playing or paused)
|
||||||
*/
|
*/
|
||||||
function updateStatus() {
|
function getCurrentlyPlayingStatus() {
|
||||||
let pause = elements.get("pause");
|
let pause = elements.get("pause");
|
||||||
let status;
|
let status = undefined;
|
||||||
|
|
||||||
// if pause button is visible tidal is playing
|
// if pause button is visible tidal is playing
|
||||||
if (pause) {
|
if (pause) {
|
||||||
@ -210,11 +211,29 @@ function updateStatus() {
|
|||||||
} else {
|
} else {
|
||||||
status = statuses.paused;
|
status = statuses.paused;
|
||||||
}
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update Tidal-hifi's media info
|
||||||
|
*
|
||||||
|
* @param {*} options
|
||||||
|
*/
|
||||||
|
function updateMediaInfo(options, notify) {
|
||||||
|
if (options) {
|
||||||
|
ipcRenderer.send(globalEvents.updateInfo, options);
|
||||||
|
store.get(settings.notifications) && notify && notifier.notify(options);
|
||||||
|
|
||||||
if (status) {
|
|
||||||
ipcRenderer.send(globalEvents.updateStatus, status);
|
|
||||||
if (player) {
|
if (player) {
|
||||||
player.playbackStatus = status == statuses.paused ? "Paused" : "Playing";
|
player.metadata = {
|
||||||
|
...player.metadata,
|
||||||
|
...{
|
||||||
|
"xesam:title": options.title,
|
||||||
|
"xesam:artist": [options.artists],
|
||||||
|
"mpris:artUrl": options.image,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
player.playbackStatus = options.status == statuses.paused ? "Paused" : "Playing";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -227,56 +246,47 @@ setInterval(function () {
|
|||||||
const url = elements.get("url").href.replace(/[^0-9]/g, "");
|
const url = elements.get("url").href.replace(/[^0-9]/g, "");
|
||||||
const artists = elements.getText("artists");
|
const artists = elements.getText("artists");
|
||||||
const songDashArtistTitle = `${title} - ${artists}`;
|
const songDashArtistTitle = `${title} - ${artists}`;
|
||||||
|
const currentStatus = getCurrentlyPlayingStatus();
|
||||||
|
const options = {
|
||||||
|
title,
|
||||||
|
message: artists,
|
||||||
|
status: currentStatus,
|
||||||
|
url: `https://tidal.com/browse/track/${url}`,
|
||||||
|
};
|
||||||
|
|
||||||
updateStatus();
|
const playStatusChanged = currentStatus !== currentPlayStatus;
|
||||||
|
const titleOrArtistChanged = currentSong !== songDashArtistTitle;
|
||||||
|
|
||||||
if (getTitle() !== songDashArtistTitle) {
|
if (titleOrArtistChanged || playStatusChanged) {
|
||||||
|
// update title and play info with new info
|
||||||
setTitle(songDashArtistTitle);
|
setTitle(songDashArtistTitle);
|
||||||
|
currentSong = songDashArtistTitle;
|
||||||
|
currentPlayStatus = currentStatus;
|
||||||
|
|
||||||
if (currentSong !== songDashArtistTitle) {
|
const image = elements.getSongIcon();
|
||||||
currentSong = songDashArtistTitle;
|
|
||||||
const image = elements.getSongIcon();
|
|
||||||
|
|
||||||
const options = {
|
new Promise((resolve) => {
|
||||||
title,
|
if (image.startsWith("http")) {
|
||||||
message: artists,
|
downloadFile(image, notificationPath).then(
|
||||||
url: `https://tidal.com/browse/track/${url}`,
|
() => {
|
||||||
};
|
options.icon = notificationPath;
|
||||||
new Promise((resolve, reject) => {
|
resolve();
|
||||||
if (image.startsWith("http")) {
|
},
|
||||||
downloadFile(image, notificationPath).then(
|
() => {
|
||||||
() => {
|
// if the image can't be downloaded then continue without it
|
||||||
options.icon = notificationPath;
|
resolve();
|
||||||
resolve();
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
// if the image can't be downloaded then continue without it
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// if the image can't be found on the page continue without it
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
}).then(
|
|
||||||
() => {
|
|
||||||
ipcRenderer.send(globalEvents.updateInfo, options);
|
|
||||||
store.get(settings.notifications) && notifier.notify(options);
|
|
||||||
|
|
||||||
if (player) {
|
|
||||||
player.metadata = {
|
|
||||||
...player.metadata,
|
|
||||||
...{
|
|
||||||
"xesam:title": title,
|
|
||||||
"xesam:artist": [artists],
|
|
||||||
"mpris:artUrl": image,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
},
|
);
|
||||||
() => {}
|
} else {
|
||||||
);
|
// if the image can't be found on the page continue without it
|
||||||
}
|
resolve();
|
||||||
|
}
|
||||||
|
}).then(
|
||||||
|
() => {
|
||||||
|
updateMediaInfo(options, titleOrArtistChanged);
|
||||||
|
},
|
||||||
|
() => {}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}, 200);
|
}, 200);
|
||||||
|
|
||||||
|
@ -1,52 +1,57 @@
|
|||||||
const discordrpc = require("discord-rpc");
|
const discordrpc = require("discord-rpc");
|
||||||
const clientId = '833617820704440341';
|
const { ipcMain } = require("electron");
|
||||||
|
const electron = require("electron");
|
||||||
|
const globalEvents = require("../constants/globalEvents");
|
||||||
|
const clientId = "833617820704440341";
|
||||||
const mediaInfoModule = require("./mediaInfo");
|
const mediaInfoModule = require("./mediaInfo");
|
||||||
|
|
||||||
const discordModule = [];
|
const discordModule = [];
|
||||||
|
|
||||||
let discord;
|
|
||||||
let rpc;
|
let rpc;
|
||||||
|
const observer = (event, arg) => {
|
||||||
|
if (mediaInfoModule.mediaInfo.status == "paused" && rpc) {
|
||||||
|
rpc.setActivity(idleStatus);
|
||||||
|
} else if (rpc) {
|
||||||
|
rpc.setActivity({
|
||||||
|
...idleStatus,
|
||||||
|
...{
|
||||||
|
details: `Listening to ${mediaInfoModule.mediaInfo.title}`,
|
||||||
|
state: mediaInfoModule.mediaInfo.artist,
|
||||||
|
buttons: [{ label: "Play on Tidal", url: mediaInfoModule.mediaInfo.url }],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const idleStatus = {
|
const idleStatus = {
|
||||||
details: `Browsing Tidal`,
|
details: `Browsing Tidal`,
|
||||||
largeImageKey: 'tidal-hifi-icon',
|
largeImageKey: "tidal-hifi-icon",
|
||||||
largeImageText: 'Tidal HiFi 2.0.0',
|
largeImageText: `Tidal HiFi ${electron.app.getVersion()}`,
|
||||||
instance: false,
|
instance: false,
|
||||||
}
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up the discord rpc and listen on globalEvents.updateInfo
|
||||||
|
*/
|
||||||
discordModule.initRPC = function () {
|
discordModule.initRPC = function () {
|
||||||
rpc = new discordrpc.Client({ transport: 'ipc' });
|
rpc = new discordrpc.Client({ transport: "ipc" });
|
||||||
rpc.login({ clientId }).catch(console.error);
|
rpc.login({ clientId }).catch(console.error);
|
||||||
discordModule.rpc = rpc;
|
discordModule.rpc = rpc;
|
||||||
|
|
||||||
rpc.on('ready', () => {
|
rpc.on("ready", () => {
|
||||||
rpc.setActivity(idleStatus);
|
rpc.setActivity(idleStatus);
|
||||||
})
|
});
|
||||||
|
ipcMain.on(globalEvents.updateInfo, observer);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove any RPC connection with discord and remove the event listener on globalEvents.updateInfo
|
||||||
|
*/
|
||||||
discordModule.unRPC = function () {
|
discordModule.unRPC = function () {
|
||||||
clearInterval(discord);
|
rpc.clearActivity();
|
||||||
rpc.clearActivity();
|
rpc.destroy();
|
||||||
rpc.destroy();
|
rpc = false;
|
||||||
rpc = false;
|
discordModule.rpc = rpc;
|
||||||
discordModule.rpc = rpc;
|
ipcMain.removeListener(globalEvents.updateInfo, observer);
|
||||||
}
|
};
|
||||||
|
|
||||||
module.exports = discordModule;
|
module.exports = discordModule;
|
@ -5,7 +5,7 @@ const mediaInfo = {
|
|||||||
artist: "",
|
artist: "",
|
||||||
icon: "",
|
icon: "",
|
||||||
status: statuses.paused,
|
status: statuses.paused,
|
||||||
url: ""
|
url: "",
|
||||||
};
|
};
|
||||||
const mediaInfoModule = {
|
const mediaInfoModule = {
|
||||||
mediaInfo,
|
mediaInfo,
|
||||||
@ -14,20 +14,12 @@ const mediaInfoModule = {
|
|||||||
/**
|
/**
|
||||||
* Update artist and song info in the mediaInfo constant
|
* Update artist and song info in the mediaInfo constant
|
||||||
*/
|
*/
|
||||||
mediaInfoModule.update = function(arg) {
|
mediaInfoModule.update = function (arg) {
|
||||||
mediaInfo.title = propOrDefault(arg.title);
|
mediaInfo.title = propOrDefault(arg.title);
|
||||||
mediaInfo.artist = propOrDefault(arg.message);
|
mediaInfo.artist = propOrDefault(arg.message);
|
||||||
mediaInfo.icon = propOrDefault(arg.icon);
|
mediaInfo.icon = propOrDefault(arg.icon);
|
||||||
mediaInfo.url = propOrDefault(arg.url);
|
mediaInfo.url = propOrDefault(arg.url);
|
||||||
};
|
mediaInfo.status = propOrDefault(arg.status);
|
||||||
|
|
||||||
/**
|
|
||||||
* Update tidal's status in the mediaInfo constant
|
|
||||||
*/
|
|
||||||
mediaInfoModule.updateStatus = function(status) {
|
|
||||||
if (Object.values(statuses).includes(status)) {
|
|
||||||
mediaInfo.status = status;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user