Update tor support with electron proxy (#225)

* Update tor support with electron proxy

* Update proxy testing, fix variable conflict

* Add default value to settings view for proxyAddress

* Remove tor-request
This commit is contained in:
ivan1548 2019-02-26 12:45:55 -08:00 committed by Preston
parent 3a1fcdfea2
commit 47094ecb85
9 changed files with 172 additions and 184 deletions

175
package-lock.json generated
View File

@ -125,6 +125,7 @@
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.0.tgz",
"integrity": "sha512-c+R/U5X+2zz2+UCrCFv6odQzJdoqI+YecuhnAJLa1zYaMc13zPfwMwZrr91Pd1DYNo/yPRbiM4WVf9whgwFsIg==",
"dev": true,
"requires": {
"es6-promisify": "^5.0.0"
}
@ -4441,12 +4442,14 @@
"es6-promise": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz",
"integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ=="
"integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==",
"dev": true
},
"es6-promisify": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
"integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
"dev": true,
"requires": {
"es6-promise": "^4.0.3"
}
@ -4623,11 +4626,6 @@
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
},
"fast-deep-equal": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
"integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
},
"fast-json-stable-stringify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
@ -5402,8 +5400,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/imul/-/imul-1.0.1.tgz",
"integrity": "sha1-nVhnFh6LPelsLDjV3HyxAvNeKsk=",
"dev": true,
"optional": true
"dev": true
},
"indent-string": {
"version": "2.1.0",
@ -5546,11 +5543,6 @@
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
"integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY="
},
"ip": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
"integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo="
},
"is-absolute-url": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz",
@ -5647,8 +5639,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
"integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=",
"dev": true,
"optional": true
"dev": true
},
"is-relative-path": {
"version": "1.0.2",
@ -6782,8 +6773,7 @@
"version": "2.11.1",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz",
"integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==",
"dev": true,
"optional": true
"dev": true
},
"natives": {
"version": "1.1.6",
@ -8445,11 +8435,6 @@
"integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
"dev": true
},
"smart-buffer": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.1.tgz",
"integrity": "sha512-RFqinRVJVcCAL9Uh1oVqE6FZkqsyLiVOYEZ20TqIOjuX7iFVJ+zsbs4RIghnw/pTs7mZvt8ZHhvm1ZUrR4fykg=="
},
"sntp": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
@ -8460,24 +8445,6 @@
"hoek": "2.x.x"
}
},
"socks": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.2.1.tgz",
"integrity": "sha512-0GabKw7n9mI46vcNrVfs0o6XzWzjVa3h6GaSo2UPxtWAROXUWavfJWh1M4PR5tnE0dcnQXZIDFP4yrAysLze/w==",
"requires": {
"ip": "^1.1.5",
"smart-buffer": "^4.0.1"
}
},
"socks-proxy-agent": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz",
"integrity": "sha512-Kezx6/VBguXOsEe5oU3lXYyKMi4+gva72TwJ7pQY5JfqUx2nMk7NXA6z/mpNqIlfQjWYVfeuNvQjexiTaTn6Nw==",
"requires": {
"agent-base": "~4.2.0",
"socks": "~2.2.0"
}
},
"sorcery": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz",
@ -9144,134 +9111,6 @@
"integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=",
"dev": true
},
"tor-request": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/tor-request/-/tor-request-2.3.0.tgz",
"integrity": "sha512-uFsCDUYaJn1S55bPyIbi7TrpQyEB6F2WdU7LxgCqKN+VrfRladNaE99V9zCD5TrCPvizmLL+sTH2JHWFIpgv3A==",
"requires": {
"request": "~2.88.0",
"socks-proxy-agent": "~4.0.1"
},
"dependencies": {
"ajv": {
"version": "5.5.2",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
"integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
"requires": {
"co": "^4.6.0",
"fast-deep-equal": "^1.0.0",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.3.0"
}
},
"aws4": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
},
"combined-stream": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
"integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
"requires": {
"delayed-stream": "~1.0.0"
}
},
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
},
"form-data": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.6",
"mime-types": "^2.1.12"
}
},
"har-validator": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz",
"integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==",
"requires": {
"ajv": "^5.3.0",
"har-schema": "^2.0.0"
}
},
"mime-db": {
"version": "1.36.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz",
"integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw=="
},
"mime-types": {
"version": "2.1.20",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz",
"integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==",
"requires": {
"mime-db": "~1.36.0"
}
},
"oauth-sign": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
},
"qs": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
},
"request": {
"version": "2.88.0",
"resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
"integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
"requires": {
"aws-sign2": "~0.7.0",
"aws4": "^1.8.0",
"caseless": "~0.12.0",
"combined-stream": "~1.0.6",
"extend": "~3.0.2",
"forever-agent": "~0.6.1",
"form-data": "~2.3.2",
"har-validator": "~5.1.0",
"http-signature": "~1.2.0",
"is-typedarray": "~1.0.0",
"isstream": "~0.1.2",
"json-stringify-safe": "~5.0.1",
"mime-types": "~2.1.19",
"oauth-sign": "~0.9.0",
"performance-now": "^2.1.0",
"qs": "~6.5.2",
"safe-buffer": "^5.1.2",
"tough-cookie": "~2.4.3",
"tunnel-agent": "^0.6.0",
"uuid": "^3.3.2"
}
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"tough-cookie": {
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
"integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
"requires": {
"psl": "^1.1.24",
"punycode": "^1.4.1"
}
},
"uuid": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
}
}
},
"touch": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/touch/-/touch-0.0.3.tgz",

View File

@ -100,7 +100,6 @@
"mustache": "^2.3.0",
"nedb": "^1.8.0",
"opml-to-json": "0.0.3",
"tor-request": "^2.3.0",
"vue": "^2.5.17",
"ytdl-core": "^0.29.1"
}

View File

@ -24,7 +24,8 @@ const {
app,
BrowserWindow,
dialog,
protocol
protocol,
ipcMain
} = require('electron');
const path = require('path');
const url = require('url');
@ -163,6 +164,17 @@ let init = function () {
const menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
/**
* Sets proxy when setProxy event is sent from renderer
*
* example data "SOCKS5://127.0.0.1:9050"
*/
ipcMain.on("setProxy", (_e, data) => {
win.webContents.session.setProxy({ proxyRules: data }, function () {
win.webContents.send("proxyAvailable")
});
});
};
/**

View File

@ -38,7 +38,6 @@ const shell = electron.shell; // Used to open external links into the user's nat
const clipboard = electron.clipboard;
const getOpml = require('opml-to-json'); // Gets the file type for imported files.
const fs = require('fs'); // Used to read files. Specifically in the settings page.
const tor = require('tor-request');
// User Defaults
let currentTheme = '';
@ -50,6 +49,10 @@ let checkForUpdates = true;
let currentVolume = 1;
let defaultQuality = 720;
let defaultPlaybackRate = '1';
// Proxy address variable
let defaultProxy = false;
// This variable is to make sure that proxy was set before making any API calls
let proxyAvailable = false;
let dialog = electron.remote.dialog; // Used for opening file browser to export / import subscriptions.
let toastTimeout; // Timeout for toast notifications.
@ -69,6 +72,11 @@ electron.ipcRenderer.on('ping', function(event, message) {
ft.log(message);
});
// Listens for proxy to be set in main process
electron.ipcRenderer.on('proxyAvailable', function(event, message) {
proxyAvailable = true;
});
$(document).ready(() => {
const searchBar = document.getElementById('search');
const jumpToInput = document.getElementById('jumpToInput');
@ -209,3 +217,28 @@ function showVideoOptions(element) {
element.nextElementSibling.style.display = 'none'
}
}
/**
* Wrapper around AJAX calls to wait for proxy to become available
* @return {Void}
*/
function proxyRequest(callback) {
let proxyCheckingInterval;
let counter = 0;
// Wait for proxy to become available
proxyCheckingInterval = setInterval(function() {
if(proxyAvailable) {
clearInterval(proxyCheckingInterval)
callback();
} else {
if(counter > 10) {
clearInterval(proxyCheckingInterval);
showToast('Unable to connect to the Tor network. Check the help page if you\'re having trouble setting up your node.');
}
counter++;
}
}, 100);
}

View File

@ -77,6 +77,12 @@ function updateSettingsView() {
document.getElementById('qualitySelect').value = defaultQuality;
document.getElementById('rateSelect').value = defaultPlaybackRate;
if(defaultProxy) {
settingsView.proxyAddress = defaultProxy;
} else {
settingsView.proxyAddress = "SOCKS5://127.0.0.1:9050";
}
});
}
@ -98,6 +104,7 @@ function checkDefaultSettings() {
'updates': true,
'quality': '720',
'rate': '1',
'proxy': "SOCKS5://127.0.0.1:9050" // This is default value for tor client
};
console.log(settingDefaults);
@ -151,6 +158,13 @@ function checkDefaultSettings() {
case 'rate':
defaultPlaybackRate = docs[0]['value'];
break;
case 'proxy':
defaultProxy = docs[0]['value'];
if(useTor && defaultProxy) {
electron.ipcRenderer.send("setProxy", defaultProxy);
}
break;
default:
break;
}
@ -173,6 +187,7 @@ function updateSettings() {
let updatesSwitch = document.getElementById('updatesSwitch').checked;
let qualitySelect = document.getElementById('qualitySelect').value;
let rateSelect = document.getElementById('rateSelect').value;
let proxyAddress = document.getElementById('proxyAddress').value;
let theme = 'light';
settingsView.useTor = torSwitch;
@ -180,6 +195,7 @@ function updateSettings() {
settingsView.autoplay = autoplaySwitch;
settingsView.subtitles = subtitlesSwitch;
settingsView.updates = updatesSwitch;
settingsView.proxyAddress = proxyAddress;
rememberHistory = historySwitch;
defaultQuality = qualitySelect;
defaultPlaybackRate = rateSelect;
@ -209,6 +225,17 @@ function updateSettings() {
useTor = torSwitch;
});
// Update proxy address
settingsDb.update({
_id: 'proxy'
}, {
value: proxyAddress
}, {}, function(err, numReplaced) {
console.log(err);
console.log(numReplaced);
defaultProxy = proxyAddress;
});
// Update history
settingsDb.update({
_id: 'history'
@ -275,6 +302,13 @@ function updateSettings() {
defaultPlaybackRate = rateSelect;
});
// set proxy in electron based on new values
if(torSwitch) {
electron.ipcRenderer.send("setProxy", proxyAddress);
} else {
electron.ipcRenderer.send("setProxy", {});
}
showToast('Settings have been saved.');
}

View File

@ -368,6 +368,39 @@ let settingsView = new Vue({
autoplay: true,
subtitles: false,
updates: true,
proxyAddress: false,
checkProxyResult: false,
proxyTestLoading: false
},
methods: {
checkProxy() {
this.checkProxyResult = false;
this.proxyTestLoading = true;
electron.ipcRenderer.send("setProxy", this.proxyAddress)
proxyRequest(() => {
$.ajax({
url: "https://ifconfig.co/json",
dataType: 'json',
timeout: 3000 // 3 second timeout
}).done(response => {
this.checkProxyResult = response;
})
.fail((xhr, textStatus, error) => {
console.log(xhr);
console.log(textStatus);
showToast('Proxy test failed');
}).always(() =>{
this.proxyTestLoading = false;
electron.ipcRenderer.send("setProxy", {});
});
})
}
},
computed: {
proxyTestButtonText() {
return this.proxyTestLoading ? "LOADING..." : "TEST PROXY"
}
},
template: settingsTemplate
});

View File

@ -32,17 +32,19 @@ function invidiousAPI(resource, id, params, success, fail = function(){
let requestUrl = 'https://www.invidio.us/api/v1/' + resource + '/' + id + '?' + $.param(params);
if (useTor) {
tor.request(requestUrl, (err, res, body) => {
if (!err && res.statusCode == 200) {
success(JSON.parse(body));
} else {
showToast('Unable to connect to the Tor network. Check the help page if you\'re having trouble setting up your node.');
console.log(err);
console.log(res);
console.log(body);
loadingView.seen = false;
}
});
proxyRequest(() => {
$.getJSON(
requestUrl,
success
).fail((xhr, textStatus, error) => {
fail(xhr);
console.log(xhr);
console.log(textStatus);
console.log(requestUrl);
});
})
} else {
$.getJSON(
requestUrl,

View File

@ -242,6 +242,19 @@ a {
border-bottom: 1px solid #616161;
}
.input-text-settings input {
width: auto;
border-bottom: 1px solid #616161;
width: 50%;
margin: 0 auto;
display: block;
}
#ipInfoSettings {
border: 1px solid;
margin: 10px 0;
}
.settingsButton {
padding: 10px;
display: inline-block;

View File

@ -3,8 +3,6 @@
<div class='center'>
<input type="checkbox" id="themeSwitch" name="set-name" class="switch-input" onchange='toggleTheme(this)' :checked='useTheme'>
<label for="themeSwitch" class="switch-label">Use Dark Theme</label>
<input type="checkbox" id="torSwitch" name="set-name" class="switch-input" :checked='useTor'>
<label for="torSwitch" class="switch-label">Use Tor for API calls</label>
<input type="checkbox" id="updatesSwitch" name="set-name" class="switch-input" :checked='updates'>
<label for="updatesSwitch" class="switch-label">Check for Updates</label>
<br />
@ -43,6 +41,31 @@
</div>
<br />
</div>
<div class="center">
<input type="checkbox" id="torSwitch" name="set-name" class="switch-input" :checked='useTor'>
<label for="torSwitch" class="switch-label">Use Tor / Proxy for API calls</label>
<div class="input-text-settings">
<label for="proxyAddress">Proxy Address (Example: SOCKS5://127.0.0.1:9050):</label>
<input type="text" id="proxyAddress" name="set-name" v-model="proxyAddress">
</div>
<div id="ipInfoSettings" v-if="checkProxyResult">
<h4>Your Info:</h4>
<p>ip: {{checkProxyResult.ip}}</p>
<p>ip_decimal: {{checkProxyResult.ip_decimal}}</p>
<p>country: {{checkProxyResult.country}}</p>
<p>city: {{checkProxyResult.city || "N/A"}}</p>
<p>hostname: {{checkProxyResult.hostname || "N/A"}}</p>
</div>
<p>Clicking "TEST PROXY" button will send a request to https://ifconfig.co/json</p>
<div v-on:click='checkProxy' class='center settingsButton'>
{{proxyTestButtonText}}
</div>
</div>
<br />
<br />
<div class='center'>
<div onclick='importSubscriptions()' class='settingsButton'>
IMPORT SUBSCRIPTIONS