multichat-ts 0.0.87 → 0.0.90

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.
@@ -1,206 +0,0 @@
1
- import Pusher from 'pusher-js/worker';
2
- import { type BadgeURLsByNameOrCount, type EmoteURLsByName, type Message } from './index.js';
3
- type ConnectionState = 'initialized' | 'connecting' | 'connected' | 'unavailable' | 'failed';
4
- type ConnectionStateEvent = {
5
- previous: ConnectionState;
6
- current: ConnectionState;
7
- };
8
- type EventCallbackFunctions = {
9
- message: (message: Message) => unknown;
10
- subscription: (data: ChatSubscriptionEvent) => unknown;
11
- gifted: (data: ChatGiftedEvent) => unknown;
12
- raw_message: (message: ChatMessageEvent) => unknown;
13
- connection_state_changed: (state: ConnectionStateEvent) => unknown;
14
- };
15
- type EventNames = keyof EventCallbackFunctions;
16
- export declare class KickPusher {
17
- kick_pusher_key: string;
18
- channel_name?: string;
19
- private assets;
20
- private public_listeners;
21
- socket?: Pusher;
22
- isConnected: boolean;
23
- setBadges(badges: BadgeURLsByNameOrCount): void;
24
- setExternalEmotes(external_emotes: EmoteURLsByName): void;
25
- getStoredBadges(): BadgeURLsByNameOrCount;
26
- getStoredExternalEmotes(): EmoteURLsByName;
27
- connect(channel?: {
28
- channelName?: string;
29
- }, get_channel?: (channelName: string) => Promise<GetChannelResponse | undefined>): Promise<void>;
30
- disconnect(): void;
31
- on<EventName extends EventNames>(event_name: EventName, callback_fn: EventCallbackFunctions[EventName]): void;
32
- private onSubscriptionSuccess;
33
- private onChatSubscription;
34
- private onChatGifted;
35
- private onChatMessage;
36
- }
37
- export interface GetChannelResponse {
38
- id: number;
39
- user_id: number;
40
- slug: string;
41
- is_banned: boolean;
42
- playback_url?: string;
43
- vod_enabled: boolean;
44
- subscription_enabled: boolean;
45
- followers_count: number;
46
- following?: boolean;
47
- subscription?: unknown;
48
- subscriber_badges: Array<{
49
- id: number;
50
- channel_id: number;
51
- months: number;
52
- badge_image: {
53
- srcset: string;
54
- src: string;
55
- };
56
- }>;
57
- banner_image?: {
58
- url: string;
59
- };
60
- livestream?: ChannelLivestream;
61
- role?: unknown;
62
- muted: boolean;
63
- follower_badges: unknown[];
64
- offline_banner_image: unknown;
65
- verified: boolean;
66
- recent_categories: Array<{
67
- id: number;
68
- category_id: number;
69
- name: string;
70
- slug: string;
71
- tags: string[];
72
- description?: string;
73
- deleted_at: unknown;
74
- viewers: number;
75
- banner: {
76
- responsive: string;
77
- url: string;
78
- };
79
- category: {
80
- id: number;
81
- name: string;
82
- slug: string;
83
- icon: string;
84
- };
85
- }>;
86
- can_host: boolean;
87
- user: {
88
- id: number;
89
- username: string;
90
- agreed_to_terms: true;
91
- email_verified_at: Date;
92
- bio?: string;
93
- country?: string;
94
- state?: string;
95
- city?: string;
96
- instagram?: string;
97
- twitter?: string;
98
- youtube?: string;
99
- discord?: string;
100
- tiktok?: string;
101
- facebook?: string;
102
- profile_pic?: string;
103
- };
104
- chatroom: ChannelChatroom;
105
- ascending_links?: Array<{
106
- id: number;
107
- channel_id: number;
108
- description: string;
109
- link: string;
110
- created_at: Date;
111
- updated_at: Date;
112
- order: number;
113
- title: string;
114
- }>;
115
- }
116
- export interface ChannelLivestream {
117
- id: number;
118
- slug: string;
119
- channel_id: number;
120
- created_at: Date;
121
- session_title: string;
122
- is_live: boolean;
123
- risk_level_id: unknown;
124
- start_time: Date;
125
- source: unknown;
126
- twitch_channel: unknown;
127
- duration: number;
128
- language: string;
129
- is_mature: boolean;
130
- viewer_count: number;
131
- thumbnail: {
132
- url: string;
133
- };
134
- categories: Array<{
135
- id: number;
136
- category_id: number;
137
- name: string;
138
- slug: string;
139
- tags: string[];
140
- description?: string;
141
- deleted_at: unknown;
142
- viewers: number;
143
- category: {
144
- id: number;
145
- name: string;
146
- slug: string;
147
- icon: string;
148
- };
149
- }>;
150
- tags: unknown[];
151
- }
152
- export interface ChannelChatroom {
153
- id: number;
154
- chatable_type: string;
155
- channel_id: string;
156
- created_at: Date;
157
- updated_at: Date;
158
- chat_mode_old: string;
159
- chat_mode: string;
160
- slow_mode: boolean;
161
- chatable_id: number;
162
- followers_mode: boolean;
163
- subscribers_mode: boolean;
164
- emotes_mode: boolean;
165
- message_interval: number;
166
- following_min_duration: number;
167
- }
168
- export interface ChatMessageEvent {
169
- id: string;
170
- chatroom_id: number;
171
- content: string;
172
- type: 'message' | 'celebration';
173
- created_at: string;
174
- metadata?: {
175
- celebration: {
176
- created_at: string;
177
- id: string;
178
- total_months: number;
179
- type: 'subscription_renewed';
180
- };
181
- };
182
- sender: {
183
- id: number;
184
- username: string;
185
- slug?: string;
186
- identity: {
187
- color: string;
188
- badges: Array<{
189
- type: string;
190
- text: string;
191
- count?: number;
192
- }>;
193
- };
194
- };
195
- }
196
- export interface ChatSubscriptionEvent {
197
- chatroom_id: string;
198
- username: string;
199
- months: number;
200
- }
201
- export interface ChatGiftedEvent {
202
- chatroom_id: string;
203
- gifted_usernames: string[];
204
- gifter_username: string;
205
- }
206
- export {};
@@ -1,220 +0,0 @@
1
- import Pusher from 'pusher-js/worker';
2
- const DEFAULT_KICK_PUSHER_KEY = '32cbd69e4b950bf97679';
3
- export class KickPusher {
4
- kick_pusher_key = DEFAULT_KICK_PUSHER_KEY;
5
- channel_name;
6
- assets = {
7
- external_emotes: {},
8
- badges: {
9
- founder: '/svgs/badges/default-kick/founder.svg',
10
- moderator: '/svgs/badges/default-kick/moderator.svg',
11
- og: '/svgs/badges/default-kick/og.svg',
12
- sub_gifter: {
13
- 1: '/svgs/badges/default-kick/sub-gifter-blue.svg',
14
- 25: '/svgs/badges/default-kick/sub-gifter-purple.svg',
15
- 50: '/svgs/badges/default-kick/sub-gifter-red.svg',
16
- 100: '/svgs/badges/default-kick/sub-gifter-yellow.svg',
17
- 200: '/svgs/badges/default-kick/sub-gifter-green.svg',
18
- },
19
- verified: '/svgs/badges/default-kick/verified.svg',
20
- vip: '/svgs/badges/default-kick/vip.svg',
21
- broadcaster: '/svgs/badges/default-kick/broadcaster.svg',
22
- staff: '/svgs/badges/default-kick/staff.svg',
23
- },
24
- };
25
- public_listeners = {};
26
- socket;
27
- isConnected = false;
28
- setBadges(badges) {
29
- this.assets.badges = { ...this.assets.badges, ...badges };
30
- }
31
- setExternalEmotes(external_emotes) {
32
- this.assets.external_emotes = { ...this.assets.external_emotes, ...external_emotes };
33
- }
34
- getStoredBadges() {
35
- return this.assets.badges;
36
- }
37
- getStoredExternalEmotes() {
38
- return this.assets.external_emotes;
39
- }
40
- async connect(channel, get_channel = async (channelName) => {
41
- const res = await fetch(`https://kick.com/api/v2/channels/${channelName}`, {
42
- headers: {
43
- accept: 'aplication/json',
44
- 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
45
- },
46
- });
47
- const json = await res.json();
48
- return json;
49
- }) {
50
- if (channel?.channelName)
51
- this.channel_name = channel.channelName;
52
- if (!this.channel_name)
53
- return console.error('channel_name not specified');
54
- console.log(`connecting to ${this.channel_name}...`);
55
- const channel_response = await get_channel(this.channel_name);
56
- if (!channel_response)
57
- return console.error('Failed to connect to Kick.com chat');
58
- channel_response.subscriber_badges.forEach((subscriber_badge) => {
59
- this.assets.badges['subscriber'] = {
60
- ...(this.assets.badges['subscriber'] ?? {}),
61
- [subscriber_badge.months]: subscriber_badge.badge_image.src,
62
- };
63
- });
64
- this.disconnect();
65
- this.socket = new Pusher(this.kick_pusher_key, {
66
- cluster: 'us2',
67
- });
68
- this.socket
69
- .subscribe(`chatrooms.${channel_response.chatroom.id}.v2`)
70
- .bind('pusher:subscription_succeeded', () => this.onSubscriptionSuccess('pusher:subscription_succeeded'))
71
- .bind('App\\Events\\ChatMessageEvent', (data) => this.onChatMessage(data))
72
- .bind('App\\Events\\SubscriptionEvent', (data) => this.onChatSubscription(data))
73
- .bind('App\\Events\\GiftedSubscriptionsEvent', (data) => this.onChatGifted(data));
74
- this.socket.connection.bind('state_change', (state) => {
75
- switch (state.current) {
76
- case 'connected': {
77
- this.isConnected = true;
78
- console.log(`Connected to Kick Pusher (${this.channel_name})!`);
79
- break;
80
- }
81
- case 'connecting': {
82
- this.isConnected = false;
83
- console.log(`Connecting to Kick Pusher (${this.channel_name})...`);
84
- break;
85
- }
86
- case 'failed': {
87
- this.isConnected = false;
88
- console.log(`Failed to connect to Kick Pusher (${this.channel_name})`);
89
- break;
90
- }
91
- case 'unavailable': {
92
- this.isConnected = false;
93
- console.log(`Disconnected from Kick Pusher (${this.channel_name})`);
94
- break;
95
- }
96
- default: {
97
- this.isConnected = false;
98
- break;
99
- }
100
- }
101
- this.public_listeners.connection_state_changed?.(state);
102
- });
103
- }
104
- disconnect() {
105
- this.socket?.disconnect();
106
- this.socket?.unbind_all();
107
- }
108
- on(event_name, callback_fn) {
109
- this.public_listeners[event_name] = callback_fn;
110
- }
111
- onSubscriptionSuccess(channel) {
112
- console.log(`Subscribed to Channel on Kick Pusher (${channel})`);
113
- }
114
- onChatSubscription(data) {
115
- this.public_listeners.subscription?.(data);
116
- }
117
- onChatGifted(data) {
118
- this.public_listeners.gifted?.(data);
119
- }
120
- onChatMessage(data) {
121
- this.public_listeners.raw_message?.(data);
122
- const text = data.content;
123
- const emote_matches = [...data.content.matchAll(/\[emote:\d+:[a-zA-Z0-9]*\]/g)];
124
- const body = [];
125
- emote_matches.forEach((match) => {
126
- const emote_string = match[0];
127
- const emote_parts = emote_string.slice(1, emote_string.length - 1).split(':');
128
- const emote_id = emote_parts[1];
129
- if (!emote_id)
130
- return;
131
- console.log(emote_id);
132
- body.push({
133
- type: 'emote',
134
- start_inclusive: match.index,
135
- end_exclusive: match.index + emote_string.length,
136
- url: `https://files.kick.com/emotes/${emote_id}/fullsize`,
137
- });
138
- });
139
- body.sort((a, b) => a.start_inclusive - b.start_inclusive);
140
- const old_body_length = body.length;
141
- if (old_body_length > 0) {
142
- body.forEach((segment, index) => {
143
- const previous_segment = body[index - 1];
144
- const text_start_inclusive = previous_segment?.end_exclusive !== undefined ? previous_segment.end_exclusive + 1 : 0;
145
- const text_end_exclusive = Math.max(0, segment.start_inclusive);
146
- if (text_end_exclusive - text_start_inclusive > 0) {
147
- body.push({
148
- type: 'text',
149
- text: text.slice(text_start_inclusive, text_end_exclusive),
150
- start_inclusive: text_start_inclusive,
151
- end_exclusive: text_end_exclusive,
152
- });
153
- }
154
- if (index === old_body_length - 1 && segment.end_exclusive < text.length - 1) {
155
- body.push({
156
- type: 'text',
157
- text: text.slice(segment.end_exclusive),
158
- start_inclusive: segment.end_exclusive,
159
- end_exclusive: text.length,
160
- });
161
- }
162
- });
163
- }
164
- else {
165
- body.push({
166
- type: 'text',
167
- text,
168
- start_inclusive: 0,
169
- end_exclusive: text.length,
170
- });
171
- }
172
- body.sort((a, b) => a.start_inclusive - b.start_inclusive);
173
- const message = {
174
- id: data.id,
175
- user: {
176
- id: `${data.sender.id}`,
177
- username: data.sender.slug ?? data.sender.username.toLowerCase(),
178
- display_name: data.sender.username,
179
- roles: {},
180
- color: data.sender.identity.color,
181
- badges: data.sender.identity.badges.flatMap((badge) => {
182
- let badge_url = undefined;
183
- const badge_url_or_counts = this.assets.badges[badge.type];
184
- const badge_count = badge.count;
185
- if (typeof badge_url_or_counts === 'string')
186
- badge_url = badge_url_or_counts;
187
- else if (typeof badge_url_or_counts === 'object' && badge_count !== undefined) {
188
- const badge_entry_by_count = Object.entries(badge_url_or_counts)
189
- .sort(([a_min_count], [b_min_count]) => Number(a_min_count) - Number(b_min_count))
190
- .find(([min_count]) => badge_count >= Number(min_count));
191
- if (badge_entry_by_count)
192
- badge_url = badge_entry_by_count[1];
193
- }
194
- if (!badge_url)
195
- return [];
196
- return {
197
- set_id: badge.type,
198
- url: badge_url,
199
- info: String(badge.count),
200
- };
201
- }),
202
- },
203
- body,
204
- channel: {
205
- room_id: String(data.chatroom_id),
206
- name: this.channel_name ?? 'unknown',
207
- },
208
- raw_text: data.content,
209
- timestamp_sent: Date.parse(data.created_at),
210
- };
211
- if (data.type === 'celebration' && data.metadata?.celebration) {
212
- message.resubscription = {
213
- id: data.metadata.celebration.id,
214
- months: data.metadata.celebration.total_months,
215
- subscribed_since_timestamp: data.metadata.celebration.created_at,
216
- };
217
- }
218
- this.public_listeners.message?.(message);
219
- }
220
- }
@@ -1,73 +0,0 @@
1
- import { WebSocket } from 'partysocket';
2
- import { type ClearMessages, type DeleteMessage, type Message, type Event, type EmoteURLsByName, type BadgeURLsBySetIDOrSetIDAndVersion } from './index.js';
3
- type EventCallbackFunctions = {
4
- message: (message: Message) => unknown;
5
- clear_messages: (data: ClearMessages) => unknown;
6
- delete_message: (data: DeleteMessage) => unknown;
7
- event: (event: Event) => unknown;
8
- raw_message: (message: IRC_Message) => unknown;
9
- };
10
- type EventNames = keyof EventCallbackFunctions;
11
- export declare class TwitchIRC {
12
- channel_name?: string;
13
- private assets;
14
- latency: number;
15
- private ping;
16
- private public_listeners;
17
- socket?: WebSocket;
18
- ws?: WebSocket | undefined;
19
- constructor(ws?: WebSocket);
20
- setBadges(badges: BadgeURLsBySetIDOrSetIDAndVersion): void;
21
- setExternalEmotes(external_emotes: EmoteURLsByName): void;
22
- getStoredBadges(): BadgeURLsBySetIDOrSetIDAndVersion;
23
- getStoredExternalEmotes(): EmoteURLsByName;
24
- connect(channel?: {
25
- channelName?: string;
26
- }): void;
27
- disconnect(): void;
28
- on<EventName extends EventNames>(event_name: EventName, callback_fn: EventCallbackFunctions[EventName]): void;
29
- isConnected(): this is {
30
- socket: {
31
- readyState: typeof WebSocket.OPEN;
32
- } & WebSocket;
33
- };
34
- private onOpen;
35
- private onClose;
36
- private sendPing;
37
- private send;
38
- private onMessage;
39
- }
40
- type IRC_Message = {
41
- [C in CommandType]: {
42
- channel: string;
43
- command: C;
44
- params: string[];
45
- source: RawSource | undefined;
46
- tags: SpecificRawTags<C> | undefined;
47
- };
48
- }[CommandType];
49
- type RAW_TAGS = typeof RAW_TAGS;
50
- type CommandType = keyof RAW_TAGS;
51
- type SpecificRawTags<Command extends CommandType> = Record<RAW_TAGS[Command][number], string | undefined>;
52
- type RawSource = {
53
- host: string;
54
- nick?: string | undefined;
55
- user?: string | undefined;
56
- };
57
- declare const RAW_TAGS: {
58
- readonly CLEARCHAT: readonly ["ban-duration", "room-id", "target-user-id", "tmi-sent-ts"];
59
- readonly CLEARMSG: readonly ["login", "room-id", "target-msg-id", "tmi-sent-ts"];
60
- readonly GLOBALUSERSTATE: readonly ["badge-info", "badges", "color", "display-name", "emote-sets", "turbo", "user-id", "user-type"];
61
- readonly HOSTTARGET: readonly [];
62
- readonly NOTICE: readonly ["msg-id", "target-user-id"];
63
- readonly PART: readonly [];
64
- readonly PING: readonly [];
65
- readonly PONG: readonly [];
66
- 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"];
67
- readonly RECONNECT: readonly [];
68
- readonly ROOMSTATE: readonly ["emote-only", "followers-only", "r9k", "room-id", "slow", "subs-only"];
69
- 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"];
70
- readonly USERSTATE: readonly ["badge-info", "badges", "color", "display-name", "emote-sets", "id", "mod", "subscriber", "turbo", "user-type"];
71
- readonly WHISPER: readonly ["badges", "color", "display-name", "emotes", "message-id", "thread-id", "turbo", "user-id", "user-type"];
72
- };
73
- export {};