Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
1363657a12 | ||
|
07112ebbb6 | ||
|
e52355f42b | ||
|
5869acade3 | ||
|
773aebda93 | ||
|
0f081bbce5 | ||
|
4a440c9dd6 | ||
|
4401b6ad73 | ||
|
a069a2e434 | ||
|
57b8f4fdb5 | ||
|
e0e2c6ba26 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
node_modules
|
node_modules
|
||||||
release
|
release
|
||||||
|
dist
|
||||||
debug.log
|
debug.log
|
66
README.md
66
README.md
@ -1,47 +1,53 @@
|
|||||||
|
Modified by Michael Peters
|
||||||
|
|
||||||
|
Primary changes:
|
||||||
|
- Make it work again in 2022
|
||||||
|
- Use SIGUSR2 to toggle mute
|
||||||
|
- Removes dependency on key tracking library
|
||||||
|
- Improve UI to be more similar to discord
|
||||||
|
- Improve logger UI / font
|
||||||
|
|
||||||
# Discord-Sandbox <a href="https://github.com/khlam/discord-sandboxed/releases/latest"><img src="https://img.shields.io/badge/download-latest-green.svg"></a>
|
# Discord-Sandbox <a href="https://github.com/khlam/discord-sandboxed/releases/latest"><img src="https://img.shields.io/badge/download-latest-green.svg"></a>
|
||||||
|
|
||||||
> Open-source Sandbox Discord client for the privacy-minded. Say NO to intrusive data collection.
|
> Open-source Sandbox Discord client
|
||||||
|
> Because asking for privacy will get you nowhere.
|
||||||
|
|
||||||
Are you worried Discord is watching what programs you have open or listening to your mic even while you're not pressing your push-to-talk key?
|
Are you worried Discord is watching what programs you have open or listening to your mic even while you're not pressing your push-to-talk key?
|
||||||
Discord-Sandbox isolates the Discord client from reading background processes by running the [Discord web client](https://discord.com/) inside of a [\<webview>](https://developer.chrome.com/apps/tags/webview), which is finally contained inside the Electron process. While I cannot guarantee this client protects you from anything, I have tried my best to remove Discord's data collection.
|
Discord-Sandbox isolates the Discord client from reading background processes by running the [Discord web client](https://discord.com/) inside of a [\<webview>](https://developer.chrome.com/apps/tags/webview), which is finally contained inside the Electron process. While I cannot guarantee this client protects you from anything, I have tried my best to remove Discord's data collection.
|
||||||
|
|
||||||
|
Note that since this client is running the Discord web client, the following features will (unfortunately) NOT be available.
|
||||||
Note that since this client is running the Discord web client, the following features will NOT be available.
|
|
||||||
|
|
||||||
- Viewing Streams or Streaming your desktop
|
- Viewing Streams or Streaming your desktop
|
||||||
- Discord's "High Quality Audio" or whatever
|
- Discord's "High Quality Audio" or whatever
|
||||||
|
|
||||||
|
## Toggle Mute
|
||||||
|
|
||||||
## Push to Talk
|
Push-to-Talk is configured using the SIGUSR2. Send a SIGUSR2 to the electron process to trigger a click on the mute button.
|
||||||
1. To enable push-to-talk, open Discord-Sandbox, set your push-to-talk key to `Backspace`, and lower the `Push to Talk Release Delay` slider all the way to 0 as shown.
|
You can send this signal in the terminal with pkill
|
||||||
<p align="center">
|
`pkill -SIGUSR2 --oldest electron`
|
||||||
<img src="./docs/img/PTTSettings.PNG" />
|
|
||||||
</p>
|
|
||||||
|
|
||||||
2. Click on the gear icon in the top left corner. Check the box to enable system-wide push to talk. Set your push to talk key by clicking in the black box and pressing the desired key (Default PTT key is mouse button 4). Configuration settings are stored in `/Documents/DiscordSandbox/config.json`.
|
|
||||||
<p align="center">
|
|
||||||
<img src="./docs/img/PTT.PNG" />
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
> Note: Make sure to use --oldest. Otherwise, the electron GPU processes will get angry and quit passive-agressively:
|
||||||
|
> [130264:0223/232600.871793:FATAL:gpu\_data\_manager\_impl\_private.cc(448)] GPU process isn't usable. Goodbye.
|
||||||
|
> /home/michael/builds/discord-sandboxed/node_modules/electron/dist/electron exited with signal SIGTRAP
|
||||||
|
|
||||||
## Telemetry Mitigations
|
## Telemetry Mitigations
|
||||||
As detailed from [Luna Mendes' discord-unofficial-docs]("https://luna.gitlab.io/discord-unofficial-docs/"), Discord sends telemetry data over the `/api/science` endpoint. This project does its best to disable this telemetry communication by running javascript code into the webview that adds a blacklist/whitelist to the default `XMLHttpRequest` behavior. In this way, we explicitly block all communication with the `science` address, while simultaneously whitelisting addresses needed for minimum Discord functionality. See the full code in [mainRender.js]("./views/js/mainRender.js").
|
|
||||||
|
|
||||||
|
As detailed from [Luna Mendes' discord-unofficial-docs]("https://luna.gitlab.io/discord-unofficial-docs/"), Discord sends telemetry data over the `/api/science` endpoint. This project does its best to disable this telemetry communication by running javascript code into the webview that adds a blacklist/whitelist to the default `XMLHttpRequest` behavior. In this way, we explicitly block all communication with the `science` address, while simultaneously whitelisting addresses needed for minimum Discord functionality. See the full code in [mainRender.js]("./views/js/mainRender.js").
|
||||||
|
|
||||||
Discord likely does other sneaky things to spy on us. If you have any ideas on improving this project's security/privacy please let me know by opening an issue!
|
Discord likely does other sneaky things to spy on us. If you have any ideas on improving this project's security/privacy please let me know by opening an issue!
|
||||||
|
|
||||||
|
Clicking on the Logs icon in the client will open the Log window, which will detail when a communication by the client is blocked.
|
||||||
|
|
||||||
Clicking on the Logs icon to the right of the settings button in the client will open the Log window, which will detail when a communication by the client is blocked.
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="./docs/img/logs.PNG" />
|
<img src="./docs/img/logs.PNG" />
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
## What this Client Tries to Do
|
## What this Client Tries to Do
|
||||||
|
|
||||||
Discord-Sandbox tries to isolate the Discord client within the Electron process, preventing it from watching keystrokes or processes it has no business in.
|
Discord-Sandbox tries to isolate the Discord client within the Electron process, preventing it from watching keystrokes or processes it has no business in.
|
||||||
|
|
||||||
|
|
||||||
## What this Client Cannot Do
|
## What this Client Cannot Do
|
||||||
|
|
||||||
Discord's desktop application has the capabilities to collect a lot of user-behavior information.
|
Discord's desktop application has the capabilities to collect a lot of user-behavior information.
|
||||||
This project seeks to isolate your keystrokes and background processes from Discord.
|
This project seeks to isolate your keystrokes and background processes from Discord.
|
||||||
Discord can still collect the following information. Since these are inherent to the service, we can't do much about it.
|
Discord can still collect the following information. Since these are inherent to the service, we can't do much about it.
|
||||||
@ -49,25 +55,35 @@ Discord can still collect the following information. Since these are inherent to
|
|||||||
- Messages, client data, emails, and voice data
|
- Messages, client data, emails, and voice data
|
||||||
- Links you have clicked/opened from within the client (Passing links to a browser has been disabled to somewhat mitigate this)
|
- Links you have clicked/opened from within the client (Passing links to a browser has been disabled to somewhat mitigate this)
|
||||||
|
|
||||||
|
|
||||||
### How does Push-to-Talk Work?
|
### How does Push-to-Talk Work?
|
||||||
|
|
||||||
The [Discord web client](https://discord.com/) lacks push-to-talk detection while the browser session does not have window focus. This project works enables system-wide push-to-talk while respecting your privacyby using a separate key-press detection library, [iohook](https://www.npmjs.com/package/iohook), and mediating its interaction with Discord.
|
The [Discord web client](https://discord.com/) lacks push-to-talk detection while the browser session does not have window focus. This project works enables system-wide push-to-talk while respecting your privacyby using a separate key-press detection library, [iohook](https://www.npmjs.com/package/iohook), and mediating its interaction with Discord.
|
||||||
This separates your activity from Discord without compromising usability.
|
This separates your activity from Discord without compromising usability.
|
||||||
|
|
||||||
When your push-to-talk key is held down, the renderer process will send a `backspace` key-down keycode to the [\<webview>](https://developer.chrome.com/apps/tags/webview). This opens your microphone without giving the client window focus, so you can use Discord without worrying about the client listening in on whatever else you're running.
|
When your push-to-talk key is held down, the renderer process will send a `backspace` key-down keycode to the [\<webview>](https://developer.chrome.com/apps/tags/webview). This opens your microphone without giving the client window focus, so you can use Discord without worrying about the client listening in on whatever else you're running.
|
||||||
|
|
||||||
|
# Installation (for Linux)
|
||||||
|
|
||||||
|
## Prereqs
|
||||||
|
|
||||||
|
- Make sure you've installed libxkbcommon-x11 `pacman -S libxkbcommon-x11`
|
||||||
|
|
||||||
## Building From Source
|
## Building From Source
|
||||||
0. If you're using Windows 10, make sure you have the [latest C++ Redistributable for Visual Studio 2015, 2017, and 2019](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads)
|
|
||||||
1. Install [Node (https://nodejs.org/en/download/)](https://nodejs.org/en/download/)
|
1. Install [Node (https://nodejs.org/en/download/)](https://nodejs.org/en/download/)
|
||||||
2. Clone Repo `git clone https://github.com/khlam/discord-sandboxed.git`
|
2. Clone Repo `git clone https://github.com/khlam/discord-sandboxed.git`
|
||||||
3. Install dependencies `npm i && npm i -d`
|
3. Install dependencies `npm i && npm i -d`
|
||||||
4. Run `npm start`
|
4. To test it out, run `npm start`
|
||||||
5. (Optional) Create Windows installer `npm run package-win`
|
|
||||||
|
|
||||||
|
## Packaging and Installing on Arch Linux (pacman)
|
||||||
|
|
||||||
|
1. `yay -S libxcrypt-compat` Currently, electron-builder's ruby depends on an old version of libxcrypt so you might need to install the libxcrypt-compat library (especially if you're on a pretty minimal system)
|
||||||
|
2. `npm run package-pacman` Create the pacman package with electron-builder
|
||||||
|
3. `./dist/linux-unpacked/discord-sandbox` Test the unpacked version
|
||||||
|
4. `pacman -U ./dist/discord-sandbox-x.x.x.pacman` Install with pacman
|
||||||
|
|
||||||
> This Discord-Sandbox open source project is not affiliated with Discord or Discord Inc.
|
> This Discord-Sandbox open source project is not affiliated with Discord or Discord Inc.
|
||||||
I do not claim to have created Discord.
|
> I do not claim to have created Discord.
|
||||||
Discord-Sandbox is not the official Discord client.
|
> Discord-Sandbox is not the official Discord client.
|
||||||
Discord is a freeware VoIP application made by Discord Inc.
|
> Discord is a freeware VoIP application made by Discord Inc.
|
||||||
You can download the official Discord client [Here](https://discord.com/).
|
> You can download the official Discord client [Here](https://discord.com/).
|
||||||
|
277
main.js
277
main.js
@ -4,37 +4,13 @@ const {clipboard} = require('electron')
|
|||||||
const path = require('path')
|
const path = require('path')
|
||||||
const URL = require('url').URL
|
const URL = require('url').URL
|
||||||
|
|
||||||
const { initConfig, saveConfig } = require('./src/config')
|
|
||||||
|
|
||||||
let ioHook = null
|
|
||||||
|
|
||||||
try {
|
|
||||||
ioHook = require('iohook')
|
|
||||||
} catch(e) {
|
|
||||||
console.log(e)
|
|
||||||
ioHook = false
|
|
||||||
}
|
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let mainWindow
|
let mainWindow
|
||||||
let logWindow
|
let logWindow
|
||||||
let settingsWindow
|
|
||||||
|
|
||||||
let devMode = false
|
let devMode = false
|
||||||
let selfMute = false
|
|
||||||
let isConnected = false
|
|
||||||
let webViewSession = null
|
let webViewSession = null
|
||||||
let isTalking = false
|
|
||||||
let muteTimeout = null
|
|
||||||
let configObj
|
|
||||||
let micPermissionGranted = false
|
|
||||||
|
|
||||||
let isChangingPTTKey = false
|
|
||||||
|
|
||||||
let pttEnable = 'mousedown' // init to mousedown/up
|
|
||||||
let pttDisable = 'mouseup'
|
|
||||||
let pttWatch = 'button'
|
|
||||||
|
|
||||||
// Set Dev mode
|
// Set Dev mode
|
||||||
if (process.argv.length === 3) {
|
if (process.argv.length === 3) {
|
||||||
@ -43,21 +19,6 @@ if (process.argv.length === 3) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function unmuteMic() {
|
|
||||||
if ( selfMute === false){
|
|
||||||
isTalking = true
|
|
||||||
console.log("Talking")
|
|
||||||
mainWindow.webContents.send('micOpen', 'mic-open')
|
|
||||||
mainWindow.setTitle("MIC OPEN")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function muteMic() {
|
|
||||||
console.log("Not Talking")
|
|
||||||
mainWindow.webContents.send('micClose', 'mic-closed')
|
|
||||||
mainWindow.setTitle("MIC CLOSED")
|
|
||||||
}
|
|
||||||
|
|
||||||
function createMainWindow () {
|
function createMainWindow () {
|
||||||
// Create the browser window.
|
// Create the browser window.
|
||||||
mainWindow = new BrowserWindow({
|
mainWindow = new BrowserWindow({
|
||||||
@ -115,28 +76,6 @@ function createLogWindow() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function createSettingsWindow() {
|
|
||||||
settingsWindow = new BrowserWindow({
|
|
||||||
width: 700,
|
|
||||||
height: 400,
|
|
||||||
show: true,
|
|
||||||
resizable: false,
|
|
||||||
alwaysOnTop:true,
|
|
||||||
webPreferences: {
|
|
||||||
preload: path.join(__dirname, 'src/settingsLoad.js'),
|
|
||||||
nodeIntegration: false,
|
|
||||||
enableRemoteModule: false,
|
|
||||||
},
|
|
||||||
frame: false
|
|
||||||
})
|
|
||||||
|
|
||||||
settingsWindow.loadFile('./views/settings.html')
|
|
||||||
settingsWindow.setTitle("Settings")
|
|
||||||
settingsWindow.on('closed', function () {
|
|
||||||
isChangingPTTKey = false
|
|
||||||
settingsWindow = null
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function maximizeMinimizeState(windowName){
|
function maximizeMinimizeState(windowName){
|
||||||
if (windowName.isMaximized()) {
|
if (windowName.isMaximized()) {
|
||||||
@ -146,66 +85,13 @@ function maximizeMinimizeState(windowName){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function restartioHook() {
|
function listenForKeySignal() {
|
||||||
if (ioHook) {
|
console.log('listening for key signals...');
|
||||||
console.log("restarting io Hook")
|
// Listen for process signal
|
||||||
return new Promise((resolve, reject) => {
|
// SIGUSR2 - Toggle muted
|
||||||
return new Promise((resolve, reject) => {
|
process.on('SIGUSR2', () => {
|
||||||
ioHook.removeAllListeners('mousedown', () => {})
|
mainWindow.webContents.send('micToggle', 'mic-toggled');
|
||||||
ioHook.removeAllListeners('mouseup', () => {})
|
});
|
||||||
ioHook.removeAllListeners('keydown', () => {})
|
|
||||||
ioHook.removeAllListeners('keyup', () => {})
|
|
||||||
ioHook.unload()
|
|
||||||
console.log("ioHook stopped")
|
|
||||||
return resolve(true)
|
|
||||||
}).then (v => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
ioHook.load()
|
|
||||||
console.log("ioHook started")
|
|
||||||
return resolve(true)
|
|
||||||
}).then(v => {
|
|
||||||
ioHook.start()
|
|
||||||
return resolve(true)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setPTTKey() {
|
|
||||||
if (ioHook && configObj.pttDevice && configObj.pttDevice) {
|
|
||||||
console.log("Set PTT Key")
|
|
||||||
if (configObj.pttDevice === 'mouse'){
|
|
||||||
pttEnable = 'mousedown'
|
|
||||||
pttDisable = 'mouseup'
|
|
||||||
pttWatch = 'button'
|
|
||||||
}else if (configObj.pttDevice === 'keyboard'){
|
|
||||||
pttEnable = 'keydown'
|
|
||||||
pttDisable = 'keyup'
|
|
||||||
pttWatch = 'keycode'
|
|
||||||
}else {
|
|
||||||
console.log("ERROR: configObj did not set PTT device to mouse or keyboard.")
|
|
||||||
}
|
|
||||||
|
|
||||||
ioHook.on(pttEnable, event => {
|
|
||||||
if (event[pttWatch] == configObj.key && (micPermissionGranted === true) && (isConnected === true) && (isChangingPTTKey === false)) {
|
|
||||||
clearTimeout(muteTimeout)
|
|
||||||
unmuteMic()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
ioHook.on(pttDisable, event => {
|
|
||||||
if (event[pttWatch] == configObj.key) {
|
|
||||||
if (isTalking === true) {
|
|
||||||
isTalking = false
|
|
||||||
muteTimeout = setTimeout(() => muteMic(), configObj.delay)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
}else {
|
|
||||||
console.log("Not listening for keypresses. ioHook library error or PTT keys not set.")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
app.on('ready', createMainWindow)
|
app.on('ready', createMainWindow)
|
||||||
@ -290,9 +176,8 @@ app.on('ready', () => {
|
|||||||
webViewSession.setPermissionRequestHandler((webContents, permission, callback) => { // deny all permissions
|
webViewSession.setPermissionRequestHandler((webContents, permission, callback) => { // deny all permissions
|
||||||
const url = webContents.getURL()
|
const url = webContents.getURL()
|
||||||
if (url.startsWith('https://discord.com/')) {
|
if (url.startsWith('https://discord.com/')) {
|
||||||
if (permission === 'media' && isConnected === true) { // if user is connected to Discord voice then enable microphone
|
if (permission === 'media') { // if user is connected to Discord voice then enable microphone
|
||||||
console.log("User connected to Discord VOIP server. Granted permission for microphone")
|
console.log("Granted permission for 'media'");
|
||||||
micPermissionGranted = true
|
|
||||||
return callback(true)
|
return callback(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -303,42 +188,12 @@ app.on('ready', () => {
|
|||||||
|
|
||||||
ipcMain.on('asynchronous-message', (event, _data) => {
|
ipcMain.on('asynchronous-message', (event, _data) => {
|
||||||
let msg = _data.msg
|
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') {
|
if (msg === 'DOMready') {
|
||||||
console.log("Discord webview loaded")
|
console.log("Discord webview loaded")
|
||||||
mainWindow.webContents.send('devMode', devMode)
|
mainWindow.webContents.send('devMode', devMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg === 'confirmMicClose') {
|
|
||||||
if (isTalking === true) {
|
|
||||||
console.log("Mic state desync. Opening Mic.")
|
|
||||||
unmuteMic()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (msg === 'blockUpdate') {
|
if (msg === 'blockUpdate') {
|
||||||
if (logWindow){
|
if (logWindow){
|
||||||
logWindow.webContents.send('blockUpdate', _data.data)
|
logWindow.webContents.send('blockUpdate', _data.data)
|
||||||
@ -352,9 +207,6 @@ ipcMain.on('asynchronous-message', (event, _data) => {
|
|||||||
if (_data.data.wName === 1) {
|
if (_data.data.wName === 1) {
|
||||||
logWindow.minimize()
|
logWindow.minimize()
|
||||||
}
|
}
|
||||||
if (_data.data.wName === 2) {
|
|
||||||
settingsWindow.minimize()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg === 'maximizeApplication') {
|
if (msg === 'maximizeApplication') {
|
||||||
@ -364,9 +216,6 @@ ipcMain.on('asynchronous-message', (event, _data) => {
|
|||||||
if (_data.data.wName === 1) {
|
if (_data.data.wName === 1) {
|
||||||
maximizeMinimizeState(logWindow)
|
maximizeMinimizeState(logWindow)
|
||||||
}
|
}
|
||||||
if (_data.data.wName === 2) {
|
|
||||||
maximizeMinimizeState(settingsWindow)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg === 'closeApplication') {
|
if (msg === 'closeApplication') {
|
||||||
@ -376,9 +225,6 @@ ipcMain.on('asynchronous-message', (event, _data) => {
|
|||||||
if (_data.data.wName === 1) {
|
if (_data.data.wName === 1) {
|
||||||
logWindow.close()
|
logWindow.close()
|
||||||
}
|
}
|
||||||
if (_data.data.wName === 2) {
|
|
||||||
settingsWindow.close()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg === 'openLog') {
|
if (msg === 'openLog') {
|
||||||
@ -390,114 +236,11 @@ ipcMain.on('asynchronous-message', (event, _data) => {
|
|||||||
logWindow.center()
|
logWindow.center()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg === 'openSettings') {
|
|
||||||
if (settingsWindow) {
|
|
||||||
if (settingsWindow.isMinimized()) settingsWindow.restore()
|
|
||||||
settingsWindow.focus()
|
|
||||||
}else {
|
|
||||||
createSettingsWindow()
|
|
||||||
settingsWindow.center()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (msg === 'SettingsDOMReady') {
|
|
||||||
if (settingsWindow) {
|
|
||||||
console.log("SettingsDOMReady. Sending Settings DOM obj")
|
|
||||||
settingsWindow.webContents.send('settingsObj', configObj)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (msg === 'setPTTKey') {
|
|
||||||
if (settingsWindow) {
|
|
||||||
if (ioHook) {
|
|
||||||
isChangingPTTKey = true
|
|
||||||
console.log("waiting for user to rebind")
|
|
||||||
if (settingsWindow && isChangingPTTKey) {
|
|
||||||
|
|
||||||
restartioHook().then(v => {
|
|
||||||
|
|
||||||
mainWindow.blur()
|
|
||||||
|
|
||||||
ioHook.once('keydown', event => {
|
|
||||||
if (settingsWindow && isChangingPTTKey) {
|
|
||||||
console.log("rebind success")
|
|
||||||
configObj.pttDevice = 'keyboard'
|
|
||||||
configObj.key = event.keycode
|
|
||||||
isChangingPTTKey = false
|
|
||||||
saveConfig(configObj)
|
|
||||||
settingsWindow.webContents.send('settingsObj', configObj)
|
|
||||||
setPTTKey()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Ignore using left click (mouse1)
|
|
||||||
ioHook.once('mousedown', event => {
|
|
||||||
if (settingsWindow && isChangingPTTKey && event.button !== 1) {
|
|
||||||
console.log("rebind success")
|
|
||||||
configObj.pttDevice = 'mouse'
|
|
||||||
configObj.key = event.button
|
|
||||||
isChangingPTTKey = false
|
|
||||||
saveConfig(configObj)
|
|
||||||
settingsWindow.webContents.send('settingsObj', configObj)
|
|
||||||
setPTTKey()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (msg === 'cancelSetPTTKey') {
|
|
||||||
console.log("cancel set new PTT")
|
|
||||||
isChangingPTTKey = false
|
|
||||||
saveConfig(configObj)
|
|
||||||
settingsWindow.webContents.send('settingsObj', configObj)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (msg === 'setPTTDelay') {
|
|
||||||
console.log(`New PTT Delay: ${_data.data} ms`)
|
|
||||||
configObj.delay = _data.data
|
|
||||||
saveConfig(configObj)
|
|
||||||
settingsWindow.webContents.send('settingsObj', configObj)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (msg === 'disablePTT') {
|
|
||||||
if (_data.data === false) {
|
|
||||||
console.log(`PTT Disabled`)
|
|
||||||
configObj.delay = null
|
|
||||||
configObj.key = null
|
|
||||||
configObj.pttDevice = null
|
|
||||||
saveConfig(configObj)
|
|
||||||
settingsWindow.webContents.send('settingsObj', configObj)
|
|
||||||
}
|
|
||||||
if (_data.data === true) {
|
|
||||||
console.log(`PTT Enabled`)
|
|
||||||
configObj.delay = 1000
|
|
||||||
configObj.key = "none"
|
|
||||||
configObj.pttDevice = "none"
|
|
||||||
saveConfig(configObj)
|
|
||||||
settingsWindow.webContents.send('settingsObj', configObj)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
app.on('ready', event => {
|
app.on('ready', event => {
|
||||||
console.log(`Dev Mode: ${devMode}`)
|
console.log(`Dev Mode: ${devMode}`)
|
||||||
|
|
||||||
initConfig()
|
listenForKeySignal();
|
||||||
.then(value => {
|
|
||||||
configObj = value
|
|
||||||
return configObj
|
|
||||||
})
|
|
||||||
.then(configObj => {
|
|
||||||
console.log(configObj)
|
|
||||||
restartioHook().then(() => {
|
|
||||||
setPTTKey()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
6820
package-lock.json
generated
6820
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
66
package.json
66
package.json
@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "discordsandbox",
|
"name": "discord-sandboxed",
|
||||||
"version": "1.1.6",
|
"author": "Michael Peters <rick.rat@protonmail.com> (http://elipzer.com)",
|
||||||
"description": "Discord Sandboxed",
|
"version": "1.2.0",
|
||||||
|
"description": "Puts Discord's web client in an electron webview to hard-block telemetry",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "electron . dev",
|
"start": "electron . dev",
|
||||||
"postinstall": "electron-builder install-app-deps",
|
"postinstall": "electron-builder install-app-deps",
|
||||||
"package-win": "electron-builder --win --publish never",
|
"package-pacman": "electron-builder --linux pacman"
|
||||||
"package-AppImage": "electron-builder --linux AppImage"
|
|
||||||
},
|
},
|
||||||
"repository": "https://github.com/khlam/discord-sandboxed",
|
"repository": "https://github.com/khlam/discord-sandboxed",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
@ -15,52 +15,24 @@
|
|||||||
"privacy",
|
"privacy",
|
||||||
"sandbox"
|
"sandbox"
|
||||||
],
|
],
|
||||||
"author": "Kin-Ho Lam",
|
|
||||||
"license": "GNU GENERAL PUBLIC LICENSE Version 3",
|
"license": "GNU GENERAL PUBLIC LICENSE Version 3",
|
||||||
"devDependencies": {
|
|
||||||
"electron": "^9.4.0",
|
|
||||||
"electron-builder": "^21.2.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chokidar": "^3.3.1",
|
"chokidar": "^3.5.3",
|
||||||
"graceful-fs": "^4.2.2",
|
"graceful-fs": "^4.2.9"
|
||||||
"iohook": "^0.7.2"
|
|
||||||
},
|
},
|
||||||
"iohook": {
|
"devDependencies": {
|
||||||
"targets": [
|
"electron": "^17.1.0",
|
||||||
"electron-80"
|
"electron-builder": "^22.14.13"
|
||||||
],
|
|
||||||
"platforms": [
|
|
||||||
"win32",
|
|
||||||
"darwin",
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"arches": [
|
|
||||||
"x64"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"build": {
|
"linux": {
|
||||||
"appId": "com.electron.DiscordSandboxed",
|
"target": "pacman",
|
||||||
"productName": "Discord Sandboxed",
|
"maintainer": "Michael Peters <rick.rat@protonmail.com> (http://elipzer.com)",
|
||||||
"win": {
|
|
||||||
"asar": true,
|
|
||||||
"icon": "views/assets/icon.ico",
|
"icon": "views/assets/icon.ico",
|
||||||
"target": [
|
"synopsis": "Discord Sandboxed fork by Michael Peters",
|
||||||
"nsis"
|
"description": "Puts Discord's web client in an electron webview to hard-block telemetry",
|
||||||
]
|
"depends": [
|
||||||
},
|
"libxkbcommon-x11"
|
||||||
"nsis": {
|
],
|
||||||
"installerIcon": "views/assets/icon.ico",
|
"packageName": "discord-sandboxed"
|
||||||
"uninstallerIcon": "views/assets/icon.ico",
|
|
||||||
"license": "LICENSE.md",
|
|
||||||
"createDesktopShortcut": true,
|
|
||||||
"createStartMenuShortcut": true,
|
|
||||||
"oneClick": false,
|
|
||||||
"allowToChangeInstallationDirectory": true,
|
|
||||||
"runAfterFinish": true
|
|
||||||
},
|
|
||||||
"directories": {
|
|
||||||
"output": "release"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
const {app} = require('electron')
|
|
||||||
const fs = require('graceful-fs')
|
|
||||||
const path = require('path')
|
|
||||||
|
|
||||||
function _saveToConfig (configObj) {
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
const documentsDir = app.getPath('documents')
|
|
||||||
const configDir = path.join(documentsDir, 'DiscordSandbox')
|
|
||||||
const configFile = path.join(configDir, 'config.json')
|
|
||||||
console.log('\tUpdating config.json', configObj)
|
|
||||||
fs.writeFile(configFile, JSON.stringify(configObj, null, 2), (err) => {
|
|
||||||
if (err) throw err;
|
|
||||||
return resolve(configObj)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
initConfig: function () {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const documentsDir = app.getPath('documents') // Fetchs user's documents directory
|
|
||||||
const configDir = path.join(documentsDir, 'DiscordSandbox') // config is stored in user's home dir
|
|
||||||
const configFile = path.join(configDir, 'config.json') // Saves all config information in config.json
|
|
||||||
|
|
||||||
let configObj // Init configObj
|
|
||||||
|
|
||||||
// If config dir does not exist create it
|
|
||||||
if (!fs.existsSync(configDir)){
|
|
||||||
fs.mkdirSync(configDir)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If config.json does not exist, create it with blank values
|
|
||||||
if (!fs.existsSync(configFile)) {
|
|
||||||
console.log(`\tCreated ${configFile}`)
|
|
||||||
configObj = {
|
|
||||||
'pttDevice': 'mouse',
|
|
||||||
'key': '4',
|
|
||||||
'delay': '1000',
|
|
||||||
}
|
|
||||||
return resolve(_saveToConfig(configObj))
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
configObj = JSON.parse(fs.readFileSync(configFile, 'utf8'))
|
|
||||||
return resolve(configObj)
|
|
||||||
} catch (err) {
|
|
||||||
return reject(err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
saveConfig: function(configObj) {
|
|
||||||
return _saveToConfig(configObj)
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,15 +6,11 @@ ipcRenderer.on('devMode', (event, msg) => {
|
|||||||
window.postMessage({ type: "devMode", text: `${msg}` }, "*")
|
window.postMessage({ type: "devMode", text: `${msg}` }, "*")
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcRenderer.on('micOpen', (event, msg) => {
|
ipcRenderer.on('micToggle', (event, msg) => {
|
||||||
window.postMessage({ type: "micOpen"}, "*")
|
console.log('got toggle mic');
|
||||||
|
window.postMessage({ type: "micToggle"}, "*")
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcRenderer.on('micClose', (event, msg) => {
|
|
||||||
window.postMessage({ type: "micClose"}, "*")
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
ipcRenderer.on('URLCopied', (event, msg) => {
|
ipcRenderer.on('URLCopied', (event, msg) => {
|
||||||
window.postMessage({ type: "URLCopied"}, "*")
|
window.postMessage({ type: "URLCopied"}, "*")
|
||||||
})
|
})
|
||||||
@ -45,22 +41,6 @@ window.addEventListener(
|
|||||||
ipcRenderer.send('asynchronous-message', {msg: 'disconnected'})
|
ipcRenderer.send('asynchronous-message', {msg: 'disconnected'})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.data.type === 'self-muted'){
|
|
||||||
ipcRenderer.send('asynchronous-message', {msg:'self-muted'})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.data.type === 'self-unmuted'){
|
|
||||||
ipcRenderer.send('asynchronous-message', {msg: 'self-unmuted'})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.data.type === 'confirmMicOpen'){
|
|
||||||
ipcRenderer.send('asynchronous-message', {msg: 'confirmMicOpen'})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.data.type === 'confirmMicClose'){
|
|
||||||
ipcRenderer.send('asynchronous-message', {msg: 'confirmMicClose'})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.data.type === 'blockUpdate'){
|
if (event.data.type === 'blockUpdate'){
|
||||||
ipcRenderer.send('asynchronous-message', {msg: 'blockUpdate', data: event.data.payload})
|
ipcRenderer.send('asynchronous-message', {msg: 'blockUpdate', data: event.data.payload})
|
||||||
}
|
}
|
||||||
@ -80,11 +60,6 @@ window.addEventListener(
|
|||||||
if (event.data.type === 'openLog'){
|
if (event.data.type === 'openLog'){
|
||||||
ipcRenderer.send('asynchronous-message', {msg: 'openLog'})
|
ipcRenderer.send('asynchronous-message', {msg: 'openLog'})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (event.data.type === 'openSettings'){
|
|
||||||
ipcRenderer.send('asynchronous-message', {msg: 'openSettings'})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
false
|
false
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
const { ipcRenderer } = require('electron')
|
|
||||||
|
|
||||||
// Pass commands sent from main.js to settingsRender
|
|
||||||
ipcRenderer.on('settingsObj', (event, msg) => {
|
|
||||||
window.postMessage({ type: "settingsObj", payload: msg }, "*")
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcRenderer.on('unfocused', (event, msg) => {
|
|
||||||
window.postMessage({ type: "unfocused"}, "*")
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcRenderer.on('focused', (event, msg) => {
|
|
||||||
window.postMessage({ type: "focused"}, "*")
|
|
||||||
})
|
|
||||||
|
|
||||||
// Pass commands sent from settings window (processed by settingsRender.js) to main.js
|
|
||||||
window.addEventListener(
|
|
||||||
"message",
|
|
||||||
event => {
|
|
||||||
if (event.origin === "file://" && event.source === window) {
|
|
||||||
|
|
||||||
if (event.data.type === 'SettingsDOMReady'){
|
|
||||||
ipcRenderer.send('asynchronous-message', {msg: 'SettingsDOMReady'})
|
|
||||||
}
|
|
||||||
if (event.data.type === 'setPTTKey'){
|
|
||||||
ipcRenderer.send('asynchronous-message', {msg: 'setPTTKey'})
|
|
||||||
}
|
|
||||||
if (event.data.type === 'cancelSetPTTKey'){
|
|
||||||
ipcRenderer.send('asynchronous-message', {msg: 'cancelSetPTTKey'})
|
|
||||||
}
|
|
||||||
if (event.data.type === 'setPTTDelay'){
|
|
||||||
ipcRenderer.send('asynchronous-message', {msg: 'setPTTDelay', data: event.data.delay})
|
|
||||||
}
|
|
||||||
if (event.data.type === 'disablePTT'){
|
|
||||||
ipcRenderer.send('asynchronous-message', {msg: 'disablePTT', data: event.data.pttEnable})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.data.type === 'minimizeApplication'){
|
|
||||||
ipcRenderer.send('asynchronous-message', {msg: 'minimizeApplication', data: event.data.payload})
|
|
||||||
}
|
|
||||||
if (event.data.type === 'maximizeApplication'){
|
|
||||||
ipcRenderer.send('asynchronous-message', {msg: 'maximizeApplication', data: event.data.payload})
|
|
||||||
}
|
|
||||||
if (event.data.type === 'closeApplication'){
|
|
||||||
ipcRenderer.send('asynchronous-message', {msg: 'closeApplication', data: event.data.payload})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
false
|
|
||||||
)
|
|
@ -1,9 +1,9 @@
|
|||||||
html, body{
|
html, body{
|
||||||
color: #FFFFFF;
|
color: #ffffff;
|
||||||
font-family: "Lucida Console", Courier, monospace;
|
font-family: "Hack Nerd Font", Courier, monospace;
|
||||||
background-color: #23272A;
|
background-color: #202225;
|
||||||
margin: 0px;
|
margin: 0;
|
||||||
padding: 0px;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logContainer {
|
.logContainer {
|
||||||
@ -18,7 +18,8 @@ html, body{
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logTable td, .logTable th {
|
.logTable td,
|
||||||
|
.logTable th {
|
||||||
border: 0px;
|
border: 0px;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
@ -29,5 +30,5 @@ html, body{
|
|||||||
padding-top: 3px;
|
padding-top: 3px;
|
||||||
padding-bottom: 3px;
|
padding-bottom: 3px;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
color: #FFFFFF;
|
color: #ffffff;
|
||||||
}
|
}
|
@ -1,17 +0,0 @@
|
|||||||
html, body{
|
|
||||||
color: #FFFFFF;
|
|
||||||
font-family: "Lucida Console", Courier, monospace;
|
|
||||||
background-color: #23272A;
|
|
||||||
margin: 0px;
|
|
||||||
padding: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.settingsContainer {
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.niceButton {
|
|
||||||
margin: 10px;
|
|
||||||
color: #FFFFFF;
|
|
||||||
background-color: #000000;
|
|
||||||
}
|
|
@ -2,66 +2,47 @@
|
|||||||
-webkit-app-region: drag;
|
-webkit-app-region: drag;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
background-color: #000000;
|
background-color: #202225;
|
||||||
color: #FFFFFF;
|
color: #ffffff;
|
||||||
width: 100%;
|
|
||||||
height: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-button-container {
|
|
||||||
background-color: #000000;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-name-container {
|
.app-name-container {
|
||||||
background-color: #000000;
|
flex: 1;
|
||||||
|
color: #ffffff;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: left;
|
justify-content: left;
|
||||||
align-items: left;
|
align-items: center;
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
font-size: 11px;
|
|
||||||
padding-top: 0px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.menu-button-container,
|
||||||
.window-controls-container {
|
.window-controls-container {
|
||||||
background-color: #000000;
|
color: #dcddde;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
|
||||||
align-items: center;
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-button {
|
.menu-button {
|
||||||
-webkit-app-region: no-drag;
|
-webkit-app-region: no-drag;
|
||||||
display: inline-block;
|
width: 28px;
|
||||||
text-align: center;
|
|
||||||
width: 50px;
|
|
||||||
height: 24px;
|
height: 24px;
|
||||||
padding-top: 3px;
|
display: flex;
|
||||||
padding-bottom: 3px;
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-button:hover {
|
.menu-button:hover {
|
||||||
background-color: #e5e5e5;
|
background-color: #677bc4;
|
||||||
color: #191919;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.minimize-button {
|
.menu-button.close-button:hover {
|
||||||
-webkit-app-region: no-drag;
|
background-color: #f04747;
|
||||||
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.min-max-button {
|
.menu-button > svg {
|
||||||
-webkit-app-region: no-drag;
|
width: 12px;
|
||||||
}
|
height: 12px;
|
||||||
|
|
||||||
.close-button {
|
|
||||||
-webkit-app-region: no-drag;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-button:hover {
|
|
||||||
background-color: rgb(255, 59, 48);
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,12 +15,6 @@
|
|||||||
|
|
||||||
<div class="title-bar" id="titleBar">
|
<div class="title-bar" id="titleBar">
|
||||||
<div class="menu-button-container">
|
<div class="menu-button-container">
|
||||||
<div id="openSettingsButton" class="menu-button">
|
|
||||||
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-gear" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path fill-rule="evenodd" d="M8.837 1.626c-.246-.835-1.428-.835-1.674 0l-.094.319A1.873 1.873 0 0 1 4.377 3.06l-.292-.16c-.764-.415-1.6.42-1.184 1.185l.159.292a1.873 1.873 0 0 1-1.115 2.692l-.319.094c-.835.246-.835 1.428 0 1.674l.319.094a1.873 1.873 0 0 1 1.115 2.693l-.16.291c-.415.764.42 1.6 1.185 1.184l.292-.159a1.873 1.873 0 0 1 2.692 1.116l.094.318c.246.835 1.428.835 1.674 0l.094-.319a1.873 1.873 0 0 1 2.693-1.115l.291.16c.764.415 1.6-.42 1.184-1.185l-.159-.291a1.873 1.873 0 0 1 1.116-2.693l.318-.094c.835-.246.835-1.428 0-1.674l-.319-.094a1.873 1.873 0 0 1-1.115-2.692l.16-.292c.415-.764-.42-1.6-1.185-1.184l-.291.159A1.873 1.873 0 0 1 8.93 1.945l-.094-.319zm-2.633-.283c.527-1.79 3.065-1.79 3.592 0l.094.319a.873.873 0 0 0 1.255.52l.292-.16c1.64-.892 3.434.901 2.54 2.541l-.159.292a.873.873 0 0 0 .52 1.255l.319.094c1.79.527 1.79 3.065 0 3.592l-.319.094a.873.873 0 0 0-.52 1.255l.16.292c.893 1.64-.902 3.434-2.541 2.54l-.292-.159a.873.873 0 0 0-1.255.52l-.094.319c-.527 1.79-3.065 1.79-3.592 0l-.094-.319a.873.873 0 0 0-1.255-.52l-.292.16c-1.64.893-3.433-.902-2.54-2.541l.159-.292a.873.873 0 0 0-.52-1.255l-.319-.094c-1.79-.527-1.79-3.065 0-3.592l.319-.094a.873.873 0 0 0 .52-1.255l-.16-.292c-.892-1.64.902-3.433 2.541-2.54l.292.159a.873.873 0 0 0 1.255-.52l.094-.319z"/>
|
|
||||||
<path fill-rule="evenodd" d="M8 5.754a2.246 2.246 0 1 0 0 4.492 2.246 2.246 0 0 0 0-4.492zM4.754 8a3.246 3.246 0 1 1 6.492 0 3.246 3.246 0 0 1-6.492 0z"/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div id="openLogButton" class="menu-button">
|
<div id="openLogButton" class="menu-button">
|
||||||
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-card-text" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-card-text" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path fill-rule="evenodd" d="M14.5 3h-13a.5.5 0 0 0-.5.5v9a.5.5 0 0 0 .5.5h13a.5.5 0 0 0 .5-.5v-9a.5.5 0 0 0-.5-.5zm-13-1A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h13a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2h-13z"/>
|
<path fill-rule="evenodd" d="M14.5 3h-13a.5.5 0 0 0-.5.5v9a.5.5 0 0 0 .5.5h13a.5.5 0 0 0 .5-.5v-9a.5.5 0 0 0-.5-.5zm-13-1A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h13a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2h-13z"/>
|
||||||
@ -29,24 +23,36 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="app-name-container">
|
<div class="app-name-container">
|
||||||
<p></p>
|
<div></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="window-controls-container">
|
<div class="window-controls-container">
|
||||||
<div id="minimize-button" class="minimize-button menu-button">
|
<div id="minimize-button" class="minimize-button menu-button">
|
||||||
<svg height="100%" width="100%" viewBox="0 0 24 24" fill="currentColor" style="display: block; margin: auto" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M20,19H4v-2h16V19z"/></svg>
|
<svg width="12" height="12" viewBox="0 0 12 12">
|
||||||
|
<rect fill="currentColor" width="10" height="1" x="1" y="6" />
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div id="min-max-button" class="min-max-button menu-button">
|
<div id="min-max-button" class="min-max-button menu-button">
|
||||||
<svg height="100%" width="100%" viewBox="0 0 24 24" fill="currentColor" style="display: block; margin: auto" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M18.8,4H5.2C4.6,4,4,4.6,4,5.2v13.5C4,19.4,4.6,20,5.2,20h13.5c0.7,0,1.2-0.6,1.2-1.2V5.2C20,4.6,19.4,4,18.8,4z M18,18H6V6h12V18z"/></svg>
|
<svg width="12" height="12" viewBox="0 0 12 12">
|
||||||
|
<rect fill="none" stroke="currentColor" width="9" height="9" x="1.5" y="1.5" />
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div id="close-button" class="close-button menu-button">
|
<div id="close-button" class="close-button menu-button">
|
||||||
<svg height="100%" width="100%" viewBox="0 0 24 24" fill="currentColor" style="display: block; margin: auto" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M20,5.6L18.4,4L12,10.4L5.6,4L4,5.6l6.4,6.4L4,18.4L5.6,20l6.4-6.4l6.4,6.4l1.6-1.6L13.6,12L20,5.6z"/></svg>
|
<svg width="12" height="12" viewBox="0 0 12 12">
|
||||||
|
<polygon fill="currentColor" fillRule="evenodd" points="11 1.576 6.583 6 11 10.424 10.424 11 6 6.583 1.576 11 1 10.424 5.417 6 1 1.576 1.576 1 6 5.417 10.424 1" />
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="mainDisplay">
|
<div id="mainDisplay">
|
||||||
<!-- https://electronjs.org/docs/tutorial/security#15-disable-the-remote-module -->
|
<!-- https://electronjs.org/docs/tutorial/security#15-disable-the-remote-module -->
|
||||||
<webview id="discord" enableremotemodule="false" webpreferences="useragent='Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko'" partition="persist:discord" src="https://discord.com/login"></webview>
|
<webview
|
||||||
|
id="discord"
|
||||||
|
enableremotemodule="false"
|
||||||
|
partition="persist:discord"
|
||||||
|
src="https://discord.com/login"
|
||||||
|
useragent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36"
|
||||||
|
></webview>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -19,18 +19,10 @@ function convertObjToString(arr) {
|
|||||||
return arrStr
|
return arrStr
|
||||||
}
|
}
|
||||||
|
|
||||||
function openMic(webview){
|
function toggleMic(webview) {
|
||||||
console.log("talking")
|
webview.executeJavaScript(`
|
||||||
document.getElementById("overlay").style.display = "block";
|
document.querySelector('button[aria-label="Mute"]').click();
|
||||||
webview.sendInputEvent({keyCode: 'Backspace', type: 'keyDown'});
|
`);
|
||||||
//webview.sendInputEvent({keyCode: 'Backspace', type: 'char'});
|
|
||||||
}
|
|
||||||
|
|
||||||
function muteMic(webview){
|
|
||||||
console.log("not talking")
|
|
||||||
document.getElementById("overlay").style.display = "none";
|
|
||||||
webview.sendInputEvent({keyCode: 'Backspace', type: 'keyUp'});
|
|
||||||
//webview.sendInputEvent({keyCode: 'Backspace', type: 'char'});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeBloat(webview) {
|
function removeBloat(webview) {
|
||||||
@ -85,8 +77,8 @@ onload = () => {
|
|||||||
|
|
||||||
// Insert JS to detect when discord finishes loading
|
// Insert JS to detect when discord finishes loading
|
||||||
webview.addEventListener('did-finish-load', function() {
|
webview.addEventListener('did-finish-load', function() {
|
||||||
|
|
||||||
webview.executeJavaScript(`
|
webview.executeJavaScript(`
|
||||||
|
|
||||||
(function(open, send) {
|
(function(open, send) {
|
||||||
let whiteList = ${_whiteList}
|
let whiteList = ${_whiteList}
|
||||||
|
|
||||||
@ -156,59 +148,10 @@ onload = () => {
|
|||||||
}
|
}
|
||||||
})(XMLHttpRequest.prototype.open, XMLHttpRequest.prototype.send)
|
})(XMLHttpRequest.prototype.open, XMLHttpRequest.prototype.send)
|
||||||
`)
|
`)
|
||||||
|
|
||||||
webview.executeJavaScript(`
|
|
||||||
let dlButton = document.querySelectorAll('[aria-label="Download Apps"]')
|
|
||||||
t = setInterval(function(){
|
|
||||||
let dlButton = document.querySelectorAll('[aria-label="Servers sidebar"]')
|
|
||||||
if(dlButton.length != 0) {
|
|
||||||
console.log("--discord-load-complete")
|
|
||||||
clearInterval(t)
|
|
||||||
isMicMuted()
|
|
||||||
}else {
|
|
||||||
console.log("waiting for load")
|
|
||||||
console.log(dlButton)
|
|
||||||
}
|
|
||||||
}, 500);
|
|
||||||
`)
|
|
||||||
|
|
||||||
// Insert a function that will be called later
|
|
||||||
webview.executeJavaScript(`
|
|
||||||
function isMicMuted() {
|
|
||||||
if (document.querySelectorAll('[aria-label="Mute"]')[0].getAttribute("aria-checked") === "false"){
|
|
||||||
console.log("unmuted")
|
|
||||||
}else {
|
|
||||||
console.log("muted")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Send commands to preload.js
|
// Send commands to preload.js
|
||||||
webview.addEventListener('console-message', (e) => {
|
webview.addEventListener('console-message', (e) => {
|
||||||
if (e.message.includes("RTC media connection state: CONNECTED")) {
|
|
||||||
console.log("Connected to server")
|
|
||||||
window.postMessage({ type: "connected"}, "*")
|
|
||||||
removeBloat(webview)
|
|
||||||
isConnectedToVoiceServer = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.message.includes("RTC media connection state: DISCONNECTED")) {
|
|
||||||
console.log("Disconnected from server")
|
|
||||||
window.postMessage({ type: "disconnected"}, "*")
|
|
||||||
isConnectedToVoiceServer = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.message === "muted") {
|
|
||||||
console.log("Self Muted in Discord")
|
|
||||||
window.postMessage({ type: "self-muted"}, "*")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.message === "unmuted") {
|
|
||||||
console.log("Self Un-Muted in Discord")
|
|
||||||
window.postMessage({ type: "self-unmuted"}, "*")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute JS into the webview after login
|
// Execute JS into the webview after login
|
||||||
if (e.message === "--discord-load-complete") {
|
if (e.message === "--discord-load-complete") {
|
||||||
userMuteDeafenListener(webview)
|
userMuteDeafenListener(webview)
|
||||||
@ -269,14 +212,9 @@ onload = () => {
|
|||||||
document.getElementById('titleBar').style.color = "#ffffff"
|
document.getElementById('titleBar').style.color = "#ffffff"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.data.type === 'micOpen'){
|
if (event.data.type === 'micToggle') {
|
||||||
openMic(webview)
|
console.log('toggling mic');
|
||||||
window.postMessage({ type: "confirmMicOpen"}, "*")
|
toggleMic(webview);
|
||||||
}
|
|
||||||
|
|
||||||
if (event.data.type === 'micClose'){
|
|
||||||
muteMic(webview)
|
|
||||||
window.postMessage({ type: "confirmMicClose"}, "*")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.data.type === 'URLCopied') {
|
if (event.data.type === 'URLCopied') {
|
||||||
|
@ -1,86 +0,0 @@
|
|||||||
let windowName = 2
|
|
||||||
|
|
||||||
let configObj = null
|
|
||||||
|
|
||||||
let isSettingPTTKey = false
|
|
||||||
|
|
||||||
onload = () => {
|
|
||||||
window.postMessage({ type: "SettingsDOMReady"}, "*")
|
|
||||||
console.log("sent dom ready")
|
|
||||||
}
|
|
||||||
|
|
||||||
const setPTTEnable = document.getElementById('pttEnable')
|
|
||||||
if (setPTTEnable) {
|
|
||||||
setPTTEnable.onclick = function () {
|
|
||||||
console.log(`Set PTT Enabled: ${setPTTEnable.checked}`)
|
|
||||||
window.postMessage({ type: "disablePTT" , pttEnable: setPTTEnable.checked}, "*")
|
|
||||||
if (setPTTEnable.checked) {
|
|
||||||
setPTTKey.style.display = "block"
|
|
||||||
setPTTDelay.type = "number"
|
|
||||||
}else {
|
|
||||||
setPTTKey.style.display = "none"
|
|
||||||
setPTTDelay.type = "hidden"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const setPTTKey = document.getElementById('setPTTKeyButton')
|
|
||||||
if (setPTTKey) {
|
|
||||||
setPTTKey.onclick = function () {
|
|
||||||
if (isSettingPTTKey === false) {
|
|
||||||
isSettingPTTKey = true
|
|
||||||
console.log("Rebind PTT key clicked")
|
|
||||||
window.postMessage({ type: "setPTTKey"}, "*")
|
|
||||||
document.getElementById("setPTTKeyButton").innerText = "Press any key... Click here to cancel"
|
|
||||||
}else {
|
|
||||||
window.postMessage({ type: "cancelSetPTTKey"}, "*")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const setPTTDelay = document.getElementById('pttDelay')
|
|
||||||
if (setPTTDelay) {
|
|
||||||
setPTTDelay.onchange = function () {
|
|
||||||
console.log(setPTTDelay.value)
|
|
||||||
window.postMessage({ type: "setPTTDelay" , delay: setPTTDelay.value}, "*")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function displayCurrentSettings() {
|
|
||||||
if (configObj.pttDevice && configObj.key) {
|
|
||||||
setPTTEnable.checked = true
|
|
||||||
setPTTKey.innerText = `${configObj.pttDevice} button ${configObj.key}`
|
|
||||||
setPTTDelay.value = configObj.delay
|
|
||||||
setPTTKey.style.display = "block"
|
|
||||||
setPTTDelay.type = "number"
|
|
||||||
}else {
|
|
||||||
setPTTEnable.checked = false
|
|
||||||
setPTTKey.style.display = "none"
|
|
||||||
setPTTDelay.type = "hidden"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Accept commands from settingsLoad.js
|
|
||||||
window.addEventListener(
|
|
||||||
"message",
|
|
||||||
event => {
|
|
||||||
if (event.origin === "file://" && event.source === window) {
|
|
||||||
if (event.data.type === 'settingsObj') {
|
|
||||||
isSettingPTTKey = false
|
|
||||||
configObj = event.data.payload
|
|
||||||
console.log(configObj)
|
|
||||||
displayCurrentSettings()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.data.type === 'unfocused'){
|
|
||||||
console.log("window unfocused")
|
|
||||||
document.getElementById('titleBar').style.color = "#7f7f7f"
|
|
||||||
}
|
|
||||||
if (event.data.type === 'focused'){
|
|
||||||
console.log("window focused")
|
|
||||||
document.getElementById('titleBar').style.color = "#ffffff"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
false
|
|
||||||
)
|
|
@ -1,5 +1,5 @@
|
|||||||
// Send window minimize/maximize/close commands to main
|
// Send window minimize/maximize/close commands to main
|
||||||
// See windowName variable in mainRender.js, logRender.js, and settingsRender.js
|
// See windowName variable in mainRender.js and logRender.js
|
||||||
const minButton = document.getElementById('minimize-button')
|
const minButton = document.getElementById('minimize-button')
|
||||||
if (minButton) {
|
if (minButton) {
|
||||||
minButton.onclick = function () {
|
minButton.onclick = function () {
|
||||||
@ -28,9 +28,3 @@ if (logButton) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const settingsButton = document.getElementById('openSettingsButton')
|
|
||||||
if (settingsButton) {
|
|
||||||
settingsButton.onclick = function () {
|
|
||||||
window.postMessage({ type: "openSettings" }, "*")
|
|
||||||
}
|
|
||||||
}
|
|
@ -12,14 +12,18 @@
|
|||||||
|
|
||||||
<div class="title-bar" id="titleBar">
|
<div class="title-bar" id="titleBar">
|
||||||
<div class="app-name-container">
|
<div class="app-name-container">
|
||||||
<p>Logs</p>
|
<div>Log</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="window-controls-container">
|
<div class="window-controls-container">
|
||||||
<div id="minimize-button" class="minimize-button menu-button">
|
<div id="minimize-button" class="minimize-button menu-button">
|
||||||
<svg height="100%" width="100%" viewBox="0 0 24 24" fill="currentColor" style="display: block; margin: auto" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M20,19H4v-2h16V19z"/></svg>
|
<svg width="12" height="12" viewBox="0 0 12 12">
|
||||||
|
<rect fill="currentColor" width="10" height="1" x="1" y="6" />
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div id="close-button" class="close-button menu-button">
|
<div id="close-button" class="close-button menu-button">
|
||||||
<svg height="100%" width="100%" viewBox="0 0 24 24" fill="currentColor" style="display: block; margin: auto" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M20,5.6L18.4,4L12,10.4L5.6,4L4,5.6l6.4,6.4L4,18.4L5.6,20l6.4-6.4l6.4,6.4l1.6-1.6L13.6,12L20,5.6z"/></svg>
|
<svg width="12" height="12" viewBox="0 0 12 12">
|
||||||
|
<polygon fill="currentColor" fillRule="evenodd" points="11 1.576 6.583 6 11 10.424 10.424 11 6 6.583 1.576 11 1 10.424 5.417 6 1 1.576 1.576 1 6 5.417 10.424 1" />
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -31,5 +35,5 @@
|
|||||||
<script src="./js/logRender.js"></script>
|
<script src="./js/logRender.js"></script>
|
||||||
<script src="./js/titlebar.js"></script>
|
<script src="./js/titlebar.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<!--style-src 'self' 'unsafe-inline' needs evaluation, some conflict with node_modules\electron\dist\resources\electron.asar\renderer\web-view\web-view-impl.js-->
|
|
||||||
<meta http-equiv="Content-Security-Policy" content="default-src none; script-src 'self'; style-src 'self' 'unsafe-inline'">
|
|
||||||
<link type="text/css" rel="stylesheet" href="./css/settingsStyle.css">
|
|
||||||
<link type="text/css" rel="stylesheet" href="./css/titlebar.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div class="title-bar" id="titleBar">
|
|
||||||
<div class="app-name-container">
|
|
||||||
<p>Settings</p>
|
|
||||||
</div>
|
|
||||||
<div class="window-controls-container">
|
|
||||||
<div id="minimize-button" class="minimize-button menu-button">
|
|
||||||
<svg height="100%" width="100%" viewBox="0 0 24 24" fill="currentColor" style="display: block; margin: auto" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M20,19H4v-2h16V19z"/></svg>
|
|
||||||
</div>
|
|
||||||
<div id="close-button" class="close-button menu-button">
|
|
||||||
<svg height="100%" width="100%" viewBox="0 0 24 24" fill="currentColor" style="display: block; margin: auto" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M20,5.6L18.4,4L12,10.4L5.6,4L4,5.6l6.4,6.4L4,18.4L5.6,20l6.4-6.4l6.4,6.4l1.6-1.6L13.6,12L20,5.6z"/></svg>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="settingsContainer" class="settingsContainer">
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td align="right">Enable System-wide Push to Talk</td>
|
|
||||||
<td>
|
|
||||||
<input type="checkbox" id="pttEnable" name="ptt">
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td align="right">Push to Talk Key</td>
|
|
||||||
<td>
|
|
||||||
<span id='setPTTKeyButton' class="niceButton">loading...</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td align="right">Push to Talk Release Delay (ms)</td>
|
|
||||||
<td>
|
|
||||||
<input id='pttDelay' type="number">
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="./js/settingsRender.js"></script>
|
|
||||||
<script src="./js/titlebar.js"></script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
Loading…
Reference in New Issue
Block a user