@pocketping/sdk-node 1.6.0 → 1.7.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.
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { IncomingMessage, ServerResponse } from 'http';
1
+ import { IncomingMessage, ServerResponse } from 'node:http';
2
2
 
3
3
  /**
4
4
  * Bridge message IDs for edit/delete sync.
@@ -31,6 +31,156 @@ interface Storage {
31
31
  cleanupOldSessions?(olderThan: Date): Promise<number>;
32
32
  }
33
33
 
34
+ declare class PocketPing {
35
+ private storage;
36
+ private bridges;
37
+ private config;
38
+ private wss;
39
+ private sessionSockets;
40
+ private operatorOnline;
41
+ private eventHandlers;
42
+ constructor(config?: PocketPingConfig);
43
+ private initStorage;
44
+ middleware(): (req: IncomingMessage & {
45
+ body?: unknown;
46
+ query?: Record<string, string>;
47
+ }, res: ServerResponse, next?: () => void) => void;
48
+ private parseBody;
49
+ attachWebSocket(server: any): void;
50
+ private handleWebSocketMessage;
51
+ private handleCustomEvent;
52
+ private broadcastToSession;
53
+ handleConnect(request: ConnectRequest): Promise<ConnectResponse>;
54
+ handleMessage(request: SendMessageRequest): Promise<SendMessageResponse>;
55
+ handleGetMessages(request: GetMessagesRequest): Promise<GetMessagesResponse>;
56
+ handleTyping(request: TypingRequest): Promise<{
57
+ ok: boolean;
58
+ }>;
59
+ handlePresence(): Promise<PresenceResponse>;
60
+ handleRead(request: ReadRequest): Promise<ReadResponse>;
61
+ /**
62
+ * Handle user identification from widget
63
+ * Called when visitor calls PocketPing.identify()
64
+ */
65
+ handleIdentify(request: IdentifyRequest): Promise<IdentifyResponse>;
66
+ /**
67
+ * Get a session by ID
68
+ */
69
+ getSession(sessionId: string): Promise<Session | null>;
70
+ /**
71
+ * Handle message edit from widget
72
+ * Only the message sender can edit their own messages
73
+ */
74
+ handleEditMessage(request: EditMessageRequest): Promise<EditMessageResponse>;
75
+ /**
76
+ * Handle message delete from widget
77
+ * Only the message sender can delete their own messages
78
+ */
79
+ handleDeleteMessage(request: DeleteMessageRequest): Promise<DeleteMessageResponse>;
80
+ sendOperatorMessage(sessionId: string, content: string): Promise<Message>;
81
+ setOperatorOnline(online: boolean): void;
82
+ /**
83
+ * Subscribe to custom events from widgets
84
+ * @param eventName - The name of the event to listen for, or '*' for all events
85
+ * @param handler - Callback function when event is received
86
+ * @returns Unsubscribe function
87
+ * @example
88
+ * // Listen for specific event
89
+ * pp.onEvent('clicked_pricing', async (event, session) => {
90
+ * console.log(`User ${session.visitorId} clicked pricing: ${event.data?.plan}`)
91
+ * })
92
+ *
93
+ * // Listen for all events
94
+ * pp.onEvent('*', async (event, session) => {
95
+ * console.log(`Event: ${event.name}`, event.data)
96
+ * })
97
+ */
98
+ onEvent(eventName: string, handler: CustomEventHandler): () => void;
99
+ /**
100
+ * Unsubscribe from a custom event
101
+ * @param eventName - The name of the event
102
+ * @param handler - The handler to remove
103
+ */
104
+ offEvent(eventName: string, handler: CustomEventHandler): void;
105
+ /**
106
+ * Send a custom event to a specific widget/session
107
+ * @param sessionId - The session ID to send the event to
108
+ * @param eventName - The name of the event
109
+ * @param data - Optional payload to send with the event
110
+ * @example
111
+ * // Send a promotion offer to a specific user
112
+ * pp.emitEvent('session-123', 'show_offer', {
113
+ * discount: 20,
114
+ * code: 'SAVE20',
115
+ * message: 'Special offer just for you!'
116
+ * })
117
+ */
118
+ emitEvent(sessionId: string, eventName: string, data?: Record<string, unknown>): void;
119
+ /**
120
+ * Broadcast a custom event to all connected widgets
121
+ * @param eventName - The name of the event
122
+ * @param data - Optional payload to send with the event
123
+ * @example
124
+ * // Notify all users about maintenance
125
+ * pp.broadcastEvent('maintenance_warning', {
126
+ * message: 'Site will be down for maintenance in 5 minutes'
127
+ * })
128
+ */
129
+ broadcastEvent(eventName: string, data?: Record<string, unknown>): void;
130
+ /**
131
+ * Process a custom event server-side (runs handlers, bridges, webhooks)
132
+ * Useful for server-side automation or triggering events programmatically
133
+ * @param sessionId - The session ID to associate with the event
134
+ * @param eventName - The name of the event
135
+ * @param data - Optional payload for the event
136
+ * @example
137
+ * // Trigger event from backend logic (e.g., after purchase)
138
+ * await pp.triggerEvent('session-123', 'purchase_completed', {
139
+ * orderId: 'order-456',
140
+ * amount: 99.99
141
+ * })
142
+ */
143
+ triggerEvent(sessionId: string, eventName: string, data?: Record<string, unknown>): Promise<void>;
144
+ private notifyBridges;
145
+ private notifyBridgesRead;
146
+ private notifyBridgesEvent;
147
+ private notifyBridgesIdentity;
148
+ /**
149
+ * Sync message edit to all bridges that support it
150
+ */
151
+ private syncEditToBridges;
152
+ /**
153
+ * Sync message delete to all bridges that support it
154
+ */
155
+ private syncDeleteToBridges;
156
+ /**
157
+ * Forward custom event to configured webhook URL (non-blocking)
158
+ * Used for integrations with Zapier, Make, n8n, or custom backends
159
+ */
160
+ private forwardToWebhook;
161
+ /**
162
+ * Forward identity update to webhook as a special event
163
+ */
164
+ private forwardIdentityToWebhook;
165
+ addBridge(bridge: Bridge): void;
166
+ private generateId;
167
+ getStorage(): Storage;
168
+ /**
169
+ * Check widget version against configured min/latest versions
170
+ * @param widgetVersion - Version from X-PocketPing-Version header
171
+ * @returns Version check result with status and headers to set
172
+ */
173
+ checkWidgetVersion(widgetVersion: string | undefined): VersionCheckResult;
174
+ /**
175
+ * Set version warning headers on HTTP response
176
+ */
177
+ private setVersionHeaders;
178
+ /**
179
+ * Send version warning via WebSocket to a session
180
+ */
181
+ sendVersionWarning(sessionId: string, versionCheck: VersionCheckResult): void;
182
+ }
183
+
34
184
  /**
35
185
  * Result from sending a message to a bridge.
36
186
  * Contains the bridge-specific message ID for later edit/delete.
@@ -84,19 +234,6 @@ interface Bridge {
84
234
  destroy?(): void | Promise<void>;
85
235
  }
86
236
 
87
- /**
88
- * AI provider interface.
89
- * Implement this to add support for OpenAI, Gemini, Claude, or local models.
90
- */
91
- interface AIProvider {
92
- /** Provider name */
93
- name: string;
94
- /** Generate a response to the conversation */
95
- generateResponse(messages: Message[], systemPrompt?: string): Promise<string>;
96
- /** Check if the provider is available */
97
- isAvailable(): Promise<boolean>;
98
- }
99
-
100
237
  /**
101
238
  * IP Filtering utilities for PocketPing SDK
102
239
  * Supports CIDR notation and individual IP addresses
@@ -134,6 +271,10 @@ interface IpFilterLogEvent {
134
271
  timestamp: Date;
135
272
  sessionId?: string;
136
273
  }
274
+ interface IpFilterResult {
275
+ allowed: boolean;
276
+ reason: 'allowlist' | 'blocklist' | 'custom' | 'not_in_allowlist' | 'default';
277
+ }
137
278
  /**
138
279
  * Custom IP filter callback
139
280
  * Return true to allow, false to block, undefined to defer to list-based filtering
@@ -142,6 +283,95 @@ type IpFilterCallback = (ip: string, request: {
142
283
  path: string;
143
284
  sessionId?: string;
144
285
  }) => boolean | undefined | Promise<boolean | undefined>;
286
+ /**
287
+ * Check if an IP matches a CIDR range or exact IP
288
+ */
289
+ declare function ipMatchesCidr(ip: string, cidr: string): boolean;
290
+ /**
291
+ * Check if IP matches any entry in a list of IPs/CIDRs
292
+ */
293
+ declare function ipMatchesAny(ip: string, list: string[]): boolean;
294
+ /**
295
+ * Check IP filter with support for custom filter callback
296
+ */
297
+ declare function checkIpFilter(ip: string, config: IpFilterConfig, requestInfo: {
298
+ path: string;
299
+ sessionId?: string;
300
+ }): Promise<IpFilterResult>;
301
+
302
+ /**
303
+ * User-Agent Filtering utilities for PocketPing SDK
304
+ * Blocks bots and unwanted user agents to prevent spam sessions
305
+ */
306
+ type UaFilterMode = 'allowlist' | 'blocklist' | 'both';
307
+ type UaFilterReason = 'allowlist' | 'blocklist' | 'default_bot' | 'custom' | 'not_in_allowlist' | 'default';
308
+ interface UaFilterConfig {
309
+ /** Enable/disable UA filtering (default: false) */
310
+ enabled?: boolean;
311
+ /** Filter mode (default: 'blocklist') */
312
+ mode?: UaFilterMode;
313
+ /** UA patterns to allow (case-insensitive substring match) */
314
+ allowlist?: string[];
315
+ /** UA patterns to block (case-insensitive substring match) */
316
+ blocklist?: string[];
317
+ /** Include default bot patterns in blocklist (default: true) */
318
+ useDefaultBots?: boolean;
319
+ /** Custom filter callback for advanced logic */
320
+ customFilter?: UaFilterCallback;
321
+ /** Log blocked requests for security auditing (default: true) */
322
+ logBlocked?: boolean;
323
+ /** Custom logger function */
324
+ logger?: (event: UaFilterLogEvent) => void;
325
+ /** HTTP status code for blocked requests (default: 403) */
326
+ blockedStatusCode?: number;
327
+ /** Response message for blocked requests (default: 'Forbidden') */
328
+ blockedMessage?: string;
329
+ }
330
+ interface UaFilterLogEvent {
331
+ type: 'blocked' | 'allowed';
332
+ userAgent: string;
333
+ reason: UaFilterReason;
334
+ matchedPattern?: string;
335
+ path: string;
336
+ timestamp: Date;
337
+ sessionId?: string;
338
+ }
339
+ interface UaFilterResult {
340
+ allowed: boolean;
341
+ reason: UaFilterReason;
342
+ matchedPattern?: string;
343
+ }
344
+ /**
345
+ * Custom UA filter callback
346
+ * Return true to allow, false to block, undefined to defer to list-based filtering
347
+ */
348
+ type UaFilterCallback = (userAgent: string, request: {
349
+ path: string;
350
+ sessionId?: string;
351
+ }) => boolean | undefined | Promise<boolean | undefined>;
352
+ /**
353
+ * Default bot patterns to block
354
+ * These are known bots, crawlers, and automated tools that shouldn't create chat sessions
355
+ */
356
+ declare const DEFAULT_BOT_PATTERNS: string[];
357
+ /**
358
+ * Check if a user-agent matches any pattern in the list
359
+ * Supports both substring matching and regex patterns (e.g., /bot-\d+/)
360
+ * Returns the matched pattern or undefined
361
+ */
362
+ declare function matchesAnyPattern(userAgent: string, patterns: string[]): string | undefined;
363
+ /**
364
+ * Check UA filter with support for custom filter callback
365
+ */
366
+ declare function checkUaFilter(userAgent: string | undefined, config: UaFilterConfig, requestInfo: {
367
+ path: string;
368
+ sessionId?: string;
369
+ }): Promise<UaFilterResult>;
370
+ /**
371
+ * Check if a user-agent looks like a bot based on default patterns
372
+ * Utility function for quick bot detection
373
+ */
374
+ declare function isBot(userAgent: string): boolean;
145
375
 
146
376
  interface PocketPingConfig {
147
377
  /** Storage adapter for sessions and messages */
@@ -178,6 +408,8 @@ interface PocketPingConfig {
178
408
  versionUpgradeUrl?: string;
179
409
  /** IP filtering configuration (allowlist/blocklist) */
180
410
  ipFilter?: IpFilterConfig;
411
+ /** User-Agent filtering configuration (block bots/crawlers) */
412
+ uaFilter?: UaFilterConfig;
181
413
  }
182
414
  interface AIConfig {
183
415
  provider: AIProvider | 'openai' | 'gemini' | 'anthropic';
@@ -416,327 +648,17 @@ interface WebhookPayload {
416
648
  sentAt: string;
417
649
  }
418
650
 
419
- declare class PocketPing {
420
- private storage;
421
- private bridges;
422
- private config;
423
- private wss;
424
- private sessionSockets;
425
- private operatorOnline;
426
- private eventHandlers;
427
- constructor(config?: PocketPingConfig);
428
- private initStorage;
429
- middleware(): (req: IncomingMessage & {
430
- body?: unknown;
431
- query?: Record<string, string>;
432
- }, res: ServerResponse, next?: () => void) => void;
433
- private parseBody;
434
- attachWebSocket(server: any): void;
435
- private handleWebSocketMessage;
436
- private handleCustomEvent;
437
- private broadcastToSession;
438
- handleConnect(request: ConnectRequest): Promise<ConnectResponse>;
439
- handleMessage(request: SendMessageRequest): Promise<SendMessageResponse>;
440
- handleGetMessages(request: GetMessagesRequest): Promise<GetMessagesResponse>;
441
- handleTyping(request: TypingRequest): Promise<{
442
- ok: boolean;
443
- }>;
444
- handlePresence(): Promise<PresenceResponse>;
445
- handleRead(request: ReadRequest): Promise<ReadResponse>;
446
- /**
447
- * Handle user identification from widget
448
- * Called when visitor calls PocketPing.identify()
449
- */
450
- handleIdentify(request: IdentifyRequest): Promise<IdentifyResponse>;
451
- /**
452
- * Get a session by ID
453
- */
454
- getSession(sessionId: string): Promise<Session | null>;
455
- /**
456
- * Handle message edit from widget
457
- * Only the message sender can edit their own messages
458
- */
459
- handleEditMessage(request: EditMessageRequest): Promise<EditMessageResponse>;
460
- /**
461
- * Handle message delete from widget
462
- * Only the message sender can delete their own messages
463
- */
464
- handleDeleteMessage(request: DeleteMessageRequest): Promise<DeleteMessageResponse>;
465
- sendOperatorMessage(sessionId: string, content: string): Promise<Message>;
466
- setOperatorOnline(online: boolean): void;
467
- /**
468
- * Subscribe to custom events from widgets
469
- * @param eventName - The name of the event to listen for, or '*' for all events
470
- * @param handler - Callback function when event is received
471
- * @returns Unsubscribe function
472
- * @example
473
- * // Listen for specific event
474
- * pp.onEvent('clicked_pricing', async (event, session) => {
475
- * console.log(`User ${session.visitorId} clicked pricing: ${event.data?.plan}`)
476
- * })
477
- *
478
- * // Listen for all events
479
- * pp.onEvent('*', async (event, session) => {
480
- * console.log(`Event: ${event.name}`, event.data)
481
- * })
482
- */
483
- onEvent(eventName: string, handler: CustomEventHandler): () => void;
484
- /**
485
- * Unsubscribe from a custom event
486
- * @param eventName - The name of the event
487
- * @param handler - The handler to remove
488
- */
489
- offEvent(eventName: string, handler: CustomEventHandler): void;
490
- /**
491
- * Send a custom event to a specific widget/session
492
- * @param sessionId - The session ID to send the event to
493
- * @param eventName - The name of the event
494
- * @param data - Optional payload to send with the event
495
- * @example
496
- * // Send a promotion offer to a specific user
497
- * pp.emitEvent('session-123', 'show_offer', {
498
- * discount: 20,
499
- * code: 'SAVE20',
500
- * message: 'Special offer just for you!'
501
- * })
502
- */
503
- emitEvent(sessionId: string, eventName: string, data?: Record<string, unknown>): void;
504
- /**
505
- * Broadcast a custom event to all connected widgets
506
- * @param eventName - The name of the event
507
- * @param data - Optional payload to send with the event
508
- * @example
509
- * // Notify all users about maintenance
510
- * pp.broadcastEvent('maintenance_warning', {
511
- * message: 'Site will be down for maintenance in 5 minutes'
512
- * })
513
- */
514
- broadcastEvent(eventName: string, data?: Record<string, unknown>): void;
515
- /**
516
- * Process a custom event server-side (runs handlers, bridges, webhooks)
517
- * Useful for server-side automation or triggering events programmatically
518
- * @param sessionId - The session ID to associate with the event
519
- * @param eventName - The name of the event
520
- * @param data - Optional payload for the event
521
- * @example
522
- * // Trigger event from backend logic (e.g., after purchase)
523
- * await pp.triggerEvent('session-123', 'purchase_completed', {
524
- * orderId: 'order-456',
525
- * amount: 99.99
526
- * })
527
- */
528
- triggerEvent(sessionId: string, eventName: string, data?: Record<string, unknown>): Promise<void>;
529
- private notifyBridges;
530
- private notifyBridgesRead;
531
- private notifyBridgesEvent;
532
- private notifyBridgesIdentity;
533
- /**
534
- * Sync message edit to all bridges that support it
535
- */
536
- private syncEditToBridges;
537
- /**
538
- * Sync message delete to all bridges that support it
539
- */
540
- private syncDeleteToBridges;
541
- /**
542
- * Forward custom event to configured webhook URL (non-blocking)
543
- * Used for integrations with Zapier, Make, n8n, or custom backends
544
- */
545
- private forwardToWebhook;
546
- /**
547
- * Forward identity update to webhook as a special event
548
- */
549
- private forwardIdentityToWebhook;
550
- addBridge(bridge: Bridge): void;
551
- private generateId;
552
- getStorage(): Storage;
553
- /**
554
- * Check widget version against configured min/latest versions
555
- * @param widgetVersion - Version from X-PocketPing-Version header
556
- * @returns Version check result with status and headers to set
557
- */
558
- checkWidgetVersion(widgetVersion: string | undefined): VersionCheckResult;
559
- /**
560
- * Set version warning headers on HTTP response
561
- */
562
- private setVersionHeaders;
563
- /**
564
- * Send version warning via WebSocket to a session
565
- */
566
- sendVersionWarning(sessionId: string, versionCheck: VersionCheckResult): void;
567
- }
568
-
569
- /**
570
- * In-memory storage adapter.
571
- * Useful for development and testing. Data is lost on restart.
572
- */
573
- declare class MemoryStorage implements Storage {
574
- private sessions;
575
- private messages;
576
- private messageById;
577
- private bridgeMessageIds;
578
- createSession(session: Session): Promise<void>;
579
- getSession(sessionId: string): Promise<Session | null>;
580
- getSessionByVisitorId(visitorId: string): Promise<Session | null>;
581
- updateSession(session: Session): Promise<void>;
582
- deleteSession(sessionId: string): Promise<void>;
583
- saveMessage(message: Message): Promise<void>;
584
- getMessages(sessionId: string, after?: string, limit?: number): Promise<Message[]>;
585
- getMessage(messageId: string): Promise<Message | null>;
586
- updateMessage(message: Message): Promise<void>;
587
- saveBridgeMessageIds(messageId: string, bridgeIds: BridgeMessageIds): Promise<void>;
588
- getBridgeMessageIds(messageId: string): Promise<BridgeMessageIds | null>;
589
- cleanupOldSessions(olderThan: Date): Promise<number>;
590
- }
591
-
592
- /** Attachment from an operator message */
593
- interface OperatorAttachment {
594
- filename: string;
595
- mimeType: string;
596
- size: number;
597
- data: Buffer;
598
- bridgeFileId?: string;
599
- }
600
- /** Callback when operator sends a message from a bridge */
601
- type OperatorMessageCallback = (sessionId: string, content: string, operatorName: string, sourceBridge: 'telegram' | 'discord' | 'slack', attachments: OperatorAttachment[], replyToBridgeMessageId?: number | null, bridgeMessageId?: number | string | null) => void | Promise<void>;
602
- type OperatorMessageEditCallback = (sessionId: string, bridgeMessageId: number | string, content: string, sourceBridge: 'telegram' | 'discord' | 'slack', editedAt?: string) => void | Promise<void>;
603
- type OperatorMessageDeleteCallback = (sessionId: string, bridgeMessageId: number | string, sourceBridge: 'telegram' | 'discord' | 'slack', deletedAt?: string) => void | Promise<void>;
604
- /** Webhook handler configuration */
605
- interface WebhookConfig {
606
- telegramBotToken?: string;
607
- slackBotToken?: string;
608
- discordBotToken?: string;
609
- allowedBotIds?: string[];
610
- onOperatorMessage: OperatorMessageCallback;
611
- onOperatorMessageEdit?: OperatorMessageEditCallback;
612
- onOperatorMessageDelete?: OperatorMessageDeleteCallback;
613
- }
614
- declare class WebhookHandler {
615
- private config;
616
- constructor(config: WebhookConfig);
617
- /**
618
- * Create an Express/Connect middleware for handling Telegram webhooks
619
- */
620
- handleTelegramWebhook(): (req: IncomingMessage & {
621
- body?: unknown;
622
- }, res: ServerResponse) => Promise<void>;
623
- /**
624
- * Create an Express/Connect middleware for handling Slack webhooks
625
- */
626
- handleSlackWebhook(): (req: IncomingMessage & {
627
- body?: unknown;
628
- }, res: ServerResponse) => Promise<void>;
629
- /**
630
- * Create an Express/Connect middleware for handling Discord webhooks
631
- */
632
- handleDiscordWebhook(): (req: IncomingMessage & {
633
- body?: unknown;
634
- }, res: ServerResponse) => Promise<void>;
635
- private parseBody;
636
- private writeOK;
637
- private downloadTelegramFile;
638
- private downloadSlackFile;
639
- private getSlackUserName;
640
- }
641
-
642
651
  /**
643
- * Options for TelegramBridge
644
- */
645
- interface TelegramBridgeOptions {
646
- /** Parse mode for message formatting */
647
- parseMode?: 'HTML' | 'Markdown';
648
- /** Disable notification sound */
649
- disableNotification?: boolean;
650
- }
651
- /**
652
- * Telegram Bridge for PocketPing.
653
- * Sends visitor messages to a Telegram chat using the Bot API.
654
- *
655
- * @example
656
- * ```ts
657
- * const telegram = new TelegramBridge(
658
- * 'BOT_TOKEN',
659
- * '-1001234567890',
660
- * { parseMode: 'HTML' }
661
- * );
662
- * const pocketping = new PocketPing({ bridges: [telegram] });
663
- * ```
652
+ * AI provider interface.
653
+ * Implement this to add support for OpenAI, Gemini, Claude, or local models.
664
654
  */
665
- declare class TelegramBridge implements Bridge {
666
- readonly name = "telegram";
667
- private pocketping?;
668
- private readonly botToken;
669
- private readonly chatId;
670
- private readonly parseMode;
671
- private readonly disableNotification;
672
- private readonly baseUrl;
673
- constructor(botToken: string, chatId: string | number, options?: TelegramBridgeOptions);
674
- /**
675
- * Initialize the bridge (optional setup)
676
- */
677
- init(pocketping: PocketPing): Promise<void>;
678
- /**
679
- * Called when a new chat session is created
680
- */
681
- onNewSession(session: Session): Promise<void>;
682
- /**
683
- * Called when a visitor sends a message.
684
- * Returns the Telegram message ID for edit/delete sync.
685
- */
686
- onVisitorMessage(message: Message, session: Session): Promise<BridgeMessageResult>;
687
- /**
688
- * Called when an operator sends a message (for cross-bridge sync)
689
- */
690
- onOperatorMessage(message: Message, _session: Session, sourceBridge?: string, operatorName?: string): Promise<void>;
691
- /**
692
- * Called when visitor starts/stops typing
693
- */
694
- onTyping(sessionId: string, isTyping: boolean): Promise<void>;
695
- /**
696
- * Called when a visitor edits their message.
697
- * @returns true if edit succeeded, false otherwise
698
- */
699
- onMessageEdit(_messageId: string, newContent: string, bridgeMessageId: string | number): Promise<boolean>;
700
- /**
701
- * Called when a visitor deletes their message.
702
- * @returns true if delete succeeded, false otherwise
703
- */
704
- onMessageDelete(_messageId: string, bridgeMessageId: string | number): Promise<boolean>;
705
- /**
706
- * Called when a custom event is triggered from the widget
707
- */
708
- onCustomEvent(event: {
709
- name: string;
710
- data?: Record<string, unknown>;
711
- }, session: Session): Promise<void>;
712
- /**
713
- * Called when a user identifies themselves via PocketPing.identify()
714
- */
715
- onIdentityUpdate(session: Session): Promise<void>;
716
- /**
717
- * Send a message to the Telegram chat
718
- */
719
- private sendMessage;
720
- /**
721
- * Send a chat action (e.g., "typing")
722
- */
723
- private sendChatAction;
724
- /**
725
- * Format new session notification
726
- */
727
- private formatNewSession;
728
- /**
729
- * Format visitor message
730
- */
731
- private formatVisitorMessage;
732
- /**
733
- * Escape HTML special characters
734
- */
735
- private escapeHtml;
736
- /**
737
- * Escape Markdown special characters
738
- */
739
- private escapeMarkdown;
655
+ interface AIProvider {
656
+ /** Provider name */
657
+ name: string;
658
+ /** Generate a response to the conversation */
659
+ generateResponse(messages: Message[], systemPrompt?: string): Promise<string>;
660
+ /** Check if the provider is available */
661
+ isAvailable(): Promise<boolean>;
740
662
  }
741
663
 
742
664
  /**
@@ -958,4 +880,177 @@ declare class SlackBridge implements Bridge {
958
880
  private escapeSlack;
959
881
  }
960
882
 
961
- export { type AIProvider, type Bridge, type BridgeMessageIds, type BridgeMessageResult, type ConnectRequest, type ConnectResponse, type CustomEvent, type CustomEventHandler, type DeleteMessageRequest, type DeleteMessageResponse, type DiscordBotOptions, DiscordBridge, type DiscordWebhookOptions, type EditMessageRequest, type EditMessageResponse, MemoryStorage, type Message, type OperatorAttachment, type OperatorMessageCallback, type OperatorMessageDeleteCallback, type OperatorMessageEditCallback, PocketPing, type PocketPingConfig, type PresenceResponse, type SendMessageRequest, type SendMessageResponse, type Session, type SlackBotOptions, SlackBridge, type SlackWebhookOptions, type Storage, TelegramBridge, type TelegramBridgeOptions, type TrackedElement, type TriggerOptions, type WebhookConfig, WebhookHandler, type WebhookPayload };
883
+ /**
884
+ * Options for TelegramBridge
885
+ */
886
+ interface TelegramBridgeOptions {
887
+ /** Parse mode for message formatting */
888
+ parseMode?: 'HTML' | 'Markdown';
889
+ /** Disable notification sound */
890
+ disableNotification?: boolean;
891
+ }
892
+ /**
893
+ * Telegram Bridge for PocketPing.
894
+ * Sends visitor messages to a Telegram chat using the Bot API.
895
+ *
896
+ * @example
897
+ * ```ts
898
+ * const telegram = new TelegramBridge(
899
+ * 'BOT_TOKEN',
900
+ * '-1001234567890',
901
+ * { parseMode: 'HTML' }
902
+ * );
903
+ * const pocketping = new PocketPing({ bridges: [telegram] });
904
+ * ```
905
+ */
906
+ declare class TelegramBridge implements Bridge {
907
+ readonly name = "telegram";
908
+ private pocketping?;
909
+ private readonly botToken;
910
+ private readonly chatId;
911
+ private readonly parseMode;
912
+ private readonly disableNotification;
913
+ private readonly baseUrl;
914
+ constructor(botToken: string, chatId: string | number, options?: TelegramBridgeOptions);
915
+ /**
916
+ * Initialize the bridge (optional setup)
917
+ */
918
+ init(pocketping: PocketPing): Promise<void>;
919
+ /**
920
+ * Called when a new chat session is created
921
+ */
922
+ onNewSession(session: Session): Promise<void>;
923
+ /**
924
+ * Called when a visitor sends a message.
925
+ * Returns the Telegram message ID for edit/delete sync.
926
+ */
927
+ onVisitorMessage(message: Message, session: Session): Promise<BridgeMessageResult>;
928
+ /**
929
+ * Called when an operator sends a message (for cross-bridge sync)
930
+ */
931
+ onOperatorMessage(message: Message, _session: Session, sourceBridge?: string, operatorName?: string): Promise<void>;
932
+ /**
933
+ * Called when visitor starts/stops typing
934
+ */
935
+ onTyping(_sessionId: string, isTyping: boolean): Promise<void>;
936
+ /**
937
+ * Called when a visitor edits their message.
938
+ * @returns true if edit succeeded, false otherwise
939
+ */
940
+ onMessageEdit(_messageId: string, newContent: string, bridgeMessageId: string | number): Promise<boolean>;
941
+ /**
942
+ * Called when a visitor deletes their message.
943
+ * @returns true if delete succeeded, false otherwise
944
+ */
945
+ onMessageDelete(_messageId: string, bridgeMessageId: string | number): Promise<boolean>;
946
+ /**
947
+ * Called when a custom event is triggered from the widget
948
+ */
949
+ onCustomEvent(event: {
950
+ name: string;
951
+ data?: Record<string, unknown>;
952
+ }, session: Session): Promise<void>;
953
+ /**
954
+ * Called when a user identifies themselves via PocketPing.identify()
955
+ */
956
+ onIdentityUpdate(session: Session): Promise<void>;
957
+ /**
958
+ * Send a message to the Telegram chat
959
+ */
960
+ private sendMessage;
961
+ /**
962
+ * Send a chat action (e.g., "typing")
963
+ */
964
+ private sendChatAction;
965
+ /**
966
+ * Format new session notification
967
+ */
968
+ private formatNewSession;
969
+ /**
970
+ * Format visitor message
971
+ */
972
+ private formatVisitorMessage;
973
+ /**
974
+ * Escape HTML special characters
975
+ */
976
+ private escapeHtml;
977
+ /**
978
+ * Escape Markdown special characters
979
+ */
980
+ private escapeMarkdown;
981
+ }
982
+
983
+ /**
984
+ * In-memory storage adapter.
985
+ * Useful for development and testing. Data is lost on restart.
986
+ */
987
+ declare class MemoryStorage implements Storage {
988
+ private sessions;
989
+ private messages;
990
+ private messageById;
991
+ private bridgeMessageIds;
992
+ createSession(session: Session): Promise<void>;
993
+ getSession(sessionId: string): Promise<Session | null>;
994
+ getSessionByVisitorId(visitorId: string): Promise<Session | null>;
995
+ updateSession(session: Session): Promise<void>;
996
+ deleteSession(sessionId: string): Promise<void>;
997
+ saveMessage(message: Message): Promise<void>;
998
+ getMessages(sessionId: string, after?: string, limit?: number): Promise<Message[]>;
999
+ getMessage(messageId: string): Promise<Message | null>;
1000
+ updateMessage(message: Message): Promise<void>;
1001
+ saveBridgeMessageIds(messageId: string, bridgeIds: BridgeMessageIds): Promise<void>;
1002
+ getBridgeMessageIds(messageId: string): Promise<BridgeMessageIds | null>;
1003
+ cleanupOldSessions(olderThan: Date): Promise<number>;
1004
+ }
1005
+
1006
+ /** Attachment from an operator message */
1007
+ interface OperatorAttachment {
1008
+ filename: string;
1009
+ mimeType: string;
1010
+ size: number;
1011
+ data: Buffer;
1012
+ bridgeFileId?: string;
1013
+ }
1014
+ /** Callback when operator sends a message from a bridge */
1015
+ type OperatorMessageCallback = (sessionId: string, content: string, operatorName: string, sourceBridge: 'telegram' | 'discord' | 'slack', attachments: OperatorAttachment[], replyToBridgeMessageId?: number | null, bridgeMessageId?: number | string | null) => void | Promise<void>;
1016
+ type OperatorMessageEditCallback = (sessionId: string, bridgeMessageId: number | string, content: string, sourceBridge: 'telegram' | 'discord' | 'slack', editedAt?: string) => void | Promise<void>;
1017
+ type OperatorMessageDeleteCallback = (sessionId: string, bridgeMessageId: number | string, sourceBridge: 'telegram' | 'discord' | 'slack', deletedAt?: string) => void | Promise<void>;
1018
+ /** Webhook handler configuration */
1019
+ interface WebhookConfig {
1020
+ telegramBotToken?: string;
1021
+ slackBotToken?: string;
1022
+ discordBotToken?: string;
1023
+ allowedBotIds?: string[];
1024
+ onOperatorMessage: OperatorMessageCallback;
1025
+ onOperatorMessageEdit?: OperatorMessageEditCallback;
1026
+ onOperatorMessageDelete?: OperatorMessageDeleteCallback;
1027
+ }
1028
+ declare class WebhookHandler {
1029
+ private config;
1030
+ constructor(config: WebhookConfig);
1031
+ /**
1032
+ * Create an Express/Connect middleware for handling Telegram webhooks
1033
+ */
1034
+ handleTelegramWebhook(): (req: IncomingMessage & {
1035
+ body?: unknown;
1036
+ }, res: ServerResponse) => Promise<void>;
1037
+ /**
1038
+ * Create an Express/Connect middleware for handling Slack webhooks
1039
+ */
1040
+ handleSlackWebhook(): (req: IncomingMessage & {
1041
+ body?: unknown;
1042
+ }, res: ServerResponse) => Promise<void>;
1043
+ /**
1044
+ * Create an Express/Connect middleware for handling Discord webhooks
1045
+ */
1046
+ handleDiscordWebhook(): (req: IncomingMessage & {
1047
+ body?: unknown;
1048
+ }, res: ServerResponse) => Promise<void>;
1049
+ private parseBody;
1050
+ private writeOK;
1051
+ private downloadTelegramFile;
1052
+ private downloadSlackFile;
1053
+ private getSlackUserName;
1054
+ }
1055
+
1056
+ export { type AIProvider, type Bridge, type BridgeMessageIds, type BridgeMessageResult, type ConnectRequest, type ConnectResponse, type CustomEvent, type CustomEventHandler, DEFAULT_BOT_PATTERNS, type DeleteMessageRequest, type DeleteMessageResponse, type DiscordBotOptions, DiscordBridge, type DiscordWebhookOptions, type EditMessageRequest, type EditMessageResponse, type IpFilterConfig, type IpFilterLogEvent, type IpFilterMode, MemoryStorage, type Message, type OperatorAttachment, type OperatorMessageCallback, type OperatorMessageDeleteCallback, type OperatorMessageEditCallback, PocketPing, type PocketPingConfig, type PresenceResponse, type SendMessageRequest, type SendMessageResponse, type Session, type SlackBotOptions, SlackBridge, type SlackWebhookOptions, type Storage, TelegramBridge, type TelegramBridgeOptions, type TrackedElement, type TriggerOptions, type UaFilterConfig, type UaFilterLogEvent, type UaFilterMode, type UaFilterReason, type UaFilterResult, type WebhookConfig, WebhookHandler, type WebhookPayload, checkIpFilter, checkUaFilter, ipMatchesAny, ipMatchesCidr, isBot, matchesAnyPattern };