ddchat 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/test/server.mjs CHANGED
@@ -1,143 +1,143 @@
1
- import http from "node:http";
2
- import { readFile } from "node:fs/promises";
3
- import { WebSocketServer } from "ws";
4
-
5
- const HTTP_PORT = Number(process.env.DDCHAT_MOCK_HTTP_PORT ?? 9020);
6
- const WS_PORT = Number(process.env.DDCHAT_MOCK_WS_PORT ?? 9001);
7
-
8
- const clients = new Set();
9
- const uiClients = new Set();
10
- let pluginClient = null;
11
- const history = [];
12
-
13
- const server = http.createServer(async (req, res) => {
14
- if (!req.url || req.url === "/") {
15
- try {
16
- const html = await readFile(new URL("./chat.html", import.meta.url), "utf-8");
17
- res.statusCode = 200;
18
- res.setHeader("Content-Type", "text/html; charset=utf-8");
19
- res.end(html);
20
- return;
21
- } catch (error) {
22
- res.statusCode = 500;
23
- res.end(String(error));
24
- return;
25
- }
26
- }
27
- if (req.url === "/history") {
28
- res.statusCode = 200;
29
- res.setHeader("Content-Type", "application/json; charset=utf-8");
30
- res.end(JSON.stringify(history.slice(-300)));
31
- return;
32
- }
33
- res.statusCode = 404;
34
- res.end("not found");
35
- });
36
-
37
- server.listen(HTTP_PORT, () => {
38
- console.log(`[ddchat-mock] ui: http://127.0.0.1:${HTTP_PORT}`);
39
- });
40
-
41
- const wss = new WebSocketServer({ port: WS_PORT });
42
- wss.on("connection", (ws, req) => {
43
- clients.add(ws);
44
- const role = new URL(req.url ?? "/", "http://localhost").searchParams.get("role");
45
- const isUi = role === "ui";
46
- if (isUi) {
47
- uiClients.add(ws);
48
- console.log("[ddchat-mock] ui connected");
49
- } else {
50
- pluginClient = ws;
51
- console.log("[ddchat-mock] ddchat plugin connected");
52
- }
53
- ws.send(
54
- JSON.stringify({
55
- type: "hello",
56
- role: "ddchat-mock",
57
- ts: Date.now(),
58
- peerRole: isUi ? "ui" : "plugin",
59
- }),
60
- );
61
- ws.on("close", () => {
62
- clients.delete(ws);
63
- uiClients.delete(ws);
64
- if (pluginClient === ws) {
65
- pluginClient = null;
66
- console.log("[ddchat-mock] ddchat plugin disconnected");
67
- }
68
- });
69
- ws.on("message", (buf) => {
70
- const text = buf.toString("utf-8");
71
- let payload;
72
- try {
73
- payload = JSON.parse(text);
74
- } catch {
75
- payload = { type: "raw", text };
76
- }
77
- if (uiClients.has(ws)) {
78
- history.push({ direction: "to_plugin", payload, ts: Date.now() });
79
- if (pluginClient && pluginClient.readyState === 1) {
80
- pluginClient.send(JSON.stringify(payload));
81
- }
82
- broadcastToUi({
83
- type: "event",
84
- event: "to_plugin",
85
- payload,
86
- ts: Date.now(),
87
- });
88
- return;
89
- }
90
- history.push({ direction: "from_plugin", payload, ts: Date.now() });
91
- broadcastToUi({
92
- type: "event",
93
- event: "from_plugin",
94
- payload,
95
- ts: Date.now(),
96
- });
97
- });
98
- });
99
-
100
- console.log(`[ddchat-mock] websocket: ws://127.0.0.1:${WS_PORT}`);
101
-
102
- function broadcastToUi(data) {
103
- const text = JSON.stringify(data);
104
- for (const ws of uiClients) {
105
- try {
106
- ws.send(text);
107
- } catch {}
108
- }
109
- }
110
-
111
- process.stdin.setEncoding("utf-8");
112
- process.stdin.on("data", (chunk) => {
113
- const text = chunk.trim();
114
- if (!text) return;
115
- if (text === "help") {
116
- console.log(
117
- 'stdin example: {"accountId":"xkx","chatType":"direct","userId":"u-1001","messageId":"m-1","text":"hello"}',
118
- );
119
- return;
120
- }
121
- try {
122
- const payload = JSON.parse(text);
123
- const message = {
124
- type: "inbound_message",
125
- accountId: payload.accountId ?? "xkx",
126
- messageId: payload.messageId ?? `m-${Date.now()}`,
127
- chatType: payload.chatType === "group" ? "group" : "direct",
128
- userId: payload.userId ?? "u-1001",
129
- groupId: payload.groupId,
130
- text: payload.text ?? "",
131
- files: Array.isArray(payload.files) ? payload.files : undefined,
132
- ts: Date.now(),
133
- };
134
- history.push({ direction: "to_plugin", payload: message, ts: Date.now() });
135
- broadcastToUi({ type: "event", event: "to_plugin", payload: message, ts: Date.now() });
136
- if (pluginClient && pluginClient.readyState === 1) {
137
- pluginClient.send(JSON.stringify(message));
138
- }
139
- console.log("[ddchat-mock] sent inbound_message");
140
- } catch (error) {
141
- console.error("[ddchat-mock] invalid json:", error);
142
- }
143
- });
1
+ import http from "node:http";
2
+ import { readFile } from "node:fs/promises";
3
+ import { WebSocketServer } from "ws";
4
+
5
+ const HTTP_PORT = Number(process.env.DDCHAT_MOCK_HTTP_PORT ?? 9020);
6
+ const WS_PORT = Number(process.env.DDCHAT_MOCK_WS_PORT ?? 9001);
7
+
8
+ const clients = new Set();
9
+ const uiClients = new Set();
10
+ let pluginClient = null;
11
+ const history = [];
12
+
13
+ const server = http.createServer(async (req, res) => {
14
+ if (!req.url || req.url === "/") {
15
+ try {
16
+ const html = await readFile(new URL("./chat.html", import.meta.url), "utf-8");
17
+ res.statusCode = 200;
18
+ res.setHeader("Content-Type", "text/html; charset=utf-8");
19
+ res.end(html);
20
+ return;
21
+ } catch (error) {
22
+ res.statusCode = 500;
23
+ res.end(String(error));
24
+ return;
25
+ }
26
+ }
27
+ if (req.url === "/history") {
28
+ res.statusCode = 200;
29
+ res.setHeader("Content-Type", "application/json; charset=utf-8");
30
+ res.end(JSON.stringify(history.slice(-300)));
31
+ return;
32
+ }
33
+ res.statusCode = 404;
34
+ res.end("not found");
35
+ });
36
+
37
+ server.listen(HTTP_PORT, () => {
38
+ console.log(`[ddchat-mock] ui: http://127.0.0.1:${HTTP_PORT}`);
39
+ });
40
+
41
+ const wss = new WebSocketServer({ port: WS_PORT });
42
+ wss.on("connection", (ws, req) => {
43
+ clients.add(ws);
44
+ const role = new URL(req.url ?? "/", "http://localhost").searchParams.get("role");
45
+ const isUi = role === "ui";
46
+ if (isUi) {
47
+ uiClients.add(ws);
48
+ console.log("[ddchat-mock] ui connected");
49
+ } else {
50
+ pluginClient = ws;
51
+ console.log("[ddchat-mock] ddchat plugin connected");
52
+ }
53
+ ws.send(
54
+ JSON.stringify({
55
+ type: "hello",
56
+ role: "ddchat-mock",
57
+ ts: Date.now(),
58
+ peerRole: isUi ? "ui" : "plugin",
59
+ }),
60
+ );
61
+ ws.on("close", () => {
62
+ clients.delete(ws);
63
+ uiClients.delete(ws);
64
+ if (pluginClient === ws) {
65
+ pluginClient = null;
66
+ console.log("[ddchat-mock] ddchat plugin disconnected");
67
+ }
68
+ });
69
+ ws.on("message", (buf) => {
70
+ const text = buf.toString("utf-8");
71
+ let payload;
72
+ try {
73
+ payload = JSON.parse(text);
74
+ } catch {
75
+ payload = { type: "raw", text };
76
+ }
77
+ if (uiClients.has(ws)) {
78
+ history.push({ direction: "to_plugin", payload, ts: Date.now() });
79
+ if (pluginClient && pluginClient.readyState === 1) {
80
+ pluginClient.send(JSON.stringify(payload));
81
+ }
82
+ broadcastToUi({
83
+ type: "event",
84
+ event: "to_plugin",
85
+ payload,
86
+ ts: Date.now(),
87
+ });
88
+ return;
89
+ }
90
+ history.push({ direction: "from_plugin", payload, ts: Date.now() });
91
+ broadcastToUi({
92
+ type: "event",
93
+ event: "from_plugin",
94
+ payload,
95
+ ts: Date.now(),
96
+ });
97
+ });
98
+ });
99
+
100
+ console.log(`[ddchat-mock] websocket: ws://127.0.0.1:${WS_PORT}`);
101
+
102
+ function broadcastToUi(data) {
103
+ const text = JSON.stringify(data);
104
+ for (const ws of uiClients) {
105
+ try {
106
+ ws.send(text);
107
+ } catch {}
108
+ }
109
+ }
110
+
111
+ process.stdin.setEncoding("utf-8");
112
+ process.stdin.on("data", (chunk) => {
113
+ const text = chunk.trim();
114
+ if (!text) return;
115
+ if (text === "help") {
116
+ console.log(
117
+ 'stdin example: {"accountId":"xkx","chatType":"direct","userId":"u-1001","messageId":"m-1","text":"hello"}',
118
+ );
119
+ return;
120
+ }
121
+ try {
122
+ const payload = JSON.parse(text);
123
+ const message = {
124
+ type: "inbound_message",
125
+ accountId: payload.accountId ?? "xkx",
126
+ messageId: payload.messageId ?? `m-${Date.now()}`,
127
+ chatType: payload.chatType === "group" ? "group" : "direct",
128
+ userId: payload.userId ?? "u-1001",
129
+ groupId: payload.groupId,
130
+ text: payload.text ?? "",
131
+ files: Array.isArray(payload.files) ? payload.files : undefined,
132
+ ts: Date.now(),
133
+ };
134
+ history.push({ direction: "to_plugin", payload: message, ts: Date.now() });
135
+ broadcastToUi({ type: "event", event: "to_plugin", payload: message, ts: Date.now() });
136
+ if (pluginClient && pluginClient.readyState === 1) {
137
+ pluginClient.send(JSON.stringify(message));
138
+ }
139
+ console.log("[ddchat-mock] sent inbound_message");
140
+ } catch (error) {
141
+ console.error("[ddchat-mock] invalid json:", error);
142
+ }
143
+ });