diff --git a/src/main/base/app.ts b/src/main/base/app.ts index 235948e3..ade28ef5 100644 --- a/src/main/base/app.ts +++ b/src/main/base/app.ts @@ -9,7 +9,7 @@ export class AppEvents { "musics", "music" ] - + private static plugin: any = null; private static store: any = null; constructor(store: any) { @@ -88,27 +88,34 @@ export class AppEvents { }) } - electron.app.on('open-url', (event, url) => { - event.preventDefault() - if (this.protocols.some((protocol: string) => url.includes(protocol))) { - AppEvents.LinkHandler(url) - } - }) + } public quit() { console.log('App stopped'); } - public ready() { + public ready(plug: any) { + AppEvents.plugin = plug console.log('App ready'); } + public bwCreated(win: Electron.BrowserWindow) { + electron.app.on('open-url', (event, url) => { + event.preventDefault() + if (AppEvents.protocols.some((protocol: string) => url.includes(protocol))) { + AppEvents.LinkHandler(url, win) + } + }) + + AppEvents.InstanceHandler(win) + } + /*********************************************************************************************************************** * Private methods **********************************************************************************************************************/ - private static LinkHandler(arg: string) { + private static LinkHandler(arg: any, win: Electron.BrowserWindow) { if (!arg) return; // LastFM Auth URL @@ -118,8 +125,8 @@ export class AppEvents { const authKey = authURI.split('lastfm?token=')[1]; AppEvents.store.set('lastfm.enabled', true); AppEvents.store.set('lastfm.auth_token', authKey); - // AppEvents.window.webContents.send('LastfmAuthenticated', authKey); - // lastfm.authenticate() + win.webContents.send('LastfmAuthenticated', authKey); + AppEvents.plugin.callPlugin('lastfm', 'authenticate', authKey); } } // Play @@ -148,4 +155,28 @@ export class AppEvents { electron.ipcRenderer.send('play', 'url', url) } } + + private static InstanceHandler(win: Electron.BrowserWindow) { + + // Detects of an existing instance is running (So if the lock has been achieved, no existing instance has been found) + const gotTheLock = electron.app.requestSingleInstanceLock() + + if (!gotTheLock) { // Runs on the new instance if another instance has been found + console.log('[Cider] Another instance has been found, quitting.') + electron.app.quit() + } else { // Runs on the first instance if no other instance has been found + electron.app.on('second-instance', (_event, startArgs) => { + if (startArgs.includes("--force-quit")) { + console.warn('[InstanceHandler][SecondInstanceHandler] Force Quit found. Quitting App.'); + electron.app.quit() + } else if (startArgs.includes("cider://")) { + AppEvents.LinkHandler(startArgs, win) + } else if (win) { + if (win.isMinimized()) win.restore() + win.focus() + } + }) + } + + } } \ No newline at end of file diff --git a/src/main/base/plugins.ts b/src/main/base/plugins.ts index be87e89f..637f6bd2 100644 --- a/src/main/base/plugins.ts +++ b/src/main/base/plugins.ts @@ -34,6 +34,7 @@ export default class PluginHandler { fs.readdirSync(this.userPluginsPath).forEach(file => { if (file.endsWith('.ts') || file.endsWith('.js')) { const plugin = require(path.join(this.userPluginsPath, file)).default; + file = file.replace('.ts', '').replace('.js', ''); if (plugins[file] || plugin in plugins) { console.log(`[${plugin.name}] Plugin already loaded / Duplicate Class Name`); } else { @@ -54,4 +55,10 @@ export default class PluginHandler { } } + public callPlugin(plugin: string, event: string, ...args: any[]) { + if (this.pluginsList[plugin][event]) { + this.pluginsList[plugin][event](...args); + } + } + } diff --git a/src/main/base/win.ts b/src/main/base/win.ts index d3e49ffc..3e402329 100644 --- a/src/main/base/win.ts +++ b/src/main/base/win.ts @@ -8,7 +8,6 @@ import * as yt from "youtube-search-without-api-key"; import * as fs from "fs"; import { Stream } from "stream"; import * as qrcode from "qrcode-terminal"; -import * as qrcode2 from "qrcode"; import * as os from "os"; import {wsapi} from "./wsapi"; @@ -62,7 +61,6 @@ export class Win { sandbox: true, allowRunningInsecureContent: true, contextIsolation: false, - webviewTag: true, plugins: true, nodeIntegrationInWorker: false, @@ -74,7 +72,7 @@ export class Win { /** * Creates the browser window */ - async createWindow(): Promise { + async createWindow(): Promise { this.clientPort = await getPort({ port: 9000 }); this.verifyFiles(); @@ -91,9 +89,6 @@ export class Win { this.startWebServer(); this.win = new electron.BrowserWindow(this.options); - this.win.on("ready-to-show", () => { - this.win.show(); - }); const ws = new wsapi(this.win) ws.InitWebSockets() // and load the renderer. diff --git a/src/main/index.ts b/src/main/index.ts index 81687a57..cad03017 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -1,8 +1,8 @@ require('v8-compile-cache'); // Analytics for debugging fun yeah. -const ElectronSentry = require("@sentry/electron"); -ElectronSentry.init({dsn: "https://68c422bfaaf44dea880b86aad5a820d2@o954055.ingest.sentry.io/6112214"}); +import * as sentry from '@sentry/electron'; +sentry.init({dsn: "https://68c422bfaaf44dea880b86aad5a820d2@o954055.ingest.sentry.io/6112214"}); import * as electron from 'electron'; import {Win} from "./base/win"; @@ -10,18 +10,19 @@ import {ConfigStore} from "./base/store"; import {AppEvents} from "./base/app"; import PluginHandler from "./base/plugins"; -// const test = new PluginHandler(); const config = new ConfigStore(); const App = new AppEvents(config.store); const Cider = new Win(electron.app, config.store) const plug = new PluginHandler(); +let win: Electron.BrowserWindow; + /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * App Event Handlers * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ electron.app.on('ready', () => { - App.ready(); + App.ready(plug); console.log('[Cider] Application is Ready. Creating Window.') if (!electron.app.isPackaged) { @@ -30,13 +31,13 @@ electron.app.on('ready', () => { } electron.components.whenReady().then(async () => { - await Cider.createWindow() - plug.callPlugins('onReady', Cider); - - - }) - - + win = await Cider.createWindow() + App.bwCreated(win); + win.on("ready-to-show", () => { + win.show(); + }); + }); + plug.callPlugins('onReady', win); }); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -51,57 +52,31 @@ electron.ipcMain.on('nowPlayingItemDidChange', (event, attributes) => { plug.callPlugins('onNowPlayingItemDidChange', attributes); }); -// electron.app.on('before-quit', () => { plug.callPlugins('onBeforeQuit'); console.warn(`${electron.app.getName()} exited.`); }); -// -// // @ts-ignore -// // Widevine Stuff -// electron.app.on('widevine-ready', (version, lastVersion) => { -// if (null !== lastVersion) { -// 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!') -// } -// }) -// // @ts-ignore -// electron.app.on('widevine-update-pending', (currentVersion, pendingVersion) => { -// console.log('[Cider][Widevine] Widevine ' + currentVersion + ' is ready to be upgraded to ' + pendingVersion + '!') -// }) +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +* Widevine Event Handlers +* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ -// // @ts-ignore -// electron.app.on('widevine-error', (error) => { -// console.log('[Cider][Widevine] Widevine installation encountered an error: ' + error) -// electron.app.exit() -// }) - -// -// -// app.on('open-url', (event, url) => { -// event.preventDefault() -// if (url.includes('ame://') || url.includes('itms://') || url.includes('itmss://') || url.includes('musics://') || url.includes('music://')) { -// CiderBase.LinkHandler(url) -// } -// }) -// -electron.app.on('second-instance', (_e, argv) => { - console.warn(`[InstanceHandler][SecondInstanceHandler] Second Instance Started with args: [${argv.join(', ')}]`) - - // Checks if first instance is authorized and if second instance has protocol args - if (argv.includes("--force-quit")) { - console.warn('[InstanceHandler][SecondInstanceHandler] Force Quit found. Quitting App.'); - electron.app.quit() - } else if (Cider.win) { // If a Second Instance has Been Started - console.warn('[InstanceHandler][SecondInstanceHandler] Showing window.'); - Cider.win.show() - Cider.win.focus() +// @ts-ignore +electron.app.on('widevine-ready', (version, lastVersion) => { + if (null !== lastVersion) { + 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!') } }) -if (!electron.app.requestSingleInstanceLock()) { - console.warn("[InstanceHandler] Existing Instance is Blocking Second Instance."); - electron.app.quit(); -} +// @ts-ignore +electron.app.on('widevine-update-pending', (currentVersion, pendingVersion) => { + console.log('[Cider][Widevine] Widevine ' + currentVersion + ' is ready to be upgraded to ' + pendingVersion + '!') +}) + +// @ts-ignore +electron.app.on('widevine-error', (error) => { + console.log('[Cider][Widevine] Widevine installation encountered an error: ' + error) + electron.app.exit() +}) diff --git a/src/main/plugins/lastfm.ts b/src/main/plugins/lastfm.ts index 1eccf2d6..78fdfa90 100644 --- a/src/main/plugins/lastfm.ts +++ b/src/main/plugins/lastfm.ts @@ -1,4 +1,3 @@ - import * as electron from 'electron'; import * as fs from 'fs'; import {resolve} from 'path'; @@ -10,12 +9,13 @@ export default class LastFMPlugin { key: "f9986d12aab5a0fe66193c559435ede3", secret: "acba3c29bd5973efa38cc2f0b63cc625" } - /** - * Private variables for interaction in plugins - */ - private _win: any; - private _app: any; + /** + * Private variables for interaction in plugins + */ + private _win: any; + private _app: any; private _lastfm: any; + private authenticateFromFile() { let sessionData = require(this.sessionPath) console.log("[LastFM][authenticateFromFile] Logging in with Session Info.") @@ -24,64 +24,64 @@ export default class LastFMPlugin { } - private authenticate() { - try{ - 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 - } - /// 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._win.store.store.lastfm.auth_token) - 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(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() + authenticate() { + try { + 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 + } + /// 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._win.store.store.lastfm.auth_token) + 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(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 async scrobbleSong(attributes : any) { + 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 ) { + + if (!this._lastfm || this._lastfm.cachedAttributes === attributes) { return } @@ -112,11 +112,11 @@ export default class LastFMPlugin { this.authenticate(); } } else { - return console.log('[LastFM] Did not add ', attributes.name , '—' , this.filterArtistName(attributes.artistName), 'because now playing a other song.'); + return console.log('[LastFM] Did not add ', attributes.name, '—', this.filterArtistName(attributes.artistName), 'because now playing a other song.'); } } - private filterArtistName(artist :any) { + private filterArtistName(artist: any) { if (!this._win.store.store.lastfm.enabledRemoveFeaturingArtists) return artist; artist = artist.split(' '); @@ -134,8 +134,8 @@ export default class LastFMPlugin { 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) { + private updateNowPlayingSong(attributes: any) { + if (!this._lastfm || this._lastfm.cachedNowPlayingAttributes === attributes || !this._win.store.store.lastfm.NowPlaying) { return } @@ -147,20 +147,20 @@ export default class LastFMPlugin { // 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) { + '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); + console.log('[LastFM] Successfully updated nowPlayingSong', nowPlaying); }); this._lastfm.cachedNowPlayingAttributes = attributes } - + } else { this.authenticate() } @@ -178,10 +178,10 @@ export default class LastFMPlugin { * Runs on plugin load (Currently run on application start) */ constructor(app: any) { - this._app = app; - electron.app.on('second-instance', (_e:any, argv:any) => { + this._app = app; + electron.app.on('second-instance', (_e: any, argv: any) => { // Checks if first instance is authorized and if second instance has protocol args - argv.forEach((value: any) => { + argv.forEach((value: any) => { if (value.includes('auth')) { console.log('[LastFMPlugin ok]') let authURI = String(argv).split('/auth/')[1]; @@ -193,10 +193,10 @@ export default class LastFMPlugin { this._win.win.webContents.send('LastfmAuthenticated', authKey); this.authenticate(); } - } + } }) }) - electron.app.on('open-url', (event :any, arg:any) => { + electron.app.on('open-url', (event: any, arg: any) => { console.log('[LastFMPlugin] yes') event.preventDefault(); if (arg.includes('auth')) { @@ -211,13 +211,13 @@ export default class LastFMPlugin { } } }) - } + } /** * Runs on app ready */ onReady(win: any): void { - this._win = win; + this._win = win; this.authenticate(); }