mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-20 17:41:33 -06:00
b7b7eec5ee
Move Mantis Telegram Desktop proof from the remote AWS/Crabbox lane to a recorder-driven local Docker desktop. Keep proof scenarios agent-authored, cache trusted build outputs, and publish exact visible Telegram evidence without writing the QA bot token to artifacts. Co-authored-by: Ayaan Zaidi <hi@obviy.us>
117 lines
3.4 KiB
JavaScript
117 lines
3.4 KiB
JavaScript
#!/usr/bin/env -S node --import tsx
|
|
|
|
import http, { type IncomingMessage, type ServerResponse } from "node:http";
|
|
import https from "node:https";
|
|
import { pathToFileURL } from "node:url";
|
|
|
|
const hopByHopHeaders = new Set([
|
|
"connection",
|
|
"keep-alive",
|
|
"proxy-authenticate",
|
|
"proxy-authorization",
|
|
"te",
|
|
"trailer",
|
|
"transfer-encoding",
|
|
"upgrade",
|
|
]);
|
|
|
|
function requiredEnv(name: string): string {
|
|
const value = process.env[name]?.trim();
|
|
if (!value) {
|
|
throw new Error(`${name} is required`);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
function escapeRegExp(value: string): string {
|
|
return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
}
|
|
|
|
export function rewriteTelegramBotApiPath(
|
|
requestPath: string,
|
|
aliasToken: string,
|
|
upstreamToken: string,
|
|
): string | undefined {
|
|
const alias = escapeRegExp(aliasToken);
|
|
const methodMatch = new RegExp(`^/bot${alias}/([A-Za-z][A-Za-z0-9_]{0,63})(\\?.*)?$`, "u").exec(
|
|
requestPath,
|
|
);
|
|
if (methodMatch) {
|
|
return `/bot${upstreamToken}/${methodMatch[1]}${methodMatch[2] ?? ""}`;
|
|
}
|
|
const fileMatch = new RegExp(`^/file/bot${alias}/([^?#]+)(\\?.*)?$`, "u").exec(requestPath);
|
|
const filePath = fileMatch?.[1];
|
|
if (filePath && !filePath.split("/").includes("..")) {
|
|
return `/file/bot${upstreamToken}/${filePath}${fileMatch[2] ?? ""}`;
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
function forwardedHeaders(headers: IncomingMessage["headers"]): http.OutgoingHttpHeaders {
|
|
return Object.fromEntries(
|
|
Object.entries(headers).filter(
|
|
([name, value]) => value !== undefined && !hopByHopHeaders.has(name),
|
|
),
|
|
);
|
|
}
|
|
|
|
export function createTelegramBotApiProxy(params: {
|
|
aliasToken: string;
|
|
upstreamOrigin?: URL;
|
|
upstreamToken: string;
|
|
}): http.Server {
|
|
const upstreamOrigin = params.upstreamOrigin ?? new URL("https://api.telegram.org");
|
|
const transport = upstreamOrigin.protocol === "https:" ? https : http;
|
|
return http.createServer((request: IncomingMessage, response: ServerResponse) => {
|
|
const upstreamPath = rewriteTelegramBotApiPath(
|
|
request.url ?? "",
|
|
params.aliasToken,
|
|
params.upstreamToken,
|
|
);
|
|
if (!upstreamPath) {
|
|
response.writeHead(404).end();
|
|
return;
|
|
}
|
|
const upstream = transport.request(
|
|
{
|
|
headers: { ...forwardedHeaders(request.headers), host: upstreamOrigin.host },
|
|
hostname: upstreamOrigin.hostname,
|
|
method: request.method,
|
|
path: upstreamPath,
|
|
port: upstreamOrigin.port || undefined,
|
|
protocol: upstreamOrigin.protocol,
|
|
},
|
|
(upstreamResponse) => {
|
|
response.writeHead(
|
|
upstreamResponse.statusCode ?? 502,
|
|
forwardedHeaders(upstreamResponse.headers),
|
|
);
|
|
upstreamResponse.pipe(response);
|
|
},
|
|
);
|
|
upstream.setTimeout(90_000, () => upstream.destroy(new Error("Telegram Bot API timed out")));
|
|
upstream.on("error", () => {
|
|
if (!response.headersSent) {
|
|
response.writeHead(502);
|
|
}
|
|
response.end();
|
|
});
|
|
request.pipe(upstream);
|
|
});
|
|
}
|
|
|
|
function main(): void {
|
|
const server = createTelegramBotApiProxy({
|
|
aliasToken: requiredEnv("TELEGRAM_PROXY_ALIAS_TOKEN"),
|
|
upstreamToken: requiredEnv("TELEGRAM_PROXY_UPSTREAM_TOKEN"),
|
|
});
|
|
server.listen(8080, "0.0.0.0", () => console.log("Telegram Bot API proxy listening"));
|
|
const close = () => server.close();
|
|
process.once("SIGINT", close);
|
|
process.once("SIGTERM", close);
|
|
}
|
|
|
|
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
main();
|
|
}
|