multichat-ts 0.0.2 → 0.0.4
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/README.md +6 -3
- package/dist/index.d.ts +3 -4
- package/dist/kick.d.ts +22 -1
- package/dist/kick.js +1 -1
- package/dist/twitch.d.ts +40 -4
- package/dist/twitch.js +10 -4
- package/package.json +53 -51
- package/src/index.ts +4 -4
- package/src/kick.ts +3 -3
- package/src/twitch.ts +17 -14
package/README.md
CHANGED
|
@@ -40,14 +40,17 @@ kick_chat.on('message', (message) => {
|
|
|
40
40
|
|
|
41
41
|
```svelte
|
|
42
42
|
<script lang="ts">
|
|
43
|
-
import { TwitchIRC, type Message
|
|
43
|
+
import { TwitchIRC, type Message } from 'multichat-ts';
|
|
44
44
|
|
|
45
45
|
let messages: Message[] = $state([]);
|
|
46
46
|
|
|
47
47
|
const twitch_chat = new TwitchIRC();
|
|
48
|
+
$effect(() => {
|
|
49
|
+
twitch_chat.connect({
|
|
50
|
+
channelName: 'piratesoftware'
|
|
51
|
+
});
|
|
48
52
|
|
|
49
|
-
|
|
50
|
-
channelName: 'piratesoftware'
|
|
53
|
+
return () => twitch_chat.disconnect();
|
|
51
54
|
});
|
|
52
55
|
|
|
53
56
|
twitch_chat.on('message', (message) => {
|
package/dist/index.d.ts
CHANGED
|
@@ -134,10 +134,9 @@ export type BadgeURLsByNameOrCount = {
|
|
|
134
134
|
[badge_count: number]: string;
|
|
135
135
|
};
|
|
136
136
|
};
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
};
|
|
137
|
+
type StringOrAny = '*' | (string & Record<never, never>);
|
|
138
|
+
export type BadgeURLsBySetIDAndVersionIDOrAny = {
|
|
139
|
+
[badge_set_id: string]: Record<StringOrAny, string>;
|
|
141
140
|
};
|
|
142
141
|
export type EmoteURLsByName = {
|
|
143
142
|
[emote_name: string]: string;
|
package/dist/kick.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import Pusher from 'pusher-js';
|
|
2
2
|
import { type BadgeURLsByNameOrCount, type EmoteURLsByName, type Message } from './index.js';
|
|
3
3
|
type EventCallbackFunctions = {
|
|
4
|
-
message: (
|
|
4
|
+
message: (message: Message) => unknown;
|
|
5
|
+
raw_message: (message: ChatMessageEvent) => unknown;
|
|
5
6
|
};
|
|
6
7
|
type EventNames = keyof EventCallbackFunctions;
|
|
7
8
|
export declare class KickPusher {
|
|
@@ -22,4 +23,24 @@ export declare class KickPusher {
|
|
|
22
23
|
private onSubscriptionSuccess;
|
|
23
24
|
private onChatMessage;
|
|
24
25
|
}
|
|
26
|
+
interface ChatMessageEvent {
|
|
27
|
+
id: string;
|
|
28
|
+
chatroom_id: number;
|
|
29
|
+
content: string;
|
|
30
|
+
type: string;
|
|
31
|
+
created_at: string;
|
|
32
|
+
sender: {
|
|
33
|
+
id: number;
|
|
34
|
+
username: string;
|
|
35
|
+
slug?: string;
|
|
36
|
+
identity: {
|
|
37
|
+
color: string;
|
|
38
|
+
badges: Array<{
|
|
39
|
+
type: string;
|
|
40
|
+
text: string;
|
|
41
|
+
count?: number;
|
|
42
|
+
}>;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
}
|
|
25
46
|
export {};
|
package/dist/kick.js
CHANGED
|
@@ -62,7 +62,7 @@ export class KickPusher {
|
|
|
62
62
|
console.log(`Connected to Kick Pusher (${this.channel_name})`);
|
|
63
63
|
}
|
|
64
64
|
onChatMessage(data) {
|
|
65
|
-
|
|
65
|
+
this.public_listeners.raw_message?.(data);
|
|
66
66
|
const text = data.content;
|
|
67
67
|
const emote_matches = [...data.content.matchAll(/\[emote:\d+:[a-zA-Z0-9]*\]/g)];
|
|
68
68
|
console.log(emote_matches);
|
package/dist/twitch.d.ts
CHANGED
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
import { WebSocket } from 'partysocket';
|
|
2
|
-
import { type ClearMessages, type DeleteMessage, type Message, type Event, type EmoteURLsByName, type
|
|
2
|
+
import { type ClearMessages, type DeleteMessage, type Message, type Event, type EmoteURLsByName, type BadgeURLsBySetIDAndVersionIDOrAny } from './index.js';
|
|
3
3
|
type EventCallbackFunctions = {
|
|
4
|
-
message: (
|
|
4
|
+
message: (message: Message) => unknown;
|
|
5
5
|
clear_messages: (data: ClearMessages) => unknown;
|
|
6
6
|
delete_message: (data: DeleteMessage) => unknown;
|
|
7
|
-
event: (
|
|
7
|
+
event: (event: Event) => unknown;
|
|
8
|
+
raw_message: (message: IRC_Message) => unknown;
|
|
8
9
|
};
|
|
9
10
|
type EventNames = keyof EventCallbackFunctions;
|
|
10
11
|
export declare class TwitchIRC {
|
|
11
12
|
channel_name?: string;
|
|
12
13
|
assets: {
|
|
13
14
|
external_emotes: EmoteURLsByName;
|
|
14
|
-
badges:
|
|
15
|
+
badges: BadgeURLsBySetIDAndVersionIDOrAny;
|
|
15
16
|
};
|
|
16
17
|
latency: number;
|
|
17
18
|
private ping;
|
|
18
19
|
private public_listeners;
|
|
19
20
|
socket?: WebSocket;
|
|
21
|
+
ws?: WebSocket | undefined;
|
|
22
|
+
constructor(ws?: WebSocket);
|
|
20
23
|
connect(channel?: {
|
|
21
24
|
channelName?: string;
|
|
22
25
|
}): void;
|
|
@@ -33,4 +36,37 @@ export declare class TwitchIRC {
|
|
|
33
36
|
private send;
|
|
34
37
|
private onMessage;
|
|
35
38
|
}
|
|
39
|
+
type IRC_Message = {
|
|
40
|
+
[C in CommandType]: {
|
|
41
|
+
channel: string;
|
|
42
|
+
command: C;
|
|
43
|
+
params: string[];
|
|
44
|
+
source: RawSource | undefined;
|
|
45
|
+
tags: SpecificRawTags<C> | undefined;
|
|
46
|
+
};
|
|
47
|
+
}[CommandType];
|
|
48
|
+
type RAW_TAGS = typeof RAW_TAGS;
|
|
49
|
+
type CommandType = keyof RAW_TAGS;
|
|
50
|
+
type SpecificRawTags<Command extends CommandType> = Record<RAW_TAGS[Command][number], string | undefined>;
|
|
51
|
+
type RawSource = {
|
|
52
|
+
host: string;
|
|
53
|
+
nick?: string | undefined;
|
|
54
|
+
user?: string | undefined;
|
|
55
|
+
};
|
|
56
|
+
declare const RAW_TAGS: {
|
|
57
|
+
readonly CLEARCHAT: readonly ["ban-duration", "room-id", "target-user-id", "tmi-sent-ts"];
|
|
58
|
+
readonly CLEARMSG: readonly ["login", "room-id", "target-msg-id", "tmi-sent-ts"];
|
|
59
|
+
readonly GLOBALUSERSTATE: readonly ["badge-info", "badges", "color", "display-name", "emote-sets", "turbo", "user-id", "user-type"];
|
|
60
|
+
readonly HOSTTARGET: readonly [];
|
|
61
|
+
readonly NOTICE: readonly ["msg-id", "target-user-id"];
|
|
62
|
+
readonly PART: readonly [];
|
|
63
|
+
readonly PING: readonly [];
|
|
64
|
+
readonly PONG: readonly [];
|
|
65
|
+
readonly PRIVMSG: readonly ["badge-info", "badges", "bits", "color", "display-name", "emotes", "emote-only", "id", "mod", "custom-reward-id", "reply-thread-parent-display-name", "reply-thread-parent-user-id", "pinned-chat-paid-amount", "pinned-chat-paid-currency", "pinned-chat-paid-exponent", "pinned-chat-paid-level", "pinned-chat-paid-is-system-message", "reply-parent-msg-id", "reply-parent-user-id", "reply-parent-user-login", "reply-parent-display-name", "reply-parent-msg-body", "reply-thread-parent-msg-id", "reply-thread-parent-user-login", "room-id", "subscriber", "tmi-sent-ts", "turbo", "user-id", "user-type", "vip", "client-nonce", "first-msg", "flags", "returning-chatter"];
|
|
66
|
+
readonly RECONNECT: readonly [];
|
|
67
|
+
readonly ROOMSTATE: readonly ["emote-only", "followers-only", "r9k", "room-id", "slow", "subs-only"];
|
|
68
|
+
readonly USERNOTICE: readonly ["badge-info", "badges", "color", "display-name", "emotes", "id", "login", "mod", "msg-id", "room-id", "subscriber", "system-msg", "tmi-sent-ts", "turbo", "user-id", "user-type", "vip", "flags", "msg-param-cumulative-months", "msg-param-displayName", "msg-param-login", "msg-param-multimonth-duration", "msg-param-multimonth-tenure", "msg-param-was-gifted=false", "msg-param-months", "msg-param-promo-gift-total", "msg-param-promo-name", "msg-param-recipient-display-name", "msg-param-recipient-id", "msg-param-recipient-user-name", "msg-param-sender-login", "msg-param-sender-name", "msg-param-should-share-streak", "msg-param-streak-months", "msg-param-sub-plan", "msg-param-sub-plan-name", "msg-param-viewerCount", "msg-param-ritual-name", "msg-param-threshold", "msg-param-gift-months", "msg-param-was-gifted", "msg-param-community-gift-id", "msg-param-mass-gift-count", "msg-param-origin-id"];
|
|
69
|
+
readonly USERSTATE: readonly ["badge-info", "badges", "color", "display-name", "emote-sets", "id", "mod", "subscriber", "turbo", "user-type"];
|
|
70
|
+
readonly WHISPER: readonly ["badges", "color", "display-name", "emotes", "message-id", "thread-id", "turbo", "user-id", "user-type"];
|
|
71
|
+
};
|
|
36
72
|
export {};
|
package/dist/twitch.js
CHANGED
|
@@ -13,6 +13,10 @@ export class TwitchIRC {
|
|
|
13
13
|
ping = {};
|
|
14
14
|
public_listeners = {};
|
|
15
15
|
socket;
|
|
16
|
+
ws;
|
|
17
|
+
constructor(ws) {
|
|
18
|
+
this.ws = ws;
|
|
19
|
+
}
|
|
16
20
|
connect(channel) {
|
|
17
21
|
if (channel?.channelName)
|
|
18
22
|
this.channel_name = channel.channelName;
|
|
@@ -20,11 +24,12 @@ export class TwitchIRC {
|
|
|
20
24
|
return console.error('channel_name not specified');
|
|
21
25
|
console.log(`connecting to ${this.channel_name}...`);
|
|
22
26
|
this.socket?.close();
|
|
23
|
-
this.socket = new WebSocket('wss://irc-ws.chat.twitch.tv'
|
|
27
|
+
this.socket = new WebSocket('wss://irc-ws.chat.twitch.tv', null, {
|
|
28
|
+
WebSocket: this.ws,
|
|
29
|
+
});
|
|
24
30
|
this.socket.onopen = () => this.onOpen();
|
|
25
31
|
this.socket.onclose = () => this.onClose();
|
|
26
32
|
this.socket.onmessage = (event) => this.onMessage(event);
|
|
27
|
-
console.log(parseIRCLine(`@badge-info=;badges=turbo/1;color=#9ACD32;display-name=TestChannel;emotes=;id=3d830f12-795c-447d-af3c-ea05e40fbddb;login=testchannel;mod=0;msg-id=raid;msg-param-displayName=TestChannel;msg-param-login=testchannel;msg-param-viewerCount=15;room-id=33332222;subscriber=0;system-msg=15\sraiders\sfrom\sTestChannel\shave\sjoined\n!;tmi-sent-ts=1507246572675;turbo=1;user-id=123456;user-type= :tmi.twitch.tv USERNOTICE #othertestchannel`));
|
|
28
33
|
}
|
|
29
34
|
disconnect() {
|
|
30
35
|
this.socket?.close();
|
|
@@ -72,6 +77,7 @@ export class TwitchIRC {
|
|
|
72
77
|
const lines = String(event.data).trim().split('\r\n');
|
|
73
78
|
const messages = lines.map(parseIRCLine);
|
|
74
79
|
messages.forEach((message) => {
|
|
80
|
+
this.public_listeners.raw_message?.(message);
|
|
75
81
|
switch (message.command) {
|
|
76
82
|
case 'PONG': {
|
|
77
83
|
if (!this.ping.lastSentTimestamp)
|
|
@@ -183,7 +189,7 @@ export class TwitchIRC {
|
|
|
183
189
|
const [set_id, version] = badge.split('/');
|
|
184
190
|
if (!set_id || !version)
|
|
185
191
|
return [];
|
|
186
|
-
const url = this.assets.badges[set_id]?.[version];
|
|
192
|
+
const url = this.assets.badges[set_id]?.[version] ?? this.assets.badges[set_id]?.['*'];
|
|
187
193
|
if (!url)
|
|
188
194
|
return [];
|
|
189
195
|
return {
|
|
@@ -194,7 +200,7 @@ export class TwitchIRC {
|
|
|
194
200
|
}) ?? [],
|
|
195
201
|
color: tags.color ?? '#FFFFFF',
|
|
196
202
|
id: tags['user-id'],
|
|
197
|
-
username: '
|
|
203
|
+
username: (tags['display-name'] ?? 'Unknown').toLowerCase(),
|
|
198
204
|
display_name: tags['display-name'] ?? 'Unknown',
|
|
199
205
|
roles: {},
|
|
200
206
|
},
|
package/package.json
CHANGED
|
@@ -1,52 +1,54 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
2
|
+
"name": "multichat-ts",
|
|
3
|
+
"version": "0.0.4",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Receive type-safe realtime events for chat-related messages on multiple platforms (Twitch, Kick)",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/0Abdullah/multichat-ts.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/0Abdullah/multichat-ts",
|
|
11
|
+
"main": "dist/index.js",
|
|
12
|
+
"types": "dist/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc",
|
|
18
|
+
"prepublishOnly": "pnpm build",
|
|
19
|
+
"pub": "npm publish --access public",
|
|
20
|
+
"lint": "eslint .",
|
|
21
|
+
"lint:fix": "eslint . --fix",
|
|
22
|
+
"format": "prettier --check src",
|
|
23
|
+
"format:fix": "prettier --write src"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"chat",
|
|
27
|
+
"multichat",
|
|
28
|
+
"twitch",
|
|
29
|
+
"kick",
|
|
30
|
+
"realtime",
|
|
31
|
+
"irc",
|
|
32
|
+
"pusher",
|
|
33
|
+
"typescript",
|
|
34
|
+
"ts"
|
|
35
|
+
],
|
|
36
|
+
"author": {
|
|
37
|
+
"name": "Abdullah",
|
|
38
|
+
"url": "https://github.com/0Abdullah"
|
|
39
|
+
},
|
|
40
|
+
"license": "MIT",
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@eslint/js": "^9.10.0",
|
|
43
|
+
"@types/node": "^22.5.4",
|
|
44
|
+
"eslint": "^9.10.0",
|
|
45
|
+
"eslint-config-prettier": "^9.1.0",
|
|
46
|
+
"prettier": "^3.3.3",
|
|
47
|
+
"typescript": "^5.5.4",
|
|
48
|
+
"typescript-eslint": "^8.4.0"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"partysocket": "^1.0.2",
|
|
52
|
+
"pusher-js": "8.4.0-rc2"
|
|
53
|
+
}
|
|
54
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -155,10 +155,10 @@ export type BadgeURLsByNameOrCount = {
|
|
|
155
155
|
};
|
|
156
156
|
};
|
|
157
157
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
158
|
+
type StringOrAny = '*' | (string & Record<never, never>);
|
|
159
|
+
|
|
160
|
+
export type BadgeURLsBySetIDAndVersionIDOrAny = {
|
|
161
|
+
[badge_set_id: string]: Record<StringOrAny, string>;
|
|
162
162
|
};
|
|
163
163
|
|
|
164
164
|
export type EmoteURLsByName = {
|
package/src/kick.ts
CHANGED
|
@@ -8,7 +8,8 @@ import {
|
|
|
8
8
|
} from './index.js';
|
|
9
9
|
|
|
10
10
|
type EventCallbackFunctions = {
|
|
11
|
-
message: (
|
|
11
|
+
message: (message: Message) => unknown;
|
|
12
|
+
raw_message: (message: ChatMessageEvent) => unknown;
|
|
12
13
|
};
|
|
13
14
|
|
|
14
15
|
type EventNames = keyof EventCallbackFunctions;
|
|
@@ -109,8 +110,7 @@ export class KickPusher {
|
|
|
109
110
|
}
|
|
110
111
|
|
|
111
112
|
private onChatMessage(data: ChatMessageEvent) {
|
|
112
|
-
|
|
113
|
-
|
|
113
|
+
this.public_listeners.raw_message?.(data);
|
|
114
114
|
const text = data.content;
|
|
115
115
|
const emote_matches = [...data.content.matchAll(/\[emote:\d+:[a-zA-Z0-9]*\]/g)];
|
|
116
116
|
console.log(emote_matches);
|
package/src/twitch.ts
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
type Message,
|
|
8
8
|
type Event,
|
|
9
9
|
type EmoteURLsByName,
|
|
10
|
-
type
|
|
10
|
+
type BadgeURLsBySetIDAndVersionIDOrAny,
|
|
11
11
|
} from './index.js';
|
|
12
12
|
|
|
13
13
|
const ANONYMOUS_IRC_PASS = 'SCHMOOPIIE';
|
|
@@ -16,10 +16,11 @@ const PING_INTERVAL_MS = 30_000;
|
|
|
16
16
|
const PING_TIMEOUT_MS = 10_000;
|
|
17
17
|
|
|
18
18
|
type EventCallbackFunctions = {
|
|
19
|
-
message: (
|
|
19
|
+
message: (message: Message) => unknown;
|
|
20
20
|
clear_messages: (data: ClearMessages) => unknown;
|
|
21
21
|
delete_message: (data: DeleteMessage) => unknown;
|
|
22
|
-
event: (
|
|
22
|
+
event: (event: Event) => unknown;
|
|
23
|
+
raw_message: (message: IRC_Message) => unknown;
|
|
23
24
|
};
|
|
24
25
|
|
|
25
26
|
type EventNames = keyof EventCallbackFunctions;
|
|
@@ -28,7 +29,7 @@ export class TwitchIRC {
|
|
|
28
29
|
public channel_name?: string;
|
|
29
30
|
public assets: {
|
|
30
31
|
external_emotes: EmoteURLsByName;
|
|
31
|
-
badges:
|
|
32
|
+
badges: BadgeURLsBySetIDAndVersionIDOrAny;
|
|
32
33
|
} = {
|
|
33
34
|
external_emotes: {},
|
|
34
35
|
badges: {},
|
|
@@ -44,6 +45,11 @@ export class TwitchIRC {
|
|
|
44
45
|
private public_listeners: Partial<EventCallbackFunctions> = {};
|
|
45
46
|
|
|
46
47
|
public socket?: WebSocket;
|
|
48
|
+
public ws?: WebSocket | undefined;
|
|
49
|
+
|
|
50
|
+
constructor(ws?: WebSocket) {
|
|
51
|
+
this.ws = ws;
|
|
52
|
+
}
|
|
47
53
|
|
|
48
54
|
public connect(channel?: { channelName?: string }) {
|
|
49
55
|
if (channel?.channelName) this.channel_name = channel.channelName;
|
|
@@ -53,17 +59,12 @@ export class TwitchIRC {
|
|
|
53
59
|
|
|
54
60
|
this.socket?.close();
|
|
55
61
|
|
|
56
|
-
this.socket = new WebSocket('wss://irc-ws.chat.twitch.tv'
|
|
62
|
+
this.socket = new WebSocket('wss://irc-ws.chat.twitch.tv', null, {
|
|
63
|
+
WebSocket: this.ws,
|
|
64
|
+
});
|
|
57
65
|
this.socket.onopen = () => this.onOpen();
|
|
58
66
|
this.socket.onclose = () => this.onClose();
|
|
59
67
|
this.socket.onmessage = (event) => this.onMessage(event);
|
|
60
|
-
|
|
61
|
-
console.log(
|
|
62
|
-
parseIRCLine(
|
|
63
|
-
// eslint-disable-next-line no-useless-escape
|
|
64
|
-
`@badge-info=;badges=turbo/1;color=#9ACD32;display-name=TestChannel;emotes=;id=3d830f12-795c-447d-af3c-ea05e40fbddb;login=testchannel;mod=0;msg-id=raid;msg-param-displayName=TestChannel;msg-param-login=testchannel;msg-param-viewerCount=15;room-id=33332222;subscriber=0;system-msg=15\sraiders\sfrom\sTestChannel\shave\sjoined\n!;tmi-sent-ts=1507246572675;turbo=1;user-id=123456;user-type= :tmi.twitch.tv USERNOTICE #othertestchannel`,
|
|
65
|
-
),
|
|
66
|
-
);
|
|
67
68
|
}
|
|
68
69
|
|
|
69
70
|
public disconnect() {
|
|
@@ -122,6 +123,7 @@ export class TwitchIRC {
|
|
|
122
123
|
const lines = String(event.data).trim().split('\r\n');
|
|
123
124
|
const messages = lines.map(parseIRCLine);
|
|
124
125
|
messages.forEach((message) => {
|
|
126
|
+
this.public_listeners.raw_message?.(message);
|
|
125
127
|
switch (message.command) {
|
|
126
128
|
case 'PONG': {
|
|
127
129
|
if (!this.ping.lastSentTimestamp) return console.error('got PONG without sending PING');
|
|
@@ -244,7 +246,8 @@ export class TwitchIRC {
|
|
|
244
246
|
const [set_id, version] = badge.split('/');
|
|
245
247
|
if (!set_id || !version) return [];
|
|
246
248
|
|
|
247
|
-
const url =
|
|
249
|
+
const url =
|
|
250
|
+
this.assets.badges[set_id]?.[version] ?? this.assets.badges[set_id]?.['*'];
|
|
248
251
|
if (!url) return [];
|
|
249
252
|
|
|
250
253
|
return {
|
|
@@ -255,7 +258,7 @@ export class TwitchIRC {
|
|
|
255
258
|
}) ?? [],
|
|
256
259
|
color: tags.color ?? '#FFFFFF',
|
|
257
260
|
id: tags['user-id'],
|
|
258
|
-
username: '
|
|
261
|
+
username: (tags['display-name'] ?? 'Unknown').toLowerCase(),
|
|
259
262
|
display_name: tags['display-name'] ?? 'Unknown',
|
|
260
263
|
roles: {},
|
|
261
264
|
},
|