multichat-ts 0.0.93 → 0.0.95
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/.prettierrc +7 -7
- package/dist/kick.js +1 -1
- package/dist/twitch.d.ts +20 -3
- package/dist/twitch.js +53 -16
- package/package.json +1 -1
- package/src/default/index.ts +173 -173
- package/src/default/kick.ts +676 -676
- package/src/default/twitch.ts +64 -16
package/src/default/twitch.ts
CHANGED
|
@@ -21,12 +21,18 @@ type EventCallbackFunctions = {
|
|
|
21
21
|
delete_message: (data: DeleteMessage) => unknown;
|
|
22
22
|
event: (event: Event) => unknown;
|
|
23
23
|
raw_message: (message: IRC_Message) => unknown;
|
|
24
|
+
connected: () => unknown;
|
|
25
|
+
auth_error: () => unknown;
|
|
24
26
|
};
|
|
25
27
|
|
|
26
28
|
type EventNames = keyof EventCallbackFunctions;
|
|
27
29
|
|
|
28
30
|
export class TwitchIRC {
|
|
29
31
|
public channel_name?: string;
|
|
32
|
+
public auth?: { username: string; token: string } | undefined;
|
|
33
|
+
public bot_name?: string;
|
|
34
|
+
public bot_token?: string;
|
|
35
|
+
|
|
30
36
|
private assets: {
|
|
31
37
|
external_emotes: EmoteURLsByName;
|
|
32
38
|
badges: BadgeURLsBySetIDOrSetIDAndVersion;
|
|
@@ -45,10 +51,11 @@ export class TwitchIRC {
|
|
|
45
51
|
private public_listeners: Partial<EventCallbackFunctions> = {};
|
|
46
52
|
|
|
47
53
|
public socket?: WebSocket;
|
|
48
|
-
public
|
|
54
|
+
public wsCustom?: WebSocket | undefined;
|
|
49
55
|
|
|
50
|
-
constructor(ws?: WebSocket) {
|
|
51
|
-
this.
|
|
56
|
+
constructor(options: { ws?: WebSocket; auth?: { username: string; token: string } }) {
|
|
57
|
+
this.wsCustom = options.ws;
|
|
58
|
+
this.auth = options.auth;
|
|
52
59
|
}
|
|
53
60
|
|
|
54
61
|
public setBadges(badges: BadgeURLsBySetIDOrSetIDAndVersion) {
|
|
@@ -67,6 +74,11 @@ export class TwitchIRC {
|
|
|
67
74
|
return this.assets.external_emotes;
|
|
68
75
|
}
|
|
69
76
|
|
|
77
|
+
public authenticate(username: string, token: string) {
|
|
78
|
+
this.bot_name = username;
|
|
79
|
+
this.bot_token = token;
|
|
80
|
+
}
|
|
81
|
+
|
|
70
82
|
public connect(channel?: { channelName?: string }) {
|
|
71
83
|
if (channel?.channelName) this.channel_name = channel.channelName;
|
|
72
84
|
if (!this.channel_name) return console.error('channel_name not specified');
|
|
@@ -76,14 +88,24 @@ export class TwitchIRC {
|
|
|
76
88
|
this.socket?.close();
|
|
77
89
|
|
|
78
90
|
this.socket = new WebSocket('wss://irc-ws.chat.twitch.tv', null, {
|
|
79
|
-
WebSocket: this.
|
|
91
|
+
WebSocket: this.wsCustom,
|
|
80
92
|
});
|
|
81
93
|
this.socket.onopen = () => this.onOpen();
|
|
82
94
|
this.socket.onclose = () => this.onClose();
|
|
83
95
|
this.socket.onmessage = (event) => this.onMessage(event);
|
|
84
96
|
}
|
|
85
97
|
|
|
98
|
+
public send(message: string, replyParentMessageId?: string) {
|
|
99
|
+
if (this.auth === undefined) return console.error('No Auth Information');
|
|
100
|
+
if (!this.isConnected()) return console.error('Not Connected');
|
|
101
|
+
|
|
102
|
+
this.socket.send(
|
|
103
|
+
`${replyParentMessageId ? `@reply-parent-msg-id=${replyParentMessageId} ` : ''}PRIVMSG #${this.channel_name} :${message}`,
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
86
107
|
public disconnect() {
|
|
108
|
+
this.socket?.send(`Part #${this.channel_name}`);
|
|
87
109
|
this.socket?.close();
|
|
88
110
|
}
|
|
89
111
|
|
|
@@ -99,12 +121,18 @@ export class TwitchIRC {
|
|
|
99
121
|
}
|
|
100
122
|
|
|
101
123
|
private onOpen() {
|
|
102
|
-
this.
|
|
103
|
-
this.
|
|
104
|
-
|
|
105
|
-
|
|
124
|
+
this.sendIRC('CAP REQ :twitch.tv/commands twitch.tv/tags');
|
|
125
|
+
if (this.auth !== undefined) {
|
|
126
|
+
this.sendIRC(`PASS oauth:${this.auth.token}`);
|
|
127
|
+
this.sendIRC(`NICK ${this.auth.username}`);
|
|
128
|
+
this.sendIRC(`JOIN #${this.channel_name}`);
|
|
129
|
+
} else {
|
|
130
|
+
this.sendIRC(`PASS ${ANONYMOUS_IRC_PASS}`);
|
|
131
|
+
this.sendIRC(`NICK ${ANONYMOUS_IRC_LOGIN}`);
|
|
132
|
+
this.sendIRC(`JOIN #${this.channel_name}`);
|
|
133
|
+
}
|
|
106
134
|
|
|
107
|
-
|
|
135
|
+
this.public_listeners.connected?.();
|
|
108
136
|
|
|
109
137
|
if (this.ping.interval) clearInterval(this.ping.interval);
|
|
110
138
|
this.sendPing();
|
|
@@ -117,7 +145,7 @@ export class TwitchIRC {
|
|
|
117
145
|
}
|
|
118
146
|
|
|
119
147
|
private sendPing() {
|
|
120
|
-
this.
|
|
148
|
+
this.sendIRC('PING');
|
|
121
149
|
this.ping.lastSentTimestamp = Date.now();
|
|
122
150
|
|
|
123
151
|
if (this.ping.timeout) clearTimeout(this.ping.timeout);
|
|
@@ -127,10 +155,9 @@ export class TwitchIRC {
|
|
|
127
155
|
}, PING_TIMEOUT_MS);
|
|
128
156
|
}
|
|
129
157
|
|
|
130
|
-
private
|
|
131
|
-
if (!this.isConnected())
|
|
132
|
-
|
|
133
|
-
}
|
|
158
|
+
private sendIRC(irc_message: string) {
|
|
159
|
+
if (!this.isConnected()) return console.error('Not Connected');
|
|
160
|
+
|
|
134
161
|
this.socket?.send(irc_message);
|
|
135
162
|
}
|
|
136
163
|
|
|
@@ -149,7 +176,26 @@ export class TwitchIRC {
|
|
|
149
176
|
break;
|
|
150
177
|
}
|
|
151
178
|
case 'PING': {
|
|
152
|
-
this.
|
|
179
|
+
this.sendIRC('PONG');
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
case '001': {
|
|
183
|
+
console.log(
|
|
184
|
+
`Connected to Twitch IRC as ${this.auth?.username ?? 'Anonymous'} (${this.channel_name})`,
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
this.public_listeners.connected?.();
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
case 'NOTICE': {
|
|
191
|
+
if (
|
|
192
|
+
message.params[0] === 'Login authentication failed' ||
|
|
193
|
+
message.params[0] === 'Improperly formatted auth'
|
|
194
|
+
) {
|
|
195
|
+
clearTimeout(this.ping.timeout);
|
|
196
|
+
this.disconnect();
|
|
197
|
+
this.public_listeners.auth_error?.();
|
|
198
|
+
}
|
|
153
199
|
break;
|
|
154
200
|
}
|
|
155
201
|
case 'CLEARCHAT': {
|
|
@@ -316,7 +362,7 @@ function parseIRCLine(line: string): IRC_Message {
|
|
|
316
362
|
componentIndex++;
|
|
317
363
|
|
|
318
364
|
let channel: string = '';
|
|
319
|
-
if (components[componentIndex]
|
|
365
|
+
if (components[componentIndex]?.startsWith('#')) channel = components[componentIndex]!.slice(1);
|
|
320
366
|
componentIndex++;
|
|
321
367
|
|
|
322
368
|
const params: string[] = [];
|
|
@@ -430,6 +476,8 @@ const RAW_TAGS = {
|
|
|
430
476
|
|
|
431
477
|
PONG: [],
|
|
432
478
|
|
|
479
|
+
'001': [],
|
|
480
|
+
|
|
433
481
|
PRIVMSG: [
|
|
434
482
|
'badge-info',
|
|
435
483
|
'badges',
|