@gamalan/pi-gateway 1.0.0

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.
Files changed (75) hide show
  1. package/README.md +366 -0
  2. package/config/config.default.json +51 -0
  3. package/dist/adapters/base.d.ts +85 -0
  4. package/dist/adapters/base.js +34 -0
  5. package/dist/adapters/base.js.map +1 -0
  6. package/dist/adapters/discord.d.ts +53 -0
  7. package/dist/adapters/discord.js +224 -0
  8. package/dist/adapters/discord.js.map +1 -0
  9. package/dist/adapters/index.d.ts +13 -0
  10. package/dist/adapters/index.js +8 -0
  11. package/dist/adapters/index.js.map +1 -0
  12. package/dist/adapters/slack.d.ts +49 -0
  13. package/dist/adapters/slack.js +231 -0
  14. package/dist/adapters/slack.js.map +1 -0
  15. package/dist/adapters/telegram.d.ts +64 -0
  16. package/dist/adapters/telegram.js +274 -0
  17. package/dist/adapters/telegram.js.map +1 -0
  18. package/dist/adapters/twitch.d.ts +75 -0
  19. package/dist/adapters/twitch.js +222 -0
  20. package/dist/adapters/twitch.js.map +1 -0
  21. package/dist/adapters/websocket.d.ts +30 -0
  22. package/dist/adapters/websocket.js +132 -0
  23. package/dist/adapters/websocket.js.map +1 -0
  24. package/dist/adapters/whatsapp.d.ts +49 -0
  25. package/dist/adapters/whatsapp.js +251 -0
  26. package/dist/adapters/whatsapp.js.map +1 -0
  27. package/dist/background/index.d.ts +1 -0
  28. package/dist/background/index.js +2 -0
  29. package/dist/background/index.js.map +1 -0
  30. package/dist/background/manager.d.ts +70 -0
  31. package/dist/background/manager.js +291 -0
  32. package/dist/background/manager.js.map +1 -0
  33. package/dist/index.d.ts +18 -0
  34. package/dist/index.js +1275 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/logger.d.ts +12 -0
  37. package/dist/logger.js +39 -0
  38. package/dist/logger.js.map +1 -0
  39. package/dist/paths.d.ts +14 -0
  40. package/dist/paths.js +32 -0
  41. package/dist/paths.js.map +1 -0
  42. package/dist/security/auth.d.ts +91 -0
  43. package/dist/security/auth.js +316 -0
  44. package/dist/security/auth.js.map +1 -0
  45. package/dist/security/index.d.ts +1 -0
  46. package/dist/security/index.js +2 -0
  47. package/dist/security/index.js.map +1 -0
  48. package/dist/security/tool-policy.d.ts +66 -0
  49. package/dist/security/tool-policy.js +467 -0
  50. package/dist/security/tool-policy.js.map +1 -0
  51. package/dist/sessions/index.d.ts +1 -0
  52. package/dist/sessions/index.js +2 -0
  53. package/dist/sessions/index.js.map +1 -0
  54. package/dist/sessions/store.d.ts +64 -0
  55. package/dist/sessions/store.js +247 -0
  56. package/dist/sessions/store.js.map +1 -0
  57. package/package.json +57 -0
  58. package/src/adapters/base.ts +124 -0
  59. package/src/adapters/discord.ts +270 -0
  60. package/src/adapters/index.ts +13 -0
  61. package/src/adapters/slack.ts +313 -0
  62. package/src/adapters/telegram.ts +394 -0
  63. package/src/adapters/twitch.ts +316 -0
  64. package/src/adapters/websocket.ts +158 -0
  65. package/src/adapters/whatsapp.ts +296 -0
  66. package/src/background/index.ts +1 -0
  67. package/src/background/manager.ts +395 -0
  68. package/src/index.ts +1665 -0
  69. package/src/logger.ts +43 -0
  70. package/src/paths.ts +40 -0
  71. package/src/security/auth.ts +458 -0
  72. package/src/security/index.ts +1 -0
  73. package/src/security/tool-policy.ts +568 -0
  74. package/src/sessions/index.ts +1 -0
  75. package/src/sessions/store.ts +360 -0
@@ -0,0 +1,274 @@
1
+ /**
2
+ * Telegram Adapter - Hermes-style Telegram platform adapter
3
+ *
4
+ * Features:
5
+ * - Polling and webhook modes
6
+ * - DM and group chat support
7
+ * - Inline queries
8
+ * - Callback buttons
9
+ */
10
+ import { BaseAdapter, } from "./base.js";
11
+ import { logger } from "../logger.js";
12
+ export class TelegramAdapter extends BaseAdapter {
13
+ platform = "telegram";
14
+ config;
15
+ offset = 0;
16
+ pollingActive = false;
17
+ connected = false;
18
+ constructor(config) {
19
+ super();
20
+ this.config = {
21
+ enabled: true,
22
+ platform: "telegram",
23
+ ...config,
24
+ };
25
+ }
26
+ async initialize() {
27
+ // Test bot token
28
+ const response = await this.apiRequest("/getMe");
29
+ const data = (await response.json());
30
+ if (!response.ok || !data.ok) {
31
+ throw new Error(`Telegram auth failed: ${response.status}`);
32
+ }
33
+ logger.info(`[Telegram] Bot initialized: @${data.result?.username}`);
34
+ // Set webhook if URL configured; otherwise long polling is used
35
+ if (this.config.webhookUrl) {
36
+ await this.apiRequest("/setWebhook", {
37
+ method: "POST",
38
+ body: JSON.stringify({
39
+ url: this.config.webhookUrl,
40
+ ...(this.config.webhookSecret
41
+ ? { secret_token: this.config.webhookSecret }
42
+ : {}),
43
+ }),
44
+ });
45
+ logger.info(`[Telegram] Webhook set → ${this.config.webhookUrl}`);
46
+ }
47
+ else {
48
+ logger.info("[Telegram] No webhookUrl — will use long polling");
49
+ }
50
+ }
51
+ async apiRequest(endpoint, options = {}) {
52
+ const url = `https://api.telegram.org/bot${this.config.token}${endpoint}`;
53
+ return fetch(url, {
54
+ ...options,
55
+ headers: {
56
+ "Content-Type": "application/json",
57
+ ...options.headers,
58
+ },
59
+ });
60
+ }
61
+ async start(callbacks) {
62
+ await super.start(callbacks);
63
+ if (!this.config.webhookUrl) {
64
+ // Long polling — keep a persistent connection and receive messages near-real-time
65
+ this.startLongPolling();
66
+ }
67
+ // Webhook mode: gateway's HTTP server calls handleWebhookUpdate() on each POST
68
+ }
69
+ /**
70
+ * Long polling via getUpdates.
71
+ *
72
+ * Telegram holds the connection open (up to `timeout` seconds) and
73
+ * returns immediately when a message arrives. This is NOT interval-
74
+ * based polling — it is near-real-time, similar to a persistent
75
+ * connection. Used as a fallback when no webhookUrl is configured.
76
+ */
77
+ startLongPolling() {
78
+ this.connected = true;
79
+ this.pollingActive = true;
80
+ this.longPoll();
81
+ }
82
+ async longPoll() {
83
+ while (this.pollingActive) {
84
+ try {
85
+ const response = await this.apiRequest("/getUpdates", {
86
+ method: "POST",
87
+ body: JSON.stringify({
88
+ offset: this.offset,
89
+ timeout: 30, // Telegram long-poll timeout (seconds)
90
+ }),
91
+ });
92
+ if (!response.ok) {
93
+ logger.error(`[Telegram] Poll error: ${response.status}`);
94
+ await this.sleep(5000);
95
+ continue;
96
+ }
97
+ const data = (await response.json());
98
+ if (data.ok && data.result && data.result.length > 0) {
99
+ for (const update of data.result) {
100
+ await this.handleUpdate(update);
101
+ this.offset = update.update_id + 1;
102
+ }
103
+ }
104
+ }
105
+ catch (err) {
106
+ logger.error("[Telegram] Poll exception:", err);
107
+ await this.sleep(5000);
108
+ }
109
+ }
110
+ }
111
+ async handleUpdate(update) {
112
+ // Handle messages
113
+ if (update.message || update.edited_message) {
114
+ const msg = update.message || update.edited_message;
115
+ // Check if chat is allowed
116
+ if (this.config.allowedChats &&
117
+ !this.config.allowedChats.includes(String(msg.chat.id))) {
118
+ return;
119
+ }
120
+ // Check if username is required
121
+ if (this.config.requireUsername && !msg.from?.username) {
122
+ // Could send "Please set a username" message here
123
+ return;
124
+ }
125
+ const content = msg.text || msg.caption || "";
126
+ // Skip empty messages
127
+ if (!content)
128
+ return;
129
+ const message = {
130
+ id: this.generateMessageId(),
131
+ platform: "telegram",
132
+ channelId: String(msg.chat.id),
133
+ userId: String(msg.from?.id || 0),
134
+ content,
135
+ timestamp: msg.date * 1000,
136
+ metadata: {
137
+ username: msg.from?.username,
138
+ firstName: msg.from?.first_name,
139
+ chatType: msg.chat.type,
140
+ chatTitle: msg.chat.title,
141
+ isEdited: !!update.edited_message,
142
+ },
143
+ };
144
+ await this.emitMessage(message);
145
+ }
146
+ // Handle callback queries (button presses)
147
+ if (update.callback_query) {
148
+ const query = update.callback_query;
149
+ const message = {
150
+ id: this.generateMessageId(),
151
+ platform: "telegram",
152
+ channelId: String(query.message?.chat.id || query.from.id),
153
+ userId: String(query.from.id),
154
+ content: `Callback: ${query.data}`,
155
+ timestamp: query.message?.date ? query.message.date * 1000 : Date.now(),
156
+ metadata: {
157
+ callbackId: query.id,
158
+ callbackData: query.data,
159
+ username: query.from.username,
160
+ },
161
+ };
162
+ await this.emitMessage(message);
163
+ // Answer callback to remove loading state
164
+ await this.apiRequest("/answerCallbackQuery", {
165
+ method: "POST",
166
+ body: JSON.stringify({ callback_query_id: query.id }),
167
+ });
168
+ }
169
+ }
170
+ sleep(ms) {
171
+ return new Promise((resolve) => setTimeout(resolve, ms));
172
+ }
173
+ async stop() {
174
+ this.connected = false;
175
+ this.pollingActive = false;
176
+ await super.stop();
177
+ }
178
+ async sendMessage(channelId, content) {
179
+ const response = await this.apiRequest("/sendMessage", {
180
+ method: "POST",
181
+ body: JSON.stringify({
182
+ chat_id: channelId,
183
+ text: content,
184
+ parse_mode: "HTML",
185
+ }),
186
+ });
187
+ const data = (await response.json());
188
+ if (!data.ok) {
189
+ throw new Error(`Failed to send message: ${data}`);
190
+ }
191
+ return String(data.result?.message_id || 0);
192
+ }
193
+ async sendPhoto(channelId, photoUrl, caption) {
194
+ const response = await this.apiRequest("/sendPhoto", {
195
+ method: "POST",
196
+ body: JSON.stringify({
197
+ chat_id: channelId,
198
+ photo: photoUrl,
199
+ caption,
200
+ parse_mode: "HTML",
201
+ }),
202
+ });
203
+ const data = (await response.json());
204
+ if (!data.ok) {
205
+ throw new Error(`Failed to send photo: ${data}`);
206
+ }
207
+ return String(data.result?.message_id || 0);
208
+ }
209
+ async sendButtons(channelId, text, buttons) {
210
+ const replyMarkup = {
211
+ inline_keyboard: buttons.map((row) => row.map((btn) => ({ text: btn.text, callback_data: btn.data }))),
212
+ };
213
+ const response = await this.apiRequest("/sendMessage", {
214
+ method: "POST",
215
+ body: JSON.stringify({
216
+ chat_id: channelId,
217
+ text,
218
+ parse_mode: "HTML",
219
+ reply_markup: replyMarkup,
220
+ }),
221
+ });
222
+ const data = (await response.json());
223
+ if (!data.ok) {
224
+ throw new Error(`Failed to send buttons: ${data}`);
225
+ }
226
+ return String(data.result?.message_id || 0);
227
+ }
228
+ async editMessage(channelId, messageId, content) {
229
+ await this.apiRequest("/editMessageText", {
230
+ method: "POST",
231
+ body: JSON.stringify({
232
+ chat_id: channelId,
233
+ message_id: parseInt(messageId),
234
+ text: content,
235
+ parse_mode: "HTML",
236
+ }),
237
+ });
238
+ }
239
+ async deleteMessage(channelId, messageId) {
240
+ await this.apiRequest("/deleteMessage", {
241
+ method: "POST",
242
+ body: JSON.stringify({
243
+ chat_id: channelId,
244
+ message_id: parseInt(messageId),
245
+ }),
246
+ });
247
+ }
248
+ async setTyping(channelId, isTyping) {
249
+ const action = isTyping ? "typing" : "cancel";
250
+ await this.apiRequest("/sendChatAction", {
251
+ method: "POST",
252
+ body: JSON.stringify({
253
+ chat_id: channelId,
254
+ action,
255
+ }),
256
+ });
257
+ }
258
+ async getStatus() {
259
+ return { connected: this.connected };
260
+ }
261
+ async getMe() {
262
+ const response = await this.apiRequest("/getMe");
263
+ const data = (await response.json());
264
+ return data.result;
265
+ }
266
+ // Handle webhook update (called from HTTP handler)
267
+ async handleWebhookUpdate(update) {
268
+ if (this.config.webhookSecret) {
269
+ // Verify secret here
270
+ }
271
+ await this.handleUpdate(update);
272
+ }
273
+ }
274
+ //# sourceMappingURL=telegram.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram.js","sourceRoot":"","sources":["../../src/adapters/telegram.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Twitch Adapter - Hermes-style Twitch platform adapter
3
+ *
4
+ * Features:
5
+ * - Helix API integration
6
+ * - EventSub WebSocket for real-time events
7
+ * - Stream notifications (live/offline)
8
+ * - Chat settings and moderation
9
+ */
10
+ import { BaseAdapter, type PlatformConfig } from "./base.js";
11
+ export interface TwitchConfig extends PlatformConfig {
12
+ platform: "twitch";
13
+ clientId: string;
14
+ clientSecret: string;
15
+ channels?: string[];
16
+ events?: string[];
17
+ }
18
+ interface TwitchStream {
19
+ id: string;
20
+ user_id: string;
21
+ user_login: string;
22
+ user_name: string;
23
+ game_name: string;
24
+ title: string;
25
+ viewer_count: number;
26
+ started_at: string;
27
+ }
28
+ export declare class TwitchAdapter extends BaseAdapter {
29
+ readonly platform: "twitch";
30
+ config: TwitchConfig;
31
+ private token;
32
+ private tokenExpiry;
33
+ private eventsubWs;
34
+ private eventsubSessionId;
35
+ private subscribedChannels;
36
+ private streamStatus;
37
+ constructor(config: TwitchConfig);
38
+ initialize(): Promise<void>;
39
+ private authenticate;
40
+ private getAccessToken;
41
+ private getHeaders;
42
+ start(callbacks: any): Promise<void>;
43
+ private connectEventSub;
44
+ private handleEventSubMessage;
45
+ private subscribeToChannel;
46
+ stop(): Promise<void>;
47
+ sendMessage(channelId: string, content: string): Promise<string>;
48
+ editMessage(channelId: string, messageId: string, content: string): Promise<void>;
49
+ deleteMessage(channelId: string, messageId: string): Promise<void>;
50
+ setTyping(channelId: string, isTyping: boolean): Promise<void>;
51
+ getStatus(): Promise<{
52
+ connected: boolean;
53
+ latency?: number;
54
+ }>;
55
+ getStream(broadcaster: string): Promise<TwitchStream | null>;
56
+ getUser(login: string): Promise<{
57
+ id: string;
58
+ login: string;
59
+ display_name: string;
60
+ } | null>;
61
+ createClip(broadcaster: string): Promise<{
62
+ url: string;
63
+ title: string;
64
+ }>;
65
+ getChatSettings(broadcasterId: string): Promise<{
66
+ slow: number;
67
+ follower_delay: number;
68
+ subscriber: boolean;
69
+ emote_mode: boolean;
70
+ }>;
71
+ getModerators(broadcasterId: string): Promise<string[]>;
72
+ getMonitoredChannels(): string[];
73
+ isChannelLive(channel: string): boolean;
74
+ }
75
+ export {};
@@ -0,0 +1,222 @@
1
+ /**
2
+ * Twitch Adapter - Hermes-style Twitch platform adapter
3
+ *
4
+ * Features:
5
+ * - Helix API integration
6
+ * - EventSub WebSocket for real-time events
7
+ * - Stream notifications (live/offline)
8
+ * - Chat settings and moderation
9
+ */
10
+ import { BaseAdapter } from "./base.js";
11
+ import { logger } from "../logger.js";
12
+ export class TwitchAdapter extends BaseAdapter {
13
+ platform = "twitch";
14
+ config;
15
+ token = null;
16
+ tokenExpiry = 0;
17
+ eventsubWs = null;
18
+ eventsubSessionId = null;
19
+ subscribedChannels = new Set();
20
+ streamStatus = new Map();
21
+ constructor(config) {
22
+ super();
23
+ this.config = {
24
+ enabled: true,
25
+ platform: "twitch",
26
+ channels: [],
27
+ events: ["stream.online", "stream.offline"],
28
+ ...config,
29
+ };
30
+ // Initialize monitored channels
31
+ if (this.config.channels) {
32
+ this.config.channels.forEach(c => this.subscribedChannels.add(c.toLowerCase()));
33
+ }
34
+ }
35
+ async initialize() {
36
+ await this.authenticate();
37
+ logger.info(`[Twitch] Adapter initialized for ${this.subscribedChannels.size} channels`);
38
+ }
39
+ async authenticate() {
40
+ const params = new URLSearchParams({
41
+ client_id: this.config.clientId,
42
+ client_secret: this.config.clientSecret,
43
+ grant_type: "client_credentials",
44
+ });
45
+ const response = await fetch("https://id.twitch.tv/oauth2/token", {
46
+ method: "POST",
47
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
48
+ body: params.toString(),
49
+ });
50
+ if (!response.ok) {
51
+ throw new Error(`Twitch auth failed: ${response.status}`);
52
+ }
53
+ this.token = await response.json();
54
+ this.tokenExpiry = Date.now() + (this.token.expires_in * 1000);
55
+ }
56
+ async getAccessToken() {
57
+ if (this.token && Date.now() < this.tokenExpiry - 60000) {
58
+ return this.token.access_token;
59
+ }
60
+ await this.authenticate();
61
+ return this.token.access_token;
62
+ }
63
+ getHeaders() {
64
+ if (!this.token)
65
+ throw new Error("Not authenticated");
66
+ return {
67
+ "Client-ID": this.config.clientId,
68
+ "Authorization": `Bearer ${this.token.access_token}`,
69
+ };
70
+ }
71
+ async start(callbacks) {
72
+ await super.start(callbacks);
73
+ // Connect to EventSub WebSocket
74
+ await this.connectEventSub();
75
+ }
76
+ async connectEventSub() {
77
+ this.eventsubWs = new WebSocket("wss://eventsub.wss.twitch.tv/ws");
78
+ this.eventsubWs.onopen = () => {
79
+ logger.info("[Twitch] EventSub WebSocket connected");
80
+ };
81
+ this.eventsubWs.onmessage = async (event) => {
82
+ await this.handleEventSubMessage(event.data);
83
+ };
84
+ this.eventsubWs.onclose = () => {
85
+ logger.info("[Twitch] EventSub WebSocket closed");
86
+ this.callbacks?.onDisconnect?.();
87
+ // Reconnect after 5 seconds
88
+ setTimeout(() => this.connectEventSub(), 5000);
89
+ };
90
+ this.eventsubWs.onerror = (error) => {
91
+ logger.error("[Twitch] EventSub error:", error);
92
+ };
93
+ }
94
+ async handleEventSubMessage(data) {
95
+ try {
96
+ const msg = JSON.parse(data);
97
+ const type = msg.metadata?.message_type;
98
+ switch (type) {
99
+ case "session_welcome": {
100
+ this.eventsubSessionId = msg.payload.session.id;
101
+ logger.info(`[Twitch] EventSub session: ${this.eventsubSessionId}`);
102
+ // Subscribe to events for each channel
103
+ for (const channel of this.subscribedChannels) {
104
+ await this.subscribeToChannel(channel);
105
+ }
106
+ break;
107
+ }
108
+ case "notification": {
109
+ const eventType = msg.payload?.subscription?.type;
110
+ const eventData = msg.payload?.event || {};
111
+ if (eventType === "stream.online" || eventType === "stream.offline") {
112
+ const broadcaster = eventData.broadcaster_user_login;
113
+ const wasLive = this.streamStatus.get(broadcaster) || false;
114
+ const isLive = eventType === "stream.online";
115
+ this.streamStatus.set(broadcaster, isLive);
116
+ // Emit message to gateway
117
+ const message = {
118
+ id: this.generateMessageId(),
119
+ platform: "twitch",
120
+ channelId: broadcaster,
121
+ userId: broadcaster, // Twitch events don't have a "from" user
122
+ content: isLive
123
+ ? `🎮 ${broadcaster} is now LIVE!`
124
+ : `📴 ${broadcaster} went offline`,
125
+ timestamp: Date.now(),
126
+ metadata: { eventType, wasLive, isLive, stream: eventData },
127
+ };
128
+ this.emitMessage(message);
129
+ }
130
+ break;
131
+ }
132
+ case "session_keepalive":
133
+ // Heartbeat - no action needed
134
+ break;
135
+ }
136
+ }
137
+ catch (err) {
138
+ logger.error("[Twitch] EventSub parse error:", err);
139
+ }
140
+ }
141
+ async subscribeToChannel(channel) {
142
+ // Get broadcaster ID first
143
+ const userResponse = await fetch(`https://api.twitch.tv/helix/users?login=${channel}`, { headers: this.getHeaders() });
144
+ const userData = await userResponse.json();
145
+ const broadcaster = userData.data[0];
146
+ if (!broadcaster) {
147
+ logger.warn(`[Twitch] Channel not found: ${channel}`);
148
+ return;
149
+ }
150
+ // Note: Subscription creation requires webhook transport
151
+ // For WebSocket, events are received if the user has a subscription
152
+ logger.info(`[Twitch] Monitoring channel: ${channel} (${broadcaster.id})`);
153
+ }
154
+ async stop() {
155
+ if (this.eventsubWs) {
156
+ this.eventsubWs.close();
157
+ this.eventsubWs = null;
158
+ }
159
+ this.eventsubSessionId = null;
160
+ await super.stop();
161
+ }
162
+ async sendMessage(channelId, content) {
163
+ // Twitch doesn't support chat via API (requires IRC or EventSub Chat)
164
+ // For now, this is a no-op - chat messages must come through EventSub Chat
165
+ logger.warn("[Twitch] sendMessage not supported - use IRC for chat");
166
+ return this.generateMessageId();
167
+ }
168
+ async editMessage(channelId, messageId, content) {
169
+ // Not supported via Helix API
170
+ }
171
+ async deleteMessage(channelId, messageId) {
172
+ // Not supported via Helix API
173
+ }
174
+ async setTyping(channelId, isTyping) {
175
+ // Not supported via Helix API
176
+ }
177
+ async getStatus() {
178
+ return {
179
+ connected: this.eventsubWs?.readyState === WebSocket.OPEN && this.eventsubSessionId !== null,
180
+ };
181
+ }
182
+ // ============ API Methods (for tools) ============
183
+ async getStream(broadcaster) {
184
+ const response = await fetch(`https://api.twitch.tv/helix/streams?user_login=${broadcaster}`, { headers: this.getHeaders() });
185
+ const data = await response.json();
186
+ return data.data[0] || null;
187
+ }
188
+ async getUser(login) {
189
+ const response = await fetch(`https://api.twitch.tv/helix/users?login=${login}`, { headers: this.getHeaders() });
190
+ const data = await response.json();
191
+ return data.data[0] || null;
192
+ }
193
+ async createClip(broadcaster) {
194
+ // Get broadcaster ID first
195
+ const user = await this.getUser(broadcaster);
196
+ if (!user)
197
+ throw new Error(`Channel not found: ${broadcaster}`);
198
+ const response = await fetch(`https://api.twitch.tv/helix/clips?broadcaster_id=${user.id}`, {
199
+ method: "POST",
200
+ headers: this.getHeaders()
201
+ });
202
+ const data = await response.json();
203
+ return { url: data.data[0]?.edit_url || "", title: data.data[0]?.title || "" };
204
+ }
205
+ async getChatSettings(broadcasterId) {
206
+ const response = await fetch(`https://api.twitch.tv/helix/chat/settings?broadcaster_id=${broadcasterId}`, { headers: this.getHeaders() });
207
+ const data = await response.json();
208
+ return data.data[0] || { slow: 0, follower_delay: -1, subscriber: false, emote_mode: false };
209
+ }
210
+ async getModerators(broadcasterId) {
211
+ const response = await fetch(`https://api.twitch.tv/helix/moderation/moderators?broadcaster_id=${broadcasterId}`, { headers: this.getHeaders() });
212
+ const data = await response.json();
213
+ return data.data.map(m => m.login);
214
+ }
215
+ getMonitoredChannels() {
216
+ return Array.from(this.subscribedChannels);
217
+ }
218
+ isChannelLive(channel) {
219
+ return this.streamStatus.get(channel.toLowerCase()) || false;
220
+ }
221
+ }
222
+ //# sourceMappingURL=twitch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twitch.js","sourceRoot":"","sources":["../../src/adapters/twitch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * WebSocket Adapter - For web clients and other WebSocket-based platforms
3
+ */
4
+ import { BaseAdapter, type PlatformConfig } from "./base.js";
5
+ export interface WebSocketConfig extends PlatformConfig {
6
+ platform: "websocket";
7
+ clientId: string;
8
+ }
9
+ export declare class WebSocketAdapter extends BaseAdapter {
10
+ readonly platform: "websocket";
11
+ config: WebSocketConfig;
12
+ private client;
13
+ private reconnectAttempts;
14
+ private maxReconnectAttempts;
15
+ private reconnectDelay;
16
+ constructor(config: WebSocketConfig);
17
+ initialize(): Promise<void>;
18
+ start(callbacks: any): Promise<void>;
19
+ connect(url: string, token?: string): Promise<void>;
20
+ private attemptReconnect;
21
+ sendMessage(channelId: string, content: string): Promise<string>;
22
+ editMessage(channelId: string, messageId: string, content: string): Promise<void>;
23
+ deleteMessage(channelId: string, messageId: string): Promise<void>;
24
+ setTyping(channelId: string, isTyping: boolean): Promise<void>;
25
+ getStatus(): Promise<{
26
+ connected: boolean;
27
+ latency?: number;
28
+ }>;
29
+ stop(): Promise<void>;
30
+ }