Skip to content

Instantly share code, notes, and snippets.

@cenan
Created March 17, 2026 14:08
Show Gist options
  • Select an option

  • Save cenan/c7323fe82a2c7a5788af8822896d37ca to your computer and use it in GitHub Desktop.

Select an option

Save cenan/c7323fe82a2c7a5788af8822896d37ca to your computer and use it in GitHub Desktop.
server list builder
import { readFile, writeFile } from "node:fs/promises";
const INPUT = "servers.json";
const OUTPUT = "params.txt";
function extractRelays(data) {
for (const item of data) {
if (
item &&
item.type === "data" &&
item.data &&
Array.isArray(item.data.relays)
) {
return item.data.relays;
}
}
throw new Error("Could not find relays array in servers.json");
}
async function main() {
const raw = await readFile(INPUT, "utf8");
const json = JSON.parse(raw);
const relays = extractRelays(json);
const params = relays
.filter(r => r.active)
.map(r => `-r socks5://${r.socks_name}:${r.socks_port}`)
.join(" ");
await writeFile(OUTPUT, params + "\n", "utf8");
console.log(`Wrote ${OUTPUT} with ${relays.length} relays (${params.split(" -r ").length - 1} active)`);
}
main().catch(err => {
console.error(err);
process.exit(1);
});
import { writeFile } from "node:fs/promises";
const URL = "https://mullvad.net/en/servers?type=wireguard&status=true";
const OUTPUT_FILE = "servers.json";
function extractDataArray(source) {
const marker = "data:";
const markerIndex = source.indexOf(marker);
if (markerIndex === -1) {
throw new Error(`Could not find "${marker}" in response`);
}
const arrayStart = source.indexOf("[", markerIndex);
if (arrayStart === -1) {
throw new Error("Could not find array start after data:");
}
let depth = 0;
let inString = false;
let stringQuote = "";
let escaped = false;
for (let i = arrayStart; i < source.length; i++) {
const ch = source[i];
if (inString) {
if (escaped) {
escaped = false;
continue;
}
if (ch === "\\") {
escaped = true;
continue;
}
if (ch === stringQuote) {
inString = false;
stringQuote = "";
}
continue;
}
if (ch === '"' || ch === "'" || ch === "`") {
inString = true;
stringQuote = ch;
continue;
}
if (ch === "[") {
depth++;
} else if (ch === "]") {
depth--;
if (depth === 0) {
return source.slice(arrayStart, i + 1);
}
}
}
throw new Error("Could not find matching closing bracket for data array");
}
async function main() {
const res = await fetch(URL, {
headers: {
"user-agent": "bun fetch script",
},
});
if (!res.ok) {
throw new Error(`Fetch failed: ${res.status} ${res.statusText}`);
}
const html = await res.text();
if (!html.includes('data: [null,{type:"data"')) {
console.warn('Warning: expected prefix `data: [null,{type:"data"` was not found exactly.');
}
const arraySource = extractDataArray(html);
const data = Function(`"use strict"; return (${arraySource});`)();
await writeFile(OUTPUT_FILE, JSON.stringify(data, null, 2), "utf8");
console.log(`Saved ${OUTPUT_FILE}`);
}
main().catch((err) => {
console.error(err);
process.exit(1);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment