hellgate/hellgate.js

132 lines
3.2 KiB
JavaScript

const { ipcMain, app, BrowserWindow } = require("electron")
const gemini = require("gemini-server")
const fs = require("fs")
const url = require("url")
const path = require("path")
const sigils_dir = "sigils"
const gemini_port = 1965
const electron_options = {
show: false,
webPreferences: {
sandbox: true,
contextIsolation: true,
nodeIntegration: false,
enableRemoteModule: false,
webgl: false,
disableDialogs: true,
preload: path.join(__dirname, "preload.js"),
},
}
const server_options = {
cert: fs.readFileSync('tls/cert.pem'),
key: fs.readFileSync('tls/key.pem')
}
const server = gemini(server_options)
async function handle_request(request, response) {
if (!request.query) {
response.data("Please supply a url in the query string.")
return
}
const target_url = decodeURIComponent(request.query)
const win = new BrowserWindow(electron_options)
const load_timeout_ms = 2000
const exec_timeout_ms = 2000
async function timeout(timeout_ms, reason = "") {
return new Promise((resolve, reject) => {
setTimeout(
reject,
timeout_ms,
reason + " timed out after " + timeout_ms + " miliseconds"
)
})
}
var error
var current_url
var page_sigil_name
var page_sigil
var data = ""
var available_sigils = fs.readdirSync(sigils_dir)
await Promise.race([
win.loadURL(target_url)
.catch((err) => { // there was an error loading the page
if (err.errno !== -3) {
error = err.message
} }),
timeout(load_timeout_ms)
]).catch(() => { // loading timed out
win.webContents.stop()
})
try {
current_url = new URL(win.webContents.getURL())
} catch (err) {
error = err.code
response.data(error)
win.destroy()
return
}
for (let sigil_name of available_sigils) {
if (current_url.host === sigil_name) {
page_sigil_name = sigil_name
break
} else if (
sigil_name[0] === "*"
&& current_url.host.endsWith(sigil_name.replace("*.", ""))
){
page_sigil_name = sigil_name
break
}
}
if (! page_sigil_name) {
page_sigil = fs.readFileSync(sigils_dir + "/default")
} else {
page_sigil = fs.readFileSync(sigils_dir + "/" + page_sigil_name)
}
ipcMain.on("page-gemtext", (event, arg) => {
data += arg
})
await Promise.race([
win.webContents.executeJavaScript(page_sigil).catch(
(err) => error = err
),
timeout(exec_timeout_ms, "Script execution")
]).catch((err) => error = err)
ipcMain.removeAllListeners()
win.destroy()
if (error) {
response.data(error)
} else {
response.data(data, mimeType="text/gemini")
}
}
app.on('window-all-closed', () => {
;
})
app.whenReady().then(() => {
server.on("*", handle_request)
server.listen(() => {
console.log("listening on localhost:" + gemini_port)
}, gemini_port)
});