sorry for doing this.
This commit is contained in:
parent
5fc82a8bc7
commit
b3db294485
106 changed files with 86 additions and 259 deletions
163
oldshit/resources/functions/app-init.js
Normal file
163
oldshit/resources/functions/app-init.js
Normal file
|
@ -0,0 +1,163 @@
|
|||
const {app, protocol, dialog} = require("electron"),
|
||||
{join, resolve} = require("path"),
|
||||
{existsSync, createReadStream, unlink, rmSync} = require("fs"),
|
||||
Store = require('electron-store');
|
||||
|
||||
module.exports = () => {
|
||||
|
||||
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Application Configuration Init
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
||||
app.setPath("userData", join(app.getPath("appData"), app.name.replace(/\s/g, ''))) // Set Linux to use .cache instead of .config and remove the space as its annoying
|
||||
|
||||
// Set the Theme List based on css files in themes directory
|
||||
app.userThemesPath = resolve(app.getPath('userData'), 'themes');
|
||||
app.userPluginsPath = resolve(app.getPath('userData'), 'plugins');
|
||||
let showIntro = false
|
||||
|
||||
const migrationFunctions = {
|
||||
clearElectronPrefs: () => {
|
||||
if (existsSync(resolve(app.getPath('userData'), 'preferences.json'))) {
|
||||
unlink(resolve(app.getPath('userData'), 'preferences.json'), (err) => {
|
||||
if (err) console.error(err)
|
||||
})
|
||||
}
|
||||
if (existsSync(resolve(app.getPath('userData'), 'Preferences'))) {
|
||||
unlink(resolve(app.getPath('userData'), 'Preferences'), (err) => {
|
||||
if (err) console.error(err)
|
||||
})
|
||||
}
|
||||
},
|
||||
clearCache: () => {
|
||||
if (existsSync(resolve(app.getPath('userData'), 'Cache'))) {
|
||||
rmSync(resolve(app.getPath('userData'), 'Cache'), {recursive: true, force: true})
|
||||
}
|
||||
},
|
||||
showDevelopmentMessage: () => {
|
||||
app.whenReady().then(() => {
|
||||
dialog.showMessageBox({
|
||||
title: "Version under Development!",
|
||||
message: "This version is under development. Expect bugs and issues whilst using the application.",
|
||||
type: "warning"
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
const storeDefaults = {
|
||||
general: {
|
||||
storefront: "",
|
||||
incognitoMode: false,
|
||||
playbackNotifications: "minimized",
|
||||
trayTooltipSongName: true,
|
||||
startupPage: "browse",
|
||||
discordRPC: "ame-title",
|
||||
discordClearActivityOnPause: true,
|
||||
lastfm: false,
|
||||
lastfmRemoveFeaturingArtists: true,
|
||||
lastfmNowPlaying: true,
|
||||
analyticsEnabled: true,
|
||||
lastfmScrobbleDelay: 30
|
||||
},
|
||||
visual: {
|
||||
theme: "default",
|
||||
frameType: "",
|
||||
transparencyEffect: "",
|
||||
transparencyTheme: "appearance-based",
|
||||
transparencyDisableBlur: true,
|
||||
transparencyMaximumRefreshRate: "",
|
||||
streamerMode: false,
|
||||
removeUpsell: true,
|
||||
removeAppleLogo: true,
|
||||
removeFooter: true,
|
||||
removeScrollbars: true,
|
||||
useOperatingSystemAccent: false,
|
||||
scaling: 1,
|
||||
yton: false,
|
||||
mxmon: false,
|
||||
mxmlanguage: "en"
|
||||
},
|
||||
audio: {
|
||||
audioQuality: "auto",
|
||||
seamlessAudioTransitions: false,
|
||||
castingBitDepth: '16',
|
||||
enableDLNA: false,
|
||||
},
|
||||
window: {
|
||||
appStartupBehavior: "",
|
||||
closeButtonMinimize: true,
|
||||
alwaysOnTop: false
|
||||
},
|
||||
advanced: {
|
||||
forceApplicationMode: "system",
|
||||
hardwareAcceleration: true,
|
||||
verboseLogging: false,
|
||||
autoUpdaterBetaBuilds: false,
|
||||
useBetaSite: true,
|
||||
preventMediaKeyHijacking: false,
|
||||
devToolsOnStartup: false,
|
||||
allowMultipleInstances: false
|
||||
},
|
||||
tokens: {
|
||||
lastfm: ""
|
||||
}
|
||||
}
|
||||
const storeMigrations = {
|
||||
'>=3.0.0': store => {
|
||||
showIntro = true
|
||||
},
|
||||
|
||||
'<=3.0.0': store => {
|
||||
migrationFunctions.clearElectronPrefs()
|
||||
migrationFunctions.clearCache()
|
||||
migrationFunctions.showDevelopmentMessage()
|
||||
}
|
||||
}
|
||||
|
||||
app.cfg = new Store({
|
||||
defaults: storeDefaults,
|
||||
migrations: storeMigrations
|
||||
})
|
||||
app.cfg.watch = true;
|
||||
app.isQuiting = false;
|
||||
|
||||
app.whenReady().then(() => {
|
||||
protocol.registerFileProtocol('themes', (request, callback) => {
|
||||
const url = request.url.substr(7)
|
||||
callback({
|
||||
path: join(app.userThemesPath, url.toLowerCase())
|
||||
})
|
||||
})
|
||||
protocol.registerFileProtocol('ameres', (request, callback) => {
|
||||
const url = request.url.substr(7)
|
||||
callback(createReadStream(join(join(__dirname, '../'), url.toLowerCase())))
|
||||
})
|
||||
protocol.registerFileProtocol('plugin', (request, callback) => {
|
||||
const url = request.url.substr(7)
|
||||
callback({
|
||||
path: join(app.userPluginsPath, url.toLowerCase())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
const handlersFuncs = require('./handler'),
|
||||
initFuncs = require('./init'),
|
||||
loadFuncs = require('./load'),
|
||||
utilsFuncs = require('./utils'),
|
||||
winFuncs = require('./win'),
|
||||
discordFuncs = require('./media/discordrpc'),
|
||||
lastfmFuncs = require('./media/lastfm'),
|
||||
mprisFuncs = require('./media/mpris');
|
||||
|
||||
return {
|
||||
handler: handlersFuncs,
|
||||
init: initFuncs,
|
||||
load: loadFuncs,
|
||||
utils: utilsFuncs,
|
||||
win: winFuncs,
|
||||
discord: discordFuncs,
|
||||
lastfm: lastfmFuncs,
|
||||
mpris: mprisFuncs,
|
||||
wsapi: require('./wsapi'),
|
||||
showOOBE: showIntro
|
||||
};
|
||||
}
|
1468
oldshit/resources/functions/handler.js
Normal file
1468
oldshit/resources/functions/handler.js
Normal file
File diff suppressed because it is too large
Load diff
234
oldshit/resources/functions/init.js
Normal file
234
oldshit/resources/functions/init.js
Normal file
|
@ -0,0 +1,234 @@
|
|||
const {app, nativeTheme, nativeImage, Tray} = require("electron"),
|
||||
{join, resolve} = require("path"),
|
||||
os = require("os"),
|
||||
{existsSync, readdirSync} = require("fs"),
|
||||
regedit = require("regedit"),
|
||||
{initAnalytics} = require('./utils');
|
||||
initAnalytics();
|
||||
|
||||
const init = {
|
||||
|
||||
BaseInit: () => {
|
||||
const censoredConfig = app.cfg.store;
|
||||
censoredConfig.tokens = {};
|
||||
|
||||
console.log('---------------------------------------------------------------------')
|
||||
console.log(`${app.getName()} has started.`);
|
||||
console.log(`Version: ${app.getVersion()} | Electron Version: ${process.versions.electron}`)
|
||||
console.log(`Type: ${os.type} | Release: ${os.release()} ${app.ame.utils.fetchOperatingSystem() ? `(${app.ame.utils.fetchOperatingSystem()})` : ""} | Platform: ${os.platform()}`)
|
||||
console.log(`User Data Path: '${app.getPath('userData')}'`)
|
||||
console.log(`Current Configuration: ${JSON.stringify(censoredConfig)}`)
|
||||
console.log("---------------------------------------------------------------------")
|
||||
if (app.cfg.get('general.analyticsEnabled') && app.isPackaged) console.log('[Sentry] Sentry logging is enabled, any errors you receive will be presented to the development team to fix for the next release.')
|
||||
console.verbose('[InitializeBase] Started.');
|
||||
|
||||
// Disable CORS
|
||||
app.commandLine.appendSwitch('disable-features', 'OutOfBlinkCors')
|
||||
app.commandLine.appendSwitch('high-dpi-support', 'true')
|
||||
if (process.platform === "win32") {
|
||||
app.commandLine.appendSwitch('force-device-scale-factor', '1')
|
||||
}
|
||||
|
||||
if (app.cfg.get('advanced.verboseLogging')) {
|
||||
app.commandLine.appendSwitch('--enable-logging');
|
||||
app.commandLine.appendSwitch('--log-file', join(app.getPath('userData'), 'logs', 'renderer.log'));
|
||||
console.verbose(`[InitializeBase] Renderer logging setup at ${join(app.getPath('userData'), 'logs', 'renderer.log')}`);
|
||||
}
|
||||
|
||||
// Media Key Hijacking
|
||||
if (app.cfg.get('advanced.preventMediaKeyHijacking')) {
|
||||
console.log("[Apple-Music-Electron] Hardware Media Key Handling disabled.")
|
||||
app.commandLine.appendSwitch('disable-features', 'HardwareMediaKeyHandling,MediaSessionService');
|
||||
}
|
||||
|
||||
// GPU Hardware Acceleration
|
||||
if (!app.cfg.get('advanced.hardwareAcceleration')) {
|
||||
app.commandLine.appendSwitch('disable-gpu')
|
||||
}
|
||||
|
||||
// Registry
|
||||
if (process.platform === "win32") {
|
||||
regedit.setExternalVBSLocation("resources/regedit/vbs")
|
||||
}
|
||||
|
||||
// Sets the ModelId (For windows notifications)
|
||||
if (process.platform === "win32") app.setAppUserModelId(app.getName());
|
||||
|
||||
// Disable the Media Session to allow MPRIS to be the primary service
|
||||
if (process.platform === "linux") app.commandLine.appendSwitch('disable-features', 'MediaSessionService');
|
||||
|
||||
// Assign Default Variables
|
||||
app.isQuiting = (app.isQuiting ? app.isQuiting : false);
|
||||
app.win = '';
|
||||
app.ipc = {
|
||||
existingNotification: false
|
||||
};
|
||||
|
||||
if (app.cfg.get('general.incognitoMode')) {
|
||||
console.log("[Incognito] Incognito Mode enabled. DiscordRPC and LastFM updates are ignored.")
|
||||
}
|
||||
|
||||
/* Protocols for Link Handling */
|
||||
if (process.defaultApp) {
|
||||
if (process.argv.length >= 2) {
|
||||
app.setAsDefaultProtocolClient('ame', process.execPath, [resolve(process.argv[1])])
|
||||
app.setAsDefaultProtocolClient('itms', process.execPath, [resolve(process.argv[1])])
|
||||
app.setAsDefaultProtocolClient('itmss', process.execPath, [resolve(process.argv[1])])
|
||||
app.setAsDefaultProtocolClient('musics', process.execPath, [resolve(process.argv[1])])
|
||||
app.setAsDefaultProtocolClient('music', process.execPath, [resolve(process.argv[1])])
|
||||
}
|
||||
} else {
|
||||
app.setAsDefaultProtocolClient('ame') // Custom AME Protocol
|
||||
app.setAsDefaultProtocolClient('itms') // iTunes HTTP Protocol
|
||||
app.setAsDefaultProtocolClient('itmss') // iTunes HTTPS Protocol
|
||||
app.setAsDefaultProtocolClient('musics') // macOS Client Protocol
|
||||
app.setAsDefaultProtocolClient('music') // macOS Client Protocol
|
||||
}
|
||||
|
||||
app.on('open-url', (event, url) => {
|
||||
event.preventDefault()
|
||||
if (url.includes('ame://') || url.includes('itms://') || url.includes('itmss://') || url.includes('musics://') || url.includes('music://')) {
|
||||
app.ame.handler.LinkHandler(url)
|
||||
}
|
||||
})
|
||||
|
||||
// Running the Application on Login
|
||||
if (app.cfg.get('window.appStartupBehavior')) {
|
||||
app.setLoginItemSettings({
|
||||
openAtLogin: true,
|
||||
args: [
|
||||
'--process-start-args', `${app.cfg.get('window.appStartupBehavior') === 'hidden' ? "--hidden" : (app.cfg.get('window.appStartupBehavior') === 'minimized' ? "--minimized" : "")}`
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
// Set Max Listener
|
||||
require('events').EventEmitter.defaultMaxListeners = Infinity;
|
||||
},
|
||||
|
||||
LoggingInit: () => {
|
||||
app.log = require("electron-log");
|
||||
|
||||
if (app.commandLine.hasSwitch('verbose')) {
|
||||
app.verboseLaunched = true
|
||||
}
|
||||
|
||||
app.log.transports.file.resolvePath = (vars) => {
|
||||
return join(app.getPath('userData'), 'logs', vars.fileName);
|
||||
}
|
||||
|
||||
Object.assign(console, app.log.functions);
|
||||
|
||||
console.verbose = () => {
|
||||
};
|
||||
|
||||
if (app.cfg.get('advanced.verboseLogging') || app.verboseLaunched) {
|
||||
console.verbose = app.log.debug
|
||||
} else {
|
||||
console.verbose = function (_data) {
|
||||
return false
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
ThemeInstallation: () => {
|
||||
const themesPath = join(app.getPath('userData'), "themes");
|
||||
|
||||
// Check if the themes folder exists and check permissions
|
||||
if (existsSync(join(themesPath, 'README.md'))) {
|
||||
console.verbose('[ThemeInstallation] Themes Directory Exists. Running Permission Check.')
|
||||
app.ame.utils.permissionsCheck(themesPath, 'README.md')
|
||||
} else {
|
||||
app.ame.utils.updateThemes().catch(err => console.error(err))
|
||||
}
|
||||
|
||||
// Save all the file names to array and log it
|
||||
if (existsSync(themesPath)) {
|
||||
console.log(`[InitializeTheme] Files found in Themes Directory: [${readdirSync(themesPath).join(', ')}]`)
|
||||
}
|
||||
|
||||
// Set the default theme
|
||||
if (app.cfg.get('advanced.forceApplicationMode')) {
|
||||
nativeTheme.themeSource = app.cfg.get('advanced.forceApplicationMode')
|
||||
}
|
||||
},
|
||||
|
||||
PluginInstallation: () => {
|
||||
if (!existsSync(resolve(app.getPath("userData"), "plugins"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the plugins folder exists and check permissions
|
||||
app.pluginsEnabled = true;
|
||||
console.log("[PluginInstallation][existsSync] Plugins folder exists!");
|
||||
app.ame.utils.permissionsCheck(app.userPluginsPath, '/');
|
||||
app.ame.utils.fetchPluginsListing();
|
||||
|
||||
// Save all the file names to array and log it
|
||||
console.log(`[PluginInstallation] Files found in Plugins Directory: [${readdirSync(resolve(app.getPath("userData"), "plugins")).join(', ')}]`);
|
||||
},
|
||||
|
||||
AppReady: () => {
|
||||
console.verbose('[ApplicationReady] Started.');
|
||||
app.pluginsEnabled = false;
|
||||
|
||||
// Run the Functions
|
||||
init.ThemeInstallation()
|
||||
init.PluginInstallation()
|
||||
init.TrayInit()
|
||||
|
||||
app.ame.mpris.connect(); // M.P.R.I.S
|
||||
app.ame.lastfm.authenticate(); // LastFM
|
||||
app.ame.discord.connect(app.cfg.get('general.discordRPC') === 'ame-title' ? '911790844204437504' : '886578863147192350'); // Discord
|
||||
|
||||
app.isAuthorized = false;
|
||||
app.isMiniplayerActive = false;
|
||||
app.injectedCSS = {}
|
||||
app.media = {status: false, playParams: {id: 'no-id-found'}};
|
||||
|
||||
/** wsapi */
|
||||
// app.ame.wsapi.inAppUI()
|
||||
/** wsapi */
|
||||
},
|
||||
|
||||
TrayInit: () => {
|
||||
console.verbose('[InitializeTray] Started.');
|
||||
|
||||
const winTray = nativeImage.createFromPath(join(__dirname, `../icons/icon.ico`)).resize({
|
||||
width: 32,
|
||||
height: 32
|
||||
})
|
||||
const macTray = nativeImage.createFromPath(join(__dirname, `../icons/icon.png`)).resize({
|
||||
width: 20,
|
||||
height: 20
|
||||
})
|
||||
const linuxTray = nativeImage.createFromPath(join(__dirname, `../icons/icon.png`)).resize({
|
||||
width: 32,
|
||||
height: 32
|
||||
})
|
||||
let trayIcon;
|
||||
if (process.platform === "win32") {
|
||||
trayIcon = winTray
|
||||
} else if (process.platform === "linux") {
|
||||
trayIcon = linuxTray
|
||||
} else if (process.platform === "darwin") {
|
||||
trayIcon = macTray
|
||||
}
|
||||
|
||||
app.tray = new Tray(trayIcon)
|
||||
app.tray.setToolTip(app.getName());
|
||||
app.ame.win.SetContextMenu(true);
|
||||
|
||||
app.tray.on('double-click', () => {
|
||||
if (typeof app.win.show === 'function') {
|
||||
if (app.win.isVisible()) {
|
||||
app.win.focus()
|
||||
} else {
|
||||
app.win.show()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = init
|
238
oldshit/resources/functions/load.js
Normal file
238
oldshit/resources/functions/load.js
Normal file
|
@ -0,0 +1,238 @@
|
|||
const {join, resolve} = require("path"),
|
||||
{app, ipcMain, systemPreferences} = require("electron"),
|
||||
{readFile, constants, chmodSync, existsSync, watch} = require("fs"),
|
||||
{initAnalytics} = require('./utils');
|
||||
initAnalytics();
|
||||
|
||||
module.exports = {
|
||||
|
||||
LoadCSS: function (path, theme, important) {
|
||||
const fileName = path
|
||||
if (theme) {
|
||||
path = join(app.userThemesPath, path.toLowerCase());
|
||||
} else {
|
||||
path = join(join(__dirname, '../css/'), path)
|
||||
}
|
||||
|
||||
// Check that the file exists
|
||||
if (!existsSync(path)) {
|
||||
console.warn(`[LoadCSS] ${path} not found.`)
|
||||
return
|
||||
}
|
||||
|
||||
// Remove previous inject (If there is one)
|
||||
if (app.injectedCSS[path]) {
|
||||
app.win.webContents.removeInsertedCSS(app.injectedCSS[fileName]).then(r => { if (r) console.error(r); });
|
||||
}
|
||||
|
||||
// Get the CSS to inject
|
||||
readFile(path, "utf-8", function (error, data) {
|
||||
if (error) {
|
||||
console.error(`[LoadCSS] Error while injecting: '${path}' - ${error}`)
|
||||
try {
|
||||
chmodSync(path, constants.S_IRUSR | constants.S_IWUSR);
|
||||
} catch (err) {
|
||||
console.error(`[LoadCSS] ${err}`)
|
||||
}
|
||||
} else {
|
||||
let formattedData = data.replace(/\s{2,10}/g, ' ').trim();
|
||||
app.win.webContents.insertCSS(formattedData, {cssOrigin: (important ? 'user' : 'author')}).then((key) => {
|
||||
console.verbose(`[${theme ? 'LoadTheme' : 'LoadCSS'}] '${fileName}' successfully injected.`)
|
||||
app.injectedCSS[fileName] = key
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
LoadJS: function (path, formatting = true) {
|
||||
const fileName = path;
|
||||
path = join(join(__dirname, '../js/'), path)
|
||||
|
||||
readFile(path, "utf-8", function (error, data) {
|
||||
if (!error) {
|
||||
try {
|
||||
let formattedData = data
|
||||
if (formatting) {
|
||||
formattedData = data.replace(/\s{2,10}/g, ' ').trim();
|
||||
}
|
||||
app.win.webContents.executeJavaScript(formattedData).then(() => {
|
||||
console.verbose(`[LoadJSFile] '${fileName}' successfully injected.`)
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(`[LoadJSFile] Error while injecting: '${fileName}' - Error: ${err}`)
|
||||
}
|
||||
} else {
|
||||
console.error(`[LoadJSFile] Error while reading: '${fileName}' - Error: ${error}`)
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
LoadWebsite: function (win) {
|
||||
if (!win) return;
|
||||
|
||||
app.storefront = app.cfg.get('general.storefront');
|
||||
const urlBase = app.cfg.get('advanced.useBetaSite') ? 'https://beta.music.apple.com' : 'https://music.apple.com/' + app.cfg.get('general.storefront'),
|
||||
urlFallback = `https://music.apple.com/`;
|
||||
|
||||
ipcMain.once('userAuthorized', (e, args) => {
|
||||
app.isAuthorized = true
|
||||
console.log(`[LoadWebsite] User Authenticated. Setting page to: ${args}`)
|
||||
win.webContents.clearHistory()
|
||||
})
|
||||
|
||||
win.loadURL(urlBase).then(() => {
|
||||
app.ame.load.LoadJS('checkAuth.js')
|
||||
}).catch((err) => {
|
||||
win.loadURL(urlFallback).then(() => console.error(`[LoadWebsite] '${urlBase}' was unavailable, falling back to '${urlFallback}' | ${err}`))
|
||||
})
|
||||
},
|
||||
|
||||
LoadFiles: function () {
|
||||
app.ame.load.LoadJS('settingsPage.js');
|
||||
if (app.cfg.get('visual.removeAppleLogo')) {
|
||||
app.win.webContents.insertCSS(`
|
||||
@media only screen and (max-width: 483px) {
|
||||
.web-navigation__nav-list {
|
||||
margin-top: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
`).catch((e) => console.error(e));
|
||||
}
|
||||
|
||||
if (app.cfg.get('visual.useOperatingSystemAccent') && (process.platform === "win32" || process.platform === "darwin")) {
|
||||
if (systemPreferences.getAccentColor()) {
|
||||
const accent = '#' + systemPreferences.getAccentColor().slice(0, -2)
|
||||
app.win.webContents.insertCSS(`
|
||||
:root {
|
||||
--keyColor: ${accent} !important;
|
||||
--systemAccentBG: ${accent} !important;
|
||||
--systemAccentBG-pressed: rgba(${app.ame.utils.hexToRgb(accent).r}, ${app.ame.utils.hexToRgb(accent).g}, ${app.ame.utils.hexToRgb(accent).b}, 0.75) !important;
|
||||
--keyColor-rgb: ${app.ame.utils.hexToRgb(accent).r} ${app.ame.utils.hexToRgb(accent).g} ${app.ame.utils.hexToRgb(accent).b} !important;
|
||||
}`).then((key) => {
|
||||
app.injectedCSS['useOperatingSystemAccent'] = key
|
||||
})
|
||||
}
|
||||
} else {
|
||||
app.ame.win.removeInsertedCSS('useOperatingSystemAccent')
|
||||
}
|
||||
|
||||
/* Load Window Frame */
|
||||
if (app.cfg.get('visual.frameType') === 'mac') {
|
||||
app.ame.load.LoadJS('frame_macOS.js')
|
||||
} else if ((app.cfg.get('visual.frameType') === 'mac-right')) {
|
||||
app.ame.load.LoadJS('frame_Windows.js')
|
||||
} else if (process.platform === 'darwin' && !app.cfg.get('visual.frameType')) {
|
||||
app.ame.load.LoadJS('frame_macOS.js')
|
||||
} else if (process.platform === 'win32' && !app.cfg.get('visual.frameType')) {
|
||||
app.ame.load.LoadJS('frame_Windows.js')
|
||||
if (app.win.isMaximized()) {
|
||||
app.win.webContents.executeJavaScript(`if (document.querySelector("#maximize")) { document.querySelector("#maximize").classList.add("maxed"); }`).catch((e) => console.error(e));
|
||||
}
|
||||
}
|
||||
|
||||
const BackButtonChecks = (url) => {
|
||||
if (!app.win.webContents.canGoBack()) return false
|
||||
const backButtonBlacklist = [`*music.apple.com/*/listen-now*`, `*music.apple.com/*/browse*`, `*music.apple.com/*/radio*`, `*music.apple.com/*/search*`, `*music.apple.com/library/recently-added?l=*`, `*music.apple.com/library/albums?l=*`, `*music.apple.com/library/songs?l=*`, `*music.apple.com/library/made-for-you?l=*`, `*music.apple.com/library/recently-added`, `*music.apple.com/library/albums`, `*music.apple.com/library/made-for-you`, `*music.apple.com/library/songs*`, `*music.apple.com/library/artists/*`, `*music.apple.com/library/playlist/*`];
|
||||
let blacklistPassed = true
|
||||
backButtonBlacklist.forEach((item) => {
|
||||
if (!blacklistPassed) return;
|
||||
if (app.ame.utils.matchRuleShort(url, item) || url === item) {
|
||||
blacklistPassed = false
|
||||
}
|
||||
});
|
||||
return blacklistPassed
|
||||
}
|
||||
|
||||
/* Load Back Button */
|
||||
if (BackButtonChecks(app.win.webContents.getURL())) {
|
||||
app.ame.load.LoadJS('backButton.js')
|
||||
app.win.webContents.executeJavaScript(`document.body.setAttribute('back-button', 1)`)
|
||||
} else { /* Removes the button if the check failed. */
|
||||
app.win.webContents.executeJavaScript(`if (document.querySelector('#backButtonBar')) { document.getElementById('backButtonBar').remove() };`).catch((e) => console.error(e));
|
||||
app.win.webContents.executeJavaScript(`document.body.removeAttribute('back-button')`)
|
||||
}
|
||||
|
||||
/* Load the Startup JavaScript Function */
|
||||
app.win.webContents.executeJavaScript('if (AMJavaScript) { AMJavaScript.LoadCustom(); }').catch((e) => console.error(e));
|
||||
},
|
||||
|
||||
LoadOneTimeFiles: function () {
|
||||
// Inject the custom stylesheet
|
||||
app.ame.load.LoadCSS('custom-stylesheet.css')
|
||||
app.ame.load.LoadCSS('ameframework.css')
|
||||
|
||||
// Inject Plugin Interaction
|
||||
if (app.pluginsEnabled) {
|
||||
app.ame.load.LoadJS('pluginSystem.js', false)
|
||||
}
|
||||
// Load this first so it doesn't stuck
|
||||
app.ame.load.LoadJS('OpusMediaRecorder.umd.js')
|
||||
app.ame.load.LoadJS('encoderWorker.umd.js')
|
||||
|
||||
|
||||
// Lyrics
|
||||
app.ame.load.LoadJS('lyrics.js')
|
||||
|
||||
// Vue Test
|
||||
app.ame.load.LoadJS('vue.js')
|
||||
app.ame.load.LoadJS('utils.js', false)
|
||||
app.ame.load.LoadJS('tests.js', false)
|
||||
// wsapi
|
||||
app.ame.load.LoadJS('WSAPI_Interop.js', false)
|
||||
// wsapi
|
||||
|
||||
// Bulk JavaScript Functions
|
||||
app.ame.load.LoadJS('custom.js')
|
||||
|
||||
// Audio Manuipulation Stuff
|
||||
|
||||
app.ame.load.LoadJS('eq.js')
|
||||
|
||||
|
||||
// Window Frames
|
||||
if (app.cfg.get('visual.frameType') === 'mac') {
|
||||
app.ame.load.LoadCSS('frame_macOS_emulation.css')
|
||||
} else if (app.cfg.get('visual.frameType') === 'mac-right') {
|
||||
app.ame.load.LoadCSS('frame_macOS_emulation_right.css')
|
||||
} else if (process.platform === 'win32' && !app.cfg.get('visual.frameType')) {
|
||||
app.ame.load.LoadCSS('frame_Windows.css')
|
||||
}
|
||||
|
||||
// Set the settings variables if needed
|
||||
if (app.cfg.get('visual.frameType') === 'mac' || app.cfg.get('visual.frameType') === 'mac-right') {
|
||||
app.cfg.set('visual.removeUpsell', true);
|
||||
app.cfg.set('visual.removeAppleLogo', true);
|
||||
}
|
||||
|
||||
// Streamer Mode
|
||||
if (app.cfg.get('visual.streamerMode')) {
|
||||
app.ame.load.LoadCSS('streamerMode.css')
|
||||
}
|
||||
|
||||
/* Remove the Scrollbar */
|
||||
if (app.cfg.get('visual.removeScrollbars')) {
|
||||
app.win.webContents.insertCSS('::-webkit-scrollbar { display: none; }').then()
|
||||
} else {
|
||||
app.ame.load.LoadCSS('macosScrollbar.css')
|
||||
}
|
||||
|
||||
/* Inject the MusicKitInterop file */
|
||||
app.win.webContents.executeJavaScript('MusicKitInterop.init()').catch((e) => console.error(e));
|
||||
|
||||
/* Watches for changes to a theme */
|
||||
if (app.watcher) {
|
||||
app.watcher.close();
|
||||
console.verbose('[Watcher] Removed old watcher.')
|
||||
}
|
||||
|
||||
if (existsSync(resolve(app.getPath('userData'), 'themes', `${app.cfg.get('visual.theme')}.css`)) && app.cfg.get('visual.theme') !== "default" && app.cfg.get('visual.theme')) {
|
||||
app.watcher = watch(resolve(app.getPath('userData'), 'themes', `${app.cfg.get('visual.theme')}.css`), (event, fileName) => {
|
||||
if (event === "change" && fileName === `${app.cfg.get('visual.theme')}.css`) {
|
||||
app.win.webContents.executeJavaScript(`AMStyling.loadTheme("${app.cfg.get('visual.theme')}", true);`).catch((err) => console.error(err));
|
||||
}
|
||||
});
|
||||
console.verbose(`[Watcher] Watching for changes: 'themes/${app.cfg.get('visual.theme')}.css'`)
|
||||
}
|
||||
}
|
||||
}
|
121
oldshit/resources/functions/media/discordrpc.js
Normal file
121
oldshit/resources/functions/media/discordrpc.js
Normal file
|
@ -0,0 +1,121 @@
|
|||
const {app} = require('electron'),
|
||||
DiscordRPC = require('discord-rpc'),
|
||||
{initAnalytics} = require('../utils');
|
||||
initAnalytics();
|
||||
|
||||
module.exports = {
|
||||
connect: function (clientId) {
|
||||
app.discord = {isConnected: false};
|
||||
if (!app.cfg.get('general.discordRPC')) return;
|
||||
|
||||
DiscordRPC.register(clientId) // Apparently needed for ask to join, join, spectate etc.
|
||||
const client = new DiscordRPC.Client({ transport: "ipc" });
|
||||
app.discord = Object.assign(client,{error: false, activityCache: null, isConnected: false});
|
||||
|
||||
// Login to Discord
|
||||
app.discord.login({ clientId })
|
||||
.then(() => {
|
||||
app.discord.isConnected = true;
|
||||
})
|
||||
.catch((e) => console.error(`[DiscordRPC][connect] ${e}`));
|
||||
|
||||
app.discord.on('ready', () => {
|
||||
console.log(`[DiscordRPC][connect] Successfully Connected to Discord. Authed for user: ${client.user.username} (${client.user.id})`);
|
||||
|
||||
if (app.discord.activityCache) {
|
||||
client.setActivity(app.discord.activityCache).catch((e) => console.error(e));
|
||||
app.discord.activityCache = null;
|
||||
}
|
||||
})
|
||||
|
||||
// Handles Errors
|
||||
app.discord.on('error', err => {
|
||||
console.error(`[DiscordRPC] ${err}`);
|
||||
this.disconnect()
|
||||
app.discord.isConnected = false;
|
||||
});
|
||||
},
|
||||
|
||||
disconnect: function () {
|
||||
if (!app.cfg.get('general.discordRPC') || !app.discord.isConnected) return;
|
||||
|
||||
try {
|
||||
app.discord.destroy().then(() => {
|
||||
app.discord.isConnected = false;
|
||||
console.verbose('[DiscordRPC][disconnect] Disconnected from discord.')
|
||||
}).catch((e) => console.error(`[DiscordRPC][disconnect] ${e}`));
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
},
|
||||
|
||||
updateActivity: function (attributes) {
|
||||
if (!app.cfg.get('general.discordRPC') || app.cfg.get('general.incognitoMode')) return;
|
||||
|
||||
if (!app.discord.isConnected) {
|
||||
this.connect()
|
||||
}
|
||||
|
||||
if (!app.discord.isConnected) return;
|
||||
|
||||
console.verbose('[DiscordRPC][updateActivity] Updating Discord Activity.')
|
||||
|
||||
const listenURL = `https://applemusicelectron.com/p?id=${attributes.playParams.id}`
|
||||
|
||||
let ActivityObject = {
|
||||
details: attributes.name,
|
||||
state: `by ${attributes.artistName}`,
|
||||
startTimestamp: attributes.startTime,
|
||||
endTimestamp: attributes.endTime,
|
||||
largeImageKey: ((app.cfg.get('general.discordRPC') === 'am-title') ? 'apple' : 'cider'),
|
||||
largeImageText: attributes.albumName,
|
||||
smallImageKey: (attributes.status ? 'play' : 'pause'),
|
||||
smallImageText: (attributes.status ? 'Playing': 'Paused'),
|
||||
instance: true,
|
||||
buttons: [
|
||||
{label: "Listen on Cider", url: listenURL},
|
||||
]
|
||||
};
|
||||
console.verbose(`[LinkHandler] Listening URL has been set to: ${listenURL}`);
|
||||
|
||||
if (app.cfg.get('general.discordClearActivityOnPause')) {
|
||||
delete ActivityObject.smallImageKey
|
||||
delete ActivityObject.smallImageText
|
||||
}
|
||||
|
||||
// Check all the values work
|
||||
if (!((new Date(attributes.endTime)).getTime() > 0)) {
|
||||
delete ActivityObject.startTimestamp
|
||||
delete ActivityObject.endTimestamp
|
||||
}
|
||||
if (!attributes.artistName) {
|
||||
delete ActivityObject.state
|
||||
}
|
||||
if (!ActivityObject.largeImageText || ActivityObject.largeImageText.length < 2) {
|
||||
delete ActivityObject.largeImageText
|
||||
}
|
||||
|
||||
// Clear if if needed
|
||||
if (!attributes.status) {
|
||||
if (app.cfg.get('general.discordClearActivityOnPause')) {
|
||||
app.discord.clearActivity().catch((e) => console.error(`[DiscordRPC][clearActivity] ${e}`));
|
||||
ActivityObject = null
|
||||
} else {
|
||||
delete ActivityObject.startTimestamp
|
||||
delete ActivityObject.endTimestamp
|
||||
ActivityObject.smallImageKey = 'pause'
|
||||
ActivityObject.smallImageText = 'Paused'
|
||||
}
|
||||
}
|
||||
|
||||
if (ActivityObject) {
|
||||
try {
|
||||
console.verbose(`[DiscordRPC][setActivity] Setting activity to ${JSON.stringify(ActivityObject)}`);
|
||||
app.discord.setActivity(ActivityObject)
|
||||
} catch (err) {
|
||||
console.error(`[DiscordRPC][setActivity] ${err}`)
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
}
|
155
oldshit/resources/functions/media/lastfm.js
Normal file
155
oldshit/resources/functions/media/lastfm.js
Normal file
|
@ -0,0 +1,155 @@
|
|||
const {app, Notification} = require('electron'),
|
||||
fs = require('fs'),
|
||||
{resolve} = require('path'),
|
||||
sessionPath = resolve(app.getPath('userData'), 'session.json'),
|
||||
apiCredentials = require('../../lfmApiCredentials.json'),
|
||||
LastfmAPI = require('lastfmapi'),
|
||||
{initAnalytics} = require('../utils');
|
||||
initAnalytics();
|
||||
|
||||
const lfm = {
|
||||
authenticateFromFile: function () {
|
||||
let sessionData = require(sessionPath)
|
||||
console.log("[LastFM][authenticateFromFile] Logging in with Session Info.")
|
||||
app.lastfm.setSessionCredentials(sessionData.name, sessionData.key)
|
||||
console.log("[LastFM][authenticateFromFile] Logged in.")
|
||||
},
|
||||
|
||||
authenticate: function () {
|
||||
if (app.cfg.get('tokens.lastfm')) {
|
||||
app.cfg.set('general.lastfm', true);
|
||||
}
|
||||
|
||||
if (!app.cfg.get('general.lastfm') || !app.cfg.get('tokens.lastfm')) {
|
||||
app.cfg.set('general.lastfm', false);
|
||||
return
|
||||
}
|
||||
|
||||
const lfmAPI = new LastfmAPI({
|
||||
'api_key': apiCredentials.key,
|
||||
'secret': apiCredentials.secret
|
||||
});
|
||||
|
||||
app.lastfm = Object.assign(lfmAPI, {cachedAttributes: false, cachedNowPlayingAttributes: false});
|
||||
|
||||
fs.stat(sessionPath, function (err) {
|
||||
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")
|
||||
app.lastfm.authenticate(app.cfg.get('tokens.lastfm'), function (err, session) {
|
||||
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) => {
|
||||
if (err)
|
||||
console.log("[LastFM][fs]", err)
|
||||
else {
|
||||
console.log("[LastFM][fs] File was written successfully.")
|
||||
lfm.authenticateFromFile()
|
||||
new Notification({
|
||||
title: app.getName(),
|
||||
body: "Successfully logged into LastFM using Authentication Key."
|
||||
}).show()
|
||||
}
|
||||
})
|
||||
});
|
||||
} else {
|
||||
lfm.authenticateFromFile()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
scrobbleSong: async function (attributes) {
|
||||
await new Promise(resolve => setTimeout(resolve, app.cfg.get('general.lastfmScrobbleDelay') * 1000));
|
||||
const currentAttributes = app.media;
|
||||
|
||||
if (!app.lastfm || app.lastfm.cachedAttributes === attributes || app.cfg.get('general.incognitoMode')) {
|
||||
return
|
||||
}
|
||||
|
||||
if (app.lastfm.cachedAttributes) {
|
||||
if (app.lastfm.cachedAttributes.playParams.id === attributes.playParams.id) return;
|
||||
}
|
||||
|
||||
if (currentAttributes.status && currentAttributes === attributes) {
|
||||
if (fs.existsSync(sessionPath)) {
|
||||
// Scrobble playing song.
|
||||
if (attributes.status === true) {
|
||||
app.lastfm.track.scrobble({
|
||||
'artist': lfm.filterArtistName(attributes.artistName),
|
||||
'track': attributes.name,
|
||||
'album': attributes.albumName,
|
||||
'albumArtist': this.filterArtistName(attributes.artistName),
|
||||
'timestamp': new Date().getTime() / 1000
|
||||
}, function (err, scrobbled) {
|
||||
if (err) {
|
||||
return console.error('[LastFM] An error occurred while scrobbling', err);
|
||||
}
|
||||
|
||||
console.verbose('[LastFM] Successfully scrobbled: ', scrobbled);
|
||||
});
|
||||
app.lastfm.cachedAttributes = attributes
|
||||
}
|
||||
} else {
|
||||
this.authenticate();
|
||||
}
|
||||
} else {
|
||||
return console.verbose('[LastFM] Did not add ', attributes.name , '-' , lfm.filterArtistName(attributes.artistName), 'because now playing a other song.');
|
||||
}
|
||||
},
|
||||
|
||||
filterArtistName: function (artist) {
|
||||
if (!app.cfg.get('general.lastfmRemoveFeaturingArtists')) 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);
|
||||
},
|
||||
|
||||
updateNowPlayingSong: function (attributes) {
|
||||
if (!app.lastfm ||app.lastfm.cachedNowPlayingAttributes === attributes || app.cfg.get('general.incognitoMode') || !app.cfg.get('general.lastfmNowPlaying')) {
|
||||
return
|
||||
}
|
||||
|
||||
if (app.lastfm.cachedNowPlayingAttributes) {
|
||||
if (app.lastfm.cachedNowPlayingAttributes.playParams.id === attributes.playParams.id) return;
|
||||
}
|
||||
|
||||
if (fs.existsSync(sessionPath)) {
|
||||
// update Now Playing
|
||||
if (attributes.status === true) {
|
||||
app.lastfm.track.updateNowPlaying({
|
||||
'artist': lfm.filterArtistName(attributes.artistName),
|
||||
'track': attributes.name,
|
||||
'album': attributes.albumName,
|
||||
'albumArtist': this.filterArtistName(attributes.artistName)
|
||||
}, function (err, nowPlaying) {
|
||||
if (err) {
|
||||
return console.error('[LastFM] An error occurred while updating nowPlayingSong', err);
|
||||
}
|
||||
|
||||
console.verbose('[LastFM] Successfully updated nowPlayingSong', nowPlaying);
|
||||
});
|
||||
app.lastfm.cachedNowPlayingAttributes = attributes
|
||||
}
|
||||
|
||||
} else {
|
||||
this.authenticate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = lfm;
|
119
oldshit/resources/functions/media/mpris.js
Normal file
119
oldshit/resources/functions/media/mpris.js
Normal file
|
@ -0,0 +1,119 @@
|
|||
const {app} = require('electron'),
|
||||
Player = require('mpris-service'),
|
||||
{initAnalytics} = require('../utils');
|
||||
initAnalytics();
|
||||
|
||||
// Remember to use playerctl when debugging this.
|
||||
// I'm just putting this here as I keep forgetting the command.
|
||||
|
||||
module.exports = {
|
||||
connect: function () {
|
||||
if (process.platform !== "linux") {
|
||||
app.mpris = {active: false}
|
||||
return;
|
||||
}
|
||||
console.log('[MPRIS][connect] Initializing Connection.')
|
||||
|
||||
try {
|
||||
app.mpris = Player({
|
||||
name: 'AppleMusic',
|
||||
identity: 'Apple Music',
|
||||
supportedUriSchemes: [],
|
||||
supportedMimeTypes: [],
|
||||
supportedInterfaces: ['player']
|
||||
});
|
||||
app.mpris = Object.assign(app.mpris, { active: false, canQuit: true, canControl: true, canPause: true, canPlay: true, canGoNext: true })
|
||||
} catch (err) {
|
||||
app.mpris.active = false
|
||||
console.error(`[MPRIS][connect] ${err}`)
|
||||
return
|
||||
}
|
||||
|
||||
let pos_atr = {durationInMillis: 0};
|
||||
app.mpris.getPosition = function () {
|
||||
const durationInMicro = pos_atr.durationInMillis * 1000;
|
||||
const percentage = parseFloat(0) || 0;
|
||||
return durationInMicro * percentage;
|
||||
}
|
||||
|
||||
app.mpris.active = true
|
||||
|
||||
this.clearActivity()
|
||||
this.stateHandler()
|
||||
},
|
||||
|
||||
stateHandler: function () {
|
||||
app.mpris.on('playpause', async () => {
|
||||
app.win.webContents.executeJavaScript('MusicKitInterop.pausePlay()').catch(err => console.error(err))
|
||||
});
|
||||
|
||||
app.mpris.on('play', async () => {
|
||||
app.win.webContents.executeJavaScript('MusicKitInterop.pausePlay()').catch(err => console.error(err))
|
||||
});
|
||||
|
||||
app.mpris.on('pause', async () => {
|
||||
app.win.webContents.executeJavaScript('MusicKitInterop.pausePlay()').catch(err => console.error(err))
|
||||
});
|
||||
|
||||
app.mpris.on('next', async () => {
|
||||
app.win.webContents.executeJavaScript('MusicKitInterop.nextTrack()').catch(err => console.error(err))
|
||||
});
|
||||
|
||||
app.mpris.on('previous', async () => {
|
||||
app.win.webContents.executeJavaScript('MusicKitInterop.previousTrack()').catch(err => console.error(err))
|
||||
});
|
||||
},
|
||||
|
||||
updateActivity: function (attributes) {
|
||||
if (!app.mpris.active) return;
|
||||
|
||||
console.verbose('[MPRIS][updateActivity] Updating Song Activity.')
|
||||
|
||||
const MetaData = {
|
||||
'mpris:trackid': app.mpris.objectPath(`track/${attributes.playParams.id.replace(/[.]+/g, "")}`),
|
||||
'mpris:length': attributes.durationInMillis * 1000, // In microseconds
|
||||
'mpris:artUrl': (attributes.artwork.url.replace('/{w}x{h}bb', '/512x512bb')).replace('/2000x2000bb', '/35x35bb'),
|
||||
'xesam:title': `${attributes.name}`,
|
||||
'xesam:album': `${attributes.albumName}`,
|
||||
'xesam:artist': [`${attributes.artistName}`,],
|
||||
'xesam:genre': attributes.genreNames
|
||||
}
|
||||
|
||||
if (app.mpris.metadata["mpris:trackid"] === MetaData["mpris:trackid"]) {
|
||||
return
|
||||
}
|
||||
|
||||
app.mpris.metadata = MetaData
|
||||
},
|
||||
|
||||
updateState: function (attributes) {
|
||||
if (!app.mpris.active) return;
|
||||
|
||||
console.verbose('[MPRIS][updateState] Updating Song Playback State.')
|
||||
|
||||
function setPlaybackIfNeeded(status) {
|
||||
if (app.mpris.playbackStatus === status) {
|
||||
return
|
||||
}
|
||||
app.mpris.playbackStatus = status;
|
||||
}
|
||||
|
||||
switch (attributes.status) {
|
||||
case true: // Playing
|
||||
setPlaybackIfNeeded('Playing');
|
||||
break;
|
||||
case false: // Paused
|
||||
setPlaybackIfNeeded('Paused');
|
||||
break;
|
||||
default: // Stopped
|
||||
setPlaybackIfNeeded('Stopped');
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
clearActivity: function () {
|
||||
if (!app.mpris.active) return;
|
||||
app.mpris.metadata = {'mpris:trackid': '/org/mpris/MediaPlayer2/TrackList/NoTrack'}
|
||||
app.mpris.playbackStatus = 'Stopped';
|
||||
},
|
||||
}
|
30
oldshit/resources/functions/splash.js
Normal file
30
oldshit/resources/functions/splash.js
Normal file
|
@ -0,0 +1,30 @@
|
|||
const {
|
||||
BrowserWindow
|
||||
} = require('electron');
|
||||
|
||||
const SplashScreen = {
|
||||
win: null,
|
||||
show: function () {
|
||||
this.win = new BrowserWindow({
|
||||
width: 300,
|
||||
height: 300,
|
||||
resizable: false,
|
||||
show: true,
|
||||
center: true,
|
||||
transparent: true,
|
||||
frame: false,
|
||||
alwaysOnTop: true,
|
||||
// skipTaskbar: true,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
this.win.show()
|
||||
this.win.loadFile('./resources/splash/index.html')
|
||||
this.win.on("closed", () => {
|
||||
this.win = null
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SplashScreen
|
395
oldshit/resources/functions/utils.js
Normal file
395
oldshit/resources/functions/utils.js
Normal file
|
@ -0,0 +1,395 @@
|
|||
const {app, nativeImage, nativeTheme, Notification, dialog} = require("electron"),
|
||||
{existsSync, readFileSync, readdirSync, constants, access, writeFileSync, copyFileSync} = require("fs"),
|
||||
{readdir, mkdir} = require("fs/promises"),
|
||||
{join, resolve} = require("path"),
|
||||
{autoUpdater} = require("electron-updater"),
|
||||
os = require("os"),
|
||||
rimraf = require("rimraf"),
|
||||
chmod = require("chmodr"),
|
||||
clone = require("git-clone/promise"),
|
||||
trayIconDir = (nativeTheme.shouldUseDarkColors ? join(__dirname, `../icons/media/light/`) : join(__dirname, `../icons/media/dark/`)),
|
||||
ElectronSentry = require("@sentry/electron");
|
||||
|
||||
const Utils = {
|
||||
|
||||
/* hexToRgb - Converts hex codes to rgb */
|
||||
hexToRgb: (hex) => {
|
||||
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
||||
return result ? {
|
||||
r: parseInt(result[1], 16),
|
||||
g: parseInt(result[2], 16),
|
||||
b: parseInt(result[3], 16)
|
||||
} : null;
|
||||
},
|
||||
|
||||
/* matchRuleShort - Used for wildcards */
|
||||
matchRuleShort: (str, rule) => {
|
||||
var escapeRegex = (str) => str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
|
||||
return new RegExp("^" + rule.split("*").map(escapeRegex).join(".*") + "$").test(str);
|
||||
},
|
||||
|
||||
/* isVibrancySupported - Checks if the operating system support electron-acrylic-window (Windows 10 or greater) */
|
||||
isVibrancySupported: () => {
|
||||
return (process.platform === 'win32' && parseInt(os.release().split('.')[0]) >= 10)
|
||||
},
|
||||
|
||||
/* isAcrylicSupported - Checks if the operating system supports the acrylic transparency affect (Windows RS3 (Redstone 3) 1709 or Greater) */
|
||||
isAcrylicSupported: () => {
|
||||
return (process.platform === 'win32' && parseInt(os.release().replace(/\./g, "").replace(',', '.')) >= 10016299)
|
||||
},
|
||||
|
||||
/* fetchThemeMeta - Fetches the meta data associated to a theme */
|
||||
fetchThemeMeta: (fileName) => {
|
||||
const filePath = resolve(app.getPath("userData"), "themes", `${fileName}.css`);
|
||||
|
||||
let fileMeta = {
|
||||
name: null,
|
||||
author: null,
|
||||
description: null,
|
||||
transparency: {dark: null, light: null},
|
||||
options: []
|
||||
};
|
||||
|
||||
if (!existsSync(filePath)) return fileMeta;
|
||||
const file = readFileSync(filePath, "utf8");
|
||||
if (!file) return;
|
||||
|
||||
file.split(/\r?\n/).forEach((line) => {
|
||||
if (line.includes("@name")) {
|
||||
fileMeta.name = line.split("@name ")[1].trim();
|
||||
}
|
||||
|
||||
if (line.includes("@author")) {
|
||||
fileMeta.author = line.split("@author ")[1].trim();
|
||||
}
|
||||
|
||||
if (line.includes("@description")) {
|
||||
fileMeta.description = line.split("@description ")[1]
|
||||
}
|
||||
|
||||
if (line.includes("@option")) {
|
||||
var themeOption = line.split("@option ")[1].trim().split("|")
|
||||
fileMeta.options.push({
|
||||
key: themeOption[0],
|
||||
name: themeOption[1],
|
||||
defaultValue: themeOption[2]
|
||||
})
|
||||
}
|
||||
|
||||
if (line.includes("--lightTransparency")) {
|
||||
fileMeta.transparency.light = line.split("--lightTransparency: ")[1].trim().split(' ')[0];
|
||||
}
|
||||
|
||||
if (line.includes("--darkTransparency")) {
|
||||
fileMeta.transparency.dark = line.split("--darkTransparency: ")[1].trim().split(' ')[0];
|
||||
}
|
||||
|
||||
if (fileMeta.transparency.dark && fileMeta.transparency.light) {
|
||||
fileMeta.transparency = nativeTheme.shouldUseDarkColors ? fileMeta.transparency.dark : fileMeta.transparency.light
|
||||
}
|
||||
|
||||
if (!fileMeta.transparency.dark || !fileMeta.transparency.light) {
|
||||
if (line.includes("--transparency")) {
|
||||
fileMeta.transparency = line.split("--transparency: ")[1].split(' ')[0];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (typeof fileMeta.transparency == "object") {
|
||||
if (!fileMeta.transparency.dark || !fileMeta.transparency.light) {
|
||||
fileMeta.transparency = false;
|
||||
}
|
||||
}
|
||||
|
||||
console.verbose(`[fetchThemeMeta] Returning ${JSON.stringify(fileMeta)}`);
|
||||
return fileMeta
|
||||
},
|
||||
|
||||
/* fetchTransparencyOptions - Fetches the transparency options */
|
||||
fetchTransparencyOptions: () => {
|
||||
if (process.platform === "darwin" && (!app.cfg.get('visual.transparencyEffect') || !Utils.isVibrancySupported())) {
|
||||
app.transparency = true;
|
||||
return "fullscreen-ui"
|
||||
} else if (!app.cfg.get('visual.transparencyEffect') || !Utils.isVibrancySupported()) {
|
||||
console.verbose(`[fetchTransparencyOptions] Vibrancy not created. Required options not met. (transparencyEffect: ${app.cfg.get('visual.transparencyEffect')} | isVibrancySupported: ${Utils.isVibrancySupported()})`);
|
||||
app.transparency = false;
|
||||
return false
|
||||
} else if (process.platform === "win32" && app.cfg.get('visual.transparencyEffect') === "mica") {
|
||||
return false
|
||||
}
|
||||
|
||||
console.log('[fetchTransparencyOptions] Fetching Transparency Options')
|
||||
let transparencyOptions = {
|
||||
theme: null,
|
||||
effect: app.cfg.get('visual.transparencyEffect'),
|
||||
debug: app.cfg.get('advanced.verboseLogging'),
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
// Disable on blur for acrylic
|
||||
//------------------------------------------
|
||||
if (app.cfg.get('visual.transparencyEffect') === 'acrylic') {
|
||||
transparencyOptions.disableOnBlur = app.cfg.get('visual.transparencyDisableBlur');
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
// Set the transparency theme
|
||||
//------------------------------------------
|
||||
if (app.cfg.get('visual.transparencyTheme') === 'appearance-based') {
|
||||
if (app.cfg.get('visual.theme') && app.cfg.get('visual.theme') !== "default") {
|
||||
transparencyOptions.theme = Utils.fetchThemeMeta(app.cfg.get('visual.theme')).transparency; /* Fetch the Transparency from the Themes Folder */
|
||||
} else if ((!app.cfg.get('visual.theme') || app.cfg.get('visual.theme') === "default") && app.cfg.get('visual.transparencyEffect') === 'acrylic') {
|
||||
transparencyOptions.theme = (nativeTheme.shouldUseDarkColors ? '#3C3C4307' : '#EBEBF507') /* Default Theme when Using Acrylic */
|
||||
} else { // Fallback
|
||||
transparencyOptions.theme = (nativeTheme.shouldUseDarkColors ? 'dark' : 'light')
|
||||
}
|
||||
} else {
|
||||
transparencyOptions.theme = app.cfg.get('visual.transparencyTheme');
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
// Set the refresh rate
|
||||
//------------------------------------------
|
||||
if (app.cfg.get('visual.transparencyMaximumRefreshRate')) {
|
||||
transparencyOptions.useCustomWindowRefreshMethod = true
|
||||
transparencyOptions.maximumRefreshRate = app.cfg.get('visual.transparencyMaximumRefreshRate')
|
||||
}
|
||||
|
||||
app.transparency = true
|
||||
console.log(`[fetchTransparencyOptions] Returning: ${JSON.stringify(transparencyOptions)}`)
|
||||
return transparencyOptions
|
||||
},
|
||||
|
||||
/* fetchThemesListing - Fetches the themes directory listing (Lists .css files) */
|
||||
fetchThemesListing: () => {
|
||||
if (!existsSync(resolve(app.getPath("userData"), "themes"))) return;
|
||||
|
||||
let themesFileNames = [], themesListing = {};
|
||||
|
||||
|
||||
readdirSync(resolve(app.getPath("userData"), "themes")).forEach((value) => {
|
||||
if (value.split('.').pop() === 'css') {
|
||||
themesFileNames.push(value.split('.').shift())
|
||||
}
|
||||
});
|
||||
|
||||
// Get the Info
|
||||
themesFileNames.forEach((themeFileName) => {
|
||||
const themeData = Utils.fetchThemeMeta(themeFileName);
|
||||
if (themeData && themeData.name && themeData.description && themeData.author) {
|
||||
themesListing[themeFileName] = themeData;
|
||||
}
|
||||
})
|
||||
|
||||
return themesListing
|
||||
},
|
||||
|
||||
/* fetchPluginsListing - Fetches the plugins directory listing (Lists .js files) */
|
||||
fetchPluginsListing: () => {
|
||||
if (!existsSync(resolve(app.getPath("userData"), "plugins"))) return;
|
||||
|
||||
let pluginsFileNames = [], pluginsListing = {};
|
||||
|
||||
|
||||
readdirSync(resolve(app.getPath("userData"), "plugins")).forEach((value) => {
|
||||
if (value.split('.').pop() === 'js') {
|
||||
pluginsFileNames.push(value.split('.').shift())
|
||||
}
|
||||
});
|
||||
|
||||
console.log(pluginsFileNames)
|
||||
|
||||
return pluginsFileNames
|
||||
},
|
||||
|
||||
/* fetchOperatingSystem - Fetches the operating system name */
|
||||
fetchOperatingSystem: () => {
|
||||
if (process.platform === "win32") {
|
||||
const release = parseInt(os.release().replaceAll('.', ''))
|
||||
if (release >= 10022000) {
|
||||
return 'Windows 11'
|
||||
} else if (release < 10022000 && release >= 10010240) {
|
||||
return 'Windows 10'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/* updateThemes - Purges the themes directory and clones a fresh copy of the themes */
|
||||
updateThemes: async () => {
|
||||
if (app.watcher) {
|
||||
app.watcher.close()
|
||||
}
|
||||
|
||||
const tmpDir = join(os.tmpdir(), "ame-themes")
|
||||
const themesDir = join(app.getPath("userData"), "themes")
|
||||
|
||||
if (existsSync(themesDir)) {
|
||||
if (existsSync(tmpDir)) {
|
||||
rimraf(tmpDir, [], async (err) => {
|
||||
if (err) return err
|
||||
await clone('https://github.com/Apple-Music-Electron/Apple-Music-Electron-Themes', tmpDir, [], (err) => console.log(err))
|
||||
})
|
||||
} else {
|
||||
await mkdir(tmpDir, {recursive: true})
|
||||
await clone('https://github.com/Apple-Music-Electron/Apple-Music-Electron-Themes', tmpDir, [], (err) => console.log(err))
|
||||
}
|
||||
|
||||
// Base Line Directory Comparison
|
||||
const updateList = await readdir(tmpDir);
|
||||
const foundChanges = {};
|
||||
|
||||
for (const file of updateList) {
|
||||
if (file.split('.').pop() === 'css' && file !== "Template.css") { // Reduces listing compare down to css files
|
||||
console.verbose(`[compareDirectories] Comparing ${file}`)
|
||||
|
||||
if (!existsSync(join(themesDir, file))) {
|
||||
copyFileSync(join(tmpDir, file), join(themesDir, file))
|
||||
foundChanges[file] = 'added'
|
||||
} else {
|
||||
const updateFile = readFileSync(join(tmpDir, file));
|
||||
const origFile = readFileSync(join(themesDir, file));
|
||||
|
||||
if (origFile.toString() !== updateFile.toString()) {
|
||||
writeFileSync(join(themesDir, file), updateFile)
|
||||
foundChanges[file] = 'updated'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return foundChanges
|
||||
} else {
|
||||
await mkdir(tmpDir, {recursive: true})
|
||||
await clone('https://github.com/Apple-Music-Electron/Apple-Music-Electron-Themes', themesDir, [], (err) => console.log(err))
|
||||
return {'initial': true}
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
|
||||
/* permissionsCheck - Checks of the file can be read and written to, if it cannot be chmod -r is run on the directory */
|
||||
permissionsCheck: (folder, file) => {
|
||||
console.verbose(`[permissionsCheck] Running check on ${join(folder, file)}`)
|
||||
access(join(folder, file), constants.R_OK | constants.W_OK, (err) => {
|
||||
if (err) { // File cannot be read after cloning
|
||||
console.error(`[permissionsCheck][access] ${err}`)
|
||||
chmod(folder, 0o777, (err) => {
|
||||
if (err) {
|
||||
console.error(`[permissionsCheck][chmod] ${err} - Theme set to default to prevent application launch halt.`);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.verbose('[permissionsCheck] Check passed.')
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
/* initAnalytics - Sentry Analytics */
|
||||
initAnalytics: () => {
|
||||
if (app.cfg.get('general.analyticsEnabled') && app.isPackaged) {
|
||||
ElectronSentry.init({dsn: "https://20e1c34b19d54dfcb8231e3ef7975240@o954055.ingest.sentry.io/5903033"});
|
||||
}
|
||||
},
|
||||
|
||||
/* checkForUpdates - Checks for update using electron-updater (Part of electron-builder) */
|
||||
checkForUpdates: (manual) => {
|
||||
if (!app.isPackaged || process.env.NODE_ENV !== 'production') return;
|
||||
|
||||
autoUpdater.logger = require("electron-log");
|
||||
autoUpdater.logger.transports.file.resolvePath = (vars) => {
|
||||
return join(app.getPath('userData'), 'logs', vars.fileName);
|
||||
}
|
||||
autoUpdater.logger.transports.file.level = "info";
|
||||
|
||||
if (app.cfg.get('advanced.autoUpdaterBetaBuilds')) {
|
||||
autoUpdater.allowPrerelease = true
|
||||
autoUpdater.allowDowngrade = false
|
||||
}
|
||||
|
||||
autoUpdater.on('update-not-available', () => {
|
||||
if (manual === true) {
|
||||
let bodyVer = `You are on the latest version. (v${app.getVersion()})`
|
||||
new Notification({title: "Apple Music", body: bodyVer}).show()
|
||||
}
|
||||
})
|
||||
|
||||
autoUpdater.on('download-progress', (progress) => {
|
||||
let convertedProgress = parseFloat(progress);
|
||||
app.win.setProgressBar(convertedProgress)
|
||||
})
|
||||
|
||||
autoUpdater.on("error", function (error) {
|
||||
console.error(`[checkForUpdates] Error ${error}`)
|
||||
});
|
||||
|
||||
autoUpdater.on('update-downloaded', (updateInfo) => {
|
||||
console.warn('[checkForUpdates] New version downloaded. Starting user prompt.');
|
||||
|
||||
dialog.showMessageBox({
|
||||
type: 'info',
|
||||
title: 'Updates Available',
|
||||
message: `Update was found and downloaded, would you like to install the update now?`,
|
||||
details: updateInfo,
|
||||
buttons: ['Sure', 'No']
|
||||
}).then(({response}) => {
|
||||
if (response === 0) {
|
||||
const isSilent = true;
|
||||
const isForceRunAfter = true;
|
||||
autoUpdater.quitAndInstall(isSilent, isForceRunAfter);
|
||||
} else {
|
||||
updater.enabled = true
|
||||
updater = null
|
||||
}
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
autoUpdater.checkForUpdates()
|
||||
.then(r => {
|
||||
console.verbose(`[checkForUpdates] Check for updates completed. Response: ${r}`)
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(`[checkUpdates] An error occurred while checking for updates: ${err}`)
|
||||
})
|
||||
},
|
||||
|
||||
/* Media Controlling Functions (Pause/Play/Skip/Previous) */
|
||||
media: {
|
||||
pausePlay() {
|
||||
console.verbose('[AppleMusic] pausePlay run.')
|
||||
app.win.webContents.executeJavaScript("MusicKitInterop.pausePlay()").catch((err) => console.error(err))
|
||||
},
|
||||
|
||||
nextTrack() {
|
||||
console.verbose('[AppleMusic] nextTrack run.')
|
||||
app.win.webContents.executeJavaScript("MusicKitInterop.nextTrack()").catch((err) => console.error(err))
|
||||
},
|
||||
|
||||
previousTrack() {
|
||||
console.verbose('[AppleMusic] previousTrack run.')
|
||||
app.win.webContents.executeJavaScript("MusicKitInterop.previousTrack()").catch((err) => console.error(err))
|
||||
}
|
||||
},
|
||||
|
||||
/* Media-associated Icons (Used for Thumbar and TouchBar) */
|
||||
icons: {
|
||||
pause: nativeImage.createFromPath(join(trayIconDir, 'pause.png')).resize({width: 32, height: 32}),
|
||||
play: nativeImage.createFromPath(join(trayIconDir, 'play.png')).resize({width: 32, height: 32}),
|
||||
nextTrack: nativeImage.createFromPath(join(trayIconDir, 'next.png')).resize({width: 32, height: 32}),
|
||||
previousTrack: nativeImage.createFromPath(join(trayIconDir, 'previous.png')).resize({width: 32, height: 32}),
|
||||
inactive: {
|
||||
play: nativeImage.createFromPath(join(trayIconDir, 'play-inactive.png')).resize({width: 32, height: 32}),
|
||||
nextTrack: nativeImage.createFromPath(join(trayIconDir, 'next-inactive.png')).resize({
|
||||
width: 32,
|
||||
height: 32
|
||||
}),
|
||||
previousTrack: nativeImage.createFromPath(join(trayIconDir, 'previous-inactive.png')).resize({
|
||||
width: 32,
|
||||
height: 32
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Utils.initAnalytics()
|
||||
module.exports = Utils;
|
407
oldshit/resources/functions/win.js
Normal file
407
oldshit/resources/functions/win.js
Normal file
|
@ -0,0 +1,407 @@
|
|||
const {app, Menu, Notification, TouchBar, BrowserWindow} = require("electron"),
|
||||
{TouchBarButton, TouchBarLabel, TouchBarSpacer} = TouchBar,
|
||||
{join} = require("path"),
|
||||
windowStateKeeper = require("electron-window-state"),
|
||||
{initAnalytics} = require('./utils');
|
||||
initAnalytics();
|
||||
|
||||
module.exports = {
|
||||
|
||||
SetApplicationMenu: () => {
|
||||
if (process.platform !== "darwin") return;
|
||||
|
||||
Menu.setApplicationMenu(Menu.buildFromTemplate([
|
||||
{
|
||||
label: app.getName(),
|
||||
submenu: [
|
||||
{ role: 'about' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'services' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'hide' },
|
||||
{ role: 'hideOthers' },
|
||||
{ role: 'unhide' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'quit' }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'View',
|
||||
submenu: [
|
||||
{ role: 'reload' },
|
||||
{ role: 'forceReload' },
|
||||
{ role: 'toggleDevTools' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'resetZoom' },
|
||||
{ role: 'zoomIn' },
|
||||
{ role: 'zoomOut' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'togglefullscreen' }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Window',
|
||||
role: 'window',
|
||||
submenu: [
|
||||
{ role: 'minimize' },
|
||||
{ role: 'zoom' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'front' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'window' }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Support',
|
||||
role: 'help',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Discord',
|
||||
click() {
|
||||
require("shell").openExternal("https://discord.gg/CezHYdXHEM")
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'GitHub Wiki',
|
||||
click() {
|
||||
require("shell").openExternal("https://github.com/Apple-Music-Electron/Apple-Music-Electron/wiki")
|
||||
}
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{
|
||||
label: 'View License',
|
||||
click() {
|
||||
require("shell").openExternal("https://github.com/Apple-Music-Electron/Apple-Music-Electron/blob/master/LICENSE")
|
||||
}
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{
|
||||
label: 'Toggle Developer Tools',
|
||||
accelerator: 'Option+CommandOrControl+I',
|
||||
click() {
|
||||
app.win.webContents.openDevTools()
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Open Configuration File in Editor',
|
||||
click() {
|
||||
app.cfg.openInEditor()
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
]));
|
||||
},
|
||||
|
||||
SetContextMenu: (visibility) => {
|
||||
|
||||
if (visibility) {
|
||||
app.tray.setContextMenu(Menu.buildFromTemplate([
|
||||
{
|
||||
label: 'Check for Updates',
|
||||
click: function () {
|
||||
app.ame.utils.checkForUpdates(true)
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Minimize to Tray',
|
||||
click: function () {
|
||||
if (typeof app.win.hide === 'function') {
|
||||
app.win.hide();
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Quit',
|
||||
click: function () {
|
||||
app.quit();
|
||||
}
|
||||
}
|
||||
]));
|
||||
} else {
|
||||
app.tray.setContextMenu(Menu.buildFromTemplate([
|
||||
{
|
||||
label: 'Check for Updates',
|
||||
click: function () {
|
||||
app.ame.utils.checkForUpdates(true)
|
||||
}
|
||||
},
|
||||
{
|
||||
label: `Show ${app.getName()}`,
|
||||
click: function () {
|
||||
if (typeof app.win.show === 'function') {
|
||||
app.win.show();
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Quit',
|
||||
click: function () {
|
||||
app.quit();
|
||||
}
|
||||
}
|
||||
]));
|
||||
}
|
||||
return true
|
||||
|
||||
},
|
||||
|
||||
SetTaskList: () => {
|
||||
if (process.platform !== "win32") return;
|
||||
|
||||
app.setUserTasks([
|
||||
{
|
||||
program: process.execPath,
|
||||
arguments: '--force-quit',
|
||||
iconPath: process.execPath,
|
||||
iconIndex: 0,
|
||||
title: `Quit ${app.getName()}`
|
||||
}
|
||||
]);
|
||||
return true
|
||||
},
|
||||
|
||||
SetButtons: () => {
|
||||
|
||||
if (process.platform === 'win32') { // Set the Windows Thumbnail Toolbar Buttons
|
||||
if (app.media.playParams.id !== 'no-id-found') {
|
||||
app.win.setThumbarButtons([
|
||||
{
|
||||
tooltip: 'Previous',
|
||||
icon: app.ame.utils.icons.previousTrack,
|
||||
click() {
|
||||
app.ame.utils.media.previousTrack()
|
||||
}
|
||||
},
|
||||
{
|
||||
tooltip: app.media.status ? 'Pause' : 'Play',
|
||||
icon: app.media.status ? app.ame.utils.icons.pause : app.ame.utils.icons.play,
|
||||
click() {
|
||||
app.ame.utils.media.pausePlay()
|
||||
}
|
||||
},
|
||||
{
|
||||
tooltip: 'Next',
|
||||
icon: app.ame.utils.icons.nextTrack,
|
||||
click() {
|
||||
app.ame.utils.media.nextTrack()
|
||||
}
|
||||
}
|
||||
]);
|
||||
} else {
|
||||
app.win.setThumbarButtons([
|
||||
{
|
||||
tooltip: 'Previous',
|
||||
icon: app.ame.utils.icons.inactive.previousTrack,
|
||||
flags: ["disabled"]
|
||||
},
|
||||
{
|
||||
tooltip: 'Play',
|
||||
icon: app.ame.utils.icons.inactive.play,
|
||||
flags: ["disabled"]
|
||||
},
|
||||
{
|
||||
tooltip: 'Next',
|
||||
icon: app.ame.utils.icons.inactive.nextTrack,
|
||||
flags: ["disabled"]
|
||||
}
|
||||
]);
|
||||
}
|
||||
} else if (process.platform === 'darwin') { // Set the macOS Touchbar
|
||||
if (!app.media || app.media.playParams.id === 'no-id-found') return;
|
||||
|
||||
const nextTrack = new TouchBarButton({
|
||||
icon: app.ame.utils.icons.nextTrack,
|
||||
click: () => {
|
||||
app.ame.utils.media.nextTrack()
|
||||
}
|
||||
})
|
||||
|
||||
const previousTrack = new TouchBarButton({
|
||||
icon: app.ame.utils.icons.previousTrack,
|
||||
click: () => {
|
||||
app.ame.utils.media.previousTrack()
|
||||
}
|
||||
})
|
||||
|
||||
const playPause = new TouchBarButton({
|
||||
icon: app.media.status ? app.ame.utils.icons.pause : app.ame.utils.icons.play,
|
||||
click: () => {
|
||||
app.ame.utils.media.pausePlay()
|
||||
}
|
||||
})
|
||||
|
||||
const trackInfo = new TouchBarLabel({
|
||||
label: app.media.name ? `${app.media.name} by ${app.media.artistName}` : `Nothing is Playing`
|
||||
})
|
||||
|
||||
const touchBar = new TouchBar({
|
||||
items: [
|
||||
previousTrack,
|
||||
playPause,
|
||||
nextTrack,
|
||||
new TouchBarSpacer({size: 'flexible'}),
|
||||
trackInfo,
|
||||
new TouchBarSpacer({size: 'flexible'})
|
||||
]
|
||||
})
|
||||
|
||||
app.win.setTouchBar(touchBar)
|
||||
}
|
||||
},
|
||||
|
||||
SetTrayTooltip: (attributes) => {
|
||||
if (!app.cfg.get('general.trayTooltipSongName')) return;
|
||||
|
||||
console.verbose(`[UpdateTooltip] Updating Tooltip for ${attributes.name} to ${attributes.status}`)
|
||||
|
||||
if (attributes.status === true) {
|
||||
app.tray.setToolTip(`Playing ${attributes.name} by ${attributes.artistName} on ${attributes.albumName}`);
|
||||
} else {
|
||||
app.tray.setToolTip(`Paused ${attributes.name} by ${attributes.artistName} on ${attributes.albumName}`);
|
||||
}
|
||||
},
|
||||
|
||||
CreateNotification: (attributes) => {
|
||||
if (!Notification.isSupported() || !(app.cfg.get('general.playbackNotifications') || app.cfg.get('general.playbackNotifications') === 'minimized')) return;
|
||||
|
||||
if (app.cfg.get('general.playbackNotifications') === "minimized" && !(!app.win.isVisible() || app.win.isMinimized())) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.verbose(`[CreateNotification] Notification Generating | Function Parameters: SongName: ${attributes.name} | Artist: ${attributes.artistName} | Album: ${attributes.albumName}`)
|
||||
|
||||
if (app.ipc.existingNotification) {
|
||||
console.log("[CreateNotification] Existing Notification Found - Removing. ")
|
||||
app.ipc.existingNotification.close()
|
||||
app.ipc.existingNotification = false
|
||||
}
|
||||
|
||||
const NOTIFICATION_OBJECT = {
|
||||
title: attributes.name,
|
||||
body: `${attributes.artistName} - ${attributes.albumName}`,
|
||||
silent: true,
|
||||
icon: join(__dirname, '../icons/icon.png'),
|
||||
actions: [{
|
||||
type: 'button',
|
||||
text: 'Skip'
|
||||
}]
|
||||
}
|
||||
|
||||
app.ipc.existingNotification = new Notification(NOTIFICATION_OBJECT)
|
||||
app.ipc.existingNotification.show()
|
||||
|
||||
|
||||
app.ipc.existingNotification.addListener('action', (_event) => {
|
||||
app.ame.utils.media.nextTrack()
|
||||
});
|
||||
},
|
||||
|
||||
CreateBrowserWindow: () => {
|
||||
console.log('[CreateBrowserWindow] Initializing Browser Window Creation.')
|
||||
// Set default window sizes
|
||||
const mainWindowState = windowStateKeeper({
|
||||
defaultWidth: 1024,
|
||||
defaultHeight: 600
|
||||
});
|
||||
|
||||
const options = {
|
||||
icon: join(__dirname, `../icons/icon.ico`),
|
||||
width: mainWindowState.width,
|
||||
height: mainWindowState.height,
|
||||
x: mainWindowState.x,
|
||||
y: mainWindowState.y,
|
||||
minWidth: (app.cfg.get('visual.streamerMode') ? 400 : 300),
|
||||
minHeight: ((app.cfg.get('visual.frameType') === 'mac' || app.cfg.get('visual.frameType') === 'mac-right') ? (app.cfg.get('visual.streamerMode')? 55 : 300) : (app.cfg.get('visual.streamerMode') ? 115 : 300)),
|
||||
frame: (process.platform !== 'win32' && !(app.cfg.get('visual.frameType') === 'mac' || app.cfg.get('visual.frameType') === 'mac-right')),
|
||||
title: app.getName(),
|
||||
resizable: true,
|
||||
// Enables DRM
|
||||
webPreferences: {
|
||||
plugins: true,
|
||||
preload: join(__dirname, '../js/MusicKitInterop.js'),
|
||||
allowRunningInsecureContent: true,
|
||||
nodeIntegration: false,
|
||||
nodeIntegrationInWorker: false,
|
||||
contextIsolation: false,
|
||||
webSecurity: true,
|
||||
sandbox: true,
|
||||
nativeWindowOpen: true
|
||||
}
|
||||
};
|
||||
|
||||
// Fetch the transparency options
|
||||
const transparencyOptions = app.ame.utils.fetchTransparencyOptions()
|
||||
|
||||
if (process.platform === 'darwin' && !app.cfg.get('visual.frameType')) { // macOS Frame and transparency
|
||||
options.titleBarStyle = 'hidden'
|
||||
options.titleBarOverlay = true
|
||||
options.frame = true
|
||||
options.trafficLightPosition = {x: 20, y: 20}
|
||||
options.transparent = (app.transparency && transparencyOptions)
|
||||
}
|
||||
|
||||
// Create the Browser Window
|
||||
console.log('[CreateBrowserWindow] Creating BrowserWindow.')
|
||||
let win;
|
||||
if (process.platform === "darwin" || process.platform === "linux") {
|
||||
win = new BrowserWindow(options)
|
||||
} else {
|
||||
const {BrowserWindow} = require("electron-acrylic-window");
|
||||
if (app.transparency && transparencyOptions) {
|
||||
console.log('[CreateBrowserWindow] Setting Vibrancy')
|
||||
options.vibrancy = transparencyOptions
|
||||
}
|
||||
win = new BrowserWindow(options)
|
||||
}
|
||||
|
||||
// Set the transparency
|
||||
if (app.transparency && transparencyOptions && process.platform === "darwin") {
|
||||
console.log('[CreateBrowserWindow] Setting Vibrancy')
|
||||
win.setVibrancy(transparencyOptions)
|
||||
}
|
||||
|
||||
// alwaysOnTop
|
||||
if (!app.cfg.get('window.alwaysOnTop')) {
|
||||
win.setAlwaysOnTop(false)
|
||||
} else {
|
||||
win.setAlwaysOnTop(true)
|
||||
}
|
||||
|
||||
win.setMenuBarVisibility(false); // Hide that nasty menu bar
|
||||
if (app.cfg.get('advanced.devToolsOnStartup')) win.webContents.openDevTools({mode: 'detach'}); // Enables Detached DevTools
|
||||
|
||||
// Register listeners on Window to track size and position of the Window.
|
||||
mainWindowState.manage(win);
|
||||
|
||||
// Load the Website
|
||||
app.ame.load.LoadWebsite(win)
|
||||
|
||||
return win
|
||||
},
|
||||
|
||||
HandleBrowserWindow: () => {
|
||||
// Detect if the application has been opened with --minimized
|
||||
if (app.commandLine.hasSwitch('minimized') || process.argv.includes('--minimized')) {
|
||||
console.log("[Apple-Music-Electron] Application opened with '--minimized'");
|
||||
if (typeof app.win.minimize === 'function') {
|
||||
app.win.minimize();
|
||||
}
|
||||
}
|
||||
|
||||
// Detect if the application has been opened with --hidden
|
||||
if (app.commandLine.hasSwitch('hidden') || process.argv.includes('--hidden')) {
|
||||
console.log("[Apple-Music-Electron] Application opened with '--hidden'");
|
||||
if (typeof app.win.hide === 'function') {
|
||||
app.win.hide()
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
removeInsertedCSS: (index) => {
|
||||
if (app.injectedCSS[index]) {
|
||||
app.win.webContents.removeInsertedCSS(app.injectedCSS[index]).then(r => { if (r) { console.error(r); }});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
321
oldshit/resources/functions/wsapi.js
Normal file
321
oldshit/resources/functions/wsapi.js
Normal file
|
@ -0,0 +1,321 @@
|
|||
const ws = require('ws');
|
||||
const http = require('http');
|
||||
const WebSocketServer = ws.Server;
|
||||
const WebSocket = ws.WebSocket;
|
||||
const url = require('url');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const port = process.argv[2] || 9000;
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const getPort = require('get-port');
|
||||
const {
|
||||
ipcMain,
|
||||
app,
|
||||
BrowserWindow
|
||||
} = require('electron');
|
||||
|
||||
const wsapi = {
|
||||
standardResponse: function (status, data, message, type = "generic") {
|
||||
this.status = status;
|
||||
this.message = message;
|
||||
this.data = data;
|
||||
this.type = type;
|
||||
},
|
||||
port: 26369,
|
||||
wss: null,
|
||||
clients: [],
|
||||
createId() {
|
||||
// create random guid
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
||||
var r = Math.random() * 16 | 0,
|
||||
v = c == 'x' ? r : (r & 0x3 | 0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
},
|
||||
async InitWebSockets () {
|
||||
ipcMain.on('wsapi-updatePlaybackState', (event, arg) => {
|
||||
wsapi.updatePlaybackState(arg);
|
||||
})
|
||||
|
||||
ipcMain.on('wsapi-returnQueue', (event, arg) => {
|
||||
wsapi.returnQueue(JSON.parse(arg));
|
||||
});
|
||||
|
||||
ipcMain.on('wsapi-returnSearch', (event, arg) => {
|
||||
wsapi.returnSearch(JSON.parse(arg));
|
||||
});
|
||||
|
||||
ipcMain.on('wsapi-returnSearchLibrary', (event, arg) => {
|
||||
wsapi.returnSearchLibrary(JSON.parse(arg));
|
||||
});
|
||||
|
||||
ipcMain.on('wsapi-returnDynamic', (event, arg, type) => {
|
||||
wsapi.returnDynamic(JSON.parse(arg), type);
|
||||
});
|
||||
|
||||
ipcMain.on('wsapi-returnMusicKitApi', (event, arg, method) => {
|
||||
wsapi.returnMusicKitApi(JSON.parse(arg), method);
|
||||
});
|
||||
|
||||
ipcMain.on('wsapi-returnLyrics', (event, arg) => {
|
||||
wsapi.returnLyrics(JSON.parse(arg));
|
||||
});
|
||||
var safeport = await getPort({port : 26369});
|
||||
wss = new WebSocketServer({
|
||||
port: safeport,
|
||||
perMessageDeflate: {
|
||||
zlibDeflateOptions: {
|
||||
// See zlib defaults.
|
||||
chunkSize: 1024,
|
||||
memLevel: 7,
|
||||
level: 3
|
||||
},
|
||||
zlibInflateOptions: {
|
||||
chunkSize: 10 * 1024
|
||||
},
|
||||
// Other options settable:
|
||||
clientNoContextTakeover: true, // Defaults to negotiated value.
|
||||
serverNoContextTakeover: true, // Defaults to negotiated value.
|
||||
serverMaxWindowBits: 10, // Defaults to negotiated value.
|
||||
// Below options specified as default values.
|
||||
concurrencyLimit: 10, // Limits zlib concurrency for perf.
|
||||
threshold: 1024 // Size (in bytes) below which messages
|
||||
// should not be compressed if context takeover is disabled.
|
||||
}
|
||||
})
|
||||
console.log(`WebSocketServer started on port: ${safeport}`);
|
||||
|
||||
const defaultResponse = new wsapi.standardResponse(0, {}, "OK");
|
||||
|
||||
|
||||
wss.on('connection', function connection(ws) {
|
||||
ws.id = wsapi.createId();
|
||||
console.log(`Client ${ws.id} connected`)
|
||||
wsapi.clients.push(ws);
|
||||
ws.on('message', function incoming(message) {
|
||||
|
||||
});
|
||||
// ws on message
|
||||
ws.on('message', function incoming(message) {
|
||||
let data = JSON.parse(message);
|
||||
let response = new wsapi.standardResponse(0, {}, "OK");;
|
||||
if (data.action) {
|
||||
data.action.toLowerCase();
|
||||
}
|
||||
switch (data.action) {
|
||||
default:
|
||||
response.message = "Action not found";
|
||||
break;
|
||||
case "identify":
|
||||
response.message = "Thanks for identifying!"
|
||||
response.data = {
|
||||
id: ws.id
|
||||
}
|
||||
ws.identity = {
|
||||
name: data.name,
|
||||
author: data.author,
|
||||
description: data.description,
|
||||
version: data.version
|
||||
}
|
||||
break;
|
||||
case "play-next":
|
||||
app.win.webContents.executeJavaScript(`wsapi.playNext(\`${data.type}\`,\`${data.id}\`)`);
|
||||
response.message = "Play Next";
|
||||
break;
|
||||
case "play-later":
|
||||
app.win.webContents.executeJavaScript(`wsapi.playLater(\`${data.type}\`,\`${data.id}\`)`);
|
||||
response.message = "Play Later";
|
||||
break;
|
||||
case "quick-play":
|
||||
app.win.webContents.executeJavaScript(`wsapi.quickPlay(\`${data.term}\`)`);
|
||||
response.message = "Quick Play";
|
||||
break;
|
||||
case "get-lyrics":
|
||||
app.win.webContents.executeJavaScript(`wsapi.getLyrics()`);
|
||||
break;
|
||||
case "shuffle":
|
||||
app.win.webContents.executeJavaScript(`wsapi.toggleShuffle()`);
|
||||
break;
|
||||
case "set-shuffle":
|
||||
if(data.shuffle == true) {
|
||||
app.win.webContents.executeJavaScript(`MusicKit.getInstance().shuffleMode = 1`);
|
||||
}else{
|
||||
app.win.webContents.executeJavaScript(`MusicKit.getInstance().shuffleMode = 0`);
|
||||
}
|
||||
break;
|
||||
case "repeat":
|
||||
app.win.webContents.executeJavaScript(`wsapi.toggleRepeat()`);
|
||||
break;
|
||||
case "seek":
|
||||
app.win.webContents.executeJavaScript(`MusicKit.getInstance().seekToTime(${parseFloat(data.time)})`);
|
||||
response.message = "Seek";
|
||||
break;
|
||||
case "pause":
|
||||
app.win.webContents.executeJavaScript(`MusicKit.getInstance().pause()`);
|
||||
response.message = "Paused";
|
||||
break;
|
||||
case "play":
|
||||
app.win.webContents.executeJavaScript(`MusicKit.getInstance().play()`);
|
||||
response.message = "Playing";
|
||||
break;
|
||||
case "stop":
|
||||
app.win.webContents.executeJavaScript(`MusicKit.getInstance().stop()`);
|
||||
response.message = "Stopped";
|
||||
break;
|
||||
case "volume":
|
||||
app.win.webContents.executeJavaScript(`MusicKit.getInstance().volume = ${parseFloat(data.volume)}`);
|
||||
response.message = "Volume";
|
||||
break;
|
||||
case "mute":
|
||||
app.win.webContents.executeJavaScript(`MusicKit.getInstance().mute()`);
|
||||
response.message = "Muted";
|
||||
break;
|
||||
case "unmute":
|
||||
app.win.webContents.executeJavaScript(`MusicKit.getInstance().unmute()`);
|
||||
response.message = "Unmuted";
|
||||
break;
|
||||
case "next":
|
||||
app.win.webContents.executeJavaScript(`MusicKit.getInstance().skipToNextItem()`);
|
||||
response.message = "Next";
|
||||
break;
|
||||
case "previous":
|
||||
app.win.webContents.executeJavaScript(`MusicKit.getInstance().skipToPreviousItem()`);
|
||||
response.message = "Previous";
|
||||
break;
|
||||
case "musickit-api":
|
||||
app.win.webContents.executeJavaScript(`wsapi.musickitApi(\`${data.method}\`, \`${data.id}\`, ${JSON.stringify(data.params)})`);
|
||||
break;
|
||||
case "musickit-library-api":
|
||||
break;
|
||||
case "set-autoplay":
|
||||
app.win.webContents.executeJavaScript(`wsapi.setAutoplay(${data.autoplay})`);
|
||||
break;
|
||||
case "queue-move":
|
||||
app.win.webContents.executeJavaScript(`wsapi.moveQueueItem(${data.from},${data.to})`);
|
||||
break;
|
||||
case "get-queue":
|
||||
app.win.webContents.executeJavaScript(`wsapi.getQueue()`);
|
||||
break;
|
||||
case "search":
|
||||
if (!data.limit) {
|
||||
data.limit = 10;
|
||||
}
|
||||
app.win.webContents.executeJavaScript(`wsapi.search(\`${data.term}\`, \`${data.limit}\`)`);
|
||||
break;
|
||||
case "library-search":
|
||||
if (!data.limit) {
|
||||
data.limit = 10;
|
||||
}
|
||||
app.win.webContents.executeJavaScript(`wsapi.searchLibrary(\`${data.term}\`, \`${data.limit}\`)`);
|
||||
break;
|
||||
case "show-window":
|
||||
app.win.show()
|
||||
break;
|
||||
case "hide-window":
|
||||
app.win.hide()
|
||||
break;
|
||||
case "play-mediaitem":
|
||||
app.win.webContents.executeJavaScript(`wsapi.playTrackById(${data.id}, \`${data.kind}\`)`);
|
||||
response.message = "Playing track";
|
||||
break;
|
||||
case "get-status":
|
||||
response.data = {
|
||||
isAuthorized: true
|
||||
};
|
||||
response.message = "Status";
|
||||
break;
|
||||
case "get-currentmediaitem":
|
||||
app.win.webContents.executeJavaScript(`wsapi.getPlaybackState()`);
|
||||
break;
|
||||
}
|
||||
ws.send(JSON.stringify(response));
|
||||
});
|
||||
|
||||
ws.on('close', function close() {
|
||||
// remove client from list
|
||||
wsapi.clients.splice(wsapi.clients.indexOf(ws), 1);
|
||||
console.log(`Client ${ws.id} disconnected`);
|
||||
});
|
||||
ws.send(JSON.stringify(defaultResponse));
|
||||
});
|
||||
},
|
||||
sendToClient(id) {
|
||||
// replace the clients.forEach with a filter to find the client that requested
|
||||
},
|
||||
win: null,
|
||||
inAppUI() {
|
||||
// create a browserwindow and load "localhost:8090"
|
||||
this.win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
});
|
||||
this.win.loadURL(`http://localhost:${this.webRemotePort}`);
|
||||
this.win.show()
|
||||
this.win.on('closed', () => {
|
||||
this.win = null;
|
||||
});
|
||||
},
|
||||
updatePlaybackState(attr) {
|
||||
const response = new wsapi.standardResponse(0, attr, "OK", "playbackStateUpdate");
|
||||
wsapi.clients.forEach(function each(client) {
|
||||
client.send(JSON.stringify(response));
|
||||
});
|
||||
},
|
||||
returnMusicKitApi(results, method) {
|
||||
const response = new wsapi.standardResponse(0, results, "OK", `musickitapi.${method}`);
|
||||
wsapi.clients.forEach(function each(client) {
|
||||
client.send(JSON.stringify(response));
|
||||
});
|
||||
},
|
||||
returnDynamic(results, type) {
|
||||
const response = new wsapi.standardResponse(0, results, "OK", type);
|
||||
wsapi.clients.forEach(function each(client) {
|
||||
client.send(JSON.stringify(response));
|
||||
});
|
||||
},
|
||||
returnLyrics(results) {
|
||||
const response = new wsapi.standardResponse(0, results, "OK", "lyrics");
|
||||
wsapi.clients.forEach(function each(client) {
|
||||
client.send(JSON.stringify(response));
|
||||
});
|
||||
},
|
||||
returnSearch(results) {
|
||||
const response = new wsapi.standardResponse(0, results, "OK", "searchResults");
|
||||
wsapi.clients.forEach(function each(client) {
|
||||
client.send(JSON.stringify(response));
|
||||
});
|
||||
},
|
||||
returnSearchLibrary(results) {
|
||||
const response = new wsapi.standardResponse(0, results, "OK", "searchResultsLibrary");
|
||||
wsapi.clients.forEach(function each(client) {
|
||||
client.send(JSON.stringify(response));
|
||||
});
|
||||
},
|
||||
returnQueue(queue) {
|
||||
const response = new wsapi.standardResponse(0, queue, "OK", "queue");
|
||||
wsapi.clients.forEach(function each(client) {
|
||||
client.send(JSON.stringify(response));
|
||||
});
|
||||
},
|
||||
webRemotePort: 8090,
|
||||
async InitWebServer() {
|
||||
const webRemotePort = await getPort({port : wsapi.webRemotePort});
|
||||
// Web Remote
|
||||
// express server that will serve static files in the "../web-remote" folder
|
||||
const webapp = express();
|
||||
const webRemotePath = path.join(__dirname, '../web-remote');
|
||||
webapp.use(express.static(webRemotePath));
|
||||
webapp.get('/', function (req, res) {
|
||||
res.sendFile(path.join(webRemotePath, 'index.html'));
|
||||
});
|
||||
webapp.listen(webRemotePort, function () {
|
||||
console.log(`Web Remote listening on port ${webRemotePort}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = wsapi
|
Loading…
Add table
Add a link
Reference in a new issue