[mod] allow multiple connections
Christian Fraß

Christian Fraß commited on 2021-11-19 01:20:24
Zeige 1 geänderte Dateien mit 88 Einfügungen und 40 Löschungen.

... ...
@@ -1,15 +1,58 @@
1
+type type_event = {
2
+	timestamp: int;
3
+	kind: string;
4
+	data: any;
5
+};
6
+
7
+
8
+type type_user = {
9
+	name: string;
10
+	role: string;
11
+};
12
+
13
+
14
+type type_connection = {
15
+	events: Array<type_event>;
16
+	users: Array<type_user>;
17
+	client: any;
18
+};
19
+
20
+
1 21
 function get_timestamp(): int
2 22
 {
3 23
 	return Math.floor(Date.now()/1000);
4 24
 }
5 25
 
6
-async function main(): Promise<void>
26
+
27
+function log(message: string): void
28
+{
29
+	process.stderr.write(`-- ${message}\n`);
30
+}
31
+
32
+
33
+function generate_id(): string
34
+{
35
+	return (Math.random() * (1 << 24)).toFixed(0).padStart(8, '0');
36
+}
37
+
38
+
39
+var connections: Record<string, type_connection> = {};
40
+
41
+
42
+function get_connection(data_in: any): type_connection
7 43
 {
8
-	var nm_irc = require("irc");
44
+	if (! connections.hasOwnProperty(data_in["id"])) {
45
+		throw (new Error("no connection for ID '" + data_in["id"] + "'"));
46
+	}
47
+	else {
48
+		return connections[data_in["id"]];
49
+	}
50
+}
9 51
 
10
-	var _events: Array<any> = [];
11
-	var _users: Array<{name: string; role: string;}> = [];
12
-	var _client = null;
52
+
53
+async function main(): Promise<void>
54
+{
55
+	var nm_irc: any = require("irc");
13 56
 	
14 57
 	const server: lib_server.class_server = new lib_server.class_server(
15 58
 		7979,
... ...
@@ -17,15 +60,17 @@ async function main(): Promise<void>
17 60
 			const request: lib_http.type_request = lib_http.decode_request(input);
18 61
 			// process.stderr.write(JSON.stringify(request, undefined, "\t") + "\n");
19 62
 			const data_in: any = JSON.parse(request.body);
63
+			// log(data_in["action"] + " | " + (data_in["id"] ?? "-") + " | " + JSON.stringify(data_in["data"]));
20 64
 			let data_out: any;
21 65
 			let error: (null | Error);
22 66
 			try {
23 67
 				switch (data_in["action"]) {
24
-					case "connect":
25
-						if (_client !== null) {
68
+					case "connect": {
69
+						if (data_in.hasOwnProperty("id") && connections.hasOwnProperty(data_in["id"])) {
26 70
 							throw (new Error("already connected"));
27 71
 						}
28 72
 						else {
73
+							const id: string = generate_id();
29 74
 							const client = new nm_irc.Client(
30 75
 								data_in["data"]["server"],
31 76
 								data_in["data"]["nickname"],
... ...
@@ -34,10 +79,15 @@ async function main(): Promise<void>
34 79
 									"autoConnect": false,
35 80
 								}
36 81
 							);
82
+							const connection: type_connection = {
83
+								"client": client,
84
+								"events": [],
85
+								"users": [],
86
+							};
37 87
 							client.addListener(
38 88
 								"message",
39 89
 								(from, to, message) => {
40
-									_events.push({
90
+									connection.events.push({
41 91
 										"timestamp": get_timestamp(),
42 92
 										"kind": "channel_message",
43 93
 										"data": {
... ...
@@ -51,7 +101,7 @@ async function main(): Promise<void>
51 101
 							client.addListener(
52 102
 								"pm",
53 103
 								(from, message) => {
54
-									_events.push({
104
+									connection.events.push({
55 105
 										"timestamp": get_timestamp(),
56 106
 										"kind": "private_message",
57 107
 										"data": {
... ...
@@ -64,66 +114,62 @@ async function main(): Promise<void>
64 114
 							client.addListener(
65 115
 								"names",
66 116
 								(channel, users) => {
67
-									_users = Object.entries(users).map(([key, value]) => ({"name": key, "role": value.toString()}));
117
+									connection.users = Object.entries(users).map(([key, value]) => ({"name": key, "role": value.toString()}));
68 118
 								}
69 119
 							);
70 120
 							client.addListener(
71 121
 								"error",
72 122
 								(error) => {
73
-									process.stderr.write("error: " + error.message + "\n");
123
+									log("error: " + error.message);
74 124
 								}
75 125
 							);
76 126
 							client.connect(
77 127
 								3,
78 128
 								() => {
79
-									_client = client;
129
+									connections[id] = connection;
80 130
 								}
81 131
 							);
132
+							data_out = id;
82 133
 						}
83
-						data_out = null;
84 134
 						break;
85
-					case "check":
86
-						data_out = (_client !== null);
87
-						break;
88
-					case "disconnect":
89
-						if (_client === null) {
90
-							throw (new Error("not (yet) connected"));
91 135
 					}
92
-						else {
93
-							_client.disconnect(
94
-								"",
95
-								() => {
96
-									_client = null;
136
+					case "check": {
137
+						try {
138
+							get_connection(data_in);
139
+							data_out = true;
97 140
 						}
98
-							);
99
-							data_out = null;
141
+						catch (error) {
142
+							data_out = false;
100 143
 						}
101 144
 						break;
102
-					case "say":
103
-						if (_client === null) {
104
-							throw (new Error("not (yet) connected"));
105 145
 					}
106
-						else {
107
-							_client.say(data_in["data"]["channel"], data_in["data"]["message"]);
146
+					case "disconnect": {
147
+						const connection: type_connection = get_connection(data_in);
148
+						delete connections[data_in["id"]];
149
+						connection.client.disconnect("", () => {});
108 150
 						data_out = null;
151
+						break;
109 152
 					}
153
+					case "say": {
154
+						const connection: type_connection = get_connection(data_in);
155
+						connection.client.say(data_in["data"]["channel"], data_in["data"]["message"]);
156
+						data_out = null;
110 157
 						break;
111
-					case "fetch":
112
-						if (_client === null) {
113
-							throw (new Error("not (yet) connected"));
114 158
 					}
115
-						else {
159
+					case "fetch": {
160
+						const connection: type_connection = get_connection(data_in);
116 161
 						data_out = {
117
-								"users": _users,
118
-								"events": _events,
162
+							"users": connection.users,
163
+							"events": connection.events,
119 164
 						};
120
-							_events = [];
121
-						}
165
+						connection.events = [];
122 166
 						break;
123 167
 					}
168
+				}
124 169
 				error = null;
125 170
 			}
126 171
 			catch (error_) {
172
+				process.stderr.write(error_.toString() + "\n");
127 173
 				error = error_;
128 174
 			}
129 175
 			const response: lib_http.type_response = (
... ...
@@ -131,13 +177,15 @@ async function main(): Promise<void>
131 177
 				? {
132 178
 					"statuscode": 500,
133 179
 					"headers": {
180
+						"Content-Type": "text/plain",
134 181
 						"Access-Control-Allow-Origin": "*",
135 182
 					},
136
-					"body": JSON.stringify({"error": error.toString()}),
183
+					"body": error.toString(),
137 184
 				}
138 185
 				: {
139 186
 					"statuscode": 200,
140 187
 					"headers": {
188
+						"Content-Type": "application/json",
141 189
 						"Access-Control-Allow-Origin": "*",
142 190
 					},
143 191
 					"body": JSON.stringify(data_out),
144 192