From 44b840eb0368c2e5b0754631c5b0b479e02c5a9f Mon Sep 17 00:00:00 2001 From: vapormusic Date: Wed, 19 Jan 2022 14:30:58 +0700 Subject: [PATCH] lastfm module (not working for now) --- src/main/index.ts | 4 +- src/main/plugins/lastfm.ts | 207 +++++++++++++++++++++++++++++++++++++ 2 files changed, 208 insertions(+), 3 deletions(-) create mode 100644 src/main/plugins/lastfm.ts diff --git a/src/main/index.ts b/src/main/index.ts index 30ed265b..fcd03e28 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -31,9 +31,7 @@ electron.app.on('ready', () => { electron.components.whenReady().then(async () => { await Cider.createWindow() - plug.callPlugins('onReady', Cider); - - + plug.callPlugins('onReady', Cider); }) diff --git a/src/main/plugins/lastfm.ts b/src/main/plugins/lastfm.ts new file mode 100644 index 00000000..6469b4b9 --- /dev/null +++ b/src/main/plugins/lastfm.ts @@ -0,0 +1,207 @@ + +import * as electron from 'electron'; +import * as fs from 'fs'; +import {resolve} from 'path'; +const sessionPath = resolve(electron.app.getPath('userData'), 'session.json'), + apiCredentials = require('../../resources/lfmApiCredentials.json'), + LastfmAPI = require('lastfmapi'); + +export default class LastFMPlugin { + /** + * Private variables for interaction in plugins + */ + private _win: any; + private _app: any; + private _lastfm: any; + private authenticateFromFile() { + let sessionData = require(sessionPath) + console.log("[LastFM][authenticateFromFile] Logging in with Session Info.") + this._lastfm.setSessionCredentials(sessionData.name, sessionData.key) + console.log("[LastFM][authenticateFromFile] Logged in.") + } + + private authenticate() { + if (this._win.store.store.lastfm.auth_token) { + this._win.store.store.lastfm.enabled = true; + } + + if (!this._win.store.store.lastfm.enabled || !this._win.store.store.lastfm.auth_token) { + this._win.store.store.lastfm.enabled = false; + return + } + + const lfmAPI = new LastfmAPI({ + 'api_key': apiCredentials.key, + 'secret': apiCredentials.secret + }); + + this._lastfm = Object.assign(lfmAPI, {cachedAttributes: false, cachedNowPlayingAttributes: false}); + + fs.stat(sessionPath, (err : any) => { + if (err) { + console.error("[LastFM][Session] Session file couldn't be opened or doesn't exist,", err) + console.log("[LastFM][Auth] Beginning authentication from configuration") + this._lastfm.authenticate(this._win.store.store.lastfm.auth_token, (err: any, session: any) => { + if (err) { + throw err; + } + console.log("[LastFM] Successfully obtained LastFM session info,", session); // {"name": "LASTFM_USERNAME", "key": "THE_USER_SESSION_KEY"} + console.log("[LastFM] Saving session info to disk.") + let tempData = JSON.stringify(session) + fs.writeFile(sessionPath, tempData, (err: any) => { + if (err) + console.log("[LastFM][fs]", err) + else { + console.log("[LastFM][fs] File was written successfully.") + this.authenticateFromFile() + new electron.Notification({ + title: electron.app.getName(), + body: "Successfully logged into LastFM using Authentication Key." + }).show() + } + }) + }); + } else { + this.authenticateFromFile() + } + }) + } + + private async scrobbleSong(attributes : any) { + await new Promise(resolve => setTimeout(resolve, Math.round(attributes.durationInMillis * (this._win.store.store.lastfm.scrobble_after / 100)))); + const currentAttributes = attributes; + + if (!this._lastfm || this._lastfm.cachedAttributes === attributes ) { + return + } + + if (this._lastfm.cachedAttributes) { + if (this._lastfm.cachedAttributes.playParams.id === attributes.playParams.id) return; + } + + if (currentAttributes.status && currentAttributes === attributes) { + if (fs.existsSync(sessionPath)) { + // Scrobble playing song. + if (attributes.status === true) { + this._lastfm.track.scrobble({ + 'artist': this.filterArtistName(attributes.artistName), + 'track': attributes.name, + 'album': attributes.albumName, + 'albumArtist': this.filterArtistName(attributes.artistName), + 'timestamp': new Date().getTime() / 1000 + }, function (err: any, scrobbled: any) { + if (err) { + return console.error('[LastFM] An error occurred while scrobbling', err); + } + + console.log('[LastFM] Successfully scrobbled: ', scrobbled); + }); + this._lastfm.cachedAttributes = attributes + } + } else { + this.authenticate(); + } + } else { + return console.log('[LastFM] Did not add ', attributes.name , '—' , this.filterArtistName(attributes.artistName), 'because now playing a other song.'); + } + } + + private filterArtistName(artist :any) { + if (!this._win.store.store.lastfm.enabledRemoveFeaturingArtists) return artist; + + artist = artist.split(' '); + if (artist.includes('&')) { + artist.length = artist.indexOf('&'); + } + if (artist.includes('and')) { + artist.length = artist.indexOf('and'); + } + artist = artist.join(' '); + if (artist.includes(',')) { + artist = artist.split(',') + artist = artist[0] + } + return artist.charAt(0).toUpperCase() + artist.slice(1); + } + + private updateNowPlayingSong(attributes : any) { + if (!this._lastfm ||this._lastfm.cachedNowPlayingAttributes === attributes || !this._win.store.store.lastfm.NowPlaying) { + return + } + + if (this._lastfm.cachedNowPlayingAttributes) { + if (this._lastfm.cachedNowPlayingAttributes.playParams.id === attributes.playParams.id) return; + } + + if (fs.existsSync(sessionPath)) { + // update Now Playing + if (attributes.status === true) { + this._lastfm.track.updateNowPlaying({ + 'artist': this.filterArtistName(attributes.artistName), + 'track': attributes.name, + 'album': attributes.albumName, + 'albumArtist': this.filterArtistName(attributes.artistName) + }, function (err : any, nowPlaying :any) { + if (err) { + return console.error('[LastFM] An error occurred while updating nowPlayingSong', err); + } + + console.log('[LastFM] Successfully updated nowPlayingSong', nowPlaying); + }); + this._lastfm.cachedNowPlayingAttributes = attributes + } + + } else { + this.authenticate() + } + } + + /** + * Base Plugin Details (Eventually implemented into a GUI in settings) + */ + public name: string = 'LastFMPlugin'; + public description: string = 'LastFM 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.authenticate() + } + + /** + * 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.scrobbleSong(attributes) + this.updateNowPlayingSong(attributes) + } + + /** + * Runs on song change + * @param attributes Music Attributes + */ + onNowPlayingItemDidChange(attributes: object): void { + this.scrobbleSong(attributes) + this.updateNowPlayingSong(attributes) + } + +}