DiscordRPC customisation

This commit is contained in:
Core 2022-04-14 14:37:06 +01:00
parent e91df882aa
commit 99b4c2960c
No known key found for this signature in database
GPG key ID: FE9BF1B547F8F3C6

View file

@ -2,15 +2,15 @@ import * as RPC from 'discord-rpc'
import {ipcMain} from "electron"; import {ipcMain} from "electron";
import fetch from 'electron-fetch' import fetch from 'electron-fetch'
export default class DiscordRichPresence { export default class DiscordRPC {
/** /**
* Private variables for interaction in plugins * Private variables for interaction in plugins
*/ */
private static _store: any; private _utils: any;
private _app: any; private _app: any;
private _attributes: any; private _attributes: any;
private static _connection: boolean = false; private _connection: boolean = false;
/** /**
* Base Plugin Details (Eventually implemented into a GUI in settings) * Base Plugin Details (Eventually implemented into a GUI in settings)
@ -33,7 +33,6 @@ export default class DiscordRichPresence {
smallImageText: '', smallImageText: '',
instance: false instance: false
}; };
private _clientId: number = 0;
private _activityCache: RPC.Presence = { private _activityCache: RPC.Presence = {
details: '', details: '',
@ -50,21 +49,21 @@ export default class DiscordRichPresence {
* ****************************************************************************************/ * ****************************************************************************************/
/** /**
* Connect to Discord * Connect to Discord RPC
* @param clientId
* @private * @private
*/ */
private connect(clientId: any) { private connect() {
this._clientId = clientId; if (!this._utils.getStoreValue("general.discord_rpc.enabled")) {
if (DiscordRichPresence._store.general.discord_rpc == 0) { return;
return
} }
const clientId = this._utils.getStoreValue("general.discord_rpc.client") === "Cider" ? '911790844204437504' : '886578863147192350';
// Apparently needed for ask to join, join, spectate etc. // Apparently needed for ask to join, join, spectate etc.
RPC.register(clientId) RPC.register(clientId)
// Create the client // Create the client
this._client = new RPC.Client({transport: "ipc"}); this._client = new RPC.Client({transport: "ipc"});
// Runs on Ready // Runs on Ready
this._client.on('ready', () => { this._client.on('ready', () => {
console.info(`[DiscordRPC][connect] Successfully Connected to Discord. Authed for user: ${this._client.user.id}.`); console.info(`[DiscordRPC][connect] Successfully Connected to Discord. Authed for user: ${this._client.user.id}.`);
@ -72,22 +71,22 @@ export default class DiscordRichPresence {
// Handles Errors // Handles Errors
this._client.on('error', (err: any) => { this._client.on('error', (err: any) => {
console.error(`[DiscordRichPresence] ${err}`); console.error(`[DiscordRPC] ${err}`);
this.disconnect() this.disconnect()
}); });
// If Discord is closed, allow reconnecting // If Discord is closed, allow reconnecting
this._client.transport.once('close', () => { this._client.transport.once('close', () => {
console.info(`[DiscordRichPresence] Connection closed`); console.info(`[DiscordRPC] Connection closed`);
this.disconnect() this.disconnect()
}); });
// Login to Discord // Login to Discord
this._client.login({clientId}) this._client.login({clientId})
.then(() => { .then(() => {
DiscordRichPresence._connection = true; this._connection = true;
}) })
.catch((e: any) => console.error(`[DiscordRichPresence][connect] ${e}`)); .catch((e: any) => console.error(`[DiscordRPC][connect] ${e}`));
} }
/** /**
@ -99,7 +98,7 @@ export default class DiscordRichPresence {
} }
this._client.destroy().then(() => { this._client.destroy().then(() => {
DiscordRichPresence._connection = false; this._connection = false;
console.log('[DiscordRPC][disconnect] Disconnected from discord.') console.log('[DiscordRPC][disconnect] Disconnected from discord.')
}).catch((e: any) => console.error(`[DiscordRPC][disconnect] ${e}`)); }).catch((e: any) => console.error(`[DiscordRPC][disconnect] ${e}`));
@ -112,6 +111,32 @@ export default class DiscordRichPresence {
*/ */
private static filterActivity(activity: any, attributes: any): Object { private static filterActivity(activity: any, attributes: any): Object {
/**
* Works with:
* {artist}
* {composer}
* {title}
* {album}
* {trackNumber}
*/
const rpcVars: any = {
"artist": attributes.artistName,
"composer": attributes.composerName,
"title": attributes.name,
"album": attributes.albumName,
"trackNumber": attributes.trackNumber
}
// Replace the variables
Object.keys(rpcVars).forEach((key) => {
if (activity.details.includes(`{${key}}`)) {
activity.details = activity.details.replace(`{${key}}`, rpcVars[key])
}
if (activity.state.includes(`{${key}}`)) {
activity.state = activity.state.replace(`{${key}}`, rpcVars[key])
}
})
// Checks if the name is greater than 128 because some songs can be that long // Checks if the name is greater than 128 because some songs can be that long
if (activity.details && activity.details.length > 128) { if (activity.details && activity.details.length > 128) {
activity.details = activity.details.substring(0, 125) + '...' activity.details = activity.details.substring(0, 125) + '...'
@ -139,67 +164,68 @@ export default class DiscordRichPresence {
return activity return activity
} }
/**
* Sets the activity
* @param {activity} activity
*/
private setActivity(activity: any) {
if (!this._connection || !this._client || !activity) {
return
}
// Filter the activity
activity = DiscordRPC.filterActivity(activity, this._attributes)
// Set the activity
if (!this._attributes.status && this._utils.getStoreValue("general.discord_rpc.clear_on_pause")) {
this._client.clearActivity()
} else {
this._client.setActivity(activity)
this._activityCache = this._activity;
}
}
/** /**
* Sets the activity of the client * Sets the activity of the client
* @param {object} attributes * @param {object} attributes
*/ */
private updateActivity(attributes: any) { private updateActivity(attributes: any) {
if (DiscordRichPresence._store.general.discord_rpc == 0) { if (!this._utils.getStoreValue("general.discord_rpc.enabled") || this._utils.getStoreValue("general.privateEnabled")) {
return return
} else if (!DiscordRichPresence._connection || !this._client) { } else if (!this._client || !this._connection) {
this.connect(this._clientId) this.connect()
}
if (!DiscordRichPresence._connection) {
this._client.clearActivity().catch((e: any) => console.error(`[DiscordRichPresence][clearActivity] ${e}`));
return;
} }
// Check if show buttons is (true) or (false) // Check if show buttons is (true) or (false)
this._activity = { this._activity = {
details: attributes.name, details: this._utils.getStoreValue("general.discord_rpc.details_format"),
state: `${attributes.artistName ? `by ${attributes.artistName}` : ''}`, state: this._utils.getStoreValue("general.discord_rpc.state_format"),
startTimestamp: Date.now() - (attributes?.durationInMillis - attributes?.remainingTime),
endTimestamp: attributes.endTime,
largeImageKey: attributes?.artwork?.url?.replace('{w}', '1024').replace('{h}', '1024'), largeImageKey: attributes?.artwork?.url?.replace('{w}', '1024').replace('{h}', '1024'),
largeImageText: attributes.albumName, largeImageText: attributes.albumName,
instance: false // Whether the activity is in a game session instance: false // Whether the activity is in a game session
} }
if (!DiscordRichPresence._store.general.discord_rpc_hide_buttons) { // Add the buttons if people want them
if (!this._utils.getStoreValue("general.discord_rpc.hide_buttons")) {
this._activity.buttons = [ this._activity.buttons = [
{label: 'Listen on Cider', url: attributes.url.cider}, {label: 'Listen on Cider', url: attributes.url.cider},
{label: 'View on Apple Music', url: attributes.url.appleMusic} {label: 'View on Apple Music', url: attributes.url.appleMusic}
] //To change attributes.url => preload/cider-preload.js ] //To change attributes.url => preload/cider-preload.js
} }
// Add the timestamp if its playing
this._activity = DiscordRichPresence.filterActivity(this._activity, attributes) if (attributes.status) {
this._activity.startTimestamp = Date.now() - (attributes?.durationInMillis - attributes?.remainingTime)
// Check if its pausing (false) or playing (true) this._activity.endTimestamp = attributes.endTime
if (!attributes.status) {
if (DiscordRichPresence._store.general.discord_rpc_clear_on_pause) {
this._client.clearActivity()
.catch((e: any) => console.error(`[DiscordRichPresence][clearActivity] ${e}`));
} else {
this._activity.smallImageKey = 'pause';
this._activity.smallImageText = 'Paused';
delete this._activity.endTimestamp;
delete this._activity.startTimestamp;
this._client.setActivity(this._activity)
.catch((e: any) => console.error(`[DiscordRichPresence][setActivity] ${e}`));
}
} else if (this._activity && this._activityCache !== this._activity && this._activity.details) {
if (!DiscordRichPresence._store.general.discord_rpc_clear_on_pause) {
this._activity.smallImageKey = 'play';
this._activity.smallImageText = 'Playing';
} }
this._client.setActivity(this._activity) // If the user wants to keep the activity when paused
.catch((e: any) => console.error(`[DiscordRichPresence][updateActivity] ${e}`)); if (!this._utils.getStoreValue("general.discord_rpc.clear_on_pause")) {
this._activityCache = this._activity; this._activity.smallImageKey = attributes.status ? 'pause' : 'play';
this._activity.smallImageText = attributes.status ? 'Paused' : 'Playing';
} }
this.setActivity(this._activity)
} }
/******************************************************************************************* /*******************************************************************************************
@ -210,7 +236,7 @@ export default class DiscordRichPresence {
* Runs on plugin load (Currently run on application start) * Runs on plugin load (Currently run on application start)
*/ */
constructor(utils: { getStore: () => any; getApp: () => any; }) { constructor(utils: { getStore: () => any; getApp: () => any; }) {
DiscordRichPresence._store = utils.getStore(); this._utils = utils;
console.debug(`[Plugin][${this.name}] Loading Complete.`); console.debug(`[Plugin][${this.name}] Loading Complete.`);
this._app = utils.getApp(); this._app = utils.getApp();
} }
@ -220,10 +246,10 @@ export default class DiscordRichPresence {
*/ */
onReady(_win: any): void { onReady(_win: any): void {
let self = this let self = this
this.connect((DiscordRichPresence._store.general.discord_rpc == 1) ? '911790844204437504' : '886578863147192350'); this.connect();
console.debug(`[Plugin][${this.name}] Ready.`); console.debug(`[Plugin][${this.name}] Ready.`);
ipcMain.on('updateRPCImage', (_event, imageurl) => { ipcMain.on('updateRPCImage', (_event, imageurl) => {
if (!DiscordRichPresence._store.general.privateEnabled) { if (!this._utils.getStoreValue("general.privateEnabled")) {
fetch('https://api.cider.sh/v1/images', { fetch('https://api.cider.sh/v1/images', {
method: 'POST', method: 'POST',
@ -246,6 +272,9 @@ export default class DiscordRichPresence {
* Runs on app stop * Runs on app stop
*/ */
onBeforeQuit(): void { onBeforeQuit(): void {
if (this._client) {
this.disconnect()
}
console.debug(`[Plugin][${this.name}] Stopped.`); console.debug(`[Plugin][${this.name}] Stopped.`);
} }
@ -254,10 +283,9 @@ export default class DiscordRichPresence {
* @param attributes Music Attributes (attributes.status = current state) * @param attributes Music Attributes (attributes.status = current state)
*/ */
onPlaybackStateDidChange(attributes: object): void { onPlaybackStateDidChange(attributes: object): void {
if (!DiscordRichPresence._store.general.privateEnabled) {
this._attributes = attributes this._attributes = attributes
this.updateActivity(attributes) this.updateActivity(attributes)
}
} }
/** /**
@ -265,9 +293,8 @@ export default class DiscordRichPresence {
* @param attributes Music Attributes * @param attributes Music Attributes
*/ */
onNowPlayingItemDidChange(attributes: object): void { onNowPlayingItemDidChange(attributes: object): void {
if (!DiscordRichPresence._store.general.privateEnabled) {
this._attributes = attributes this._attributes = attributes
this.updateActivity(attributes) this.updateActivity(attributes)
}
} }
} }