alvin-bot 5.7.0 → 5.8.1
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/CHANGELOG.md +25 -0
- package/README.md +25 -31
- package/dist/claude.js +1 -102
- package/dist/config.js +1 -96
- package/dist/engine.js +1 -90
- package/dist/find-claude-binary.js +1 -98
- package/dist/handlers/async-agent-chunk-handler.js +1 -50
- package/dist/handlers/background-bypass.js +1 -75
- package/dist/handlers/commands.js +1 -2336
- package/dist/handlers/cron-progress.js +1 -52
- package/dist/handlers/document.js +1 -194
- package/dist/handlers/message.js +1 -959
- package/dist/handlers/photo.js +1 -154
- package/dist/handlers/platform-message.js +1 -360
- package/dist/handlers/stuck-timer.js +1 -54
- package/dist/handlers/video.js +1 -237
- package/dist/handlers/voice.js +1 -148
- package/dist/i18n.js +1 -805
- package/dist/index.js +1 -697
- package/dist/init-data-dir.js +1 -98
- package/dist/middleware/auth.js +1 -233
- package/dist/migrate.js +1 -162
- package/dist/paths.js +1 -146
- package/dist/platforms/discord.js +1 -175
- package/dist/platforms/index.js +1 -130
- package/dist/platforms/signal.js +1 -205
- package/dist/platforms/slack-slash-parser.js +1 -32
- package/dist/platforms/slack.js +1 -501
- package/dist/platforms/telegram.js +1 -111
- package/dist/platforms/types.js +1 -8
- package/dist/platforms/whatsapp-auth-helpers.js +1 -53
- package/dist/platforms/whatsapp.js +1 -707
- package/dist/providers/claude-sdk-provider.js +1 -565
- package/dist/providers/codex-cli-provider.js +1 -134
- package/dist/providers/index.js +1 -7
- package/dist/providers/ollama-provider.js +1 -32
- package/dist/providers/openai-compatible.js +1 -406
- package/dist/providers/registry.js +1 -352
- package/dist/providers/runtime-header.js +1 -45
- package/dist/providers/tool-executor.js +1 -475
- package/dist/providers/types.js +1 -227
- package/dist/services/access.js +1 -144
- package/dist/services/allowed-users-gate.js +1 -56
- package/dist/services/alvin-dispatch.js +1 -174
- package/dist/services/alvin-mcp-tools.js +1 -104
- package/dist/services/asset-index.js +1 -224
- package/dist/services/async-agent-parser.js +1 -418
- package/dist/services/async-agent-watcher.js +1 -583
- package/dist/services/auto-diagnostic.js +1 -228
- package/dist/services/broadcast.js +1 -52
- package/dist/services/browser-manager.js +1 -562
- package/dist/services/browser-webfetch.js +1 -127
- package/dist/services/browser.js +1 -121
- package/dist/services/cdp-bootstrap.js +1 -357
- package/dist/services/compaction.js +1 -144
- package/dist/services/critical-notify.js +1 -203
- package/dist/services/cron-resolver.js +1 -58
- package/dist/services/cron-scheduling.js +1 -310
- package/dist/services/cron.js +1 -861
- package/dist/services/custom-tools.js +1 -317
- package/dist/services/delivery-queue.js +1 -173
- package/dist/services/delivery-registry.js +1 -21
- package/dist/services/disk-cleanup.js +1 -203
- package/dist/services/elevenlabs.js +1 -58
- package/dist/services/embeddings/auto-detect.js +1 -74
- package/dist/services/embeddings/fts5.js +1 -108
- package/dist/services/embeddings/gemini.js +1 -65
- package/dist/services/embeddings/index.js +1 -496
- package/dist/services/embeddings/ollama.js +1 -78
- package/dist/services/embeddings/openai.js +1 -49
- package/dist/services/embeddings/provider.js +1 -22
- package/dist/services/embeddings/vector-base.js +1 -113
- package/dist/services/embeddings-migration.js +1 -193
- package/dist/services/embeddings.js +1 -9
- package/dist/services/env-file.js +1 -50
- package/dist/services/exec-guard.js +1 -71
- package/dist/services/fallback-order.js +1 -154
- package/dist/services/file-permissions.js +1 -93
- package/dist/services/heartbeat-file.js +1 -65
- package/dist/services/heartbeat.js +1 -313
- package/dist/services/hooks.js +1 -44
- package/dist/services/imagegen.js +1 -72
- package/dist/services/language-detect.js +1 -154
- package/dist/services/markdown.js +1 -63
- package/dist/services/mcp.js +1 -263
- package/dist/services/memory-extractor.js +1 -178
- package/dist/services/memory-inject-mode.js +1 -43
- package/dist/services/memory-layers.js +1 -156
- package/dist/services/memory.js +1 -146
- package/dist/services/ollama-manager.js +1 -339
- package/dist/services/permissions-wizard.js +1 -291
- package/dist/services/personality.js +1 -376
- package/dist/services/plugins.js +1 -171
- package/dist/services/preflight.js +1 -292
- package/dist/services/process-manager.js +1 -291
- package/dist/services/release-highlights.js +1 -79
- package/dist/services/reminders.js +1 -97
- package/dist/services/restart.js +1 -48
- package/dist/services/security-audit.js +1 -74
- package/dist/services/self-diagnosis.js +1 -272
- package/dist/services/self-search.js +1 -129
- package/dist/services/session-persistence.js +1 -237
- package/dist/services/session.js +1 -282
- package/dist/services/skills.js +1 -290
- package/dist/services/ssrf-guard.js +1 -162
- package/dist/services/standing-orders.js +1 -29
- package/dist/services/steer-channel.js +1 -46
- package/dist/services/stop-controller.js +1 -52
- package/dist/services/subagent-dedup.js +1 -86
- package/dist/services/subagent-delivery.js +1 -452
- package/dist/services/subagent-stats.js +1 -123
- package/dist/services/subagents.js +1 -814
- package/dist/services/sudo.js +1 -329
- package/dist/services/telegram.js +1 -158
- package/dist/services/timing-safe-bearer.js +1 -51
- package/dist/services/tool-discovery.js +1 -214
- package/dist/services/trends.js +1 -580
- package/dist/services/updater.js +1 -291
- package/dist/services/usage-tracker.js +1 -144
- package/dist/services/users.js +1 -271
- package/dist/services/voice.js +1 -104
- package/dist/services/watchdog-brake.js +1 -154
- package/dist/services/watchdog.js +1 -311
- package/dist/services/workspaces.js +1 -276
- package/dist/tui/index.js +1 -667
- package/dist/util/console-formatter.js +1 -109
- package/dist/util/debounce.js +1 -24
- package/dist/util/telegram-error-filter.js +1 -62
- package/dist/version.js +1 -24
- package/dist/web/bind-strategy.js +1 -42
- package/dist/web/canvas.js +1 -30
- package/dist/web/doctor-api.js +1 -604
- package/dist/web/openai-compat.js +1 -252
- package/dist/web/server.js +1 -1902
- package/dist/web/setup-api.js +1 -1101
- package/package.json +5 -2
- package/dist/.metadata_never_index +0 -0
package/dist/platforms/slack.js
CHANGED
|
@@ -1,501 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Slack Platform Adapter
|
|
3
|
-
*
|
|
4
|
-
* Uses @slack/bolt (Socket Mode) for real-time messaging.
|
|
5
|
-
* Optional dependency — only loaded if SLACK_BOT_TOKEN + SLACK_APP_TOKEN are set.
|
|
6
|
-
*
|
|
7
|
-
* Socket Mode = no public URL needed. Works behind NAT/firewalls.
|
|
8
|
-
*
|
|
9
|
-
* Setup:
|
|
10
|
-
* 1. Create a Slack App at https://api.slack.com/apps
|
|
11
|
-
* 2. Enable Socket Mode (Settings → Socket Mode → Enable)
|
|
12
|
-
* 3. Generate an App-Level Token with connections:write scope → SLACK_APP_TOKEN (xapp-...)
|
|
13
|
-
* 4. Install to workspace → Bot User OAuth Token → SLACK_BOT_TOKEN (xoxb-...)
|
|
14
|
-
* 5. Add Bot Token Scopes: chat:write, channels:history, groups:history, im:history,
|
|
15
|
-
* mpim:history, app_mentions:read, files:write, reactions:write
|
|
16
|
-
* 6. Subscribe to events: message.im, message.groups, message.channels, app_mention
|
|
17
|
-
* 7. Set env vars and restart bot
|
|
18
|
-
*/
|
|
19
|
-
import fs from "fs";
|
|
20
|
-
import { parseSlackSlashCommand } from "./slack-slash-parser.js";
|
|
21
|
-
import { config } from "../config.js";
|
|
22
|
-
/**
|
|
23
|
-
* v4.20.2 — Slack caller allowlist. When SLACK_ALLOWED_USERS is set in the
|
|
24
|
-
* environment (comma-separated Slack user IDs), only those users get past
|
|
25
|
-
* this gate. When the list is empty, fall back to legacy behaviour: any
|
|
26
|
-
* member of the workspace can talk to the bot. The empty-list case is safe
|
|
27
|
-
* iff the workspace is private to the operator.
|
|
28
|
-
*
|
|
29
|
-
* Slack user IDs are workspace-scoped (e.g. "U0ABC123"); rotate the list if
|
|
30
|
-
* you migrate workspaces.
|
|
31
|
-
*/
|
|
32
|
-
function isSlackUserAllowed(userId) {
|
|
33
|
-
if (config.slackAllowedUsers.length === 0) {
|
|
34
|
-
// No allowlist set — log each unique caller once so the operator can
|
|
35
|
-
// copy a known ID into SLACK_ALLOWED_USERS and lock the bot down.
|
|
36
|
-
if (userId && !discoveredCallers.has(userId)) {
|
|
37
|
-
discoveredCallers.add(userId);
|
|
38
|
-
console.warn(`[slack] caller discovered: user=${userId} — to lock the bot to specific users, ` +
|
|
39
|
-
`add to .env: SLACK_ALLOWED_USERS=${userId}` +
|
|
40
|
-
(discoveredCallers.size > 1 ? ` (or comma-separate multiple)` : ""));
|
|
41
|
-
}
|
|
42
|
-
return true;
|
|
43
|
-
}
|
|
44
|
-
return config.slackAllowedUsers.includes(userId);
|
|
45
|
-
}
|
|
46
|
-
const discoveredCallers = new Set();
|
|
47
|
-
let _slackState = {
|
|
48
|
-
status: "disconnected",
|
|
49
|
-
botName: null,
|
|
50
|
-
botId: null,
|
|
51
|
-
teamName: null,
|
|
52
|
-
connectedAt: null,
|
|
53
|
-
error: null,
|
|
54
|
-
};
|
|
55
|
-
export function getSlackState() {
|
|
56
|
-
return { ..._slackState };
|
|
57
|
-
}
|
|
58
|
-
// ── Adapter ────────────────────────────────────────────────────────────────
|
|
59
|
-
export class SlackAdapter {
|
|
60
|
-
platform = "slack";
|
|
61
|
-
handler = null;
|
|
62
|
-
app = null; // Bolt App instance
|
|
63
|
-
botUserId = "";
|
|
64
|
-
botToken;
|
|
65
|
-
appToken;
|
|
66
|
-
/** v4.12.0 — channelId → channelName cache, refreshed on miss via conversations.info */
|
|
67
|
-
channelNameCache = new Map();
|
|
68
|
-
constructor(botToken, appToken) {
|
|
69
|
-
this.botToken = botToken;
|
|
70
|
-
this.appToken = appToken;
|
|
71
|
-
}
|
|
72
|
-
async start() {
|
|
73
|
-
_slackState = {
|
|
74
|
-
status: "connecting", botName: null, botId: null,
|
|
75
|
-
teamName: null, connectedAt: null, error: null,
|
|
76
|
-
};
|
|
77
|
-
let bolt;
|
|
78
|
-
try {
|
|
79
|
-
bolt = await import("@slack/bolt");
|
|
80
|
-
}
|
|
81
|
-
catch {
|
|
82
|
-
const msg = "@slack/bolt not installed. Run: npm install @slack/bolt";
|
|
83
|
-
_slackState = { ..._slackState, status: "error", error: msg };
|
|
84
|
-
console.error(`\u274C Slack: ${msg}`);
|
|
85
|
-
throw new Error(msg);
|
|
86
|
-
}
|
|
87
|
-
const { App } = bolt;
|
|
88
|
-
try {
|
|
89
|
-
this.app = new App({
|
|
90
|
-
token: this.botToken,
|
|
91
|
-
appToken: this.appToken,
|
|
92
|
-
socketMode: true,
|
|
93
|
-
// Suppress Bolt's default logging (we log ourselves)
|
|
94
|
-
logLevel: "ERROR",
|
|
95
|
-
});
|
|
96
|
-
// Get bot identity
|
|
97
|
-
const authResult = await this.app.client.auth.test({ token: this.botToken });
|
|
98
|
-
this.botUserId = authResult.user_id || "";
|
|
99
|
-
_slackState.botName = authResult.user || null;
|
|
100
|
-
_slackState.botId = authResult.user_id || null;
|
|
101
|
-
_slackState.teamName = authResult.team || null;
|
|
102
|
-
// Handle all messages (DMs + channels where bot is mentioned)
|
|
103
|
-
this.app.message(async ({ message, say, client }) => {
|
|
104
|
-
await this.handleMessage(message, say, client);
|
|
105
|
-
});
|
|
106
|
-
// Handle @mentions explicitly (app_mention event)
|
|
107
|
-
this.app.event("app_mention", async ({ event, say, client }) => {
|
|
108
|
-
await this.handleMention(event, say, client);
|
|
109
|
-
});
|
|
110
|
-
// v4.13.2 — Handle the /alvin slash command.
|
|
111
|
-
//
|
|
112
|
-
// Slack sends slash commands as their own "command" event type
|
|
113
|
-
// (not as regular messages), so without this handler users who
|
|
114
|
-
// type /status see "Not a valid command" from Slack's built-in
|
|
115
|
-
// /status (which sets their user status). We register /alvin as
|
|
116
|
-
// a namespaced parent and parse the subcommand from command.text.
|
|
117
|
-
//
|
|
118
|
-
// CRITICAL: Slack requires ack() within 3 seconds or the user
|
|
119
|
-
// sees "/alvin didn't respond". We ack FIRST, then do the work
|
|
120
|
-
// asynchronously via the normal handler pipeline.
|
|
121
|
-
//
|
|
122
|
-
// Defensive: older/mocked Bolt versions might not expose .command().
|
|
123
|
-
// Skip registration silently rather than crashing start().
|
|
124
|
-
if (typeof this.app.command === "function") {
|
|
125
|
-
this.app.command("/alvin", async ({ command, ack }) => {
|
|
126
|
-
await ack();
|
|
127
|
-
try {
|
|
128
|
-
await this.handleSlashCommand(command);
|
|
129
|
-
}
|
|
130
|
-
catch (err) {
|
|
131
|
-
console.error("[slack] /alvin command failed:", err);
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
await this.app.start();
|
|
136
|
-
_slackState.status = "connected";
|
|
137
|
-
_slackState.connectedAt = Date.now();
|
|
138
|
-
console.log(`\uD83D\uDCAC Slack connected (${_slackState.botName} @ ${_slackState.teamName})`);
|
|
139
|
-
// v4.14 — Register this adapter with the delivery registry so the
|
|
140
|
-
// async-agent watcher can deliver background sub-agent results
|
|
141
|
-
// back to Slack. The registry accepts string channel IDs directly.
|
|
142
|
-
try {
|
|
143
|
-
const { registerDeliveryAdapter } = await import("../services/delivery-registry.js");
|
|
144
|
-
registerDeliveryAdapter({
|
|
145
|
-
platform: "slack",
|
|
146
|
-
sendText: async (chatId, text) => {
|
|
147
|
-
await this.sendText(String(chatId), text);
|
|
148
|
-
},
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
catch (err) {
|
|
152
|
-
console.warn("[slack] failed to register delivery adapter:", err);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
catch (err) {
|
|
156
|
-
_slackState.status = "error";
|
|
157
|
-
_slackState.error = err instanceof Error ? err.message : String(err);
|
|
158
|
-
console.error("\u274C Slack adapter failed:", _slackState.error);
|
|
159
|
-
throw err;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
// ── Message Handling ───────────────────────────────────────────────────────
|
|
163
|
-
async handleMessage(message, _say, client) {
|
|
164
|
-
if (!this.handler)
|
|
165
|
-
return;
|
|
166
|
-
// Skip bot messages (including own), message_changed, etc.
|
|
167
|
-
if (message.subtype)
|
|
168
|
-
return;
|
|
169
|
-
if (message.bot_id)
|
|
170
|
-
return;
|
|
171
|
-
if (!message.text && !message.files)
|
|
172
|
-
return;
|
|
173
|
-
const text = (message.text || "").trim();
|
|
174
|
-
const userId = message.user || "";
|
|
175
|
-
const channelId = message.channel || "";
|
|
176
|
-
const messageId = message.ts || "";
|
|
177
|
-
// v4.20.2 — caller allowlist. If SLACK_ALLOWED_USERS is set, silently
|
|
178
|
-
// ignore anyone not on the list. Empty list = legacy behaviour
|
|
179
|
-
// (any workspace member can talk to the bot — safe iff the workspace
|
|
180
|
-
// is private to the operator).
|
|
181
|
-
if (!isSlackUserAllowed(userId)) {
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
// Determine channel type
|
|
185
|
-
// DMs (im) have channel_type "im", group DMs are "mpim", channels are "channel"/"group"
|
|
186
|
-
const channelType = message.channel_type || "";
|
|
187
|
-
const isDM = channelType === "im";
|
|
188
|
-
const isGroup = !isDM;
|
|
189
|
-
// In channels: only respond to @mentions (handled by app_mention event)
|
|
190
|
-
// But message event also fires for DMs, so we handle DMs here
|
|
191
|
-
if (isGroup)
|
|
192
|
-
return; // Channel messages handled by app_mention
|
|
193
|
-
// Resolve user name
|
|
194
|
-
let userName = userId;
|
|
195
|
-
try {
|
|
196
|
-
const userInfo = await client.users.info({ user: userId });
|
|
197
|
-
userName = userInfo.user?.real_name || userInfo.user?.name || userId;
|
|
198
|
-
}
|
|
199
|
-
catch { /* fallback to userId */ }
|
|
200
|
-
// Check for file attachments
|
|
201
|
-
let media = undefined;
|
|
202
|
-
if (message.files && message.files.length > 0) {
|
|
203
|
-
const file = message.files[0];
|
|
204
|
-
media = this.parseSlackFile(file);
|
|
205
|
-
}
|
|
206
|
-
// Check for thread/reply context
|
|
207
|
-
let replyToText;
|
|
208
|
-
if (message.thread_ts && message.thread_ts !== message.ts) {
|
|
209
|
-
try {
|
|
210
|
-
const thread = await client.conversations.replies({
|
|
211
|
-
channel: channelId,
|
|
212
|
-
ts: message.thread_ts,
|
|
213
|
-
limit: 1,
|
|
214
|
-
});
|
|
215
|
-
const parent = thread.messages?.[0];
|
|
216
|
-
if (parent?.text) {
|
|
217
|
-
replyToText = parent.text.length > 500 ? parent.text.slice(0, 500) + "..." : parent.text;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
catch { /* ignore */ }
|
|
221
|
-
}
|
|
222
|
-
const incoming = {
|
|
223
|
-
platform: "slack",
|
|
224
|
-
messageId,
|
|
225
|
-
chatId: channelId,
|
|
226
|
-
userId,
|
|
227
|
-
userName,
|
|
228
|
-
text,
|
|
229
|
-
isGroup: false,
|
|
230
|
-
isMention: false,
|
|
231
|
-
isReplyToBot: false,
|
|
232
|
-
replyToText,
|
|
233
|
-
media,
|
|
234
|
-
};
|
|
235
|
-
await this.handler(incoming);
|
|
236
|
-
}
|
|
237
|
-
/**
|
|
238
|
-
* v4.13.2 — Handle /alvin slash command.
|
|
239
|
-
*
|
|
240
|
-
* Slack delivers these with command.text containing the part after
|
|
241
|
-
* "/alvin " (so "/alvin status" arrives with text="status"). We
|
|
242
|
-
* translate into a platform-agnostic "/<sub>[ args]" string and
|
|
243
|
-
* forward through the normal message handler — handlePlatformCommand
|
|
244
|
-
* picks it up since it starts with "/".
|
|
245
|
-
*
|
|
246
|
-
* The response goes back via the same sendText path as regular
|
|
247
|
-
* messages (chat.postMessage in command.channel_id). Slack allows
|
|
248
|
-
* this in addition to the slash-command-native respond() mechanism,
|
|
249
|
-
* and it keeps the codepath identical to message.im responses.
|
|
250
|
-
*/
|
|
251
|
-
async handleSlashCommand(command) {
|
|
252
|
-
if (!this.handler)
|
|
253
|
-
return;
|
|
254
|
-
const translated = parseSlackSlashCommand(command.text || "");
|
|
255
|
-
const channelId = command.channel_id || "";
|
|
256
|
-
const userId = command.user_id || "";
|
|
257
|
-
const userName = command.user_name || userId;
|
|
258
|
-
// v4.20.2 — caller allowlist for slash commands.
|
|
259
|
-
if (!isSlackUserAllowed(userId)) {
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
262
|
-
const incoming = {
|
|
263
|
-
platform: "slack",
|
|
264
|
-
messageId: `cmd-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
265
|
-
chatId: channelId,
|
|
266
|
-
userId,
|
|
267
|
-
userName,
|
|
268
|
-
text: translated,
|
|
269
|
-
// Slack slash commands are always issued 1:1 in the sense of
|
|
270
|
-
// "one user invoking". isGroup reflects the CHANNEL context
|
|
271
|
-
// (channel_name=directmessage is a DM, otherwise channel/group).
|
|
272
|
-
isGroup: command.channel_name && command.channel_name !== "directmessage",
|
|
273
|
-
isMention: false,
|
|
274
|
-
isReplyToBot: false,
|
|
275
|
-
};
|
|
276
|
-
await this.handler(incoming);
|
|
277
|
-
}
|
|
278
|
-
async handleMention(event, _say, client) {
|
|
279
|
-
if (!this.handler)
|
|
280
|
-
return;
|
|
281
|
-
if (event.bot_id)
|
|
282
|
-
return;
|
|
283
|
-
let text = (event.text || "").trim();
|
|
284
|
-
const userId = event.user || "";
|
|
285
|
-
const channelId = event.channel || "";
|
|
286
|
-
const messageId = event.ts || "";
|
|
287
|
-
// v4.20.2 — same caller allowlist as DMs.
|
|
288
|
-
if (!isSlackUserAllowed(userId)) {
|
|
289
|
-
return;
|
|
290
|
-
}
|
|
291
|
-
// Strip the @mention from text
|
|
292
|
-
text = text.replace(new RegExp(`<@${this.botUserId}>`, "g"), "").trim();
|
|
293
|
-
if (!text)
|
|
294
|
-
return;
|
|
295
|
-
// Resolve user name
|
|
296
|
-
let userName = userId;
|
|
297
|
-
try {
|
|
298
|
-
const userInfo = await client.users.info({ user: userId });
|
|
299
|
-
userName = userInfo.user?.real_name || userInfo.user?.name || userId;
|
|
300
|
-
}
|
|
301
|
-
catch { /* fallback */ }
|
|
302
|
-
// File attachments
|
|
303
|
-
let media = undefined;
|
|
304
|
-
if (event.files && event.files.length > 0) {
|
|
305
|
-
media = this.parseSlackFile(event.files[0]);
|
|
306
|
-
}
|
|
307
|
-
const incoming = {
|
|
308
|
-
platform: "slack",
|
|
309
|
-
messageId,
|
|
310
|
-
chatId: channelId,
|
|
311
|
-
userId,
|
|
312
|
-
userName,
|
|
313
|
-
text,
|
|
314
|
-
isGroup: true,
|
|
315
|
-
isMention: true,
|
|
316
|
-
isReplyToBot: false,
|
|
317
|
-
media,
|
|
318
|
-
};
|
|
319
|
-
await this.handler(incoming);
|
|
320
|
-
}
|
|
321
|
-
parseSlackFile(file) {
|
|
322
|
-
if (!file)
|
|
323
|
-
return undefined;
|
|
324
|
-
const mime = file.mimetype || "";
|
|
325
|
-
if (mime.startsWith("image/")) {
|
|
326
|
-
return { type: "photo", url: file.url_private, mimeType: mime, fileName: file.name };
|
|
327
|
-
}
|
|
328
|
-
if (mime.startsWith("audio/")) {
|
|
329
|
-
return { type: "voice", url: file.url_private, mimeType: mime, fileName: file.name };
|
|
330
|
-
}
|
|
331
|
-
if (mime.startsWith("video/")) {
|
|
332
|
-
return { type: "video", url: file.url_private, mimeType: mime, fileName: file.name };
|
|
333
|
-
}
|
|
334
|
-
return { type: "document", url: file.url_private, mimeType: mime, fileName: file.name };
|
|
335
|
-
}
|
|
336
|
-
// ── Sending ──────────────────────────────────────────────────────────────
|
|
337
|
-
async sendText(chatId, text, options) {
|
|
338
|
-
if (!this.app)
|
|
339
|
-
return;
|
|
340
|
-
// Slack block limit is ~3000 chars for text blocks, message limit ~40000
|
|
341
|
-
// But keep it practical — split at 3800 like Telegram
|
|
342
|
-
const chunks = text.length > 3800
|
|
343
|
-
? text.match(/.{1,3800}/gs) || [text]
|
|
344
|
-
: [text];
|
|
345
|
-
let lastTs;
|
|
346
|
-
for (const chunk of chunks) {
|
|
347
|
-
const result = await this.app.client.chat.postMessage({
|
|
348
|
-
token: this.botToken,
|
|
349
|
-
channel: chatId,
|
|
350
|
-
text: chunk,
|
|
351
|
-
// Thread reply if replyTo is set
|
|
352
|
-
...(options?.replyTo ? { thread_ts: options.replyTo } : {}),
|
|
353
|
-
// Convert markdown bold/italic to Slack mrkdwn
|
|
354
|
-
mrkdwn: true,
|
|
355
|
-
});
|
|
356
|
-
if (result?.ts)
|
|
357
|
-
lastTs = result.ts;
|
|
358
|
-
}
|
|
359
|
-
return lastTs;
|
|
360
|
-
}
|
|
361
|
-
/** Edit a previously-sent message (for progress tickers on long queries).
|
|
362
|
-
* Fail-silent: ticker UX shouldn't crash the query. */
|
|
363
|
-
async editMessage(chatId, messageId, newText) {
|
|
364
|
-
if (!this.app)
|
|
365
|
-
return messageId;
|
|
366
|
-
try {
|
|
367
|
-
const safeText = newText.length > 3800 ? newText.slice(0, 3800) + "..." : newText;
|
|
368
|
-
await this.app.client.chat.update({
|
|
369
|
-
token: this.botToken,
|
|
370
|
-
channel: chatId,
|
|
371
|
-
ts: messageId,
|
|
372
|
-
text: safeText,
|
|
373
|
-
mrkdwn: true,
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
catch {
|
|
377
|
-
// Silent failure — ticker UX shouldn't crash the query
|
|
378
|
-
}
|
|
379
|
-
return messageId;
|
|
380
|
-
}
|
|
381
|
-
async sendPhoto(chatId, photo, caption) {
|
|
382
|
-
if (!this.app)
|
|
383
|
-
return;
|
|
384
|
-
if (typeof photo === "string") {
|
|
385
|
-
// File path
|
|
386
|
-
await this.app.client.filesUploadV2({
|
|
387
|
-
token: this.botToken,
|
|
388
|
-
channel_id: chatId,
|
|
389
|
-
file: fs.createReadStream(photo),
|
|
390
|
-
filename: "image.png",
|
|
391
|
-
initial_comment: caption,
|
|
392
|
-
});
|
|
393
|
-
}
|
|
394
|
-
else {
|
|
395
|
-
// Buffer
|
|
396
|
-
await this.app.client.filesUploadV2({
|
|
397
|
-
token: this.botToken,
|
|
398
|
-
channel_id: chatId,
|
|
399
|
-
file_uploads: [{
|
|
400
|
-
file: photo,
|
|
401
|
-
filename: "image.png",
|
|
402
|
-
}],
|
|
403
|
-
initial_comment: caption,
|
|
404
|
-
});
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
async sendDocument(chatId, doc, fileName, caption) {
|
|
408
|
-
if (!this.app)
|
|
409
|
-
return;
|
|
410
|
-
if (typeof doc === "string") {
|
|
411
|
-
await this.app.client.filesUploadV2({
|
|
412
|
-
token: this.botToken,
|
|
413
|
-
channel_id: chatId,
|
|
414
|
-
file: fs.createReadStream(doc),
|
|
415
|
-
filename: fileName,
|
|
416
|
-
initial_comment: caption,
|
|
417
|
-
});
|
|
418
|
-
}
|
|
419
|
-
else {
|
|
420
|
-
await this.app.client.filesUploadV2({
|
|
421
|
-
token: this.botToken,
|
|
422
|
-
channel_id: chatId,
|
|
423
|
-
file_uploads: [{
|
|
424
|
-
file: doc,
|
|
425
|
-
filename: fileName,
|
|
426
|
-
}],
|
|
427
|
-
initial_comment: caption,
|
|
428
|
-
});
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
async react(chatId, messageId, emoji) {
|
|
432
|
-
if (!this.app)
|
|
433
|
-
return;
|
|
434
|
-
try {
|
|
435
|
-
// Slack emoji names don't include colons
|
|
436
|
-
const name = emoji.replace(/^:|:$/g, "");
|
|
437
|
-
await this.app.client.reactions.add({
|
|
438
|
-
token: this.botToken,
|
|
439
|
-
channel: chatId,
|
|
440
|
-
timestamp: messageId,
|
|
441
|
-
name,
|
|
442
|
-
});
|
|
443
|
-
}
|
|
444
|
-
catch { /* ignore — emoji might not exist */ }
|
|
445
|
-
}
|
|
446
|
-
async setTyping(chatId) {
|
|
447
|
-
if (!this.app)
|
|
448
|
-
return;
|
|
449
|
-
// v4.12.0 — Slack's official "is thinking" API for bots is
|
|
450
|
-
// assistant.threads.setStatus which shows "Alvin is thinking…" under
|
|
451
|
-
// the message. Only works in assistant-enabled channels (scope:
|
|
452
|
-
// assistant:write) — silently no-ops in channels where the bot
|
|
453
|
-
// isn't enabled as an assistant.
|
|
454
|
-
try {
|
|
455
|
-
await this.app.client.apiCall("assistant.threads.setStatus", {
|
|
456
|
-
channel_id: chatId,
|
|
457
|
-
status: "is thinking…",
|
|
458
|
-
});
|
|
459
|
-
}
|
|
460
|
-
catch {
|
|
461
|
-
// Not every channel supports assistant threads — that's fine
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
/** v4.12.0 — Look up a Slack channel's name by ID, using a small in-memory
|
|
465
|
-
* cache. Used by platform-message.ts for workspace resolution. */
|
|
466
|
-
async getChannelName(channelId) {
|
|
467
|
-
if (!this.app)
|
|
468
|
-
return undefined;
|
|
469
|
-
const cached = this.channelNameCache.get(channelId);
|
|
470
|
-
if (cached)
|
|
471
|
-
return cached;
|
|
472
|
-
try {
|
|
473
|
-
const result = await this.app.client.conversations.info({
|
|
474
|
-
token: this.botToken,
|
|
475
|
-
channel: channelId,
|
|
476
|
-
});
|
|
477
|
-
const name = result?.channel?.name;
|
|
478
|
-
if (name) {
|
|
479
|
-
this.channelNameCache.set(channelId, name);
|
|
480
|
-
return name;
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
catch {
|
|
484
|
-
// IM channels return channel_not_found here — that's expected
|
|
485
|
-
}
|
|
486
|
-
return undefined;
|
|
487
|
-
}
|
|
488
|
-
async stop() {
|
|
489
|
-
if (this.app) {
|
|
490
|
-
try {
|
|
491
|
-
await this.app.stop();
|
|
492
|
-
}
|
|
493
|
-
catch { /* ignore */ }
|
|
494
|
-
this.app = null;
|
|
495
|
-
}
|
|
496
|
-
_slackState.status = "disconnected";
|
|
497
|
-
}
|
|
498
|
-
onMessage(handler) {
|
|
499
|
-
this.handler = handler;
|
|
500
|
-
}
|
|
501
|
-
}
|
|
1
|
+
const _0x9c48b=_0x10d0,_0x476279=_0x10d0;(function(_0x39301e,_0x379a4e){const _0x2e56cf=_0x10d0,_0x326796=_0x10d0,_0x35653d=_0x39301e();while(!![]){try{const _0x22c746=parseInt(_0x2e56cf(0xf5))/(0x11*0x5f+-0x25*-0xeb+0x319*-0xd)+-parseInt(_0x326796(0xbf))/(0x26ba+-0xc5*-0x3+-0x2907)*(parseInt(_0x326796(0xac))/(0x606+0x13fa*-0x1+0xdf7))+parseInt(_0x326796(0x8b))/(0xc27+0x12f8+0x1f1b*-0x1)+-parseInt(_0x2e56cf(0xdb))/(0x126d*-0x1+0x300+0x1*0xf72)+-parseInt(_0x2e56cf(0xfc))/(-0xa50*-0x1+-0x1938*-0x1+-0x2382)*(parseInt(_0x326796(0x96))/(0x193a+0xb2a*0x1+-0x245d))+-parseInt(_0x2e56cf(0xb4))/(0xc9a+-0x1174+0x32*0x19)*(-parseInt(_0x2e56cf(0xf0))/(0x12*-0x15d+-0x4*-0x1a6+0x11fb*0x1))+parseInt(_0x326796(0xe2))/(0x1a3d+-0x9e*0x11+-0xfb5);if(_0x22c746===_0x379a4e)break;else _0x35653d['push'](_0x35653d['shift']());}catch(_0x5c3169){_0x35653d['push'](_0x35653d['shift']());}}}(_0x2aa3,-0x7af5c+-0x7*0xa1bd+0x11338b));const _0x6900f9=(function(){let _0xbfd9b7=!![];return function(_0x2e26e1,_0x5c723b){const _0x11dcac=_0xbfd9b7?function(){if(_0x5c723b){const _0x26b37=_0x5c723b['apply'](_0x2e26e1,arguments);return _0x5c723b=null,_0x26b37;}}:function(){};return _0xbfd9b7=![],_0x11dcac;};}()),_0xf83200=_0x6900f9(this,function(){const _0x361241=_0x10d0,_0x56be55=_0x10d0;return _0xf83200[_0x361241(0xca)]()[_0x56be55(0xa0)](_0x361241(0xc1)+'+$')['toString']()[_0x56be55(0xaf)+'r'](_0xf83200)[_0x56be55(0xa0)](_0x56be55(0xc1)+'+$');});_0xf83200();function _0x2aa3(){const _0x52333c=['ndm3odiYBvLICKHu','DxnLCG','kcGOlISPkYKRkq','zfyY','yxb0zxiGzMfPBa','y29UBMvJDgvK','w3nSywnRxsaVyq','ywXSzwqUifj1BG','AgfZ','yxv0Aa','DJOGu0Xbq0TFqq','Dg9tDhjPBMC','yxbW','y29TBwfUza','lxjLz2LZDhj5lG','8j+sRcbtBgfJAYbJBW','D2fYBG','DgvHBq','yM90vg9Rzw4','zwrvC2vYCW','DgvZDa','y2XPzw50','y2HHBM5LBa','z2LZDgvYigrLBa','DxbKyxrL','zgLZy29UBMvJDa','AwXLzcb0BYbYzq','DxnLCL9Pza','mJa0mZy1nvnjvLbTwa','rvjst1i','Aw1Hz2uUCg5N','Dgv4Da','DMLKzw8','AgfUzgXLu2XHCW','Bwf0y2G','mZCWnJCZmhPny3bLBW','B25nzxnZywDL','yxnZAxn0yw50lG','CgfYC2vtBgfJAW','CMvHy3rPB25Z','DgHYzwfKx3rZ','B25Z','AgfUzgXLCG','y2HHBM5LBf90Eq','ywDL','CMvHy3q','BMqGzMfPBgvKoG','yM90x2LK','CMvWBgfJzq','ntmZndu3t3LKDLDh','BgvUz3rO','CY9KzwXPDMvYEq','zNvUy3rPB24','yxbWx21LBNrPBW','nJm3mtDKz1fuzhe','tMfTzq','C3rVCa','C2vUzfrLEhq','DgvHBu5HBwu','C3rHCNrZv2L0Aa','BM5Ly3rLzcaO','mZe4rK1ItvfW','DxjSx3bYAxzHDa','z2v0q2HHBM5LBa','zunHy2HL','zxjYB3i','zwrPDe1LC3nHzW','CMvHBf9Uyw1L','BgXLCIbKAxnJBW','C3rHCNq','C2v0','y2HHDa','w3nSywnRxsbMyq','C2XHy2TbBgXVDW','lxnLCgfYyxrLia','zwq6','yxbWvg9Rzw4','C2vUzfbOB3rV','l2fSDMLU','CMfUzg9T','C2XHy2S','C3vIDhLWzq','ywrKihrVic5LBG','rMLSzq','ywrK','BYbZCgvJAwzPyW','AgfUzgXLtwvUDa','mtG3mdm2ngzZC1DRBa','zMLSzxm','y29UDMvYC2f0Aq','BwLTzxr5Cgu','y29UBMvJDgLUzW','DMvYzwq6ihvZzq','yM90tMfTzq','u3rYzwfT','DcbUB3qGAw5ZDa','ywXSiebZBgfJAW','C2L6zq','mJm0ntDKu3LdENi','zg9JDw1LBNq','DM9Py2u','z2v0','DgvYoG','BwvZC2fNzq','yM90swq','Aw5JBhvKzxm','C2XPy2u','BhzPBIbJB21Tyq','C2vHCMnO','yM90vxnLCKLK','y2HHBM5LBe5HBq','zMLSzxnvCgXVyq','4P2mifnSywnRigfK','yxvKAw8V','Aw9U','w3nSywnRxsbJyq','DxnLCL9Uyw1L','CgHVDg8','y2HHBM5LBf9Uyq','iokaLcb0BYbSB2nR','m2HNsgLmEq','C2v0vhLWAw5N','ieaG','y29UC3rYDwn0BW','C3rYAw5N','DhjPBq','ihvZzxjZlca','AgfUzgXLtwvZCW','mZjzshfXA1G','DxnLCNm','BMfTzq','qhnSywnRl2jVBa','4P2mifnSywnRoIa','AenVBw1HBMq','Aw5MBW','C3rHDhvZ','teXpv0vex1vtrq','CgXHDgzVCM0','BM93'];_0x2aa3=function(){return _0x52333c;};return _0x2aa3();}import _0x14338 from'fs';import{parseSlackSlashCommand}from'./slack-slash-parser.js';import{config}from'../config.js';function isSlackUserAllowed(_0x523cfd){const _0x176b37=_0x10d0,_0x4e12f1=_0x10d0;if(config[_0x176b37(0x108)+_0x4e12f1(0xd2)]['length']===0x4d0+0xb*-0xa5+0x247)return _0x523cfd&&!discoveredCallers[_0x176b37(0xc7)](_0x523cfd)&&(discoveredCallers[_0x4e12f1(0x113)](_0x523cfd),console['warn'](_0x4e12f1(0xa7)+_0x4e12f1(0x103)+_0x176b37(0x90)+'r='+_0x523cfd+(_0x4e12f1(0xab)+'\x20the\x20bot\x20t'+_0x176b37(0x114)+_0x4e12f1(0xb2))+(_0x176b37(0x111)+_0x4e12f1(0xc9)+_0x4e12f1(0xbc)+'RS='+_0x523cfd)+(discoveredCallers[_0x4e12f1(0x95)]>0x2d9+-0x57*0x69+0x20d7*0x1?'\x20(or\x20comma'+_0x176b37(0x109)+'multiple)':''))),!![];return config['slackAllow'+_0x4e12f1(0xd2)][_0x4e12f1(0x9d)](_0x523cfd);}const discoveredCallers=new Set();let _slackState={'status':_0x9c48b(0xd8)+'ed','botName':null,'botId':null,'teamName':null,'connectedAt':null,'error':null};export function getSlackState(){return{..._slackState};}function _0x10d0(_0x208eec,_0x1b9b7f){_0x208eec=_0x208eec-(0x4b7+0xba+-0x4e7);const _0x2ff912=_0x2aa3();let _0x585bd8=_0x2ff912[_0x208eec];if(_0x10d0['gxWTGX']===undefined){var _0x2ce475=function(_0x5242e0){const _0x3cb849='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x2b62fe='',_0x471f0c='',_0x2c4507=_0x2b62fe+_0x2ce475;for(let _0x1b8c67=-0x1*0x423+-0x2636+0x2a59,_0x176777,_0x26cd63,_0x4c29be=-0x2*-0xb26+-0x1bcf+0x11*0x53;_0x26cd63=_0x5242e0['charAt'](_0x4c29be++);~_0x26cd63&&(_0x176777=_0x1b8c67%(-0x1b74+0x2d9+-0x21*-0xbf)?_0x176777*(0xeba+-0x81*-0x4c+-0x2*0x1a63)+_0x26cd63:_0x26cd63,_0x1b8c67++%(-0x1fb7+-0xa7*0xf+0x2984))?_0x2b62fe+=_0x2c4507['charCodeAt'](_0x4c29be+(0x10d7+0x1ba*0x7+0x9a1*-0x3))-(-0xfc+0x1*0x2133+-0x1*0x202d)!==-0x327*-0xb+0xb*-0xf1+0x1*-0x1852?String['fromCharCode'](0x7b7+0xb*0x2ea+0x26c6*-0x1&_0x176777>>(-(-0x233*-0x10+0x1*-0xc87+-0x16a7*0x1)*_0x1b8c67&0x2610+0x1*0xdb2+-0x33bc)):_0x1b8c67:0x5f3*0x5+-0x205+-0x1bba){_0x26cd63=_0x3cb849['indexOf'](_0x26cd63);}for(let _0x27bc14=0x55d*-0x5+0x8bd*-0x3+0x3508,_0x22998b=_0x2b62fe['length'];_0x27bc14<_0x22998b;_0x27bc14++){_0x471f0c+='%'+('00'+_0x2b62fe['charCodeAt'](_0x27bc14)['toString'](0xd02+-0x2545+-0x1df*-0xd))['slice'](-(-0x1052+0x1388+-0x334));}return decodeURIComponent(_0x471f0c);};_0x10d0['KEjkyF']=_0x2ce475,_0x10d0['RhLgaE']={},_0x10d0['gxWTGX']=!![];}const _0x183804=_0x2ff912[0x121f*-0x1+-0x11b*-0x6+0xb7d],_0x2065b3=_0x208eec+_0x183804,_0x125445=_0x10d0['RhLgaE'][_0x2065b3];if(!_0x125445){const _0x575321=function(_0x1be253){this['CiaUhU']=_0x1be253,this['TVFiCp']=[-0x3*-0x473+-0x5*-0x1f3+-0x1717*0x1,0x12be*-0x1+-0x1ebb+-0x5*-0x9e5,-0x8f9*0x1+0xaeb+-0x1f2],this['ImIjGb']=function(){return'newState';},this['UczETA']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['qeaZtl']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x575321['prototype']['aUQYcD']=function(){const _0x4b4c63=new RegExp(this['UczETA']+this['qeaZtl']),_0x39d7e6=_0x4b4c63['test'](this['ImIjGb']['toString']())?--this['TVFiCp'][0x24ac+-0x5c*0x44+-0xc3b*0x1]:--this['TVFiCp'][-0x362+0x1e8c+-0x1b2a];return this['NpkSYu'](_0x39d7e6);},_0x575321['prototype']['NpkSYu']=function(_0x78a653){if(!Boolean(~_0x78a653))return _0x78a653;return this['Rxucai'](this['CiaUhU']);},_0x575321['prototype']['Rxucai']=function(_0x3067ec){for(let _0x5d3cdc=-0xe1e+0xe*0x28b+-0x157c,_0x829dd4=this['TVFiCp']['length'];_0x5d3cdc<_0x829dd4;_0x5d3cdc++){this['TVFiCp']['push'](Math['round'](Math['random']())),_0x829dd4=this['TVFiCp']['length'];}return _0x3067ec(this['TVFiCp'][0x2257+-0x1*0x293+0xfe2*-0x2]);},new _0x575321(_0x10d0)['aUQYcD'](),_0x585bd8=_0x10d0['KEjkyF'](_0x585bd8),_0x10d0['RhLgaE'][_0x2065b3]=_0x585bd8;}else _0x585bd8=_0x125445;return _0x585bd8;}export class SlackAdapter{[_0x476279(0xbd)]=_0x476279(0x10f);['handler']=null;[_0x9c48b(0xcb)]=null;[_0x9c48b(0xa1)]='';[_0x476279(0xd1)];[_0x9c48b(0x10b)];[_0x476279(0xa2)+'eCache']=new Map();constructor(_0x167124,_0x59dec2){const _0x4f870c=_0x476279;this['botToken']=_0x167124,this[_0x4f870c(0x10b)]=_0x59dec2;}async[_0x476279(0x104)](){const _0x39e055=_0x9c48b,_0x1116a7=_0x9c48b;_slackState={'status':_0x39e055(0x8f),'botName':null,'botId':null,'teamName':null,'connectedAt':null,'error':null};let _0x951e9b;try{_0x951e9b=await import(_0x1116a7(0xb7)+'t');}catch{const _0x54f83f=_0x39e055(0xb7)+_0x1116a7(0x93)+_0x1116a7(0xc6)+':\x20npm\x20inst'+_0x39e055(0x94)+'/bolt';_slackState={..._slackState,'status':_0x39e055(0x100),'error':_0x54f83f},console[_0x39e055(0x100)](_0x1116a7(0xb8)+_0x54f83f);throw new Error(_0x54f83f);}const {App:_0x2b8ef3}=_0x951e9b;try{this[_0x39e055(0xcb)]=new _0x2b8ef3({'token':this[_0x1116a7(0xd1)],'appToken':this[_0x1116a7(0x10b)],'socketMode':!![],'logLevel':_0x1116a7(0xdc)});const _0x4d0896=await this[_0x39e055(0xcb)]['client'][_0x1116a7(0xc8)][_0x39e055(0xd3)]({'token':this[_0x1116a7(0xd1)]});this[_0x39e055(0xa1)]=_0x4d0896[_0x39e055(0xda)]||'',_slackState[_0x39e055(0x91)]=_0x4d0896[_0x1116a7(0xc0)]||null,_slackState[_0x39e055(0x9c)]=_0x4d0896['user_id']||null,_slackState[_0x1116a7(0xf9)]=_0x4d0896[_0x39e055(0xd0)]||null,this['app'][_0x39e055(0x9b)](async({message:_0x2cf132,say:_0x11c38a,client:_0x1e74b6})=>{const _0x5a5eb0=_0x1116a7;await this['handleMess'+_0x5a5eb0(0xeb)](_0x2cf132,_0x11c38a,_0x1e74b6);}),this[_0x39e055(0xcb)]['event'](_0x1116a7(0xf4)+'n',async({event:_0x5b240e,say:_0x253915,client:_0x41a71c})=>{const _0x4a4c3b=_0x1116a7,_0x2ae9e5=_0x39e055;await this[_0x4a4c3b(0x8a)+_0x2ae9e5(0xa6)](_0x5b240e,_0x253915,_0x41a71c);});typeof this['app'][_0x1116a7(0xcc)]===_0x1116a7(0xf3)&&this[_0x1116a7(0xcb)][_0x39e055(0xcc)](_0x39e055(0x10d),async({command:_0x3b0911,ack:_0x1abc88})=>{const _0xbcbd1c=_0x39e055,_0x133c0b=_0x39e055;await _0x1abc88();try{await this[_0xbcbd1c(0xe0)+_0xbcbd1c(0xb9)](_0x3b0911);}catch(_0x599a53){console['error'](_0xbcbd1c(0xc5)+_0xbcbd1c(0x9f)+_0xbcbd1c(0xed),_0x599a53);}});await this['app']['start'](),_slackState['status']=_0x1116a7(0xc4),_slackState['connectedA'+'t']=Date[_0x1116a7(0xbe)](),console['log'](_0x39e055(0xce)+_0x39e055(0xfb)+_slackState[_0x39e055(0x91)]+_0x1116a7(0xae)+_slackState[_0x1116a7(0xf9)]+')');try{const {registerDeliveryAdapter:_0x2c8c68}=await import('../service'+_0x1116a7(0xf2)+_0x39e055(0xcd)+'js');_0x2c8c68({'platform':'slack','sendText':async(_0xea02bd,_0x57a330)=>{const _0x1fee2f=_0x39e055;await this[_0x1fee2f(0xf8)](String(_0xea02bd),_0x57a330);}});}catch(_0x18cbc7){console[_0x39e055(0xcf)](_0x39e055(0x107)+_0x39e055(0xd9)+_0x1116a7(0xd6)+'ivery\x20adap'+_0x39e055(0x9a),_0x18cbc7);}}catch(_0x54b708){_slackState['status']=_0x1116a7(0x100),_slackState['error']=_0x54b708 instanceof Error?_0x54b708[_0x39e055(0x9b)]:String(_0x54b708),console[_0x39e055(0x100)](_0x1116a7(0xa4)+_0x1116a7(0xc3)+_0x39e055(0x10a),_slackState[_0x39e055(0x100)]);throw _0x54b708;}}async[_0x476279(0xb3)+_0x476279(0xeb)](_0x5854b6,_0x208eec,_0x1b9b7f){const _0x31a786=_0x476279,_0xa799c8=_0x476279;if(!this['handler'])return;if(_0x5854b6[_0x31a786(0x110)])return;if(_0x5854b6[_0x31a786(0xee)])return;if(!_0x5854b6[_0xa799c8(0xde)]&&!_0x5854b6['files'])return;const _0x2ff912=(_0x5854b6[_0x31a786(0xde)]||'')[_0xa799c8(0xb1)](),_0x585bd8=_0x5854b6['user']||'',_0x2ce475=_0x5854b6[_0x31a786(0xd5)]||'',_0x183804=_0x5854b6['ts']||'';if(!isSlackUserAllowed(_0x585bd8))return;const _0x2065b3=_0x5854b6[_0x31a786(0xea)+'pe']||'',_0x125445=_0x2065b3==='im',_0x5242e0=!_0x125445;if(_0x5242e0)return;let _0x3cb849=_0x585bd8;try{const _0x1b8c67=await _0x1b9b7f[_0x31a786(0xb5)]['info']({'user':_0x585bd8});_0x3cb849=_0x1b8c67[_0xa799c8(0xc0)]?.[_0x31a786(0x102)]||_0x1b8c67[_0x31a786(0xc0)]?.[_0x31a786(0xb6)]||_0x585bd8;}catch{}let _0x2b62fe=undefined;if(_0x5854b6[_0xa799c8(0x8c)]&&_0x5854b6[_0xa799c8(0x8c)][_0xa799c8(0xf1)]>-0x1799+-0x2*-0x1da+0x13e5){const _0x176777=_0x5854b6['files'][-0xa7*0xf+-0x2012+0x5*0x85f];_0x2b62fe=this[_0x31a786(0xe5)+_0x31a786(0x112)](_0x176777);}let _0x471f0c;if(_0x5854b6[_0xa799c8(0xe7)]&&_0x5854b6[_0x31a786(0xe7)]!==_0x5854b6['ts'])try{const _0x26cd63=await _0x1b9b7f['conversati'+_0x31a786(0xe8)]['replies']({'channel':_0x2ce475,'ts':_0x5854b6[_0xa799c8(0xe7)],'limit':0x1}),_0x4c29be=_0x26cd63['messages']?.[0x3f*-0x7f+-0x1*-0xc79+-0x4b2*-0x4];_0x4c29be?.['text']&&(_0x471f0c=_0x4c29be[_0xa799c8(0xde)]['length']>-0x5*-0x33+-0x6*-0x80+-0x20b*0x1?_0x4c29be['text'][_0x31a786(0x9e)](0x1*0x17a6+0xd0d*0x1+-0x24b3,0x1a7f*0x1+-0x17*-0xa3+-0x98*0x42)+'...':_0x4c29be[_0x31a786(0xde)]);}catch{}const _0x2c4507={'platform':_0x31a786(0x10f),'messageId':_0x183804,'chatId':_0x2ce475,'userId':_0x585bd8,'userName':_0x3cb849,'text':_0x2ff912,'isGroup':![],'isMention':![],'isReplyToBot':![],'replyToText':_0x471f0c,'media':_0x2b62fe};await this[_0x31a786(0xe9)](_0x2c4507);}async[_0x9c48b(0xe0)+'hCommand'](_0x27bc14){const _0x452975=_0x476279,_0x54eba2=_0x9c48b;if(!this['handler'])return;const _0x22998b=parseSlackSlashCommand(_0x27bc14['text']||''),_0x575321=_0x27bc14['channel_id']||'',_0x1be253=_0x27bc14[_0x452975(0xda)]||'',_0x4b4c63=_0x27bc14[_0x452975(0xa8)]||_0x1be253;if(!isSlackUserAllowed(_0x1be253))return;const _0x39d7e6={'platform':_0x452975(0x10f),'messageId':'cmd-'+Date[_0x54eba2(0xbe)]()+'-'+Math[_0x54eba2(0x10e)]()[_0x452975(0xca)](-0x796*-0x1+0x1*0x821+-0xf93)[_0x54eba2(0x9e)](0xe17+-0x1*-0x7af+0xc7*-0x1c,-0x2f0+-0xf8a+0x67*0x2e),'chatId':_0x575321,'userId':_0x1be253,'userName':_0x4b4c63,'text':_0x22998b,'isGroup':_0x27bc14['channel_na'+'me']&&_0x27bc14[_0x54eba2(0xaa)+'me']!=='directmess'+_0x452975(0xeb),'isMention':![],'isReplyToBot':![]};await this['handler'](_0x39d7e6);}async[_0x476279(0x8a)+_0x476279(0xa6)](_0x78a653,_0x3067ec,_0x5d3cdc){const _0x35b3b4=_0x476279,_0x245eb4=_0x476279;if(!this[_0x35b3b4(0xe9)])return;if(_0x78a653[_0x245eb4(0xee)])return;let _0x829dd4=(_0x78a653[_0x35b3b4(0xde)]||'')[_0x35b3b4(0xb1)]();const _0xeed0b0=_0x78a653[_0x245eb4(0xc0)]||'',_0x5d67d8=_0x78a653[_0x245eb4(0xd5)]||'',_0x4673ee=_0x78a653['ts']||'';if(!isSlackUserAllowed(_0xeed0b0))return;_0x829dd4=_0x829dd4[_0x35b3b4(0xef)](new RegExp('<@'+this['botUserId']+'>','g'),'')['trim']();if(!_0x829dd4)return;let _0x25e755=_0xeed0b0;try{const _0x33078c=await _0x5d3cdc['users'][_0x35b3b4(0xba)]({'user':_0xeed0b0});_0x25e755=_0x33078c[_0x35b3b4(0xc0)]?.[_0x35b3b4(0x102)]||_0x33078c[_0x245eb4(0xc0)]?.[_0x245eb4(0xb6)]||_0xeed0b0;}catch{}let _0x2a2d0f=undefined;_0x78a653[_0x35b3b4(0x8c)]&&_0x78a653[_0x35b3b4(0x8c)]['length']>0x2410+-0x1991*-0x1+-0x3da1&&(_0x2a2d0f=this['parseSlack'+_0x245eb4(0x112)](_0x78a653[_0x35b3b4(0x8c)][-0x9e1+0x4a9+-0x1*-0x538]));const _0x47233d={'platform':_0x35b3b4(0x10f),'messageId':_0x4673ee,'chatId':_0x5d67d8,'userId':_0xeed0b0,'userName':_0x25e755,'text':_0x829dd4,'isGroup':!![],'isMention':!![],'isReplyToBot':![],'media':_0x2a2d0f};await this[_0x245eb4(0xe9)](_0x47233d);}['parseSlack'+_0x476279(0x112)](_0x3aef49){const _0x38f278=_0x9c48b,_0x4c6f79=_0x9c48b;if(!_0x3aef49)return undefined;const _0x20cb78=_0x3aef49[_0x38f278(0x8e)]||'';if(_0x20cb78[_0x38f278(0xfa)]('image/'))return{'type':_0x38f278(0xa9),'url':_0x3aef49[_0x4c6f79(0xfd)+'e'],'mimeType':_0x20cb78,'fileName':_0x3aef49[_0x38f278(0xb6)]};if(_0x20cb78[_0x38f278(0xfa)](_0x38f278(0xa5)))return{'type':_0x38f278(0x98),'url':_0x3aef49[_0x38f278(0xfd)+'e'],'mimeType':_0x20cb78,'fileName':_0x3aef49[_0x38f278(0xb6)]};if(_0x20cb78[_0x4c6f79(0xfa)]('video/'))return{'type':_0x38f278(0xdf),'url':_0x3aef49[_0x4c6f79(0xfd)+'e'],'mimeType':_0x20cb78,'fileName':_0x3aef49[_0x38f278(0xb6)]};return{'type':_0x38f278(0x97),'url':_0x3aef49[_0x38f278(0xfd)+'e'],'mimeType':_0x20cb78,'fileName':_0x3aef49[_0x4c6f79(0xb6)]};}async[_0x476279(0xf8)](_0x5e5c79,_0x15b5ab,_0x4cf47d){const _0x2c5b66=_0x9c48b,_0x347edf=_0x476279;if(!this[_0x2c5b66(0xcb)])return;const _0x152154=_0x15b5ab[_0x2c5b66(0xf1)]>-0x1271+0x1c3*-0x9+0x2e4*0x11?_0x15b5ab[_0x347edf(0xe1)](/.{1,3800}/gs)||[_0x15b5ab]:[_0x15b5ab];let _0x41e2c3;for(const _0x20a2d5 of _0x152154){const _0x29557b=await this[_0x347edf(0xcb)][_0x347edf(0xd4)]['chat']['postMessag'+'e']({'token':this['botToken'],'channel':_0x5e5c79,'text':_0x20a2d5,..._0x4cf47d?.['replyTo']?{'thread_ts':_0x4cf47d['replyTo']}:{},'mrkdwn':!![]});if(_0x29557b?.['ts'])_0x41e2c3=_0x29557b['ts'];}return _0x41e2c3;}async[_0x9c48b(0x101)+'e'](_0x5efec8,_0x2759b9,_0x3bacbe){const _0x559998=_0x9c48b,_0x50fcb0=_0x9c48b;if(!this[_0x559998(0xcb)])return _0x2759b9;try{const _0x13d34b=_0x3bacbe['length']>0x1*-0x17d5+-0x1*0x6da+-0x23*-0x14d?_0x3bacbe[_0x50fcb0(0x9e)](0x118f+-0x203d+0xeae*0x1,-0x1d18+0x7ed+0x525*0x7)+'...':_0x3bacbe;await this['app'][_0x559998(0xd4)][_0x50fcb0(0x106)][_0x50fcb0(0xd7)]({'token':this[_0x559998(0xd1)],'channel':_0x5efec8,'ts':_0x2759b9,'text':_0x13d34b,'mrkdwn':!![]});}catch{}return _0x2759b9;}async[_0x476279(0x10c)](_0x408e71,_0x299fbb,_0x1adb4f){const _0x24fdc7=_0x476279,_0x4433fd=_0x9c48b;if(!this[_0x24fdc7(0xcb)])return;typeof _0x299fbb===_0x4433fd(0xb0)?await this[_0x24fdc7(0xcb)]['client'][_0x4433fd(0xa3)+_0x4433fd(0xc2)]({'token':this[_0x4433fd(0xd1)],'channel_id':_0x408e71,'file':_0x14338['createRead'+'Stream'](_0x299fbb),'filename':_0x24fdc7(0xdd),'initial_comment':_0x1adb4f}):await this[_0x4433fd(0xcb)][_0x4433fd(0xd4)][_0x24fdc7(0xa3)+'dV2']({'token':this[_0x24fdc7(0xd1)],'channel_id':_0x408e71,'file_uploads':[{'file':_0x299fbb,'filename':_0x24fdc7(0xdd)}],'initial_comment':_0x1adb4f});}async['sendDocume'+'nt'](_0x10f123,_0x166482,_0x293269,_0x3803fb){const _0x3f60f5=_0x476279,_0x11f85d=_0x9c48b;if(!this[_0x3f60f5(0xcb)])return;typeof _0x166482===_0x11f85d(0xb0)?await this['app'][_0x11f85d(0xd4)][_0x11f85d(0xa3)+'dV2']({'token':this[_0x11f85d(0xd1)],'channel_id':_0x10f123,'file':_0x14338['createRead'+_0x11f85d(0x92)](_0x166482),'filename':_0x293269,'initial_comment':_0x3803fb}):await this['app'][_0x3f60f5(0xd4)][_0x3f60f5(0xa3)+'dV2']({'token':this[_0x11f85d(0xd1)],'channel_id':_0x10f123,'file_uploads':[{'file':_0x166482,'filename':_0x293269}],'initial_comment':_0x3803fb});}async[_0x476279(0xec)](_0x34467d,_0x29f7f4,_0x31e743){const _0x3edb3f=_0x9c48b,_0xfbf3e3=_0x476279;if(!this[_0x3edb3f(0xcb)])return;try{const _0x2c33e2=_0x31e743[_0xfbf3e3(0xef)](/^:|:$/g,'');await this['app'][_0xfbf3e3(0xd4)][_0xfbf3e3(0xe6)][_0xfbf3e3(0x113)]({'token':this['botToken'],'channel':_0x34467d,'timestamp':_0x29f7f4,'name':_0x2c33e2});}catch{}}async[_0x476279(0xad)](_0x4ab0aa){const _0x1eee6f=_0x476279,_0x346c93=_0x476279;if(!this['app'])return;try{await this[_0x1eee6f(0xcb)][_0x1eee6f(0xd4)]['apiCall'](_0x1eee6f(0xe4)+'threads.se'+'tStatus',{'channel_id':_0x4ab0aa,'status':'is\x20thinkin'+'g…'});}catch{}}async[_0x476279(0xfe)+_0x476279(0xf6)](_0x4acbc2){const _0x30cb7b=_0x476279,_0xf2693b=_0x476279;if(!this[_0x30cb7b(0xcb)])return undefined;const _0x13e7db=this['channelNam'+_0x30cb7b(0xff)][_0xf2693b(0x99)](_0x4acbc2);if(_0x13e7db)return _0x13e7db;try{const _0x66de3b=await this[_0x30cb7b(0xcb)][_0xf2693b(0xd4)][_0xf2693b(0x8d)+_0x30cb7b(0xe8)][_0xf2693b(0xba)]({'token':this['botToken'],'channel':_0x4acbc2}),_0x2d6a5b=_0x66de3b?.['channel']?.[_0x30cb7b(0xb6)];if(_0x2d6a5b)return this[_0xf2693b(0xa2)+'eCache'][_0xf2693b(0x105)](_0x4acbc2,_0x2d6a5b),_0x2d6a5b;}catch{}return undefined;}async['stop'](){const _0x5983d7=_0x9c48b,_0x58ec60=_0x476279;if(this[_0x5983d7(0xcb)]){try{await this['app'][_0x5983d7(0xf7)]();}catch{}this[_0x5983d7(0xcb)]=null;}_slackState[_0x58ec60(0xbb)]=_0x58ec60(0xd8)+'ed';}[_0x9c48b(0xe3)](_0x1ff33e){const _0x101c5b=_0x476279;this[_0x101c5b(0xe9)]=_0x1ff33e;}}
|