From d19f5d3c041aebd10d93044dd6ba9a944033d0de Mon Sep 17 00:00:00 2001 From: Core <64542347+coredev-uk@users.noreply.github.com> Date: Mon, 13 Jun 2022 15:20:32 +0100 Subject: [PATCH 01/34] Initial lastfm overhaul commit --- package.json | 1 + src/main/plugins/lfm_new.ts | 53 +++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 src/main/plugins/lfm_new.ts diff --git a/package.json b/package.json index 5ca5c12b..fdceb0f6 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "get-port": "^5.1.1", "jimp": "^0.16.1", "jsonc": "^2.0.0", + "lastfm-autocorrect": "^1.0.0", "lastfmapi": "^0.1.1", "mdns-js": "git+https://github.com/ciderapp/node-mdns-js.git", "mpris-service": "^2.1.2", diff --git a/src/main/plugins/lfm_new.ts b/src/main/plugins/lfm_new.ts new file mode 100644 index 00000000..72d8d422 --- /dev/null +++ b/src/main/plugins/lfm_new.ts @@ -0,0 +1,53 @@ +import * as utils from '../base/utils'; +import {app} from 'electron'; +// @ts-ignore +import LastfmAPI from 'lastfmapi'; + +// https://github.com/maxkueng/node-lastfmapi +// https://github.com/maxkueng/lastfm-autocorrect + +export default class lfm_new { + + /** + * Base Plugin Information + */ + public name: string = 'LastFM Plugin for Cider'; + public version: string = '2.0.0'; + public author: string = 'Core (Cider Collective)'; + + /** + * Private variables for interaction in plugins + */ + private _attributes: any; + private _apiCredentials = { + key: "f9986d12aab5a0fe66193c559435ede3", + secret: "acba3c29bd5973efa38cc2f0b63cc625" + } + + /** + * Plugin Initialization + */ + private _client: any = null; + private _lastfm: any = null; + private _activityCache: any = { + details: '', + state: '', + largeImageKey: '', + largeImageText: '', + smallImageKey: '', + smallImageText: '', + instance: false + }; + + constructor() { + } + + /** + * Private Methods + */ + private initializeLastFM(clientSession: string): void { + + } + + +} \ No newline at end of file From f9becc61aea9d3e23d347f3131a5a872d2752587 Mon Sep 17 00:00:00 2001 From: Core <64542347+coredev-uk@users.noreply.github.com> Date: Mon, 13 Jun 2022 15:26:47 +0100 Subject: [PATCH 02/34] just adding todo for later --- src/main/plugins/lfm_new.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/plugins/lfm_new.ts b/src/main/plugins/lfm_new.ts index 72d8d422..2165d937 100644 --- a/src/main/plugins/lfm_new.ts +++ b/src/main/plugins/lfm_new.ts @@ -5,6 +5,9 @@ import LastfmAPI from 'lastfmapi'; // https://github.com/maxkueng/node-lastfmapi // https://github.com/maxkueng/lastfm-autocorrect +// @todo: add autocorrect +// @todo: add scrobble and filter to prevent no-title-found being scrobbled +// @todo: handle session keys through config to stop aids session.json export default class lfm_new { From c8c437449e7583d5a477c86c855bcbd48a703431 Mon Sep 17 00:00:00 2001 From: Core <64542347+coredev-uk@users.noreply.github.com> Date: Tue, 14 Jun 2022 12:40:49 +0100 Subject: [PATCH 03/34] yh --- {src/main/plugins => resources}/lastfm.ts | 0 src/main/base/app.ts | 12 ++-- src/main/base/store.ts | 8 ++- src/main/base/utils.ts | 7 +++ src/main/plugins/lfm_new.ts | 68 ++++++++++++++++++++--- 5 files changed, 78 insertions(+), 17 deletions(-) rename {src/main/plugins => resources}/lastfm.ts (100%) diff --git a/src/main/plugins/lastfm.ts b/resources/lastfm.ts similarity index 100% rename from src/main/plugins/lastfm.ts rename to resources/lastfm.ts diff --git a/src/main/base/app.ts b/src/main/base/app.ts index 58ccda47..2799eb9f 100644 --- a/src/main/base/app.ts +++ b/src/main/base/app.ts @@ -162,13 +162,13 @@ export class AppEvents { // LastFM Auth URL if (arg.includes('auth')) { - let authURI = arg.split('/auth/')[1] + const authURI = arg.split('/auth/')[1] if (authURI.startsWith('lastfm')) { // If we wanted more auth options - const authKey = authURI.split('lastfm?token=')[1]; - utils.setStoreValue('lastfm.enabled', true); - utils.setStoreValue('lastfm.auth_token', authKey); - utils.getWindow().webContents.send('LastfmAuthenticated', authKey); - this.plugin.callPlugin('lastfm', 'authenticate', authKey); + // const authKey = authURI.split('lastfm?token=')[1]; + // utils.setStoreValue('lastfm.enabled', true); + // utils.setStoreValue('lastfm.auth_token', authKey); + // utils.getWindow().webContents.send('LastfmAuthenticated', authKey); + this.plugin.callPlugin('lastfm', 'authenticateUser', authURI.split('lastfm?token=')[1]); } } // Play diff --git a/src/main/base/store.ts b/src/main/base/store.ts index 8cbcd2c4..53f3a42a 100644 --- a/src/main/base/store.ts +++ b/src/main/base/store.ts @@ -222,10 +222,14 @@ export class Store { "lastfm": { "enabled": false, "scrobble_after": 30, - "auth_token": "", "enabledRemoveFeaturingArtists": true, "filterLoop": true, - "NowPlaying": "true" + "NowPlaying": "true", + "secrets": { + "auth_token": "", + "session": {}, + } + }, "advanced": { "AudioContext": false, diff --git a/src/main/base/utils.ts b/src/main/base/utils.ts index 41e0ae12..035553d7 100644 --- a/src/main/base/utils.ts +++ b/src/main/base/utils.ts @@ -43,6 +43,13 @@ export class utils { return app; } + /** + * Get the IPCMain + */ + static getIPCMain(): Electron.IpcMain { + return ipcMain + } + /** * Fetches the i18n locale for the given language. * @param language {string} The language to fetch the locale for. diff --git a/src/main/plugins/lfm_new.ts b/src/main/plugins/lfm_new.ts index 2165d937..8bcbba88 100644 --- a/src/main/plugins/lfm_new.ts +++ b/src/main/plugins/lfm_new.ts @@ -1,7 +1,4 @@ -import * as utils from '../base/utils'; import {app} from 'electron'; -// @ts-ignore -import LastfmAPI from 'lastfmapi'; // https://github.com/maxkueng/node-lastfmapi // https://github.com/maxkueng/lastfm-autocorrect @@ -30,8 +27,9 @@ export default class lfm_new { /** * Plugin Initialization */ - private _client: any = null; - private _lastfm: any = null; + private _lfm: any = null; + private _authenticated: boolean = false; + private _utils: any = null; private _activityCache: any = { details: '', state: '', @@ -42,15 +40,67 @@ export default class lfm_new { instance: false }; - constructor() { + /** + * Initialize LastFM + * @param token + * @param api + * @private + */ + private initializeLastFM(token: string, api: {key: string, secret: string}): void { + const LastfmAPI = require("lastfmapi") + this._lfm = new LastfmAPI({ + 'api_key' : api.key, + 'secret' : api.secret, + }); + + if (this._utils.getStoreValue("lastfm.secrets.session")) { + this._lfm.setSessionCredentials(this._utils.getStoreValue("lastfm.secrets.session")); + this._authenticated = true; + } else { + this.authenticateLastFM(token) + } } /** - * Private Methods + * Authenticate the user with the given token + * @param token + * @private */ - private initializeLastFM(clientSession: string): void { - + private authenticateLastFM(token: string): void { + if (!token) return; + this._lfm.authenticate(token, (err: any, session: any) => { + if (err) { console.error(err); return; } + console.log(session); // {"name": "LASTFM_USERNAME", "key": "THE_USER_SESSION_KEY"} + this._utils.setStoreValue('lastfm.secrets.session', session); + this._authenticated = true; + }); + } + + /** + * Public Methods + */ + public authenticateUser(token: string): void { + this.initializeLastFM(token, this._apiCredentials) + } + + constructor(utils: any) { + this._utils = utils; + this.authenticateUser("") + } + + public onReady(win: Electron.BrowserWindow): void { + + this._utils.getIPCMain().handle('lfm_new:url', (event: any) => { + console.debug('lfm_new:url', event) + return this._lfm.getAuthenticationUrl({"cb": "cider://auth/lastfm"}) + }) + + this._utils.getIPCMain().on('lfm_new:auth', (event: any, token: string) => { + console.debug('lfm_new:auth', event, token) + this.authenticateUser(token) + }) } + } \ No newline at end of file From d4c8d9001aa527385a091edf9992c90e18b6b422 Mon Sep 17 00:00:00 2001 From: Core <64542347+coredev-uk@users.noreply.github.com> Date: Wed, 15 Jun 2022 20:23:13 +0100 Subject: [PATCH 04/34] no more mk lookup :) --- package.json | 1 - src/main/base/app.ts | 7 +- src/main/base/plugins.ts | 3 +- src/main/base/store.ts | 8 +- src/main/plugins/lastfm.ts | 216 ++++++++++++++++++++++++++ src/main/plugins/lfm_new.ts | 106 ------------- src/renderer/main/vueapp.js | 31 ---- src/renderer/views/pages/settings.ejs | 60 ++++--- 8 files changed, 250 insertions(+), 182 deletions(-) create mode 100644 src/main/plugins/lastfm.ts delete mode 100644 src/main/plugins/lfm_new.ts diff --git a/package.json b/package.json index fdceb0f6..5ca5c12b 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,6 @@ "get-port": "^5.1.1", "jimp": "^0.16.1", "jsonc": "^2.0.0", - "lastfm-autocorrect": "^1.0.0", "lastfmapi": "^0.1.1", "mdns-js": "git+https://github.com/ciderapp/node-mdns-js.git", "mpris-service": "^2.1.2", diff --git a/src/main/base/app.ts b/src/main/base/app.ts index 2799eb9f..24dd1e4f 100644 --- a/src/main/base/app.ts +++ b/src/main/base/app.ts @@ -164,11 +164,8 @@ export class AppEvents { if (arg.includes('auth')) { const authURI = arg.split('/auth/')[1] if (authURI.startsWith('lastfm')) { // If we wanted more auth options - // const authKey = authURI.split('lastfm?token=')[1]; - // utils.setStoreValue('lastfm.enabled', true); - // utils.setStoreValue('lastfm.auth_token', authKey); - // utils.getWindow().webContents.send('LastfmAuthenticated', authKey); - this.plugin.callPlugin('lastfm', 'authenticateUser', authURI.split('lastfm?token=')[1]); + console.log('token: ', authURI.split('lastfm?token=')[1]) + utils.getWindow().webContents.executeJavaScript(`ipcRenderer.send('lastfm:auth', "${authURI.split('lastfm?token=')[1]}")`).catch(console.error) } } // Play diff --git a/src/main/base/plugins.ts b/src/main/base/plugins.ts index d51e8a85..24402278 100644 --- a/src/main/base/plugins.ts +++ b/src/main/base/plugins.ts @@ -107,7 +107,8 @@ export class Plugins { try{ this.pluginsList[plugin][event](...args); }catch(e) { - console.log(`[${plugin}] Plugin error: ${e}`); + console.error(`[${plugin}] An error was encountered: ${e}`); + console.error(e) } } } diff --git a/src/main/base/store.ts b/src/main/base/store.ts index 53f3a42a..76b96a43 100644 --- a/src/main/base/store.ts +++ b/src/main/base/store.ts @@ -222,12 +222,10 @@ export class Store { "lastfm": { "enabled": false, "scrobble_after": 30, - "enabledRemoveFeaturingArtists": true, - "filterLoop": true, - "NowPlaying": "true", "secrets": { - "auth_token": "", - "session": {}, + "username": "", + "key": "", + "token": "" } }, diff --git a/src/main/plugins/lastfm.ts b/src/main/plugins/lastfm.ts new file mode 100644 index 00000000..5c3c9767 --- /dev/null +++ b/src/main/plugins/lastfm.ts @@ -0,0 +1,216 @@ +// https://github.com/maxkueng/node-lastfmapi +// https://github.com/maxkueng/lastfm-autocorrect +// @todo: add autocorrect +// @todo: add scrobble and filter to prevent no-title-found being scrobbled +// @todo: handle session keys through config to stop aids session.json + +export default class lastfm { + + /** + * Base Plugin Information + */ + public name: string = 'LastFM Plugin for Cider'; + public version: string = '2.0.0'; + public author: string = 'Core (Cider Collective)'; + + /** + * Private variables for interaction in plugins + */ + private _attributes: any; + private _apiCredentials = { + key: "f9986d12aab5a0fe66193c559435ede3", + secret: "acba3c29bd5973efa38cc2f0b63cc625" + } + /** + * Plugin Initialization + */ + private _lfm: any = null; + private _authenticated: boolean = false; + private _utils: any = null; + private _activityCache: any = { + details: '', + state: '', + largeImageKey: '', + largeImageText: '', + smallImageKey: '', + smallImageText: '', + instance: false + }; + + + /** + * Public Methods + */ + + constructor(utils: any) { + this._utils = utils; + this.initializeLastFM("", this._apiCredentials) + } + + onReady(win: Electron.BrowserWindow): void { + + // Register the ipcMain handlers + this._utils.getIPCMain().handle('lastfm:url', (event: any) => { + // console.debug('lastfm:url', event) + return this._lfm.getAuthenticationUrl({"cb": "cider://auth/lastfm"}) + }) + + this._utils.getIPCMain().on('lastfm:auth', (event: any, token: string) => { + // console.debug('lastfm:auth', event, token) + this.authenticateLastFM(token) + }) + } + + /** + * Runs on playback State Change + * @param attributes Music Attributes (attributes.status = current state) + */ + onPlaybackStateDidChange(attributes: object): void { + this._attributes = attributes + // this.scrobbleTrack(attributes) + } + + /** + * Runs on song change + * @param attributes Music Attributes + */ + onNowPlayingItemDidChange(attributes: object): void { + this._attributes = attributes + this.scrobbleTrack(attributes) + } + + /** + * Initialize LastFM + * @param token + * @param api + * @private + */ + private initializeLastFM(token: string, api: { key: string, secret: string }): void { + const LastfmAPI = require("lastfmapi") + this._lfm = new LastfmAPI({ + 'api_key': api.key, + 'secret': api.secret, + }); + + if (this._utils.getStoreValue("lastfm.secrets.username") && this._utils.getStoreValue("lastfm.secrets.key")) { + this._lfm.setSessionCredentials(this._utils.getStoreValue("lastfm.secrets.session.username"), this._utils.getStoreValue("lastfm.secrets.session.key")); + this._authenticated = true; + } else { + this.authenticateLastFM(token) + } + } + + /** + * Authenticate the user with the given token + * @param token + * @private + */ + private authenticateLastFM(token: string): void { + if (!token) return; + this._lfm.authenticate(token, (err: any, session: any) => { + if (err) { + console.error(err); + return; + } + console.log(session); // {"name": "LASTFM_USERNAME", "key": "THE_USER_SESSION_KEY"} + this._utils.setStoreValue("lastfm.secrets.token", token) + this._utils.setStoreValue('lastfm.secrets.username', session.username); + this._utils.setStoreValue('lastfm.secrets.key', session.key); + this._authenticated = true; + }); + } + + /** + * Verifies the track information with lastfm + * @param attributes + * @private + */ + private verifyTrack(attributes: any): object { + if (!attributes) return {}; + + if (!attributes.lfmAlbum) { + return this._lfm.album.getInfo({ + "artist": attributes.artistName, + "album": attributes.albumName + }, (err: any, data: any) => { + if (err) { + console.error(`[${lastfm.name}] [album.getInfo] Error: ${err}`) + return {}; + } + if (data) { + attributes.lfmAlbum = data + } + this.scrobbleTrack(attributes) + }) + } else { + return this._lfm.track.getCorrection(attributes.artistName, attributes.name, (err: any, data: any) => { + if (err) { + console.error(`[${lastfm.name}] [track.getCorrection] Error: ${err}`) + console.error(err) + return {}; + } + if (data) { + attributes.lfmTrack = data.correction.track + } + this.scrobbleTrack(attributes) + }) + } + + + } + + /** + * Scrobbles the track to lastfm + * @param attributes + * @private + */ + private scrobbleTrack(attributes: any): void { + if (!attributes?.lfmTrack || !attributes?.lfmAlbum) { + this.verifyTrack(attributes) + return + } + + if (!this._authenticated || !attributes) return; + // Scrobble + + const scrobble = { + 'artist': attributes.lfmTrack.artist.name, + 'track': attributes.lfmTrack.name, + 'album': attributes.lfmAlbum.name, + 'albumArtist': attributes.lfmAlbum.artist, + 'timestamp': new Date().getTime() / 1000, + 'trackNumber': attributes.trackNumber, + 'duration': attributes.durationInMillis / 1000, + } + if (!this._utils.getApp().isPackaged) { + console.debug(scrobble) + } + this._lfm.track.scrobble(scrobble, (err: any, res: any) => { + if (err) { + console.error(`[${lastfm.name}] [lastfm:scrobble] Scrobble failed: ${err.message}`); + } else { + console.debug(`[${lastfm.name}] [lastfm:scrobble] Track scrobbled: ${res}`); + } + }); + this._activityCache = attributes + } + + private updateNowPlaying(attributes: any): void { + if (!this._authenticated) return; + this._lfm.track.updateNowPlaying({ + 'artist': attributes.artistName, + 'track': attributes.name, + 'album': attributes.albumName, + 'albumArtist': attributes.albumName, + 'trackNumber': attributes.trackNumber, + 'duration': attributes.duration / 1000, + }, function (err: any, scrobbled: any) { + if (err) { + return console.error('[LastFM] An error occurred while updating now playing', err); + } + + console.log('[LastFM] Successfully updated now playing: ', scrobbled); + }); + } + +} \ No newline at end of file diff --git a/src/main/plugins/lfm_new.ts b/src/main/plugins/lfm_new.ts deleted file mode 100644 index 8bcbba88..00000000 --- a/src/main/plugins/lfm_new.ts +++ /dev/null @@ -1,106 +0,0 @@ -import {app} from 'electron'; - -// https://github.com/maxkueng/node-lastfmapi -// https://github.com/maxkueng/lastfm-autocorrect -// @todo: add autocorrect -// @todo: add scrobble and filter to prevent no-title-found being scrobbled -// @todo: handle session keys through config to stop aids session.json - -export default class lfm_new { - - /** - * Base Plugin Information - */ - public name: string = 'LastFM Plugin for Cider'; - public version: string = '2.0.0'; - public author: string = 'Core (Cider Collective)'; - - /** - * Private variables for interaction in plugins - */ - private _attributes: any; - private _apiCredentials = { - key: "f9986d12aab5a0fe66193c559435ede3", - secret: "acba3c29bd5973efa38cc2f0b63cc625" - } - - /** - * Plugin Initialization - */ - private _lfm: any = null; - private _authenticated: boolean = false; - private _utils: any = null; - private _activityCache: any = { - details: '', - state: '', - largeImageKey: '', - largeImageText: '', - smallImageKey: '', - smallImageText: '', - instance: false - }; - - /** - * Initialize LastFM - * @param token - * @param api - * @private - */ - private initializeLastFM(token: string, api: {key: string, secret: string}): void { - const LastfmAPI = require("lastfmapi") - this._lfm = new LastfmAPI({ - 'api_key' : api.key, - 'secret' : api.secret, - }); - - if (this._utils.getStoreValue("lastfm.secrets.session")) { - this._lfm.setSessionCredentials(this._utils.getStoreValue("lastfm.secrets.session")); - this._authenticated = true; - } else { - this.authenticateLastFM(token) - } - } - - /** - * Authenticate the user with the given token - * @param token - * @private - */ - private authenticateLastFM(token: string): void { - if (!token) return; - this._lfm.authenticate(token, (err: any, session: any) => { - if (err) { console.error(err); return; } - console.log(session); // {"name": "LASTFM_USERNAME", "key": "THE_USER_SESSION_KEY"} - this._utils.setStoreValue('lastfm.secrets.session', session); - this._authenticated = true; - }); - } - - /** - * Public Methods - */ - public authenticateUser(token: string): void { - this.initializeLastFM(token, this._apiCredentials) - } - - constructor(utils: any) { - this._utils = utils; - this.authenticateUser("") - } - - public onReady(win: Electron.BrowserWindow): void { - - this._utils.getIPCMain().handle('lfm_new:url', (event: any) => { - console.debug('lfm_new:url', event) - return this._lfm.getAuthenticationUrl({"cb": "cider://auth/lastfm"}) - }) - - this._utils.getIPCMain().on('lfm_new:auth', (event: any, token: string) => { - console.debug('lfm_new:auth', event, token) - this.authenticateUser(token) - }) - } - - - -} \ No newline at end of file diff --git a/src/renderer/main/vueapp.js b/src/renderer/main/vueapp.js index 94a39304..58f54f25 100644 --- a/src/renderer/main/vueapp.js +++ b/src/renderer/main/vueapp.js @@ -4339,37 +4339,6 @@ const app = new Vue({ } }, - LastFMDeauthorize() { - ipcRenderer.invoke('setStoreValue', 'lastfm.enabled', false).catch((e) => console.error(e)); - ipcRenderer.invoke('setStoreValue', 'lastfm.auth_token', '').catch((e) => console.error(e)); - app.cfg.lastfm.auth_token = ""; - app.cfg.lastfm.enabled = false; - const element = document.getElementById('lfmConnect'); - element.innerHTML = app.getLz('term.connect'); - element.onclick = app.LastFMAuthenticate; - }, - LastFMAuthenticate() { - console.log("[LastFM] Received LastFM authentication callback") - const element = document.getElementById('lfmConnect'); - // new key : f9986d12aab5a0fe66193c559435ede3 - window.open('https://www.last.fm/api/auth?api_key=f9986d12aab5a0fe66193c559435ede3&cb=cider://auth/lastfm'); - element.innerText = app.getLz('term.connecting') + '...'; - - /* Just a timeout for the button */ - setTimeout(() => { - if (element.innerText === app.getLz('term.connecting') + '...') { - element.innerText = app.getLz('term.connect'); - console.warn('[LastFM] Attempted connection timed out.'); - } - }, 20000); - - ipcRenderer.on('LastfmAuthenticated', function (_event, lfmAuthKey) { - app.cfg.lastfm.auth_token = lfmAuthKey; - app.cfg.lastfm.enabled = true; - element.innerHTML = `${app.getLz('term.disconnect')}\n

(${app.getLz('term.authed')}: ${lfmAuthKey})

`; - element.onclick = app.LastFMDeauthorize; - }); - }, fullscreen(flag) { this.fullscreenState = flag; if (flag) { diff --git a/src/renderer/views/pages/settings.ejs b/src/renderer/views/pages/settings.ejs index 30774200..1cca7314 100644 --- a/src/renderer/views/pages/settings.ejs +++ b/src/renderer/views/pages/settings.ejs @@ -1064,7 +1064,7 @@
@@ -1079,37 +1079,6 @@ -
-
- {{$root.getLz('settings.option.connectivity.lastfmScrobble.nowPlaying')}} -
-
- -
-
-
-
- {{$root.getLz('settings.option.connectivity.lastfmScrobble.removeFeatured')}} -
-
- -
-
-
-
- {{$root.getLz('settings.option.connectivity.lastfmScrobble.filterLoop')}} -
-
- -
-
@@ -1504,7 +1473,32 @@ }, reloadDiscordRPC() { ipcRenderer.send('reloadRPC') - } + }, + lfmDisconnect(event) { + ipcRenderer.invoke('setStoreValue', 'lastfm.enabled', false).catch((e) => console.error(e)); + ipcRenderer.invoke('setStoreValue', 'lastfm.secrets.session', {}).catch((e) => console.error(e)); + event.target.innerHTML = app.getLz('term.connect'); + event.target.onclick = this.lfmAuthorize; + }, + async lfmAuthorize(event) { + console.debug("[lastfm:authorize] Token received.") + window.open(await ipcRenderer.invoke('lastfm:url')); + event.target.innerText = app.getLz('term.connecting') + '...'; + + /* Just a timeout for the button */ + setTimeout(() => { + if (event.target.innerText === app.getLz('term.connecting') + '...') { + event.target.innerText = app.getLz('term.connect'); + console.warn('[lastfm:authorize] Last.fm authorization timed out.'); + } + }, 20000); + + ipcRenderer.on('lastfm:renderer-auth', function (event, session) { + element.innerHTML = `${app.getLz('term.disconnect')}\n

(${app.getLz('term.authed')}: ${session.username})

`; + element.onclick = this.lfmDisconnect; + }); + + }, } }) \ No newline at end of file From 5c955820dd007b74d04c831b33169241e50c4190 Mon Sep 17 00:00:00 2001 From: Core <64542347+coredev-uk@users.noreply.github.com> Date: Wed, 15 Jun 2022 20:28:18 +0100 Subject: [PATCH 05/34] also no more session.json --- src/main/plugins/lastfm.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/plugins/lastfm.ts b/src/main/plugins/lastfm.ts index 5c3c9767..902671e7 100644 --- a/src/main/plugins/lastfm.ts +++ b/src/main/plugins/lastfm.ts @@ -93,7 +93,7 @@ export default class lastfm { }); if (this._utils.getStoreValue("lastfm.secrets.username") && this._utils.getStoreValue("lastfm.secrets.key")) { - this._lfm.setSessionCredentials(this._utils.getStoreValue("lastfm.secrets.session.username"), this._utils.getStoreValue("lastfm.secrets.session.key")); + this._lfm.setSessionCredentials(this._utils.getStoreValue("lastfm.secrets.username"), this._utils.getStoreValue("lastfm.secrets.key")); this._authenticated = true; } else { this.authenticateLastFM(token) @@ -112,7 +112,6 @@ export default class lastfm { console.error(err); return; } - console.log(session); // {"name": "LASTFM_USERNAME", "key": "THE_USER_SESSION_KEY"} this._utils.setStoreValue("lastfm.secrets.token", token) this._utils.setStoreValue('lastfm.secrets.username', session.username); this._utils.setStoreValue('lastfm.secrets.key', session.key); From f98a82240b23228639fc588fd4c60af084e6240f Mon Sep 17 00:00:00 2001 From: Core <64542347+coredev-uk@users.noreply.github.com> Date: Wed, 15 Jun 2022 21:22:04 +0100 Subject: [PATCH 06/34] Now Playing Working Commented some annoying mpris debugs --- src/main/base/store.ts | 2 +- src/main/plugins/lastfm.ts | 102 ++++++++++++++++++++----------------- src/main/plugins/mpris.ts | 6 +-- 3 files changed, 60 insertions(+), 50 deletions(-) diff --git a/src/main/base/store.ts b/src/main/base/store.ts index 76b96a43..56b0743f 100644 --- a/src/main/base/store.ts +++ b/src/main/base/store.ts @@ -221,7 +221,7 @@ export class Store { }, "lastfm": { "enabled": false, - "scrobble_after": 30, + "scrobble_after": 50, "secrets": { "username": "", "key": "", diff --git a/src/main/plugins/lastfm.ts b/src/main/plugins/lastfm.ts index 902671e7..c49b0b2d 100644 --- a/src/main/plugins/lastfm.ts +++ b/src/main/plugins/lastfm.ts @@ -26,17 +26,10 @@ export default class lastfm { */ private _lfm: any = null; private _authenticated: boolean = false; + private _scrobbleDelay: any = null; private _utils: any = null; - private _activityCache: any = { - details: '', - state: '', - largeImageKey: '', - largeImageText: '', - smallImageKey: '', - smallImageText: '', - instance: false - }; - + private _scrobbleCache: any = {}; + private _nowPlayingCache: any = {}; /** * Public Methods @@ -74,9 +67,14 @@ export default class lastfm { * Runs on song change * @param attributes Music Attributes */ - onNowPlayingItemDidChange(attributes: object): void { + onNowPlayingItemDidChange(attributes: any): void { this._attributes = attributes + if (!attributes?.lfmTrack || !attributes?.lfmAlbum) { + this.verifyTrack(attributes) + return + } this.scrobbleTrack(attributes) + this.updateNowPlayingTrack(attributes) } /** @@ -139,7 +137,7 @@ export default class lastfm { if (data) { attributes.lfmAlbum = data } - this.scrobbleTrack(attributes) + this.onNowPlayingItemDidChange(attributes) }) } else { return this._lfm.track.getCorrection(attributes.artistName, attributes.name, (err: any, data: any) => { @@ -151,7 +149,7 @@ export default class lastfm { if (data) { attributes.lfmTrack = data.correction.track } - this.scrobbleTrack(attributes) + this.onNowPlayingItemDidChange(attributes) }) } @@ -164,52 +162,64 @@ export default class lastfm { * @private */ private scrobbleTrack(attributes: any): void { - if (!attributes?.lfmTrack || !attributes?.lfmAlbum) { - this.verifyTrack(attributes) - return + if (!this._authenticated || !attributes || (this._scrobbleCache.track === attributes.lfmTrack.name)) return; + + if (this._scrobbleDelay) { + clearTimeout(this._scrobbleDelay); } - if (!this._authenticated || !attributes) return; - // Scrobble + // Scrobble delay + this._scrobbleDelay = setTimeout(() => { - const scrobble = { + // Scrobble + const scrobble = { + 'artist': attributes.lfmTrack.artist.name, + 'track': attributes.lfmTrack.name, + 'album': attributes.lfmAlbum.name, + 'albumArtist': attributes.lfmAlbum.artist, + 'timestamp': new Date().getTime() / 1000, + 'trackNumber': attributes.trackNumber, + 'duration': attributes.durationInMillis / 1000, + } + + // Easy Debugging + if (!this._utils.getApp().isPackaged) { + console.debug(scrobble) + } + + // Scrobble the track + this._lfm.track.scrobble(scrobble, (err: any, _res: any) => { + if (err) { + console.error(`[${lastfm.name}] [lastfm:scrobble] Scrobble failed: ${err.message}`); + } else { + console.debug(`[${lastfm.name}] [lastfm:scrobble] Track scrobbled: ${scrobble.artist} - ${scrobble.track}`); + this._scrobbleCache = scrobble + } + }); + }, Math.round(attributes.durationInMillis * Math.min((this._utils.getStoreValue("lastfm.scrobble_after") / 100), 0.8))) + } + + private updateNowPlayingTrack(attributes: any): void { + if (!this._authenticated || !attributes || (this._nowPlayingCache.track === attributes.lfmTrack.name)) return; + + const nowPlaying = { 'artist': attributes.lfmTrack.artist.name, 'track': attributes.lfmTrack.name, 'album': attributes.lfmAlbum.name, - 'albumArtist': attributes.lfmAlbum.artist, - 'timestamp': new Date().getTime() / 1000, 'trackNumber': attributes.trackNumber, 'duration': attributes.durationInMillis / 1000, + 'albumArtist': attributes.lfmAlbum.artist, } - if (!this._utils.getApp().isPackaged) { - console.debug(scrobble) - } - this._lfm.track.scrobble(scrobble, (err: any, res: any) => { + + this._lfm.track.updateNowPlaying(nowPlaying, (err: any, res: any) => { if (err) { - console.error(`[${lastfm.name}] [lastfm:scrobble] Scrobble failed: ${err.message}`); + console.error(`[${lastfm.name}] [lastfm:updateNowPlaying] Now Playing Update failed: ${err.message}`); } else { - console.debug(`[${lastfm.name}] [lastfm:scrobble] Track scrobbled: ${res}`); + console.log(res) + console.debug(`[${lastfm.name}] [lastfm:updateNowPlaying] Now Playing Updated: ${nowPlaying.artist} - ${nowPlaying.track}`); + this._nowPlayingCache = nowPlaying } }); - this._activityCache = attributes - } - - private updateNowPlaying(attributes: any): void { - if (!this._authenticated) return; - this._lfm.track.updateNowPlaying({ - 'artist': attributes.artistName, - 'track': attributes.name, - 'album': attributes.albumName, - 'albumArtist': attributes.albumName, - 'trackNumber': attributes.trackNumber, - 'duration': attributes.duration / 1000, - }, function (err: any, scrobbled: any) { - if (err) { - return console.error('[LastFM] An error occurred while updating now playing', err); - } - - console.log('[LastFM] Successfully updated now playing: ', scrobbled); - }); } } \ No newline at end of file diff --git a/src/main/plugins/mpris.ts b/src/main/plugins/mpris.ts index 25730ee9..6b70c5c8 100644 --- a/src/main/plugins/mpris.ts +++ b/src/main/plugins/mpris.ts @@ -37,7 +37,7 @@ export default class mpris { * @private */ private static runMediaEvent(type: string) { - console.debug(`[Plugin][${this.name}] ${type}.`); + // console.debug(`[Plugin][${this.name}] ${type}.`); mpris.utils.getWindow().webContents.executeJavaScript(`MusicKitInterop.${type}()`).catch(console.error) } @@ -188,7 +188,7 @@ export default class mpris { */ @mpris.linuxOnly onPlaybackStateDidChange(attributes: object): void { - console.debug(`[Plugin][${mpris.name}] onPlaybackStateDidChange.`); + // console.debug(`[Plugin][${mpris.name}] onPlaybackStateDidChange.`); mpris.updatePlayerState(attributes) } @@ -198,7 +198,7 @@ export default class mpris { */ @mpris.linuxOnly onNowPlayingItemDidChange(attributes: object): void { - console.debug(`[Plugin][${mpris.name}] onMetadataDidChange.`); + // console.debug(`[Plugin][${mpris.name}] onMetadataDidChange.`); mpris.updatePlayer(attributes); } From 47e3ad5b446a8af3f0d04b574581cecd358c79d6 Mon Sep 17 00:00:00 2001 From: Core <64542347+coredev-uk@users.noreply.github.com> Date: Wed, 15 Jun 2022 21:33:32 +0100 Subject: [PATCH 07/34] removed redundant code --- src/preload/cider-preload.js | 49 +++++++----------------------------- 1 file changed, 9 insertions(+), 40 deletions(-) diff --git a/src/preload/cider-preload.js b/src/preload/cider-preload.js index 44ba7589..3923fbd3 100644 --- a/src/preload/cider-preload.js +++ b/src/preload/cider-preload.js @@ -11,9 +11,6 @@ const MusicKitInterop = { if (MusicKitInterop.filterTrack(attributes, true, false)) { global.ipcRenderer.send('playbackStateDidChange', attributes) global.ipcRenderer.send('wsapi-updatePlaybackState', attributes); - // if (typeof _plugins != "undefined") { - // _plugins.execute("OnPlaybackStateChanged", {Attributes: MusicKitInterop.getAttributes()}) - // } } }); @@ -24,7 +21,7 @@ const MusicKitInterop = { /** wsapi */ MusicKit.getInstance().addEventListener(MusicKit.Events.nowPlayingItemDidChange, async () => { - console.debug('nowPlayingItemDidChange') + console.debug('[cider:preload] nowPlayingItemDidChange') const attributes = MusicKitInterop.getAttributes() const trackFilter = MusicKitInterop.filterTrack(attributes, false, true) @@ -32,12 +29,6 @@ const MusicKitInterop = { global.ipcRenderer.send('nowPlayingItemDidChange', attributes); } - // LastFM's Custom Call - await MusicKitInterop.modifyNamesOnLocale(); - if (trackFilter || !app.cfg.lastfm.filterLoop) { - global.ipcRenderer.send('nowPlayingItemDidChangeLastFM', attributes); - } - if (MusicKit.getInstance().nowPlayingItem) { await this.sleep(750); MusicKit.getInstance().playbackRate = app.cfg.audio.playbackRate; @@ -49,38 +40,16 @@ const MusicKitInterop = { }) MusicKit.getInstance().addEventListener(MusicKit.Events.mediaPlaybackError, (e) => { - console.warn(`[mediaPlaybackError] ${e}`); + console.warn(`[cider:preload] mediaPlaybackError] ${e}`); }) }, sleep(ms) { return new Promise((resolve) => { - setTimeout(resolve, ms); + setTimeout(resolve, ms); }); }, - async modifyNamesOnLocale() { - if (app.mklang === '' || app.mklang == null) { - return; - } - const mk = MusicKit.getInstance() - const nowPlayingItem = mk.nowPlayingItem; - if ((nowPlayingItem?._songId ?? nowPlayingItem?.songId) == null){ - return; - } - const id = nowPlayingItem?._songId ?? (nowPlayingItem?.songId ?? nowPlayingItem?.id) - if (id != null && id !== -1) { - try{ - const query = await mk.api.v3.music(`/v1${(((nowPlayingItem?._songId ?? nowPlayingItem?.songId) != null) && ((nowPlayingItem?._songId ?? nowPlayingItem?.songId) !== -1)) ? `/catalog/${mk.storefrontId}/` : `/me/library/`}songs/${id}?l=${app.mklang}`); - if (query?.data?.data[0]){ - let attrs = query?.data?.data[0]?.attributes; - if (attrs?.name) { nowPlayingItem.attributes.name = attrs?.name ?? ''} - if (attrs?.albumName) { nowPlayingItem.attributes.albumName = attrs?.albumName ?? ''} - if (attrs?.artistName) { nowPlayingItem.attributes.artistName = attrs?.artistName ?? ''} - - }} catch (e) { } - } else {} - }, getAttributes: function () { const mk = MusicKit.getInstance() const nowPlayingItem = mk.nowPlayingItem; @@ -96,8 +65,8 @@ const MusicKitInterop = { attributes.playParams = attributes?.playParams ?? {id: 'no-id-found'}; attributes.playParams.id = attributes?.playParams?.id ?? 'no-id-found'; attributes.url = { - cider: `https://cider.sh/link?play/s/${nowPlayingItem?._songId ?? (nowPlayingItem?.songId ??'no-id-found')}`, - appleMusic: attributes.websiteUrl ? attributes.websiteUrl : `https://music.apple.com/${mk.storefrontId}/song/${nowPlayingItem?._songId ?? (nowPlayingItem?.songId ??'no-id-found')}` + cider: `https://cider.sh/link?play/s/${nowPlayingItem?._songId ?? (nowPlayingItem?.songId ?? 'no-id-found')}`, + appleMusic: attributes.websiteUrl ? attributes.websiteUrl : `https://music.apple.com/${mk.storefrontId}/song/${nowPlayingItem?._songId ?? (nowPlayingItem?.songId ?? 'no-id-found')}` } if (attributes.playParams.id === 'no-id-found') { attributes.playParams.id = nowPlayingItem?.id ?? 'no-id-found'; @@ -115,7 +84,7 @@ const MusicKitInterop = { attributes?.playParams?.id === cache.playParams.id ? Date.now() + attributes?.remainingTime : attributes?.startTime + attributes?.durationInMillis - ); + ); return attributes; }, @@ -156,19 +125,19 @@ const MusicKitInterop = { // } catch (e) { } // if (MusicKit.getInstance().queue.nextPlayableItemIndex != -1 && MusicKit.getInstance().queue.nextPlayableItemIndex != null) // MusicKit.getInstance().changeToMediaAtIndex(MusicKit.getInstance().queue.nextPlayableItemIndex); - MusicKit.getInstance().skipToNextItem().then(r => console.debug(`[MusicKitInterop.next] Skipping to Next ${r}`)); + MusicKit.getInstance().skipToNextItem().then(r => console.debug(`[cider:preload] [next] Skipping to Next ${r}`)); }, previous: () => { // if (MusicKit.getInstance().queue.previousPlayableItemIndex != -1 && MusicKit.getInstance().queue.previousPlayableItemIndex != null) // MusicKit.getInstance().changeToMediaAtIndex(MusicKit.getInstance().queue.previousPlayableItemIndex); - MusicKit.getInstance().skipToPreviousItem().then(r => console.debug(`[MusicKitInterop.previous] Skipping to Previous ${r}`)); + MusicKit.getInstance().skipToPreviousItem().then(r => console.debug(`[cider:preload] [previous] Skipping to Previous ${r}`)); } } process.once('loaded', () => { - console.debug("Setting ipcRenderer") + console.debug("[cider:preload] IPC Listeners Created!") global.MusicKitInterop = MusicKitInterop; }); From 2827dfb36dc95dafe980ca75db8b677f30b92c34 Mon Sep 17 00:00:00 2001 From: Core <64542347+coredev-uk@users.noreply.github.com> Date: Wed, 15 Jun 2022 22:11:54 +0100 Subject: [PATCH 08/34] renderer side of lastfm updated --- src/i18n/README.md | 3 +++ src/i18n/en_US.json | 1 + src/i18n/source/en_US.json | 1 + src/main/plugins/lastfm.ts | 12 ++++++++++- src/renderer/views/pages/settings.ejs | 29 ++++++++------------------- 5 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/i18n/README.md b/src/i18n/README.md index a21bf49e..575da984 100644 --- a/src/i18n/README.md +++ b/src/i18n/README.md @@ -448,3 +448,6 @@ Update 10/06/2022 20:00 UTC * `settings.option.visual.purplePodcastPlaybackBar`: Added to `en_US` +Update 15/06/2022 20:00 UTC + +* `settings.notyf.connectivity.lastfmScrobble.connectError`: Added to `en_US` \ No newline at end of file diff --git a/src/i18n/en_US.json b/src/i18n/en_US.json index 692e86c2..06a09bdf 100644 --- a/src/i18n/en_US.json +++ b/src/i18n/en_US.json @@ -539,6 +539,7 @@ "settings.option.connectivity.lastfmScrobble.nowPlaying": "Enable Last.fm Now Playing", "settings.option.connectivity.lastfmScrobble.removeFeatured": "Remove featuring artists from song title (Last.fm)", "settings.option.connectivity.lastfmScrobble.filterLoop": "Filter looped track (Last.fm)", + "settings.notyf.connectivity.lastfmScrobble.connectError": "Last.fm Connection Timed Out", "settings.header.debug": "Debug", "settings.option.debug.copy_log": "Copy logs to clipboard", "settings.option.debug.openAppData": "Open Cider Folder", diff --git a/src/i18n/source/en_US.json b/src/i18n/source/en_US.json index e202b0bf..3a05d741 100644 --- a/src/i18n/source/en_US.json +++ b/src/i18n/source/en_US.json @@ -527,6 +527,7 @@ "settings.option.connectivity.lastfmScrobble.nowPlaying": "Enable Last.fm Now Playing", "settings.option.connectivity.lastfmScrobble.removeFeatured": "Remove featuring artists from song title (Last.fm)", "settings.option.connectivity.lastfmScrobble.filterLoop": "Filter looped track (Last.fm)", + "settings.notyf.connectivity.lastfmScrobble.connectError": "Last.fm Connection Timed Out", "settings.header.debug": "Debug", "settings.option.debug.copy_log": "Copy logs to clipboard", "settings.option.debug.openAppData": "Open Cider Folder", diff --git a/src/main/plugins/lastfm.ts b/src/main/plugins/lastfm.ts index c49b0b2d..4960781d 100644 --- a/src/main/plugins/lastfm.ts +++ b/src/main/plugins/lastfm.ts @@ -52,6 +52,15 @@ export default class lastfm { // console.debug('lastfm:auth', event, token) this.authenticateLastFM(token) }) + + this._utils.getIPCMain().on('lastfm:disconnect', (event: any) => { + this._lfm.setSessionCredentials(null, null); + this._authenticated = false; + this._utils.setStoreValue('lastfm.enabled', false) + this._utils.setStoreValue('lastfm.secrets.username', "") + this._utils.setStoreValue('lastfm.secrets.key', "") + console.debug('[lastfm] [disconnect] Disconnected') + }) } /** @@ -110,10 +119,11 @@ export default class lastfm { console.error(err); return; } - this._utils.setStoreValue("lastfm.secrets.token", token) this._utils.setStoreValue('lastfm.secrets.username', session.username); this._utils.setStoreValue('lastfm.secrets.key', session.key); + this._utils.setStoreValue('lastfm.enabled', true) this._authenticated = true; + console.debug(`[${lastfm.name}] [authenticate] Authenticated as ${session.username}`) }); } diff --git a/src/renderer/views/pages/settings.ejs b/src/renderer/views/pages/settings.ejs index 1cca7314..8e0d45aa 100644 --- a/src/renderer/views/pages/settings.ejs +++ b/src/renderer/views/pages/settings.ejs @@ -1063,8 +1063,11 @@ {{$root.getLz('settings.option.connectivity.lastfmScrobble')}}
- +
@@ -1346,14 +1349,6 @@ this.canChangeHash = true } }) - - if (app.cfg.lastfm.enabled) { - const element = document.getElementById('lfmConnect'); - if (element) { - element.innerHTML = `Disconnect\n

(Authed: ${app.cfg.lastfm.auth_token})

`; - element.onclick = app.LastFMDeauthorize; - } - } }, methods: { windowBgStyleChange() { @@ -1474,14 +1469,10 @@ reloadDiscordRPC() { ipcRenderer.send('reloadRPC') }, - lfmDisconnect(event) { - ipcRenderer.invoke('setStoreValue', 'lastfm.enabled', false).catch((e) => console.error(e)); - ipcRenderer.invoke('setStoreValue', 'lastfm.secrets.session', {}).catch((e) => console.error(e)); - event.target.innerHTML = app.getLz('term.connect'); - event.target.onclick = this.lfmAuthorize; + lfmDisconnect() { + ipcRenderer.send('lastfm:disconnect'); }, async lfmAuthorize(event) { - console.debug("[lastfm:authorize] Token received.") window.open(await ipcRenderer.invoke('lastfm:url')); event.target.innerText = app.getLz('term.connecting') + '...'; @@ -1489,15 +1480,11 @@ setTimeout(() => { if (event.target.innerText === app.getLz('term.connecting') + '...') { event.target.innerText = app.getLz('term.connect'); + app.notyf.error(app.getLz('settings.notyf.connectivity.lastfmScrobble.connectError')); console.warn('[lastfm:authorize] Last.fm authorization timed out.'); } }, 20000); - ipcRenderer.on('lastfm:renderer-auth', function (event, session) { - element.innerHTML = `${app.getLz('term.disconnect')}\n

(${app.getLz('term.authed')}: ${session.username})

`; - element.onclick = this.lfmDisconnect; - }); - }, } }) From 3e3c38a25f04ab40a1fca0c6195bdb217e6c5c04 Mon Sep 17 00:00:00 2001 From: Core <64542347+coredev-uk@users.noreply.github.com> Date: Wed, 15 Jun 2022 22:13:42 +0100 Subject: [PATCH 09/34] that was bad --- src/main/plugins/lastfm.ts | 7 +------ src/renderer/main/vueapp.js | 6 ++++++ src/renderer/views/pages/settings.ejs | 3 +++ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main/plugins/lastfm.ts b/src/main/plugins/lastfm.ts index 4960781d..db808902 100644 --- a/src/main/plugins/lastfm.ts +++ b/src/main/plugins/lastfm.ts @@ -56,9 +56,6 @@ export default class lastfm { this._utils.getIPCMain().on('lastfm:disconnect', (event: any) => { this._lfm.setSessionCredentials(null, null); this._authenticated = false; - this._utils.setStoreValue('lastfm.enabled', false) - this._utils.setStoreValue('lastfm.secrets.username', "") - this._utils.setStoreValue('lastfm.secrets.key', "") console.debug('[lastfm] [disconnect] Disconnected') }) } @@ -119,9 +116,7 @@ export default class lastfm { console.error(err); return; } - this._utils.setStoreValue('lastfm.secrets.username', session.username); - this._utils.setStoreValue('lastfm.secrets.key', session.key); - this._utils.setStoreValue('lastfm.enabled', true) + this._utils.getWindow().webContents.send('lastfm:authenticated', session) this._authenticated = true; console.debug(`[${lastfm.name}] [authenticate] Authenticated as ${session.username}`) }); diff --git a/src/renderer/main/vueapp.js b/src/renderer/main/vueapp.js index 58f54f25..7e051b58 100644 --- a/src/renderer/main/vueapp.js +++ b/src/renderer/main/vueapp.js @@ -829,6 +829,12 @@ const app = new Vue({ MusicKit.getInstance().videoContainerElement = document.getElementById("apple-music-video-player") + ipcRenderer.on('lastfm:authenticated', (_e, session) => { + app.cfg.lastfm.username = session.username + app.cfg.lastfm.key = session.key + app.cfg.lastfm.enabled = true + }) + ipcRenderer.on('theme-update', async (event, arg) => { await less.refresh(true, true, true) self.setTheme(self.cfg.visual.theme, true) diff --git a/src/renderer/views/pages/settings.ejs b/src/renderer/views/pages/settings.ejs index 8e0d45aa..3aef03bb 100644 --- a/src/renderer/views/pages/settings.ejs +++ b/src/renderer/views/pages/settings.ejs @@ -1470,6 +1470,9 @@ ipcRenderer.send('reloadRPC') }, lfmDisconnect() { + app.cfg.lastfm.enabled = false; + app.cfg.lastfm.username = ""; + app.cfg.lastfm.key = ""; ipcRenderer.send('lastfm:disconnect'); }, async lfmAuthorize(event) { From 69c460ad03a352afad6b66fdd60a82b7082c3929 Mon Sep 17 00:00:00 2001 From: Core <64542347+coredev-uk@users.noreply.github.com> Date: Wed, 15 Jun 2022 22:27:27 +0100 Subject: [PATCH 10/34] patch cider connect renderer issues --- src/main/base/browserwindow.ts | 3 +-- src/renderer/main/vueapp.js | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/base/browserwindow.ts b/src/main/base/browserwindow.ts index 89c54e55..ac84bef7 100644 --- a/src/main/base/browserwindow.ts +++ b/src/main/base/browserwindow.ts @@ -614,8 +614,7 @@ export class BrowserWindow { //region Connect Integration app.get("/connect/set-cc-user/:data", (req, res) => { //utils.getStoreValue('connectUser', JSON.parse()) // [Connect] Save user in store - utils.setStoreValue('connectUser', JSON.parse(req.params.data)) - utils.getWindow().reload() + utils.getWindow().webContents.send('setStoreValue', 'connectUser', JSON.parse(req.params.data)) res.redirect(`https://connect.cidercollective.dev/linked.html`) }); // [Connect] Set auth URL in store for `shell.openExternal` diff --git a/src/renderer/main/vueapp.js b/src/renderer/main/vueapp.js index 7e051b58..4e6af4e7 100644 --- a/src/renderer/main/vueapp.js +++ b/src/renderer/main/vueapp.js @@ -835,6 +835,10 @@ const app = new Vue({ app.cfg.lastfm.enabled = true }) + ipcRenderer.on('setStoreValue', (e, key, value) => { + app.cfg[key] = value + }) + ipcRenderer.on('theme-update', async (event, arg) => { await less.refresh(true, true, true) self.setTheme(self.cfg.visual.theme, true) From bd330c1ec0c31299b697c15af6cf08090210dd78 Mon Sep 17 00:00:00 2001 From: Core <64542347+coredev-uk@users.noreply.github.com> Date: Wed, 15 Jun 2022 23:26:51 +0100 Subject: [PATCH 11/34] various optimisations --- src/i18n/README.md | 4 +++- src/i18n/en_US.json | 2 ++ src/i18n/source/en_US.json | 2 ++ src/main/base/store.ts | 3 +-- src/renderer/main/vueapp.js | 6 ------ src/renderer/views/pages/settings.ejs | 27 +++++++++++++++------------ 6 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/i18n/README.md b/src/i18n/README.md index 575da984..265a6214 100644 --- a/src/i18n/README.md +++ b/src/i18n/README.md @@ -450,4 +450,6 @@ Update 10/06/2022 20:00 UTC Update 15/06/2022 20:00 UTC -* `settings.notyf.connectivity.lastfmScrobble.connectError`: Added to `en_US` \ No newline at end of file +* `settings.notyf.connectivity.lastfmScrobble.connectError`: Added to `en_US` +* `settings.notyf.connectivity.lastfmScrobble.connectSuccess`: Added to `en_US` +* `settings.notyf.connectivity.lastfmScrobble.connecting`: Added to `en_US` \ No newline at end of file diff --git a/src/i18n/en_US.json b/src/i18n/en_US.json index 06a09bdf..e094d697 100644 --- a/src/i18n/en_US.json +++ b/src/i18n/en_US.json @@ -540,6 +540,8 @@ "settings.option.connectivity.lastfmScrobble.removeFeatured": "Remove featuring artists from song title (Last.fm)", "settings.option.connectivity.lastfmScrobble.filterLoop": "Filter looped track (Last.fm)", "settings.notyf.connectivity.lastfmScrobble.connectError": "Last.fm Connection Timed Out", + "settings.notyf.connectivity.lastfmScrobble.connectSuccess": "Last.fm Connection Successful", + "settings.notyf.connectivity.lastfmScrobble.connecting": "Connecting to Last.fm...", "settings.header.debug": "Debug", "settings.option.debug.copy_log": "Copy logs to clipboard", "settings.option.debug.openAppData": "Open Cider Folder", diff --git a/src/i18n/source/en_US.json b/src/i18n/source/en_US.json index 3a05d741..8316123c 100644 --- a/src/i18n/source/en_US.json +++ b/src/i18n/source/en_US.json @@ -528,6 +528,8 @@ "settings.option.connectivity.lastfmScrobble.removeFeatured": "Remove featuring artists from song title (Last.fm)", "settings.option.connectivity.lastfmScrobble.filterLoop": "Filter looped track (Last.fm)", "settings.notyf.connectivity.lastfmScrobble.connectError": "Last.fm Connection Timed Out", + "settings.notyf.connectivity.lastfmScrobble.connectSuccess": "Last.fm Connection Successful", + "settings.notyf.connectivity.lastfmScrobble.connecting": "Connecting to Last.fm...", "settings.header.debug": "Debug", "settings.option.debug.copy_log": "Copy logs to clipboard", "settings.option.debug.openAppData": "Open Cider Folder", diff --git a/src/main/base/store.ts b/src/main/base/store.ts index 56b0743f..fd706f8e 100644 --- a/src/main/base/store.ts +++ b/src/main/base/store.ts @@ -224,8 +224,7 @@ export class Store { "scrobble_after": 50, "secrets": { "username": "", - "key": "", - "token": "" + "key": "" } }, diff --git a/src/renderer/main/vueapp.js b/src/renderer/main/vueapp.js index 4e6af4e7..526bb3b5 100644 --- a/src/renderer/main/vueapp.js +++ b/src/renderer/main/vueapp.js @@ -829,12 +829,6 @@ const app = new Vue({ MusicKit.getInstance().videoContainerElement = document.getElementById("apple-music-video-player") - ipcRenderer.on('lastfm:authenticated', (_e, session) => { - app.cfg.lastfm.username = session.username - app.cfg.lastfm.key = session.key - app.cfg.lastfm.enabled = true - }) - ipcRenderer.on('setStoreValue', (e, key, value) => { app.cfg[key] = value }) diff --git a/src/renderer/views/pages/settings.ejs b/src/renderer/views/pages/settings.ejs index 3aef03bb..5833c872 100644 --- a/src/renderer/views/pages/settings.ejs +++ b/src/renderer/views/pages/settings.ejs @@ -1063,12 +1063,9 @@ {{$root.getLz('settings.option.connectivity.lastfmScrobble')}}
- -
@@ -1471,23 +1468,29 @@ }, lfmDisconnect() { app.cfg.lastfm.enabled = false; - app.cfg.lastfm.username = ""; - app.cfg.lastfm.key = ""; + app.cfg.lastfm.secrets.username = ""; + app.cfg.lastfm.secrets.key = ""; ipcRenderer.send('lastfm:disconnect'); }, - async lfmAuthorize(event) { + async lfmAuthorize() { window.open(await ipcRenderer.invoke('lastfm:url')); - event.target.innerText = app.getLz('term.connecting') + '...'; + app.notyf.success(app.getLz('settings.notyf.connectivity.lastfmScrobble.connecting')); /* Just a timeout for the button */ setTimeout(() => { - if (event.target.innerText === app.getLz('term.connecting') + '...') { - event.target.innerText = app.getLz('term.connect'); + if (document.getElementById('lfmConnect').innerText === app.getLz('term.connecting') + '...') { app.notyf.error(app.getLz('settings.notyf.connectivity.lastfmScrobble.connectError')); console.warn('[lastfm:authorize] Last.fm authorization timed out.'); } }, 20000); + ipcRenderer.once('lastfm:authenticated', (_e, session) => { + app.cfg.lastfm.secrets.username = session.username + app.cfg.lastfm.secrets.key = session.key + app.cfg.lastfm.enabled = true + app.notyf.success(app.getLz('settings.notyf.connectivity.lastfmScrobble.connectSuccess')); + }) + }, } }) From bbcae012b818b111acfa660007ee16e63a53c412 Mon Sep 17 00:00:00 2001 From: Core <64542347+coredev-uk@users.noreply.github.com> Date: Thu, 16 Jun 2022 14:01:04 +0100 Subject: [PATCH 12/34] Restructure --- src/main/base/utils.ts | 54 ++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/src/main/base/utils.ts b/src/main/base/utils.ts index 0c75015b..46b865be 100644 --- a/src/main/base/utils.ts +++ b/src/main/base/utils.ts @@ -2,18 +2,36 @@ import * as fs from "fs"; import * as path from "path"; import {Store} from "./store"; import {BrowserWindow as bw} from "./browserwindow"; -import {app, dialog, ipcMain, Notification, shell, BrowserWindow} from "electron"; +import {app, BrowserWindow, ipcMain} from "electron"; import fetch from "electron-fetch"; -import {AppImageUpdater, NsisUpdater} from "electron-updater"; -import * as log from "electron-log"; import ElectronStore from "electron-store"; export class utils { + /** + * Playback Functions + */ + static playback = { + pause: () => { + bw.win.webContents.executeJavaScript("MusicKitInterop.pause()") + }, + play: () => { + bw.win.webContents.executeJavaScript("MusicKitInterop.play()") + }, + playPause: () => { + bw.win.webContents.executeJavaScript("MusicKitInterop.playPause()") + }, + next: () => { + bw.win.webContents.executeJavaScript("MusicKitInterop.next()") + }, + previous: () => { + bw.win.webContents.executeJavaScript("MusicKitInterop.previous()") + } + } /** * Paths for the application to use */ - private static paths: any = { + static paths: any = { srcPath: path.join(__dirname, "../../src"), rendererPath: path.join(__dirname, "../../src/renderer"), mainPath: path.join(__dirname, "../../src/main"), @@ -71,7 +89,7 @@ export class utils { } else { i18n = Object.assign(i18n, JSON.parse(fs.readFileSync(path.join(this.paths.i18nPath, `en_US.json`), "utf8"))); } - }) + }) } if (key) { return i18n[key] @@ -97,7 +115,6 @@ export class utils { return Store.cfg.store } - /** * Get the store instance * @returns {Store} @@ -123,10 +140,6 @@ export class utils { return Store.pushToCloud } - - - - /** * Gets the browser window */ @@ -145,25 +158,4 @@ export class utils { static loadJSFrontend(path: string): void { bw.win.webContents.executeJavaScript(fs.readFileSync(path, "utf8")); } - - /** - * Playback Functions - */ - static playback = { - pause: () => { - bw.win.webContents.executeJavaScript("MusicKitInterop.pause()") - }, - play: () => { - bw.win.webContents.executeJavaScript("MusicKitInterop.play()") - }, - playPause: () => { - bw.win.webContents.executeJavaScript("MusicKitInterop.playPause()") - }, - next: () => { - bw.win.webContents.executeJavaScript("MusicKitInterop.next()") - }, - previous: () => { - bw.win.webContents.executeJavaScript("MusicKitInterop.previous()") - } - } } From 23ad2640dc146f6cfb9c72f316eedd6f032a5d4a Mon Sep 17 00:00:00 2001 From: Core <64542347+coredev-uk@users.noreply.github.com> Date: Thu, 16 Jun 2022 14:33:24 +0100 Subject: [PATCH 13/34] Private implemented --- src/main/index.ts | 57 +++++++++++++++++++------------------- src/main/plugins/lastfm.ts | 7 +---- 2 files changed, 30 insertions(+), 34 deletions(-) diff --git a/src/main/index.ts b/src/main/index.ts index ce2d043d..4a74f0e9 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -1,18 +1,19 @@ -require('v8-compile-cache'); - -const {app, components, ipcMain} = require('electron'); -import {join} from 'path'; +require("v8-compile-cache"); +import {join} from "path"; +import {app} from "electron" if (!app.isPackaged) { - app.setPath('userData', join(app.getPath('appData'), 'Cider')); + app.setPath("userData", join(app.getPath("appData"), "Cider")); } import {Store} from "./base/store"; import {AppEvents} from "./base/app"; import {Plugins} from "./base/plugins"; import {BrowserWindow} from "./base/browserwindow"; -import {init as Sentry} from '@sentry/electron'; +import {init as Sentry} from "@sentry/electron"; import {RewriteFrames} from "@sentry/integrations"; +import {components, ipcMain} from "electron" + // Analytics for debugging fun yeah. Sentry({ @@ -32,13 +33,13 @@ const CiderPlug = new Plugins(); * App Event Handlers * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ -app.on('ready', () => { +app.on("ready", () => { Cider.ready(CiderPlug); - console.log('[Cider] Application is Ready. Creating Window.') + console.log("[Cider] Application is Ready. Creating Window.") if (!app.isPackaged) { - console.info('[Cider] Running in development mode.') - require('vue-devtools').install() + console.info("[Cider] Running in development mode.") + require("vue-devtools").install() } components.whenReady().then(async () => { @@ -49,11 +50,11 @@ app.on('ready', () => { console.log(gpuInfo) }) - console.log('[Cider][Widevine] Status:', components.status()); + console.log("[Cider][Widevine] Status:", components.status()); Cider.bwCreated(); win.on("ready-to-show", () => { - console.debug('[Cider] Window is Ready.') - CiderPlug.callPlugins('onReady', win); + console.debug("[Cider] Window is Ready.") + CiderPlug.callPlugins("onReady", win); win.show(); }); }); @@ -68,20 +69,20 @@ ipcMain.handle("renderer-ready", (event) => { CiderPlug.callPlugins("onRendererReady", event); }) -ipcMain.on('playbackStateDidChange', (_event, attributes) => { - CiderPlug.callPlugins('onPlaybackStateDidChange', attributes); +ipcMain.on("playbackStateDidChange", (_event, attributes) => { + CiderPlug.callPlugins("onPlaybackStateDidChange", attributes); }); -ipcMain.on('nowPlayingItemDidChange', (_event, attributes) => { - CiderPlug.callPlugins('onNowPlayingItemDidChange', attributes); +ipcMain.on("nowPlayingItemDidChange", (_event, attributes) => { + CiderPlug.callPlugins("onNowPlayingItemDidChange", attributes); }); -ipcMain.on('nowPlayingItemDidChangeLastFM', (_event, attributes) => { - CiderPlug.callPlugin('lastfm.js', 'nowPlayingItemDidChangeLastFM', attributes); +ipcMain.on("nowPlayingItemDidChangeLastFM", (_event, attributes) => { + CiderPlug.callPlugin("lastfm.js", "nowPlayingItemDidChangeLastFM", attributes); }) -app.on('before-quit', () => { - CiderPlug.callPlugins('onBeforeQuit'); +app.on("before-quit", () => { + CiderPlug.callPlugins("onBeforeQuit"); console.warn(`${app.getName()} exited.`); }); @@ -90,21 +91,21 @@ app.on('before-quit', () => { * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ // @ts-ignore -app.on('widevine-ready', (version, lastVersion) => { +app.on("widevine-ready", (version, lastVersion) => { if (null !== lastVersion) { - console.log('[Cider][Widevine] Widevine ' + version + ', upgraded from ' + lastVersion + ', is ready to be used!') + console.log("[Cider][Widevine] Widevine " + version + ", upgraded from " + lastVersion + ", is ready to be used!") } else { - console.log('[Cider][Widevine] Widevine ' + version + ' is ready to be used!') + console.log("[Cider][Widevine] Widevine " + version + " is ready to be used!") } }) // @ts-ignore -app.on('widevine-update-pending', (currentVersion, pendingVersion) => { - console.log('[Cider][Widevine] Widevine ' + currentVersion + ' is ready to be upgraded to ' + pendingVersion + '!') +app.on("widevine-update-pending", (currentVersion, pendingVersion) => { + console.log("[Cider][Widevine] Widevine " + currentVersion + " is ready to be upgraded to " + pendingVersion + "!") }) // @ts-ignore -app.on('widevine-error', (error) => { - console.log('[Cider][Widevine] Widevine installation encountered an error: ' + error) +app.on("widevine-error", (error) => { + console.log("[Cider][Widevine] Widevine installation encountered an error: " + error) app.exit() }) diff --git a/src/main/plugins/lastfm.ts b/src/main/plugins/lastfm.ts index db808902..b85383f6 100644 --- a/src/main/plugins/lastfm.ts +++ b/src/main/plugins/lastfm.ts @@ -1,9 +1,3 @@ -// https://github.com/maxkueng/node-lastfmapi -// https://github.com/maxkueng/lastfm-autocorrect -// @todo: add autocorrect -// @todo: add scrobble and filter to prevent no-title-found being scrobbled -// @todo: handle session keys through config to stop aids session.json - export default class lastfm { /** @@ -74,6 +68,7 @@ export default class lastfm { * @param attributes Music Attributes */ onNowPlayingItemDidChange(attributes: any): void { + if (this._utils.getStoreValue("general.privateEnabled")) return; this._attributes = attributes if (!attributes?.lfmTrack || !attributes?.lfmAlbum) { this.verifyTrack(attributes) From 7850493c9e5eb101340203a369e639baa50acb31 Mon Sep 17 00:00:00 2001 From: Core <64542347+coredev-uk@users.noreply.github.com> Date: Thu, 16 Jun 2022 14:47:52 +0100 Subject: [PATCH 14/34] Filter loop added --- src/main/base/store.ts | 1 + src/main/plugins/lastfm.ts | 4 ++-- src/renderer/views/pages/settings.ejs | 10 ++++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main/base/store.ts b/src/main/base/store.ts index fd706f8e..9bfb548f 100644 --- a/src/main/base/store.ts +++ b/src/main/base/store.ts @@ -222,6 +222,7 @@ export class Store { "lastfm": { "enabled": false, "scrobble_after": 50, + "filter_loop": false, "secrets": { "username": "", "key": "" diff --git a/src/main/plugins/lastfm.ts b/src/main/plugins/lastfm.ts index b85383f6..af63f4a1 100644 --- a/src/main/plugins/lastfm.ts +++ b/src/main/plugins/lastfm.ts @@ -162,7 +162,7 @@ export default class lastfm { * @private */ private scrobbleTrack(attributes: any): void { - if (!this._authenticated || !attributes || (this._scrobbleCache.track === attributes.lfmTrack.name)) return; + if (!this._authenticated || !attributes || (this._utils.getStoreValue("lastfm.filter_loop") && this._scrobbleCache.track === attributes.lfmTrack.name)) return; if (this._scrobbleDelay) { clearTimeout(this._scrobbleDelay); @@ -200,7 +200,7 @@ export default class lastfm { } private updateNowPlayingTrack(attributes: any): void { - if (!this._authenticated || !attributes || (this._nowPlayingCache.track === attributes.lfmTrack.name)) return; + if (!this._authenticated || !attributes || (this._utils.getStoreValue("lastfm.filter_loop") && this._nowPlayingCache.track === attributes.lfmTrack.name)) return; const nowPlaying = { 'artist': attributes.lfmTrack.artist.name, diff --git a/src/renderer/views/pages/settings.ejs b/src/renderer/views/pages/settings.ejs index ff1bdbc9..c64432f1 100644 --- a/src/renderer/views/pages/settings.ejs +++ b/src/renderer/views/pages/settings.ejs @@ -1079,6 +1079,16 @@ +
+
+ {{$root.getLz('settings.option.connectivity.filterLoop')}} +
+
+ +
+
From 742e606c09a876b0b3eeddc53be2447b5d2a09ff Mon Sep 17 00:00:00 2001 From: Core <64542347+coredev-uk@users.noreply.github.com> Date: Thu, 16 Jun 2022 16:14:53 +0100 Subject: [PATCH 15/34] filter loop fixes --- src/main/plugins/lastfm.ts | 14 +++++++++++--- src/preload/cider-preload.js | 2 ++ src/renderer/views/pages/settings.ejs | 2 +- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/main/plugins/lastfm.ts b/src/main/plugins/lastfm.ts index af63f4a1..bf0b88e5 100644 --- a/src/main/plugins/lastfm.ts +++ b/src/main/plugins/lastfm.ts @@ -52,6 +52,11 @@ export default class lastfm { this._authenticated = false; console.debug('[lastfm] [disconnect] Disconnected') }) + + this._utils.getIPCMain().on('lastfm:nowPlayingChange', (event: any, attributes: any) => { + if (this._utils.getStoreValue("lastfm.filter_loop")) return; + this.onNowPlayingItemDidChange(attributes) + }) } /** @@ -123,15 +128,18 @@ export default class lastfm { * @private */ private verifyTrack(attributes: any): object { - if (!attributes) return {}; + if (!attributes) return attributes; if (!attributes.lfmAlbum) { + console.log(attributes.artistName) + console.log(attributes.albumName) return this._lfm.album.getInfo({ "artist": attributes.artistName, "album": attributes.albumName }, (err: any, data: any) => { if (err) { - console.error(`[${lastfm.name}] [album.getInfo] Error: ${err}`) + console.error(`[${lastfm.name}] [album.getInfo] Error: ${typeof err === "string" ? err : err.message}`) + console.error(err) return {}; } if (data) { @@ -142,7 +150,7 @@ export default class lastfm { } else { return this._lfm.track.getCorrection(attributes.artistName, attributes.name, (err: any, data: any) => { if (err) { - console.error(`[${lastfm.name}] [track.getCorrection] Error: ${err}`) + console.error(`[${lastfm.name}] [track.getCorrection] Error: ${typeof err === "string" ? err : err.message}`) console.error(err) return {}; } diff --git a/src/preload/cider-preload.js b/src/preload/cider-preload.js index 3923fbd3..57ae5df3 100644 --- a/src/preload/cider-preload.js +++ b/src/preload/cider-preload.js @@ -29,6 +29,8 @@ const MusicKitInterop = { global.ipcRenderer.send('nowPlayingItemDidChange', attributes); } + global.ipcRenderer.send('lastfm:nowPlayingChange', attributes); + if (MusicKit.getInstance().nowPlayingItem) { await this.sleep(750); MusicKit.getInstance().playbackRate = app.cfg.audio.playbackRate; diff --git a/src/renderer/views/pages/settings.ejs b/src/renderer/views/pages/settings.ejs index c64432f1..170dcfd8 100644 --- a/src/renderer/views/pages/settings.ejs +++ b/src/renderer/views/pages/settings.ejs @@ -1081,7 +1081,7 @@
- {{$root.getLz('settings.option.connectivity.filterLoop')}} + {{$root.getLz('settings.option.connectivity.lastfmScrobble.filterLoop')}}