libredirect/src/assets/javascripts/utils.js

227 lines
4.6 KiB
JavaScript

window.browser = window.browser || window.chrome
/**
* @param {Array.<T>} instances
* @returns {T}
*/
function getRandomInstance(instances) {
return instances[~~(instances.length * Math.random())]
}
/**
* @param {string} currentInstanceUrl
* @param {Array.<T>} instances
* @returns {T}
*/
function getNextInstance(currentInstanceUrl, instances) {
const currentInstanceIndex = instances.indexOf(currentInstanceUrl);
if (currentInstanceIndex === -1){
return getRandomInstance(instances);
}
const nextInstanceIndex = (currentInstanceIndex + 1) % instances.length;
return instances[nextInstanceIndex];
}
/**
* @param {string} str
*/
function camelCase(str) {
return str.charAt(0).toUpperCase() + str.slice(1)
}
/**
* @param {URL} url
*/
function protocolHost(url) {
if (url.username && url.password) return `${url.protocol}//${url.username}:${url.password}@${url.host}`
if (url.pathname == "/TekstoLibre/" && url.host.endsWith("github.io")) // workaround
return `${url.protocol}//${url.host}${url.pathname.slice(0, -1)}`
return `${url.protocol}//${url.host}`
}
/**
* @typedef FrontendInfo
* @prop {boolean} instanceList
* @prop {string} name
* @prop {string} url
*/
/**
* @typedef {Object} Service
* @prop {Object.<string, FrontendInfo>} frontends
* @prop {Object} options
*/
/**
* @typedef {Object} Config
* @prop {Object.<string, Service>} services
*/
/**
* @returns {Promise<Config>}
*/
function getConfig() {
return new Promise(resolve => {
fetch("/config.json")
.then(response => response.text())
.then(json => {
resolve(JSON.parse(json))
return
})
})
}
/**
* @typedef {Object} Option
* @prop {string} frontend
*/
/**
* @returns {Promise<Object.<string, Option | string[]>>}
*/
function getOptions() {
return new Promise(resolve =>
browser.storage.local.get("options", r => {
resolve(r.options)
})
)
}
function getPingCache() {
return new Promise(resolve =>
browser.storage.local.get("pingCache", r => {
resolve(r.pingCache ?? {})
})
)
}
function getBlacklist(options) {
return new Promise(resolve => {
let url
if (options.fetchInstances == 'github') {
url = 'https://raw.githubusercontent.com/libredirect/instances/main/blacklist.json'
}
else if (options.fetchInstances == 'codeberg') {
url = 'https://codeberg.org/LibRedirect/instances/raw/branch/main/blacklist.json'
}
else {
resolve('disabled')
return
}
const http = new XMLHttpRequest()
http.open("GET", url, true)
http.onreadystatechange = () => {
if (http.status === 200 && http.readyState == XMLHttpRequest.DONE) {
resolve(JSON.parse(http.responseText))
return
}
}
http.onerror = () => {
resolve()
return
}
http.ontimeout = () => {
resolve()
return
}
http.send(null)
})
}
function getList(options) {
return new Promise(resolve => {
let url
if (options.fetchInstances == 'github') {
url = 'https://raw.githubusercontent.com/libredirect/instances/main/data.json'
}
else if (options.fetchInstances == 'codeberg') {
url = 'https://codeberg.org/LibRedirect/instances/raw/branch/main/data.json'
}
else {
resolve('disabled')
return
}
const http = new XMLHttpRequest()
http.open("GET", url, true)
http.onreadystatechange = () => {
if (http.status === 200 && http.readyState == XMLHttpRequest.DONE) {
resolve(JSON.parse(http.responseText))
return
}
}
http.onerror = () => {
resolve()
return
}
http.ontimeout = () => {
resolve()
return
}
http.send(null)
})
}
/**
* @param {string} href
*/
function pingOnce(href) {
return new Promise(async resolve => {
let started
let http = new XMLHttpRequest()
http.timeout = 5000
http.ontimeout = () => resolve(5000)
http.onerror = () => resolve()
http.onreadystatechange = () => {
if (http.readyState == 2) {
if (http.status == 200) {
let ended = new Date().getTime()
http.abort()
resolve(ended - started)
} else {
resolve(5000 + http.status)
}
}
}
http.open("GET", `${href}?_=${new Date().getTime()}`, true)
started = new Date().getTime()
http.send(null)
})
}
/**
* @param {string} href
*/
function ping(href) {
return new Promise(async resolve => {
let average = 0
let time
for (let i = 0; i < 3; i++) {
time = await pingOnce(href)
if (i == 0) continue
if (time >= 5000) {
resolve(time)
return
}
average += time
}
average = parseInt(average / 3)
resolve(average)
})
}
export default {
getRandomInstance,
getNextInstance,
protocolHost,
getList,
getBlacklist,
camelCase,
getConfig,
getOptions,
getPingCache,
ping,
}