diff --git a/README.md b/README.md index d61df1d..7161a18 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ npm update npm install ``` -Generate the HTML pages: +Generate the HTML pages (you should install [pug-cli](https://www.npmjs.com/package/pug-cli) first globally): ``` npm run pug @@ -87,24 +87,23 @@ npm run start ### Install temporarily -1. open `about:addons` -2. type in the address bar `about:debugging` -3. press `load temporarily addon` +1. Type in the address bar: `about:debugging#/runtime/this-firefox` +3. Press `Load Temporary Add-on...` ### Install in Firefox ESR, Developer Edition, Nightly -1. open `about:config` -2. set `xpinstall.signatures.required` to `false` -3. open `about:addons` -4. click on the gear shaped `settings` button and select `Install Add-on From File...` -5. select `libredirect-VERSION.zip` from `web-ext-artifacts` folder +1. Type in the address bar: `about:config` +2. Set `xpinstall.signatures.required` to `false` +3. Type in the address bar: `about:addons` +4. Click on the gear shaped `settings` button and select `Install Add-on From File...` +5. Select `libredirect-VERSION.zip` from `web-ext-artifacts` folder ### Install in Chromium browsers -1. open `chrome://extensions` -2. enable `dev mode` -3. select `load unpacked extension` -4. select `src` folder +1. Open `chrome://extensions` +2. Enable `dev mode` +3. Select `load unpacked extension` +4. Select `src` folder --- diff --git a/src/assets/javascripts/general.js b/src/assets/javascripts/general.js index 0295eb0..592f604 100644 --- a/src/assets/javascripts/general.js +++ b/src/assets/javascripts/general.js @@ -7,7 +7,7 @@ window.browser = window.browser || window.chrome let exceptions function isException(url) { - for (const item of exceptions.url) if (item == `${url.protocol}//${url.host}`) return true + for (const item of exceptions.url) if (item == url.href) return true for (const item of exceptions.regex) if (new RegExp(item).test(url.href)) return true return false } diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 181dec0..6a7751d 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -31,10 +31,11 @@ function all(service, frontend, options, config) { function regexArray(service, url, config, frontend) { let targetList = config.services[service].targets - if (frontend && config.services[service].frontends[frontend].excludeTargets) - for (const i in config.services[service].frontends[frontend].excludeTargets) { - targetList = targetList.splice(i, 1) - } + if (frontend && config.services[service].frontends[frontend].excludeTargets) { + targetList = targetList.filter(val => + !config.services[service].frontends[frontend].excludeTargets.includes(targetList.indexOf(val)) + ) + } for (const targetString in targetList) { const target = new RegExp(targetList[targetString]) if (target.test(url.href)) return true @@ -42,7 +43,7 @@ function regexArray(service, url, config, frontend) { return false } -function redirect(url, type, initiator, forceRedirection, tabId) { +function redirect(url, type, initiator, forceRedirection) { if (type != "main_frame" && type != "sub_frame" && type != "image") return let randomInstance let frontend @@ -62,6 +63,8 @@ function redirect(url, type, initiator, forceRedirection, tabId) { for (const network in options[frontend]) { instanceList.push(...options[frontend]) } + + console.log(frontend, instanceList) if (instanceList.length === 0) return randomInstance = utils.getRandomInstance(instanceList) @@ -396,9 +399,11 @@ function computeService(url, returnFrontend) { return } else { for (const frontend in config.services[service].frontends) { - if (all(service, frontend, options, config).includes(utils.protocolHost(url))) { - if (returnFrontend) resolve([service, frontend, utils.protocolHost(url)]) - else resolve(service) + if (all(service, frontend, options, config).some(val => val.includes(utils.protocolHost(url)))) { + if (returnFrontend) + resolve([service, frontend, utils.protocolHost(url)]) + else + resolve(service) return } } @@ -413,36 +418,30 @@ function _switchInstance(url) { await init() const protocolHost = utils.protocolHost(url) for (const service in config.services) { - if (!all(service, null, options, config).includes(protocolHost)) continue + if (!all(service, undefined, options, config).some(val => val.includes(protocolHost))) continue let instancesList = [] - if (Object.keys(config.services[service].frontends).length == 1) { - const frontend = Object.keys(config.services[service].frontends)[0] - for (const network in options[frontend]) { - instancesList.push(...options[frontend]) - } - } else { - const frontend = options[service].frontend - for (const network in options[frontend]) { - instancesList.push(...options[frontend]) - } - } + let frontend + if (!options[service].frontend) + frontend = Object.keys(config.services[service].frontends)[0] + else + frontend = options[service].frontend + + instancesList = [...options[frontend]] let oldInstance const i = instancesList.indexOf(protocolHost) if (i > -1) { - oldInstance = instancesList[i] instancesList.splice(i, 1) } if (instancesList.length === 0) { resolve() return } + console.log(instancesList) const randomInstance = utils.getRandomInstance(instancesList) - const oldUrl = `${oldInstance}${url.pathname}${url.search} ` - // This is to make instance switching work when the instance depends on the pathname, eg https://darmarit.org/searx - // Doesn't work because of .includes array method, not a top priotiry atm - resolve(oldUrl.replace(oldInstance, randomInstance)) + const newUrl = `${randomInstance}${url.pathname}${url.search}` + resolve(newUrl) return } resolve() @@ -452,11 +451,12 @@ function _switchInstance(url) { function reverse(url, urlString) { return new Promise(async resolve => { await init() + url = new URL(url) let protocolHost - if (!urlString) protocolHost = utils.protocolHost(url) - else protocolHost = url.match(/^https?:\/{2}/)[0] + protocolHost = utils.protocolHost(url) + for (const service in config.services) { - if (!all(service, null, options, config).includes(protocolHost)) continue + if (!all(service, undefined, options, config).some(val => val.includes(protocolHost))) continue switch (service) { case "youtube": @@ -468,6 +468,8 @@ function reverse(url, urlString) { case "imdb": case "quora": case "medium": + resolve(config.services[service].url + url.pathname + url.search) + return case "fandom": let regex = url.pathname.match(/^\/([a-zA-Z0-9-]+)\/wiki\/([a-zA-Z0-9-]+)/) if (regex) { @@ -482,6 +484,7 @@ function reverse(url, urlString) { } } resolve() + return }) } @@ -508,6 +511,30 @@ function initDefaults() { options['theme'] = "detect" options['popupServices'] = ["youtube", "twitter", "tiktok", "imgur", "reddit", "quora", "translate", "maps"] + options['invidious'] = ['https://inv.vern.cc/'] + options['piped'] = ['https://piped.video'] + options['pipedMaterial'] = ['https://piped-material.xn--17b.net'] + options['cloudtube'] = ['https://tube.cadence.moe'] + options['proxitok'] = ['https://proxitok.pabloferreiro.es'] + options['send'] = ['https://send.vis.ee'] + options['nitter'] = ['https://nitter.net'] + options['libreddit'] = ['https://libreddit.spike.codes'] + options['teddit'] = ['https://teddit.net'] + options['scribe'] = ['https://scribe.rip'] + options['quetre'] = ['https://quetre.iket.me'] + options['libremdb'] = ['https://libremdb.iket.me'] + options['simplytranslate'] = ['https://simplytranslate.org'] + options['linvgatranslate'] = ['https://lingva.ml'] + options['searxng'] = ['https://sx.vern.cc/'] + options['rimgo'] = ['https://rimgo.vern.cc'] + options['librarian'] = ['https://lbry.vern.cc'] + options['beatbump'] = ['https://beatbump.ml'] + options['hyperpipe'] = ['https://hyperpipe.surge.sh'] + options['facil'] = [' https://facilmap.org '] + options['osm'] = ['https://www.openstreetmap.org'] + options['breezeWiki'] = ['https://breezewiki.com'] + + browser.storage.local.set({ options }, () => resolve() ) @@ -663,7 +690,7 @@ function copyRaw(test, copyRawElement) { }) } -function switchInstance(test) { +function switchInstance() { return new Promise(resolve => { browser.tabs.query({ active: true, currentWindow: true }, async tabs => { let currTab = tabs[0] @@ -676,11 +703,7 @@ function switchInstance(test) { return } const newUrl = await _switchInstance(url) - - if (newUrl) { - if (!test) browser.tabs.update({ url: newUrl }) - resolve(true) - } else resolve() + resolve(newUrl) } }) }) diff --git a/src/config.json b/src/config.json index 7163113..b457db9 100644 --- a/src/config.json +++ b/src/config.json @@ -28,8 +28,8 @@ }, "piped": { "excludeTargets": [ - 1, - 2 + 2, + 3 ], "name": "Piped", "embeddable": true, @@ -38,8 +38,8 @@ }, "pipedMaterial": { "excludeTargets": [ - 1, - 2 + 2, + 3 ], "name": "Piped-Material", "embeddable": false, @@ -54,8 +54,8 @@ }, "freetube": { "excludeTargets": [ - 1, - 2 + 2, + 3 ], "name": "FreeTube", "embeddable": false, @@ -64,8 +64,8 @@ }, "yattee": { "excludeTargets": [ - 1, - 2 + 2, + 3 ], "name": "Yattee", "embeddable": false, diff --git a/src/pages/background/background.js b/src/pages/background/background.js index 5c6ec52..dbc788f 100644 --- a/src/pages/background/background.js +++ b/src/pages/background/background.js @@ -18,8 +18,8 @@ browser.runtime.onInstalled.addListener(async details => { await servicesHelper.upgradeOptions() // await servicesHelper.processUpdate() } + browser.runtime.openOptionsPage() } - browser.runtime.openOptionsPage() }) let tabIdRedirects = {} @@ -41,7 +41,12 @@ browser.webRequest.onBeforeRequest.addListener( if (details.frameAncestors && details.frameAncestors.length > 0 && generalHelper.isException(new URL(details.frameAncestors[0].url))) newUrl = null - if (generalHelper.isException(url)) newUrl = "BYPASSTAB" + if (generalHelper.isException(url)) { + if (details.type == "main_frame") + newUrl = "BYPASSTAB" + else + return null + } if (newUrl) { if (newUrl === "CANCEL") { @@ -69,8 +74,11 @@ browser.tabs.onRemoved.addListener(tabId => { } }) -browser.commands.onCommand.addListener(command => { - if (command === "switchInstance") servicesHelper.switchInstance() +browser.commands.onCommand.addListener(async command => { + if (command === "switchInstance") { + const newUrl = await servicesHelper.switchInstance() + if (newUrl) browser.tabs.update({ url: newUrl }) + } else if (command == "copyRaw") servicesHelper.copyRaw() }) @@ -92,72 +100,43 @@ browser.contextMenus.create({ contexts: ["browser_action"], }) +browser.contextMenus.create({ + id: "redirectToOriginal", + title: 'Redirect to original', + contexts: ["browser_action"], +}) + browser.contextMenus.create({ id: "redirectLink", title: browser.i18n.getMessage("redirectLink"), contexts: ["link"], }) -function handleToggleTab(tab) { - return new Promise(async resolve => { - switch (tabIdRedirects[tab.id]) { - case false: - const newUrl = await servicesHelper.reverse(tab.url, true) - if (newUrl) browser.tabs.update(tab.id, { url: newUrl }) - resolve() - return - case true: - browser.tabs.reload(tab.id) - resolve() - return - } - }) -} - browser.contextMenus.onClicked.addListener((info, tab) => { return new Promise(async resolve => { - switch (info.menuItemId) { - case "switchInstance": - servicesHelper.switchInstance() - resolve() - return - case "settings": - browser.runtime.openOptionsPage() - resolve() - return - case "copyRaw": - servicesHelper.copyRaw() - resolve() - return - case "toggleTab": - if (tabIdRedirects[tab.id] != undefined) { - tabIdRedirects[tab.id] = !tabIdRedirects[tab.id] - await handleToggleTab(tab) - resolve() - return - } else { - const url = new URL(tab.url) - const service = await servicesHelper.computeService(url) - if (service) { - if ((await utils.getOptions())[service].enabled) tabIdRedirects[tab.id] = false - else tabIdRedirects[tab.id] = true - await handleToggleTab(tab) - resolve() - return - } else { - tabIdRedirects[tab.id] = false - await handleToggleTab(tab) - resolve() - return - } - } - case "redirectLink": - const tmpUrl = new URL(info.linkUrl) - const newUrl = servicesHelper.redirect(tmpUrl, "main_frame", null, true) - if (newUrl) browser.tabs.create({ url: newUrl }) - resolve() - return + if (info.menuItemId == 'switchInstance') { + servicesHelper.switchInstance() } + else if (info.menuItemId == 'settings') { + browser.runtime.openOptionsPage() + } + else if (info.menuItemId == 'copyRaw') { + servicesHelper.copyRaw() + } + else if (info.menuItemId == 'redirectToOriginal') { + const newUrl = await servicesHelper.reverse(tab.url) + if (newUrl) { + tabIdRedirects[tab.id] = false + browser.tabs.update(tab.id, { url: newUrl }) + } + } + else if (info.menuItemId == 'redirectLink') { + const url = new URL(info.linkUrl) + const newUrl = servicesHelper.redirect(url, "main_frame", null, true) + if (newUrl) browser.tabs.create({ url: newUrl }) + } + resolve() + return }) }) diff --git a/src/pages/options/widgets/general.js b/src/pages/options/widgets/general.js index e89ce17..09c222a 100644 --- a/src/pages/options/widgets/general.js +++ b/src/pages/options/widgets/general.js @@ -95,25 +95,27 @@ for (const service in config.services) { }) } -!async function () { - const options = await utils.getOptions() - themeElement.value = options.theme - instanceTypeElement.addEventListener("change", event => { - instanceType = event.target.options[instanceTypeElement.selectedIndex].value - if (instanceType == "url") { - nameCustomInstanceInput.setAttribute("type", "url") - nameCustomInstanceInput.setAttribute("placeholder", "https://www.google.com") - } else if (instanceType == "regex") { - nameCustomInstanceInput.setAttribute("type", "text") - nameCustomInstanceInput.setAttribute("placeholder", "https?://(www.|)youtube.com/") - } - }) - let exceptionsCustomInstances = options.exceptions - function calcExceptionsCustomInstances() { - document.getElementById("exceptions-custom-checklist").innerHTML = [...exceptionsCustomInstances.url, ...exceptionsCustomInstances.regex] - .map( - x => `
+let options = await utils.getOptions() +themeElement.value = options.theme +for (const service in config.services) document.getElementById(service).checked = options.popupServices.includes(service) + +instanceTypeElement.addEventListener("change", event => { + instanceType = event.target.options[instanceTypeElement.selectedIndex].value + if (instanceType == "url") { + nameCustomInstanceInput.setAttribute("type", "url") + nameCustomInstanceInput.setAttribute("placeholder", "https://www.google.com") + } else if (instanceType == "regex") { + nameCustomInstanceInput.setAttribute("type", "text") + nameCustomInstanceInput.setAttribute("placeholder", "https?://(www.|)youtube.com/") + } +}) + +let exceptionsCustomInstances = options.exceptions +function calcExceptionsCustomInstances() { + document.getElementById("exceptions-custom-checklist").innerHTML = [...exceptionsCustomInstances.url, ...exceptionsCustomInstances.regex] + .map( + x => `
${x}

` - ) - .join("\n") + ) + .join("\n") - for (const x of [...exceptionsCustomInstances.url, ...exceptionsCustomInstances.regex]) { - document.getElementById(`clear-${x}`).addEventListener("click", () => { - let index - index = exceptionsCustomInstances.url.indexOf(x) - if (index > -1) exceptionsCustomInstances.url.splice(index, 1) - else { - index = exceptionsCustomInstances.regex.indexOf(x) - if (index > -1) exceptionsCustomInstances.regex.splice(index, 1) - } - options.exceptions = exceptionsCustomInstances - browser.storage.local.set({ options }) - calcExceptionsCustomInstances() - }) - } - } - calcExceptionsCustomInstances() - document.getElementById("custom-exceptions-instance-form").addEventListener("submit", event => { - event.preventDefault() - - let val - if (instanceType == "url") { - if (nameCustomInstanceInput.validity.valid) { - let url = new URL(nameCustomInstanceInput.value) - val = `${url.protocol}//${url.host}` - if (!exceptionsCustomInstances.url.includes(val)) exceptionsCustomInstances.url.push(val) + for (const x of [...exceptionsCustomInstances.url, ...exceptionsCustomInstances.regex]) { + document.getElementById(`clear-${x}`).addEventListener("click", async () => { + let index + index = exceptionsCustomInstances.url.indexOf(x) + if (index > -1) exceptionsCustomInstances.url.splice(index, 1) + else { + index = exceptionsCustomInstances.regex.indexOf(x) + if (index > -1) exceptionsCustomInstances.regex.splice(index, 1) } - } else if (instanceType == "regex") { - val = nameCustomInstanceInput.value - if (val.trim() != "" && !exceptionsCustomInstances.regex.includes(val)) exceptionsCustomInstances.regex.push(val) - } - if (val) { + options = await utils.getOptions() options.exceptions = exceptionsCustomInstances browser.storage.local.set({ options }) - nameCustomInstanceInput.value = "" - } - calcExceptionsCustomInstances() - }) + calcExceptionsCustomInstances() + }) + } +} +calcExceptionsCustomInstances() +document.getElementById("custom-exceptions-instance-form").addEventListener("submit", async event => { + event.preventDefault() - for (const service in config.services) document.getElementById(service).checked = options.popupServices.includes(service) -} \ No newline at end of file + let val + if (instanceType == "url") { + if (nameCustomInstanceInput.validity.valid) { + val = nameCustomInstanceInput.value + if (!exceptionsCustomInstances.url.includes(val)) exceptionsCustomInstances.url.push(val) + } + } else if (instanceType == "regex") { + val = nameCustomInstanceInput.value + if (val.trim() != "" && !exceptionsCustomInstances.regex.includes(val)) exceptionsCustomInstances.regex.push(val) + } + if (val) { + options = await utils.getOptions() + options.exceptions = exceptionsCustomInstances + console.log(options.exceptions) + browser.storage.local.set({ options }, () => + nameCustomInstanceInput.value = "" + ) + + } + calcExceptionsCustomInstances() +}) diff --git a/src/pages/popup/popup.js b/src/pages/popup/popup.js index 4cd59eb..56c0c3c 100644 --- a/src/pages/popup/popup.js +++ b/src/pages/popup/popup.js @@ -9,9 +9,11 @@ let config, config = await utils.getConfig() -servicesHelper.switchInstance(true).then(r => { +servicesHelper.switchInstance().then(r => { if (!r) document.getElementById("change_instance_div").style.display = "none" - else document.getElementById("change_instance").addEventListener("click", () => servicesHelper.switchInstance(false)) + else document.getElementById("change_instance").addEventListener("click", async () => { + browser.tabs.update({ url: await servicesHelper.switchInstance() }) + }) }) servicesHelper.copyRaw(true).then(r => {