orchard/src/main/plugins/discordrpc.ts
Core 604ef16db8
Revert "Merge branch 'develop' into develop"
This reverts commit 5fa345e6c8, reversing
changes made to a02b633f49.
2022-02-17 01:05:52 +00:00

252 lines
8.1 KiB
TypeScript

import * as RPC from 'discord-rpc'
import {ipcMain} from "electron";
import fetch from 'electron-fetch'
export default class DiscordRichPresence {
/**
* Private variables for interaction in plugins
*/
private static _store: any;
private _app : any;
private _attributes : any;
private static _connection: boolean = false;
/**
* Base Plugin Details (Eventually implemented into a GUI in settings)
*/
public name: string = 'Discord Rich Presence';
public description: string = 'Discord RPC plugin for Cider';
public version: string = '1.0.0';
public author: string = 'vapormusic/Core (Cider Collective)';
/**
* Plugin Initialization
*/
private _client: any = null;
private _activity: RPC.Presence = {
details: '',
state: '',
largeImageKey: '',
largeImageText: '',
smallImageKey: '',
smallImageText: '',
instance: false
};
private _activityCache: RPC.Presence = {
details: '',
state: '',
largeImageKey: '',
largeImageText: '',
smallImageKey: '',
smallImageText: '',
instance: false
};
/*******************************************************************************************
* Private Methods
* ****************************************************************************************/
/**
* Connect to Discord
* @param clientId
* @private
*/
private connect(clientId: any) {
if (DiscordRichPresence._store.general.discord_rpc == 0) {
return
}
// Apparently needed for ask to join, join, spectate etc.
RPC.register(clientId)
// Create the client
this._client = new RPC.Client({transport: "ipc"});
// Runs on Ready
this._client.on('ready', () => {
console.info(`[DiscordRPC][connect] Successfully Connected to Discord. Authed for user: ${this._client.user.id}.`);
})
// Handles Errors
this._client.on('error', (err: any) => {
console.error(`[DiscordRichPresence] ${err}`);
this.disconnect()
});
// Login to Discord
this._client.login({clientId})
.then(() => {
DiscordRichPresence._connection = true;
})
.catch((e: any) => console.error(`[DiscordRichPresence][connect] ${e}`));
}
/**
* Disconnects from Discord RPC
*/
private disconnect() {
if (!this._client) return;
this._client.destroy().then(() => {
DiscordRichPresence._connection = false;
console.log('[DiscordRPC][disconnect] Disconnected from discord.')
}).catch((e: any) => console.error(`[DiscordRPC][disconnect] ${e}`));
}
/**
* Filter the Discord activity object
*/
private filterActivity(activity: any, attributes: any): Object {
// Checks if the name is greater than 128 because some songs can be that long
if (activity.details && activity.details.length > 128) {
activity.details = activity.details.substring(0, 125) + '...'
}
// Check large image
if (activity.largeImageKey == null || activity.largeImageKey === "" || activity.largeImageKey.length > 256) {
activity.largeImageKey = "cider";
}
// Timestamp
if (new Date(attributes.endTime).getTime() < 0) {
delete activity.startTime
delete activity.endTime
}
// not sure
if (!attributes.artistName) {
delete activity.state;
}
if (!activity.largeImageText || activity.largeImageText.length < 2) {
delete activity.largeImageText
}
activity.buttons.forEach((key: {label: string, url: string}, _v: Number) => {
if (key.url.includes('undefined') || key.url.includes('no-id-found')) {
activity.buttons.splice(key, 1);
}
})
return activity
}
/**
* Sets the activity of the client
* @param {object} attributes
*/
private updateActivity(attributes: any) {
if (!this._client) return;
if (!DiscordRichPresence._connection) {
this._client.clearActivity().catch((e: any) => console.error(`[DiscordRichPresence][clearActivity] ${e}`));
return;
}
this._activity = {
details: attributes.name,
state: `${attributes.artistName ? `by ${attributes.artistName}` : ''}`,
startTimestamp: attributes.startTime,
endTimestamp: attributes.endTime,
largeImageKey: attributes?.artwork?.url?.replace('{w}', '1024').replace('{h}', '1024'),
largeImageText: attributes.albumName,
instance: false, // Whether the activity is in a game session
buttons: [
{label: "Listen on Cider", url: attributes.url.cider},
{label: "View on Apple Music", url: attributes.url.appleMusic},
]
};
this._activity = this.filterActivity(this._activity, attributes)
// Check if its pausing (false) or playing (true)
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)
.catch((e: any) => console.error(`[DiscordRichPresence][updateActivity] ${e}`));
this._activityCache = this._activity;
}
}
/*******************************************************************************************
* Public Methods
* ****************************************************************************************/
/**
* Runs on plugin load (Currently run on application start)
*/
constructor(app: any, store: any) {
DiscordRichPresence._store = store
console.debug(`[Plugin][${this.name}] Loading Complete.`);
this._app = app;
}
/**
* Runs on app ready
*/
onReady(_win: any): void {
let self = this
this.connect((DiscordRichPresence._store.general.discord_rpc == 1) ? '911790844204437504' : '886578863147192350');
console.debug(`[Plugin][${this.name}] Ready.`);
ipcMain.on('updateRPCImage', (_event, imageurl) => {
fetch('https://api.cider.sh/v1/images' ,{
method: 'POST',
body: JSON.stringify({url : imageurl}),
headers: {
'Content-Type': 'application/json',
'User-Agent': _win.webContents.getUserAgent()
},
})
.then(res => res.json())
.then(function(json){
self._attributes["artwork"]["url"] = json.url
self.updateActivity(self._attributes)
})
})
}
/**
* Runs on app stop
*/
onBeforeQuit(): void {
console.debug(`[Plugin][${this.name}] Stopped.`);
}
/**
* Runs on playback State Change
* @param attributes Music Attributes (attributes.status = current state)
*/
onPlaybackStateDidChange(attributes: object): void {
this._attributes = attributes
this.updateActivity(attributes)
}
/**
* Runs on song change
* @param attributes Music Attributes
*/
onNowPlayingItemDidChange(attributes: object): void {
this._attributes = attributes
this.updateActivity(attributes)
}
}