streamops-twitch-connector 0.1.2 → 0.1.3
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,4 +1,5 @@
|
|
|
1
1
|
import type { EventSubConnectionState, EventSubNotificationHandler } from './types.js';
|
|
2
|
+
export type EventSubSessionHandler = (sessionId: string, isReconnectHandover: boolean) => Promise<void> | void;
|
|
2
3
|
export declare class EventSubClient {
|
|
3
4
|
private readonly onStateChange?;
|
|
4
5
|
private socket;
|
|
@@ -10,10 +11,12 @@ export declare class EventSubClient {
|
|
|
10
11
|
private intentionalClose;
|
|
11
12
|
private state;
|
|
12
13
|
private readonly handlers;
|
|
14
|
+
private readonly sessionHandlers;
|
|
13
15
|
constructor(onStateChange?: ((state: EventSubConnectionState) => void) | undefined);
|
|
14
16
|
get connectionState(): EventSubConnectionState;
|
|
15
17
|
get currentSessionId(): string | null;
|
|
16
18
|
onNotification(handler: EventSubNotificationHandler): () => void;
|
|
19
|
+
onSession(handler: EventSubSessionHandler): () => void;
|
|
17
20
|
connect(): Promise<void>;
|
|
18
21
|
disconnect(): Promise<void>;
|
|
19
22
|
private openSocket;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eventsub-client.d.ts","sourceRoot":"","sources":["../../src/eventsub/eventsub-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,uBAAuB,EAEvB,2BAA2B,EAC5B,MAAM,YAAY,CAAC;AAKpB,qBAAa,cAAc;
|
|
1
|
+
{"version":3,"file":"eventsub-client.d.ts","sourceRoot":"","sources":["../../src/eventsub/eventsub-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,uBAAuB,EAEvB,2BAA2B,EAC5B,MAAM,YAAY,CAAC;AAKpB,MAAM,MAAM,sBAAsB,GAAG,CACnC,SAAS,EAAE,MAAM,EACjB,mBAAmB,EAAE,OAAO,KACzB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAE1B,qBAAa,cAAc;IAcvB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC;IAbjC,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,uBAAuB,CAAM;IACrC,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,KAAK,CAA2C;IAExD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0C;IACnE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqC;gBAGlD,aAAa,CAAC,GAAE,CAC/B,KAAK,EAAE,uBAAuB,KAC3B,IAAI,aAAA;IAGX,IAAI,eAAe,IAAI,uBAAuB,CAE7C;IAED,IAAI,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAEpC;IAED,cAAc,CAAC,OAAO,EAAE,2BAA2B,GAAG,MAAM,IAAI;IAKhE,SAAS,CAAC,OAAO,EAAE,sBAAsB,GAAG,MAAM,IAAI;IAKhD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBjC,OAAO,CAAC,UAAU;YA8FJ,aAAa;IAuG3B,OAAO,CAAC,mBAAmB;IAuB3B,OAAO,CAAC,iBAAiB;IAiBzB,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,WAAW;CAIpB"}
|
|
@@ -11,6 +11,7 @@ export class EventSubClient {
|
|
|
11
11
|
intentionalClose = false;
|
|
12
12
|
state = 'disconnected';
|
|
13
13
|
handlers = new Set();
|
|
14
|
+
sessionHandlers = new Set();
|
|
14
15
|
constructor(onStateChange) {
|
|
15
16
|
this.onStateChange = onStateChange;
|
|
16
17
|
}
|
|
@@ -24,6 +25,10 @@ export class EventSubClient {
|
|
|
24
25
|
this.handlers.add(handler);
|
|
25
26
|
return () => this.handlers.delete(handler);
|
|
26
27
|
}
|
|
28
|
+
onSession(handler) {
|
|
29
|
+
this.sessionHandlers.add(handler);
|
|
30
|
+
return () => this.sessionHandlers.delete(handler);
|
|
31
|
+
}
|
|
27
32
|
async connect() {
|
|
28
33
|
this.intentionalClose = false;
|
|
29
34
|
this.clearReconnectTimer();
|
|
@@ -47,35 +52,53 @@ export class EventSubClient {
|
|
|
47
52
|
}
|
|
48
53
|
this.setState('disconnected');
|
|
49
54
|
}
|
|
50
|
-
openSocket(url) {
|
|
55
|
+
openSocket(url, isReconnectHandover = false) {
|
|
51
56
|
let socket;
|
|
52
57
|
try {
|
|
53
58
|
socket = new WebSocket(url);
|
|
54
59
|
}
|
|
55
60
|
catch (error) {
|
|
61
|
+
console.error('[EventSub] Failed to create WebSocket:', error);
|
|
56
62
|
this.scheduleReconnect();
|
|
57
63
|
throw new TwitchError('Unable to create Twitch EventSub WebSocket.', undefined, undefined, { cause: error });
|
|
58
64
|
}
|
|
65
|
+
const previousSocket = this.socket;
|
|
59
66
|
this.socket = socket;
|
|
67
|
+
if (previousSocket &&
|
|
68
|
+
previousSocket !== socket &&
|
|
69
|
+
previousSocket.readyState !== WebSocket.CLOSED) {
|
|
70
|
+
console.log('[EventSub] Replacing the previous WebSocket connection.');
|
|
71
|
+
}
|
|
60
72
|
socket.addEventListener('open', () => {
|
|
61
|
-
if (this.socket
|
|
62
|
-
|
|
73
|
+
if (this.socket !== socket) {
|
|
74
|
+
return;
|
|
63
75
|
}
|
|
76
|
+
console.log('[EventSub] WebSocket connected.');
|
|
77
|
+
this.setState('connected');
|
|
64
78
|
});
|
|
65
79
|
socket.addEventListener('message', (message) => {
|
|
66
80
|
if (this.socket !== socket) {
|
|
67
81
|
return;
|
|
68
82
|
}
|
|
69
|
-
|
|
70
|
-
|
|
83
|
+
const raw = String(message.data);
|
|
84
|
+
try {
|
|
85
|
+
const envelope = JSON.parse(raw);
|
|
86
|
+
console.log(`[EventSub] Received message type: ${envelope.metadata?.message_type ?? 'unknown'}`);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
console.warn('[EventSub] Received a non-JSON WebSocket message.');
|
|
90
|
+
}
|
|
91
|
+
void this.handleMessage(raw, isReconnectHandover).catch((error) => {
|
|
71
92
|
console.error('[EventSub] Failed to process message:', error);
|
|
72
93
|
});
|
|
73
94
|
});
|
|
74
95
|
socket.addEventListener('error', () => {
|
|
75
|
-
|
|
96
|
+
if (this.socket === socket) {
|
|
97
|
+
console.error('[EventSub] WebSocket error.');
|
|
98
|
+
}
|
|
76
99
|
});
|
|
77
|
-
socket.addEventListener('close', () => {
|
|
78
|
-
|
|
100
|
+
socket.addEventListener('close', (event) => {
|
|
101
|
+
console.log(`[EventSub] Socket closed: code=${event.code}, reason=${event.reason || '(none)'}`);
|
|
79
102
|
if (this.socket !== socket) {
|
|
80
103
|
return;
|
|
81
104
|
}
|
|
@@ -90,7 +113,7 @@ export class EventSubClient {
|
|
|
90
113
|
}
|
|
91
114
|
});
|
|
92
115
|
}
|
|
93
|
-
async handleMessage(raw) {
|
|
116
|
+
async handleMessage(raw, isReconnectHandover) {
|
|
94
117
|
const envelope = JSON.parse(raw);
|
|
95
118
|
const messageType = envelope.metadata?.message_type;
|
|
96
119
|
if (!messageType) {
|
|
@@ -107,20 +130,27 @@ export class EventSubClient {
|
|
|
107
130
|
session.keepalive_timeout_seconds ?? 10;
|
|
108
131
|
this.reconnectUrl = null;
|
|
109
132
|
this.resetKeepaliveTimer();
|
|
133
|
+
console.log(`[EventSub] Session established. Keepalive timeout: ${this.keepaliveTimeoutSeconds}s.`);
|
|
134
|
+
for (const handler of this.sessionHandlers) {
|
|
135
|
+
await handler(session.id, isReconnectHandover);
|
|
136
|
+
}
|
|
110
137
|
break;
|
|
111
138
|
}
|
|
112
139
|
case 'session_keepalive':
|
|
140
|
+
console.log('[EventSub] Keepalive received.');
|
|
113
141
|
this.resetKeepaliveTimer();
|
|
114
142
|
break;
|
|
115
143
|
case 'session_reconnect': {
|
|
116
144
|
const reconnectUrl = envelope.payload.session?.reconnect_url;
|
|
117
|
-
if (reconnectUrl) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
// Twitch expects the existing socket to remain alive until
|
|
121
|
-
// the replacement connection is established.
|
|
122
|
-
this.openSocket(reconnectUrl);
|
|
145
|
+
if (!reconnectUrl) {
|
|
146
|
+
console.warn('[EventSub] Reconnect message did not contain a reconnect URL.');
|
|
147
|
+
return;
|
|
123
148
|
}
|
|
149
|
+
console.log('[EventSub] Twitch requested a session handover.');
|
|
150
|
+
this.reconnectUrl = reconnectUrl;
|
|
151
|
+
this.clearKeepaliveTimer();
|
|
152
|
+
// The replacement connection inherits the existing subscriptions.
|
|
153
|
+
this.openSocket(reconnectUrl, true);
|
|
124
154
|
break;
|
|
125
155
|
}
|
|
126
156
|
case 'notification': {
|
|
@@ -136,6 +166,7 @@ export class EventSubClient {
|
|
|
136
166
|
break;
|
|
137
167
|
}
|
|
138
168
|
case 'session_reconnect_failed':
|
|
169
|
+
console.warn('[EventSub] Twitch reported that session handover failed.');
|
|
139
170
|
this.reconnectUrl = null;
|
|
140
171
|
this.scheduleReconnect();
|
|
141
172
|
break;
|
|
@@ -143,16 +174,17 @@ export class EventSubClient {
|
|
|
143
174
|
console.warn('[EventSub] Subscription revoked:', envelope.payload);
|
|
144
175
|
break;
|
|
145
176
|
default:
|
|
177
|
+
console.log(`[EventSub] Unhandled message type: ${messageType}`);
|
|
146
178
|
break;
|
|
147
179
|
}
|
|
148
180
|
}
|
|
149
181
|
resetKeepaliveTimer() {
|
|
150
182
|
this.clearKeepaliveTimer();
|
|
151
183
|
this.keepaliveTimer = setTimeout(() => {
|
|
152
|
-
console.warn(
|
|
184
|
+
console.warn(`[EventSub] No keepalive or notification received within ${this.keepaliveTimeoutSeconds}s.`);
|
|
153
185
|
const socket = this.socket;
|
|
154
186
|
this.socket = null;
|
|
155
|
-
if (socket) {
|
|
187
|
+
if (socket && socket.readyState !== WebSocket.CLOSED) {
|
|
156
188
|
socket.close();
|
|
157
189
|
}
|
|
158
190
|
if (!this.intentionalClose) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eventsub-client.js","sourceRoot":"","sources":["../../src/eventsub/eventsub-client.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAExD,MAAM,YAAY,GAAG,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"eventsub-client.js","sourceRoot":"","sources":["../../src/eventsub/eventsub-client.ts"],"names":[],"mappings":"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"}
|