diff options
| author | Hygna <hygna@proton.me> | 2022-10-04 19:00:06 +0100 |
|---|---|---|
| committer | Hygna <hygna@proton.me> | 2022-10-04 19:00:06 +0100 |
| commit | aa408a4c9b3fd61d355328490e20048f77d0c647 (patch) | |
| tree | 841ec358fbab402b625b860d83432b10e2a1d32a /src/assets/javascripts/services.js | |
| parent | updated instances (diff) | |
| parent | Display if server is not found, made images in settings clickable (diff) | |
| download | libredirect-aa408a4c9b3fd61d355328490e20048f77d0c647.zip | |
Merge branch 'optimizations'
Diffstat (limited to 'src/assets/javascripts/services.js')
| -rw-r--r-- | src/assets/javascripts/services.js | 682 |
1 files changed, 682 insertions, 0 deletions
diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js new file mode 100644 index 00000000..afd7906f --- /dev/null +++ b/src/assets/javascripts/services.js @@ -0,0 +1,682 @@ +window.browser = window.browser || window.chrome
+
+import utils from "./utils.js"
+
+let config, options, redirects
+
+function init() {
+ return new Promise(async resolve => {
+ browser.storage.local.get(["options", "redirects"], r => {
+ options = r.options
+ redirects = r.redirects
+ fetch("/config/config.json")
+ .then(response => response.text())
+ .then(configData => {
+ config = JSON.parse(configData)
+ resolve()
+ })
+ })
+ })
+}
+
+init()
+browser.storage.onChanged.addListener(init)
+
+function fetchFrontendInstanceList(service, frontend, redirects, options, config) {
+ let tmp = []
+ if (config.services[service].frontends[frontend].instanceList) {
+ for (const network in config.networks) {
+ tmp.push(...redirects[network], ...options[frontend][network].custom)
+ }
+ } else if (config.services[service].frontends[frontend].singleInstance) tmp = config.services[service].frontends[frontend].singleInstance
+ return tmp
+}
+
+function all(service, frontend, options, config, redirects) {
+ let instances = []
+ if (!frontend) {
+ for (const frontend in config.services[service].frontends) {
+ instances.push(...fetchFrontendInstanceList(service, frontend, redirects[frontend], options, config))
+ }
+ } else {
+ instances.push(...fetchFrontendInstanceList(service, frontend, redirects[frontend], options, config))
+ }
+ return instances
+}
+
+function regexArray(service, url, config) {
+ let targets
+ if (config.services[service].targets == "datajson") {
+ browser.storage.local.get("targets", r => {
+ targets = r.targets[service]
+ })
+ } else {
+ targets = config.services[service].targets
+ }
+ for (const targetString in targets) {
+ const target = new RegExp(targets[targetString])
+ if (target.test(url.href)) return true
+ }
+ return false
+}
+
+function redirect(url, type, initiator) {
+ let randomInstance
+ let frontend
+ for (const service in config.services) {
+ if (!options[service].enabled) continue
+ if (config.services[service].embeddable && type != options[service].redirectType && options[service].redirectType != "both") continue
+ if (!config.services[service].embeddable && type != "main_frame") continue
+ let targets = new RegExp(config.services[service].targets.join("|"), "i")
+
+ if (!regexArray(service, url, config)) continue
+ if (initiator) {
+ if (targets.test(initiator.host)) continue
+ if (all(service, null, options, config, redirects).includes(initiator.origin)) return "BYPASSTAB"
+ }
+
+ if (Object.keys(config.services[service].frontends).length > 1) {
+ if (type == "sub_frame" && config.services[service].embeddable && !config.services[service].frontends[options[service].frontend].embeddable) frontend = options[service].embedFrontend
+ else frontend = options[service].frontend
+ } else frontend = Object.keys(config.services[service].frontends)[0]
+
+ if (config.services[service].frontends[frontend].instanceList) {
+ let instanceList = [...options[frontend][options.network].enabled, ...options[frontend][options.network].custom]
+ if (instanceList.length === 0 && options.networkFallback) instanceList = [...options[frontend].clearnet.enabled, ...options[frontend].clearnet.custom]
+ if (instanceList.length === 0) return
+ randomInstance = utils.getRandomInstance(instanceList)
+ } else if (config.services[service].frontends[frontend].singleInstance) randomInstance = config.services[service].frontends[frontend].singleInstance
+ break
+ }
+ if (!frontend) return
+
+ // Here is a (temperory) space for defining constants required in 2 or more switch cases.
+ // When possible, try have the two switch cases share all their code as done with searx and searxng.
+ // Do not do that when they do not share 100% of their code.
+
+ const mapCentreRegex = /@(-?\d[0-9.]*),(-?\d[0-9.]*),(\d{1,2})[.z]/
+ const dataLatLngRegex = /!3d(-?[0-9]{1,}.[0-9]{1,})!4d(-?[0-9]{1,}.[0-9]{1,})/
+ const placeRegex = /\/place\/(.*)\//
+ function convertMapCentre() {
+ let [lat, lon, zoom] = [null, null, null]
+ if (url.pathname.match(mapCentreRegex)) {
+ // Set map centre if present
+ ;[lat, lon, zoom] = url.pathname.match(mapCentreRegex)
+ } else if (url.searchParams.has("center")) {
+ ;[lat, lon] = url.searchParams.get("center").split(",")
+ zoom = url.searchParams.get("zoom") ?? "17"
+ }
+ return [zoom, lon, lat]
+ }
+
+ switch (frontend) {
+ // This is where all instance-specific code must be ran to convert the service url to one that can be understood by the frontend.
+ case "beatbump":
+ return `${randomInstance}${url.pathname}${url.search}`
+ .replace("/watch?v=", "/listen?id=")
+ .replace("/channel/", "/artist/")
+ .replace("/playlist?list=", "/playlist/VL")
+ .replace(/\/search\?q=.*/, searchQuery => searchQuery.replace("?q=", "/") + "?filter=all")
+ case "hyperpipe":
+ return `${randomInstance}${url.pathname}${url.search}`.replace(/\/search\?q=.*/, searchQuery => searchQuery.replace("?q=", "/"))
+ case "bibliogram":
+ const reservedPaths = ["u", "p", "privacy"]
+ if (url.pathname === "/" || reservedPaths.includes(url.pathname.split("/")[1])) return `${randomInstance}${url.pathname}${url.search}`
+ if (url.pathname.startsWith("/reel") || url.pathname.startsWith("/tv")) return `${randomInstance}/p${url.pathname.replace(/\/reel|\/tv/i, "")}${url.search}`
+ else return `${randomInstance}/u${url.pathname}${url.search}` // Likely a user profile, redirect to '/u/...'
+ case "lbryDesktop":
+ return url.href.replace(/^https?:\/{2}odysee\.com\//, "lbry://").replace(/:(?=[a-zA-Z0-9])/g, "#")
+ case "neuters":
+ if (url.pathname.startsWith("/article/") || url.pathname.startsWith("/pf/") || url.pathname.startsWith("/arc/") || url.pathname.startsWith("/resizer/")) return null
+ else if (url.pathname.endsWith("/")) return `${randomInstance}${url.pathname}`
+ else return `${randomInstance}${url.pathname}/`
+ case "searx":
+ case "searxng":
+ return `${randomInstance}/?q=${encodeURIComponent(url.searchParams.get("q"))}`
+ case "whoogle":
+ return `${randomInstance}/search${encodeURIComponent(url.searchParams.get("q"))}`
+ case "librex":
+ return `${randomInstance}/search.php?q=${encodeURIComponent(url.searchParams.get("q"))}`
+ case "send":
+ return randomInstance
+ case "nitter":
+ if (url.host.split(".")[0] === "pbs" || url.host.split(".")[0] === "video") {
+ const [, id, format, extra] = url.search.match(/(.*)\?format=(.*)&(.*)/)
+ const query = encodeURIComponent(`${id}.${format}?${extra}`)
+ return `${randomInstance}/pic${url.pathname}${query}`
+ } else if (url.pathname.split("/").includes("tweets")) return `${randomInstance}${url.pathname.replace("/tweets", "")}${url.search}`
+ else if (url.host == "t.co") return `${randomInstance}/t.co${url.pathname}`
+ else return `${randomInstance}${url.pathname}${url.search}`
+ case "yattee":
+ return url.href.replace(/^https?:\/{2}/, "yattee://")
+ case "freetube":
+ return `freetube://https://youtu.be${url.pathname}${url.search}`.replace(/watch\?v=/, "")
+ case "simplyTranslate":
+ return `${randomInstance}/${url.search}`
+ case "osm": {
+ if (initiator && initiator.host === "earth.google.com") return
+ const travelModes = {
+ driving: "fossgis_osrm_car",
+ walking: "fossgis_osrm_foot",
+ bicycling: "fossgis_osrm_bike",
+ transit: "fossgis_osrm_car", // not implemented on OSM, default to car.
+ }
+
+ function addressToLatLng(address) {
+ const xmlhttp = new XMLHttpRequest()
+ xmlhttp.open("GET", `https://nominatim.openstreetmap.org/search/${address}?format=json&limit=1`, false)
+ xmlhttp.send()
+ if (xmlhttp.status === 200) {
+ const json = JSON.parse(xmlhttp.responseText)[0]
+ if (json) {
+ console.log("json", json)
+ return [`${json.lat},${json.lon}`, `${json.boundingbox[2]},${json.boundingbox[1]},${json.boundingbox[3]},${json.boundingbox[0]}`]
+ }
+ }
+ console.info("Error: Status is " + xmlhttp.status)
+ }
+
+ let mapCentre = "#"
+ let prefs = {}
+
+ const mapCentreData = convertMapCentre()
+ if (mapCentreData[0] && mapCentreData[1] && mapCentreData[2]) mapCentre = `#map=${mapCentreData[0]}/${mapCentreData[1]}/${mapCentreData[2]}`
+ if (url.searchParams.get("layer")) prefs.layers = osmLayers[url.searchParams.get("layer")]
+
+ if (url.pathname.includes("/embed")) {
+ // Handle Google Maps Embed API
+ // https://www.google.com/maps/embed/v1/place?key=AIzaSyD4iE2xVSpkLLOXoyqT-RuPwURN3ddScAI&q=Eiffel+Tower,Paris+France
+ //console.log("embed life")
+
+ let query = ""
+ if (url.searchParams.has("q")) query = url.searchParams.get("q")
+ else if (url.searchParams.has("query")) query = url.searchParams.has("query")
+ else if (url.searchParams.has("pb"))
+ try {
+ query = url.searchParams.get("pb").split(/!2s(.*?)!/)[1]
+ } catch (error) {
+ console.error(error)
+ } // Unable to find map marker in URL.
+
+ let [coords, boundingbox] = addressToLatLng(query)
+ prefs.bbox = boundingbox
+ prefs.marker = coords
+ prefs.layer = "mapnik"
+ let prefsEncoded = new URLSearchParams(prefs).toString()
+ return `${randomInstance}/export/embed.html?${prefsEncoded}`
+ } else if (url.pathname.includes("/dir")) {
+ // Handle Google Maps Directions
+ // https://www.google.com/maps/dir/?api=1&origin=Space+Needle+Seattle+WA&destination=Pike+Place+Market+Seattle+WA&travelmode=bicycling
+
+ let travMod = url.searchParams.get("travelmode")
+ if (url.searchParams.has("travelmode")) prefs.engine = travelModes[travMod]
+
+ let orgVal = url.searchParams.get("origin")
+ let destVal = url.searchParams.get("destination")
+
+ let org = addressToLatLng(orgVal)
+ let dest = addressToLatLng(destVal)
+ prefs.route = `${org};${dest}`
+
+ let prefsEncoded = new URLSearchParams(prefs).toString()
+ return `${randomInstance}/directions?${prefsEncoded}${mapCentre}`
+ } else if (url.pathname.includes("data=") && url.pathname.match(dataLatLngRegex)) {
+ // Get marker from data attribute
+ // https://www.google.com/maps/place/41%C2%B001'58.2%22N+40%C2%B029'18.2%22E/@41.032833,40.4862063,17z/data=!3m1!4b1!4m6!3m5!1s0x0:0xf64286eaf72fc49d!7e2!8m2!3d41.0328329!4d40.4883948
+ //console.log("data life")
+
+ let [, mlat, mlon] = url.pathname.match(dataLatLngRegex)
+
+ return `${randomInstance}/search?query=${mlat}%2C${mlon}`
+ } else if (url.searchParams.has("ll")) {
+ // Get marker from ll param
+ // https://maps.google.com/?ll=38.882147,-76.99017
+ //console.log("ll life")
+
+ const [mlat, mlon] = url.searchParams.get("ll").split(",")
+
+ return `${randomInstance}/search?query=${mlat}%2C${mlon}`
+ } else if (url.searchParams.has("viewpoint")) {
+ // Get marker from viewpoint param.
+ // https://www.google.com/maps/@?api=1&map_action=pano&viewpoint=48.857832,2.295226&heading=-45&pitch=38&fov=80
+ //console.log("viewpoint life")
+
+ const [mlat, mlon] = url.searchParams.get("viewpoint").split(",")
+
+ return `${randomInstance}/search?query=${mlat}%2C${mlon}`
+ } else {
+ // Use query as search if present.
+ //console.log("normal life")
+
+ let query
+ if (url.searchParams.has("q")) query = url.searchParams.get("q")
+ else if (url.searchParams.has("query")) query = url.searchParams.get("query")
+ else if (url.pathname.match(placeRegex)) query = url.pathname.match(placeRegex)[1]
+
+ let prefsEncoded = new URLSearchParams(prefs).toString()
+ if (query) return `${randomInstance}/search?query="${query}${mapCentre}&${prefsEncoded}`
+ }
+
+ let prefsEncoded = new URLSearchParams(prefs).toString()
+ console.log("mapCentre", mapCentre)
+ console.log("prefs", prefs)
+ console.log("prefsEncoded", prefsEncoded)
+ return `${randomInstance}/${mapCentre}&${prefsEncoded}`
+ }
+ case "facil": {
+ if (initiator && initiator.host === "earth.google.com") return
+ const travelModes = {
+ driving: "car",
+ walking: "pedestrian",
+ bicycling: "bicycle",
+ transit: "car", // not implemented on Facil, default to car.
+ }
+ const mapCentreData = convertMapCentre()
+ let mapCentre = "#"
+ if (mapCentreData[0] && mapCentreData[1] && mapCentreData[2]) mapCentre = `#${mapCentreData[0]}/${mapCentreData[1]}/${mapCentreData[2]}`
+
+ if (url.pathname.includes("/embed")) {
+ // Handle Google Maps Embed API
+ // https://www.google.com/maps/embed/v1/place?key=AIzaSyD4iE2xVSpkLLOXoyqT-RuPwURN3ddScAI&q=Eiffel+Tower,Paris+France
+ //console.log("embed life")
+
+ let query = ""
+ if (url.searchParams.has("q")) query = url.searchParams.get("q")
+ else if (url.searchParams.has("query")) query = url.searchParams.has("query")
+ else if (url.searchParams.has("pb"))
+ try {
+ query = url.searchParams.get("pb").split(/!2s(.*?)!/)[1]
+ } catch (error) {
+ console.error(error)
+ } // Unable to find map marker in URL.
+
+ return `${randomInstance}/#q=${query}`
+ } else if (url.pathname.includes("/dir")) {
+ // Handle Google Maps Directions
+ // https://www.google.com/maps/dir/?api=1&origin=Space+Needle+Seattle+WA&destination=Pike+Place+Market+Seattle+WA&travelmode=bicycling
+
+ let travMod = url.searchParams.get("travelmode")
+
+ let orgVal = url.searchParams.get("origin")
+ let destVal = url.searchParams.get("destination")
+
+ return `${randomInstance}/#q=${orgVal}%20to%20${destVal}%20by%20${travelModes[travMod]}`
+ } else if (url.pathname.includes("data=") && url.pathname.match(dataLatLngRegex)) {
+ // Get marker from data attribute
+ // https://www.google.com/maps/place/41%C2%B001'58.2%22N+40%C2%B029'18.2%22E/@41.032833,40.4862063,17z/data=!3m1!4b1!4m6!3m5!1s0x0:0xf64286eaf72fc49d!7e2!8m2!3d41.0328329!4d40.4883948
+ //console.log("data life")
+
+ let [, mlat, mlon] = url.pathname.match(dataLatLngRegex)
+
+ return `${randomInstance}/#q=${mlat}%2C${mlon}`
+ } else if (url.searchParams.has("ll")) {
+ // Get marker from ll param
+ // https://maps.google.com/?ll=38.882147,-76.99017
+ //console.log("ll life")
+
+ const [mlat, mlon] = url.searchParams.get("ll").split(",")
+
+ return `${randomInstance}/#q=${mlat}%2C${mlon}`
+ } else if (url.searchParams.has("viewpoint")) {
+ // Get marker from viewpoint param.
+ // https://www.google.com/maps/@?api=1&map_action=pano&viewpoint=48.857832,2.295226&heading=-45&pitch=38&fov=80
+ //console.log("viewpoint life")
+
+ const [mlat, mlon] = url.searchParams.get("viewpoint").split(",")
+
+ return `${randomInstance}/#q=${mlat}%2C${mlon}`
+ } else {
+ // Use query as search if present.
+ //console.log("normal life")
+
+ let query
+ if (url.searchParams.has("q")) query = url.searchParams.get("q")
+ else if (url.searchParams.has("query")) query = url.searchParams.get("query")
+ else if (url.pathname.match(placeRegex)) query = url.pathname.match(placeRegex)[1]
+
+ if (query) return `${randomInstance}/${mapCentre}/Mpnk/${query}`
+ }
+ }
+ case "wikiless":
+ let GETArguments = []
+ if (url.search.length > 0) {
+ let search = url.search.substring(1) //get rid of '?'
+ let argstrings = search.split("&")
+ for (let i = 0; i < argstrings.length; i++) {
+ let args = argstrings[i].split("=")
+ GETArguments.push([args[0], args[1]])
+ }
+ }
+
+ let link = `${randomInstance}${url.pathname}`
+ let urlSplit = url.host.split(".")
+ if (urlSplit[0] != "wikipedia" && urlSplit[0] != "www") {
+ if (urlSplit[0] == "m") GETArguments.push(["mobileaction", "toggle_view_mobile"])
+ else GETArguments.push(["lang", urlSplit[0]])
+ if (urlSplit[1] == "m") GETArguments.push(["mobileaction", "toggle_view_mobile"])
+ // wikiless doesn't have mobile view support yet
+ }
+ for (let i = 0; i < GETArguments.length; i++) link += (i == 0 ? "?" : "&") + GETArguments[i][0] + "=" + GETArguments[i][1]
+ return link
+
+ case "lingva":
+ let params_arr = url.search.split("&")
+ params_arr[0] = params_arr[0].substring(1)
+ let params = {}
+ for (let i = 0; i < params_arr.length; i++) {
+ let pair = params_arr[i].split("=")
+ params[pair[0]] = pair[1]
+ }
+ if (params.sl && params.tl && params.text) {
+ return `${randomInstance}/${params.sl}/${params.tl}/${params.text}`
+ }
+ return randomInstance
+ default:
+ return `${randomInstance}${url.pathname}${url.search}`
+ }
+}
+
+function computeService(url, returnFrontend) {
+ return new Promise(resolve => {
+ fetch("/config/config.json")
+ .then(response => response.text())
+ .then(configData => {
+ const config = JSON.parse(configData)
+ browser.storage.local.get(["redirects", "options"], r => {
+ const redirects = r.redirects
+ const options = r.options
+ for (const service in config.services) {
+ if (regexArray(service, url, config)) {
+ if (returnFrontend) {
+ resolve([service, null])
+ } else {
+ resolve(service)
+ }
+ return
+ } else {
+ for (const frontend in config.services[service].frontends) {
+ if (all(service, frontend, options, config, redirects).includes(utils.protocolHost(url))) {
+ if (returnFrontend) {
+ resolve([service, frontend])
+ } else {
+ resolve(service)
+ }
+ return
+ }
+ }
+ }
+ }
+ resolve()
+ })
+ })
+ })
+}
+
+function switchInstance(url) {
+ return new Promise(async resolve => {
+ await init()
+ const protocolHost = utils.protocolHost(url)
+ for (const service in config.services) {
+ if (!all(service, null, options, config, redirects).includes(protocolHost)) continue
+
+ let instancesList = [...options[options[service].frontend][options.network].enabled, ...options[options[service].frontend][options.network].custom]
+ if (instancesList.length === 0 && options.networkFallback) instancesList = [...options[options[service].frontend].clearnet.enabled, ...options[options[service].frontend].clearnet.custom]
+
+ let oldInstance
+ const i = instancesList.indexOf(protocolHost)
+ if (i > -1) {
+ oldInstance = instancesList[i]
+ instancesList.splice(i, 1)
+ }
+ if (instancesList.length === 0) {
+ resolve()
+ return
+ }
+ 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))
+ return
+ }
+ resolve()
+ })
+}
+
+function reverse(url) {
+ return new Promise(async resolve => {
+ await init()
+ let protocolHost = utils.protocolHost(url)
+ for (const service in config.services) {
+ if (!all(service, null, options, config, redirects).includes(protocolHost)) continue
+
+ switch (service) {
+ case "instagram":
+ if (url.pathname.startsWith("/p")) resolve(`https://instagram.com${url.pathname.replace("/p", "")}${url.search}`)
+ if (url.pathname.startsWith("/u")) resolve(`https://instagram.com${url.pathname.replace("/u", "")}${url.search}`)
+ resolve(config.services[service].url + url.pathname + url.search)
+ return
+ case "youtube":
+ case "imdb":
+ case "imgur":
+ case "tiktok":
+ case "twitter":
+ case "reddit":
+ resolve(config.services[service].url + url.pathname + url.search)
+ return
+ default:
+ resolve()
+ return
+ }
+ }
+ resolve()
+ })
+}
+
+function unifyPreferences(url, tabId) {
+ return new Promise(async resolve => {
+ await init()
+ const protocolHost = utils.protocolHost(url)
+ for (const service in config.services) {
+ for (const frontend in config.services[service].frontends) {
+ if (all(service, frontend, options, config, redirects).includes(protocolHost)) {
+ let instancesList = [...options[frontend][options.network].enabled, ...options[frontend][options.network].custom]
+ if (options.networkFallback && options.network != "clearnet") instancesList.push(...options[frontend].clearnet.enabled, ...options[frontend].clearnet.custom)
+
+ const frontendObject = config.services[service].frontends[frontend]
+ if ("cookies" in frontendObject.preferences) {
+ for (const cookie of frontendObject.preferences.cookies) {
+ utils.copyCookie(frontendObject, url, instancesList, cookie)
+ }
+ }
+ if ("localstorage" in frontendObject.preferences) {
+ browser.storage.local.set({ tmp: [frontend, frontendObject.preferences.localstorage] })
+ browser.tabs.executeScript(tabId, {
+ file: "/assets/javascripts/get-localstorage.js",
+ runAt: "document_start",
+ })
+ for (const instance of instancesList)
+ browser.tabs.create({ url: instance }, tab =>
+ browser.tabs.executeScript(tab.id, {
+ file: "/assets/javascripts/set-localstorage.js",
+ runAt: "document_start",
+ })
+ )
+ }
+ /*
+ if ("indexeddb" in frontendObject.preferences) {
+ }
+ if ("token" in frontendObject.preferences) {
+ }
+ */
+ resolve(true)
+ return
+ }
+ }
+ }
+ })
+}
+
+async function setRedirects(redirects) {
+ fetch("/config/config.json")
+ .then(response => response.text())
+ .then(configData => {
+ //browser.storage.local.get(["options", "blacklists"], async r => {
+ //const options = r.options
+ const config = JSON.parse(configData)
+ let targets = {}
+ for (const service in config.services) {
+ if (config.services[service].targets == "datajson") {
+ targets[service] = redirects[service]
+ }
+ /*
+ for (const frontend in config.services[service].frontends) {
+ if (config.services[service].frontends[frontend].instanceList) {
+ for (const network in config.networks) {
+ options[frontend][network].enabled = redirects[frontend][network]
+ }
+ for (const blacklist in r.blacklists) {
+ for (const instance of blacklist) {
+ let i = options[frontend].clearnet.enabled.indexOf(instance)
+ if (i > -1) options[frontend].clearnet.enabled.splice(i, 1)
+ }
+ }
+ }
+ }
+ */
+ // The above will be implemented with https://github.com/libredirect/libredirect/issues/334
+ }
+ browser.storage.local.set({ redirects, targets /*, options*/ })
+ //})
+ })
+}
+
+function initDefaults() {
+ return new Promise(resolve => {
+ fetch("/instances/data.json")
+ .then(response => response.text())
+ .then(data => {
+ fetch("/config/config.json")
+ .then(response => response.text())
+ .then(configData => {
+ browser.storage.local.get(["options", "blacklists"], r => {
+ let redirects = JSON.parse(data)
+ let options = r.options
+ let targets = {}
+ let config = JSON.parse(configData)
+ const localstorage = {}
+ const latency = {}
+ for (const service in config.services) {
+ options[service] = {}
+ if (config.services[service].targets == "datajson") {
+ targets[service] = redirects[service]
+ }
+ for (const defaultOption in config.services[service].options) {
+ options[service][defaultOption] = config.services[service].options[defaultOption]
+ }
+ for (const frontend in config.services[service].frontends) {
+ if (config.services[service].frontends[frontend].instanceList) {
+ options[frontend] = {}
+ for (const network in config.networks) {
+ options[frontend][network] = {}
+ options[frontend][network].enabled = JSON.parse(data)[frontend][network]
+ options[frontend][network].custom = []
+ }
+ for (const blacklist in r.blacklists) {
+ for (const instance of r.blacklists[blacklist]) {
+ let i = options[frontend].clearnet.enabled.indexOf(instance)
+ if (i > -1) options[frontend].clearnet.enabled.splice(i, 1)
+ }
+ }
+ }
+ }
+ }
+ browser.storage.local.set({ redirects, options, targets, latency, localstorage })
+ resolve()
+ })
+ })
+ })
+ })
+}
+
+function upgradeOptions() {
+ return new Promise(resolve => {
+ fetch("/config/config.json")
+ .then(response => response.text())
+ .then(configData => {
+ browser.storage.local.get(null, r => {
+ let options = r.options
+ let latency = {}
+ const config = JSON.parse(configData)
+ options.exceptions = r.exceptions
+ if (r.theme != "DEFAULT") options.theme = r.theme
+ options.popupServices = r.popupFrontends
+ let tmp = options.popupServices.indexOf("tikTok")
+ if (tmp > -1) {
+ options.popupServices.splice(tmp, 1)
+ options.popupServices.push("tiktok")
+ }
+ tmp = options.popupServices.indexOf("sendTarget")
+ if (tmp > -1) {
+ options.popupServices.splice(tmp, 1)
+ options.popupServices.push("sendFiles")
+ }
+ options.firstPartyIsolate = r.firstPartyIsolate
+ options.autoRedirect = r.autoRedirect
+ switch (r.onlyEmbeddedVideo) {
+ case "onlyNotEmbedded":
+ options.youtube.redirectType = "main_frame"
+ case "onlyEmbedded":
+ options.youtube.redirectType = "sub_frame"
+ case "both":
+ options.youtube.redirectType = "both"
+ }
+ for (const service in config.services) {
+ let oldService
+ switch (service) {
+ case "tiktok":
+ oldService = "tikTok"
+ break
+ case "sendFiles":
+ oldService = "sendTarget"
+ break
+ default:
+ oldService = service
+ }
+ options[service].enabled = !r["disable" + utils.camelCase(oldService)]
+ if (r[oldService + "Frontend"]) {
+ if (r[oldService + "Frontend"] == "yatte") options[service].frontend = "yattee"
+ else options[service].frontend = r[oldService + "Frontend"]
+ }
+ if (r[oldService + "RedirectType"]) options[service].redirectType = r[oldService + "RedirectType"]
+ if (r[oldService + "EmbedFrontend"] && (service != "youtube" || r[oldService + "EmbedFrontend"] == "invidious" || r[oldService + "EmbedFrontend"] == "piped"))
+ options[service].embedFrontend = r[oldService + "EmbedFrontend"]
+ for (const frontend in config.services[service].frontends) {
+ if (r[frontend + "Latency"]) latency[frontend] = r[frontend + "Latency"]
+ for (const network in config.networks) {
+ let protocol
+ if (network == "clearnet") protocol = "normal"
+ else protocol = network
+ if (r[frontend + utils.camelCase(protocol) + "RedirectsChecks"]) {
+ options[frontend][network].enabled = r[frontend + utils.camelCase(protocol) + "RedirectsChecks"]
+ options[frontend][network].custom = r[frontend + utils.camelCase(protocol) + "CustomRedirects"]
+ }
+ }
+ }
+ }
+ browser.storage.local.set({ options, latency }, () => resolve())
+ })
+ })
+ })
+}
+
+export default {
+ redirect,
+ computeService,
+ switchInstance,
+ reverse,
+ unifyPreferences,
+ setRedirects,
+ initDefaults,
+ upgradeOptions,
+}
|
