275 lines
7.4 KiB
JavaScript
275 lines
7.4 KiB
JavaScript
const { app, BrowserWindow, ipcMain } = require('electron')
|
|
const {clipboard} = require('electron')
|
|
|
|
const path = require('path')
|
|
const URL = require('url').URL
|
|
|
|
'use strict';
|
|
|
|
let mainWindow
|
|
let logWindow
|
|
|
|
let devMode = false
|
|
let selfMute = false
|
|
let isConnected = false
|
|
let webViewSession = null
|
|
let configObj
|
|
let micPermissionGranted = false
|
|
|
|
// Set Dev mode
|
|
if (process.argv.length === 3) {
|
|
if (process.argv[2] === 'dev'){
|
|
devMode = true
|
|
}
|
|
}
|
|
|
|
function createMainWindow () {
|
|
// Create the browser window.
|
|
mainWindow = new BrowserWindow({
|
|
width: 1230,
|
|
height: 800,
|
|
webPreferences: {
|
|
preload: path.join(__dirname, 'src/mainLoad.js'),
|
|
partition: 'persist:discord',
|
|
nodeIntegration: false, // https://electronjs.org/docs/tutorial/security#2-do-not-enable-nodejs-integration-for-remote-content
|
|
enableRemoteModule: false, // https://electronjs.org/docs/tutorial/security#15-disable-the-remote-module
|
|
webviewTag: true,
|
|
sandbox: true,
|
|
nodeIntegrationInSubFrames: false,
|
|
webSecurity: true,
|
|
allowRunningInsecureContent: false,
|
|
plugins: false,
|
|
experimentalFeatures: false
|
|
},
|
|
frame: false
|
|
})
|
|
|
|
mainWindow.loadFile('./views/index.html')
|
|
|
|
mainWindow.setTitle("Discord Sandboxed")
|
|
|
|
mainWindow.on('closed', function () {
|
|
mainWindow = null
|
|
})
|
|
}
|
|
|
|
function createLogWindow() {
|
|
logWindow = new BrowserWindow({
|
|
width: 700,
|
|
height: 400,
|
|
resizable: false,
|
|
webPreferences: {
|
|
preload: path.join(__dirname, 'src/logLoad.js'),
|
|
nodeIntegration: false, // https://electronjs.org/docs/tutorial/security#2-do-not-enable-nodejs-integration-for-remote-content
|
|
enableRemoteModule: false, // https://electronjs.org/docs/tutorial/security#15-disable-the-remote-module
|
|
webviewTag: true,
|
|
sandbox: true,
|
|
nodeIntegrationInSubFrames: false,
|
|
webSecurity: true,
|
|
allowRunningInsecureContent: false,
|
|
plugins: false,
|
|
experimentalFeatures: false
|
|
},
|
|
frame: false
|
|
})
|
|
|
|
logWindow.loadFile('./views/log.html')
|
|
logWindow.setTitle("Logs")
|
|
logWindow.on('closed', function () {
|
|
logWindow = null
|
|
})
|
|
}
|
|
|
|
|
|
function maximizeMinimizeState(windowName){
|
|
if (windowName.isMaximized()) {
|
|
windowName.unmaximize()
|
|
} else {
|
|
windowName.maximize()
|
|
}
|
|
}
|
|
|
|
function listenForKeySignal() {
|
|
console.log('listening for key signals...');
|
|
// Listen for process signal
|
|
// SIGUSR2 - Toggle muted
|
|
process.on('SIGUSR2', () => {
|
|
mainWindow.webContents.send('micToggle', 'mic-toggled');
|
|
});
|
|
}
|
|
|
|
app.on('ready', createMainWindow)
|
|
|
|
// Quit when all windows are closed.
|
|
app.on('window-all-closed', function () {
|
|
if (process.platform !== 'darwin') app.quit()
|
|
})
|
|
|
|
app.on('activate', function () {
|
|
if (mainWindow === null) createMainWindow()
|
|
})
|
|
|
|
// Force single instance
|
|
let isSingleInstance = app.requestSingleInstanceLock()
|
|
if (!isSingleInstance) {
|
|
app.quit()
|
|
}
|
|
// Force focus on single instance
|
|
app.on('second-instance', (event, argv, cwd) => {
|
|
if (mainWindow) {
|
|
if (mainWindow.isMinimized()) mainWindow.restore()
|
|
mainWindow.focus()
|
|
}
|
|
|
|
if (logWindow) {
|
|
if (logWindow.isMinimized()) mainWindow.restore()
|
|
logWindow.focus()
|
|
}
|
|
})
|
|
|
|
/* Security Stuff */
|
|
|
|
app.on('web-contents-created', (event, contents) => { // https://electronjs.org/docs/tutorial/security#11-verify-webview-options-before-creation
|
|
contents.on('will-attach-webview', (event, webPreferences, params) => {
|
|
// Strip away preload scripts if unused or verify their location is legitimate
|
|
delete webPreferences.preload
|
|
delete webPreferences.preloadURL
|
|
|
|
// Disable Node.js integration
|
|
webPreferences.nodeIntegration = false
|
|
console.log(`web-contents-created: ${params.src}`)
|
|
// Verify discord.com is being loaded
|
|
if (!params.src.startsWith('https://discord.com/')) {
|
|
event.preventDefault()
|
|
}
|
|
})
|
|
})
|
|
|
|
app.on('web-contents-created', (event, contents) => { // https://electronjs.org/docs/tutorial/security#12-disable-or-limit-navigation
|
|
contents.on('will-navigate', (event, navigationUrl) => { // https://electronjs.org/docs/tutorial/security#13-disable-or-limit-creation-of-new-windows
|
|
const parsedUrl = new URL(navigationUrl)
|
|
console.log(`will-navigate ${navigationUrl}`)
|
|
if (parsedUrl.origin !== 'https://discord.com/') { // Limit navigation to discordapp.com; not really relevant
|
|
event.preventDefault()
|
|
}
|
|
})
|
|
|
|
contents.on('new-window', async (event, navigationUrl) => {
|
|
clipboard.writeText(navigationUrl, 'selection') // I really hope this is safe to do. Could also do a little URL cleaning here to remove trackers
|
|
console.log(`URL ${navigationUrl.toString().slice(0, 20)} Copied to Clipboard`)
|
|
mainWindow.webContents.send('URLCopied', null)
|
|
//event.preventDefault() // Prevents external links from opening
|
|
})
|
|
})
|
|
|
|
/* ---- */
|
|
|
|
|
|
app.on ('browser-window-blur', function (event, browserWindow) {
|
|
browserWindow.webContents.send('unfocused', null)
|
|
})
|
|
|
|
app.on ('browser-window-focus', function (event, browserWindow) {
|
|
browserWindow.webContents.send('focused', null)
|
|
})
|
|
|
|
app.on('ready', () => {
|
|
// Handle permission requests
|
|
webViewSession = mainWindow.webContents.session
|
|
|
|
webViewSession.setPermissionRequestHandler((webContents, permission, callback) => { // deny all permissions
|
|
const url = webContents.getURL()
|
|
if (url.startsWith('https://discord.com/')) {
|
|
if (permission === 'media' && isConnected === true) { // if user is connected to Discord voice then enable microphone
|
|
console.log("User connected to Discord VOIP server. Granted permission for microphone")
|
|
micPermissionGranted = true
|
|
return callback(true)
|
|
}
|
|
}
|
|
console.log("Denied permission: ", permission)
|
|
return callback(false)
|
|
})
|
|
})
|
|
|
|
ipcMain.on('asynchronous-message', (event, _data) => {
|
|
let msg = _data.msg
|
|
if (msg === 'connected') {
|
|
console.log("User connected to Discord VOIP server")
|
|
if (micPermissionGranted === false && selfMute === false){
|
|
micPermissionGranted = true
|
|
}
|
|
isConnected = true
|
|
}
|
|
|
|
if (msg === 'disconnected') {
|
|
console.log("User disconnected to Discord VOIP server")
|
|
isConnected = false
|
|
}
|
|
|
|
if (msg === 'self-muted') {
|
|
console.log("User self-muted")
|
|
webViewSession.setPermissionRequestHandler(null)
|
|
selfMute = true
|
|
}
|
|
|
|
if (msg === 'self-unmuted') {
|
|
console.log("User self-unmuted")
|
|
selfMute = false
|
|
}
|
|
|
|
if (msg === 'DOMready') {
|
|
console.log("Discord webview loaded")
|
|
mainWindow.webContents.send('devMode', devMode)
|
|
}
|
|
|
|
if (msg === 'blockUpdate') {
|
|
if (logWindow){
|
|
logWindow.webContents.send('blockUpdate', _data.data)
|
|
}
|
|
}
|
|
|
|
if (msg === 'minimizeApplication') {
|
|
if (_data.data.wName === 0) {
|
|
mainWindow.minimize()
|
|
}
|
|
if (_data.data.wName === 1) {
|
|
logWindow.minimize()
|
|
}
|
|
}
|
|
|
|
if (msg === 'maximizeApplication') {
|
|
if (_data.data.wName === 0) {
|
|
maximizeMinimizeState(mainWindow)
|
|
}
|
|
if (_data.data.wName === 1) {
|
|
maximizeMinimizeState(logWindow)
|
|
}
|
|
}
|
|
|
|
if (msg === 'closeApplication') {
|
|
if (_data.data.wName === 0) {
|
|
app.quit()
|
|
}
|
|
if (_data.data.wName === 1) {
|
|
logWindow.close()
|
|
}
|
|
}
|
|
|
|
if (msg === 'openLog') {
|
|
if (logWindow) {
|
|
if (logWindow.isMinimized()) logWindow.restore()
|
|
logWindow.focus()
|
|
}else {
|
|
createLogWindow()
|
|
logWindow.center()
|
|
}
|
|
}
|
|
})
|
|
|
|
app.on('ready', event => {
|
|
console.log(`Dev Mode: ${devMode}`)
|
|
|
|
listenForKeySignal();
|
|
})
|
|
|