feat: update server & userscript

This commit is contained in:
2026-09-15 18:07:56 +08:00
parent 5329bb2ed9
commit 3b589578af
2 changed files with 40 additions and 26 deletions
+39 -25
View File
@@ -11,7 +11,8 @@ const wss = new WebSocketServer({
port: PORT, port: PORT,
}); });
let whatsapp: WebSocket | undefined; const bridgeSockets = new Set<WebSocket>();
const clientSockets = new Set<WebSocket>();
const pending = new Map< const pending = new Map<
string, string,
@@ -26,11 +27,24 @@ function requestId() {
return crypto.randomUUID(); return crypto.randomUUID();
} }
function getWhatsApp(): WebSocket | undefined {
for (const ws of bridgeSockets) {
if (ws.readyState === WebSocket.OPEN) {
return ws;
}
bridgeSockets.delete(ws);
}
return undefined;
}
function call<T>( function call<T>(
method: BridgeRequest["method"], method: BridgeRequest["method"],
params?: unknown, params?: unknown,
): Promise<T> { ): Promise<T> {
if (!whatsapp || whatsapp.readyState !== WebSocket.OPEN) { const wa = getWhatsApp();
if (!wa || wa.readyState !== WebSocket.OPEN) {
throw new Error("WhatsApp Web is not connected"); throw new Error("WhatsApp Web is not connected");
} }
@@ -49,7 +63,7 @@ function call<T>(
timer, timer,
}); });
whatsapp!.send( wa!.send(
JSON.stringify({ JSON.stringify({
type: "request", type: "request",
id, id,
@@ -94,6 +108,11 @@ function handleWhatsAppMessage(data: string) {
// console.log("[WhatsApp event]", message.event, message.data); // console.log("[WhatsApp event]", message.event, message.data);
if (message.event === "message") { if (message.event === "message") {
// forward to clients
clientSockets.forEach((ws) => {
ws.send(JSON.stringify(message));
});
const m = message.data as MessageDTO; const m = message.data as MessageDTO;
insertMessage({ insertMessage({
@@ -109,15 +128,14 @@ function handleWhatsAppMessage(data: string) {
} }
wss.on("connection", (ws) => { wss.on("connection", (ws) => {
console.log("[WS] client connected"); console.log("[WS] socket connected");
/* const url = new URL(ws.url ?? "", "http://localhost");
* First connection from Tampermonkey is the const isBridge =
* WhatsApp bridge. !url.searchParams.get("client") || url.searchParams.get("bridge") === "1";
*/
if (!whatsapp && !ws.url.includes("?client=1")) {
whatsapp = ws;
if (isBridge) {
bridgeSockets.add(ws);
console.log("[WS] WhatsApp bridge attached"); console.log("[WS] WhatsApp bridge attached");
ws.on("message", (data) => { ws.on("message", (data) => {
@@ -125,32 +143,23 @@ wss.on("connection", (ws) => {
}); });
ws.on("close", () => { ws.on("close", () => {
if (whatsapp === ws) { bridgeSockets.delete(ws);
whatsapp = undefined; console.log("[WS] WhatsApp bridge disconnected");
}
console.log("[WS] WhatsApp disconnected");
}); });
ws.on("error", () => {
bridgeSockets.delete(ws);
});
return; return;
} }
/* clientSockets.add(ws);
* This is an external application/client.
*
* Example:
* my backend
* CLI
* React application
* another service
*/
ws.on("message", async (data) => { ws.on("message", async (data) => {
let request: any; let request: any;
try { try {
request = JSON.parse(data.toString()) as BridgeRequest; request = JSON.parse(data.toString()) as BridgeRequest;
if (request.type !== "request") { if (request.type !== "request") {
return; return;
} }
@@ -214,8 +223,13 @@ wss.on("connection", (ws) => {
}); });
ws.on("close", () => { ws.on("close", () => {
clientSockets.delete(ws);
console.log("[WS] external client disconnected"); console.log("[WS] external client disconnected");
}); });
ws.on("error", () => {
clientSockets.delete(ws);
});
}); });
initDb(); initDb();
+1 -1
View File
@@ -7,7 +7,7 @@ import {
serializeMessage, serializeMessage,
} from "./serializer"; } from "./serializer";
const WS_URL = "wss://wa-bridge.rul.sh/ws"; const WS_URL = "wss://wa-bridge.rul.sh/ws?bridge=1";
let socket: WebSocket | undefined; let socket: WebSocket | undefined;