Skip to content

Commit f12fc9f

Browse files
committed
Commit
1 parent a0d4477 commit f12fc9f

5 files changed

Lines changed: 211 additions & 3 deletions

File tree

server-src/pinggy.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
const { spawn } = require('node:child_process');
2+
3+
// Configuration
4+
let serverPort = process.env.PORT || process.env.serverPort || 3000;
5+
const filterLinks = ["https://dashboard.pinggy.io", "https://pinggy.io"];
6+
const maxPinggy = 10; // Total concurrent tunnels
7+
8+
const commandArgs = [
9+
['ssh', [
10+
'-p', '443',
11+
'-o', 'StrictHostKeyChecking=no',
12+
'-o', 'ServerAliveInterval=30',
13+
'-R', `0:localhost:${serverPort}`,
14+
'-L', '4300:127.0.0.1:4300',
15+
'qr@free.pinggy.io'
16+
]]
17+
];
18+
19+
var activeTunnels = new Map();
20+
var curPinggy = 0;
21+
22+
function spawnTunnel(index) {
23+
if (curPinggy >= maxPinggy) return;
24+
25+
curPinggy += 1;
26+
const [cmdName, args] = commandArgs[index];
27+
const child = spawn(cmdName, args);
28+
const pid = child.pid;
29+
30+
child.stdout.on('data', (data) => {
31+
const output = data.toString();
32+
33+
// Improved URL regex to catch URLs even if they are surrounded by ANSI codes
34+
const urlRegex = /https:\/\/[^\s"'<>]+/g;
35+
const foundLinks = output.match(urlRegex);
36+
37+
if (foundLinks) {
38+
foundLinks.forEach(link => {
39+
const s = link.trim().replace(/\x1B\[[0-9;]*[mK]/g, ""); // Clean ANSI colors
40+
41+
if (!filterLinks.some(f => s.startsWith(f)) && !activeTunnels.has(pid)) {
42+
activeTunnels.set(pid, {
43+
url: s,
44+
ts: Date.now()
45+
});
46+
}
47+
});
48+
}
49+
});
50+
51+
// Capture errors to help with debugging
52+
child.stderr.on('data', (data) => {
53+
if (data.toString().includes("Permission denied")) {
54+
console.error(`[Error] PID ${pid} check your SSH keys.`);
55+
}
56+
});
57+
58+
child.on('close', (code) => {
59+
curPinggy -= 1;
60+
activeTunnels.delete(pid);
61+
62+
// Staggered restart to avoid spamming the CPU
63+
setTimeout(() => {
64+
spawnTunnel(index);
65+
}, 5000);
66+
});
67+
}
68+
69+
// Initial Boot
70+
for (let i = 0; i < maxPinggy; i++) {
71+
// Distribute processes evenly across providers
72+
spawnTunnel(i % commandArgs.length);
73+
}
74+
75+
function getActiveAltLinks() {
76+
return Array.from(activeTunnels.values());
77+
}
78+
79+
module.exports = { getActiveAltLinks };

server-src/server.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ var webpush = require("web-push");
1919
var scratchCloudWss = require("./scratch-cloud.js");
2020
var WebRTCSignaler = require("./rtcsignal/req-handler.js");
2121
var botCheck = require("./bot-check-manager.js");
22+
var pinggy = require("./pinggy.js");
2223
var userMediaDirectory = "./usermedia";
2324
var usersOnlineSockets = {};
2425
var wssServerOptions = {
@@ -2881,6 +2882,11 @@ const server = http.createServer(async function (req, res) {
28812882
}
28822883
}
28832884

2885+
if (urlsplit[1] == "tunnels.json") {
2886+
res.end(JSON.stringify(pinggy.getActiveAltLinks(), null, " "));
2887+
return;
2888+
}
2889+
28842890
if (urlsplit[1] == "webpush" && WEBPUSH_ENABLED) {
28852891
if (urlsplit[2] == "key" && req.method == "GET") {
28862892
res.end(WEBPUSH_PUBLIC_KEY);

src/menu.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,29 @@ var elementJSON = [
7474
textContent: "Updates",
7575
href: "./updates",
7676
},
77-
//Documentary button.
77+
//Alternative links button.
78+
{
79+
element: "a",
80+
className: "menuBarItem",
81+
textContent: "Alt links",
82+
href: "./alts",
83+
},
84+
//Uptime button.
7885
{
86+
element: "a",
87+
className: "menuBarItem",
88+
textContent: "Uptime",
89+
href: "https://stats.uptimerobot.com/a0xrFFxOH1",
90+
target: "_blank",
91+
},
92+
//Documentary button.
93+
/*{
7994
element: "a",
8095
className: "menuBarItem",
8196
textContent: "Site Documentary",
8297
href: "https://randomrants-docs.onrender.com",
8398
target: "_blank",
84-
},
99+
},*/
85100
],
86101
},
87102
{

src/pages/alts.js

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
async function getTunnels() {
2+
try {
3+
var response = await fetch("/tunnels.json");
4+
var data = await response.json();
5+
return data;
6+
} catch (e) {
7+
window.alert("Unable to parse or load external/other.json: " + e);
8+
console.error(e);
9+
return "";
10+
}
11+
}
12+
13+
document.title = "Random Rants + | Alternative Links";
14+
15+
require("../cookiewarning");
16+
require("./stylesheet.js");
17+
require("../sw.js");
18+
var menuBar = require("../menu.js");
19+
var elements = require("../gp2/elements.js");
20+
var accountHelper = require("../accounthelper/index.js");
21+
var dialog = require("../dialogs.js");
22+
require("./navigate-loader.js");
23+
24+
async function showAltLinks(containerDiv) {
25+
try {
26+
elements.setInnerJSON(containerDiv, [
27+
{
28+
element: "div",
29+
textContent: "Loading...",
30+
},
31+
]);
32+
var tunnels = await getTunnels();
33+
elements.setInnerJSON(
34+
containerDiv,
35+
tunnels.map((tunnel) => {
36+
return {
37+
element: "div",
38+
children: [
39+
{
40+
element: "a",
41+
textContent: tunnel.url,
42+
href: tunnel.url,
43+
target: "_blank",
44+
style: {
45+
fontSize: "20px",
46+
fontWeight: "bold"
47+
}
48+
},
49+
{
50+
element: "br"
51+
},
52+
{
53+
element: "br"
54+
}
55+
]
56+
};
57+
})
58+
);
59+
} catch (e) {
60+
dialog.alert("Unable to load updates: " + e);
61+
console.error(e);
62+
}
63+
}
64+
65+
var randomRantsUpdates = [
66+
{
67+
element: "h2",
68+
textContent: "Alternative links",
69+
style: { fontSize: "1.8em", marginTop: "1.2em", marginBottom: "0.5em" },
70+
children: [],
71+
},
72+
{
73+
element: "p",
74+
textContent:
75+
"Alternative links to satisfy your ranting needs",
76+
},
77+
{
78+
element: "p",
79+
textContent:
80+
"These links expire in 60 minutes, if they break then get new links, refresh to get the latest working ones.",
81+
},
82+
{
83+
element: "div",
84+
className: "button2",
85+
textContent: "Refresh",
86+
eventListeners: [
87+
{
88+
event: "click",
89+
func: () => showAltLinks,
90+
},
91+
],
92+
},
93+
{
94+
element: "div",
95+
GPWhenCreated: showAltLinks,
96+
},
97+
];
98+
99+
var elementJSON = [
100+
{
101+
element: "div",
102+
className: "aboutDivCenter",
103+
children: randomRantsUpdates,
104+
},
105+
];
106+
107+
var pageElements = elements.createElementsFromJSON(elementJSON);
108+
elements.appendElements(elements.body, pageElements);

wpstatic/version.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"timestamp":"1770911428376"}
1+
{"timestamp":"1771435666891"}

0 commit comments

Comments
 (0)