-
Notifications
You must be signed in to change notification settings - Fork 594
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Discord add reconnecting functionality
Clear rpc on disconnect Add menu button to reconnect
- Loading branch information
Showing
3 changed files
with
167 additions
and
77 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,71 +1,140 @@ | ||
const Discord = require("discord-rpc"); | ||
const { dev } = require("electron-is") | ||
|
||
const registerCallback = require("../../providers/song-info"); | ||
|
||
const rpc = new Discord.Client({ | ||
transport: "ipc", | ||
}); | ||
|
||
// Application ID registered by @semvis123 | ||
const clientId = "790655993809338398"; | ||
|
||
/** | ||
* @typedef {Object} Info | ||
* @property {import('discord-rpc').Client} rpc | ||
* @property {boolean} ready | ||
* @property {import('../../providers/song-info').SongInfo} lastSongInfo | ||
*/ | ||
/** | ||
* @type {Info} | ||
*/ | ||
const info = { | ||
rpc: null, | ||
ready: false, | ||
lastSongInfo: null, | ||
}; | ||
/** | ||
* @type {(() => void)[]} | ||
*/ | ||
const refreshCallbacks = []; | ||
const resetInfo = () => { | ||
info.rpc = null; | ||
info.ready = false; | ||
clearTimeout(clearActivity); | ||
if (dev()) console.log("discord disconnected"); | ||
refreshCallbacks.forEach(cb => cb()); | ||
}; | ||
|
||
const connect = () => { | ||
if (info.rpc) { | ||
if (dev()) | ||
console.log('Attempted to connect with active RPC object'); | ||
return; | ||
} | ||
|
||
info.rpc = new Discord.Client({ | ||
transport: "ipc", | ||
}); | ||
info.ready = false; | ||
|
||
info.rpc.once("connected", () => { | ||
if (dev()) console.log("discord connected"); | ||
refreshCallbacks.forEach(cb => cb()); | ||
}); | ||
info.rpc.once("ready", () => { | ||
info.ready = true; | ||
if (info.lastSongInfo) updateActivity(info.lastSongInfo) | ||
}); | ||
info.rpc.once("disconnected", resetInfo); | ||
|
||
// Startup the rpc client | ||
info.rpc.login({ clientId }).catch(err => { | ||
resetInfo(); | ||
if (dev()) console.error(err); | ||
}); | ||
}; | ||
|
||
let clearActivity; | ||
/** | ||
* @type {import('../../providers/song-info').songInfoCallback} | ||
*/ | ||
let updateActivity; | ||
|
||
module.exports = (win, {activityTimoutEnabled, activityTimoutTime}) => { | ||
// We get multiple events | ||
// Next song: PAUSE(n), PAUSE(n+1), PLAY(n+1) | ||
// Skip time: PAUSE(N), PLAY(N) | ||
updateActivity = songInfo => { | ||
if (songInfo.title.length === 0 && songInfo.artist.length === 0) { | ||
return; | ||
} | ||
info.lastSongInfo = songInfo; | ||
|
||
// stop the clear activity timout | ||
clearTimeout(clearActivity); | ||
|
||
// stop early if discord connection is not ready | ||
// do this after clearTimeout to avoid unexpected clears | ||
if (!info.rpc || !info.ready) { | ||
return; | ||
} | ||
|
||
// clear directly if timeout is 0 | ||
if (songInfo.isPaused && activityTimoutEnabled && activityTimoutTime === 0) { | ||
info.rpc.clearActivity().catch(console.error); | ||
return; | ||
} | ||
|
||
// Song information changed, so lets update the rich presence | ||
const activityInfo = { | ||
details: songInfo.title, | ||
state: songInfo.artist, | ||
largeImageKey: "logo", | ||
largeImageText: [ | ||
songInfo.uploadDate, | ||
songInfo.views.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + " views" | ||
].join(' || '), | ||
}; | ||
|
||
if (songInfo.isPaused) { | ||
// Add an idle icon to show that the song is paused | ||
activityInfo.smallImageKey = "idle"; | ||
activityInfo.smallImageText = "idle/paused"; | ||
// Set start the timer so the activity gets cleared after a while if enabled | ||
if (activityTimoutEnabled) | ||
clearActivity = setTimeout(() => info.rpc.clearActivity().catch(console.error), activityTimoutTime || 10000); | ||
} else { | ||
// Add the start and end time of the song | ||
const songStartTime = Date.now() - songInfo.elapsedSeconds * 1000; | ||
activityInfo.startTimestamp = songStartTime; | ||
activityInfo.endTimestamp = | ||
songStartTime + songInfo.songDuration * 1000; | ||
} | ||
|
||
info.rpc.setActivity(activityInfo).catch(console.error); | ||
}; | ||
|
||
// If the page is ready, register the callback | ||
win.once("ready-to-show", () => { | ||
rpc.once("ready", () => { | ||
// Register the callback | ||
// | ||
// We get multiple events | ||
// Next song: PAUSE(n), PAUSE(n+1), PLAY(n+1) | ||
// Skip time: PAUSE(N), PLAY(N) | ||
registerCallback((songInfo) => { | ||
if (songInfo.title.length === 0 && songInfo.artist.length === 0) { | ||
return; | ||
} | ||
// Song information changed, so lets update the rich presence | ||
const activityInfo = { | ||
details: songInfo.title, | ||
state: songInfo.artist, | ||
largeImageKey: "logo", | ||
largeImageText: [ | ||
songInfo.uploadDate, | ||
songInfo.views.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + " views" | ||
].join(' || '), | ||
}; | ||
|
||
// stop the clear activity timout | ||
clearTimeout(clearActivity); | ||
|
||
// clear directly if timeout is 0 | ||
if (songInfo.isPaused && activityTimoutEnabled && activityTimoutTime === 0) { | ||
rpc.clearActivity().catch(console.error); | ||
return; | ||
} | ||
|
||
if (songInfo.isPaused) { | ||
// Add an idle icon to show that the song is paused | ||
activityInfo.smallImageKey = "idle"; | ||
activityInfo.smallImageText = "idle/paused"; | ||
// Set start the timer so the activity gets cleared after a while if enabled | ||
if (activityTimoutEnabled) | ||
clearActivity = setTimeout(() => rpc.clearActivity().catch(console.error), activityTimoutTime || 10000); | ||
} else { | ||
// Add the start and end time of the song | ||
const songStartTime = Date.now() - songInfo.elapsedSeconds * 1000; | ||
activityInfo.startTimestamp = songStartTime; | ||
activityInfo.endTimestamp = | ||
songStartTime + songInfo.songDuration * 1000; | ||
} | ||
|
||
rpc.setActivity(activityInfo).catch(console.error); | ||
}); | ||
}); | ||
|
||
// Startup the rpc client | ||
rpc.login({ clientId }).catch(console.error); | ||
registerCallback(updateActivity); | ||
connect(); | ||
}); | ||
}; | ||
|
||
module.exports.clear = () => rpc.clearActivity(); | ||
module.exports.clear = () => { | ||
if (info.rpc) info.rpc.clearActivity(); | ||
clearTimeout(clearActivity); | ||
}; | ||
module.exports.connect = connect; | ||
module.exports.registerRefresh = (cb) => refreshCallbacks.push(cb); | ||
/** | ||
* @type {Info} | ||
*/ | ||
module.exports.info = Object.defineProperties({}, Object.keys(info).reduce((o, k) => ({ ...o, [k]: { enumerable: true, get: () => info[k] } }), {})); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,38 @@ | ||
const { setOptions } = require("../../config/plugins"); | ||
const { edit } = require("../../config"); | ||
const { clear } = require("./back"); | ||
const { clear, info, connect, registerRefresh } = require("./back"); | ||
|
||
module.exports = (win, options) => [ | ||
{ | ||
label: "Clear activity", | ||
click: () => { | ||
clear(); | ||
let hasRegisterred = false; | ||
|
||
module.exports = (win, options, refreshMenu) => { | ||
if (!hasRegisterred) { | ||
registerRefresh(refreshMenu); | ||
hasRegisterred = true; | ||
} | ||
|
||
return [ | ||
{ | ||
label: info.rpc !== null ? "Connected" : "Reconnect", | ||
enabled: info.rpc === null, | ||
click: connect, | ||
}, | ||
{ | ||
label: "Clear activity", | ||
click: clear, | ||
}, | ||
}, | ||
{ | ||
label: "Clear activity after timeout", | ||
type: "checkbox", | ||
checked: options.activityTimoutEnabled, | ||
click: (item) => { | ||
options.activityTimoutEnabled = item.checked; | ||
setOptions('discord', options); | ||
{ | ||
label: "Clear activity after timeout", | ||
type: "checkbox", | ||
checked: options.activityTimoutEnabled, | ||
click: (item) => { | ||
options.activityTimoutEnabled = item.checked; | ||
setOptions('discord', options); | ||
}, | ||
}, | ||
}, | ||
{ | ||
label: "Set timeout time in config", | ||
click: () => { | ||
{ | ||
label: "Set timeout time in config", | ||
// open config.json | ||
edit(); | ||
click: edit, | ||
}, | ||
}, | ||
]; | ||
]; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters