// Theseus Navigator — Electron main process. // Native .bch via a custom `bns://` protocol: resolves names with the shared // portable resolver (Argus/resolver-web.js) and serves content itself (on-chain // h, Sia s3, direct ip, redirect u). Tabs, nav controls, a search box, a home // page, and optional Tor onion routing. No system daemon; the app is the trust // boundary. const { app, BrowserWindow, WebContentsView, ipcMain, protocol, session, Menu, clipboard, nativeTheme } = require("electron"); const path = require("path"); const http = require("http"); const https = require("https"); const { spawn } = require("child_process"); const fs = require("fs"); const WebSocket = require("ws"); // Packaged builds ship the resolver and tor/ as unpacked resources (they can't // run from inside app.asar); dev runs read them from the repo. const RES_DIR = app.isPackaged ? process.resourcesPath : __dirname; // Bundled as .mjs so it loads as ES module in the packaged app (no package.json // sits next to it in resources/, so a bare .js would be treated as CommonJS and // fail on `export`). Dev reads the engine copy directly (Argus is type:module). const RESOLVER = app.isPackaged ? path.join(RES_DIR, "resolver-web.mjs") : path.join(__dirname, "..", "Argus", "src", "lib", "resolver-web.js"); // Built-in search engines. Users can also add their own (settings.customEngines, // each { id, name, url } where the url contains "%s" for the query). const SEARCH_ENGINES = { duckduckgo: { name: "DuckDuckGo", sym: "🦆", url: (q) => "https://duckduckgo.com/?q=" + encodeURIComponent(q) }, google: { name: "Google", sym: "🔵", url: (q) => "https://www.google.com/search?q=" + encodeURIComponent(q) }, brave: { name: "Brave", sym: "🦁", url: (q) => "https://search.brave.com/search?q=" + encodeURIComponent(q) }, bing: { name: "Bing", sym: "🔎", url: (q) => "https://www.bing.com/search?q=" + encodeURIComponent(q) }, startpage: { name: "Startpage", sym: "🛡️", url: (q) => "https://www.startpage.com/sp/search?query=" + encodeURIComponent(q) }, yandex: { name: "Yandex", sym: "🔴", url: (q) => "https://yandex.com/search/?text=" + encodeURIComponent(q) }, }; // Built-in + user-added, as flat metadata for the pickers (sym = a display symbol). function allEngines() { const list = Object.entries(SEARCH_ENGINES).map(([id, e]) => ({ id, name: e.name, sym: e.sym, builtin: true })); for (const c of settings.customEngines || []) list.push({ id: c.id, name: c.name, sym: c.sym || "🔍", builtin: false }); return list; } function engineUrl(id, q) { if (SEARCH_ENGINES[id]) return SEARCH_ENGINES[id].url(q); const c = (settings.customEngines || []).find((e) => e.id === id); return c ? c.url.replace(/%s/g, encodeURIComponent(q)) : SEARCH_ENGINES.duckduckgo.url(q); } const SEARCH = (q) => engineUrl(settings.searchEngine, q); // Public content relay (secret-free): serves s3/ip/h/u without shipping keys. const GATEWAY = "https://navigate.st"; // ---- BNS name detection (multi-TLD) -------------------------------------- // The engine (resolver-web.js) resolves any