@chat-adapter/slack 4.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.
@@ -0,0 +1,215 @@
1
+ import { CardElement, BaseFormatConverter, PostableMessage, Root, Adapter, ChatInstance, WebhookOptions, RawMessage, EmojiValue, FetchOptions, Message, ThreadInfo, FormattedContent } from 'chat';
2
+
3
+ /**
4
+ * Slack Block Kit converter for cross-platform cards.
5
+ *
6
+ * Converts CardElement to Slack Block Kit blocks.
7
+ * @see https://api.slack.com/block-kit
8
+ */
9
+
10
+ interface SlackBlock {
11
+ type: string;
12
+ block_id?: string;
13
+ [key: string]: unknown;
14
+ }
15
+ /**
16
+ * Convert a CardElement to Slack Block Kit blocks.
17
+ */
18
+ declare function cardToBlockKit(card: CardElement): SlackBlock[];
19
+ /**
20
+ * Generate fallback text from a card element.
21
+ * Used when blocks aren't supported or for notifications.
22
+ */
23
+ declare function cardToFallbackText(card: CardElement): string;
24
+
25
+ /**
26
+ * Slack-specific format conversion using AST-based parsing.
27
+ *
28
+ * Slack uses "mrkdwn" format which is similar but not identical to markdown:
29
+ * - Bold: *text* (not **text**)
30
+ * - Italic: _text_ (same)
31
+ * - Strikethrough: ~text~ (not ~~text~~)
32
+ * - Links: <url|text> (not [text](url))
33
+ * - User mentions: <@U123>
34
+ * - Channel mentions: <#C123|name>
35
+ */
36
+
37
+ declare class SlackFormatConverter extends BaseFormatConverter {
38
+ /**
39
+ * Convert @mentions to Slack format in plain text.
40
+ * @name → <@name>
41
+ */
42
+ private convertMentionsToSlack;
43
+ /**
44
+ * Override renderPostable to convert @mentions in plain strings.
45
+ */
46
+ renderPostable(message: PostableMessage): string;
47
+ /**
48
+ * Render an AST to Slack mrkdwn format.
49
+ */
50
+ fromAst(ast: Root): string;
51
+ /**
52
+ * Parse Slack mrkdwn into an AST.
53
+ */
54
+ toAst(mrkdwn: string): Root;
55
+ private nodeToMrkdwn;
56
+ }
57
+
58
+ interface SlackAdapterConfig {
59
+ /** Bot token (xoxb-...) */
60
+ botToken: string;
61
+ /** Signing secret for webhook verification */
62
+ signingSecret: string;
63
+ /** Override bot username (optional) */
64
+ userName?: string;
65
+ /** Bot user ID (will be fetched if not provided) */
66
+ botUserId?: string;
67
+ }
68
+ /** Slack-specific thread ID data */
69
+ interface SlackThreadId {
70
+ channel: string;
71
+ threadTs: string;
72
+ }
73
+ /** Slack event payload (raw message format) */
74
+ interface SlackEvent {
75
+ type: string;
76
+ user?: string;
77
+ bot_id?: string;
78
+ channel?: string;
79
+ text?: string;
80
+ ts?: string;
81
+ thread_ts?: string;
82
+ subtype?: string;
83
+ username?: string;
84
+ edited?: {
85
+ ts: string;
86
+ };
87
+ /** Channel type: "channel", "group", "mpim", or "im" (DM) */
88
+ channel_type?: string;
89
+ files?: Array<{
90
+ id?: string;
91
+ mimetype?: string;
92
+ url_private?: string;
93
+ name?: string;
94
+ size?: number;
95
+ original_w?: number;
96
+ original_h?: number;
97
+ }>;
98
+ }
99
+ /** Slack reaction event payload */
100
+ interface SlackReactionEvent {
101
+ type: "reaction_added" | "reaction_removed";
102
+ user: string;
103
+ reaction: string;
104
+ item_user?: string;
105
+ item: {
106
+ type: string;
107
+ channel: string;
108
+ ts: string;
109
+ };
110
+ event_ts: string;
111
+ }
112
+ declare class SlackAdapter implements Adapter<SlackThreadId, unknown> {
113
+ readonly name = "slack";
114
+ readonly userName: string;
115
+ private client;
116
+ private signingSecret;
117
+ private botToken;
118
+ private chat;
119
+ private logger;
120
+ private _botUserId;
121
+ private _botId;
122
+ private formatConverter;
123
+ private static USER_CACHE_TTL_MS;
124
+ /** Bot user ID (e.g., U_BOT_123) used for mention detection */
125
+ get botUserId(): string | undefined;
126
+ constructor(config: SlackAdapterConfig);
127
+ initialize(chat: ChatInstance): Promise<void>;
128
+ /**
129
+ * Look up user info from Slack API with caching via state adapter.
130
+ * Returns display name and real name, or falls back to user ID.
131
+ */
132
+ private lookupUser;
133
+ handleWebhook(request: Request, options?: WebhookOptions): Promise<Response>;
134
+ /**
135
+ * Handle Slack interactive payloads (button clicks, etc.).
136
+ * These are sent as form-urlencoded with a `payload` JSON field.
137
+ */
138
+ private handleInteractivePayload;
139
+ /**
140
+ * Handle block_actions payload (button clicks in Block Kit).
141
+ */
142
+ private handleBlockActions;
143
+ private verifySignature;
144
+ /**
145
+ * Handle message events from Slack.
146
+ * Bot message filtering (isMe) is handled centrally by the Chat class.
147
+ */
148
+ private handleMessageEvent;
149
+ /**
150
+ * Handle reaction events from Slack (reaction_added, reaction_removed).
151
+ */
152
+ private handleReactionEvent;
153
+ private parseSlackMessage;
154
+ /**
155
+ * Create an Attachment object from a Slack file.
156
+ * Includes a fetchData method that uses the bot token for auth.
157
+ */
158
+ private createAttachment;
159
+ postMessage(threadId: string, message: PostableMessage): Promise<RawMessage<unknown>>;
160
+ /**
161
+ * Extract card element from a PostableMessage if present.
162
+ */
163
+ private extractCard;
164
+ /**
165
+ * Extract files from a PostableMessage if present.
166
+ */
167
+ private extractFiles;
168
+ /**
169
+ * Upload files to Slack and share them to a channel.
170
+ * Returns the file IDs of uploaded files.
171
+ */
172
+ private uploadFiles;
173
+ editMessage(threadId: string, messageId: string, message: PostableMessage): Promise<RawMessage<unknown>>;
174
+ deleteMessage(threadId: string, messageId: string): Promise<void>;
175
+ addReaction(threadId: string, messageId: string, emoji: EmojiValue | string): Promise<void>;
176
+ removeReaction(threadId: string, messageId: string, emoji: EmojiValue | string): Promise<void>;
177
+ startTyping(_threadId: string): Promise<void>;
178
+ /**
179
+ * Open a direct message conversation with a user.
180
+ * Returns a thread ID that can be used to post messages.
181
+ */
182
+ openDM(userId: string): Promise<string>;
183
+ fetchMessages(threadId: string, options?: FetchOptions): Promise<Message<unknown>[]>;
184
+ fetchThread(threadId: string): Promise<ThreadInfo>;
185
+ encodeThreadId(platformData: SlackThreadId): string;
186
+ /**
187
+ * Check if a thread is a direct message conversation.
188
+ * Slack DM channel IDs start with 'D'.
189
+ */
190
+ isDM(threadId: string): boolean;
191
+ decodeThreadId(threadId: string): SlackThreadId;
192
+ parseMessage(raw: SlackEvent): Message<unknown>;
193
+ /**
194
+ * Synchronous message parsing without user lookup.
195
+ * Used for parseMessage interface - falls back to user ID for username.
196
+ */
197
+ private parseSlackMessageSync;
198
+ renderFormatted(content: FormattedContent): string;
199
+ /**
200
+ * Check if a Slack event is from this bot.
201
+ *
202
+ * Slack messages can come from:
203
+ * - User messages: have `user` field (U_xxx format)
204
+ * - Bot messages: have `bot_id` field (B_xxx format)
205
+ *
206
+ * We check both because:
207
+ * - _botUserId is the user ID (U_xxx) - matches event.user
208
+ * - _botId is the bot ID (B_xxx) - matches event.bot_id
209
+ */
210
+ private isMessageFromSelf;
211
+ private handleSlackError;
212
+ }
213
+ declare function createSlackAdapter(config: SlackAdapterConfig): SlackAdapter;
214
+
215
+ export { SlackAdapter, type SlackAdapterConfig, type SlackEvent, SlackFormatConverter, SlackFormatConverter as SlackMarkdownConverter, type SlackReactionEvent, type SlackThreadId, cardToBlockKit, cardToFallbackText, createSlackAdapter };