get real. (#1321)
* test * fix multiroom * attempt for fix rare cast bug * changes for local files: read below * added pouchdb-node * moved all logic for local files to src/main/providers/local * added new local library section on sidebar * removed dupe * added caching headers * fix * add path menu to settings-window * fix mxm for local * some test * some fix * clear this * clear log * add playlist folder class * sometest * fix * Auto focus search bar * use object instead of array for albums (#1219) * feat: 🌐 Update French language (#1218) * add pagination for library songs * Add 'go to' page * Make playlist search icon use hero color * Merge pull request #1 from vapormusic/patch-1 dont populate out-of-display doms * both infinite and paging * Add color to search button background * Add shadow to follow button * im dumb sorry * Add brightness effect of search button * add some delay to scroll v-observe-visibility * some multiroom fixes * somefixes * [Audio] Fix VBass & Added COCS * [Audio] COCS revision * some fix * fix m1 mac * fix m1 build * some fix regarding audiocontext * [Audio] Fix #1207 (discussions) Eliminates audio stuttering even when AudioContext is enabled. Make lyrics account for the extra latency introduced by Audio Lab. * idk what I did * apparently this no worki * should default to 0 * expose bitrate of localfiles * [Audio] Added CAP & Normalization behavior for local files * smh musickit * Expose more local files metadata + fix norm error * pokemon gotta catch them all * maikiwi is a clown confirmed * pokemon gotta catch them all v2 * pokemon gotta catch them all v5 * Update zh_TW.json (#1229) Fix errors, update zh-TW translation. * Change No Lyrics Message in Full Screen Player (#1210) * Modify term.noLyrics text in 5 files * Minor change in 3 files * Colorize sponsor buttons in about page Co-authored-by: ctaetcsh <48845980+ctaetcsh@users.noreply.github.com> * max size of more info panel dynamic * Add twitter social button for some developers in about page (#1232) * Big Chungus Window settings (#1230) * Initial Changes * I suposse this is the last * cryptofyre * Documentation * Revert "Big Chungus Window settings (#1230)" (#1233) This reverts commite133b2c38b
. * test * Just changed it and gonna leave for debugging * reimpe133b2c
, adjustments for macOS * resolve #1 * copied files * readded strings to en_US * adjustments to settings sidebar collapse * add multiplex * Update version.sh * Update style.css * dont break pls thx * swag * I forgot that (#1239) * Update zh_TW.json (#1236) Update TW language. * Update zh_CN.json (#1240) * because I can * Fix cider team buttons in about page * Update style.less * Float right looks better * support custom port via optional CIDER_PORT var * Scan Local Files now 46 times faster * Update .gitignore * cleanups * remove console time (1s/1600 tracks) * fix m1 * sometest * Update build-macos.yml * Fix absolutely unacceptable punctuation error (#1249) * ok * pray * revert mxm back to local * Update zh_CN.json (#1242) * Update de_DE.json (#1246) * Musixmatch fix (thx plank ily) * whoops * yes * whoops v2 * bump to e18.3.5 * don't give the lyric api id if local files * Update afterPack.js * ukie * Update afterPack.js * Update afterPack.js * how the fuck did this not throw an error * fix stupid svg smh * new mediaitem scaling method * added Maximum Element Scale * mediaitem square artwork res now adapts to window size * will not affect high dpi * fix now playing artwork * fix album genre names before: gets genre from 1st track now: gets genre from album data * clamped element scale to 1.5x * added caching for auth * adjustment to artist page * changed to v-show for list item vis * Bring back mxm lyrics (Fully tested) * fix mmx translation * fix settings view * remove useless args & nonexistent funcs * fix div hell * fixed missing end tag for local playlist * fix divs * Fix cider list * the amount of brain cells that I have lost because of mxm trans * WIP language filter * it was fun while it lasted, goodbye MXM languages * MXM changes * 4am code moments * move logic * fix lyrics translation & allow other lang * default store.ts mxm trans to be disabled * this is why you dont code at 4am * and this is why you should test your code before pushing * added Romanized langs to mxm trans * love how previous MXM changes are in vain till now * stop. uploading. this. * NEVER. CODE. AT. FOUR. AYE. EM. AGAIN. * test * Revert "test" This reverts commit256d06bbcc
. * did a funny * did another funny * yes * add prime symbol to apostrophe * Don't do anything if res != 200 * Recursive Folder Search in Cider Utils * 4am code moment * fix function (force recompile utils) * did a funny there * I need sleep * Update zh_CN.json (#1265) This is a big work * Update zh_TW.json (#1260) Update TW language. * performant logging is enabled by default * test getting rid of lyriccurrenttime * set timeout can go away now * boops forgot this * mxm moms * mxm moms * Revert "mxm moms" This reverts commit51fc09280e
. * README download link fix * Update vueapp.js * Fix settings menu (#1271) * remove unused pages * profile page (for search for now) * lol * updated recordLabel with i18n and root usage * Local Lossless Icon and more - add Cider-profile boilerplate - add local lossless icon -add hover for PPE and lossless Co-authored-by: Core <coredev-uk@users.noreply.github.com> * no coding at 4am * fix units for local lossless badge * fix units for local lossless badge * remove CAP icon for local files, cuz unsupported * mpris overhaul * Fix seeking in mpris * changed am section on sidebar to v-show allowing css manipulation * added class for css * new effect when entering fullscreen lyrics * fixes text wrapping on tab text * added is-album * linux is cooollll * Lyrics API migration * Update musickit to use api mirror by default * add div for app-playback-buttons * Add spatialization icon (#1276) * Add spatialization icon * that never happened * add checkmode func to webremote * whoops sorry * Updated config.yml * mogus * fix string matching * may Maikiwi bless your CI * MKV3 red * Go touch grass; * this was so unreadable lmao * add logic for showing spatialization icon * add space in lossless icon * Remove dead fallback token, add error log if capi call fails (#1289) I tested and the fallback key you are using is dead. 401s. Unusable. * Fix #1282 * Fix #1237 * fix default CAP * someone played with translation code * lmao yaz why * stop polluting my logs you lil POST * I18n (#1293) * Update es_ES * I18N * idk this only breaking now * added framework for c2 parity * fixes * Fix volume bar on miniplayer (#1297) * Update stale-issues.yml * removed loading bar, testing without hlscider * overwrite restriction * allow listennow "more like" nav to work * garbage gone * fix for primary-content linking * Update README.md Add QQ group info * Revert back to music metadata * gimp v2 * remove local files as experiment * just to be safe * world is now a better place * meltdown avoided * meltdown avoided * Revert "meltdown avoided" This reverts commit38e6f1b7fa
. * Revert "meltdown avoided" This reverts commit54cc6656d6
. * Revert "world is now a better place" This reverts commitc019bf9c63
. * remove quasar * add some shiz (#1313) * Update ru_RU.json keeping russian lang actual * ok * Add gradient to lyric-footer * *Commit en español Ñ (#1304) * i hate my life (#1307) * world is now a better place * meltdown avoided * meltdown avoided * stylize new listen now childs * full scale artwork, finally * dynamic width for search categories * hd all album work * Update afterPack.js * force hq quality * oops * attempt to fix * misc cleanup * why what * what was i thinking * fix duplicated text in listen now childs * Paginate/infinite scroll for albums, playlists (#1234) * Infinite scroll, pagination to album, playlists * move pagination below tracks * Make page size configurable * remove renderer * Mitigate songs / album slow app issue. * add ratings, library change to web remote (#1285) * Add compact artist header option (#1308) * Support compact artist header (optional) * Add required term Co-authored-by: h0ckerman <35598335+h0ckerman@users.noreply.github.com> Co-authored-by: vapormusic <vietanhfat@gmail.com> Co-authored-by: Monochromish <chillygamer7@gmail.com> Co-authored-by: Gabriel Davila <56521591+mefsaal@users.noreply.github.com> Co-authored-by: Core <64542347+coredev-uk@users.noreply.github.com> Co-authored-by: Maikiwi <stella@mai.kiwi> Co-authored-by: yazninja <yazlesean@gmail.com> Co-authored-by: booploops <49113086+booploops@users.noreply.github.com> Co-authored-by: Kendall Garner <17521368+kgarner7@users.noreply.github.com> Co-authored-by: Pedro Galhardo <pgalhardo@icloud.com> * obama (#1314) * Update ru_RU.json keeping russian lang actual * ok * Add gradient to lyric-footer * *Commit en español Ñ (#1304) * i hate my life (#1307) * world is now a better place * meltdown avoided * meltdown avoided * stylize new listen now childs * full scale artwork, finally * dynamic width for search categories * hd all album work * Update afterPack.js * force hq quality * oops * attempt to fix * misc cleanup * why what * what was i thinking * fix duplicated text in listen now childs * Paginate/infinite scroll for albums, playlists (#1234) * Infinite scroll, pagination to album, playlists * move pagination below tracks * Make page size configurable * remove renderer * Mitigate songs / album slow app issue. * add ratings, library change to web remote (#1285) * Add compact artist header option (#1308) * Support compact artist header (optional) * Add required term * improve pagination styling Co-authored-by: h0ckerman <35598335+h0ckerman@users.noreply.github.com> Co-authored-by: vapormusic <vietanhfat@gmail.com> Co-authored-by: Monochromish <chillygamer7@gmail.com> Co-authored-by: Gabriel Davila <56521591+mefsaal@users.noreply.github.com> Co-authored-by: Core <64542347+coredev-uk@users.noreply.github.com> Co-authored-by: Maikiwi <stella@mai.kiwi> Co-authored-by: yazninja <yazlesean@gmail.com> Co-authored-by: booploops <49113086+booploops@users.noreply.github.com> Co-authored-by: Kendall Garner <17521368+kgarner7@users.noreply.github.com> Co-authored-by: Pedro Galhardo <pgalhardo@icloud.com> Co-authored-by: yazninja <71800112+yazninja@users.noreply.github.com> * obama episode 2. (#1317) * Update ru_RU.json keeping russian lang actual * ok * Add gradient to lyric-footer * *Commit en español Ñ (#1304) * i hate my life (#1307) * world is now a better place * meltdown avoided * meltdown avoided * stylize new listen now childs * full scale artwork, finally * dynamic width for search categories * hd all album work * Update afterPack.js * force hq quality * oops * attempt to fix * misc cleanup * why what * what was i thinking * fix duplicated text in listen now childs * Paginate/infinite scroll for albums, playlists (#1234) * Infinite scroll, pagination to album, playlists * move pagination below tracks * Make page size configurable * remove renderer * Mitigate songs / album slow app issue. * add ratings, library change to web remote (#1285) * Add compact artist header option (#1308) * Support compact artist header (optional) * Add required term * improve pagination styling * Disable Fullscreen view when artist/album name is clicked. (#1315) * Disable Fullscreen view when artist/album name is clicked. idk why this change didn't exist * Seperate dash from album name * Replace `$root.showSearch()` with `app.appRoute('search')` `$root.showSearch()` prevents going back to previous page from sidebar. * Fix Anim (#1316) Co-authored-by: h0ckerman <35598335+h0ckerman@users.noreply.github.com> Co-authored-by: vapormusic <vietanhfat@gmail.com> Co-authored-by: Monochromish <chillygamer7@gmail.com> Co-authored-by: Gabriel Davila <56521591+mefsaal@users.noreply.github.com> Co-authored-by: Core <64542347+coredev-uk@users.noreply.github.com> Co-authored-by: Maikiwi <stella@mai.kiwi> Co-authored-by: yazninja <yazlesean@gmail.com> Co-authored-by: booploops <49113086+booploops@users.noreply.github.com> Co-authored-by: Kendall Garner <17521368+kgarner7@users.noreply.github.com> Co-authored-by: Pedro Galhardo <pgalhardo@icloud.com> Co-authored-by: Monochromish <79590499+Monochromish@users.noreply.github.com> * re add that i guess. github is fucked. * aa (#1320) * Update ru_RU.json keeping russian lang actual * ok * Add gradient to lyric-footer * *Commit en español Ñ (#1304) * i hate my life (#1307) * world is now a better place * meltdown avoided * meltdown avoided * stylize new listen now childs * full scale artwork, finally * dynamic width for search categories * hd all album work * Update afterPack.js * force hq quality * oops * attempt to fix * misc cleanup * why what * what was i thinking * fix duplicated text in listen now childs * Paginate/infinite scroll for albums, playlists (#1234) * Infinite scroll, pagination to album, playlists * move pagination below tracks * Make page size configurable * remove renderer * Mitigate songs / album slow app issue. * add ratings, library change to web remote (#1285) * Add compact artist header option (#1308) * Support compact artist header (optional) * Add required term * improve pagination styling * Disable Fullscreen view when artist/album name is clicked. (#1315) * Disable Fullscreen view when artist/album name is clicked. idk why this change didn't exist * Seperate dash from album name * Replace `$root.showSearch()` with `app.appRoute('search')` `$root.showSearch()` prevents going back to previous page from sidebar. * Fix Anim (#1316) * make tracks tab active (#1318) * welp that wasn't it. * Thnks (#1319) * Thnks * i need sleep Co-authored-by: h0ckerman <35598335+h0ckerman@users.noreply.github.com> Co-authored-by: vapormusic <vietanhfat@gmail.com> Co-authored-by: Monochromish <chillygamer7@gmail.com> Co-authored-by: Gabriel Davila <56521591+mefsaal@users.noreply.github.com> Co-authored-by: Core <64542347+coredev-uk@users.noreply.github.com> Co-authored-by: Maikiwi <stella@mai.kiwi> Co-authored-by: yazninja <yazlesean@gmail.com> Co-authored-by: booploops <49113086+booploops@users.noreply.github.com> Co-authored-by: Kendall Garner <17521368+kgarner7@users.noreply.github.com> Co-authored-by: Pedro Galhardo <pgalhardo@icloud.com> Co-authored-by: Monochromish <79590499+Monochromish@users.noreply.github.com> Co-authored-by: vapormusic <vietanhfat@gmail.com> Co-authored-by: booploops <49113086+booploops@users.noreply.github.com> Co-authored-by: yazninja <yazlesean@gmail.com> Co-authored-by: Pedro Galhardo <pedromgalhardo@tecnico.ulisboa.pt> Co-authored-by: Kendall Garner <17521368+kgarner7@users.noreply.github.com> Co-authored-by: Erwan <24718500+ErwanGit@users.noreply.github.com> Co-authored-by: Monochromish <chillygamer7@gmail.com> Co-authored-by: maikirakiwi <stella@mai.kiwi> Co-authored-by: yazninja <71800112+yazninja@users.noreply.github.com> Co-authored-by: 宥叡 <46503943+jay900604@users.noreply.github.com> Co-authored-by: Nathan Ritchie <48845980+ctaetcsh@users.noreply.github.com> Co-authored-by: Monochromish <79590499+Monochromish@users.noreply.github.com> Co-authored-by: Gabriel Davila <56521591+mefsaal@users.noreply.github.com> Co-authored-by: Core <64542347+coredev-uk@users.noreply.github.com> Co-authored-by: 椎名アヤネ <53814845+sakura0224@users.noreply.github.com> Co-authored-by: Jonathan Fenske <929220+jfenske89@users.noreply.github.com> Co-authored-by: UnbreakCode <unbreakcode@gmail.com> Co-authored-by: SoNothing <git@sonothing.com> Co-authored-by: Core <coredev-uk@users.noreply.github.com> Co-authored-by: Amaru8 <52407090+Amaru8@users.noreply.github.com> Co-authored-by: rlaphoenix <pragma.exe@gmail.com> Co-authored-by: h0ckerman <35598335+h0ckerman@users.noreply.github.com> Co-authored-by: Pedro Galhardo <pgalhardo@icloud.com>
This commit is contained in:
parent
57b2a86913
commit
c03f408ba5
157 changed files with 33489 additions and 10407 deletions
|
@ -1,278 +1,236 @@
|
|||
import * as electron from 'electron';
|
||||
import * as fs from 'fs';
|
||||
import {resolve} from 'path';
|
||||
export default class lastfm {
|
||||
|
||||
export default class LastFMPlugin {
|
||||
private sessionPath = resolve(electron.app.getPath('userData'), 'session.json');
|
||||
private apiCredentials = {
|
||||
/**
|
||||
* Base Plugin Information
|
||||
*/
|
||||
public name: string = 'LastFM Plugin';
|
||||
public version: string = '2.0.0';
|
||||
public author: string = 'Core (Cider Collective)';
|
||||
|
||||
|
||||
private _apiCredentials = {
|
||||
key: "f9986d12aab5a0fe66193c559435ede3",
|
||||
secret: "acba3c29bd5973efa38cc2f0b63cc625"
|
||||
}
|
||||
/**
|
||||
* Private variables for interaction in plugins
|
||||
* Plugin Initialization
|
||||
*/
|
||||
private _win: any;
|
||||
private _app: any;
|
||||
private _lastfm: any;
|
||||
private _store: any;
|
||||
private _timer: any;
|
||||
|
||||
private authenticateFromFile() {
|
||||
let sessionData = require(this.sessionPath)
|
||||
console.log("[LastFM][authenticateFromFile] Logging in with Session Info.")
|
||||
this._lastfm.setSessionCredentials(sessionData.username, sessionData.key)
|
||||
console.log("[LastFM][authenticateFromFile] Logged in.", sessionData.username, sessionData.key)
|
||||
}
|
||||
|
||||
|
||||
authenticate() {
|
||||
try {
|
||||
if (this._store.lastfm.auth_token) {
|
||||
this._store.lastfm.enabled = true;
|
||||
}
|
||||
|
||||
if (!this._store.lastfm.enabled || !this._store.lastfm.auth_token) {
|
||||
this._store.lastfm.enabled = false;
|
||||
return
|
||||
}
|
||||
/// dont move this require to top , app wont load
|
||||
const LastfmAPI = require('lastfmapi');
|
||||
const lfmAPI = new LastfmAPI({
|
||||
'api_key': this.apiCredentials.key,
|
||||
'secret': this.apiCredentials.secret
|
||||
});
|
||||
|
||||
this._lastfm = Object.assign(lfmAPI, {cachedAttributes: false, cachedNowPlayingAttributes: false});
|
||||
|
||||
fs.stat(this.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")
|
||||
console.log("[LastFM][tk]", this._store.lastfm.auth_token)
|
||||
this._lastfm.authenticate(this._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(this.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()
|
||||
}
|
||||
})
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
|
||||
private scrobbleSong(attributes: any) {
|
||||
if (this._timer) clearTimeout(this._timer);
|
||||
var self = this;
|
||||
this._timer = setTimeout(async () => {
|
||||
const currentAttributes = attributes;
|
||||
|
||||
if (!self._lastfm || self._lastfm.cachedAttributes === attributes) {
|
||||
return
|
||||
}
|
||||
|
||||
if (self._lastfm.cachedAttributes) {
|
||||
if (self._lastfm.cachedAttributes.playParams.id === attributes.playParams.id) return;
|
||||
}
|
||||
|
||||
const artist = await this.getPrimaryArtist(attributes)
|
||||
const album = this.getAlbumName(attributes)
|
||||
|
||||
if (currentAttributes.status && currentAttributes === attributes) {
|
||||
if (fs.existsSync(this.sessionPath)) {
|
||||
// Scrobble playing song.
|
||||
if (attributes.status === true) {
|
||||
self._lastfm.track.scrobble({
|
||||
'artist': artist,
|
||||
'track': attributes.name,
|
||||
'album': album,
|
||||
'albumArtist': artist,
|
||||
'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);
|
||||
});
|
||||
self._lastfm.cachedAttributes = attributes
|
||||
}
|
||||
} else {
|
||||
self.authenticate();
|
||||
}
|
||||
} else {
|
||||
return console.log('[LastFM] Did not add ', attributes.name, '—', artist, 'because now playing a other song.');
|
||||
}
|
||||
}, Math.round(attributes.durationInMillis * Math.min((self._store.lastfm.scrobble_after / 100), 0.8)));
|
||||
}
|
||||
|
||||
private async updateNowPlayingSong(attributes: any) {
|
||||
if (!this._lastfm || this._lastfm.cachedNowPlayingAttributes === attributes || !this._store.lastfm.NowPlaying) {
|
||||
return
|
||||
}
|
||||
|
||||
if (this._lastfm.cachedNowPlayingAttributes) {
|
||||
if (this._lastfm.cachedNowPlayingAttributes.playParams.id === attributes.playParams.id) return;
|
||||
}
|
||||
|
||||
if (fs.existsSync(this.sessionPath)) {
|
||||
const artist = await this.getPrimaryArtist(attributes)
|
||||
const album = this.getAlbumName(attributes)
|
||||
|
||||
// update Now Playing
|
||||
if (attributes.status === true) {
|
||||
this._lastfm.track.updateNowPlaying({
|
||||
'artist': artist,
|
||||
'track': attributes.name,
|
||||
'album': album,
|
||||
'albumArtist': artist
|
||||
}, 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()
|
||||
}
|
||||
}
|
||||
|
||||
private getAlbumName(attributes: any): string {
|
||||
return attributes.albumName.replace(/ - Single| - EP/g, '');
|
||||
}
|
||||
|
||||
private async getPrimaryArtist(attributes: any) {
|
||||
const songId = attributes.playParams.catalogId || attributes.playParams.id
|
||||
|
||||
if (!this._store.lastfm.enabledRemoveFeaturingArtists || !songId) return attributes.artistName;
|
||||
|
||||
const res = await this._win.webContents.executeJavaScript(`
|
||||
(async () => {
|
||||
const subMk = await MusicKit.getInstance().api.v3.music("/v1/catalog/" + MusicKit.getInstance().storefrontId + "/songs/${songId}", {
|
||||
include: {
|
||||
songs: ["artists"]
|
||||
}
|
||||
})
|
||||
if (!subMk) console.error('[LastFM] Request failed: /v1/catalog/us/songs/${songId}')
|
||||
return subMk.data
|
||||
})()
|
||||
`).catch(console.error)
|
||||
if (!res) return attributes.artistName
|
||||
|
||||
const data = res.data
|
||||
if (!data.length) {
|
||||
console.error(`[LastFM] Unable to locate song with id of ${songId}`)
|
||||
return attributes.artistName;
|
||||
}
|
||||
|
||||
const artists = res.data[0].relationships.artists.data
|
||||
if (!artists.length) {
|
||||
console.error(`[LastFM] Unable to find artists related to the song with id of ${songId}`)
|
||||
return attributes.artistName;
|
||||
}
|
||||
|
||||
const primaryArtist = artists[0]
|
||||
return primaryArtist.attributes.name
|
||||
}
|
||||
private _lfm: any = null;
|
||||
private _authenticated: boolean = false;
|
||||
private _scrobbleDelay: any = null;
|
||||
private _utils: any = null;
|
||||
private _scrobbleCache: any = {};
|
||||
private _nowPlayingCache: any = {};
|
||||
|
||||
/**
|
||||
* Base Plugin Details (Eventually implemented into a GUI in settings)
|
||||
* Public Methods
|
||||
*/
|
||||
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(utils: { getApp: () => any; getStore: () => any; }) {
|
||||
this._app = utils.getApp();
|
||||
this._store = utils.getStore()
|
||||
utils.getApp().on('second-instance', (_e: any, argv: any) => {
|
||||
// Checks if first instance is authorized and if second instance has protocol args
|
||||
argv.forEach((value: any) => {
|
||||
if (value.includes('auth')) {
|
||||
console.log('[LastFMPlugin ok]')
|
||||
let authURI = String(argv).split('/auth/')[1];
|
||||
if (authURI.startsWith('lastfm')) { // If we wanted more auth options
|
||||
const authKey = authURI.split('lastfm?token=')[1];
|
||||
this._store.lastfm.enabled = true;
|
||||
this._store.lastfm.auth_token = authKey;
|
||||
console.log(authKey);
|
||||
this._win.webContents.send('LastfmAuthenticated', authKey);
|
||||
this.authenticate();
|
||||
}
|
||||
}
|
||||
})
|
||||
constructor(utils: any) {
|
||||
this._utils = utils;
|
||||
}
|
||||
|
||||
onReady(_win: Electron.BrowserWindow): void {
|
||||
this.initializeLastFM("", this._apiCredentials)
|
||||
|
||||
// Register the ipcMain handlers
|
||||
this._utils.getIPCMain().handle('lastfm:url', (event: any) => {
|
||||
console.debug(`[${lastfm.name}:url] Called.`)
|
||||
return this._lfm.getAuthenticationUrl({"cb": "cider://auth/lastfm"})
|
||||
})
|
||||
electron.app.on('open-url', (event: any, arg: any) => {
|
||||
console.log('[LastFMPlugin] yes')
|
||||
event.preventDefault();
|
||||
if (arg.includes('auth')) {
|
||||
let authURI = String(arg).split('/auth/')[1];
|
||||
if (authURI.startsWith('lastfm')) { // If we wanted more auth options
|
||||
const authKey = authURI.split('lastfm?token=')[1];
|
||||
this._store.lastfm.enabled = true;
|
||||
this._store.lastfm.auth_token = authKey;
|
||||
this._win.webContents.send('LastfmAuthenticated', authKey);
|
||||
console.log(authKey);
|
||||
this.authenticate();
|
||||
}
|
||||
}
|
||||
|
||||
this._utils.getIPCMain().on('lastfm:auth', (event: any, token: string) => {
|
||||
console.debug(`[${lastfm.name}:auth] Token: `, token)
|
||||
this.authenticateLastFM(token)
|
||||
})
|
||||
|
||||
this._utils.getIPCMain().on('lastfm:disconnect', (_event: any) => {
|
||||
this._lfm.setSessionCredentials(null, null);
|
||||
this._authenticated = false;
|
||||
console.debug(`[${lastfm.name}:disconnect] Disconnected`)
|
||||
})
|
||||
|
||||
this._utils.getIPCMain().on('lastfm:nowPlayingChange', (event: any, attributes: any) => {
|
||||
if (this._utils.getStoreValue("connectivity.lastfm.filter_loop") || this._utils.getStoreValue("general.privateEnabled")) return;
|
||||
this.updateNowPlayingTrack(attributes)
|
||||
})
|
||||
|
||||
this._utils.getIPCMain().on('lastfm:scrobbleTrack', (event: any, attributes: any) => {
|
||||
if (this._utils.getStoreValue("general.privateEnabled")) return;
|
||||
this.scrobbleTrack(attributes)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs on app ready
|
||||
* Runs on playback State Change
|
||||
* @param attributes Music Attributes (attributes.status = current state)
|
||||
*/
|
||||
onReady(win: any): void {
|
||||
this._win = win;
|
||||
this.authenticate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs on app stop
|
||||
*/
|
||||
onBeforeQuit(): void {
|
||||
console.log('Example plugin stopped');
|
||||
onPlaybackStateDidChange(attributes: object): void {
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs on song change
|
||||
* @param attributes Music Attributes
|
||||
* @param scrobble
|
||||
*/
|
||||
nowPlayingItemDidChangeLastFM(attributes: any): void {
|
||||
if (!this._store.general.privateEnabled) {
|
||||
attributes.status = true
|
||||
if (!this._store.lastfm.filterLoop) {
|
||||
this._lastfm.cachedNowPlayingAttributes = false;
|
||||
this._lastfm.cachedAttributes = false
|
||||
}
|
||||
this.updateNowPlayingSong(attributes)
|
||||
this.scrobbleSong(attributes)
|
||||
onNowPlayingItemDidChange(attributes: any, scrobble = false): void {
|
||||
if (this._utils.getStoreValue("general.privateEnabled")) return;
|
||||
this.updateNowPlayingTrack(attributes)
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize LastFM
|
||||
* @param token
|
||||
* @param api
|
||||
* @private
|
||||
*/
|
||||
private initializeLastFM(token: string, api: { key: string, secret: string }): void {
|
||||
console.debug(`[${lastfm.name}:initialize] Initializing LastFM`)
|
||||
const LastfmAPI = require("lastfmapi")
|
||||
this._lfm = new LastfmAPI({
|
||||
'api_key': api.key,
|
||||
'secret': api.secret,
|
||||
});
|
||||
|
||||
if (this._utils.getStoreValue("connectivity.lastfm.secrets.username") && this._utils.getStoreValue("connectivity.lastfm.secrets.key")) {
|
||||
this._lfm.setSessionCredentials(this._utils.getStoreValue("connectivity.lastfm.secrets.username"), this._utils.getStoreValue("connectivity.lastfm.secrets.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(`[${lastfm.name}:authenticate] Error: ${typeof err === "string" ? err : err.message}`);
|
||||
|
||||
this._utils.getWindow().webContents.executeJavaScript(`app.notyf.error("${err.message}");`)
|
||||
return;
|
||||
}
|
||||
this._utils.getWindow().webContents.send('lastfm:authenticated', session)
|
||||
this._authenticated = true;
|
||||
console.debug(`[${lastfm.name}:authenticate] Authenticated as ${session.username}`)
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the track information with lastfm
|
||||
* @param attributes
|
||||
* @param callback
|
||||
* @private
|
||||
*/
|
||||
private verifyTrack(attributes: any, callback: Function): void {
|
||||
if (!attributes) return attributes;
|
||||
|
||||
if (!attributes.lfmAlbum) {
|
||||
this._lfm.album.getInfo({
|
||||
"artist": attributes.artistName,
|
||||
"album": attributes.albumName
|
||||
}, (err: any, data: any) => {
|
||||
if (err) {
|
||||
console.error(`[${lastfm.name}] [album.getInfo] Error: ${typeof err === "string" ? err : err.message}`)
|
||||
return {};
|
||||
}
|
||||
if (data) {
|
||||
attributes.lfmAlbum = data
|
||||
callback(attributes)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this._lfm.track.getCorrection(attributes.artistName, attributes.name, (err: any, data: any) => {
|
||||
if (err) {
|
||||
console.error(`[${lastfm.name}] [track.getCorrection] Error: ${typeof err === "string" ? err : err.message}`)
|
||||
return {};
|
||||
}
|
||||
if (data) {
|
||||
attributes.lfmTrack = data.correction.track
|
||||
callback(attributes)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Scrobbles the track to lastfm
|
||||
* @param attributes
|
||||
* @private
|
||||
*/
|
||||
private scrobbleTrack(attributes: any): void {
|
||||
if (!attributes?.lfmTrack || !attributes?.lfmAlbum) {
|
||||
this.verifyTrack(attributes, (a: any) => {
|
||||
this.scrobbleTrack(a)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (!this._authenticated || !attributes || this._utils.getStoreValue("connectivity.lastfm.filter_types")[attributes.playParams.kind] || (this._utils.getStoreValue("connectivity.lastfm.filter_loop") && this._scrobbleCache.track === attributes.lfmTrack.name)) 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,
|
||||
}
|
||||
|
||||
// Easy Debugging
|
||||
console.debug(`[${lastfm.name}:scrobble] Scrobbling ${scrobble.artist} - ${scrobble.track}`)
|
||||
|
||||
// Scrobble the track
|
||||
this._lfm.track.scrobble(scrobble, (err: any, _res: any) => {
|
||||
if (err) {
|
||||
console.error(`[${lastfm.name}:scrobble] Scrobble failed: ${err.message}`);
|
||||
} else {
|
||||
console.debug(`[${lastfm.name}:scrobble] Track scrobbled: ${scrobble.artist} - ${scrobble.track}`);
|
||||
this._scrobbleCache = scrobble
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the now playing track
|
||||
* @param attributes
|
||||
* @private
|
||||
*/
|
||||
private updateNowPlayingTrack(attributes: any): void {
|
||||
if (!attributes?.lfmTrack || !attributes?.lfmAlbum) {
|
||||
this.verifyTrack(attributes, (a: any) => {
|
||||
this.updateNowPlayingTrack(a)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (!this._authenticated || !attributes || this._utils.getStoreValue("connectivity.lastfm.filter_types")[attributes.playParams.kind] || (this._utils.getStoreValue("connectivity.lastfm.filter_loop") && this._nowPlayingCache.track === attributes.lfmTrack.name)) return;
|
||||
|
||||
const nowPlaying = {
|
||||
'artist': attributes.lfmTrack.artist.name,
|
||||
'track': attributes.lfmTrack.name,
|
||||
'album': attributes.lfmAlbum.name,
|
||||
'trackNumber': attributes.trackNumber,
|
||||
'duration': attributes.durationInMillis / 1000,
|
||||
'albumArtist': attributes.lfmAlbum.artist,
|
||||
}
|
||||
|
||||
this._lfm.track.updateNowPlaying(nowPlaying, (err: any, res: any) => {
|
||||
if (err) {
|
||||
console.error(`[${lastfm.name}:updateNowPlaying] Now Playing Update failed: ${err.message}`);
|
||||
} else {
|
||||
console.debug(`[${lastfm.name}:updateNowPlaying] Now Playing Updated: ${nowPlaying.artist} - ${nowPlaying.track}`);
|
||||
this._nowPlayingCache = nowPlaying
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue