discord rpc plugin

This commit is contained in:
vapormusic 2022-01-19 13:03:37 +07:00
parent 71e45aff3f
commit 2d27939881
4 changed files with 211 additions and 7 deletions

View file

@ -50,6 +50,7 @@
"youtube-search-without-api-key": "^1.0.7" "youtube-search-without-api-key": "^1.0.7"
}, },
"devDependencies": { "devDependencies": {
"@types/discord-rpc": "^4.0.0",
"@types/express": "^4.17.13", "@types/express": "^4.17.13",
"electron": "https://github.com/castlabs/electron-releases.git", "electron": "https://github.com/castlabs/electron-releases.git",
"electron-builder": "^22.14.5", "electron-builder": "^22.14.5",

View file

@ -29,10 +29,10 @@ electron.app.on('ready', () => {
require('vue-devtools').install() require('vue-devtools').install()
} }
electron.components.whenReady().then(() => { electron.components.whenReady().then(async () => {
Cider.createWindow().then((win) => { await Cider.createWindow()
plug.callPlugins('onReady', win); plug.callPlugins('onReady', Cider);
})
}) })

View file

@ -1,5 +1,3 @@
import * as electron from "electron";
export default class sendSongToTitlebar { export default class sendSongToTitlebar {
/** /**
* Base Plugin Details (Eventually implemented into a GUI in settings) * Base Plugin Details (Eventually implemented into a GUI in settings)
@ -29,7 +27,7 @@ export default class sendSongToTitlebar {
* @param attributes Music Attributes (attributes.state = current state) * @param attributes Music Attributes (attributes.state = current state)
*/ */
onPlaybackStateDidChange(attributes: any): void { onPlaybackStateDidChange(attributes: any): void {
this._win.setTitle(`${(attributes != null && attributes.name != null && attributes.name.length > 0) ? (attributes.name + " - ") : ''}Cider`) this._win.win.setTitle(`${(attributes != null && attributes.name != null && attributes.name.length > 0) ? (attributes.name + " - ") : ''}Cider`)
} }
/** /**
* Runs on song change * Runs on song change

View file

@ -0,0 +1,205 @@
import * as DiscordRPC from 'discord-rpc'
export default class DiscordRPCPlugin {
/**
* Private variables for interaction in plugins
*/
private _win: any;
private _app: any;
private _discord: any;
private connect(clientId: any) {
this._discord = { isConnected: false };
if (this._win.store.store.general.discord_rpc == 0 || this._discord.isConnected) return;
DiscordRPC.register(clientId) // Apparently needed for ask to join, join, spectate etc.
const client = new DiscordRPC.Client({ transport: "ipc" });
this._discord = Object.assign(client, { error: false, activityCache: null, isConnected: false });
// Login to Discord
this._discord.login({ clientId })
.then(() => {
this._discord.isConnected = true;
})
.catch((e : any) => console.error(`[DiscordRPC][connect] ${e}`));
this._discord.on('ready', () => {
console.log(`[DiscordRPC][connect] Successfully Connected to Discord. Authed for user: ${client.user.username} (${client.user.id})`);
})
// Handles Errors
this._discord.on('error', (err: any) => {
console.error(`[DiscordRPC] ${err}`);
this.disconnect()
this._discord.isConnected = false;
});
}
/**
* Disconnects from Discord RPC
*/
private disconnect() {
if (this._win.store.store.general.discord_rpc == 0 || !this._discord.isConnected) return;
try {
this._discord.destroy().then(() => {
this._discord.isConnected = false;
console.log('[DiscordRPC][disconnect] Disconnected from discord.')
}).catch((e : any) => console.error(`[DiscordRPC][disconnect] ${e}`));
} catch (err) {
console.error(err)
}
}
/**
* Sets the activity of the client
* @param {object} attributes
*/
private updateActivity(attributes : any) {
if (this._win.store.store.general.discord_rpc == 0) return;
if (!this._discord.isConnected) {
this._discord.clearActivity().catch((e : any) => console.error(`[DiscordRPC][updateActivity] ${e}`));
return;
}
// console.log('[DiscordRPC][updateActivity] Updating Discord Activity.')
const listenURL = `https://cider.sh/p?s&id=${attributes.playParams.id}` // cider://play/s/[id] (for song)
//console.log(attributes)
interface ActObject {
details?: any,
state?: any,
startTimestamp?: any,
endTimestamp?: any,
largeImageKey? : any,
largeImageText?: any,
smallImageKey?: any,
smallImageText?: any,
instance: true,
buttons?: [
{ label: "Listen on Cider", url?: any },
]
}
let ActivityObject : ActObject | null = {
details: attributes.name,
state: `by ${attributes.artistName}`,
startTimestamp: attributes.startTime,
endTimestamp: attributes.endTime,
largeImageKey : (attributes.artwork.url.replace('{w}', '1024').replace('{h}', '1024')) ?? 'cider',
largeImageText: attributes.albumName,
smallImageKey: (attributes.status ? 'play' : 'pause'),
smallImageText: (attributes.status ? 'Playing' : 'Paused'),
instance: true,
buttons: [
{ label: "Listen on Cider", url: listenURL },
]
};
if (ActivityObject.largeImageKey == "" || ActivityObject.largeImageKey == null) {
ActivityObject.largeImageKey = (this._win.store.store.general.discord_rpc == 1) ? "cider" : "logo"
}
// Remove the pause/play icon and test for clear activity on pause
if (this._win.store.store.general.discordClearActivityOnPause == 1) {
delete ActivityObject.smallImageKey
delete ActivityObject.smallImageText
}
// Deletes the timestamp if its not greater than 0
if (!((new Date(attributes.endTime)).getTime() > 0)) {
delete ActivityObject.startTimestamp
delete ActivityObject.endTimestamp
}
// Artist check
if (!attributes.artistName) {
delete ActivityObject.state
}
// Album text check
if (!ActivityObject.largeImageText || ActivityObject.largeImageText.length < 2) {
delete ActivityObject.largeImageText
}
// Checks if the name is greater than 128 because some songs can be that long
if (ActivityObject.details.length > 128) {
ActivityObject.details = ActivityObject.details.substring(0, 125) + '...'
}
// Check if its pausing (false) or playing (true)
if (!attributes.status) {
if (this._win.store.store.general.discordClearActivityOnPause == 1) {
this._discord.clearActivity().catch((e : any) => console.error(`[DiscordRPC][clearActivity] ${e}`));
ActivityObject = null
} else {
delete ActivityObject.startTimestamp
delete ActivityObject.endTimestamp
ActivityObject.smallImageKey = 'pause'
ActivityObject.smallImageText = 'Paused'
}
}
if (ActivityObject && ActivityObject !== this._discord.activityCache && ActivityObject.details && ActivityObject.state) {
try {
// console.log(`[DiscordRPC][setActivity] Setting activity to ${JSON.stringify(ActivityObject)}`);
this._discord.setActivity(ActivityObject)
this._discord.activityCache = ActivityObject
} catch (err) {
console.error(`[DiscordRPC][setActivity] ${err}`)
}
}
}
/**
* Base Plugin Details (Eventually implemented into a GUI in settings)
*/
public name: string = 'DiscordRPCPlugin';
public description: string = 'Discord RPC plugin for Cider';
public version: string = '0.0.1';
public author: string = 'vapormusic / Cider Collective';
/**
* Runs on plugin load (Currently run on application start)
*/
constructor(app: any) {
this._app = app;
}
/**
* Runs on app ready
*/
onReady(win: any): void {
this._win = win;
this.connect((this._win.store.store.general.discord_rpc == 1) ? '911790844204437504' : '886578863147192350');
}
/**
* Runs on app stop
*/
onBeforeQuit(): void {
console.log('Example plugin stopped');
}
/**
* Runs on playback State Change
* @param attributes Music Attributes (attributes.state = current state)
*/
onPlaybackStateDidChange(attributes: object): void {
this.updateActivity(attributes)
}
/**
* Runs on song change
* @param attributes Music Attributes
*/
onNowPlayingItemDidChange(attributes: object): void {
this.updateActivity(attributes)
}
}