From 47094ecb855266ac6fa2f5e96b8476f89e196cb0 Mon Sep 17 00:00:00 2001 From: ivan1548 <47206132+ivan1548@users.noreply.github.com> Date: Tue, 26 Feb 2019 12:45:55 -0800 Subject: [PATCH] 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 --- package-lock.json | 175 ++---------------------------------- package.json | 1 - src/js/init.js | 14 ++- src/js/layout.js | 35 +++++++- src/js/settings.js | 34 +++++++ src/js/templates.js | 33 +++++++ src/js/youtubeApi.js | 24 ++--- src/style/main.css | 13 +++ src/templates/settings.html | 27 +++++- 9 files changed, 172 insertions(+), 184 deletions(-) diff --git a/package-lock.json b/package-lock.json index 06250c9a4..58ac3669d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index 7934fb15c..c2bf0d3ab 100644 --- a/package.json +++ b/package.json @@ -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" } diff --git a/src/js/init.js b/src/js/init.js index 09b305f84..2a639b544 100644 --- a/src/js/init.js +++ b/src/js/init.js @@ -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") + }); + }); }; /** diff --git a/src/js/layout.js b/src/js/layout.js index ed2ee00fd..b78c95418 100644 --- a/src/js/layout.js +++ b/src/js/layout.js @@ -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); +} \ No newline at end of file diff --git a/src/js/settings.js b/src/js/settings.js index f2cc04ae5..fb3431212 100644 --- a/src/js/settings.js +++ b/src/js/settings.js @@ -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.'); } diff --git a/src/js/templates.js b/src/js/templates.js index 9612872ec..030be3756 100644 --- a/src/js/templates.js +++ b/src/js/templates.js @@ -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 }); diff --git a/src/js/youtubeApi.js b/src/js/youtubeApi.js index 37bb661bc..34bdca9b8 100644 --- a/src/js/youtubeApi.js +++ b/src/js/youtubeApi.js @@ -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, diff --git a/src/style/main.css b/src/style/main.css index 2c4c4cf7d..2846302e5 100644 --- a/src/style/main.css +++ b/src/style/main.css @@ -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; diff --git a/src/templates/settings.html b/src/templates/settings.html index aa91807dc..927829c4e 100644 --- a/src/templates/settings.html +++ b/src/templates/settings.html @@ -3,8 +3,6 @@
- -
@@ -43,6 +41,31 @@

+
+ + + +
+ + +
+ +
+

Your Info:

+

ip: {{checkProxyResult.ip}}

+

ip_decimal: {{checkProxyResult.ip_decimal}}

+

country: {{checkProxyResult.country}}

+

city: {{checkProxyResult.city || "N/A"}}

+

hostname: {{checkProxyResult.hostname || "N/A"}}

+
+ +

Clicking "TEST PROXY" button will send a request to https://ifconfig.co/json

+
+ {{proxyTestButtonText}} +
+
+
+
IMPORT SUBSCRIPTIONS