alvin-bot 5.6.2 → 5.8.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/CHANGELOG.md +29 -0
- package/README.md +1 -1
- 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 -130
- 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 -443
- 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 -0
- 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 -1831
- 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 _0xe04bd4=_0x441f,_0x346927=_0x441f;function _0x441f(_0x29f56e,_0x18f45c){_0x29f56e=_0x29f56e-(-0x12*0x1b1+0x10e2*-0x1+0x1*0x30d7);const _0x13008f=_0x5954();let _0x298e52=_0x13008f[_0x29f56e];if(_0x441f['iIHoDf']===undefined){var _0x411a72=function(_0x5cb1b0){const _0x509e1a='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x552ed4='',_0x491a7d='',_0x406c55=_0x552ed4+_0x411a72;for(let _0x5e71c2=0xd4d+0x7f0+-0x1*0x153d,_0x3a4964,_0x5154e2,_0x5b0202=0x1e5*0x1+0xc37+0x3*-0x4b4;_0x5154e2=_0x5cb1b0['charAt'](_0x5b0202++);~_0x5154e2&&(_0x3a4964=_0x5e71c2%(-0xbb1+0x103e+-0x2b*0x1b)?_0x3a4964*(0x188+-0x17a1*0x1+-0x1659*-0x1)+_0x5154e2:_0x5154e2,_0x5e71c2++%(-0x66*0x45+0xecf+0x1*0xcb3))?_0x552ed4+=_0x406c55['charCodeAt'](_0x5b0202+(0x3e*0x9d+-0x6f3+-0x1f09))-(0x20b1+-0x13e+-0x1f69)!==0x129*0x1c+-0xe7a+-0x1202?String['fromCharCode'](-0x59*0x59+-0x339+-0x1*-0x2329&_0x3a4964>>(-(0x3*-0x48b+0x11ad+-0x40a)*_0x5e71c2&-0x1*0x1f1e+-0x1*0x1444+0x3368)):_0x5e71c2:0x1*0x1fe7+0x2178+-0x415f){_0x5154e2=_0x509e1a['indexOf'](_0x5154e2);}for(let _0x9c5e80=-0x1867+0x0+0x1*0x1867,_0x14a8c8=_0x552ed4['length'];_0x9c5e80<_0x14a8c8;_0x9c5e80++){_0x491a7d+='%'+('00'+_0x552ed4['charCodeAt'](_0x9c5e80)['toString'](0x255f+-0x350*-0x1+-0x289f))['slice'](-(-0x17ef+-0x212d+0x391e));}return decodeURIComponent(_0x491a7d);};_0x441f['XRlZpu']=_0x411a72,_0x441f['gaXFDb']={},_0x441f['iIHoDf']=!![];}const _0x426d9f=_0x13008f[0x221*0x1+-0x1*0x209+-0xc*0x2],_0x3f98b2=_0x29f56e+_0x426d9f,_0xf0f57b=_0x441f['gaXFDb'][_0x3f98b2];if(!_0xf0f57b){const _0xc85f55=function(_0x765ddd){this['iMBgoZ']=_0x765ddd,this['MYAosc']=[-0x118*-0x1c+0x1*0x11ad+-0x232*0x16,-0x2458+-0x2*-0x7f1+0x1476,0x38f*0x1+0x6e1*0x2+-0x1151],this['SPjTtk']=function(){return'newState';},this['RHKuvG']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['COleoQ']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0xc85f55['prototype']['rigijR']=function(){const _0x564fac=new RegExp(this['RHKuvG']+this['COleoQ']),_0x4a1cb9=_0x564fac['test'](this['SPjTtk']['toString']())?--this['MYAosc'][-0x53+0xbc5+-0x65*0x1d]:--this['MYAosc'][-0x1da9*0x1+0x1ea9+0x8*-0x20];return this['FIHujQ'](_0x4a1cb9);},_0xc85f55['prototype']['FIHujQ']=function(_0x44e615){if(!Boolean(~_0x44e615))return _0x44e615;return this['rEjmhh'](this['iMBgoZ']);},_0xc85f55['prototype']['rEjmhh']=function(_0x2dd1ee){for(let _0x49c464=-0x7*-0x4cb+0xf6*-0x9+0x18e7*-0x1,_0x3ca6f7=this['MYAosc']['length'];_0x49c464<_0x3ca6f7;_0x49c464++){this['MYAosc']['push'](Math['round'](Math['random']())),_0x3ca6f7=this['MYAosc']['length'];}return _0x2dd1ee(this['MYAosc'][-0x1*-0x12c9+0x17a0+-0xb*0x3db]);},new _0xc85f55(_0x441f)['rigijR'](),_0x298e52=_0x441f['XRlZpu'](_0x298e52),_0x441f['gaXFDb'][_0x3f98b2]=_0x298e52;}else _0x298e52=_0xf0f57b;return _0x298e52;}(function(_0x3dd8c9,_0x259c73){const _0x3506f0=_0x441f,_0x2fa07b=_0x441f,_0x51433e=_0x3dd8c9();while(!![]){try{const _0x162cc4=-parseInt(_0x3506f0(0x192))/(0x3*0x31+0x1795*-0x1+0x1703)*(parseInt(_0x2fa07b(0x1dd))/(-0xfa*0x1+-0x1e04+0x8*0x3e0))+-parseInt(_0x2fa07b(0x1ba))/(-0x1f0a+0x2*0x89f+0x65*0x23)*(-parseInt(_0x3506f0(0x1df))/(-0x1fa5*0x1+-0x3a6*-0x2+0x185d))+parseInt(_0x3506f0(0x1a6))/(0x1307*0x1+-0x10d9*0x2+-0x178*-0xa)*(parseInt(_0x3506f0(0x213))/(0x4*-0x226+-0x1*0x2d7+0x7*0x1a3))+parseInt(_0x2fa07b(0x186))/(0x255c+0x7*-0x287+-0x13a4)*(-parseInt(_0x3506f0(0x1bb))/(-0x1*0x15d7+-0x1*0x673+0x1c52))+-parseInt(_0x2fa07b(0x198))/(-0x64c+-0x9e5+-0x81d*-0x2)+-parseInt(_0x3506f0(0x19d))/(0x5*0x100+-0x1419+0xf23)*(parseInt(_0x2fa07b(0x199))/(-0xe63+0x2e*0xbb+-0x132c))+parseInt(_0x3506f0(0x1a9))/(0x2*-0x2d9+0x1567*0x1+0x1*-0xfa9);if(_0x162cc4===_0x259c73)break;else _0x51433e['push'](_0x51433e['shift']());}catch(_0x1bd8e7){_0x51433e['push'](_0x51433e['shift']());}}}(_0x5954,0xa13*-0x56+0x1*-0x203df+0x8c889*0x1));const _0x4baae6=(function(){let _0x407aef=!![];return function(_0x393b50,_0x4cb564){const _0x5bee9c=_0x407aef?function(){const _0x401bb7=_0x441f;if(_0x4cb564){const _0x595d81=_0x4cb564[_0x401bb7(0x1d1)](_0x393b50,arguments);return _0x4cb564=null,_0x595d81;}}:function(){};return _0x407aef=![],_0x5bee9c;};}()),_0x17ef49=_0x4baae6(this,function(){const _0x16b836=_0x441f,_0x2a9d55=_0x441f;return _0x17ef49['toString']()[_0x16b836(0x190)](_0x2a9d55(0x1e6)+'+$')['toString']()['constructo'+'r'](_0x17ef49)['search']('(((.+)+)+)'+'+$');});_0x17ef49();import _0x3407f6 from'fs';import{parseSlackSlashCommand}from'./slack-slash-parser.js';import{config}from'../config.js';function isSlackUserAllowed(_0x25ccf6){const _0xcfc4f8=_0x441f,_0x432da2=_0x441f;if(config[_0xcfc4f8(0x1cd)+_0xcfc4f8(0x1fa)][_0x432da2(0x18b)]===0xd1f*-0x1+-0x1*-0x1e5+0x1*0xb3a)return _0x25ccf6&&!discoveredCallers[_0xcfc4f8(0x211)](_0x25ccf6)&&(discoveredCallers[_0xcfc4f8(0x1d4)](_0x25ccf6),console[_0x432da2(0x1ad)](_0x432da2(0x1d2)+_0xcfc4f8(0x19b)+_0xcfc4f8(0x1bc)+'r='+_0x25ccf6+('\x20—\x20to\x20lock'+_0xcfc4f8(0x189)+'o\x20specific'+_0xcfc4f8(0x18a))+(_0xcfc4f8(0x1b8)+_0xcfc4f8(0x202)+'LLOWED_USE'+'RS='+_0x25ccf6)+(discoveredCallers['size']>-0xbb1+0x103e+-0x61*0xc?'\x20(or\x20comma'+_0xcfc4f8(0x1cf)+_0xcfc4f8(0x1cc):''))),!![];return config[_0x432da2(0x1cd)+_0x432da2(0x1fa)][_0x432da2(0x203)](_0x25ccf6);}const discoveredCallers=new Set();let _slackState={'status':_0xe04bd4(0x1f2)+'ed','botName':null,'botId':null,'teamName':null,'connectedAt':null,'error':null};export function getSlackState(){return{..._slackState};}export class SlackAdapter{[_0x346927(0x1b4)]='slack';['handler']=null;[_0x346927(0x194)]=null;['botUserId']='';[_0x346927(0x1a1)];[_0xe04bd4(0x204)];['channelNam'+_0x346927(0x196)]=new Map();constructor(_0x2f4b65,_0x3e0e30){const _0x1a5027=_0x346927;this['botToken']=_0x2f4b65,this[_0x1a5027(0x204)]=_0x3e0e30;}async[_0xe04bd4(0x1b7)](){const _0x38833d=_0x346927,_0x5c55f7=_0xe04bd4;_slackState={'status':_0x38833d(0x1ca),'botName':null,'botId':null,'teamName':null,'connectedAt':null,'error':null};let _0x205c68;try{_0x205c68=await import('@slack/bol'+'t');}catch{const _0x5e76ef=_0x38833d(0x1ec)+_0x38833d(0x183)+'alled.\x20Run'+_0x38833d(0x1ed)+'all\x20@slack'+_0x38833d(0x19f);_slackState={..._slackState,'status':_0x38833d(0x20d),'error':_0x5e76ef},console[_0x5c55f7(0x20d)](_0x5c55f7(0x1b6)+_0x5e76ef);throw new Error(_0x5e76ef);}const {App:_0xae5b5d}=_0x205c68;try{this[_0x5c55f7(0x194)]=new _0xae5b5d({'token':this['botToken'],'appToken':this[_0x5c55f7(0x204)],'socketMode':!![],'logLevel':'ERROR'});const _0x11a7e3=await this['app'][_0x38833d(0x1b3)][_0x5c55f7(0x1d6)][_0x5c55f7(0x1e7)]({'token':this[_0x5c55f7(0x1a1)]});this[_0x38833d(0x18f)]=_0x11a7e3['user_id']||'',_slackState['botName']=_0x11a7e3[_0x5c55f7(0x1c9)]||null,_slackState[_0x38833d(0x1d0)]=_0x11a7e3[_0x38833d(0x18c)]||null,_slackState[_0x38833d(0x19e)]=_0x11a7e3['team']||null,this['app']['message'](async({message:_0xb7c974,say:_0x551bf0,client:_0x32de66})=>{const _0x499336=_0x5c55f7;await this['handleMess'+_0x499336(0x1f8)](_0xb7c974,_0x551bf0,_0x32de66);}),this[_0x38833d(0x194)][_0x5c55f7(0x1b5)]('app_mentio'+'n',async({event:_0x55f176,say:_0x29ee78,client:_0x3827e4})=>{const _0x484809=_0x5c55f7;await this[_0x484809(0x1b0)+'ion'](_0x55f176,_0x29ee78,_0x3827e4);});typeof this[_0x5c55f7(0x194)][_0x5c55f7(0x1ef)]===_0x5c55f7(0x1aa)&&this['app'][_0x38833d(0x1ef)](_0x38833d(0x1a0),async({command:_0x433211,ack:_0x58a366})=>{const _0x54dfc6=_0x38833d,_0xe30663=_0x5c55f7;await _0x58a366();try{await this[_0x54dfc6(0x193)+_0xe30663(0x1e4)](_0x433211);}catch(_0x252247){console['error'](_0x54dfc6(0x1dc)+_0x54dfc6(0x1e5)+_0x54dfc6(0x1e1),_0x252247);}});await this[_0x5c55f7(0x194)][_0x38833d(0x1b7)](),_slackState['status']=_0x5c55f7(0x20f),_slackState[_0x5c55f7(0x1e0)+'t']=Date[_0x5c55f7(0x1ce)](),console[_0x38833d(0x1d5)](_0x5c55f7(0x1f3)+_0x5c55f7(0x1a4)+_slackState[_0x38833d(0x1bf)]+_0x5c55f7(0x1f1)+_slackState[_0x5c55f7(0x19e)]+')');try{const {registerDeliveryAdapter:_0x4e60b0}=await import(_0x5c55f7(0x1c0)+_0x38833d(0x188)+_0x5c55f7(0x197)+'js');_0x4e60b0({'platform':_0x5c55f7(0x1e9),'sendText':async(_0x22f722,_0x4e2cba)=>{const _0x1cfe77=_0x5c55f7;await this[_0x1cfe77(0x1a2)](String(_0x22f722),_0x4e2cba);}});}catch(_0x50d29f){console[_0x5c55f7(0x1ad)]('[slack]\x20fa'+_0x5c55f7(0x1d8)+'gister\x20del'+'ivery\x20adap'+_0x5c55f7(0x214),_0x50d29f);}}catch(_0x515ac2){_slackState[_0x38833d(0x1de)]=_0x38833d(0x20d),_slackState[_0x38833d(0x20d)]=_0x515ac2 instanceof Error?_0x515ac2[_0x5c55f7(0x1b9)]:String(_0x515ac2),console[_0x38833d(0x20d)](_0x5c55f7(0x20c)+_0x5c55f7(0x18d)+_0x5c55f7(0x195),_slackState['error']);throw _0x515ac2;}}async[_0xe04bd4(0x1f0)+_0xe04bd4(0x1f8)](_0x5cb528,_0x469da7,_0x4c85e7){const _0x5e52e2=_0x346927,_0x48f61e=_0x346927;if(!this['handler'])return;if(_0x5cb528[_0x5e52e2(0x1ea)])return;if(_0x5cb528[_0x48f61e(0x1cb)])return;if(!_0x5cb528[_0x48f61e(0x1c3)]&&!_0x5cb528[_0x5e52e2(0x1be)])return;const _0x4b7a49=(_0x5cb528[_0x5e52e2(0x1c3)]||'')[_0x5e52e2(0x1e2)](),_0x2e0573=_0x5cb528['user']||'',_0x1ea6ed=_0x5cb528[_0x5e52e2(0x1ff)]||'',_0x52816e=_0x5cb528['ts']||'';if(!isSlackUserAllowed(_0x2e0573))return;const _0x266415=_0x5cb528[_0x48f61e(0x20e)+'pe']||'',_0x29f56e=_0x266415==='im',_0x18f45c=!_0x29f56e;if(_0x18f45c)return;let _0x13008f=_0x2e0573;try{const _0x3f98b2=await _0x4c85e7[_0x48f61e(0x207)][_0x48f61e(0x1e8)]({'user':_0x2e0573});_0x13008f=_0x3f98b2[_0x48f61e(0x1c9)]?.[_0x48f61e(0x1d3)]||_0x3f98b2[_0x5e52e2(0x1c9)]?.[_0x5e52e2(0x185)]||_0x2e0573;}catch{}let _0x298e52=undefined;if(_0x5cb528[_0x48f61e(0x1be)]&&_0x5cb528[_0x5e52e2(0x1be)][_0x5e52e2(0x18b)]>0x188+-0x17a1*0x1+-0x1619*-0x1){const _0xf0f57b=_0x5cb528[_0x5e52e2(0x1be)][-0x66*0x45+0xecf+0x11*0xbf];_0x298e52=this['parseSlack'+_0x5e52e2(0x1fc)](_0xf0f57b);}let _0x411a72;if(_0x5cb528[_0x48f61e(0x1f9)]&&_0x5cb528['thread_ts']!==_0x5cb528['ts'])try{const _0x5cb1b0=await _0x4c85e7[_0x5e52e2(0x187)+_0x48f61e(0x1c6)][_0x5e52e2(0x210)]({'channel':_0x1ea6ed,'ts':_0x5cb528[_0x5e52e2(0x1f9)],'limit':0x1}),_0x509e1a=_0x5cb1b0[_0x48f61e(0x1d9)]?.[0x3e*0x9d+-0x6f3+-0x1f13];_0x509e1a?.[_0x5e52e2(0x1c3)]&&(_0x411a72=_0x509e1a['text']['length']>0x20b1+-0x13e+-0x1d7f?_0x509e1a['text'][_0x5e52e2(0x191)](0x129*0x1c+-0xe7a+-0x1202,-0x59*0x59+-0x339+-0x17*-0x192)+_0x5e52e2(0x1af):_0x509e1a[_0x5e52e2(0x1c3)]);}catch{}const _0x426d9f={'platform':_0x5e52e2(0x1e9),'messageId':_0x52816e,'chatId':_0x1ea6ed,'userId':_0x2e0573,'userName':_0x13008f,'text':_0x4b7a49,'isGroup':![],'isMention':![],'isReplyToBot':![],'replyToText':_0x411a72,'media':_0x298e52};await this[_0x5e52e2(0x1c5)](_0x426d9f);}async[_0xe04bd4(0x193)+'hCommand'](_0x552ed4){const _0x1d9bc8=_0x346927,_0x25fe81=_0x346927;if(!this[_0x1d9bc8(0x1c5)])return;const _0x491a7d=parseSlackSlashCommand(_0x552ed4[_0x1d9bc8(0x1c3)]||''),_0x406c55=_0x552ed4[_0x25fe81(0x206)]||'',_0x5e71c2=_0x552ed4[_0x1d9bc8(0x18c)]||'',_0x3a4964=_0x552ed4[_0x1d9bc8(0x19a)]||_0x5e71c2;if(!isSlackUserAllowed(_0x5e71c2))return;const _0x5154e2={'platform':'slack','messageId':'cmd-'+Date[_0x25fe81(0x1ce)]()+'-'+Math[_0x1d9bc8(0x200)]()[_0x25fe81(0x184)](0x3*-0x48b+0x11ad+-0x3e8)[_0x1d9bc8(0x191)](-0x1*0x1f1e+-0x1*0x1444+0x3364,0x1*0x1fe7+0x2178+-0x4157),'chatId':_0x406c55,'userId':_0x5e71c2,'userName':_0x3a4964,'text':_0x491a7d,'isGroup':_0x552ed4[_0x25fe81(0x1a8)+'me']&&_0x552ed4['channel_na'+'me']!==_0x25fe81(0x1ee)+_0x1d9bc8(0x1f8),'isMention':![],'isReplyToBot':![]};await this[_0x25fe81(0x1c5)](_0x5154e2);}async['handleMent'+_0x346927(0x208)](_0x5b0202,_0x9c5e80,_0x14a8c8){const _0x56de8e=_0xe04bd4,_0x132d3b=_0x346927;if(!this[_0x56de8e(0x1c5)])return;if(_0x5b0202[_0x56de8e(0x1cb)])return;let _0xc85f55=(_0x5b0202['text']||'')[_0x56de8e(0x1e2)]();const _0x765ddd=_0x5b0202[_0x132d3b(0x1c9)]||'',_0x564fac=_0x5b0202['channel']||'',_0x4a1cb9=_0x5b0202['ts']||'';if(!isSlackUserAllowed(_0x765ddd))return;_0xc85f55=_0xc85f55['replace'](new RegExp('<@'+this[_0x56de8e(0x18f)]+'>','g'),'')[_0x56de8e(0x1e2)]();if(!_0xc85f55)return;let _0x44e615=_0x765ddd;try{const _0x3ca6f7=await _0x14a8c8[_0x56de8e(0x207)][_0x56de8e(0x1e8)]({'user':_0x765ddd});_0x44e615=_0x3ca6f7['user']?.[_0x56de8e(0x1d3)]||_0x3ca6f7[_0x132d3b(0x1c9)]?.[_0x132d3b(0x185)]||_0x765ddd;}catch{}let _0x2dd1ee=undefined;_0x5b0202[_0x56de8e(0x1be)]&&_0x5b0202[_0x56de8e(0x1be)][_0x56de8e(0x18b)]>-0x1867+0x0+0x1*0x1867&&(_0x2dd1ee=this[_0x132d3b(0x1da)+_0x132d3b(0x1fc)](_0x5b0202['files'][0x255f+-0x350*-0x1+-0x28af]));const _0x49c464={'platform':_0x132d3b(0x1e9),'messageId':_0x4a1cb9,'chatId':_0x564fac,'userId':_0x765ddd,'userName':_0x44e615,'text':_0xc85f55,'isGroup':!![],'isMention':!![],'isReplyToBot':![],'media':_0x2dd1ee};await this[_0x56de8e(0x1c5)](_0x49c464);}['parseSlack'+_0xe04bd4(0x1fc)](_0x244fcb){const _0x394ed5=_0xe04bd4,_0x4a28a2=_0x346927;if(!_0x244fcb)return undefined;const _0x3cfdcd=_0x244fcb[_0x394ed5(0x1a3)]||'';if(_0x3cfdcd['startsWith'](_0x4a28a2(0x20b)))return{'type':_0x394ed5(0x1fd),'url':_0x244fcb[_0x4a28a2(0x1c7)+'e'],'mimeType':_0x3cfdcd,'fileName':_0x244fcb[_0x4a28a2(0x185)]};if(_0x3cfdcd[_0x4a28a2(0x1c1)](_0x4a28a2(0x1ac)))return{'type':_0x4a28a2(0x1ae),'url':_0x244fcb['url_privat'+'e'],'mimeType':_0x3cfdcd,'fileName':_0x244fcb[_0x394ed5(0x185)]};if(_0x3cfdcd[_0x4a28a2(0x1c1)](_0x4a28a2(0x1b1)))return{'type':_0x394ed5(0x1f4),'url':_0x244fcb[_0x394ed5(0x1c7)+'e'],'mimeType':_0x3cfdcd,'fileName':_0x244fcb[_0x4a28a2(0x185)]};return{'type':_0x394ed5(0x1c4),'url':_0x244fcb[_0x394ed5(0x1c7)+'e'],'mimeType':_0x3cfdcd,'fileName':_0x244fcb['name']};}async[_0x346927(0x1a2)](_0x16a1fe,_0x4dea50,_0x22801f){const _0x5cd70c=_0xe04bd4,_0x4070be=_0xe04bd4;if(!this[_0x5cd70c(0x194)])return;const _0x27d9b2=_0x4dea50[_0x4070be(0x18b)]>-0x17ef+-0x212d+0x47f4?_0x4dea50[_0x5cd70c(0x1a5)](/.{1,3800}/gs)||[_0x4dea50]:[_0x4dea50];let _0x106046;for(const _0x4d98b7 of _0x27d9b2){const _0xf18f1e=await this[_0x4070be(0x194)][_0x5cd70c(0x1b3)][_0x4070be(0x18e)][_0x5cd70c(0x1f5)+'e']({'token':this[_0x5cd70c(0x1a1)],'channel':_0x16a1fe,'text':_0x4d98b7,..._0x22801f?.[_0x4070be(0x1a7)]?{'thread_ts':_0x22801f['replyTo']}:{},'mrkdwn':!![]});if(_0xf18f1e?.['ts'])_0x106046=_0xf18f1e['ts'];}return _0x106046;}async['editMessag'+'e'](_0x15e9bb,_0x1b9434,_0x8071f4){const _0x4d67b0=_0xe04bd4,_0x3b81d2=_0xe04bd4;if(!this['app'])return _0x1b9434;try{const _0x1d4b3c=_0x8071f4['length']>0x221*0x1+-0x1*0x209+-0x3b0*-0x4?_0x8071f4[_0x4d67b0(0x191)](-0x118*-0x1c+0x1*0x11ad+-0x9a9*0x5,-0x2458+-0x2*-0x7f1+0x234e)+_0x3b81d2(0x1af):_0x8071f4;await this['app']['client'][_0x3b81d2(0x18e)][_0x3b81d2(0x20a)]({'token':this[_0x3b81d2(0x1a1)],'channel':_0x15e9bb,'ts':_0x1b9434,'text':_0x1d4b3c,'mrkdwn':!![]});}catch{}return _0x1b9434;}async[_0x346927(0x1eb)](_0x202705,_0x351239,_0x52693b){const _0x2bff1e=_0xe04bd4,_0x387e3e=_0x346927;if(!this[_0x2bff1e(0x194)])return;typeof _0x351239===_0x387e3e(0x1b2)?await this[_0x2bff1e(0x194)][_0x2bff1e(0x1b3)][_0x387e3e(0x1db)+_0x387e3e(0x1d7)]({'token':this[_0x2bff1e(0x1a1)],'channel_id':_0x202705,'file':_0x3407f6[_0x2bff1e(0x1ab)+_0x2bff1e(0x1fe)](_0x351239),'filename':_0x387e3e(0x205),'initial_comment':_0x52693b}):await this[_0x2bff1e(0x194)][_0x387e3e(0x1b3)][_0x2bff1e(0x1db)+_0x387e3e(0x1d7)]({'token':this['botToken'],'channel_id':_0x202705,'file_uploads':[{'file':_0x351239,'filename':_0x387e3e(0x205)}],'initial_comment':_0x52693b});}async[_0x346927(0x1c8)+'nt'](_0x139534,_0x6bbe13,_0xf5c176,_0x5ad9f5){const _0x564f40=_0xe04bd4,_0x3796af=_0x346927;if(!this[_0x564f40(0x194)])return;typeof _0x6bbe13===_0x3796af(0x1b2)?await this[_0x564f40(0x194)][_0x3796af(0x1b3)][_0x3796af(0x1db)+_0x564f40(0x1d7)]({'token':this[_0x564f40(0x1a1)],'channel_id':_0x139534,'file':_0x3407f6['createRead'+_0x564f40(0x1fe)](_0x6bbe13),'filename':_0xf5c176,'initial_comment':_0x5ad9f5}):await this['app']['client'][_0x3796af(0x1db)+_0x3796af(0x1d7)]({'token':this[_0x564f40(0x1a1)],'channel_id':_0x139534,'file_uploads':[{'file':_0x6bbe13,'filename':_0xf5c176}],'initial_comment':_0x5ad9f5});}async[_0x346927(0x1f6)](_0x5f4ea6,_0x4ed1a3,_0x3e3b92){const _0x5ca469=_0x346927,_0x3624ca=_0xe04bd4;if(!this[_0x5ca469(0x194)])return;try{const _0x549aab=_0x3e3b92['replace'](/^:|:$/g,'');await this[_0x3624ca(0x194)][_0x5ca469(0x1b3)]['reactions'][_0x3624ca(0x1d4)]({'token':this['botToken'],'channel':_0x5f4ea6,'timestamp':_0x4ed1a3,'name':_0x549aab});}catch{}}async[_0xe04bd4(0x212)](_0x5ca8e5){const _0xbce62a=_0xe04bd4,_0x581d72=_0x346927;if(!this[_0xbce62a(0x194)])return;try{await this[_0xbce62a(0x194)]['client'][_0x581d72(0x201)]('assistant.'+'threads.se'+_0x581d72(0x1f7),{'channel_id':_0x5ca8e5,'status':'is\x20thinkin'+'g…'});}catch{}}async[_0x346927(0x1fb)+'Name'](_0x2ceebf){const _0x2ecabd=_0x346927,_0x326c77=_0xe04bd4;if(!this[_0x2ecabd(0x194)])return undefined;const _0x269ccc=this[_0x326c77(0x1e3)+'eCache'][_0x326c77(0x209)](_0x2ceebf);if(_0x269ccc)return _0x269ccc;try{const _0x32b63c=await this['app'][_0x2ecabd(0x1b3)][_0x326c77(0x187)+_0x2ecabd(0x1c6)][_0x326c77(0x1e8)]({'token':this['botToken'],'channel':_0x2ceebf}),_0x3a671b=_0x32b63c?.[_0x2ecabd(0x1ff)]?.[_0x326c77(0x185)];if(_0x3a671b)return this[_0x326c77(0x1e3)+'eCache'][_0x326c77(0x1c2)](_0x2ceebf,_0x3a671b),_0x3a671b;}catch{}return undefined;}async[_0x346927(0x19c)](){const _0x21de3e=_0x346927,_0x19deb9=_0x346927;if(this[_0x21de3e(0x194)]){try{await this[_0x21de3e(0x194)][_0x21de3e(0x19c)]();}catch{}this[_0x19deb9(0x194)]=null;}_slackState[_0x19deb9(0x1de)]=_0x21de3e(0x1f2)+'ed';}[_0x346927(0x1bd)](_0x1f5bda){const _0x5ba95a=_0x346927;this[_0x5ba95a(0x1c5)]=_0x1f5bda;}}function _0x5954(){const _0x4c6a7b=['8j+sRcbtBgfJAYbJBW','DMLKzw8','Cg9ZDe1LC3nHzW','CMvHy3q','Dfn0yxr1CW','ywDL','DgHYzwfKx3rZ','zwrvC2vYCW','z2v0q2HHBM5LBa','rMLSzq','CgHVDg8','u3rYzwfT','y2HHBM5LBa','CMfUzg9T','yxbPq2fSBa','DJOGu0Xbq0TFqq','Aw5JBhvKzxm','yxbWvg9Rzw4','Aw1Hz2uUCg5N','y2HHBM5LBf9Pza','DxnLCNm','Aw9U','z2v0','DxbKyxrL','Aw1Hz2uV','4P2mifnSywnRigfK','zxjYB3i','y2HHBM5LBf90Eq','y29UBMvJDgvK','CMvWBgLLCW','AgfZ','C2v0vhLWAw5N','nMfuAffWqW','DgvYoG','DcbUB3qGAw5ZDa','Dg9tDhjPBMC','BMfTzq','mtG2ota3y29JBKPO','y29UDMvYC2f0Aq','CY9KzwXPDMvYEq','ihrOzsbIB3qGDa','ihvZzxjZlca','BgvUz3rO','DxnLCL9Pza','yxb0zxiGzMfPBa','y2HHDa','yM90vxnLCKLK','C2vHCMnO','C2XPy2u','ndiYntG4vgLzALrP','AgfUzgXLu2XHCW','yxbW','zwq6','zunHy2HL','lxjLz2LZDhj5lG','mty0mZGXneXJCM1TzW','mtfrtM9NyNK','DxnLCL9Uyw1L','BgXLCIbKAxnJBW','C3rVCa','mtq4otqYmeLzB0zAuW','DgvHBu5HBwu','l2jVBhq','l2fSDMLU','yM90vg9Rzw4','C2vUzfrLEhq','BwLTzxr5Cgu','BM5Ly3rLzcaO','Bwf0y2G','ndC3ody1BvvtB29Q','CMvWBhLuBW','y2HHBM5LBf9Uyq','nZi5ntC2mgT2B1jgvW','zNvUy3rPB24','y3jLyxrLuMvHza','yxvKAw8V','D2fYBG','DM9Py2u','lI4U','AgfUzgXLtwvUDa','DMLKzw8V','C3rYAw5N','y2XPzw50','CgXHDgzVCM0','zxzLBNq','4P2mifnSywnRoIa','C3rHCNq','ywrKihrVic5LBG','BwvZC2fNzq','nJLiDLnLzM0','ohLRzvDArq','DMvYzwq6ihvZzq','B25nzxnZywDL','zMLSzxm','yM90tMfTzq','lI4VC2vYDMLJzq','C3rHCNrZv2L0Aa','C2v0','Dgv4Da','zg9JDw1LBNq','AgfUzgXLCG','B25Z','DxjSx3bYAxzHDa','C2vUzerVy3vTzq','DxnLCG','y29UBMvJDgLUzW','yM90x2LK','BxvSDgLWBguP','C2XHy2TbBgXVDW','BM93','lxnLCgfYyxrLia','yM90swq','yxbWBhK','w3nSywnRxsbJyq','CMvHBf9Uyw1L','ywrK','Bg9N','yxv0Aa','zfyY','AwXLzcb0BYbYzq','BwvZC2fNzxm','CgfYC2vtBgfJAW','zMLSzxnvCgXVyq','w3nSywnRxsaVyq','mNDMr2D2sW','C3rHDhvZ','ntiWmtzwDvfRDMS','y29UBMvJDgvKqq','BMqGzMfPBgvKoG','DhjPBq','y2HHBM5LBe5HBq','AenVBw1HBMq','BhzPBIbJB21Tyq','kcGOlISPkYKRkq','DgvZDa','Aw5MBW','C2XHy2S','C3vIDhLWzq','C2vUzfbOB3rV','qhnSywnRl2jVBa','oIbUCg0GAw5ZDa','zgLYzwn0BwvZCW','y29TBwfUza','AgfUzgXLtwvZCW','ieaG','zgLZy29UBMvJDa'];_0x5954=function(){return _0x4c6a7b;};return _0x5954();}
|