@elizaos/plugin-discord 2.0.0-alpha.1 → 2.0.0-alpha.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/accounts.d.ts +164 -0
- package/dist/accounts.d.ts.map +1 -0
- package/dist/actions/chatWithAttachments.d.ts +4 -0
- package/dist/actions/chatWithAttachments.d.ts.map +1 -0
- package/dist/actions/createPoll.d.ts +4 -0
- package/dist/actions/createPoll.d.ts.map +1 -0
- package/dist/actions/deleteMessage.d.ts +4 -0
- package/dist/actions/deleteMessage.d.ts.map +1 -0
- package/dist/actions/downloadMedia.d.ts +4 -0
- package/dist/actions/downloadMedia.d.ts.map +1 -0
- package/dist/actions/editMessage.d.ts +4 -0
- package/dist/actions/editMessage.d.ts.map +1 -0
- package/dist/actions/getUserInfo.d.ts +4 -0
- package/dist/actions/getUserInfo.d.ts.map +1 -0
- package/dist/actions/joinChannel.d.ts +4 -0
- package/dist/actions/joinChannel.d.ts.map +1 -0
- package/dist/actions/leaveChannel.d.ts +4 -0
- package/dist/actions/leaveChannel.d.ts.map +1 -0
- package/dist/actions/listChannels.d.ts +4 -0
- package/dist/actions/listChannels.d.ts.map +1 -0
- package/dist/actions/pinMessage.d.ts +4 -0
- package/dist/actions/pinMessage.d.ts.map +1 -0
- package/dist/actions/reactToMessage.d.ts +4 -0
- package/dist/actions/reactToMessage.d.ts.map +1 -0
- package/dist/actions/readChannel.d.ts +4 -0
- package/dist/actions/readChannel.d.ts.map +1 -0
- package/dist/actions/searchMessages.d.ts +4 -0
- package/dist/actions/searchMessages.d.ts.map +1 -0
- package/dist/actions/sendDM.d.ts +4 -0
- package/dist/actions/sendDM.d.ts.map +1 -0
- package/dist/actions/sendMessage.d.ts +4 -0
- package/dist/actions/sendMessage.d.ts.map +1 -0
- package/dist/actions/serverInfo.d.ts +4 -0
- package/dist/actions/serverInfo.d.ts.map +1 -0
- package/dist/actions/summarizeConversation.d.ts +4 -0
- package/dist/actions/summarizeConversation.d.ts.map +1 -0
- package/dist/actions/transcribeMedia.d.ts +4 -0
- package/dist/actions/transcribeMedia.d.ts.map +1 -0
- package/dist/actions/unpinMessage.d.ts +4 -0
- package/dist/actions/unpinMessage.d.ts.map +1 -0
- package/dist/allowlist.d.ts +198 -0
- package/dist/allowlist.d.ts.map +1 -0
- package/dist/attachments.d.ts +92 -0
- package/dist/attachments.d.ts.map +1 -0
- package/dist/banner.d.ts +39 -0
- package/dist/banner.d.ts.map +1 -0
- package/dist/compat.d.ts +56 -0
- package/dist/compat.d.ts.map +1 -0
- package/dist/config.d.ts +156 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/constants.d.ts +2 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/environment.d.ts +22 -0
- package/dist/environment.d.ts.map +1 -0
- package/dist/generated/prompts/typescript/prompts.d.ts +44 -0
- package/dist/generated/prompts/typescript/prompts.d.ts.map +1 -0
- package/dist/generated/specs/spec-helpers.d.ts +49 -0
- package/dist/generated/specs/spec-helpers.d.ts.map +1 -0
- package/dist/generated/specs/specs.d.ts +87 -0
- package/dist/generated/specs/specs.d.ts.map +1 -0
- package/dist/identity.d.ts +4 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/index.browser.d.ts +34 -0
- package/dist/index.browser.d.ts.map +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14175 -0
- package/dist/index.js.map +133 -0
- package/dist/messages.d.ts +55 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messaging.d.ts +129 -0
- package/dist/messaging.d.ts.map +1 -0
- package/dist/native-commands.d.ts +142 -0
- package/dist/native-commands.d.ts.map +1 -0
- package/dist/permissionEvents.d.ts +42 -0
- package/dist/permissionEvents.d.ts.map +1 -0
- package/dist/permissions.d.ts +36 -0
- package/dist/permissions.d.ts.map +1 -0
- package/dist/providers/channelState.d.ts +14 -0
- package/dist/providers/channelState.d.ts.map +1 -0
- package/dist/providers/guildInfo.d.ts +15 -0
- package/dist/providers/guildInfo.d.ts.map +1 -0
- package/dist/providers/voiceState.d.ts +12 -0
- package/dist/providers/voiceState.d.ts.map +1 -0
- package/dist/service.d.ts +403 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/test-setup.d.ts +1 -0
- package/dist/test-setup.d.ts.map +1 -0
- package/dist/tests.d.ts +123 -0
- package/dist/tests.d.ts.map +1 -0
- package/dist/types.d.ts +315 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils.d.ts +44 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.d.ts.map +1 -0
- package/dist/voice.d.ts +230 -0
- package/dist/voice.d.ts.map +1 -0
- package/package.json +134 -124
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/gateway/common.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/gateway/v10.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/globals.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/common.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/application.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/auditLog.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/autoModeration.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/channel.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/emoji.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/gateway.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/guild.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/guildScheduledEvent.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/attachment.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/base.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/boolean.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/channel.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/integer.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/mentionable.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/number.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/role.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/shared.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/string.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/subcommand.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/subcommandGroup.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/user.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/chatInput.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/contextMenu.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/permissions.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/entryPoint.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/internals.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/applicationCommands.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/autocomplete.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/base.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/messageComponents.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/modalSubmit.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/ping.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/_interactions/responses.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/interactions.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/invite.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/monetization.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/oauth2.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/permissions.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/poll.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/soundboard.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/stageInstance.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/sticker.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/teams.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/template.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/user.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/voice.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/webhook.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/payloads/v10/index.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/utils/internals.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/rest/common.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/rest/v10/application.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/rest/v10/auditLog.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/rest/v10/autoModeration.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/rest/v10/channel.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/rest/v10/emoji.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/rest/v10/gateway.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/rest/v10/guild.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/rest/v10/guildScheduledEvent.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/rest/v10/interactions.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/rest/v10/invite.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/rest/v10/monetization.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/rest/v10/oauth2.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/rest/v10/poll.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/rest/v10/soundboard.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/rest/v10/stageInstance.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/rest/v10/sticker.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/rest/v10/template.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/rest/v10/user.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/rest/v10/voice.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/rest/v10/webhook.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/rest/v10/index.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/rpc/common.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/rpc/v10.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/utils/v10.js", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/v10.js", "../index.ts", "../actions/chatWithAttachments.ts", "../generated/prompts/typescript/prompts.ts", "../generated/specs/specs.ts", "../generated/specs/spec-helpers.ts", "../actions/createPoll.ts", "../constants.ts", "../actions/deleteMessage.ts", "../actions/downloadMedia.ts", "../actions/editMessage.ts", "../actions/getUserInfo.ts", "../actions/joinChannel.ts", "../actions/leaveChannel.ts", "../actions/listChannels.ts", "../actions/pinMessage.ts", "../actions/reactToMessage.ts", "../actions/readChannel.ts", "../actions/searchMessages.ts", "../actions/sendDM.ts", "../actions/sendMessage.ts", "../actions/serverInfo.ts", "../actions/summarizeConversation.ts", "../actions/transcribeMedia.ts", "../actions/unpinMessage.ts", "../permissions.ts", "../banner.ts", "../providers/channelState.ts", "../types.ts", "../providers/guildInfo.ts", "../providers/voiceState.ts", "../service.ts", "../compat.ts", "../environment.ts", "../identity.ts", "../messages.ts", "../attachments.ts", "../utils.ts", "../permissionEvents.ts", "../voice.ts", "../tests.ts", "../accounts.ts", "../allowlist.ts", "../messaging.ts", "../../../../node_modules/.bun/discord-api-types@0.37.120/node_modules/discord-api-types/v10.mjs", "../native-commands.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=common.js.map",
|
|
6
|
+
"\"use strict\";\n/**\n * Types extracted from https://discord.com/developers/docs/topics/gateway\n */\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __exportStar = (this && this.__exportStar) || function(m, exports) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.VoiceChannelEffectSendAnimationType = exports.GatewayDispatchEvents = exports.GatewayIntentBits = exports.GatewayCloseCodes = exports.GatewayOpcodes = exports.GatewayVersion = void 0;\n__exportStar(require(\"./common\"), exports);\nexports.GatewayVersion = '10';\n/**\n * @see {@link https://discord.com/developers/docs/topics/opcodes-and-status-codes#gateway-gateway-opcodes}\n */\nvar GatewayOpcodes;\n(function (GatewayOpcodes) {\n /**\n * An event was dispatched\n */\n GatewayOpcodes[GatewayOpcodes[\"Dispatch\"] = 0] = \"Dispatch\";\n /**\n * A bidirectional opcode to maintain an active gateway connection.\n * Fired periodically by the client, or fired by the gateway to request an immediate heartbeat from the client.\n */\n GatewayOpcodes[GatewayOpcodes[\"Heartbeat\"] = 1] = \"Heartbeat\";\n /**\n * Starts a new session during the initial handshake\n */\n GatewayOpcodes[GatewayOpcodes[\"Identify\"] = 2] = \"Identify\";\n /**\n * Update the client's presence\n */\n GatewayOpcodes[GatewayOpcodes[\"PresenceUpdate\"] = 3] = \"PresenceUpdate\";\n /**\n * Used to join/leave or move between voice channels\n */\n GatewayOpcodes[GatewayOpcodes[\"VoiceStateUpdate\"] = 4] = \"VoiceStateUpdate\";\n /**\n * Resume a previous session that was disconnected\n */\n GatewayOpcodes[GatewayOpcodes[\"Resume\"] = 6] = \"Resume\";\n /**\n * You should attempt to reconnect and resume immediately\n */\n GatewayOpcodes[GatewayOpcodes[\"Reconnect\"] = 7] = \"Reconnect\";\n /**\n * Request information about offline guild members in a large guild\n */\n GatewayOpcodes[GatewayOpcodes[\"RequestGuildMembers\"] = 8] = \"RequestGuildMembers\";\n /**\n * The session has been invalidated. You should reconnect and identify/resume accordingly\n */\n GatewayOpcodes[GatewayOpcodes[\"InvalidSession\"] = 9] = \"InvalidSession\";\n /**\n * Sent immediately after connecting, contains the `heartbeat_interval` to use\n */\n GatewayOpcodes[GatewayOpcodes[\"Hello\"] = 10] = \"Hello\";\n /**\n * Sent in response to receiving a heartbeat to acknowledge that it has been received\n */\n GatewayOpcodes[GatewayOpcodes[\"HeartbeatAck\"] = 11] = \"HeartbeatAck\";\n /**\n * Request information about soundboard sounds in a set of guilds\n */\n GatewayOpcodes[GatewayOpcodes[\"RequestSoundboardSounds\"] = 31] = \"RequestSoundboardSounds\";\n})(GatewayOpcodes || (exports.GatewayOpcodes = GatewayOpcodes = {}));\n/**\n * @see {@link https://discord.com/developers/docs/topics/opcodes-and-status-codes#gateway-gateway-close-event-codes}\n */\nvar GatewayCloseCodes;\n(function (GatewayCloseCodes) {\n /**\n * We're not sure what went wrong. Try reconnecting?\n */\n GatewayCloseCodes[GatewayCloseCodes[\"UnknownError\"] = 4000] = \"UnknownError\";\n /**\n * You sent an invalid Gateway opcode or an invalid payload for an opcode. Don't do that!\n *\n * @see {@link https://discord.com/developers/docs/topics/gateway-events#payload-structure}\n */\n GatewayCloseCodes[GatewayCloseCodes[\"UnknownOpcode\"] = 4001] = \"UnknownOpcode\";\n /**\n * You sent an invalid payload to us. Don't do that!\n *\n * @see {@link https://discord.com/developers/docs/topics/gateway#sending-events}\n */\n GatewayCloseCodes[GatewayCloseCodes[\"DecodeError\"] = 4002] = \"DecodeError\";\n /**\n * You sent us a payload prior to identifying\n *\n * @see {@link https://discord.com/developers/docs/topics/gateway-events#identify}\n */\n GatewayCloseCodes[GatewayCloseCodes[\"NotAuthenticated\"] = 4003] = \"NotAuthenticated\";\n /**\n * The account token sent with your identify payload is incorrect\n *\n * @see {@link https://discord.com/developers/docs/topics/gateway-events#identify}\n */\n GatewayCloseCodes[GatewayCloseCodes[\"AuthenticationFailed\"] = 4004] = \"AuthenticationFailed\";\n /**\n * You sent more than one identify payload. Don't do that!\n */\n GatewayCloseCodes[GatewayCloseCodes[\"AlreadyAuthenticated\"] = 4005] = \"AlreadyAuthenticated\";\n /**\n * The sequence sent when resuming the session was invalid. Reconnect and start a new session\n *\n * @see {@link https://discord.com/developers/docs/topics/gateway-events#resume}\n */\n GatewayCloseCodes[GatewayCloseCodes[\"InvalidSeq\"] = 4007] = \"InvalidSeq\";\n /**\n * Woah nelly! You're sending payloads to us too quickly. Slow it down! You will be disconnected on receiving this\n */\n GatewayCloseCodes[GatewayCloseCodes[\"RateLimited\"] = 4008] = \"RateLimited\";\n /**\n * Your session timed out. Reconnect and start a new one\n */\n GatewayCloseCodes[GatewayCloseCodes[\"SessionTimedOut\"] = 4009] = \"SessionTimedOut\";\n /**\n * You sent us an invalid shard when identifying\n *\n * @see {@link https://discord.com/developers/docs/topics/gateway#sharding}\n */\n GatewayCloseCodes[GatewayCloseCodes[\"InvalidShard\"] = 4010] = \"InvalidShard\";\n /**\n * The session would have handled too many guilds - you are required to shard your connection in order to connect\n *\n * @see {@link https://discord.com/developers/docs/topics/gateway#sharding}\n */\n GatewayCloseCodes[GatewayCloseCodes[\"ShardingRequired\"] = 4011] = \"ShardingRequired\";\n /**\n * You sent an invalid version for the gateway\n */\n GatewayCloseCodes[GatewayCloseCodes[\"InvalidAPIVersion\"] = 4012] = \"InvalidAPIVersion\";\n /**\n * You sent an invalid intent for a Gateway Intent. You may have incorrectly calculated the bitwise value\n *\n * @see {@link https://discord.com/developers/docs/topics/gateway#gateway-intents}\n */\n GatewayCloseCodes[GatewayCloseCodes[\"InvalidIntents\"] = 4013] = \"InvalidIntents\";\n /**\n * You sent a disallowed intent for a Gateway Intent. You may have tried to specify an intent that you have not\n * enabled or are not whitelisted for\n *\n * @see {@link https://discord.com/developers/docs/topics/gateway#gateway-intents}\n * @see {@link https://discord.com/developers/docs/topics/gateway#privileged-intents}\n */\n GatewayCloseCodes[GatewayCloseCodes[\"DisallowedIntents\"] = 4014] = \"DisallowedIntents\";\n})(GatewayCloseCodes || (exports.GatewayCloseCodes = GatewayCloseCodes = {}));\n/**\n * @see {@link https://discord.com/developers/docs/topics/gateway#list-of-intents}\n */\nvar GatewayIntentBits;\n(function (GatewayIntentBits) {\n GatewayIntentBits[GatewayIntentBits[\"Guilds\"] = 1] = \"Guilds\";\n GatewayIntentBits[GatewayIntentBits[\"GuildMembers\"] = 2] = \"GuildMembers\";\n GatewayIntentBits[GatewayIntentBits[\"GuildModeration\"] = 4] = \"GuildModeration\";\n /**\n * @deprecated This is the old name for {@link GatewayIntentBits.GuildModeration}\n */\n GatewayIntentBits[GatewayIntentBits[\"GuildBans\"] = 4] = \"GuildBans\";\n GatewayIntentBits[GatewayIntentBits[\"GuildExpressions\"] = 8] = \"GuildExpressions\";\n /**\n * @deprecated This is the old name for {@link GatewayIntentBits.GuildExpressions}\n */\n GatewayIntentBits[GatewayIntentBits[\"GuildEmojisAndStickers\"] = 8] = \"GuildEmojisAndStickers\";\n GatewayIntentBits[GatewayIntentBits[\"GuildIntegrations\"] = 16] = \"GuildIntegrations\";\n GatewayIntentBits[GatewayIntentBits[\"GuildWebhooks\"] = 32] = \"GuildWebhooks\";\n GatewayIntentBits[GatewayIntentBits[\"GuildInvites\"] = 64] = \"GuildInvites\";\n GatewayIntentBits[GatewayIntentBits[\"GuildVoiceStates\"] = 128] = \"GuildVoiceStates\";\n GatewayIntentBits[GatewayIntentBits[\"GuildPresences\"] = 256] = \"GuildPresences\";\n GatewayIntentBits[GatewayIntentBits[\"GuildMessages\"] = 512] = \"GuildMessages\";\n GatewayIntentBits[GatewayIntentBits[\"GuildMessageReactions\"] = 1024] = \"GuildMessageReactions\";\n GatewayIntentBits[GatewayIntentBits[\"GuildMessageTyping\"] = 2048] = \"GuildMessageTyping\";\n GatewayIntentBits[GatewayIntentBits[\"DirectMessages\"] = 4096] = \"DirectMessages\";\n GatewayIntentBits[GatewayIntentBits[\"DirectMessageReactions\"] = 8192] = \"DirectMessageReactions\";\n GatewayIntentBits[GatewayIntentBits[\"DirectMessageTyping\"] = 16384] = \"DirectMessageTyping\";\n GatewayIntentBits[GatewayIntentBits[\"MessageContent\"] = 32768] = \"MessageContent\";\n GatewayIntentBits[GatewayIntentBits[\"GuildScheduledEvents\"] = 65536] = \"GuildScheduledEvents\";\n GatewayIntentBits[GatewayIntentBits[\"AutoModerationConfiguration\"] = 1048576] = \"AutoModerationConfiguration\";\n GatewayIntentBits[GatewayIntentBits[\"AutoModerationExecution\"] = 2097152] = \"AutoModerationExecution\";\n GatewayIntentBits[GatewayIntentBits[\"GuildMessagePolls\"] = 16777216] = \"GuildMessagePolls\";\n GatewayIntentBits[GatewayIntentBits[\"DirectMessagePolls\"] = 33554432] = \"DirectMessagePolls\";\n})(GatewayIntentBits || (exports.GatewayIntentBits = GatewayIntentBits = {}));\n/**\n * @see {@link https://discord.com/developers/docs/topics/gateway-events#receive-events}\n */\nvar GatewayDispatchEvents;\n(function (GatewayDispatchEvents) {\n GatewayDispatchEvents[\"ApplicationCommandPermissionsUpdate\"] = \"APPLICATION_COMMAND_PERMISSIONS_UPDATE\";\n GatewayDispatchEvents[\"AutoModerationActionExecution\"] = \"AUTO_MODERATION_ACTION_EXECUTION\";\n GatewayDispatchEvents[\"AutoModerationRuleCreate\"] = \"AUTO_MODERATION_RULE_CREATE\";\n GatewayDispatchEvents[\"AutoModerationRuleDelete\"] = \"AUTO_MODERATION_RULE_DELETE\";\n GatewayDispatchEvents[\"AutoModerationRuleUpdate\"] = \"AUTO_MODERATION_RULE_UPDATE\";\n GatewayDispatchEvents[\"ChannelCreate\"] = \"CHANNEL_CREATE\";\n GatewayDispatchEvents[\"ChannelDelete\"] = \"CHANNEL_DELETE\";\n GatewayDispatchEvents[\"ChannelPinsUpdate\"] = \"CHANNEL_PINS_UPDATE\";\n GatewayDispatchEvents[\"ChannelUpdate\"] = \"CHANNEL_UPDATE\";\n GatewayDispatchEvents[\"EntitlementCreate\"] = \"ENTITLEMENT_CREATE\";\n GatewayDispatchEvents[\"EntitlementDelete\"] = \"ENTITLEMENT_DELETE\";\n GatewayDispatchEvents[\"EntitlementUpdate\"] = \"ENTITLEMENT_UPDATE\";\n GatewayDispatchEvents[\"GuildAuditLogEntryCreate\"] = \"GUILD_AUDIT_LOG_ENTRY_CREATE\";\n GatewayDispatchEvents[\"GuildBanAdd\"] = \"GUILD_BAN_ADD\";\n GatewayDispatchEvents[\"GuildBanRemove\"] = \"GUILD_BAN_REMOVE\";\n GatewayDispatchEvents[\"GuildCreate\"] = \"GUILD_CREATE\";\n GatewayDispatchEvents[\"GuildDelete\"] = \"GUILD_DELETE\";\n GatewayDispatchEvents[\"GuildEmojisUpdate\"] = \"GUILD_EMOJIS_UPDATE\";\n GatewayDispatchEvents[\"GuildIntegrationsUpdate\"] = \"GUILD_INTEGRATIONS_UPDATE\";\n GatewayDispatchEvents[\"GuildMemberAdd\"] = \"GUILD_MEMBER_ADD\";\n GatewayDispatchEvents[\"GuildMemberRemove\"] = \"GUILD_MEMBER_REMOVE\";\n GatewayDispatchEvents[\"GuildMembersChunk\"] = \"GUILD_MEMBERS_CHUNK\";\n GatewayDispatchEvents[\"GuildMemberUpdate\"] = \"GUILD_MEMBER_UPDATE\";\n GatewayDispatchEvents[\"GuildRoleCreate\"] = \"GUILD_ROLE_CREATE\";\n GatewayDispatchEvents[\"GuildRoleDelete\"] = \"GUILD_ROLE_DELETE\";\n GatewayDispatchEvents[\"GuildRoleUpdate\"] = \"GUILD_ROLE_UPDATE\";\n GatewayDispatchEvents[\"GuildScheduledEventCreate\"] = \"GUILD_SCHEDULED_EVENT_CREATE\";\n GatewayDispatchEvents[\"GuildScheduledEventDelete\"] = \"GUILD_SCHEDULED_EVENT_DELETE\";\n GatewayDispatchEvents[\"GuildScheduledEventUpdate\"] = \"GUILD_SCHEDULED_EVENT_UPDATE\";\n GatewayDispatchEvents[\"GuildScheduledEventUserAdd\"] = \"GUILD_SCHEDULED_EVENT_USER_ADD\";\n GatewayDispatchEvents[\"GuildScheduledEventUserRemove\"] = \"GUILD_SCHEDULED_EVENT_USER_REMOVE\";\n GatewayDispatchEvents[\"GuildSoundboardSoundCreate\"] = \"GUILD_SOUNDBOARD_SOUND_CREATE\";\n GatewayDispatchEvents[\"GuildSoundboardSoundDelete\"] = \"GUILD_SOUNDBOARD_SOUND_DELETE\";\n GatewayDispatchEvents[\"GuildSoundboardSoundsUpdate\"] = \"GUILD_SOUNDBOARD_SOUNDS_UPDATE\";\n GatewayDispatchEvents[\"GuildSoundboardSoundUpdate\"] = \"GUILD_SOUNDBOARD_SOUND_UPDATE\";\n GatewayDispatchEvents[\"SoundboardSounds\"] = \"SOUNDBOARD_SOUNDS\";\n GatewayDispatchEvents[\"GuildStickersUpdate\"] = \"GUILD_STICKERS_UPDATE\";\n GatewayDispatchEvents[\"GuildUpdate\"] = \"GUILD_UPDATE\";\n GatewayDispatchEvents[\"IntegrationCreate\"] = \"INTEGRATION_CREATE\";\n GatewayDispatchEvents[\"IntegrationDelete\"] = \"INTEGRATION_DELETE\";\n GatewayDispatchEvents[\"IntegrationUpdate\"] = \"INTEGRATION_UPDATE\";\n GatewayDispatchEvents[\"InteractionCreate\"] = \"INTERACTION_CREATE\";\n GatewayDispatchEvents[\"InviteCreate\"] = \"INVITE_CREATE\";\n GatewayDispatchEvents[\"InviteDelete\"] = \"INVITE_DELETE\";\n GatewayDispatchEvents[\"MessageCreate\"] = \"MESSAGE_CREATE\";\n GatewayDispatchEvents[\"MessageDelete\"] = \"MESSAGE_DELETE\";\n GatewayDispatchEvents[\"MessageDeleteBulk\"] = \"MESSAGE_DELETE_BULK\";\n GatewayDispatchEvents[\"MessagePollVoteAdd\"] = \"MESSAGE_POLL_VOTE_ADD\";\n GatewayDispatchEvents[\"MessagePollVoteRemove\"] = \"MESSAGE_POLL_VOTE_REMOVE\";\n GatewayDispatchEvents[\"MessageReactionAdd\"] = \"MESSAGE_REACTION_ADD\";\n GatewayDispatchEvents[\"MessageReactionRemove\"] = \"MESSAGE_REACTION_REMOVE\";\n GatewayDispatchEvents[\"MessageReactionRemoveAll\"] = \"MESSAGE_REACTION_REMOVE_ALL\";\n GatewayDispatchEvents[\"MessageReactionRemoveEmoji\"] = \"MESSAGE_REACTION_REMOVE_EMOJI\";\n GatewayDispatchEvents[\"MessageUpdate\"] = \"MESSAGE_UPDATE\";\n GatewayDispatchEvents[\"PresenceUpdate\"] = \"PRESENCE_UPDATE\";\n GatewayDispatchEvents[\"Ready\"] = \"READY\";\n GatewayDispatchEvents[\"Resumed\"] = \"RESUMED\";\n GatewayDispatchEvents[\"StageInstanceCreate\"] = \"STAGE_INSTANCE_CREATE\";\n GatewayDispatchEvents[\"StageInstanceDelete\"] = \"STAGE_INSTANCE_DELETE\";\n GatewayDispatchEvents[\"StageInstanceUpdate\"] = \"STAGE_INSTANCE_UPDATE\";\n GatewayDispatchEvents[\"SubscriptionCreate\"] = \"SUBSCRIPTION_CREATE\";\n GatewayDispatchEvents[\"SubscriptionDelete\"] = \"SUBSCRIPTION_DELETE\";\n GatewayDispatchEvents[\"SubscriptionUpdate\"] = \"SUBSCRIPTION_UPDATE\";\n GatewayDispatchEvents[\"ThreadCreate\"] = \"THREAD_CREATE\";\n GatewayDispatchEvents[\"ThreadDelete\"] = \"THREAD_DELETE\";\n GatewayDispatchEvents[\"ThreadListSync\"] = \"THREAD_LIST_SYNC\";\n GatewayDispatchEvents[\"ThreadMembersUpdate\"] = \"THREAD_MEMBERS_UPDATE\";\n GatewayDispatchEvents[\"ThreadMemberUpdate\"] = \"THREAD_MEMBER_UPDATE\";\n GatewayDispatchEvents[\"ThreadUpdate\"] = \"THREAD_UPDATE\";\n GatewayDispatchEvents[\"TypingStart\"] = \"TYPING_START\";\n GatewayDispatchEvents[\"UserUpdate\"] = \"USER_UPDATE\";\n GatewayDispatchEvents[\"VoiceChannelEffectSend\"] = \"VOICE_CHANNEL_EFFECT_SEND\";\n GatewayDispatchEvents[\"VoiceServerUpdate\"] = \"VOICE_SERVER_UPDATE\";\n GatewayDispatchEvents[\"VoiceStateUpdate\"] = \"VOICE_STATE_UPDATE\";\n GatewayDispatchEvents[\"WebhooksUpdate\"] = \"WEBHOOKS_UPDATE\";\n})(GatewayDispatchEvents || (exports.GatewayDispatchEvents = GatewayDispatchEvents = {}));\n/**\n * @see {@link https://discord.com/developers/docs/topics/gateway-events#voice-channel-effect-send-animation-types}\n */\nvar VoiceChannelEffectSendAnimationType;\n(function (VoiceChannelEffectSendAnimationType) {\n /**\n * A fun animation, sent by a Nitro subscriber\n */\n VoiceChannelEffectSendAnimationType[VoiceChannelEffectSendAnimationType[\"Premium\"] = 0] = \"Premium\";\n /**\n * The standard animation\n */\n VoiceChannelEffectSendAnimationType[VoiceChannelEffectSendAnimationType[\"Basic\"] = 1] = \"Basic\";\n})(VoiceChannelEffectSendAnimationType || (exports.VoiceChannelEffectSendAnimationType = VoiceChannelEffectSendAnimationType = {}));\n// #endregion Shared\n//# sourceMappingURL=v10.js.map",
|
|
7
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.FormattingPatterns = void 0;\n/**\n * @see {@link https://discord.com/developers/docs/reference#message-formatting-formats}\n */\nexports.FormattingPatterns = {\n /**\n * Regular expression for matching a user mention, strictly without a nickname\n *\n * The `id` group property is present on the `exec` result of this expression\n */\n User: /<@(?<id>\\d{17,20})>/,\n /**\n * Regular expression for matching a user mention, strictly with a nickname\n *\n * The `id` group property is present on the `exec` result of this expression\n *\n * @deprecated Passing `!` in user mentions is no longer necessary / supported, and future message contents won't have it\n */\n UserWithNickname: /<@!(?<id>\\d{17,20})>/,\n /**\n * Regular expression for matching a user mention, with or without a nickname\n *\n * The `id` group property is present on the `exec` result of this expression\n *\n * @deprecated Passing `!` in user mentions is no longer necessary / supported, and future message contents won't have it\n */\n UserWithOptionalNickname: /<@!?(?<id>\\d{17,20})>/,\n /**\n * Regular expression for matching a channel mention\n *\n * The `id` group property is present on the `exec` result of this expression\n */\n Channel: /<#(?<id>\\d{17,20})>/,\n /**\n * Regular expression for matching a role mention\n *\n * The `id` group property is present on the `exec` result of this expression\n */\n Role: /<@&(?<id>\\d{17,20})>/,\n /**\n * Regular expression for matching a application command mention\n *\n * The `fullName` (possibly including `name`, `subcommandOrGroup` and `subcommand`) and `id` group properties are present on the `exec` result of this expression\n */\n SlashCommand: \n // eslint-disable-next-line unicorn/no-unsafe-regex\n /<\\/(?<fullName>(?<name>[-_\\p{Letter}\\p{Number}\\p{sc=Deva}\\p{sc=Thai}]{1,32})(?: (?<subcommandOrGroup>[-_\\p{Letter}\\p{Number}\\p{sc=Deva}\\p{sc=Thai}]{1,32}))?(?: (?<subcommand>[-_\\p{Letter}\\p{Number}\\p{sc=Deva}\\p{sc=Thai}]{1,32}))?):(?<id>\\d{17,20})>/u,\n /**\n * Regular expression for matching a custom emoji, either static or animated\n *\n * The `animated`, `name` and `id` group properties are present on the `exec` result of this expression\n */\n Emoji: /<(?<animated>a)?:(?<name>\\w{2,32}):(?<id>\\d{17,20})>/,\n /**\n * Regular expression for matching strictly an animated custom emoji\n *\n * The `animated`, `name` and `id` group properties are present on the `exec` result of this expression\n */\n AnimatedEmoji: /<(?<animated>a):(?<name>\\w{2,32}):(?<id>\\d{17,20})>/,\n /**\n * Regular expression for matching strictly a static custom emoji\n *\n * The `name` and `id` group properties are present on the `exec` result of this expression\n */\n StaticEmoji: /<:(?<name>\\w{2,32}):(?<id>\\d{17,20})>/,\n /**\n * Regular expression for matching a timestamp, either default or custom styled\n *\n * The `timestamp` and `style` group properties are present on the `exec` result of this expression\n */\n // eslint-disable-next-line prefer-named-capture-group\n Timestamp: /<t:(?<timestamp>-?\\d{1,13})(:(?<style>[DFRTdft]))?>/,\n /**\n * Regular expression for matching strictly default styled timestamps\n *\n * The `timestamp` group property is present on the `exec` result of this expression\n */\n DefaultStyledTimestamp: /<t:(?<timestamp>-?\\d{1,13})>/,\n /**\n * Regular expression for matching strictly custom styled timestamps\n *\n * The `timestamp` and `style` group properties are present on the `exec` result of this expression\n */\n StyledTimestamp: /<t:(?<timestamp>-?\\d{1,13}):(?<style>[DFRTdft])>/,\n /**\n * Regular expression for matching a guild navigation mention\n *\n * The `type` group property is present on the `exec` result of this expression\n */\n GuildNavigation: /<id:(?<type>customize|browse|guide|linked-roles)>/,\n /**\n * Regular expression for matching a linked role mention\n *\n * The `id` group property is present on the `exec` result of this expression\n */\n LinkedRole: /<id:linked-roles:(?<id>\\d{17,20})>/,\n};\n/**\n * Freezes the formatting patterns\n *\n * @internal\n */\nObject.freeze(exports.FormattingPatterns);\n//# sourceMappingURL=globals.js.map",
|
|
8
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.PermissionFlagsBits = void 0;\n/**\n * @see {@link https://discord.com/developers/docs/topics/permissions#permissions-bitwise-permission-flags}\n *\n * These flags are exported as `BigInt`s and NOT numbers. Wrapping them in `Number()`\n * may cause issues, try to use BigInts as much as possible or modules that can\n * replicate them in some way\n */\nexports.PermissionFlagsBits = {\n /**\n * Allows creation of instant invites\n *\n * Applies to channel types: Text, Voice, Stage\n */\n CreateInstantInvite: 1n << 0n,\n /**\n * Allows kicking members\n */\n // eslint-disable-next-line sonarjs/no-identical-expressions\n KickMembers: 1n << 1n,\n /**\n * Allows banning members\n */\n BanMembers: 1n << 2n,\n /**\n * Allows all permissions and bypasses channel permission overwrites\n */\n Administrator: 1n << 3n,\n /**\n * Allows management and editing of channels\n *\n * Applies to channel types: Text, Voice, Stage\n */\n ManageChannels: 1n << 4n,\n /**\n * Allows management and editing of the guild\n */\n ManageGuild: 1n << 5n,\n /**\n * Allows for the addition of reactions to messages\n *\n * Applies to channel types: Text, Voice, Stage\n */\n AddReactions: 1n << 6n,\n /**\n * Allows for viewing of audit logs\n */\n ViewAuditLog: 1n << 7n,\n /**\n * Allows for using priority speaker in a voice channel\n *\n * Applies to channel types: Voice\n */\n PrioritySpeaker: 1n << 8n,\n /**\n * Allows the user to go live\n *\n * Applies to channel types: Voice, Stage\n */\n Stream: 1n << 9n,\n /**\n * Allows guild members to view a channel, which includes reading messages in text channels and joining voice channels\n *\n * Applies to channel types: Text, Voice, Stage\n */\n ViewChannel: 1n << 10n,\n /**\n * Allows for sending messages in a channel and creating threads in a forum\n * (does not allow sending messages in threads)\n *\n * Applies to channel types: Text, Voice, Stage\n */\n SendMessages: 1n << 11n,\n /**\n * Allows for sending of `/tts` messages\n *\n * Applies to channel types: Text, Voice, Stage\n */\n SendTTSMessages: 1n << 12n,\n /**\n * Allows for deletion of other users messages\n *\n * Applies to channel types: Text, Voice, Stage\n */\n ManageMessages: 1n << 13n,\n /**\n * Links sent by users with this permission will be auto-embedded\n *\n * Applies to channel types: Text, Voice, Stage\n */\n EmbedLinks: 1n << 14n,\n /**\n * Allows for uploading images and files\n *\n * Applies to channel types: Text, Voice, Stage\n */\n AttachFiles: 1n << 15n,\n /**\n * Allows for reading of message history\n *\n * Applies to channel types: Text, Voice, Stage\n */\n ReadMessageHistory: 1n << 16n,\n /**\n * Allows for using the `@everyone` tag to notify all users in a channel,\n * and the `@here` tag to notify all online users in a channel\n *\n * Applies to channel types: Text, Voice, Stage\n */\n MentionEveryone: 1n << 17n,\n /**\n * Allows the usage of custom emojis from other servers\n *\n * Applies to channel types: Text, Voice, Stage\n */\n UseExternalEmojis: 1n << 18n,\n /**\n * Allows for viewing guild insights\n */\n ViewGuildInsights: 1n << 19n,\n /**\n * Allows for joining of a voice channel\n *\n * Applies to channel types: Voice, Stage\n */\n Connect: 1n << 20n,\n /**\n * Allows for speaking in a voice channel\n *\n * Applies to channel types: Voice\n */\n Speak: 1n << 21n,\n /**\n * Allows for muting members in a voice channel\n *\n * Applies to channel types: Voice, Stage\n */\n MuteMembers: 1n << 22n,\n /**\n * Allows for deafening of members in a voice channel\n *\n * Applies to channel types: Voice\n */\n DeafenMembers: 1n << 23n,\n /**\n * Allows for moving of members between voice channels\n *\n * Applies to channel types: Voice, Stage\n */\n MoveMembers: 1n << 24n,\n /**\n * Allows for using voice-activity-detection in a voice channel\n *\n * Applies to channel types: Voice\n */\n UseVAD: 1n << 25n,\n /**\n * Allows for modification of own nickname\n */\n ChangeNickname: 1n << 26n,\n /**\n * Allows for modification of other users nicknames\n */\n ManageNicknames: 1n << 27n,\n /**\n * Allows management and editing of roles\n *\n * Applies to channel types: Text, Voice, Stage\n */\n ManageRoles: 1n << 28n,\n /**\n * Allows management and editing of webhooks\n *\n * Applies to channel types: Text, Voice, Stage\n */\n ManageWebhooks: 1n << 29n,\n /**\n * Allows management and editing of emojis, stickers, and soundboard sounds\n *\n * @deprecated This is the old name for {@link PermissionFlagsBits.ManageGuildExpressions}\n */\n ManageEmojisAndStickers: 1n << 30n,\n /**\n * Allows for editing and deleting emojis, stickers, and soundboard sounds created by all users\n */\n ManageGuildExpressions: 1n << 30n,\n /**\n * Allows members to use application commands, including slash commands and context menu commands\n *\n * Applies to channel types: Text, Voice, Stage\n */\n UseApplicationCommands: 1n << 31n,\n /**\n * Allows for requesting to speak in stage channels\n *\n * Applies to channel types: Stage\n */\n RequestToSpeak: 1n << 32n,\n /**\n * Allows for editing and deleting scheduled events created by all users\n *\n * Applies to channel types: Voice, Stage\n */\n ManageEvents: 1n << 33n,\n /**\n * Allows for deleting and archiving threads, and viewing all private threads\n *\n * Applies to channel types: Text\n */\n ManageThreads: 1n << 34n,\n /**\n * Allows for creating public and announcement threads\n *\n * Applies to channel types: Text\n */\n CreatePublicThreads: 1n << 35n,\n /**\n * Allows for creating private threads\n *\n * Applies to channel types: Text\n */\n CreatePrivateThreads: 1n << 36n,\n /**\n * Allows the usage of custom stickers from other servers\n *\n * Applies to channel types: Text, Voice, Stage\n */\n UseExternalStickers: 1n << 37n,\n /**\n * Allows for sending messages in threads\n *\n * Applies to channel types: Text\n */\n SendMessagesInThreads: 1n << 38n,\n /**\n * Allows for using Activities (applications with the {@link ApplicationFlags.Embedded} flag) in a voice channel\n *\n * Applies to channel types: Voice\n */\n UseEmbeddedActivities: 1n << 39n,\n /**\n * Allows for timing out users to prevent them from sending or reacting to messages in chat and threads,\n * and from speaking in voice and stage channels\n */\n ModerateMembers: 1n << 40n,\n /**\n * Allows for viewing role subscription insights\n */\n ViewCreatorMonetizationAnalytics: 1n << 41n,\n /**\n * Allows for using soundboard in a voice channel\n *\n * Applies to channel types: Voice\n */\n UseSoundboard: 1n << 42n,\n /**\n * Allows for creating emojis, stickers, and soundboard sounds, and editing and deleting those created by the current user\n */\n CreateGuildExpressions: 1n << 43n,\n /**\n * Allows for creating scheduled events, and editing and deleting those created by the current user\n *\n * Applies to channel types: Voice, Stage\n */\n CreateEvents: 1n << 44n,\n /**\n * Allows the usage of custom soundboard sounds from other servers\n *\n * Applies to channel types: Voice\n */\n UseExternalSounds: 1n << 45n,\n /**\n * Allows sending voice messages\n *\n * Applies to channel types: Text, Voice, Stage\n */\n SendVoiceMessages: 1n << 46n,\n /**\n * Allows sending polls\n *\n * Applies to channel types: Text, Voice, Stage\n */\n SendPolls: 1n << 49n,\n /**\n * Allows user-installed apps to send public responses. When disabled, users will still be allowed to use their apps but the responses will be ephemeral. This only applies to apps not also installed to the server\n *\n * Applies to channel types: Text, Voice, Stage\n */\n UseExternalApps: 1n << 50n,\n};\n/**\n * Freeze the object of bits, preventing any modifications to it\n *\n * @internal\n */\nObject.freeze(exports.PermissionFlagsBits);\n//# sourceMappingURL=common.js.map",
|
|
9
|
+
"\"use strict\";\n/**\n * Types extracted from https://discord.com/developers/docs/resources/application\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.ApplicationWebhookEventStatus = exports.ApplicationRoleConnectionMetadataType = exports.ApplicationFlags = void 0;\n/**\n * @see {@link https://discord.com/developers/docs/resources/application#application-object-application-flags}\n */\nvar ApplicationFlags;\n(function (ApplicationFlags) {\n /**\n * @unstable This application flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n */\n ApplicationFlags[ApplicationFlags[\"EmbeddedReleased\"] = 2] = \"EmbeddedReleased\";\n /**\n * @unstable This application flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n */\n ApplicationFlags[ApplicationFlags[\"ManagedEmoji\"] = 4] = \"ManagedEmoji\";\n /**\n * @unstable This application flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n */\n ApplicationFlags[ApplicationFlags[\"EmbeddedIAP\"] = 8] = \"EmbeddedIAP\";\n /**\n * @unstable This application flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n */\n ApplicationFlags[ApplicationFlags[\"GroupDMCreate\"] = 16] = \"GroupDMCreate\";\n /**\n * Indicates if an app uses the Auto Moderation API\n */\n ApplicationFlags[ApplicationFlags[\"ApplicationAutoModerationRuleCreateBadge\"] = 64] = \"ApplicationAutoModerationRuleCreateBadge\";\n /**\n * @unstable This application flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n */\n ApplicationFlags[ApplicationFlags[\"RPCHasConnected\"] = 2048] = \"RPCHasConnected\";\n /**\n * Intent required for bots in 100 or more servers to receive `presence_update` events\n */\n ApplicationFlags[ApplicationFlags[\"GatewayPresence\"] = 4096] = \"GatewayPresence\";\n /**\n * Intent required for bots in under 100 servers to receive `presence_update` events, found in Bot Settings\n */\n ApplicationFlags[ApplicationFlags[\"GatewayPresenceLimited\"] = 8192] = \"GatewayPresenceLimited\";\n /**\n * Intent required for bots in 100 or more servers to receive member-related events like `guild_member_add`.\n *\n * @see List of member-related events {@link https://discord.com/developers/docs/topics/gateway#list-of-intents | under `GUILD_MEMBERS`}\n */\n ApplicationFlags[ApplicationFlags[\"GatewayGuildMembers\"] = 16384] = \"GatewayGuildMembers\";\n /**\n * Intent required for bots in under 100 servers to receive member-related events like `guild_member_add`, found in Bot Settings.\n *\n * @see List of member-related events {@link https://discord.com/developers/docs/topics/gateway#list-of-intents | under `GUILD_MEMBERS`}\n */\n ApplicationFlags[ApplicationFlags[\"GatewayGuildMembersLimited\"] = 32768] = \"GatewayGuildMembersLimited\";\n /**\n * Indicates unusual growth of an app that prevents verification\n */\n ApplicationFlags[ApplicationFlags[\"VerificationPendingGuildLimit\"] = 65536] = \"VerificationPendingGuildLimit\";\n /**\n * Indicates if an app is embedded within the Discord client (currently unavailable publicly)\n */\n ApplicationFlags[ApplicationFlags[\"Embedded\"] = 131072] = \"Embedded\";\n /**\n * Intent required for bots in 100 or more servers to receive {@link https://support-dev.discord.com/hc/en-us/articles/4404772028055 | message content}\n */\n ApplicationFlags[ApplicationFlags[\"GatewayMessageContent\"] = 262144] = \"GatewayMessageContent\";\n /**\n * Intent required for bots in under 100 servers to receive {@link https://support-dev.discord.com/hc/en-us/articles/4404772028055 | message content},\n * found in Bot Settings\n */\n ApplicationFlags[ApplicationFlags[\"GatewayMessageContentLimited\"] = 524288] = \"GatewayMessageContentLimited\";\n /**\n * @unstable This application flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n */\n ApplicationFlags[ApplicationFlags[\"EmbeddedFirstParty\"] = 1048576] = \"EmbeddedFirstParty\";\n /**\n * Indicates if an app has registered global {@link https://discord.com/developers/docs/interactions/application-commands | application commands}\n */\n ApplicationFlags[ApplicationFlags[\"ApplicationCommandBadge\"] = 8388608] = \"ApplicationCommandBadge\";\n})(ApplicationFlags || (exports.ApplicationFlags = ApplicationFlags = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/application-role-connection-metadata#application-role-connection-metadata-object-application-role-connection-metadata-type}\n */\nvar ApplicationRoleConnectionMetadataType;\n(function (ApplicationRoleConnectionMetadataType) {\n /**\n * The metadata value (`integer`) is less than or equal to the guild's configured value (`integer`)\n */\n ApplicationRoleConnectionMetadataType[ApplicationRoleConnectionMetadataType[\"IntegerLessThanOrEqual\"] = 1] = \"IntegerLessThanOrEqual\";\n /**\n * The metadata value (`integer`) is greater than or equal to the guild's configured value (`integer`)\n */\n ApplicationRoleConnectionMetadataType[ApplicationRoleConnectionMetadataType[\"IntegerGreaterThanOrEqual\"] = 2] = \"IntegerGreaterThanOrEqual\";\n /**\n * The metadata value (`integer`) is equal to the guild's configured value (`integer`)\n */\n ApplicationRoleConnectionMetadataType[ApplicationRoleConnectionMetadataType[\"IntegerEqual\"] = 3] = \"IntegerEqual\";\n /**\n * The metadata value (`integer`) is not equal to the guild's configured value (`integer`)\n */\n ApplicationRoleConnectionMetadataType[ApplicationRoleConnectionMetadataType[\"IntegerNotEqual\"] = 4] = \"IntegerNotEqual\";\n /**\n * The metadata value (`ISO8601 string`) is less than or equal to the guild's configured value (`integer`; days before current date)\n */\n ApplicationRoleConnectionMetadataType[ApplicationRoleConnectionMetadataType[\"DatetimeLessThanOrEqual\"] = 5] = \"DatetimeLessThanOrEqual\";\n /**\n * The metadata value (`ISO8601 string`) is greater than or equal to the guild's configured value (`integer`; days before current date)\n */\n ApplicationRoleConnectionMetadataType[ApplicationRoleConnectionMetadataType[\"DatetimeGreaterThanOrEqual\"] = 6] = \"DatetimeGreaterThanOrEqual\";\n /**\n * The metadata value (`integer`) is equal to the guild's configured value (`integer`; `1`)\n */\n ApplicationRoleConnectionMetadataType[ApplicationRoleConnectionMetadataType[\"BooleanEqual\"] = 7] = \"BooleanEqual\";\n /**\n * The metadata value (`integer`) is not equal to the guild's configured value (`integer`; `1`)\n */\n ApplicationRoleConnectionMetadataType[ApplicationRoleConnectionMetadataType[\"BooleanNotEqual\"] = 8] = \"BooleanNotEqual\";\n})(ApplicationRoleConnectionMetadataType || (exports.ApplicationRoleConnectionMetadataType = ApplicationRoleConnectionMetadataType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/application#application-object-application-event-webhook-status}\n */\nvar ApplicationWebhookEventStatus;\n(function (ApplicationWebhookEventStatus) {\n /**\n * Webhook events are disabled by developer\n */\n ApplicationWebhookEventStatus[ApplicationWebhookEventStatus[\"Disabled\"] = 1] = \"Disabled\";\n /**\n * Webhook events are enabled by developer\n */\n ApplicationWebhookEventStatus[ApplicationWebhookEventStatus[\"Enabled\"] = 2] = \"Enabled\";\n /**\n * Webhook events are disabled by Discord, usually due to inactivity\n */\n ApplicationWebhookEventStatus[ApplicationWebhookEventStatus[\"DisabledByDiscord\"] = 3] = \"DisabledByDiscord\";\n})(ApplicationWebhookEventStatus || (exports.ApplicationWebhookEventStatus = ApplicationWebhookEventStatus = {}));\n//# sourceMappingURL=application.js.map",
|
|
10
|
+
"\"use strict\";\n/**\n * Types extracted from https://discord.com/developers/docs/resources/audit-log\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.AuditLogOptionsType = exports.AuditLogEvent = void 0;\n/**\n * @see {@link https://discord.com/developers/docs/resources/audit-log#audit-log-entry-object-audit-log-events}\n */\nvar AuditLogEvent;\n(function (AuditLogEvent) {\n AuditLogEvent[AuditLogEvent[\"GuildUpdate\"] = 1] = \"GuildUpdate\";\n AuditLogEvent[AuditLogEvent[\"ChannelCreate\"] = 10] = \"ChannelCreate\";\n AuditLogEvent[AuditLogEvent[\"ChannelUpdate\"] = 11] = \"ChannelUpdate\";\n AuditLogEvent[AuditLogEvent[\"ChannelDelete\"] = 12] = \"ChannelDelete\";\n AuditLogEvent[AuditLogEvent[\"ChannelOverwriteCreate\"] = 13] = \"ChannelOverwriteCreate\";\n AuditLogEvent[AuditLogEvent[\"ChannelOverwriteUpdate\"] = 14] = \"ChannelOverwriteUpdate\";\n AuditLogEvent[AuditLogEvent[\"ChannelOverwriteDelete\"] = 15] = \"ChannelOverwriteDelete\";\n AuditLogEvent[AuditLogEvent[\"MemberKick\"] = 20] = \"MemberKick\";\n AuditLogEvent[AuditLogEvent[\"MemberPrune\"] = 21] = \"MemberPrune\";\n AuditLogEvent[AuditLogEvent[\"MemberBanAdd\"] = 22] = \"MemberBanAdd\";\n AuditLogEvent[AuditLogEvent[\"MemberBanRemove\"] = 23] = \"MemberBanRemove\";\n AuditLogEvent[AuditLogEvent[\"MemberUpdate\"] = 24] = \"MemberUpdate\";\n AuditLogEvent[AuditLogEvent[\"MemberRoleUpdate\"] = 25] = \"MemberRoleUpdate\";\n AuditLogEvent[AuditLogEvent[\"MemberMove\"] = 26] = \"MemberMove\";\n AuditLogEvent[AuditLogEvent[\"MemberDisconnect\"] = 27] = \"MemberDisconnect\";\n AuditLogEvent[AuditLogEvent[\"BotAdd\"] = 28] = \"BotAdd\";\n AuditLogEvent[AuditLogEvent[\"RoleCreate\"] = 30] = \"RoleCreate\";\n AuditLogEvent[AuditLogEvent[\"RoleUpdate\"] = 31] = \"RoleUpdate\";\n AuditLogEvent[AuditLogEvent[\"RoleDelete\"] = 32] = \"RoleDelete\";\n AuditLogEvent[AuditLogEvent[\"InviteCreate\"] = 40] = \"InviteCreate\";\n AuditLogEvent[AuditLogEvent[\"InviteUpdate\"] = 41] = \"InviteUpdate\";\n AuditLogEvent[AuditLogEvent[\"InviteDelete\"] = 42] = \"InviteDelete\";\n AuditLogEvent[AuditLogEvent[\"WebhookCreate\"] = 50] = \"WebhookCreate\";\n AuditLogEvent[AuditLogEvent[\"WebhookUpdate\"] = 51] = \"WebhookUpdate\";\n AuditLogEvent[AuditLogEvent[\"WebhookDelete\"] = 52] = \"WebhookDelete\";\n AuditLogEvent[AuditLogEvent[\"EmojiCreate\"] = 60] = \"EmojiCreate\";\n AuditLogEvent[AuditLogEvent[\"EmojiUpdate\"] = 61] = \"EmojiUpdate\";\n AuditLogEvent[AuditLogEvent[\"EmojiDelete\"] = 62] = \"EmojiDelete\";\n AuditLogEvent[AuditLogEvent[\"MessageDelete\"] = 72] = \"MessageDelete\";\n AuditLogEvent[AuditLogEvent[\"MessageBulkDelete\"] = 73] = \"MessageBulkDelete\";\n AuditLogEvent[AuditLogEvent[\"MessagePin\"] = 74] = \"MessagePin\";\n AuditLogEvent[AuditLogEvent[\"MessageUnpin\"] = 75] = \"MessageUnpin\";\n AuditLogEvent[AuditLogEvent[\"IntegrationCreate\"] = 80] = \"IntegrationCreate\";\n AuditLogEvent[AuditLogEvent[\"IntegrationUpdate\"] = 81] = \"IntegrationUpdate\";\n AuditLogEvent[AuditLogEvent[\"IntegrationDelete\"] = 82] = \"IntegrationDelete\";\n AuditLogEvent[AuditLogEvent[\"StageInstanceCreate\"] = 83] = \"StageInstanceCreate\";\n AuditLogEvent[AuditLogEvent[\"StageInstanceUpdate\"] = 84] = \"StageInstanceUpdate\";\n AuditLogEvent[AuditLogEvent[\"StageInstanceDelete\"] = 85] = \"StageInstanceDelete\";\n AuditLogEvent[AuditLogEvent[\"StickerCreate\"] = 90] = \"StickerCreate\";\n AuditLogEvent[AuditLogEvent[\"StickerUpdate\"] = 91] = \"StickerUpdate\";\n AuditLogEvent[AuditLogEvent[\"StickerDelete\"] = 92] = \"StickerDelete\";\n AuditLogEvent[AuditLogEvent[\"GuildScheduledEventCreate\"] = 100] = \"GuildScheduledEventCreate\";\n AuditLogEvent[AuditLogEvent[\"GuildScheduledEventUpdate\"] = 101] = \"GuildScheduledEventUpdate\";\n AuditLogEvent[AuditLogEvent[\"GuildScheduledEventDelete\"] = 102] = \"GuildScheduledEventDelete\";\n AuditLogEvent[AuditLogEvent[\"ThreadCreate\"] = 110] = \"ThreadCreate\";\n AuditLogEvent[AuditLogEvent[\"ThreadUpdate\"] = 111] = \"ThreadUpdate\";\n AuditLogEvent[AuditLogEvent[\"ThreadDelete\"] = 112] = \"ThreadDelete\";\n AuditLogEvent[AuditLogEvent[\"ApplicationCommandPermissionUpdate\"] = 121] = \"ApplicationCommandPermissionUpdate\";\n AuditLogEvent[AuditLogEvent[\"SoundboardSoundCreate\"] = 130] = \"SoundboardSoundCreate\";\n AuditLogEvent[AuditLogEvent[\"SoundboardSoundUpdate\"] = 131] = \"SoundboardSoundUpdate\";\n AuditLogEvent[AuditLogEvent[\"SoundboardSoundDelete\"] = 132] = \"SoundboardSoundDelete\";\n AuditLogEvent[AuditLogEvent[\"AutoModerationRuleCreate\"] = 140] = \"AutoModerationRuleCreate\";\n AuditLogEvent[AuditLogEvent[\"AutoModerationRuleUpdate\"] = 141] = \"AutoModerationRuleUpdate\";\n AuditLogEvent[AuditLogEvent[\"AutoModerationRuleDelete\"] = 142] = \"AutoModerationRuleDelete\";\n AuditLogEvent[AuditLogEvent[\"AutoModerationBlockMessage\"] = 143] = \"AutoModerationBlockMessage\";\n AuditLogEvent[AuditLogEvent[\"AutoModerationFlagToChannel\"] = 144] = \"AutoModerationFlagToChannel\";\n AuditLogEvent[AuditLogEvent[\"AutoModerationUserCommunicationDisabled\"] = 145] = \"AutoModerationUserCommunicationDisabled\";\n AuditLogEvent[AuditLogEvent[\"CreatorMonetizationRequestCreated\"] = 150] = \"CreatorMonetizationRequestCreated\";\n AuditLogEvent[AuditLogEvent[\"CreatorMonetizationTermsAccepted\"] = 151] = \"CreatorMonetizationTermsAccepted\";\n AuditLogEvent[AuditLogEvent[\"OnboardingPromptCreate\"] = 163] = \"OnboardingPromptCreate\";\n AuditLogEvent[AuditLogEvent[\"OnboardingPromptUpdate\"] = 164] = \"OnboardingPromptUpdate\";\n AuditLogEvent[AuditLogEvent[\"OnboardingPromptDelete\"] = 165] = \"OnboardingPromptDelete\";\n AuditLogEvent[AuditLogEvent[\"OnboardingCreate\"] = 166] = \"OnboardingCreate\";\n AuditLogEvent[AuditLogEvent[\"OnboardingUpdate\"] = 167] = \"OnboardingUpdate\";\n AuditLogEvent[AuditLogEvent[\"HomeSettingsCreate\"] = 190] = \"HomeSettingsCreate\";\n AuditLogEvent[AuditLogEvent[\"HomeSettingsUpdate\"] = 191] = \"HomeSettingsUpdate\";\n})(AuditLogEvent || (exports.AuditLogEvent = AuditLogEvent = {}));\nvar AuditLogOptionsType;\n(function (AuditLogOptionsType) {\n AuditLogOptionsType[\"Role\"] = \"0\";\n AuditLogOptionsType[\"Member\"] = \"1\";\n})(AuditLogOptionsType || (exports.AuditLogOptionsType = AuditLogOptionsType = {}));\n//# sourceMappingURL=auditLog.js.map",
|
|
11
|
+
"\"use strict\";\n/**\n * Types extracted from https://discord.com/developers/docs/resources/auto-moderation\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.AutoModerationActionType = exports.AutoModerationRuleEventType = exports.AutoModerationRuleKeywordPresetType = exports.AutoModerationRuleTriggerType = void 0;\n/**\n * @see {@link https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-rule-object-trigger-types}\n */\nvar AutoModerationRuleTriggerType;\n(function (AutoModerationRuleTriggerType) {\n /**\n * Check if content contains words from a user defined list of keywords (Maximum of 6 per guild)\n */\n AutoModerationRuleTriggerType[AutoModerationRuleTriggerType[\"Keyword\"] = 1] = \"Keyword\";\n /**\n * Check if content represents generic spam (Maximum of 1 per guild)\n */\n AutoModerationRuleTriggerType[AutoModerationRuleTriggerType[\"Spam\"] = 3] = \"Spam\";\n /**\n * Check if content contains words from internal pre-defined wordsets (Maximum of 1 per guild)\n */\n AutoModerationRuleTriggerType[AutoModerationRuleTriggerType[\"KeywordPreset\"] = 4] = \"KeywordPreset\";\n /**\n * Check if content contains more mentions than allowed (Maximum of 1 per guild)\n */\n AutoModerationRuleTriggerType[AutoModerationRuleTriggerType[\"MentionSpam\"] = 5] = \"MentionSpam\";\n /**\n * Check if member profile contains words from a user defined list of keywords (Maximum of 1 per guild)\n */\n AutoModerationRuleTriggerType[AutoModerationRuleTriggerType[\"MemberProfile\"] = 6] = \"MemberProfile\";\n})(AutoModerationRuleTriggerType || (exports.AutoModerationRuleTriggerType = AutoModerationRuleTriggerType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-rule-object-keyword-preset-types}\n */\nvar AutoModerationRuleKeywordPresetType;\n(function (AutoModerationRuleKeywordPresetType) {\n /**\n * Words that may be considered forms of swearing or cursing\n */\n AutoModerationRuleKeywordPresetType[AutoModerationRuleKeywordPresetType[\"Profanity\"] = 1] = \"Profanity\";\n /**\n * Words that refer to sexually explicit behavior or activity\n */\n AutoModerationRuleKeywordPresetType[AutoModerationRuleKeywordPresetType[\"SexualContent\"] = 2] = \"SexualContent\";\n /**\n * Personal insults or words that may be considered hate speech\n */\n AutoModerationRuleKeywordPresetType[AutoModerationRuleKeywordPresetType[\"Slurs\"] = 3] = \"Slurs\";\n})(AutoModerationRuleKeywordPresetType || (exports.AutoModerationRuleKeywordPresetType = AutoModerationRuleKeywordPresetType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-rule-object-event-types}\n */\nvar AutoModerationRuleEventType;\n(function (AutoModerationRuleEventType) {\n /**\n * When a member sends or edits a message in the guild\n */\n AutoModerationRuleEventType[AutoModerationRuleEventType[\"MessageSend\"] = 1] = \"MessageSend\";\n /**\n * When a member edits their profile\n */\n AutoModerationRuleEventType[AutoModerationRuleEventType[\"MemberUpdate\"] = 2] = \"MemberUpdate\";\n})(AutoModerationRuleEventType || (exports.AutoModerationRuleEventType = AutoModerationRuleEventType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-action-object-action-types}\n */\nvar AutoModerationActionType;\n(function (AutoModerationActionType) {\n /**\n * Blocks a member's message and prevents it from being posted.\n * A custom explanation can be specified and shown to members whenever their message is blocked\n */\n AutoModerationActionType[AutoModerationActionType[\"BlockMessage\"] = 1] = \"BlockMessage\";\n /**\n * Logs user content to a specified channel\n */\n AutoModerationActionType[AutoModerationActionType[\"SendAlertMessage\"] = 2] = \"SendAlertMessage\";\n /**\n * Timeout user for specified duration, this action type can be set if the bot has `MODERATE_MEMBERS` permission\n */\n AutoModerationActionType[AutoModerationActionType[\"Timeout\"] = 3] = \"Timeout\";\n /**\n * Prevents a member from using text, voice, or other interactions\n */\n AutoModerationActionType[AutoModerationActionType[\"BlockMemberInteraction\"] = 4] = \"BlockMemberInteraction\";\n})(AutoModerationActionType || (exports.AutoModerationActionType = AutoModerationActionType = {}));\n//# sourceMappingURL=autoModeration.js.map",
|
|
12
|
+
"\"use strict\";\n/**\n * Types extracted from https://discord.com/developers/docs/resources/channel\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.ChannelFlags = exports.SelectMenuDefaultValueType = exports.TextInputStyle = exports.ButtonStyle = exports.ComponentType = exports.AllowedMentionsTypes = exports.AttachmentFlags = exports.EmbedType = exports.ThreadMemberFlags = exports.ThreadAutoArchiveDuration = exports.OverwriteType = exports.MessageFlags = exports.MessageReferenceType = exports.MessageActivityType = exports.MessageType = exports.VideoQualityMode = exports.ChannelType = exports.ForumLayoutType = exports.SortOrderType = void 0;\n/**\n * @see {@link https://discord.com/developers/docs/resources/channel/#channel-object-sort-order-types}\n */\nvar SortOrderType;\n(function (SortOrderType) {\n /**\n * Sort forum posts by activity\n */\n SortOrderType[SortOrderType[\"LatestActivity\"] = 0] = \"LatestActivity\";\n /**\n * Sort forum posts by creation time (from most recent to oldest)\n */\n SortOrderType[SortOrderType[\"CreationDate\"] = 1] = \"CreationDate\";\n})(SortOrderType || (exports.SortOrderType = SortOrderType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/channel/#channel-object-forum-layout-types}\n */\nvar ForumLayoutType;\n(function (ForumLayoutType) {\n /**\n * No default has been set for forum channel\n */\n ForumLayoutType[ForumLayoutType[\"NotSet\"] = 0] = \"NotSet\";\n /**\n * Display posts as a list\n */\n ForumLayoutType[ForumLayoutType[\"ListView\"] = 1] = \"ListView\";\n /**\n * Display posts as a collection of tiles\n */\n ForumLayoutType[ForumLayoutType[\"GalleryView\"] = 2] = \"GalleryView\";\n})(ForumLayoutType || (exports.ForumLayoutType = ForumLayoutType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/channel#channel-object-channel-types}\n */\nvar ChannelType;\n(function (ChannelType) {\n /**\n * A text channel within a guild\n */\n ChannelType[ChannelType[\"GuildText\"] = 0] = \"GuildText\";\n /**\n * A direct message between users\n */\n ChannelType[ChannelType[\"DM\"] = 1] = \"DM\";\n /**\n * A voice channel within a guild\n */\n ChannelType[ChannelType[\"GuildVoice\"] = 2] = \"GuildVoice\";\n /**\n * A direct message between multiple users\n */\n ChannelType[ChannelType[\"GroupDM\"] = 3] = \"GroupDM\";\n /**\n * An organizational category that contains up to 50 channels\n *\n * @see {@link https://support.discord.com/hc/articles/115001580171}\n */\n ChannelType[ChannelType[\"GuildCategory\"] = 4] = \"GuildCategory\";\n /**\n * A channel that users can follow and crosspost into their own guild\n *\n * @see {@link https://support.discord.com/hc/articles/360032008192}\n */\n ChannelType[ChannelType[\"GuildAnnouncement\"] = 5] = \"GuildAnnouncement\";\n /**\n * A temporary sub-channel within a Guild Announcement channel\n */\n ChannelType[ChannelType[\"AnnouncementThread\"] = 10] = \"AnnouncementThread\";\n /**\n * A temporary sub-channel within a Guild Text or Guild Forum channel\n */\n ChannelType[ChannelType[\"PublicThread\"] = 11] = \"PublicThread\";\n /**\n * A temporary sub-channel within a Guild Text channel that is only viewable by those invited and those with the Manage Threads permission\n */\n ChannelType[ChannelType[\"PrivateThread\"] = 12] = \"PrivateThread\";\n /**\n * A voice channel for hosting events with an audience\n *\n * @see {@link https://support.discord.com/hc/articles/1500005513722}\n */\n ChannelType[ChannelType[\"GuildStageVoice\"] = 13] = \"GuildStageVoice\";\n /**\n * The channel in a Student Hub containing the listed servers\n *\n * @see {@link https://support.discord.com/hc/articles/4406046651927}\n */\n ChannelType[ChannelType[\"GuildDirectory\"] = 14] = \"GuildDirectory\";\n /**\n * A channel that can only contain threads\n */\n ChannelType[ChannelType[\"GuildForum\"] = 15] = \"GuildForum\";\n /**\n * A channel like forum channels but contains media for server subscriptions\n *\n * @see {@link https://creator-support.discord.com/hc/articles/14346342766743}\n */\n ChannelType[ChannelType[\"GuildMedia\"] = 16] = \"GuildMedia\";\n // EVERYTHING BELOW THIS LINE SHOULD BE OLD NAMES FOR RENAMED ENUM MEMBERS //\n /**\n * A channel that users can follow and crosspost into their own guild\n *\n * @deprecated This is the old name for {@link ChannelType.GuildAnnouncement}\n * @see {@link https://support.discord.com/hc/articles/360032008192}\n */\n ChannelType[ChannelType[\"GuildNews\"] = 5] = \"GuildNews\";\n /**\n * A temporary sub-channel within a Guild Announcement channel\n *\n * @deprecated This is the old name for {@link ChannelType.AnnouncementThread}\n */\n // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values\n ChannelType[ChannelType[\"GuildNewsThread\"] = 10] = \"GuildNewsThread\";\n /**\n * A temporary sub-channel within a Guild Text channel\n *\n * @deprecated This is the old name for {@link ChannelType.PublicThread}\n */\n ChannelType[ChannelType[\"GuildPublicThread\"] = 11] = \"GuildPublicThread\";\n /**\n * A temporary sub-channel within a Guild Text channel that is only viewable by those invited and those with the Manage Threads permission\n *\n * @deprecated This is the old name for {@link ChannelType.PrivateThread}\n */\n ChannelType[ChannelType[\"GuildPrivateThread\"] = 12] = \"GuildPrivateThread\";\n})(ChannelType || (exports.ChannelType = ChannelType = {}));\nvar VideoQualityMode;\n(function (VideoQualityMode) {\n /**\n * Discord chooses the quality for optimal performance\n */\n VideoQualityMode[VideoQualityMode[\"Auto\"] = 1] = \"Auto\";\n /**\n * 720p\n */\n VideoQualityMode[VideoQualityMode[\"Full\"] = 2] = \"Full\";\n})(VideoQualityMode || (exports.VideoQualityMode = VideoQualityMode = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/channel#message-object-message-types}\n */\nvar MessageType;\n(function (MessageType) {\n MessageType[MessageType[\"Default\"] = 0] = \"Default\";\n MessageType[MessageType[\"RecipientAdd\"] = 1] = \"RecipientAdd\";\n MessageType[MessageType[\"RecipientRemove\"] = 2] = \"RecipientRemove\";\n MessageType[MessageType[\"Call\"] = 3] = \"Call\";\n MessageType[MessageType[\"ChannelNameChange\"] = 4] = \"ChannelNameChange\";\n MessageType[MessageType[\"ChannelIconChange\"] = 5] = \"ChannelIconChange\";\n MessageType[MessageType[\"ChannelPinnedMessage\"] = 6] = \"ChannelPinnedMessage\";\n MessageType[MessageType[\"UserJoin\"] = 7] = \"UserJoin\";\n MessageType[MessageType[\"GuildBoost\"] = 8] = \"GuildBoost\";\n MessageType[MessageType[\"GuildBoostTier1\"] = 9] = \"GuildBoostTier1\";\n MessageType[MessageType[\"GuildBoostTier2\"] = 10] = \"GuildBoostTier2\";\n MessageType[MessageType[\"GuildBoostTier3\"] = 11] = \"GuildBoostTier3\";\n MessageType[MessageType[\"ChannelFollowAdd\"] = 12] = \"ChannelFollowAdd\";\n MessageType[MessageType[\"GuildDiscoveryDisqualified\"] = 14] = \"GuildDiscoveryDisqualified\";\n MessageType[MessageType[\"GuildDiscoveryRequalified\"] = 15] = \"GuildDiscoveryRequalified\";\n MessageType[MessageType[\"GuildDiscoveryGracePeriodInitialWarning\"] = 16] = \"GuildDiscoveryGracePeriodInitialWarning\";\n MessageType[MessageType[\"GuildDiscoveryGracePeriodFinalWarning\"] = 17] = \"GuildDiscoveryGracePeriodFinalWarning\";\n MessageType[MessageType[\"ThreadCreated\"] = 18] = \"ThreadCreated\";\n MessageType[MessageType[\"Reply\"] = 19] = \"Reply\";\n MessageType[MessageType[\"ChatInputCommand\"] = 20] = \"ChatInputCommand\";\n MessageType[MessageType[\"ThreadStarterMessage\"] = 21] = \"ThreadStarterMessage\";\n MessageType[MessageType[\"GuildInviteReminder\"] = 22] = \"GuildInviteReminder\";\n MessageType[MessageType[\"ContextMenuCommand\"] = 23] = \"ContextMenuCommand\";\n MessageType[MessageType[\"AutoModerationAction\"] = 24] = \"AutoModerationAction\";\n MessageType[MessageType[\"RoleSubscriptionPurchase\"] = 25] = \"RoleSubscriptionPurchase\";\n MessageType[MessageType[\"InteractionPremiumUpsell\"] = 26] = \"InteractionPremiumUpsell\";\n MessageType[MessageType[\"StageStart\"] = 27] = \"StageStart\";\n MessageType[MessageType[\"StageEnd\"] = 28] = \"StageEnd\";\n MessageType[MessageType[\"StageSpeaker\"] = 29] = \"StageSpeaker\";\n /**\n * @unstable https://github.com/discord/discord-api-docs/pull/5927#discussion_r1107678548\n */\n MessageType[MessageType[\"StageRaiseHand\"] = 30] = \"StageRaiseHand\";\n MessageType[MessageType[\"StageTopic\"] = 31] = \"StageTopic\";\n MessageType[MessageType[\"GuildApplicationPremiumSubscription\"] = 32] = \"GuildApplicationPremiumSubscription\";\n MessageType[MessageType[\"GuildIncidentAlertModeEnabled\"] = 36] = \"GuildIncidentAlertModeEnabled\";\n MessageType[MessageType[\"GuildIncidentAlertModeDisabled\"] = 37] = \"GuildIncidentAlertModeDisabled\";\n MessageType[MessageType[\"GuildIncidentReportRaid\"] = 38] = \"GuildIncidentReportRaid\";\n MessageType[MessageType[\"GuildIncidentReportFalseAlarm\"] = 39] = \"GuildIncidentReportFalseAlarm\";\n MessageType[MessageType[\"PurchaseNotification\"] = 44] = \"PurchaseNotification\";\n MessageType[MessageType[\"PollResult\"] = 46] = \"PollResult\";\n})(MessageType || (exports.MessageType = MessageType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/channel#message-object-message-activity-types}\n */\nvar MessageActivityType;\n(function (MessageActivityType) {\n MessageActivityType[MessageActivityType[\"Join\"] = 1] = \"Join\";\n MessageActivityType[MessageActivityType[\"Spectate\"] = 2] = \"Spectate\";\n MessageActivityType[MessageActivityType[\"Listen\"] = 3] = \"Listen\";\n MessageActivityType[MessageActivityType[\"JoinRequest\"] = 5] = \"JoinRequest\";\n})(MessageActivityType || (exports.MessageActivityType = MessageActivityType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/channel#message-reference-types}\n */\nvar MessageReferenceType;\n(function (MessageReferenceType) {\n /**\n * A standard reference used by replies\n */\n MessageReferenceType[MessageReferenceType[\"Default\"] = 0] = \"Default\";\n /**\n * Reference used to point to a message at a point in time\n */\n MessageReferenceType[MessageReferenceType[\"Forward\"] = 1] = \"Forward\";\n})(MessageReferenceType || (exports.MessageReferenceType = MessageReferenceType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/channel#message-object-message-flags}\n */\nvar MessageFlags;\n(function (MessageFlags) {\n /**\n * This message has been published to subscribed channels (via Channel Following)\n */\n MessageFlags[MessageFlags[\"Crossposted\"] = 1] = \"Crossposted\";\n /**\n * This message originated from a message in another channel (via Channel Following)\n */\n MessageFlags[MessageFlags[\"IsCrosspost\"] = 2] = \"IsCrosspost\";\n /**\n * Do not include any embeds when serializing this message\n */\n MessageFlags[MessageFlags[\"SuppressEmbeds\"] = 4] = \"SuppressEmbeds\";\n /**\n * The source message for this crosspost has been deleted (via Channel Following)\n */\n MessageFlags[MessageFlags[\"SourceMessageDeleted\"] = 8] = \"SourceMessageDeleted\";\n /**\n * This message came from the urgent message system\n */\n MessageFlags[MessageFlags[\"Urgent\"] = 16] = \"Urgent\";\n /**\n * This message has an associated thread, which shares its id\n */\n MessageFlags[MessageFlags[\"HasThread\"] = 32] = \"HasThread\";\n /**\n * This message is only visible to the user who invoked the Interaction\n */\n MessageFlags[MessageFlags[\"Ephemeral\"] = 64] = \"Ephemeral\";\n /**\n * This message is an Interaction Response and the bot is \"thinking\"\n */\n MessageFlags[MessageFlags[\"Loading\"] = 128] = \"Loading\";\n /**\n * This message failed to mention some roles and add their members to the thread\n */\n MessageFlags[MessageFlags[\"FailedToMentionSomeRolesInThread\"] = 256] = \"FailedToMentionSomeRolesInThread\";\n /**\n * @unstable This message flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n */\n MessageFlags[MessageFlags[\"ShouldShowLinkNotDiscordWarning\"] = 1024] = \"ShouldShowLinkNotDiscordWarning\";\n /**\n * This message will not trigger push and desktop notifications\n */\n MessageFlags[MessageFlags[\"SuppressNotifications\"] = 4096] = \"SuppressNotifications\";\n /**\n * This message is a voice message\n */\n MessageFlags[MessageFlags[\"IsVoiceMessage\"] = 8192] = \"IsVoiceMessage\";\n /**\n * This message has a snapshot (via Message Forwarding)\n */\n MessageFlags[MessageFlags[\"HasSnapshot\"] = 16384] = \"HasSnapshot\";\n})(MessageFlags || (exports.MessageFlags = MessageFlags = {}));\nvar OverwriteType;\n(function (OverwriteType) {\n OverwriteType[OverwriteType[\"Role\"] = 0] = \"Role\";\n OverwriteType[OverwriteType[\"Member\"] = 1] = \"Member\";\n})(OverwriteType || (exports.OverwriteType = OverwriteType = {}));\nvar ThreadAutoArchiveDuration;\n(function (ThreadAutoArchiveDuration) {\n ThreadAutoArchiveDuration[ThreadAutoArchiveDuration[\"OneHour\"] = 60] = \"OneHour\";\n ThreadAutoArchiveDuration[ThreadAutoArchiveDuration[\"OneDay\"] = 1440] = \"OneDay\";\n ThreadAutoArchiveDuration[ThreadAutoArchiveDuration[\"ThreeDays\"] = 4320] = \"ThreeDays\";\n ThreadAutoArchiveDuration[ThreadAutoArchiveDuration[\"OneWeek\"] = 10080] = \"OneWeek\";\n})(ThreadAutoArchiveDuration || (exports.ThreadAutoArchiveDuration = ThreadAutoArchiveDuration = {}));\nvar ThreadMemberFlags;\n(function (ThreadMemberFlags) {\n /**\n * @unstable This thread member flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n */\n ThreadMemberFlags[ThreadMemberFlags[\"HasInteracted\"] = 1] = \"HasInteracted\";\n /**\n * @unstable This thread member flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n */\n ThreadMemberFlags[ThreadMemberFlags[\"AllMessages\"] = 2] = \"AllMessages\";\n /**\n * @unstable This thread member flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n */\n ThreadMemberFlags[ThreadMemberFlags[\"OnlyMentions\"] = 4] = \"OnlyMentions\";\n /**\n * @unstable This thread member flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n */\n ThreadMemberFlags[ThreadMemberFlags[\"NoMessages\"] = 8] = \"NoMessages\";\n})(ThreadMemberFlags || (exports.ThreadMemberFlags = ThreadMemberFlags = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/channel#embed-object-embed-types}\n */\nvar EmbedType;\n(function (EmbedType) {\n /**\n * Generic embed rendered from embed attributes\n */\n EmbedType[\"Rich\"] = \"rich\";\n /**\n * Image embed\n */\n EmbedType[\"Image\"] = \"image\";\n /**\n * Video embed\n */\n EmbedType[\"Video\"] = \"video\";\n /**\n * Animated gif image embed rendered as a video embed\n */\n EmbedType[\"GIFV\"] = \"gifv\";\n /**\n * Article embed\n */\n EmbedType[\"Article\"] = \"article\";\n /**\n * Link embed\n */\n EmbedType[\"Link\"] = \"link\";\n /**\n * Auto moderation alert embed\n *\n * @unstable This embed type is currently not documented by Discord, but it is returned in the auto moderation system messages.\n */\n EmbedType[\"AutoModerationMessage\"] = \"auto_moderation_message\";\n /**\n * Poll result embed\n */\n EmbedType[\"PollResult\"] = \"poll_result\";\n})(EmbedType || (exports.EmbedType = EmbedType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/channel#attachment-object-attachment-structure-attachment-flags}\n */\nvar AttachmentFlags;\n(function (AttachmentFlags) {\n /**\n * This attachment has been edited using the remix feature on mobile\n */\n AttachmentFlags[AttachmentFlags[\"IsRemix\"] = 4] = \"IsRemix\";\n})(AttachmentFlags || (exports.AttachmentFlags = AttachmentFlags = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/channel#allowed-mentions-object-allowed-mention-types}\n */\nvar AllowedMentionsTypes;\n(function (AllowedMentionsTypes) {\n /**\n * Controls `@everyone` and `@here` mentions\n */\n AllowedMentionsTypes[\"Everyone\"] = \"everyone\";\n /**\n * Controls role mentions\n */\n AllowedMentionsTypes[\"Role\"] = \"roles\";\n /**\n * Controls user mentions\n */\n AllowedMentionsTypes[\"User\"] = \"users\";\n})(AllowedMentionsTypes || (exports.AllowedMentionsTypes = AllowedMentionsTypes = {}));\n/**\n * @see {@link https://discord.com/developers/docs/interactions/message-components#component-object-component-types}\n */\nvar ComponentType;\n(function (ComponentType) {\n /**\n * Action Row component\n */\n ComponentType[ComponentType[\"ActionRow\"] = 1] = \"ActionRow\";\n /**\n * Button component\n */\n ComponentType[ComponentType[\"Button\"] = 2] = \"Button\";\n /**\n * Select menu for picking from defined text options\n */\n ComponentType[ComponentType[\"StringSelect\"] = 3] = \"StringSelect\";\n /**\n * Text Input component\n */\n ComponentType[ComponentType[\"TextInput\"] = 4] = \"TextInput\";\n /**\n * Select menu for users\n */\n ComponentType[ComponentType[\"UserSelect\"] = 5] = \"UserSelect\";\n /**\n * Select menu for roles\n */\n ComponentType[ComponentType[\"RoleSelect\"] = 6] = \"RoleSelect\";\n /**\n * Select menu for users and roles\n */\n ComponentType[ComponentType[\"MentionableSelect\"] = 7] = \"MentionableSelect\";\n /**\n * Select menu for channels\n */\n ComponentType[ComponentType[\"ChannelSelect\"] = 8] = \"ChannelSelect\";\n // EVERYTHING BELOW THIS LINE SHOULD BE OLD NAMES FOR RENAMED ENUM MEMBERS //\n /**\n * Select menu for picking from defined text options\n *\n * @deprecated This is the old name for {@link ComponentType.StringSelect}\n */\n ComponentType[ComponentType[\"SelectMenu\"] = 3] = \"SelectMenu\";\n})(ComponentType || (exports.ComponentType = ComponentType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/interactions/message-components#button-object-button-styles}\n */\nvar ButtonStyle;\n(function (ButtonStyle) {\n ButtonStyle[ButtonStyle[\"Primary\"] = 1] = \"Primary\";\n ButtonStyle[ButtonStyle[\"Secondary\"] = 2] = \"Secondary\";\n ButtonStyle[ButtonStyle[\"Success\"] = 3] = \"Success\";\n ButtonStyle[ButtonStyle[\"Danger\"] = 4] = \"Danger\";\n ButtonStyle[ButtonStyle[\"Link\"] = 5] = \"Link\";\n ButtonStyle[ButtonStyle[\"Premium\"] = 6] = \"Premium\";\n})(ButtonStyle || (exports.ButtonStyle = ButtonStyle = {}));\n/**\n * @see {@link https://discord.com/developers/docs/interactions/message-components#text-inputs-text-input-styles}\n */\nvar TextInputStyle;\n(function (TextInputStyle) {\n TextInputStyle[TextInputStyle[\"Short\"] = 1] = \"Short\";\n TextInputStyle[TextInputStyle[\"Paragraph\"] = 2] = \"Paragraph\";\n})(TextInputStyle || (exports.TextInputStyle = TextInputStyle = {}));\n/**\n * @see {@link https://discord.com/developers/docs/interactions/message-components#select-menu-object-select-default-value-structure}\n */\nvar SelectMenuDefaultValueType;\n(function (SelectMenuDefaultValueType) {\n SelectMenuDefaultValueType[\"Channel\"] = \"channel\";\n SelectMenuDefaultValueType[\"Role\"] = \"role\";\n SelectMenuDefaultValueType[\"User\"] = \"user\";\n})(SelectMenuDefaultValueType || (exports.SelectMenuDefaultValueType = SelectMenuDefaultValueType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/channel#channel-object-channel-flags}\n */\nvar ChannelFlags;\n(function (ChannelFlags) {\n /**\n * @unstable This channel flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n */\n ChannelFlags[ChannelFlags[\"GuildFeedRemoved\"] = 1] = \"GuildFeedRemoved\";\n /**\n * This thread is pinned to the top of its parent forum channel\n */\n ChannelFlags[ChannelFlags[\"Pinned\"] = 2] = \"Pinned\";\n /**\n * @unstable This channel flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n */\n ChannelFlags[ChannelFlags[\"ActiveChannelsRemoved\"] = 4] = \"ActiveChannelsRemoved\";\n /**\n * Whether a tag is required to be specified when creating a thread in a forum channel.\n * Tags are specified in the `applied_tags` field\n */\n ChannelFlags[ChannelFlags[\"RequireTag\"] = 16] = \"RequireTag\";\n /**\n * @unstable This channel flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n */\n ChannelFlags[ChannelFlags[\"IsSpam\"] = 32] = \"IsSpam\";\n /**\n * @unstable This channel flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n */\n ChannelFlags[ChannelFlags[\"IsGuildResourceChannel\"] = 128] = \"IsGuildResourceChannel\";\n /**\n * @unstable This channel flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n */\n ChannelFlags[ChannelFlags[\"ClydeAI\"] = 256] = \"ClydeAI\";\n /**\n * @unstable This channel flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n */\n ChannelFlags[ChannelFlags[\"IsScheduledForDeletion\"] = 512] = \"IsScheduledForDeletion\";\n /**\n * Whether media download options are hidden.\n */\n ChannelFlags[ChannelFlags[\"HideMediaDownloadOptions\"] = 32768] = \"HideMediaDownloadOptions\";\n})(ChannelFlags || (exports.ChannelFlags = ChannelFlags = {}));\n//# sourceMappingURL=channel.js.map",
|
|
13
|
+
"\"use strict\";\n/**\n * Types extracted from https://discord.com/developers/docs/resources/emoji\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=emoji.js.map",
|
|
14
|
+
"\"use strict\";\n/**\n * Types extracted from\n * - https://discord.com/developers/docs/topics/gateway\n * - https://discord.com/developers/docs/topics/gateway-events\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.ActivityFlags = exports.ActivityType = exports.ActivityPlatform = exports.PresenceUpdateStatus = void 0;\n/**\n * @see {@link https://discord.com/developers/docs/topics/gateway-events#update-presence-status-types}\n */\nvar PresenceUpdateStatus;\n(function (PresenceUpdateStatus) {\n PresenceUpdateStatus[\"Online\"] = \"online\";\n PresenceUpdateStatus[\"DoNotDisturb\"] = \"dnd\";\n PresenceUpdateStatus[\"Idle\"] = \"idle\";\n /**\n * Invisible and shown as offline\n */\n PresenceUpdateStatus[\"Invisible\"] = \"invisible\";\n PresenceUpdateStatus[\"Offline\"] = \"offline\";\n})(PresenceUpdateStatus || (exports.PresenceUpdateStatus = PresenceUpdateStatus = {}));\n/**\n * @unstable This enum is currently not documented by Discord but has known values which we will try to keep up to date.\n * Values might be added or removed without a major version bump.\n */\nvar ActivityPlatform;\n(function (ActivityPlatform) {\n ActivityPlatform[\"Desktop\"] = \"desktop\";\n ActivityPlatform[\"Xbox\"] = \"xbox\";\n ActivityPlatform[\"Samsung\"] = \"samsung\";\n ActivityPlatform[\"IOS\"] = \"ios\";\n ActivityPlatform[\"Android\"] = \"android\";\n ActivityPlatform[\"Embedded\"] = \"embedded\";\n ActivityPlatform[\"PS4\"] = \"ps4\";\n ActivityPlatform[\"PS5\"] = \"ps5\";\n})(ActivityPlatform || (exports.ActivityPlatform = ActivityPlatform = {}));\n/**\n * @see {@link https://discord.com/developers/docs/topics/gateway-events#activity-object-activity-types}\n */\nvar ActivityType;\n(function (ActivityType) {\n /**\n * Playing \\{game\\}\n */\n ActivityType[ActivityType[\"Playing\"] = 0] = \"Playing\";\n /**\n * Streaming \\{details\\}\n */\n ActivityType[ActivityType[\"Streaming\"] = 1] = \"Streaming\";\n /**\n * Listening to \\{name\\}\n */\n ActivityType[ActivityType[\"Listening\"] = 2] = \"Listening\";\n /**\n * Watching \\{details\\}\n */\n ActivityType[ActivityType[\"Watching\"] = 3] = \"Watching\";\n /**\n * \\{emoji\\} \\{state\\}\n */\n ActivityType[ActivityType[\"Custom\"] = 4] = \"Custom\";\n /**\n * Competing in \\{name\\}\n */\n ActivityType[ActivityType[\"Competing\"] = 5] = \"Competing\";\n})(ActivityType || (exports.ActivityType = ActivityType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/topics/gateway-events#activity-object-activity-flags}\n */\nvar ActivityFlags;\n(function (ActivityFlags) {\n ActivityFlags[ActivityFlags[\"Instance\"] = 1] = \"Instance\";\n ActivityFlags[ActivityFlags[\"Join\"] = 2] = \"Join\";\n ActivityFlags[ActivityFlags[\"Spectate\"] = 4] = \"Spectate\";\n ActivityFlags[ActivityFlags[\"JoinRequest\"] = 8] = \"JoinRequest\";\n ActivityFlags[ActivityFlags[\"Sync\"] = 16] = \"Sync\";\n ActivityFlags[ActivityFlags[\"Play\"] = 32] = \"Play\";\n ActivityFlags[ActivityFlags[\"PartyPrivacyFriends\"] = 64] = \"PartyPrivacyFriends\";\n ActivityFlags[ActivityFlags[\"PartyPrivacyVoiceChannel\"] = 128] = \"PartyPrivacyVoiceChannel\";\n ActivityFlags[ActivityFlags[\"Embedded\"] = 256] = \"Embedded\";\n})(ActivityFlags || (exports.ActivityFlags = ActivityFlags = {}));\n//# sourceMappingURL=gateway.js.map",
|
|
15
|
+
"\"use strict\";\n/**\n * Types extracted from https://discord.com/developers/docs/resources/guild\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.GuildOnboardingPromptType = exports.GuildOnboardingMode = exports.MembershipScreeningFieldType = exports.GuildWidgetStyle = exports.IntegrationExpireBehavior = exports.GuildMemberFlags = exports.GuildFeature = exports.GuildSystemChannelFlags = exports.GuildHubType = exports.GuildPremiumTier = exports.GuildVerificationLevel = exports.GuildNSFWLevel = exports.GuildMFALevel = exports.GuildExplicitContentFilter = exports.GuildDefaultMessageNotifications = void 0;\n/**\n * @see {@link https://discord.com/developers/docs/resources/guild#guild-object-default-message-notification-level}\n */\nvar GuildDefaultMessageNotifications;\n(function (GuildDefaultMessageNotifications) {\n GuildDefaultMessageNotifications[GuildDefaultMessageNotifications[\"AllMessages\"] = 0] = \"AllMessages\";\n GuildDefaultMessageNotifications[GuildDefaultMessageNotifications[\"OnlyMentions\"] = 1] = \"OnlyMentions\";\n})(GuildDefaultMessageNotifications || (exports.GuildDefaultMessageNotifications = GuildDefaultMessageNotifications = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/guild#guild-object-explicit-content-filter-level}\n */\nvar GuildExplicitContentFilter;\n(function (GuildExplicitContentFilter) {\n GuildExplicitContentFilter[GuildExplicitContentFilter[\"Disabled\"] = 0] = \"Disabled\";\n GuildExplicitContentFilter[GuildExplicitContentFilter[\"MembersWithoutRoles\"] = 1] = \"MembersWithoutRoles\";\n GuildExplicitContentFilter[GuildExplicitContentFilter[\"AllMembers\"] = 2] = \"AllMembers\";\n})(GuildExplicitContentFilter || (exports.GuildExplicitContentFilter = GuildExplicitContentFilter = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/guild#guild-object-mfa-level}\n */\nvar GuildMFALevel;\n(function (GuildMFALevel) {\n GuildMFALevel[GuildMFALevel[\"None\"] = 0] = \"None\";\n GuildMFALevel[GuildMFALevel[\"Elevated\"] = 1] = \"Elevated\";\n})(GuildMFALevel || (exports.GuildMFALevel = GuildMFALevel = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/guild#guild-object-guild-nsfw-level}\n */\nvar GuildNSFWLevel;\n(function (GuildNSFWLevel) {\n GuildNSFWLevel[GuildNSFWLevel[\"Default\"] = 0] = \"Default\";\n GuildNSFWLevel[GuildNSFWLevel[\"Explicit\"] = 1] = \"Explicit\";\n GuildNSFWLevel[GuildNSFWLevel[\"Safe\"] = 2] = \"Safe\";\n GuildNSFWLevel[GuildNSFWLevel[\"AgeRestricted\"] = 3] = \"AgeRestricted\";\n})(GuildNSFWLevel || (exports.GuildNSFWLevel = GuildNSFWLevel = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/guild#guild-object-verification-level}\n */\nvar GuildVerificationLevel;\n(function (GuildVerificationLevel) {\n /**\n * Unrestricted\n */\n GuildVerificationLevel[GuildVerificationLevel[\"None\"] = 0] = \"None\";\n /**\n * Must have verified email on account\n */\n GuildVerificationLevel[GuildVerificationLevel[\"Low\"] = 1] = \"Low\";\n /**\n * Must be registered on Discord for longer than 5 minutes\n */\n GuildVerificationLevel[GuildVerificationLevel[\"Medium\"] = 2] = \"Medium\";\n /**\n * Must be a member of the guild for longer than 10 minutes\n */\n GuildVerificationLevel[GuildVerificationLevel[\"High\"] = 3] = \"High\";\n /**\n * Must have a verified phone number\n */\n GuildVerificationLevel[GuildVerificationLevel[\"VeryHigh\"] = 4] = \"VeryHigh\";\n})(GuildVerificationLevel || (exports.GuildVerificationLevel = GuildVerificationLevel = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/guild#guild-object-premium-tier}\n */\nvar GuildPremiumTier;\n(function (GuildPremiumTier) {\n GuildPremiumTier[GuildPremiumTier[\"None\"] = 0] = \"None\";\n GuildPremiumTier[GuildPremiumTier[\"Tier1\"] = 1] = \"Tier1\";\n GuildPremiumTier[GuildPremiumTier[\"Tier2\"] = 2] = \"Tier2\";\n GuildPremiumTier[GuildPremiumTier[\"Tier3\"] = 3] = \"Tier3\";\n})(GuildPremiumTier || (exports.GuildPremiumTier = GuildPremiumTier = {}));\nvar GuildHubType;\n(function (GuildHubType) {\n GuildHubType[GuildHubType[\"Default\"] = 0] = \"Default\";\n GuildHubType[GuildHubType[\"HighSchool\"] = 1] = \"HighSchool\";\n GuildHubType[GuildHubType[\"College\"] = 2] = \"College\";\n})(GuildHubType || (exports.GuildHubType = GuildHubType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/guild#guild-object-system-channel-flags}\n */\nvar GuildSystemChannelFlags;\n(function (GuildSystemChannelFlags) {\n /**\n * Suppress member join notifications\n */\n GuildSystemChannelFlags[GuildSystemChannelFlags[\"SuppressJoinNotifications\"] = 1] = \"SuppressJoinNotifications\";\n /**\n * Suppress server boost notifications\n */\n GuildSystemChannelFlags[GuildSystemChannelFlags[\"SuppressPremiumSubscriptions\"] = 2] = \"SuppressPremiumSubscriptions\";\n /**\n * Suppress server setup tips\n */\n GuildSystemChannelFlags[GuildSystemChannelFlags[\"SuppressGuildReminderNotifications\"] = 4] = \"SuppressGuildReminderNotifications\";\n /**\n * Hide member join sticker reply buttons\n */\n GuildSystemChannelFlags[GuildSystemChannelFlags[\"SuppressJoinNotificationReplies\"] = 8] = \"SuppressJoinNotificationReplies\";\n /**\n * Suppress role subscription purchase and renewal notifications\n */\n GuildSystemChannelFlags[GuildSystemChannelFlags[\"SuppressRoleSubscriptionPurchaseNotifications\"] = 16] = \"SuppressRoleSubscriptionPurchaseNotifications\";\n /**\n * Hide role subscription sticker reply buttons\n */\n GuildSystemChannelFlags[GuildSystemChannelFlags[\"SuppressRoleSubscriptionPurchaseNotificationReplies\"] = 32] = \"SuppressRoleSubscriptionPurchaseNotificationReplies\";\n})(GuildSystemChannelFlags || (exports.GuildSystemChannelFlags = GuildSystemChannelFlags = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/guild#guild-object-guild-features}\n */\nvar GuildFeature;\n(function (GuildFeature) {\n /**\n * Guild has access to set an animated guild banner image\n */\n GuildFeature[\"AnimatedBanner\"] = \"ANIMATED_BANNER\";\n /**\n * Guild has access to set an animated guild icon\n */\n GuildFeature[\"AnimatedIcon\"] = \"ANIMATED_ICON\";\n /**\n * Guild is using the old permissions configuration behavior\n *\n * @see {@link https://discord.com/developers/docs/change-log#upcoming-application-command-permission-changes}\n */\n GuildFeature[\"ApplicationCommandPermissionsV2\"] = \"APPLICATION_COMMAND_PERMISSIONS_V2\";\n /**\n * Guild has set up auto moderation rules\n */\n GuildFeature[\"AutoModeration\"] = \"AUTO_MODERATION\";\n /**\n * Guild has access to set a guild banner image\n */\n GuildFeature[\"Banner\"] = \"BANNER\";\n /**\n * Guild can enable welcome screen, Membership Screening and discovery, and receives community updates\n */\n GuildFeature[\"Community\"] = \"COMMUNITY\";\n /**\n * Guild has enabled monetization\n */\n GuildFeature[\"CreatorMonetizableProvisional\"] = \"CREATOR_MONETIZABLE_PROVISIONAL\";\n /**\n * Guild has enabled the role subscription promo page\n */\n GuildFeature[\"CreatorStorePage\"] = \"CREATOR_STORE_PAGE\";\n /**\n * Guild has been set as a support server on the App Directory\n */\n GuildFeature[\"DeveloperSupportServer\"] = \"DEVELOPER_SUPPORT_SERVER\";\n /**\n * Guild is able to be discovered in the directory\n */\n GuildFeature[\"Discoverable\"] = \"DISCOVERABLE\";\n /**\n * Guild is able to be featured in the directory\n */\n GuildFeature[\"Featurable\"] = \"FEATURABLE\";\n /**\n * Guild is listed in a directory channel\n */\n GuildFeature[\"HasDirectoryEntry\"] = \"HAS_DIRECTORY_ENTRY\";\n /**\n * Guild is a Student Hub\n *\n * @see {@link https://support.discord.com/hc/articles/4406046651927}\n * @unstable This feature is currently not documented by Discord, but has known value\n */\n GuildFeature[\"Hub\"] = \"HUB\";\n /**\n * Guild has disabled invite usage, preventing users from joining\n */\n GuildFeature[\"InvitesDisabled\"] = \"INVITES_DISABLED\";\n /**\n * Guild has access to set an invite splash background\n */\n GuildFeature[\"InviteSplash\"] = \"INVITE_SPLASH\";\n /**\n * Guild is in a Student Hub\n *\n * @see {@link https://support.discord.com/hc/articles/4406046651927}\n * @unstable This feature is currently not documented by Discord, but has known value\n */\n GuildFeature[\"LinkedToHub\"] = \"LINKED_TO_HUB\";\n /**\n * Guild has enabled Membership Screening\n */\n GuildFeature[\"MemberVerificationGateEnabled\"] = \"MEMBER_VERIFICATION_GATE_ENABLED\";\n /**\n * Guild has increased custom soundboard sound slots\n */\n GuildFeature[\"MoreSoundboard\"] = \"MORE_SOUNDBOARD\";\n /**\n * Guild has enabled monetization\n *\n * @unstable This feature is no longer documented by Discord\n */\n GuildFeature[\"MonetizationEnabled\"] = \"MONETIZATION_ENABLED\";\n /**\n * Guild has increased custom sticker slots\n */\n GuildFeature[\"MoreStickers\"] = \"MORE_STICKERS\";\n /**\n * Guild has access to create news channels\n */\n GuildFeature[\"News\"] = \"NEWS\";\n /**\n * Guild is partnered\n */\n GuildFeature[\"Partnered\"] = \"PARTNERED\";\n /**\n * Guild can be previewed before joining via Membership Screening or the directory\n */\n GuildFeature[\"PreviewEnabled\"] = \"PREVIEW_ENABLED\";\n /**\n * Guild has access to create private threads\n */\n GuildFeature[\"PrivateThreads\"] = \"PRIVATE_THREADS\";\n /**\n * Guild has disabled alerts for join raids in the configured safety alerts channel\n */\n GuildFeature[\"RaidAlertsDisabled\"] = \"RAID_ALERTS_DISABLED\";\n GuildFeature[\"RelayEnabled\"] = \"RELAY_ENABLED\";\n /**\n * Guild is able to set role icons\n */\n GuildFeature[\"RoleIcons\"] = \"ROLE_ICONS\";\n /**\n * Guild has role subscriptions that can be purchased\n */\n GuildFeature[\"RoleSubscriptionsAvailableForPurchase\"] = \"ROLE_SUBSCRIPTIONS_AVAILABLE_FOR_PURCHASE\";\n /**\n * Guild has enabled role subscriptions\n */\n GuildFeature[\"RoleSubscriptionsEnabled\"] = \"ROLE_SUBSCRIPTIONS_ENABLED\";\n /**\n * Guild has created soundboard sounds\n */\n GuildFeature[\"Soundboard\"] = \"SOUNDBOARD\";\n /**\n * Guild has enabled ticketed events\n */\n GuildFeature[\"TicketedEventsEnabled\"] = \"TICKETED_EVENTS_ENABLED\";\n /**\n * Guild has access to set a vanity URL\n */\n GuildFeature[\"VanityURL\"] = \"VANITY_URL\";\n /**\n * Guild is verified\n */\n GuildFeature[\"Verified\"] = \"VERIFIED\";\n /**\n * Guild has access to set 384kbps bitrate in voice (previously VIP voice servers)\n */\n GuildFeature[\"VIPRegions\"] = \"VIP_REGIONS\";\n /**\n * Guild has enabled the welcome screen\n */\n GuildFeature[\"WelcomeScreenEnabled\"] = \"WELCOME_SCREEN_ENABLED\";\n})(GuildFeature || (exports.GuildFeature = GuildFeature = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/guild#guild-member-object-guild-member-flags}\n */\nvar GuildMemberFlags;\n(function (GuildMemberFlags) {\n /**\n * Member has left and rejoined the guild\n */\n GuildMemberFlags[GuildMemberFlags[\"DidRejoin\"] = 1] = \"DidRejoin\";\n /**\n * Member has completed onboarding\n */\n GuildMemberFlags[GuildMemberFlags[\"CompletedOnboarding\"] = 2] = \"CompletedOnboarding\";\n /**\n * Member is exempt from guild verification requirements\n */\n GuildMemberFlags[GuildMemberFlags[\"BypassesVerification\"] = 4] = \"BypassesVerification\";\n /**\n * Member has started onboarding\n */\n GuildMemberFlags[GuildMemberFlags[\"StartedOnboarding\"] = 8] = \"StartedOnboarding\";\n /**\n * Member is a guest and can only access the voice channel they were invited to\n */\n GuildMemberFlags[GuildMemberFlags[\"IsGuest\"] = 16] = \"IsGuest\";\n /**\n * Member has started Server Guide new member actions\n */\n GuildMemberFlags[GuildMemberFlags[\"StartedHomeActions\"] = 32] = \"StartedHomeActions\";\n /**\n * Member has completed Server Guide new member actions\n */\n GuildMemberFlags[GuildMemberFlags[\"CompletedHomeActions\"] = 64] = \"CompletedHomeActions\";\n /**\n * Member's username, display name, or nickname is blocked by AutoMod\n */\n GuildMemberFlags[GuildMemberFlags[\"AutomodQuarantinedUsernameOrGuildNickname\"] = 128] = \"AutomodQuarantinedUsernameOrGuildNickname\";\n /**\n * @deprecated\n * {@link https://github.com/discord/discord-api-docs/pull/7113 | discord-api-docs#7113}\n */\n GuildMemberFlags[GuildMemberFlags[\"AutomodQuarantinedBio\"] = 256] = \"AutomodQuarantinedBio\";\n /**\n * Member has dismissed the DM settings upsell\n */\n GuildMemberFlags[GuildMemberFlags[\"DmSettingsUpsellAcknowledged\"] = 512] = \"DmSettingsUpsellAcknowledged\";\n})(GuildMemberFlags || (exports.GuildMemberFlags = GuildMemberFlags = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/guild#integration-object-integration-expire-behaviors}\n */\nvar IntegrationExpireBehavior;\n(function (IntegrationExpireBehavior) {\n IntegrationExpireBehavior[IntegrationExpireBehavior[\"RemoveRole\"] = 0] = \"RemoveRole\";\n IntegrationExpireBehavior[IntegrationExpireBehavior[\"Kick\"] = 1] = \"Kick\";\n})(IntegrationExpireBehavior || (exports.IntegrationExpireBehavior = IntegrationExpireBehavior = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/guild#get-guild-widget-image-widget-style-options}\n */\nvar GuildWidgetStyle;\n(function (GuildWidgetStyle) {\n /**\n * Shield style widget with Discord icon and guild members online count\n */\n GuildWidgetStyle[\"Shield\"] = \"shield\";\n /**\n * Large image with guild icon, name and online count. \"POWERED BY DISCORD\" as the footer of the widget\n */\n GuildWidgetStyle[\"Banner1\"] = \"banner1\";\n /**\n * Smaller widget style with guild icon, name and online count. Split on the right with Discord logo\n */\n GuildWidgetStyle[\"Banner2\"] = \"banner2\";\n /**\n * Large image with guild icon, name and online count. In the footer, Discord logo on the left and \"Chat Now\" on the right\n */\n GuildWidgetStyle[\"Banner3\"] = \"banner3\";\n /**\n * Large Discord logo at the top of the widget. Guild icon, name and online count in the middle portion of the widget\n * and a \"JOIN MY SERVER\" button at the bottom\n */\n GuildWidgetStyle[\"Banner4\"] = \"banner4\";\n})(GuildWidgetStyle || (exports.GuildWidgetStyle = GuildWidgetStyle = {}));\nvar MembershipScreeningFieldType;\n(function (MembershipScreeningFieldType) {\n /**\n * Server Rules\n */\n MembershipScreeningFieldType[\"Terms\"] = \"TERMS\";\n})(MembershipScreeningFieldType || (exports.MembershipScreeningFieldType = MembershipScreeningFieldType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/guild#guild-onboarding-object-onboarding-mode}\n */\nvar GuildOnboardingMode;\n(function (GuildOnboardingMode) {\n /**\n * Counts only Default Channels towards constraints\n */\n GuildOnboardingMode[GuildOnboardingMode[\"OnboardingDefault\"] = 0] = \"OnboardingDefault\";\n /**\n * Counts Default Channels and Questions towards constraints\n */\n GuildOnboardingMode[GuildOnboardingMode[\"OnboardingAdvanced\"] = 1] = \"OnboardingAdvanced\";\n})(GuildOnboardingMode || (exports.GuildOnboardingMode = GuildOnboardingMode = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/guild#guild-onboarding-object-prompt-types}\n */\nvar GuildOnboardingPromptType;\n(function (GuildOnboardingPromptType) {\n GuildOnboardingPromptType[GuildOnboardingPromptType[\"MultipleChoice\"] = 0] = \"MultipleChoice\";\n GuildOnboardingPromptType[GuildOnboardingPromptType[\"Dropdown\"] = 1] = \"Dropdown\";\n})(GuildOnboardingPromptType || (exports.GuildOnboardingPromptType = GuildOnboardingPromptType = {}));\n//# sourceMappingURL=guild.js.map",
|
|
16
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.GuildScheduledEventPrivacyLevel = exports.GuildScheduledEventStatus = exports.GuildScheduledEventEntityType = exports.GuildScheduledEventRecurrenceRuleMonth = exports.GuildScheduledEventRecurrenceRuleWeekday = exports.GuildScheduledEventRecurrenceRuleFrequency = void 0;\n/**\n * @see {@link https://discord.com/developers/docs/resources/guild-scheduled-event#guild-scheduled-event-recurrence-rule-object-guild-scheduled-event-recurrence-rule-frequency}\n */\nvar GuildScheduledEventRecurrenceRuleFrequency;\n(function (GuildScheduledEventRecurrenceRuleFrequency) {\n GuildScheduledEventRecurrenceRuleFrequency[GuildScheduledEventRecurrenceRuleFrequency[\"Yearly\"] = 0] = \"Yearly\";\n GuildScheduledEventRecurrenceRuleFrequency[GuildScheduledEventRecurrenceRuleFrequency[\"Monthly\"] = 1] = \"Monthly\";\n GuildScheduledEventRecurrenceRuleFrequency[GuildScheduledEventRecurrenceRuleFrequency[\"Weekly\"] = 2] = \"Weekly\";\n GuildScheduledEventRecurrenceRuleFrequency[GuildScheduledEventRecurrenceRuleFrequency[\"Daily\"] = 3] = \"Daily\";\n})(GuildScheduledEventRecurrenceRuleFrequency || (exports.GuildScheduledEventRecurrenceRuleFrequency = GuildScheduledEventRecurrenceRuleFrequency = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/guild-scheduled-event#guild-scheduled-event-recurrence-rule-object-guild-scheduled-event-recurrence-rule-weekday}\n */\nvar GuildScheduledEventRecurrenceRuleWeekday;\n(function (GuildScheduledEventRecurrenceRuleWeekday) {\n GuildScheduledEventRecurrenceRuleWeekday[GuildScheduledEventRecurrenceRuleWeekday[\"Monday\"] = 0] = \"Monday\";\n GuildScheduledEventRecurrenceRuleWeekday[GuildScheduledEventRecurrenceRuleWeekday[\"Tuesday\"] = 1] = \"Tuesday\";\n GuildScheduledEventRecurrenceRuleWeekday[GuildScheduledEventRecurrenceRuleWeekday[\"Wednesday\"] = 2] = \"Wednesday\";\n GuildScheduledEventRecurrenceRuleWeekday[GuildScheduledEventRecurrenceRuleWeekday[\"Thursday\"] = 3] = \"Thursday\";\n GuildScheduledEventRecurrenceRuleWeekday[GuildScheduledEventRecurrenceRuleWeekday[\"Friday\"] = 4] = \"Friday\";\n GuildScheduledEventRecurrenceRuleWeekday[GuildScheduledEventRecurrenceRuleWeekday[\"Saturday\"] = 5] = \"Saturday\";\n GuildScheduledEventRecurrenceRuleWeekday[GuildScheduledEventRecurrenceRuleWeekday[\"Sunday\"] = 6] = \"Sunday\";\n})(GuildScheduledEventRecurrenceRuleWeekday || (exports.GuildScheduledEventRecurrenceRuleWeekday = GuildScheduledEventRecurrenceRuleWeekday = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/guild-scheduled-event#guild-scheduled-event-recurrence-rule-object-guild-scheduled-event-recurrence-rule-month}\n */\nvar GuildScheduledEventRecurrenceRuleMonth;\n(function (GuildScheduledEventRecurrenceRuleMonth) {\n GuildScheduledEventRecurrenceRuleMonth[GuildScheduledEventRecurrenceRuleMonth[\"January\"] = 1] = \"January\";\n GuildScheduledEventRecurrenceRuleMonth[GuildScheduledEventRecurrenceRuleMonth[\"February\"] = 2] = \"February\";\n GuildScheduledEventRecurrenceRuleMonth[GuildScheduledEventRecurrenceRuleMonth[\"March\"] = 3] = \"March\";\n GuildScheduledEventRecurrenceRuleMonth[GuildScheduledEventRecurrenceRuleMonth[\"April\"] = 4] = \"April\";\n GuildScheduledEventRecurrenceRuleMonth[GuildScheduledEventRecurrenceRuleMonth[\"May\"] = 5] = \"May\";\n GuildScheduledEventRecurrenceRuleMonth[GuildScheduledEventRecurrenceRuleMonth[\"June\"] = 6] = \"June\";\n GuildScheduledEventRecurrenceRuleMonth[GuildScheduledEventRecurrenceRuleMonth[\"July\"] = 7] = \"July\";\n GuildScheduledEventRecurrenceRuleMonth[GuildScheduledEventRecurrenceRuleMonth[\"August\"] = 8] = \"August\";\n GuildScheduledEventRecurrenceRuleMonth[GuildScheduledEventRecurrenceRuleMonth[\"September\"] = 9] = \"September\";\n GuildScheduledEventRecurrenceRuleMonth[GuildScheduledEventRecurrenceRuleMonth[\"October\"] = 10] = \"October\";\n GuildScheduledEventRecurrenceRuleMonth[GuildScheduledEventRecurrenceRuleMonth[\"November\"] = 11] = \"November\";\n GuildScheduledEventRecurrenceRuleMonth[GuildScheduledEventRecurrenceRuleMonth[\"December\"] = 12] = \"December\";\n})(GuildScheduledEventRecurrenceRuleMonth || (exports.GuildScheduledEventRecurrenceRuleMonth = GuildScheduledEventRecurrenceRuleMonth = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/guild-scheduled-event#guild-scheduled-event-object-guild-scheduled-event-entity-types}\n */\nvar GuildScheduledEventEntityType;\n(function (GuildScheduledEventEntityType) {\n GuildScheduledEventEntityType[GuildScheduledEventEntityType[\"StageInstance\"] = 1] = \"StageInstance\";\n GuildScheduledEventEntityType[GuildScheduledEventEntityType[\"Voice\"] = 2] = \"Voice\";\n GuildScheduledEventEntityType[GuildScheduledEventEntityType[\"External\"] = 3] = \"External\";\n})(GuildScheduledEventEntityType || (exports.GuildScheduledEventEntityType = GuildScheduledEventEntityType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/guild-scheduled-event#guild-scheduled-event-object-guild-scheduled-event-status}\n */\nvar GuildScheduledEventStatus;\n(function (GuildScheduledEventStatus) {\n GuildScheduledEventStatus[GuildScheduledEventStatus[\"Scheduled\"] = 1] = \"Scheduled\";\n GuildScheduledEventStatus[GuildScheduledEventStatus[\"Active\"] = 2] = \"Active\";\n GuildScheduledEventStatus[GuildScheduledEventStatus[\"Completed\"] = 3] = \"Completed\";\n GuildScheduledEventStatus[GuildScheduledEventStatus[\"Canceled\"] = 4] = \"Canceled\";\n})(GuildScheduledEventStatus || (exports.GuildScheduledEventStatus = GuildScheduledEventStatus = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/guild-scheduled-event#guild-scheduled-event-object-guild-scheduled-event-privacy-level}\n */\nvar GuildScheduledEventPrivacyLevel;\n(function (GuildScheduledEventPrivacyLevel) {\n /**\n * The scheduled event is only accessible to guild members\n */\n GuildScheduledEventPrivacyLevel[GuildScheduledEventPrivacyLevel[\"GuildOnly\"] = 2] = \"GuildOnly\";\n})(GuildScheduledEventPrivacyLevel || (exports.GuildScheduledEventPrivacyLevel = GuildScheduledEventPrivacyLevel = {}));\n//# sourceMappingURL=guildScheduledEvent.js.map",
|
|
17
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=attachment.js.map",
|
|
18
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=base.js.map",
|
|
19
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=boolean.js.map",
|
|
20
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=channel.js.map",
|
|
21
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=integer.js.map",
|
|
22
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=mentionable.js.map",
|
|
23
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=number.js.map",
|
|
24
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=role.js.map",
|
|
25
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.ApplicationCommandOptionType = void 0;\n/**\n * @see {@link https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-option-type}\n */\nvar ApplicationCommandOptionType;\n(function (ApplicationCommandOptionType) {\n ApplicationCommandOptionType[ApplicationCommandOptionType[\"Subcommand\"] = 1] = \"Subcommand\";\n ApplicationCommandOptionType[ApplicationCommandOptionType[\"SubcommandGroup\"] = 2] = \"SubcommandGroup\";\n ApplicationCommandOptionType[ApplicationCommandOptionType[\"String\"] = 3] = \"String\";\n ApplicationCommandOptionType[ApplicationCommandOptionType[\"Integer\"] = 4] = \"Integer\";\n ApplicationCommandOptionType[ApplicationCommandOptionType[\"Boolean\"] = 5] = \"Boolean\";\n ApplicationCommandOptionType[ApplicationCommandOptionType[\"User\"] = 6] = \"User\";\n ApplicationCommandOptionType[ApplicationCommandOptionType[\"Channel\"] = 7] = \"Channel\";\n ApplicationCommandOptionType[ApplicationCommandOptionType[\"Role\"] = 8] = \"Role\";\n ApplicationCommandOptionType[ApplicationCommandOptionType[\"Mentionable\"] = 9] = \"Mentionable\";\n ApplicationCommandOptionType[ApplicationCommandOptionType[\"Number\"] = 10] = \"Number\";\n ApplicationCommandOptionType[ApplicationCommandOptionType[\"Attachment\"] = 11] = \"Attachment\";\n})(ApplicationCommandOptionType || (exports.ApplicationCommandOptionType = ApplicationCommandOptionType = {}));\n//# sourceMappingURL=shared.js.map",
|
|
26
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=string.js.map",
|
|
27
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=subcommand.js.map",
|
|
28
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=subcommandGroup.js.map",
|
|
29
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=user.js.map",
|
|
30
|
+
"\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __exportStar = (this && this.__exportStar) || function(m, exports) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\n__exportStar(require(\"./_chatInput/attachment\"), exports);\n__exportStar(require(\"./_chatInput/base\"), exports);\n__exportStar(require(\"./_chatInput/boolean\"), exports);\n__exportStar(require(\"./_chatInput/channel\"), exports);\n__exportStar(require(\"./_chatInput/integer\"), exports);\n__exportStar(require(\"./_chatInput/mentionable\"), exports);\n__exportStar(require(\"./_chatInput/number\"), exports);\n__exportStar(require(\"./_chatInput/role\"), exports);\n__exportStar(require(\"./_chatInput/shared\"), exports);\n__exportStar(require(\"./_chatInput/string\"), exports);\n__exportStar(require(\"./_chatInput/subcommand\"), exports);\n__exportStar(require(\"./_chatInput/subcommandGroup\"), exports);\n__exportStar(require(\"./_chatInput/user\"), exports);\n//# sourceMappingURL=chatInput.js.map",
|
|
31
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=contextMenu.js.map",
|
|
32
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.APIApplicationCommandPermissionsConstant = exports.ApplicationCommandPermissionType = void 0;\n/**\n * @see {@link https://discord.com/developers/docs/interactions/application-commands#application-command-permissions-object-application-command-permission-type}\n */\nvar ApplicationCommandPermissionType;\n(function (ApplicationCommandPermissionType) {\n ApplicationCommandPermissionType[ApplicationCommandPermissionType[\"Role\"] = 1] = \"Role\";\n ApplicationCommandPermissionType[ApplicationCommandPermissionType[\"User\"] = 2] = \"User\";\n ApplicationCommandPermissionType[ApplicationCommandPermissionType[\"Channel\"] = 3] = \"Channel\";\n})(ApplicationCommandPermissionType || (exports.ApplicationCommandPermissionType = ApplicationCommandPermissionType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/interactions/application-commands#application-command-permissions-object-application-command-permissions-constants}\n */\nexports.APIApplicationCommandPermissionsConstant = {\n // eslint-disable-next-line unicorn/prefer-native-coercion-functions\n Everyone: (guildId) => String(guildId),\n AllChannels: (guildId) => String(BigInt(guildId) - 1n),\n};\n//# sourceMappingURL=permissions.js.map",
|
|
33
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=entryPoint.js.map",
|
|
34
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=internals.js.map",
|
|
35
|
+
"\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __exportStar = (this && this.__exportStar) || function(m, exports) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.EntryPointCommandHandlerType = exports.InteractionContextType = exports.ApplicationIntegrationType = exports.ApplicationCommandType = void 0;\n__exportStar(require(\"./_applicationCommands/chatInput\"), exports);\n__exportStar(require(\"./_applicationCommands/contextMenu\"), exports);\n__exportStar(require(\"./_applicationCommands/permissions\"), exports);\n__exportStar(require(\"./_applicationCommands/entryPoint\"), exports);\n__exportStar(require(\"./_applicationCommands/internals\"), exports);\n/**\n * @see {@link https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-types}\n */\nvar ApplicationCommandType;\n(function (ApplicationCommandType) {\n /**\n * Slash commands; a text-based command that shows up when a user types `/`\n */\n ApplicationCommandType[ApplicationCommandType[\"ChatInput\"] = 1] = \"ChatInput\";\n /**\n * A UI-based command that shows up when you right click or tap on a user\n */\n ApplicationCommandType[ApplicationCommandType[\"User\"] = 2] = \"User\";\n /**\n * A UI-based command that shows up when you right click or tap on a message\n */\n ApplicationCommandType[ApplicationCommandType[\"Message\"] = 3] = \"Message\";\n /**\n * A UI-based command that represents the primary way to invoke an app's Activity\n */\n ApplicationCommandType[ApplicationCommandType[\"PrimaryEntryPoint\"] = 4] = \"PrimaryEntryPoint\";\n})(ApplicationCommandType || (exports.ApplicationCommandType = ApplicationCommandType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/application#application-object-application-integration-types}\n */\nvar ApplicationIntegrationType;\n(function (ApplicationIntegrationType) {\n /**\n * App is installable to servers\n */\n ApplicationIntegrationType[ApplicationIntegrationType[\"GuildInstall\"] = 0] = \"GuildInstall\";\n /**\n * App is installable to users\n */\n ApplicationIntegrationType[ApplicationIntegrationType[\"UserInstall\"] = 1] = \"UserInstall\";\n})(ApplicationIntegrationType || (exports.ApplicationIntegrationType = ApplicationIntegrationType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-interaction-context-types}\n */\nvar InteractionContextType;\n(function (InteractionContextType) {\n /**\n * Interaction can be used within servers\n */\n InteractionContextType[InteractionContextType[\"Guild\"] = 0] = \"Guild\";\n /**\n * Interaction can be used within DMs with the app's bot user\n */\n InteractionContextType[InteractionContextType[\"BotDM\"] = 1] = \"BotDM\";\n /**\n * Interaction can be used within Group DMs and DMs other than the app's bot user\n */\n InteractionContextType[InteractionContextType[\"PrivateChannel\"] = 2] = \"PrivateChannel\";\n})(InteractionContextType || (exports.InteractionContextType = InteractionContextType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/interactions/application-commands#application-command-object-entry-point-command-handler-types}\n */\nvar EntryPointCommandHandlerType;\n(function (EntryPointCommandHandlerType) {\n /**\n * The app handles the interaction using an interaction token\n */\n EntryPointCommandHandlerType[EntryPointCommandHandlerType[\"AppHandler\"] = 1] = \"AppHandler\";\n /**\n * Discord handles the interaction by launching an Activity and sending a follow-up message without coordinating with\n * the app\n */\n EntryPointCommandHandlerType[EntryPointCommandHandlerType[\"DiscordLaunchActivity\"] = 2] = \"DiscordLaunchActivity\";\n})(EntryPointCommandHandlerType || (exports.EntryPointCommandHandlerType = EntryPointCommandHandlerType = {}));\n//# sourceMappingURL=applicationCommands.js.map",
|
|
36
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=autocomplete.js.map",
|
|
37
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=base.js.map",
|
|
38
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=messageComponents.js.map",
|
|
39
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=modalSubmit.js.map",
|
|
40
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=ping.js.map",
|
|
41
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.InteractionResponseType = exports.InteractionType = void 0;\n/**\n * @see {@link https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-interaction-type}\n */\nvar InteractionType;\n(function (InteractionType) {\n InteractionType[InteractionType[\"Ping\"] = 1] = \"Ping\";\n InteractionType[InteractionType[\"ApplicationCommand\"] = 2] = \"ApplicationCommand\";\n InteractionType[InteractionType[\"MessageComponent\"] = 3] = \"MessageComponent\";\n InteractionType[InteractionType[\"ApplicationCommandAutocomplete\"] = 4] = \"ApplicationCommandAutocomplete\";\n InteractionType[InteractionType[\"ModalSubmit\"] = 5] = \"ModalSubmit\";\n})(InteractionType || (exports.InteractionType = InteractionType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-response-object-interaction-callback-type}\n */\nvar InteractionResponseType;\n(function (InteractionResponseType) {\n /**\n * ACK a `Ping`\n */\n InteractionResponseType[InteractionResponseType[\"Pong\"] = 1] = \"Pong\";\n /**\n * Respond to an interaction with a message\n */\n InteractionResponseType[InteractionResponseType[\"ChannelMessageWithSource\"] = 4] = \"ChannelMessageWithSource\";\n /**\n * ACK an interaction and edit to a response later, the user sees a loading state\n */\n InteractionResponseType[InteractionResponseType[\"DeferredChannelMessageWithSource\"] = 5] = \"DeferredChannelMessageWithSource\";\n /**\n * ACK a button interaction and update it to a loading state\n */\n InteractionResponseType[InteractionResponseType[\"DeferredMessageUpdate\"] = 6] = \"DeferredMessageUpdate\";\n /**\n * ACK a button interaction and edit the message to which the button was attached\n */\n InteractionResponseType[InteractionResponseType[\"UpdateMessage\"] = 7] = \"UpdateMessage\";\n /**\n * For autocomplete interactions\n */\n InteractionResponseType[InteractionResponseType[\"ApplicationCommandAutocompleteResult\"] = 8] = \"ApplicationCommandAutocompleteResult\";\n /**\n * Respond to an interaction with an modal for a user to fill-out\n */\n InteractionResponseType[InteractionResponseType[\"Modal\"] = 9] = \"Modal\";\n /**\n * Respond to an interaction with an upgrade button, only available for apps with monetization enabled\n *\n * @deprecated Send a button with Premium type instead.\n * {@link https://discord.com/developers/docs/change-log#premium-apps-new-premium-button-style-deep-linking-url-schemes | Learn more here}\n */\n InteractionResponseType[InteractionResponseType[\"PremiumRequired\"] = 10] = \"PremiumRequired\";\n /**\n * Launch the Activity associated with the app.\n *\n * @remarks\n * Only available for apps with Activities enabled\n */\n InteractionResponseType[InteractionResponseType[\"LaunchActivity\"] = 12] = \"LaunchActivity\";\n})(InteractionResponseType || (exports.InteractionResponseType = InteractionResponseType = {}));\n//# sourceMappingURL=responses.js.map",
|
|
42
|
+
"\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __exportStar = (this && this.__exportStar) || function(m, exports) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\n__exportStar(require(\"./_interactions/applicationCommands\"), exports);\n__exportStar(require(\"./_interactions/autocomplete\"), exports);\n__exportStar(require(\"./_interactions/base\"), exports);\n__exportStar(require(\"./_interactions/messageComponents\"), exports);\n__exportStar(require(\"./_interactions/modalSubmit\"), exports);\n__exportStar(require(\"./_interactions/ping\"), exports);\n__exportStar(require(\"./_interactions/responses\"), exports);\n//# sourceMappingURL=interactions.js.map",
|
|
43
|
+
"\"use strict\";\n/**\n * Types extracted from https://discord.com/developers/docs/resources/invite\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.InviteTargetType = exports.InviteType = void 0;\n/**\n * @see {@link https://discord.com/developers/docs/resources/invite#invite-object-invite-types}\n */\nvar InviteType;\n(function (InviteType) {\n InviteType[InviteType[\"Guild\"] = 0] = \"Guild\";\n InviteType[InviteType[\"GroupDM\"] = 1] = \"GroupDM\";\n InviteType[InviteType[\"Friend\"] = 2] = \"Friend\";\n})(InviteType || (exports.InviteType = InviteType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/invite#invite-object-invite-target-types}\n */\nvar InviteTargetType;\n(function (InviteTargetType) {\n InviteTargetType[InviteTargetType[\"Stream\"] = 1] = \"Stream\";\n InviteTargetType[InviteTargetType[\"EmbeddedApplication\"] = 2] = \"EmbeddedApplication\";\n})(InviteTargetType || (exports.InviteTargetType = InviteTargetType = {}));\n//# sourceMappingURL=invite.js.map",
|
|
44
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.SubscriptionStatus = exports.SKUType = exports.SKUFlags = exports.EntitlementType = void 0;\n/**\n * @see {@link https://discord.com/developers/docs/monetization/entitlements#entitlement-object-entitlement-types}\n */\nvar EntitlementType;\n(function (EntitlementType) {\n /**\n * Entitlement was purchased by user\n */\n EntitlementType[EntitlementType[\"Purchase\"] = 1] = \"Purchase\";\n /**\n * Entitlement for Discord Nitro subscription\n */\n EntitlementType[EntitlementType[\"PremiumSubscription\"] = 2] = \"PremiumSubscription\";\n /**\n * Entitlement was gifted by developer\n */\n EntitlementType[EntitlementType[\"DeveloperGift\"] = 3] = \"DeveloperGift\";\n /**\n * Entitlement was purchased by a dev in application test mode\n */\n EntitlementType[EntitlementType[\"TestModePurchase\"] = 4] = \"TestModePurchase\";\n /**\n * Entitlement was granted when the SKU was free\n */\n EntitlementType[EntitlementType[\"FreePurchase\"] = 5] = \"FreePurchase\";\n /**\n * Entitlement was gifted by another user\n */\n EntitlementType[EntitlementType[\"UserGift\"] = 6] = \"UserGift\";\n /**\n * Entitlement was claimed by user for free as a Nitro Subscriber\n */\n EntitlementType[EntitlementType[\"PremiumPurchase\"] = 7] = \"PremiumPurchase\";\n /**\n * Entitlement was purchased as an app subscription\n */\n EntitlementType[EntitlementType[\"ApplicationSubscription\"] = 8] = \"ApplicationSubscription\";\n})(EntitlementType || (exports.EntitlementType = EntitlementType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/monetization/skus#sku-object-sku-flags}\n */\nvar SKUFlags;\n(function (SKUFlags) {\n /**\n * SKU is available for purchase\n */\n SKUFlags[SKUFlags[\"Available\"] = 4] = \"Available\";\n /**\n * Recurring SKU that can be purchased by a user and applied to a single server.\n * Grants access to every user in that server.\n */\n SKUFlags[SKUFlags[\"GuildSubscription\"] = 128] = \"GuildSubscription\";\n /**\n * Recurring SKU purchased by a user for themselves. Grants access to the purchasing user in every server.\n */\n SKUFlags[SKUFlags[\"UserSubscription\"] = 256] = \"UserSubscription\";\n})(SKUFlags || (exports.SKUFlags = SKUFlags = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/sku#sku-object-sku-types}\n */\nvar SKUType;\n(function (SKUType) {\n /**\n * Durable one-time purchase\n */\n SKUType[SKUType[\"Durable\"] = 2] = \"Durable\";\n /**\n * Consumable one-time purchase\n */\n SKUType[SKUType[\"Consumable\"] = 3] = \"Consumable\";\n /**\n * Represents a recurring subscription\n */\n SKUType[SKUType[\"Subscription\"] = 5] = \"Subscription\";\n /**\n * System-generated group for each Subscription SKU created\n */\n SKUType[SKUType[\"SubscriptionGroup\"] = 6] = \"SubscriptionGroup\";\n})(SKUType || (exports.SKUType = SKUType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/subscription#subscription-statuses}\n */\nvar SubscriptionStatus;\n(function (SubscriptionStatus) {\n /**\n * Subscription is active and scheduled to renew.\n */\n SubscriptionStatus[SubscriptionStatus[\"Active\"] = 0] = \"Active\";\n /**\n * Subscription is active but will not renew.\n */\n SubscriptionStatus[SubscriptionStatus[\"Ending\"] = 1] = \"Ending\";\n /**\n * Subscription is inactive and not being charged.\n */\n SubscriptionStatus[SubscriptionStatus[\"Inactive\"] = 2] = \"Inactive\";\n})(SubscriptionStatus || (exports.SubscriptionStatus = SubscriptionStatus = {}));\n//# sourceMappingURL=monetization.js.map",
|
|
45
|
+
"\"use strict\";\n/**\n * Types extracted from https://discord.com/developers/docs/topics/oauth2\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.OAuth2Scopes = void 0;\nvar OAuth2Scopes;\n(function (OAuth2Scopes) {\n /**\n * For oauth2 bots, this puts the bot in the user's selected guild by default\n */\n OAuth2Scopes[\"Bot\"] = \"bot\";\n /**\n * Allows {@link https://discord.com/developers/docs/resources/user#get-user-connections | `/users/@me/connections`}\n * to return linked third-party accounts\n *\n * @see {@link https://discord.com/developers/docs/resources/user#get-user-connections}\n */\n OAuth2Scopes[\"Connections\"] = \"connections\";\n /**\n * Allows your app to see information about the user's DMs and group DMs - requires Discord approval\n */\n OAuth2Scopes[\"DMChannelsRead\"] = \"dm_channels.read\";\n /**\n * Enables {@link https://discord.com/developers/docs/resources/user#get-current-user | `/users/@me`} to return an `email`\n *\n * @see {@link https://discord.com/developers/docs/resources/user#get-current-user}\n */\n OAuth2Scopes[\"Email\"] = \"email\";\n /**\n * Allows {@link https://discord.com/developers/docs/resources/user#get-current-user | `/users/@me`} without `email`\n *\n * @see {@link https://discord.com/developers/docs/resources/user#get-current-user}\n */\n OAuth2Scopes[\"Identify\"] = \"identify\";\n /**\n * Allows {@link https://discord.com/developers/docs/resources/user#get-current-user-guilds | `/users/@me/guilds`}\n * to return basic information about all of a user's guilds\n *\n * @see {@link https://discord.com/developers/docs/resources/user#get-current-user-guilds}\n */\n OAuth2Scopes[\"Guilds\"] = \"guilds\";\n /**\n * Allows {@link https://discord.com/developers/docs/resources/guild#add-guild-member | `/guilds/[guild.id]/members/[user.id]`}\n * to be used for joining users to a guild\n *\n * @see {@link https://discord.com/developers/docs/resources/guild#add-guild-member}\n */\n OAuth2Scopes[\"GuildsJoin\"] = \"guilds.join\";\n /**\n * Allows /users/\\@me/guilds/\\{guild.id\\}/member to return a user's member information in a guild\n *\n * @see {@link https://discord.com/developers/docs/resources/user#get-current-user-guild-member}\n */\n OAuth2Scopes[\"GuildsMembersRead\"] = \"guilds.members.read\";\n /**\n * Allows your app to join users to a group dm\n *\n * @see {@link https://discord.com/developers/docs/resources/channel#group-dm-add-recipient}\n */\n OAuth2Scopes[\"GroupDMJoins\"] = \"gdm.join\";\n /**\n * For local rpc server api access, this allows you to read messages from all client channels\n * (otherwise restricted to channels/guilds your app creates)\n */\n OAuth2Scopes[\"MessagesRead\"] = \"messages.read\";\n /**\n * Allows your app to update a user's connection and metadata for the app\n */\n OAuth2Scopes[\"RoleConnectionsWrite\"] = \"role_connections.write\";\n /**\n * For local rpc server access, this allows you to control a user's local Discord client - requires Discord approval\n */\n OAuth2Scopes[\"RPC\"] = \"rpc\";\n /**\n * For local rpc server access, this allows you to update a user's activity - requires Discord approval\n */\n OAuth2Scopes[\"RPCActivitiesWrite\"] = \"rpc.activities.write\";\n /**\n * For local rpc server access, this allows you to read a user's voice settings and listen for voice events - requires Discord approval\n */\n OAuth2Scopes[\"RPCVoiceRead\"] = \"rpc.voice.read\";\n /**\n * For local rpc server access, this allows you to update a user's voice settings - requires Discord approval\n */\n OAuth2Scopes[\"RPCVoiceWrite\"] = \"rpc.voice.write\";\n /**\n * For local rpc server api access, this allows you to receive notifications pushed out to the user - requires Discord approval\n */\n OAuth2Scopes[\"RPCNotificationsRead\"] = \"rpc.notifications.read\";\n /**\n * This generates a webhook that is returned in the oauth token response for authorization code grants\n */\n OAuth2Scopes[\"WebhookIncoming\"] = \"webhook.incoming\";\n /**\n * Allows your app to connect to voice on user's behalf and see all the voice members - requires Discord approval\n */\n OAuth2Scopes[\"Voice\"] = \"voice\";\n /**\n * Allows your app to upload/update builds for a user's applications - requires Discord approval\n */\n OAuth2Scopes[\"ApplicationsBuildsUpload\"] = \"applications.builds.upload\";\n /**\n * Allows your app to read build data for a user's applications\n */\n OAuth2Scopes[\"ApplicationsBuildsRead\"] = \"applications.builds.read\";\n /**\n * Allows your app to read and update store data (SKUs, store listings, achievements, etc.) for a user's applications\n */\n OAuth2Scopes[\"ApplicationsStoreUpdate\"] = \"applications.store.update\";\n /**\n * Allows your app to read entitlements for a user's applications\n */\n OAuth2Scopes[\"ApplicationsEntitlements\"] = \"applications.entitlements\";\n /**\n * Allows your app to know a user's friends and implicit relationships - requires Discord approval\n */\n OAuth2Scopes[\"RelationshipsRead\"] = \"relationships.read\";\n /**\n * Allows your app to fetch data from a user's \"Now Playing/Recently Played\" list - requires Discord approval\n */\n OAuth2Scopes[\"ActivitiesRead\"] = \"activities.read\";\n /**\n * Allows your app to update a user's activity - requires Discord approval (NOT REQUIRED FOR GAMESDK ACTIVITY MANAGER)\n *\n * @see {@link https://discord.com/developers/docs/game-sdk/activities}\n */\n OAuth2Scopes[\"ActivitiesWrite\"] = \"activities.write\";\n /**\n * Allows your app to use Application Commands in a guild\n *\n * @see {@link https://discord.com/developers/docs/interactions/application-commands}\n */\n OAuth2Scopes[\"ApplicationsCommands\"] = \"applications.commands\";\n /**\n * Allows your app to update its Application Commands via this bearer token - client credentials grant only\n *\n * @see {@link https://discord.com/developers/docs/interactions/application-commands}\n */\n OAuth2Scopes[\"ApplicationsCommandsUpdate\"] = \"applications.commands.update\";\n /**\n * Allows your app to update permissions for its commands using a Bearer token - client credentials grant only\n *\n * @see {@link https://discord.com/developers/docs/interactions/application-commands}\n */\n OAuth2Scopes[\"ApplicationCommandsPermissionsUpdate\"] = \"applications.commands.permissions.update\";\n})(OAuth2Scopes || (exports.OAuth2Scopes = OAuth2Scopes = {}));\n//# sourceMappingURL=oauth2.js.map",
|
|
46
|
+
"\"use strict\";\n/**\n * Types extracted from https://discord.com/developers/docs/topics/permissions\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.RoleFlags = void 0;\n/**\n * @see {@link https://discord.com/developers/docs/topics/permissions#role-object-role-flags}\n */\nvar RoleFlags;\n(function (RoleFlags) {\n /**\n * Role can be selected by members in an onboarding prompt\n */\n RoleFlags[RoleFlags[\"InPrompt\"] = 1] = \"InPrompt\";\n})(RoleFlags || (exports.RoleFlags = RoleFlags = {}));\n//# sourceMappingURL=permissions.js.map",
|
|
47
|
+
"\"use strict\";\n/**\n * Types extracted from https://discord.com/developers/docs/resources/poll\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.PollLayoutType = void 0;\n/**\n * @see {@link https://discord.com/developers/docs/resources/poll#layout-type}\n */\nvar PollLayoutType;\n(function (PollLayoutType) {\n /**\n * The, uhm, default layout type\n */\n PollLayoutType[PollLayoutType[\"Default\"] = 1] = \"Default\";\n})(PollLayoutType || (exports.PollLayoutType = PollLayoutType = {}));\n//# sourceMappingURL=poll.js.map",
|
|
48
|
+
"\"use strict\";\n/**\n * Types extracted from https://discord.com/developers/docs/resources/soundboard\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=soundboard.js.map",
|
|
49
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.StageInstancePrivacyLevel = void 0;\n/**\n * @see {@link https://discord.com/developers/docs/resources/stage-instance#stage-instance-object-privacy-level}\n */\nvar StageInstancePrivacyLevel;\n(function (StageInstancePrivacyLevel) {\n /**\n * The stage instance is visible publicly, such as on stage discovery\n *\n * @deprecated\n * {@link https://github.com/discord/discord-api-docs/pull/4296 | discord-api-docs#4296}\n */\n StageInstancePrivacyLevel[StageInstancePrivacyLevel[\"Public\"] = 1] = \"Public\";\n /**\n * The stage instance is visible to only guild members\n */\n StageInstancePrivacyLevel[StageInstancePrivacyLevel[\"GuildOnly\"] = 2] = \"GuildOnly\";\n})(StageInstancePrivacyLevel || (exports.StageInstancePrivacyLevel = StageInstancePrivacyLevel = {}));\n//# sourceMappingURL=stageInstance.js.map",
|
|
50
|
+
"\"use strict\";\n/**\n * Types extracted from https://discord.com/developers/docs/resources/sticker\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.StickerFormatType = exports.StickerType = void 0;\n/**\n * @see {@link https://discord.com/developers/docs/resources/sticker#sticker-object-sticker-types}\n */\nvar StickerType;\n(function (StickerType) {\n /**\n * An official sticker in a pack\n */\n StickerType[StickerType[\"Standard\"] = 1] = \"Standard\";\n /**\n * A sticker uploaded to a guild for the guild's members\n */\n StickerType[StickerType[\"Guild\"] = 2] = \"Guild\";\n})(StickerType || (exports.StickerType = StickerType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/sticker#sticker-object-sticker-format-types}\n */\nvar StickerFormatType;\n(function (StickerFormatType) {\n StickerFormatType[StickerFormatType[\"PNG\"] = 1] = \"PNG\";\n StickerFormatType[StickerFormatType[\"APNG\"] = 2] = \"APNG\";\n StickerFormatType[StickerFormatType[\"Lottie\"] = 3] = \"Lottie\";\n StickerFormatType[StickerFormatType[\"GIF\"] = 4] = \"GIF\";\n})(StickerFormatType || (exports.StickerFormatType = StickerFormatType = {}));\n//# sourceMappingURL=sticker.js.map",
|
|
51
|
+
"\"use strict\";\n/**\n * Types extracted from https://discord.com/developers/docs/topics/teams\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.TeamMemberRole = exports.TeamMemberMembershipState = void 0;\n/**\n * @see {@link https://discord.com/developers/docs/topics/teams#data-models-membership-state-enum}\n */\nvar TeamMemberMembershipState;\n(function (TeamMemberMembershipState) {\n TeamMemberMembershipState[TeamMemberMembershipState[\"Invited\"] = 1] = \"Invited\";\n TeamMemberMembershipState[TeamMemberMembershipState[\"Accepted\"] = 2] = \"Accepted\";\n})(TeamMemberMembershipState || (exports.TeamMemberMembershipState = TeamMemberMembershipState = {}));\n/**\n * @see {@link https://discord.com/developers/docs/topics/teams#team-member-roles-team-member-role-types}\n */\nvar TeamMemberRole;\n(function (TeamMemberRole) {\n TeamMemberRole[\"Admin\"] = \"admin\";\n TeamMemberRole[\"Developer\"] = \"developer\";\n TeamMemberRole[\"ReadOnly\"] = \"read_only\";\n})(TeamMemberRole || (exports.TeamMemberRole = TeamMemberRole = {}));\n//# sourceMappingURL=teams.js.map",
|
|
52
|
+
"\"use strict\";\n/**\n * Types extracted from https://discord.com/developers/docs/resources/guild-template\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=template.js.map",
|
|
53
|
+
"\"use strict\";\n/**\n * Types extracted from https://discord.com/developers/docs/resources/user\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.ConnectionVisibility = exports.ConnectionService = exports.UserPremiumType = exports.UserFlags = void 0;\n/**\n * @see {@link https://discord.com/developers/docs/resources/user#user-object-user-flags}\n */\nvar UserFlags;\n(function (UserFlags) {\n /**\n * Discord Employee\n */\n UserFlags[UserFlags[\"Staff\"] = 1] = \"Staff\";\n /**\n * Partnered Server Owner\n */\n UserFlags[UserFlags[\"Partner\"] = 2] = \"Partner\";\n /**\n * HypeSquad Events Member\n */\n UserFlags[UserFlags[\"Hypesquad\"] = 4] = \"Hypesquad\";\n /**\n * Bug Hunter Level 1\n */\n UserFlags[UserFlags[\"BugHunterLevel1\"] = 8] = \"BugHunterLevel1\";\n /**\n * @unstable This user flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n */\n UserFlags[UserFlags[\"MFASMS\"] = 16] = \"MFASMS\";\n /**\n * @unstable This user flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n */\n UserFlags[UserFlags[\"PremiumPromoDismissed\"] = 32] = \"PremiumPromoDismissed\";\n /**\n * House Bravery Member\n */\n UserFlags[UserFlags[\"HypeSquadOnlineHouse1\"] = 64] = \"HypeSquadOnlineHouse1\";\n /**\n * House Brilliance Member\n */\n UserFlags[UserFlags[\"HypeSquadOnlineHouse2\"] = 128] = \"HypeSquadOnlineHouse2\";\n /**\n * House Balance Member\n */\n UserFlags[UserFlags[\"HypeSquadOnlineHouse3\"] = 256] = \"HypeSquadOnlineHouse3\";\n /**\n * Early Nitro Supporter\n */\n UserFlags[UserFlags[\"PremiumEarlySupporter\"] = 512] = \"PremiumEarlySupporter\";\n /**\n * User is a {@link https://discord.com/developers/docs/topics/teams | team}\n */\n UserFlags[UserFlags[\"TeamPseudoUser\"] = 1024] = \"TeamPseudoUser\";\n /**\n * @unstable This user flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n */\n UserFlags[UserFlags[\"HasUnreadUrgentMessages\"] = 8192] = \"HasUnreadUrgentMessages\";\n /**\n * Bug Hunter Level 2\n */\n UserFlags[UserFlags[\"BugHunterLevel2\"] = 16384] = \"BugHunterLevel2\";\n /**\n * Verified Bot\n */\n UserFlags[UserFlags[\"VerifiedBot\"] = 65536] = \"VerifiedBot\";\n /**\n * Early Verified Bot Developer\n */\n UserFlags[UserFlags[\"VerifiedDeveloper\"] = 131072] = \"VerifiedDeveloper\";\n /**\n * Moderator Programs Alumni\n */\n UserFlags[UserFlags[\"CertifiedModerator\"] = 262144] = \"CertifiedModerator\";\n /**\n * Bot uses only {@link https://discord.com/developers/docs/interactions/receiving-and-responding#receiving-an-interaction | HTTP interactions} and is shown in the online member list\n */\n UserFlags[UserFlags[\"BotHTTPInteractions\"] = 524288] = \"BotHTTPInteractions\";\n /**\n * User has been identified as spammer\n *\n * @unstable This user flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n */\n UserFlags[UserFlags[\"Spammer\"] = 1048576] = \"Spammer\";\n /**\n * @unstable This user flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n */\n UserFlags[UserFlags[\"DisablePremium\"] = 2097152] = \"DisablePremium\";\n /**\n * User is an {@link https://support-dev.discord.com/hc/articles/10113997751447 | Active Developer}\n */\n UserFlags[UserFlags[\"ActiveDeveloper\"] = 4194304] = \"ActiveDeveloper\";\n /**\n * User's account has been {@link https://support.discord.com/hc/articles/6461420677527 | quarantined} based on recent activity\n *\n * @unstable This user flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n * @privateRemarks\n *\n * This value would be `1 << 44`, but bit shifting above `1 << 30` requires bigints\n */\n UserFlags[UserFlags[\"Quarantined\"] = 17592186044416] = \"Quarantined\";\n /**\n * @unstable This user flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n * @privateRemarks\n *\n * This value would be `1 << 50`, but bit shifting above `1 << 30` requires bigints\n */\n UserFlags[UserFlags[\"Collaborator\"] = 1125899906842624] = \"Collaborator\";\n /**\n * @unstable This user flag is currently not documented by Discord but has a known value which we will try to keep up to date.\n * @privateRemarks\n *\n * This value would be `1 << 51`, but bit shifting above `1 << 30` requires bigints\n */\n UserFlags[UserFlags[\"RestrictedCollaborator\"] = 2251799813685248] = \"RestrictedCollaborator\";\n})(UserFlags || (exports.UserFlags = UserFlags = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/user#user-object-premium-types}\n */\nvar UserPremiumType;\n(function (UserPremiumType) {\n UserPremiumType[UserPremiumType[\"None\"] = 0] = \"None\";\n UserPremiumType[UserPremiumType[\"NitroClassic\"] = 1] = \"NitroClassic\";\n UserPremiumType[UserPremiumType[\"Nitro\"] = 2] = \"Nitro\";\n UserPremiumType[UserPremiumType[\"NitroBasic\"] = 3] = \"NitroBasic\";\n})(UserPremiumType || (exports.UserPremiumType = UserPremiumType = {}));\nvar ConnectionService;\n(function (ConnectionService) {\n ConnectionService[\"AmazonMusic\"] = \"amazon-music\";\n ConnectionService[\"BattleNet\"] = \"battlenet\";\n ConnectionService[\"Bluesky\"] = \"bluesky\";\n ConnectionService[\"BungieNet\"] = \"bungie\";\n ConnectionService[\"Crunchyroll\"] = \"crunchyroll\";\n ConnectionService[\"Domain\"] = \"domain\";\n ConnectionService[\"eBay\"] = \"ebay\";\n ConnectionService[\"EpicGames\"] = \"epicgames\";\n ConnectionService[\"Facebook\"] = \"facebook\";\n ConnectionService[\"GitHub\"] = \"github\";\n ConnectionService[\"Instagram\"] = \"instagram\";\n ConnectionService[\"LeagueOfLegends\"] = \"leagueoflegends\";\n ConnectionService[\"Mastodon\"] = \"mastodon\";\n ConnectionService[\"PayPal\"] = \"paypal\";\n ConnectionService[\"PlayStationNetwork\"] = \"playstation\";\n ConnectionService[\"Reddit\"] = \"reddit\";\n ConnectionService[\"RiotGames\"] = \"riotgames\";\n ConnectionService[\"Roblox\"] = \"roblox\";\n ConnectionService[\"Spotify\"] = \"spotify\";\n ConnectionService[\"Skype\"] = \"skype\";\n ConnectionService[\"Steam\"] = \"steam\";\n ConnectionService[\"TikTok\"] = \"tiktok\";\n ConnectionService[\"Twitch\"] = \"twitch\";\n ConnectionService[\"X\"] = \"twitter\";\n /**\n * @deprecated This is the old name for {@link ConnectionService.X}\n */\n ConnectionService[\"Twitter\"] = \"twitter\";\n ConnectionService[\"Xbox\"] = \"xbox\";\n ConnectionService[\"YouTube\"] = \"youtube\";\n})(ConnectionService || (exports.ConnectionService = ConnectionService = {}));\nvar ConnectionVisibility;\n(function (ConnectionVisibility) {\n /**\n * Invisible to everyone except the user themselves\n */\n ConnectionVisibility[ConnectionVisibility[\"None\"] = 0] = \"None\";\n /**\n * Visible to everyone\n */\n ConnectionVisibility[ConnectionVisibility[\"Everyone\"] = 1] = \"Everyone\";\n})(ConnectionVisibility || (exports.ConnectionVisibility = ConnectionVisibility = {}));\n//# sourceMappingURL=user.js.map",
|
|
54
|
+
"\"use strict\";\n/**\n * Types extracted from https://discord.com/developers/docs/resources/voice\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=voice.js.map",
|
|
55
|
+
"\"use strict\";\n/**\n * Types extracted from https://discord.com/developers/docs/resources/webhook\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.WebhookType = exports.ApplicationWebhookEventType = exports.ApplicationWebhookType = void 0;\n/**\n * @see {@link https://discord.com/developers/docs/events/webhook-events#webhook-types}\n */\nvar ApplicationWebhookType;\n(function (ApplicationWebhookType) {\n /**\n * PING event sent to verify your Webhook Event URL is active\n */\n ApplicationWebhookType[ApplicationWebhookType[\"Ping\"] = 0] = \"Ping\";\n /**\n * Webhook event (details for event in event body object)\n */\n ApplicationWebhookType[ApplicationWebhookType[\"Event\"] = 1] = \"Event\";\n})(ApplicationWebhookType || (exports.ApplicationWebhookType = ApplicationWebhookType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/events/webhook-events#event-types}\n */\nvar ApplicationWebhookEventType;\n(function (ApplicationWebhookEventType) {\n /**\n * Sent when an app was authorized by a user to a server or their account\n */\n ApplicationWebhookEventType[\"ApplicationAuthorized\"] = \"APPLICATION_AUTHORIZED\";\n /**\n * Entitlement was created\n */\n ApplicationWebhookEventType[\"EntitlementCreate\"] = \"ENTITLEMENT_CREATE\";\n /**\n * User was added to a Quest (currently unavailable)\n */\n ApplicationWebhookEventType[\"QuestUserEnrollment\"] = \"QUEST_USER_ENROLLMENT\";\n})(ApplicationWebhookEventType || (exports.ApplicationWebhookEventType = ApplicationWebhookEventType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/resources/webhook#webhook-object-webhook-types}\n */\nvar WebhookType;\n(function (WebhookType) {\n /**\n * Incoming Webhooks can post messages to channels with a generated token\n */\n WebhookType[WebhookType[\"Incoming\"] = 1] = \"Incoming\";\n /**\n * Channel Follower Webhooks are internal webhooks used with Channel Following to post new messages into channels\n */\n WebhookType[WebhookType[\"ChannelFollower\"] = 2] = \"ChannelFollower\";\n /**\n * Application webhooks are webhooks used with Interactions\n */\n WebhookType[WebhookType[\"Application\"] = 3] = \"Application\";\n})(WebhookType || (exports.WebhookType = WebhookType = {}));\n//# sourceMappingURL=webhook.js.map",
|
|
56
|
+
"\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __exportStar = (this && this.__exportStar) || function(m, exports) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\n__exportStar(require(\"../common\"), exports);\n__exportStar(require(\"./application\"), exports);\n__exportStar(require(\"./auditLog\"), exports);\n__exportStar(require(\"./autoModeration\"), exports);\n__exportStar(require(\"./channel\"), exports);\n__exportStar(require(\"./emoji\"), exports);\n__exportStar(require(\"./gateway\"), exports);\n__exportStar(require(\"./guild\"), exports);\n__exportStar(require(\"./guildScheduledEvent\"), exports);\n__exportStar(require(\"./interactions\"), exports);\n__exportStar(require(\"./invite\"), exports);\n__exportStar(require(\"./monetization\"), exports);\n__exportStar(require(\"./oauth2\"), exports);\n__exportStar(require(\"./permissions\"), exports);\n__exportStar(require(\"./poll\"), exports);\n__exportStar(require(\"./soundboard\"), exports);\n__exportStar(require(\"./stageInstance\"), exports);\n__exportStar(require(\"./sticker\"), exports);\n__exportStar(require(\"./teams\"), exports);\n__exportStar(require(\"./template\"), exports);\n__exportStar(require(\"./user\"), exports);\n__exportStar(require(\"./voice\"), exports);\n__exportStar(require(\"./webhook\"), exports);\n//# sourceMappingURL=index.js.map",
|
|
57
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.urlSafeCharacters = void 0;\n// eslint-disable-next-line unicorn/better-regex\nconst pattern = /^[\\d%A-Za-z-_]+$/g;\nexports.urlSafeCharacters = {\n test(input) {\n const result = pattern.test(input);\n pattern.lastIndex = 0;\n return result;\n },\n};\n//# sourceMappingURL=internals.js.map",
|
|
58
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.Locale = exports.RESTJSONErrorCodes = void 0;\n/**\n * @see {@link https://discord.com/developers/docs/topics/opcodes-and-status-codes#json-json-error-codes}\n */\nvar RESTJSONErrorCodes;\n(function (RESTJSONErrorCodes) {\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"GeneralError\"] = 0] = \"GeneralError\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownAccount\"] = 10001] = \"UnknownAccount\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownApplication\"] = 10002] = \"UnknownApplication\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownChannel\"] = 10003] = \"UnknownChannel\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownGuild\"] = 10004] = \"UnknownGuild\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownIntegration\"] = 10005] = \"UnknownIntegration\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownInvite\"] = 10006] = \"UnknownInvite\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownMember\"] = 10007] = \"UnknownMember\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownMessage\"] = 10008] = \"UnknownMessage\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownPermissionOverwrite\"] = 10009] = \"UnknownPermissionOverwrite\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownProvider\"] = 10010] = \"UnknownProvider\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownRole\"] = 10011] = \"UnknownRole\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownToken\"] = 10012] = \"UnknownToken\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownUser\"] = 10013] = \"UnknownUser\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownEmoji\"] = 10014] = \"UnknownEmoji\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownWebhook\"] = 10015] = \"UnknownWebhook\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownWebhookService\"] = 10016] = \"UnknownWebhookService\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownSession\"] = 10020] = \"UnknownSession\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownAsset\"] = 10021] = \"UnknownAsset\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownBan\"] = 10026] = \"UnknownBan\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownSKU\"] = 10027] = \"UnknownSKU\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownStoreListing\"] = 10028] = \"UnknownStoreListing\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownEntitlement\"] = 10029] = \"UnknownEntitlement\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownBuild\"] = 10030] = \"UnknownBuild\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownLobby\"] = 10031] = \"UnknownLobby\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownBranch\"] = 10032] = \"UnknownBranch\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownStoreDirectoryLayout\"] = 10033] = \"UnknownStoreDirectoryLayout\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownRedistributable\"] = 10036] = \"UnknownRedistributable\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownGiftCode\"] = 10038] = \"UnknownGiftCode\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownStream\"] = 10049] = \"UnknownStream\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownPremiumServerSubscribeCooldown\"] = 10050] = \"UnknownPremiumServerSubscribeCooldown\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownGuildTemplate\"] = 10057] = \"UnknownGuildTemplate\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownDiscoverableServerCategory\"] = 10059] = \"UnknownDiscoverableServerCategory\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownSticker\"] = 10060] = \"UnknownSticker\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownStickerPack\"] = 10061] = \"UnknownStickerPack\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownInteraction\"] = 10062] = \"UnknownInteraction\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownApplicationCommand\"] = 10063] = \"UnknownApplicationCommand\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownVoiceState\"] = 10065] = \"UnknownVoiceState\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownApplicationCommandPermissions\"] = 10066] = \"UnknownApplicationCommandPermissions\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownStageInstance\"] = 10067] = \"UnknownStageInstance\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownGuildMemberVerificationForm\"] = 10068] = \"UnknownGuildMemberVerificationForm\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownGuildWelcomeScreen\"] = 10069] = \"UnknownGuildWelcomeScreen\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownGuildScheduledEvent\"] = 10070] = \"UnknownGuildScheduledEvent\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownGuildScheduledEventUser\"] = 10071] = \"UnknownGuildScheduledEventUser\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownTag\"] = 10087] = \"UnknownTag\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnknownSound\"] = 10097] = \"UnknownSound\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"BotsCannotUseThisEndpoint\"] = 20001] = \"BotsCannotUseThisEndpoint\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"OnlyBotsCanUseThisEndpoint\"] = 20002] = \"OnlyBotsCanUseThisEndpoint\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ExplicitContentCannotBeSentToTheDesiredRecipient\"] = 20009] = \"ExplicitContentCannotBeSentToTheDesiredRecipient\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"NotAuthorizedToPerformThisActionOnThisApplication\"] = 20012] = \"NotAuthorizedToPerformThisActionOnThisApplication\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ActionCannotBePerformedDueToSlowmodeRateLimit\"] = 20016] = \"ActionCannotBePerformedDueToSlowmodeRateLimit\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"TheMazeIsntMeantForYou\"] = 20017] = \"TheMazeIsntMeantForYou\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"OnlyTheOwnerOfThisAccountCanPerformThisAction\"] = 20018] = \"OnlyTheOwnerOfThisAccountCanPerformThisAction\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"AnnouncementEditLimitExceeded\"] = 20022] = \"AnnouncementEditLimitExceeded\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UnderMinimumAge\"] = 20024] = \"UnderMinimumAge\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ChannelSendRateLimit\"] = 20028] = \"ChannelSendRateLimit\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ServerSendRateLimit\"] = 20029] = \"ServerSendRateLimit\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"StageTopicServerNameServerDescriptionOrChannelNamesContainDisallowedWords\"] = 20031] = \"StageTopicServerNameServerDescriptionOrChannelNamesContainDisallowedWords\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"GuildPremiumSubscriptionLevelTooLow\"] = 20035] = \"GuildPremiumSubscriptionLevelTooLow\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfGuildsReached\"] = 30001] = \"MaximumNumberOfGuildsReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfFriendsReached\"] = 30002] = \"MaximumNumberOfFriendsReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfPinsReachedForTheChannel\"] = 30003] = \"MaximumNumberOfPinsReachedForTheChannel\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfRecipientsReached\"] = 30004] = \"MaximumNumberOfRecipientsReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfGuildRolesReached\"] = 30005] = \"MaximumNumberOfGuildRolesReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfWebhooksReached\"] = 30007] = \"MaximumNumberOfWebhooksReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfEmojisReached\"] = 30008] = \"MaximumNumberOfEmojisReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfReactionsReached\"] = 30010] = \"MaximumNumberOfReactionsReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfGroupDMsReached\"] = 30011] = \"MaximumNumberOfGroupDMsReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfGuildChannelsReached\"] = 30013] = \"MaximumNumberOfGuildChannelsReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfAttachmentsInAMessageReached\"] = 30015] = \"MaximumNumberOfAttachmentsInAMessageReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfInvitesReached\"] = 30016] = \"MaximumNumberOfInvitesReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfAnimatedEmojisReached\"] = 30018] = \"MaximumNumberOfAnimatedEmojisReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfServerMembersReached\"] = 30019] = \"MaximumNumberOfServerMembersReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfServerCategoriesReached\"] = 30030] = \"MaximumNumberOfServerCategoriesReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"GuildAlreadyHasTemplate\"] = 30031] = \"GuildAlreadyHasTemplate\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfApplicationCommandsReached\"] = 30032] = \"MaximumNumberOfApplicationCommandsReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumThreadParticipantsReached\"] = 30033] = \"MaximumThreadParticipantsReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumDailyApplicationCommandCreatesReached\"] = 30034] = \"MaximumDailyApplicationCommandCreatesReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfNonGuildMemberBansHasBeenExceeded\"] = 30035] = \"MaximumNumberOfNonGuildMemberBansHasBeenExceeded\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfBanFetchesHasBeenReached\"] = 30037] = \"MaximumNumberOfBanFetchesHasBeenReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfUncompletedGuildScheduledEventsReached\"] = 30038] = \"MaximumNumberOfUncompletedGuildScheduledEventsReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfStickersReached\"] = 30039] = \"MaximumNumberOfStickersReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfPruneRequestsHasBeenReached\"] = 30040] = \"MaximumNumberOfPruneRequestsHasBeenReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfGuildWidgetSettingsUpdatesHasBeenReached\"] = 30042] = \"MaximumNumberOfGuildWidgetSettingsUpdatesHasBeenReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfSoundboardSoundsReached\"] = 30045] = \"MaximumNumberOfSoundboardSoundsReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfEditsToMessagesOlderThanOneHourReached\"] = 30046] = \"MaximumNumberOfEditsToMessagesOlderThanOneHourReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfPinnedThreadsInForumHasBeenReached\"] = 30047] = \"MaximumNumberOfPinnedThreadsInForumHasBeenReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfTagsInForumHasBeenReached\"] = 30048] = \"MaximumNumberOfTagsInForumHasBeenReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"BitrateIsTooHighForChannelOfThisType\"] = 30052] = \"BitrateIsTooHighForChannelOfThisType\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfPremiumEmojisReached\"] = 30056] = \"MaximumNumberOfPremiumEmojisReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfWebhooksPerGuildReached\"] = 30058] = \"MaximumNumberOfWebhooksPerGuildReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumNumberOfChannelPermissionOverwritesReached\"] = 30060] = \"MaximumNumberOfChannelPermissionOverwritesReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"TheChannelsForThisGuildAreTooLarge\"] = 30061] = \"TheChannelsForThisGuildAreTooLarge\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"Unauthorized\"] = 40001] = \"Unauthorized\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"VerifyYourAccount\"] = 40002] = \"VerifyYourAccount\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"OpeningDirectMessagesTooFast\"] = 40003] = \"OpeningDirectMessagesTooFast\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"SendMessagesHasBeenTemporarilyDisabled\"] = 40004] = \"SendMessagesHasBeenTemporarilyDisabled\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"RequestEntityTooLarge\"] = 40005] = \"RequestEntityTooLarge\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"FeatureTemporarilyDisabledServerSide\"] = 40006] = \"FeatureTemporarilyDisabledServerSide\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UserBannedFromThisGuild\"] = 40007] = \"UserBannedFromThisGuild\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ConnectionHasBeenRevoked\"] = 40012] = \"ConnectionHasBeenRevoked\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"OnlyConsumableSKUsCanBeConsumed\"] = 40018] = \"OnlyConsumableSKUsCanBeConsumed\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"YouCanOnlyDeleteSandboxEntitlements\"] = 40019] = \"YouCanOnlyDeleteSandboxEntitlements\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"TargetUserIsNotConnectedToVoice\"] = 40032] = \"TargetUserIsNotConnectedToVoice\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ThisMessageWasAlreadyCrossposted\"] = 40033] = \"ThisMessageWasAlreadyCrossposted\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ApplicationCommandWithThatNameAlreadyExists\"] = 40041] = \"ApplicationCommandWithThatNameAlreadyExists\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ApplicationInteractionFailedToSend\"] = 40043] = \"ApplicationInteractionFailedToSend\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"CannotSendAMessageInAForumChannel\"] = 40058] = \"CannotSendAMessageInAForumChannel\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"InteractionHasAlreadyBeenAcknowledged\"] = 40060] = \"InteractionHasAlreadyBeenAcknowledged\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"TagNamesMustBeUnique\"] = 40061] = \"TagNamesMustBeUnique\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ServiceResourceIsBeingRateLimited\"] = 40062] = \"ServiceResourceIsBeingRateLimited\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ThereAreNoTagsAvailableThatCanBeSetByNonModerators\"] = 40066] = \"ThereAreNoTagsAvailableThatCanBeSetByNonModerators\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"TagRequiredToCreateAForumPostInThisChannel\"] = 40067] = \"TagRequiredToCreateAForumPostInThisChannel\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"AnEntitlementHasAlreadyBeenGrantedForThisResource\"] = 40074] = \"AnEntitlementHasAlreadyBeenGrantedForThisResource\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ThisInteractionHasHitTheMaximumNumberOfFollowUpMessages\"] = 40094] = \"ThisInteractionHasHitTheMaximumNumberOfFollowUpMessages\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"CloudflareIsBlockingYourRequest\"] = 40333] = \"CloudflareIsBlockingYourRequest\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MissingAccess\"] = 50001] = \"MissingAccess\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"InvalidAccountType\"] = 50002] = \"InvalidAccountType\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"CannotExecuteActionOnDMChannel\"] = 50003] = \"CannotExecuteActionOnDMChannel\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"GuildWidgetDisabled\"] = 50004] = \"GuildWidgetDisabled\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"CannotEditMessageAuthoredByAnotherUser\"] = 50005] = \"CannotEditMessageAuthoredByAnotherUser\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"CannotSendAnEmptyMessage\"] = 50006] = \"CannotSendAnEmptyMessage\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"CannotSendMessagesToThisUser\"] = 50007] = \"CannotSendMessagesToThisUser\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"CannotSendMessagesInNonTextChannel\"] = 50008] = \"CannotSendMessagesInNonTextChannel\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ChannelVerificationLevelTooHighForYouToGainAccess\"] = 50009] = \"ChannelVerificationLevelTooHighForYouToGainAccess\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"OAuth2ApplicationDoesNotHaveBot\"] = 50010] = \"OAuth2ApplicationDoesNotHaveBot\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"OAuth2ApplicationLimitReached\"] = 50011] = \"OAuth2ApplicationLimitReached\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"InvalidOAuth2State\"] = 50012] = \"InvalidOAuth2State\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MissingPermissions\"] = 50013] = \"MissingPermissions\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"InvalidToken\"] = 50014] = \"InvalidToken\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"NoteWasTooLong\"] = 50015] = \"NoteWasTooLong\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ProvidedTooFewOrTooManyMessagesToDelete\"] = 50016] = \"ProvidedTooFewOrTooManyMessagesToDelete\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"InvalidMFALevel\"] = 50017] = \"InvalidMFALevel\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MessageCanOnlyBePinnedInTheChannelItWasSentIn\"] = 50019] = \"MessageCanOnlyBePinnedInTheChannelItWasSentIn\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"InviteCodeInvalidOrTaken\"] = 50020] = \"InviteCodeInvalidOrTaken\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"CannotExecuteActionOnSystemMessage\"] = 50021] = \"CannotExecuteActionOnSystemMessage\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"CannotExecuteActionOnThisChannelType\"] = 50024] = \"CannotExecuteActionOnThisChannelType\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"InvalidOAuth2AccessToken\"] = 50025] = \"InvalidOAuth2AccessToken\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MissingRequiredOAuth2Scope\"] = 50026] = \"MissingRequiredOAuth2Scope\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"InvalidWebhookToken\"] = 50027] = \"InvalidWebhookToken\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"InvalidRole\"] = 50028] = \"InvalidRole\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"InvalidRecipients\"] = 50033] = \"InvalidRecipients\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"OneOfTheMessagesProvidedWasTooOldForBulkDelete\"] = 50034] = \"OneOfTheMessagesProvidedWasTooOldForBulkDelete\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"InvalidFormBodyOrContentType\"] = 50035] = \"InvalidFormBodyOrContentType\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"InviteAcceptedToGuildWithoutTheBotBeingIn\"] = 50036] = \"InviteAcceptedToGuildWithoutTheBotBeingIn\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"InvalidActivityAction\"] = 50039] = \"InvalidActivityAction\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"InvalidAPIVersion\"] = 50041] = \"InvalidAPIVersion\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"FileUploadedExceedsMaximumSize\"] = 50045] = \"FileUploadedExceedsMaximumSize\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"InvalidFileUploaded\"] = 50046] = \"InvalidFileUploaded\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"CannotSelfRedeemThisGift\"] = 50054] = \"CannotSelfRedeemThisGift\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"InvalidGuild\"] = 50055] = \"InvalidGuild\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"InvalidSKU\"] = 50057] = \"InvalidSKU\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"InvalidRequestOrigin\"] = 50067] = \"InvalidRequestOrigin\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"InvalidMessageType\"] = 50068] = \"InvalidMessageType\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"PaymentSourceRequiredToRedeemGift\"] = 50070] = \"PaymentSourceRequiredToRedeemGift\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"CannotModifyASystemWebhook\"] = 50073] = \"CannotModifyASystemWebhook\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"CannotDeleteChannelRequiredForCommunityGuilds\"] = 50074] = \"CannotDeleteChannelRequiredForCommunityGuilds\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"CannotEditStickersWithinMessage\"] = 50080] = \"CannotEditStickersWithinMessage\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"InvalidStickerSent\"] = 50081] = \"InvalidStickerSent\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"InvalidActionOnArchivedThread\"] = 50083] = \"InvalidActionOnArchivedThread\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"InvalidThreadNotificationSettings\"] = 50084] = \"InvalidThreadNotificationSettings\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ParameterEarlierThanCreation\"] = 50085] = \"ParameterEarlierThanCreation\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"CommunityServerChannelsMustBeTextChannels\"] = 50086] = \"CommunityServerChannelsMustBeTextChannels\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"TheEntityTypeOfTheEventIsDifferentFromTheEntityYouAreTryingToStartTheEventFor\"] = 50091] = \"TheEntityTypeOfTheEventIsDifferentFromTheEntityYouAreTryingToStartTheEventFor\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ServerNotAvailableInYourLocation\"] = 50095] = \"ServerNotAvailableInYourLocation\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ServerNeedsMonetizationEnabledToPerformThisAction\"] = 50097] = \"ServerNeedsMonetizationEnabledToPerformThisAction\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ServerNeedsMoreBoostsToPerformThisAction\"] = 50101] = \"ServerNeedsMoreBoostsToPerformThisAction\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"RequestBodyContainsInvalidJSON\"] = 50109] = \"RequestBodyContainsInvalidJSON\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ProvidedFileIsInvalid\"] = 50110] = \"ProvidedFileIsInvalid\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ProvidedFileTypeIsInvalid\"] = 50123] = \"ProvidedFileTypeIsInvalid\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ProvidedFileDurationExceedsMaximumLength\"] = 50124] = \"ProvidedFileDurationExceedsMaximumLength\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"OwnerCannotBePendingMember\"] = 50131] = \"OwnerCannotBePendingMember\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"OwnershipCannotBeMovedToABotUser\"] = 50132] = \"OwnershipCannotBeMovedToABotUser\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"FailedToResizeAssetBelowTheMinimumSize\"] = 50138] = \"FailedToResizeAssetBelowTheMinimumSize\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"CannotMixSubscriptionAndNonSubscriptionRolesForAnEmoji\"] = 50144] = \"CannotMixSubscriptionAndNonSubscriptionRolesForAnEmoji\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"CannotConvertBetweenPremiumEmojiAndNormalEmoji\"] = 50145] = \"CannotConvertBetweenPremiumEmojiAndNormalEmoji\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UploadedFileNotFound\"] = 50146] = \"UploadedFileNotFound\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"SpecifiedEmojiIsInvalid\"] = 50151] = \"SpecifiedEmojiIsInvalid\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"VoiceMessagesDoNotSupportAdditionalContent\"] = 50159] = \"VoiceMessagesDoNotSupportAdditionalContent\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"VoiceMessagesMustHaveASingleAudioAttachment\"] = 50160] = \"VoiceMessagesMustHaveASingleAudioAttachment\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"VoiceMessagesMustHaveSupportingMetadata\"] = 50161] = \"VoiceMessagesMustHaveSupportingMetadata\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"VoiceMessagesCannotBeEdited\"] = 50162] = \"VoiceMessagesCannotBeEdited\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"CannotDeleteGuildSubscriptionIntegration\"] = 50163] = \"CannotDeleteGuildSubscriptionIntegration\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"YouCannotSendVoiceMessagesInThisChannel\"] = 50173] = \"YouCannotSendVoiceMessagesInThisChannel\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"TheUserAccountMustFirstBeVerified\"] = 50178] = \"TheUserAccountMustFirstBeVerified\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ProvidedFileDoesNotHaveAValidDuration\"] = 50192] = \"ProvidedFileDoesNotHaveAValidDuration\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"YouDoNotHavePermissionToSendThisSticker\"] = 50600] = \"YouDoNotHavePermissionToSendThisSticker\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"TwoFactorAuthenticationIsRequired\"] = 60003] = \"TwoFactorAuthenticationIsRequired\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"NoUsersWithDiscordTagExist\"] = 80004] = \"NoUsersWithDiscordTagExist\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ReactionWasBlocked\"] = 90001] = \"ReactionWasBlocked\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UserCannotUseBurstReactions\"] = 90002] = \"UserCannotUseBurstReactions\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ApplicationNotYetAvailable\"] = 110001] = \"ApplicationNotYetAvailable\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"APIResourceOverloaded\"] = 130000] = \"APIResourceOverloaded\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"TheStageIsAlreadyOpen\"] = 150006] = \"TheStageIsAlreadyOpen\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"CannotReplyWithoutPermissionToReadMessageHistory\"] = 160002] = \"CannotReplyWithoutPermissionToReadMessageHistory\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ThreadAlreadyCreatedForMessage\"] = 160004] = \"ThreadAlreadyCreatedForMessage\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"ThreadLocked\"] = 160005] = \"ThreadLocked\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumActiveThreads\"] = 160006] = \"MaximumActiveThreads\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MaximumActiveAnnouncementThreads\"] = 160007] = \"MaximumActiveAnnouncementThreads\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"InvalidJSONForUploadedLottieFile\"] = 170001] = \"InvalidJSONForUploadedLottieFile\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"UploadedLottiesCannotContainRasterizedImages\"] = 170002] = \"UploadedLottiesCannotContainRasterizedImages\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"StickerMaximumFramerateExceeded\"] = 170003] = \"StickerMaximumFramerateExceeded\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"StickerFrameCountExceedsMaximumOf1000Frames\"] = 170004] = \"StickerFrameCountExceedsMaximumOf1000Frames\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"LottieAnimationMaximumDimensionsExceeded\"] = 170005] = \"LottieAnimationMaximumDimensionsExceeded\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"StickerFramerateIsTooSmallOrTooLarge\"] = 170006] = \"StickerFramerateIsTooSmallOrTooLarge\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"StickerAnimationDurationExceedsMaximumOf5Seconds\"] = 170007] = \"StickerAnimationDurationExceedsMaximumOf5Seconds\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"CannotUpdateAFinishedEvent\"] = 180000] = \"CannotUpdateAFinishedEvent\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"FailedToCreateStageNeededForStageEvent\"] = 180002] = \"FailedToCreateStageNeededForStageEvent\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MessageWasBlockedByAutomaticModeration\"] = 200000] = \"MessageWasBlockedByAutomaticModeration\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"TitleWasBlockedByAutomaticModeration\"] = 200001] = \"TitleWasBlockedByAutomaticModeration\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"WebhooksPostedToForumChannelsMustHaveAThreadNameOrThreadId\"] = 220001] = \"WebhooksPostedToForumChannelsMustHaveAThreadNameOrThreadId\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"WebhooksPostedToForumChannelsCannotHaveBothAThreadNameAndThreadId\"] = 220002] = \"WebhooksPostedToForumChannelsCannotHaveBothAThreadNameAndThreadId\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"WebhooksCanOnlyCreateThreadsInForumChannels\"] = 220003] = \"WebhooksCanOnlyCreateThreadsInForumChannels\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"WebhookServicesCannotBeUsedInForumChannels\"] = 220004] = \"WebhookServicesCannotBeUsedInForumChannels\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"MessageBlockedByHarmfulLinksFilter\"] = 240000] = \"MessageBlockedByHarmfulLinksFilter\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"CannotEnableOnboardingRequirementsAreNotMet\"] = 350000] = \"CannotEnableOnboardingRequirementsAreNotMet\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"CannotUpdateOnboardingWhileBelowRequirements\"] = 350001] = \"CannotUpdateOnboardingWhileBelowRequirements\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"FailedToBanUsers\"] = 500000] = \"FailedToBanUsers\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"PollVotingBlocked\"] = 520000] = \"PollVotingBlocked\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"PollExpired\"] = 520001] = \"PollExpired\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"InvalidChannelTypeForPollCreation\"] = 520002] = \"InvalidChannelTypeForPollCreation\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"CannotEditAPollMessage\"] = 520003] = \"CannotEditAPollMessage\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"CannotUseAnEmojiIncludedWithThePoll\"] = 520004] = \"CannotUseAnEmojiIncludedWithThePoll\";\n RESTJSONErrorCodes[RESTJSONErrorCodes[\"CannotExpireANonPollMessage\"] = 520006] = \"CannotExpireANonPollMessage\";\n})(RESTJSONErrorCodes || (exports.RESTJSONErrorCodes = RESTJSONErrorCodes = {}));\n/**\n * @see {@link https://discord.com/developers/docs/reference#locales}\n */\nvar Locale;\n(function (Locale) {\n Locale[\"Indonesian\"] = \"id\";\n Locale[\"EnglishUS\"] = \"en-US\";\n Locale[\"EnglishGB\"] = \"en-GB\";\n Locale[\"Bulgarian\"] = \"bg\";\n Locale[\"ChineseCN\"] = \"zh-CN\";\n Locale[\"ChineseTW\"] = \"zh-TW\";\n Locale[\"Croatian\"] = \"hr\";\n Locale[\"Czech\"] = \"cs\";\n Locale[\"Danish\"] = \"da\";\n Locale[\"Dutch\"] = \"nl\";\n Locale[\"Finnish\"] = \"fi\";\n Locale[\"French\"] = \"fr\";\n Locale[\"German\"] = \"de\";\n Locale[\"Greek\"] = \"el\";\n Locale[\"Hindi\"] = \"hi\";\n Locale[\"Hungarian\"] = \"hu\";\n Locale[\"Italian\"] = \"it\";\n Locale[\"Japanese\"] = \"ja\";\n Locale[\"Korean\"] = \"ko\";\n Locale[\"Lithuanian\"] = \"lt\";\n Locale[\"Norwegian\"] = \"no\";\n Locale[\"Polish\"] = \"pl\";\n Locale[\"PortugueseBR\"] = \"pt-BR\";\n Locale[\"Romanian\"] = \"ro\";\n Locale[\"Russian\"] = \"ru\";\n Locale[\"SpanishES\"] = \"es-ES\";\n Locale[\"SpanishLATAM\"] = \"es-419\";\n Locale[\"Swedish\"] = \"sv-SE\";\n Locale[\"Thai\"] = \"th\";\n Locale[\"Turkish\"] = \"tr\";\n Locale[\"Ukrainian\"] = \"uk\";\n Locale[\"Vietnamese\"] = \"vi\";\n})(Locale || (exports.Locale = Locale = {}));\n//# sourceMappingURL=common.js.map",
|
|
59
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=application.js.map",
|
|
60
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=auditLog.js.map",
|
|
61
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=autoModeration.js.map",
|
|
62
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.ReactionType = void 0;\n/**\n * @see {@link https://discord.com/developers/docs/resources/channel#get-reactions-reaction-types}\n */\nvar ReactionType;\n(function (ReactionType) {\n ReactionType[ReactionType[\"Normal\"] = 0] = \"Normal\";\n ReactionType[ReactionType[\"Super\"] = 1] = \"Super\";\n})(ReactionType || (exports.ReactionType = ReactionType = {}));\n//# sourceMappingURL=channel.js.map",
|
|
63
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=emoji.js.map",
|
|
64
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=gateway.js.map",
|
|
65
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=guild.js.map",
|
|
66
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=guildScheduledEvent.js.map",
|
|
67
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=interactions.js.map",
|
|
68
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=invite.js.map",
|
|
69
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.EntitlementOwnerType = void 0;\n/**\n * @see {@link https://discord.com/developers/docs/resources/entitlement#create-test-entitlement}\n */\nvar EntitlementOwnerType;\n(function (EntitlementOwnerType) {\n EntitlementOwnerType[EntitlementOwnerType[\"Guild\"] = 1] = \"Guild\";\n EntitlementOwnerType[EntitlementOwnerType[\"User\"] = 2] = \"User\";\n})(EntitlementOwnerType || (exports.EntitlementOwnerType = EntitlementOwnerType = {}));\n//# sourceMappingURL=monetization.js.map",
|
|
70
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=oauth2.js.map",
|
|
71
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=poll.js.map",
|
|
72
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=soundboard.js.map",
|
|
73
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=stageInstance.js.map",
|
|
74
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=sticker.js.map",
|
|
75
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=template.js.map",
|
|
76
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=user.js.map",
|
|
77
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=voice.js.map",
|
|
78
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=webhook.js.map",
|
|
79
|
+
"\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __exportStar = (this && this.__exportStar) || function(m, exports) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.OAuth2Routes = exports.RouteBases = exports.CDNRoutes = exports.ImageFormat = exports.StickerPackApplicationId = exports.Routes = exports.APIVersion = void 0;\nconst internals_1 = require(\"../../utils/internals\");\n__exportStar(require(\"../common\"), exports);\n__exportStar(require(\"./application\"), exports);\n__exportStar(require(\"./auditLog\"), exports);\n__exportStar(require(\"./autoModeration\"), exports);\n__exportStar(require(\"./channel\"), exports);\n__exportStar(require(\"./emoji\"), exports);\n__exportStar(require(\"./gateway\"), exports);\n__exportStar(require(\"./guild\"), exports);\n__exportStar(require(\"./guildScheduledEvent\"), exports);\n__exportStar(require(\"./interactions\"), exports);\n__exportStar(require(\"./invite\"), exports);\n__exportStar(require(\"./monetization\"), exports);\n__exportStar(require(\"./oauth2\"), exports);\n__exportStar(require(\"./poll\"), exports);\n__exportStar(require(\"./soundboard\"), exports);\n__exportStar(require(\"./stageInstance\"), exports);\n__exportStar(require(\"./sticker\"), exports);\n__exportStar(require(\"./template\"), exports);\n__exportStar(require(\"./user\"), exports);\n__exportStar(require(\"./voice\"), exports);\n__exportStar(require(\"./webhook\"), exports);\nexports.APIVersion = '10';\nexports.Routes = {\n /**\n * Route for:\n * - GET `/applications/{application.id}/role-connections/metadata`\n * - PUT `/applications/{application.id}/role-connections/metadata`\n */\n applicationRoleConnectionMetadata(applicationId) {\n return `/applications/${applicationId}/role-connections/metadata`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/auto-moderation/rules`\n * - POST `/guilds/{guild.id}/auto-moderation/rules`\n */\n guildAutoModerationRules(guildId) {\n return `/guilds/${guildId}/auto-moderation/rules`;\n },\n /**\n * Routes for:\n * - GET `/guilds/{guild.id}/auto-moderation/rules/{rule.id}`\n * - PATCH `/guilds/{guild.id}/auto-moderation/rules/{rule.id}`\n * - DELETE `/guilds/{guild.id}/auto-moderation/rules/{rule.id}`\n */\n guildAutoModerationRule(guildId, ruleId) {\n return `/guilds/${guildId}/auto-moderation/rules/${ruleId}`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/audit-logs`\n */\n guildAuditLog(guildId) {\n return `/guilds/${guildId}/audit-logs`;\n },\n /**\n * Route for:\n * - GET `/channels/{channel.id}`\n * - PATCH `/channels/{channel.id}`\n * - DELETE `/channels/{channel.id}`\n */\n channel(channelId) {\n return `/channels/${channelId}`;\n },\n /**\n * Route for:\n * - GET `/channels/{channel.id}/messages`\n * - POST `/channels/{channel.id}/messages`\n */\n channelMessages(channelId) {\n return `/channels/${channelId}/messages`;\n },\n /**\n * Route for:\n * - GET `/channels/{channel.id}/messages/{message.id}`\n * - PATCH `/channels/{channel.id}/messages/{message.id}`\n * - DELETE `/channels/{channel.id}/messages/{message.id}`\n */\n channelMessage(channelId, messageId) {\n return `/channels/${channelId}/messages/${messageId}`;\n },\n /**\n * Route for:\n * - POST `/channels/{channel.id}/messages/{message.id}/crosspost`\n */\n channelMessageCrosspost(channelId, messageId) {\n return `/channels/${channelId}/messages/${messageId}/crosspost`;\n },\n /**\n * Route for:\n * - PUT `/channels/{channel.id}/messages/{message.id}/reactions/{emoji}/@me`\n * - DELETE `/channels/{channel.id}/messages/{message.id}/reactions/{emoji}/@me`\n *\n * **Note**: You need to URL encode the emoji yourself\n */\n channelMessageOwnReaction(channelId, messageId, emoji) {\n return `/channels/${channelId}/messages/${messageId}/reactions/${emoji}/@me`;\n },\n /**\n * Route for:\n * - DELETE `/channels/{channel.id}/messages/{message.id}/reactions/{emoji}/{user.id}`\n *\n * **Note**: You need to URL encode the emoji yourself\n */\n channelMessageUserReaction(channelId, messageId, emoji, userId) {\n return `/channels/${channelId}/messages/${messageId}/reactions/${emoji}/${userId}`;\n },\n /**\n * Route for:\n * - GET `/channels/{channel.id}/messages/{message.id}/reactions/{emoji}`\n * - DELETE `/channels/{channel.id}/messages/{message.id}/reactions/{emoji}`\n *\n * **Note**: You need to URL encode the emoji yourself\n */\n channelMessageReaction(channelId, messageId, emoji) {\n return `/channels/${channelId}/messages/${messageId}/reactions/${emoji}`;\n },\n /**\n * Route for:\n * - DELETE `/channels/{channel.id}/messages/{message.id}/reactions`\n */\n channelMessageAllReactions(channelId, messageId) {\n return `/channels/${channelId}/messages/${messageId}/reactions`;\n },\n /**\n * Route for:\n * - POST `/channels/{channel.id}/messages/bulk-delete`\n */\n channelBulkDelete(channelId) {\n return `/channels/${channelId}/messages/bulk-delete`;\n },\n /**\n * Route for:\n * - PUT `/channels/{channel.id}/permissions/{overwrite.id}`\n * - DELETE `/channels/{channel.id}/permissions/{overwrite.id}`\n */\n channelPermission(channelId, overwriteId) {\n return `/channels/${channelId}/permissions/${overwriteId}`;\n },\n /**\n * Route for:\n * - GET `/channels/{channel.id}/invites`\n * - POST `/channels/{channel.id}/invites`\n */\n channelInvites(channelId) {\n return `/channels/${channelId}/invites`;\n },\n /**\n * Route for:\n * - POST `/channels/{channel.id}/followers`\n */\n channelFollowers(channelId) {\n return `/channels/${channelId}/followers`;\n },\n /**\n * Route for:\n * - POST `/channels/{channel.id}/typing`\n */\n channelTyping(channelId) {\n return `/channels/${channelId}/typing`;\n },\n /**\n * Route for:\n * - GET `/channels/{channel.id}/pins`\n */\n channelPins(channelId) {\n return `/channels/${channelId}/pins`;\n },\n /**\n * Route for:\n * - PUT `/channels/{channel.id}/pins/{message.id}`\n * - DELETE `/channels/{channel.id}/pins/{message.id}`\n */\n channelPin(channelId, messageId) {\n return `/channels/${channelId}/pins/${messageId}`;\n },\n /**\n * Route for:\n * - PUT `/channels/{channel.id}/recipients/{user.id}`\n * - DELETE `/channels/{channel.id}/recipients/{user.id}`\n */\n channelRecipient(channelId, userId) {\n return `/channels/${channelId}/recipients/${userId}`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/emojis`\n * - POST `/guilds/{guild.id}/emojis`\n */\n guildEmojis(guildId) {\n return `/guilds/${guildId}/emojis`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/emojis/{emoji.id}`\n * - PATCH `/guilds/{guild.id}/emojis/{emoji.id}`\n * - DELETE `/guilds/{guild.id}/emojis/{emoji.id}`\n */\n guildEmoji(guildId, emojiId) {\n return `/guilds/${guildId}/emojis/${emojiId}`;\n },\n /**\n * Route for:\n * - POST `/guilds`\n */\n guilds() {\n return '/guilds';\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}`\n * - PATCH `/guilds/{guild.id}`\n * - DELETE `/guilds/{guild.id}`\n */\n guild(guildId) {\n return `/guilds/${guildId}`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/preview`\n */\n guildPreview(guildId) {\n return `/guilds/${guildId}/preview`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/channels`\n * - POST `/guilds/{guild.id}/channels`\n * - PATCH `/guilds/{guild.id}/channels`\n */\n guildChannels(guildId) {\n return `/guilds/${guildId}/channels`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/members/{user.id}`\n * - PUT `/guilds/{guild.id}/members/{user.id}`\n * - PATCH `/guilds/{guild.id}/members/@me`\n * - PATCH `/guilds/{guild.id}/members/{user.id}`\n * - DELETE `/guilds/{guild.id}/members/{user.id}`\n */\n guildMember(guildId, userId = '@me') {\n return `/guilds/${guildId}/members/${userId}`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/members`\n */\n guildMembers(guildId) {\n return `/guilds/${guildId}/members`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/members/search`\n */\n guildMembersSearch(guildId) {\n return `/guilds/${guildId}/members/search`;\n },\n /**\n * Route for:\n * - PATCH `/guilds/{guild.id}/members/@me/nick`\n *\n * @deprecated Use {@link Routes.guildMember} instead.\n */\n guildCurrentMemberNickname(guildId) {\n return `/guilds/${guildId}/members/@me/nick`;\n },\n /**\n * Route for:\n * - PUT `/guilds/{guild.id}/members/{user.id}/roles/{role.id}`\n * - DELETE `/guilds/{guild.id}/members/{user.id}/roles/{role.id}`\n */\n guildMemberRole(guildId, memberId, roleId) {\n return `/guilds/${guildId}/members/${memberId}/roles/${roleId}`;\n },\n /**\n * Route for:\n * - POST `/guilds/{guild.id}/mfa`\n */\n guildMFA(guildId) {\n return `/guilds/${guildId}/mfa`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/bans`\n */\n guildBans(guildId) {\n return `/guilds/${guildId}/bans`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/bans/{user.id}`\n * - PUT `/guilds/{guild.id}/bans/{user.id}`\n * - DELETE `/guilds/{guild.id}/bans/{user.id}`\n */\n guildBan(guildId, userId) {\n return `/guilds/${guildId}/bans/${userId}`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/roles`\n * - POST `/guilds/{guild.id}/roles`\n * - PATCH `/guilds/{guild.id}/roles`\n */\n guildRoles(guildId) {\n return `/guilds/${guildId}/roles`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/roles/{role.id}`\n * - PATCH `/guilds/{guild.id}/roles/{role.id}`\n * - DELETE `/guilds/{guild.id}/roles/{role.id}`\n */\n guildRole(guildId, roleId) {\n return `/guilds/${guildId}/roles/${roleId}`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/prune`\n * - POST `/guilds/{guild.id}/prune`\n */\n guildPrune(guildId) {\n return `/guilds/${guildId}/prune`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/regions`\n */\n guildVoiceRegions(guildId) {\n return `/guilds/${guildId}/regions`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/invites`\n */\n guildInvites(guildId) {\n return `/guilds/${guildId}/invites`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/integrations`\n */\n guildIntegrations(guildId) {\n return `/guilds/${guildId}/integrations`;\n },\n /**\n * Route for:\n * - DELETE `/guilds/{guild.id}/integrations/{integration.id}`\n */\n guildIntegration(guildId, integrationId) {\n return `/guilds/${guildId}/integrations/${integrationId}`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/widget`\n * - PATCH `/guilds/{guild.id}/widget`\n */\n guildWidgetSettings(guildId) {\n return `/guilds/${guildId}/widget`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/widget.json`\n */\n guildWidgetJSON(guildId) {\n return `/guilds/${guildId}/widget.json`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/vanity-url`\n */\n guildVanityUrl(guildId) {\n return `/guilds/${guildId}/vanity-url`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/widget.png`\n */\n guildWidgetImage(guildId) {\n return `/guilds/${guildId}/widget.png`;\n },\n /**\n * Route for:\n * - GET `/invites/{invite.code}`\n * - DELETE `/invites/{invite.code}`\n */\n invite(code) {\n return `/invites/${code}`;\n },\n /**\n * Route for:\n * - GET `/guilds/templates/{template.code}`\n * - POST `/guilds/templates/{template.code}`\n */\n template(code) {\n return `/guilds/templates/${code}`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/templates`\n * - POST `/guilds/{guild.id}/templates`\n */\n guildTemplates(guildId) {\n return `/guilds/${guildId}/templates`;\n },\n /**\n * Route for:\n * - PUT `/guilds/{guild.id}/templates/{template.code}`\n * - PATCH `/guilds/{guild.id}/templates/{template.code}`\n * - DELETE `/guilds/{guild.id}/templates/{template.code}`\n */\n guildTemplate(guildId, code) {\n return `/guilds/${guildId}/templates/${code}`;\n },\n /**\n * Route for:\n * - GET `/channels/{channel.id}/polls/{message.id}/answers/{answer_id}`\n */\n pollAnswerVoters(channelId, messageId, answerId) {\n return `/channels/${channelId}/polls/${messageId}/answers/${answerId}`;\n },\n /**\n * Route for:\n * - POST `/channels/{channel.id}/polls/{message.id}/expire`\n */\n expirePoll(channelId, messageId) {\n return `/channels/${channelId}/polls/${messageId}/expire`;\n },\n /**\n * Route for:\n * - POST `/channels/{channel.id}/threads`\n * - POST `/channels/{channel.id}/messages/{message.id}/threads`\n */\n threads(parentId, messageId) {\n const parts = ['', 'channels', parentId];\n if (messageId)\n parts.push('messages', messageId);\n parts.push('threads');\n return parts.join('/');\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/threads/active`\n */\n guildActiveThreads(guildId) {\n return `/guilds/${guildId}/threads/active`;\n },\n /**\n * Route for:\n * - GET `/channels/{channel.id}/threads/archived/public`\n * - GET `/channels/{channel.id}/threads/archived/private`\n */\n channelThreads(channelId, archivedStatus) {\n return `/channels/${channelId}/threads/archived/${archivedStatus}`;\n },\n /**\n * Route for:\n * - GET `/channels/{channel.id}/users/@me/threads/archived/private`\n */\n channelJoinedArchivedThreads(channelId) {\n return `/channels/${channelId}/users/@me/threads/archived/private`;\n },\n /**\n * Route for:\n * - GET `/channels/{thread.id}/thread-members`\n * - GET `/channels/{thread.id}/thread-members/{user.id}`\n * - PUT `/channels/{thread.id}/thread-members/@me`\n * - PUT `/channels/{thread.id}/thread-members/{user.id}`\n * - DELETE `/channels/{thread.id}/thread-members/@me`\n * - DELETE `/channels/{thread.id}/thread-members/{user.id}`\n */\n threadMembers(threadId, userId) {\n const parts = ['', 'channels', threadId, 'thread-members'];\n if (userId)\n parts.push(userId);\n return parts.join('/');\n },\n /**\n * Route for:\n * - GET `/users/@me`\n * - GET `/users/{user.id}`\n * - PATCH `/users/@me`\n *\n * @param [userId] - The user ID, defaulted to `@me`\n */\n user(userId = '@me') {\n return `/users/${userId}`;\n },\n /**\n * Route for:\n * - GET `/users/@me/applications/{application.id}/role-connection`\n * - PUT `/users/@me/applications/{application.id}/role-connection`\n */\n userApplicationRoleConnection(applicationId) {\n return `/users/@me/applications/${applicationId}/role-connection`;\n },\n /**\n * Route for:\n * - GET `/users/@me/guilds`\n */\n userGuilds() {\n return `/users/@me/guilds`;\n },\n /**\n * Route for:\n * - GET `/users/@me/guilds/{guild.id}/member`\n */\n userGuildMember(guildId) {\n return `/users/@me/guilds/${guildId}/member`;\n },\n /**\n * Route for:\n * - DELETE `/users/@me/guilds/{guild.id}`\n */\n userGuild(guildId) {\n return `/users/@me/guilds/${guildId}`;\n },\n /**\n * Route for:\n * - POST `/users/@me/channels`\n */\n userChannels() {\n return `/users/@me/channels`;\n },\n /**\n * Route for:\n * - GET `/users/@me/connections`\n */\n userConnections() {\n return `/users/@me/connections`;\n },\n /**\n * Route for:\n * - GET `/voice/regions`\n */\n voiceRegions() {\n return `/voice/regions`;\n },\n /**\n * Route for:\n * - GET `/channels/{channel.id}/webhooks`\n * - POST `/channels/{channel.id}/webhooks`\n */\n channelWebhooks(channelId) {\n return `/channels/${channelId}/webhooks`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/webhooks`\n */\n guildWebhooks(guildId) {\n return `/guilds/${guildId}/webhooks`;\n },\n /**\n * Route for:\n * - GET `/webhooks/{webhook.id}`\n * - GET `/webhooks/{webhook.id}/{webhook.token}`\n * - PATCH `/webhooks/{webhook.id}`\n * - PATCH `/webhooks/{webhook.id}/{webhook.token}`\n * - DELETE `/webhooks/{webhook.id}`\n * - DELETE `/webhooks/{webhook.id}/{webhook.token}`\n * - POST `/webhooks/{webhook.id}/{webhook.token}`\n *\n * - POST `/webhooks/{application.id}/{interaction.token}`\n */\n webhook(webhookId, webhookToken) {\n const parts = ['', 'webhooks', webhookId];\n if (webhookToken)\n parts.push(webhookToken);\n return parts.join('/');\n },\n /**\n * Route for:\n * - GET `/webhooks/{webhook.id}/{webhook.token}/messages/@original`\n * - GET `/webhooks/{webhook.id}/{webhook.token}/messages/{message.id}`\n * - PATCH `/webhooks/{webhook.id}/{webhook.token}/messages/@original`\n * - PATCH `/webhooks/{webhook.id}/{webhook.token}/messages/{message.id}`\n * - DELETE `/webhooks/{webhook.id}/{webhook.token}/messages/@original`\n * - DELETE `/webhooks/{webhook.id}/{webhook.token}/messages/{message.id}`\n *\n * - PATCH `/webhooks/{application.id}/{interaction.token}/messages/@original`\n * - PATCH `/webhooks/{application.id}/{interaction.token}/messages/{message.id}`\n * - DELETE `/webhooks/{application.id}/{interaction.token}/messages/{message.id}`\n */\n webhookMessage(webhookId, webhookToken, messageId = '@original') {\n return `/webhooks/${webhookId}/${webhookToken}/messages/${messageId}`;\n },\n /**\n * Route for:\n * - POST `/webhooks/{webhook.id}/{webhook.token}/github`\n * - POST `/webhooks/{webhook.id}/{webhook.token}/slack`\n */\n webhookPlatform(webhookId, webhookToken, platform) {\n return `/webhooks/${webhookId}/${webhookToken}/${platform}`;\n },\n /**\n * Route for:\n * - GET `/gateway`\n */\n gateway() {\n return `/gateway`;\n },\n /**\n * Route for:\n * - GET `/gateway/bot`\n */\n gatewayBot() {\n return `/gateway/bot`;\n },\n /**\n * Route for:\n * - GET `/oauth2/applications/@me`\n */\n oauth2CurrentApplication() {\n return `/oauth2/applications/@me`;\n },\n /**\n * Route for:\n * - GET `/oauth2/@me`\n */\n oauth2CurrentAuthorization() {\n return `/oauth2/@me`;\n },\n /**\n * Route for:\n * - GET `/oauth2/authorize`\n */\n oauth2Authorization() {\n return `/oauth2/authorize`;\n },\n /**\n * Route for:\n * - POST `/oauth2/token`\n */\n oauth2TokenExchange() {\n return `/oauth2/token`;\n },\n /**\n * Route for:\n * - POST `/oauth2/token/revoke`\n */\n oauth2TokenRevocation() {\n return `/oauth2/token/revoke`;\n },\n /**\n * Route for:\n * - GET `/applications/{application.id}/commands`\n * - PUT `/applications/{application.id}/commands`\n * - POST `/applications/{application.id}/commands`\n */\n applicationCommands(applicationId) {\n return `/applications/${applicationId}/commands`;\n },\n /**\n * Route for:\n * - GET `/applications/{application.id}/commands/{command.id}`\n * - PATCH `/applications/{application.id}/commands/{command.id}`\n * - DELETE `/applications/{application.id}/commands/{command.id}`\n */\n applicationCommand(applicationId, commandId) {\n return `/applications/${applicationId}/commands/${commandId}`;\n },\n /**\n * Route for:\n * - GET `/applications/{application.id}/guilds/{guild.id}/commands`\n * - PUT `/applications/{application.id}/guilds/{guild.id}/commands`\n * - POST `/applications/{application.id}/guilds/{guild.id}/commands`\n */\n applicationGuildCommands(applicationId, guildId) {\n return `/applications/${applicationId}/guilds/${guildId}/commands`;\n },\n /**\n * Route for:\n * - GET `/applications/{application.id}/guilds/{guild.id}/commands/{command.id}`\n * - PATCH `/applications/{application.id}/guilds/{guild.id}/commands/{command.id}`\n * - DELETE `/applications/{application.id}/guilds/{guild.id}/commands/{command.id}`\n */\n applicationGuildCommand(applicationId, guildId, commandId) {\n return `/applications/${applicationId}/guilds/${guildId}/commands/${commandId}`;\n },\n /**\n * Route for:\n * - POST `/interactions/{interaction.id}/{interaction.token}/callback`\n */\n interactionCallback(interactionId, interactionToken) {\n return `/interactions/${interactionId}/${interactionToken}/callback`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/member-verification`\n * - PATCH `/guilds/{guild.id}/member-verification`\n */\n guildMemberVerification(guildId) {\n return `/guilds/${guildId}/member-verification`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/voice-states/@me`\n * - GET `/guilds/{guild.id}/voice-states/{user.id}`\n * - PATCH `/guilds/{guild.id}/voice-states/@me`\n * - PATCH `/guilds/{guild.id}/voice-states/{user.id}`\n */\n guildVoiceState(guildId, userId = '@me') {\n return `/guilds/${guildId}/voice-states/${userId}`;\n },\n /**\n * Route for:\n * - GET `/applications/{application.id}/guilds/{guild.id}/commands/permissions`\n * - PUT `/applications/{application.id}/guilds/{guild.id}/commands/permissions`\n */\n guildApplicationCommandsPermissions(applicationId, guildId) {\n return `/applications/${applicationId}/guilds/${guildId}/commands/permissions`;\n },\n /**\n * Route for:\n * - GET `/applications/{application.id}/guilds/{guild.id}/commands/{command.id}/permissions`\n * - PUT `/applications/{application.id}/guilds/{guild.id}/commands/{command.id}/permissions`\n */\n applicationCommandPermissions(applicationId, guildId, commandId) {\n return `/applications/${applicationId}/guilds/${guildId}/commands/${commandId}/permissions`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/welcome-screen`\n * - PATCH `/guilds/{guild.id}/welcome-screen`\n */\n guildWelcomeScreen(guildId) {\n return `/guilds/${guildId}/welcome-screen`;\n },\n /**\n * Route for:\n * - POST `/stage-instances`\n */\n stageInstances() {\n return `/stage-instances`;\n },\n /**\n * Route for:\n * - GET `/stage-instances/{channel.id}`\n * - PATCH `/stage-instances/{channel.id}`\n * - DELETE `/stage-instances/{channel.id}`\n */\n stageInstance(channelId) {\n return `/stage-instances/${channelId}`;\n },\n /**\n * Route for:\n * - GET `/stickers/{sticker.id}`\n */\n sticker(stickerId) {\n return `/stickers/${stickerId}`;\n },\n /**\n * Route for:\n * - GET `/sticker-packs`\n */\n stickerPacks() {\n return '/sticker-packs';\n },\n /**\n * Route for:\n * - GET `/sticker-packs/{pack.id}`\n */\n stickerPack(packId) {\n return `/sticker-packs/${packId}`;\n },\n /**\n * Route for:\n * - GET `/sticker-packs`\n *\n * @deprecated Use {@link Routes.stickerPacks} instead.\n */\n nitroStickerPacks() {\n return '/sticker-packs';\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/stickers`\n * - POST `/guilds/{guild.id}/stickers`\n */\n guildStickers(guildId) {\n return `/guilds/${guildId}/stickers`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/stickers/{sticker.id}`\n * - PATCH `/guilds/{guild.id}/stickers/{sticker.id}`\n * - DELETE `/guilds/{guild.id}/stickers/{sticker.id}`\n */\n guildSticker(guildId, stickerId) {\n return `/guilds/${guildId}/stickers/${stickerId}`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/scheduled-events`\n * - POST `/guilds/{guild.id}/scheduled-events`\n */\n guildScheduledEvents(guildId) {\n return `/guilds/${guildId}/scheduled-events`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/scheduled-events/{guildScheduledEvent.id}`\n * - PATCH `/guilds/{guild.id}/scheduled-events/{guildScheduledEvent.id}`\n * - DELETE `/guilds/{guild.id}/scheduled-events/{guildScheduledEvent.id}`\n */\n guildScheduledEvent(guildId, guildScheduledEventId) {\n return `/guilds/${guildId}/scheduled-events/${guildScheduledEventId}`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/scheduled-events/{guildScheduledEvent.id}/users`\n */\n guildScheduledEventUsers(guildId, guildScheduledEventId) {\n return `/guilds/${guildId}/scheduled-events/${guildScheduledEventId}/users`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/onboarding`\n * - PUT `/guilds/{guild.id}/onboarding`\n */\n guildOnboarding(guildId) {\n return `/guilds/${guildId}/onboarding`;\n },\n /**\n * Route for:\n * - PUT `/guilds/${guild.id}/incident-actions`\n */\n guildIncidentActions(guildId) {\n return `/guilds/${guildId}/incident-actions`;\n },\n /**\n * Route for:\n * - GET `/applications/@me`\n * - PATCH `/applications/@me`\n */\n currentApplication() {\n return '/applications/@me';\n },\n /**\n * Route for:\n * - GET `/applications/{application.id}/entitlements`\n * - POST `/applications/{application.id}/entitlements`\n */\n entitlements(applicationId) {\n return `/applications/${applicationId}/entitlements`;\n },\n /**\n * Route for:\n * - GET `/applications/{application.id}/entitlements/{entitlement.id}`\n * - DELETE `/applications/{application.id}/entitlements/{entitlement.id}`\n */\n entitlement(applicationId, entitlementId) {\n return `/applications/${applicationId}/entitlements/${entitlementId}`;\n },\n /**\n * Route for:\n * - GET `/applications/{application.id}/skus`\n */\n skus(applicationId) {\n return `/applications/${applicationId}/skus`;\n },\n /**\n * Route for:\n * - POST `/guilds/{guild.id}/bulk-ban`\n */\n guildBulkBan(guildId) {\n return `/guilds/${guildId}/bulk-ban`;\n },\n /**\n * Route for:\n * - POST `/applications/{application.id}/entitlements/{entitlement.id}/consume`\n */\n consumeEntitlement(applicationId, entitlementId) {\n return `/applications/${applicationId}/entitlements/${entitlementId}/consume`;\n },\n /**\n * Route for:\n * - GET `/applications/{application.id}/emojis`\n * - POST `/applications/{application.id}/emojis`\n */\n applicationEmojis(applicationId) {\n return `/applications/${applicationId}/emojis`;\n },\n /**\n * Route for:\n * - GET `/applications/{application.id}/emojis/{emoji.id}`\n * - PATCH `/applications/{application.id}/emojis/{emoji.id}`\n * - DELETE `/applications/{application.id}/emojis/{emoji.id}`\n */\n applicationEmoji(applicationId, emojiId) {\n return `/applications/${applicationId}/emojis/${emojiId}`;\n },\n /**\n * Route for:\n * - GET `/skus/{sku.id}/subscriptions`\n */\n skuSubscriptions(skuId) {\n return `/skus/${skuId}/subscriptions`;\n },\n /**\n * Route for:\n * - GET `/skus/{sku.id}/subscriptions/{subscription.id}`\n */\n skuSubscription(skuId, subscriptionId) {\n return `/skus/${skuId}/subscriptions/${subscriptionId}`;\n },\n /**\n * Route for:\n * - POST `/channels/{channel.id}/send-soundboard-sound`\n */\n sendSoundboardSound(channelId) {\n return `/channels/${channelId}/send-soundboard-sound`;\n },\n /**\n * Route for:\n * - GET `/soundboard-default-sounds`\n */\n soundboardDefaultSounds() {\n return '/soundboard-default-sounds';\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/soundboard-sounds`\n * - POST `/guilds/{guild.id}/soundboard-sounds`\n */\n guildSoundboardSounds(guildId) {\n return `/guilds/${guildId}/soundboard-sounds`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/soundboard-sounds/{sound.id}`\n * - PATCH `/guilds/{guild.id}/soundboard-sounds/{sound.id}`\n * - DELETE `/guilds/{guild.id}/soundboard-sounds/{sound.id}`\n */\n guildSoundboardSound(guildId, soundId) {\n return `/guilds/${guildId}/soundboard-sounds/${soundId}`;\n },\n};\nfor (const [key, fn] of Object.entries(exports.Routes)) {\n exports.Routes[key] = (...args) => {\n const escaped = args.map((arg) => {\n if (arg) {\n // Skip already \"safe\" urls\n if (internals_1.urlSafeCharacters.test(String(arg))) {\n return arg;\n }\n return encodeURIComponent(arg);\n }\n return arg;\n });\n // eslint-disable-next-line no-useless-call\n return fn.call(null, ...escaped);\n };\n}\n// Freeze the object so it can't be changed\nObject.freeze(exports.Routes);\nexports.StickerPackApplicationId = '710982414301790216';\nvar ImageFormat;\n(function (ImageFormat) {\n ImageFormat[\"JPEG\"] = \"jpeg\";\n ImageFormat[\"PNG\"] = \"png\";\n ImageFormat[\"WebP\"] = \"webp\";\n ImageFormat[\"GIF\"] = \"gif\";\n ImageFormat[\"Lottie\"] = \"json\";\n})(ImageFormat || (exports.ImageFormat = ImageFormat = {}));\nexports.CDNRoutes = {\n /**\n * Route for:\n * - GET `/emojis/{emoji.id}.{png|jpeg|webp|gif}`\n *\n * As this route supports GIFs, the hash will begin with `a_` if it is available in GIF format\n *\n * This route supports the extensions: PNG, JPEG, WebP, GIF\n */\n emoji(emojiId, format) {\n return `/emojis/${emojiId}.${format}`;\n },\n /**\n * Route for:\n * - GET `/icons/{guild.id}/{guild.icon}.{png|jpeg|webp|gif}`\n *\n * As this route supports GIFs, the hash will begin with `a_` if it is available in GIF format\n *\n * This route supports the extensions: PNG, JPEG, WebP, GIF\n */\n guildIcon(guildId, guildIcon, format) {\n return `/icons/${guildId}/${guildIcon}.${format}`;\n },\n /**\n * Route for:\n * - GET `/splashes/{guild.id}/{guild.splash}.{png|jpeg|webp}`\n *\n * This route supports the extensions: PNG, JPEG, WebP\n */\n guildSplash(guildId, guildSplash, format) {\n return `/splashes/${guildId}/${guildSplash}.${format}`;\n },\n /**\n * Route for:\n * - GET `/discovery-splashes/{guild.id}/{guild.discovery_splash}.{png|jpeg|webp}`\n *\n * This route supports the extensions: PNG, JPEG, WebP\n */\n guildDiscoverySplash(guildId, guildDiscoverySplash, format) {\n return `/discovery-splashes/${guildId}/${guildDiscoverySplash}.${format}`;\n },\n /**\n * Route for:\n * - GET `/banners/{guild.id}/{guild.banner}.{png|jpeg|webp|gif}`\n *\n * As this route supports GIFs, the hash will begin with `a_` if it is available in GIF format\n *\n * This route supports the extensions: PNG, JPEG, WebP, GIF\n */\n guildBanner(guildId, guildBanner, format) {\n return `/banners/${guildId}/${guildBanner}.${format}`;\n },\n /**\n * Route for:\n * - GET `/banners/{user.id}/{user.banner}.{png|jpeg|webp|gif}`\n *\n * As this route supports GIFs, the hash will begin with `a_` if it is available in GIF format\n *\n * This route supports the extensions: PNG, JPEG, WebP, GIF\n */\n userBanner(userId, userBanner, format) {\n return `/banners/${userId}/${userBanner}.${format}`;\n },\n /**\n * Route for:\n * - GET `/embed/avatars/{index}.png`\n *\n * The value for `index` parameter depends on whether the user is {@link https://discord.com/developers/docs/change-log#unique-usernames-on-discord | migrated to the new username system}.\n * For users on the new username system, `index` will be `(user.id >> 22) % 6`.\n * For users on the legacy username system, `index` will be `user.discriminator % 5`.\n *\n * This route supports the extension: PNG\n */\n defaultUserAvatar(index) {\n return `/embed/avatars/${index}.png`;\n },\n /**\n * Route for:\n * - GET `/avatars/{user.id}/{user.avatar}.{png|jpeg|webp|gif}`\n *\n * As this route supports GIFs, the hash will begin with `a_` if it is available in GIF format\n *\n * This route supports the extensions: PNG, JPEG, WebP, GIF\n */\n userAvatar(userId, userAvatar, format) {\n return `/avatars/${userId}/${userAvatar}.${format}`;\n },\n /**\n * Route for:\n * - GET `/guilds/{guild.id}/users/{user.id}/avatars/{guild_member.avatar}.{png|jpeg|webp|gif}`\n *\n * As this route supports GIFs, the hash will begin with `a_` if it is available in GIF format\n *\n * This route supports the extensions: PNG, JPEG, WebP, GIF\n */\n guildMemberAvatar(guildId, userId, memberAvatar, format) {\n return `/guilds/${guildId}/users/${userId}/avatars/${memberAvatar}.${format}`;\n },\n /**\n * Route for:\n * - GET `/avatar-decorations/{user.id}/{user.avatar_decoration}.png`\n *\n * This route supports the extension: PNG\n *\n * @deprecated Use {@link CDNRoutes.avatarDecoration} instead.\n */\n userAvatarDecoration(userId, userAvatarDecoration) {\n return `/avatar-decorations/${userId}/${userAvatarDecoration}.png`;\n },\n /**\n * Route for:\n * - GET `/avatar-decoration-presets/{avatar_decoration_data_asset}.png`\n *\n * This route supports the extension: PNG\n */\n avatarDecoration(avatarDecorationDataAsset) {\n return `/avatar-decoration-presets/${avatarDecorationDataAsset}.png`;\n },\n /**\n * Route for:\n * - GET `/app-icons/{application.id}/{application.icon}.{png|jpeg|webp}`\n *\n * This route supports the extensions: PNG, JPEG, WebP\n */\n applicationIcon(applicationId, applicationIcon, format) {\n return `/app-icons/${applicationId}/${applicationIcon}.${format}`;\n },\n /**\n * Route for:\n * - GET `/app-icons/{application.id}/{application.cover_image}.{png|jpeg|webp}`\n *\n * This route supports the extensions: PNG, JPEG, WebP\n */\n applicationCover(applicationId, applicationCoverImage, format) {\n return `/app-icons/${applicationId}/${applicationCoverImage}.${format}`;\n },\n /**\n * Route for:\n * - GET `/app-assets/{application.id}/{application.asset_id}.{png|jpeg|webp}`\n *\n * This route supports the extensions: PNG, JPEG, WebP\n */\n applicationAsset(applicationId, applicationAssetId, format) {\n return `/app-assets/${applicationId}/${applicationAssetId}.${format}`;\n },\n /**\n * Route for:\n * - GET `/app-assets/{application.id}/achievements/{achievement.id}/icons/{achievement.icon}.{png|jpeg|webp}`\n *\n * This route supports the extensions: PNG, JPEG, WebP\n */\n achievementIcon(applicationId, achievementId, achievementIconHash, format) {\n return `/app-assets/${applicationId}/achievements/${achievementId}/icons/${achievementIconHash}.${format}`;\n },\n /**\n * Route for:\n * - GET `/app-assets/710982414301790216/store/{sticker_pack.banner.asset_id}.{png|jpeg|webp}`\n *\n * This route supports the extensions: PNG, JPEG, WebP\n */\n stickerPackBanner(stickerPackBannerAssetId, format) {\n return `/app-assets/${exports.StickerPackApplicationId}/store/${stickerPackBannerAssetId}.${format}`;\n },\n /**\n * Route for:\n * - GET `/app-assets/${application.id}/store/${asset.id}.{png|jpeg|webp}}`\n *\n * This route supports the extensions: PNG, JPEG, WebP\n */\n storePageAsset(applicationId, assetId, format = ImageFormat.PNG) {\n return `/app-assets/${applicationId}/store/${assetId}.${format}`;\n },\n /**\n * Route for:\n * - GET `/team-icons/{team.id}/{team.icon}.{png|jpeg|webp}`\n *\n * This route supports the extensions: PNG, JPEG, WebP\n */\n teamIcon(teamId, teamIcon, format) {\n return `/team-icons/${teamId}/${teamIcon}.${format}`;\n },\n /**\n * Route for:\n * - GET `/stickers/{sticker.id}.{png|json}`\n *\n * This route supports the extensions: PNG, Lottie, GIF\n */\n sticker(stickerId, format) {\n return `/stickers/${stickerId}.${format}`;\n },\n /**\n * Route for:\n * - GET `/role-icons/{role.id}/{role.icon}.{png|jpeg|webp}`\n *\n * This route supports the extensions: PNG, JPEG, WebP\n */\n roleIcon(roleId, roleIcon, format) {\n return `/role-icons/${roleId}/${roleIcon}.${format}`;\n },\n /**\n * Route for:\n * - GET `/guild-events/{guild_scheduled_event.id}/{guild_scheduled_event.image}.{png|jpeg|webp}`\n *\n * This route supports the extensions: PNG, JPEG, WebP\n */\n guildScheduledEventCover(guildScheduledEventId, guildScheduledEventCoverImage, format) {\n return `/guild-events/${guildScheduledEventId}/${guildScheduledEventCoverImage}.${format}`;\n },\n /**\n * Route for:\n * - GET `/guilds/${guild.id}/users/${user.id}/banners/${guild_member.banner}.{png|jpeg|webp|gif}`\n *\n * This route supports the extensions: PNG, JPEG, WebP, GIF\n */\n guildMemberBanner(guildId, userId, guildMemberBanner, format) {\n return `/guilds/${guildId}/users/${userId}/banners/${guildMemberBanner}.${format}`;\n },\n /**\n * Route for:\n * - GET `/soundboard-sounds/${sound.id}`\n */\n soundboardSound(soundId) {\n return `/soundboard-sounds/${soundId}`;\n },\n};\nfor (const [key, fn] of Object.entries(exports.CDNRoutes)) {\n exports.CDNRoutes[key] = (...args) => {\n const escaped = args.map((arg) => {\n if (arg) {\n // Skip already \"safe\" urls\n if (internals_1.urlSafeCharacters.test(String(arg))) {\n return arg;\n }\n return encodeURIComponent(arg);\n }\n return arg;\n });\n // eslint-disable-next-line no-useless-call\n return fn.call(null, ...escaped);\n };\n}\n// Freeze the object so it can't be changed\nObject.freeze(exports.CDNRoutes);\nexports.RouteBases = {\n api: `https://discord.com/api/v${exports.APIVersion}`,\n cdn: 'https://cdn.discordapp.com',\n media: 'https://media.discordapp.net',\n invite: 'https://discord.gg',\n template: 'https://discord.new',\n gift: 'https://discord.gift',\n scheduledEvent: 'https://discord.com/events',\n};\n// Freeze bases object\nObject.freeze(exports.RouteBases);\nexports.OAuth2Routes = {\n authorizationURL: `${exports.RouteBases.api}${exports.Routes.oauth2Authorization()}`,\n tokenURL: `${exports.RouteBases.api}${exports.Routes.oauth2TokenExchange()}`,\n /**\n * @see {@link https://tools.ietf.org/html/rfc7009}\n */\n tokenRevocationURL: `${exports.RouteBases.api}${exports.Routes.oauth2TokenRevocation()}`,\n};\n// Freeze OAuth2 route object\nObject.freeze(exports.OAuth2Routes);\n//# sourceMappingURL=index.js.map",
|
|
80
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.RPCCloseEventCodes = exports.RPCErrorCodes = exports.RelationshipType = exports.VoiceConnectionStates = exports.RPCVoiceShortcutKeyComboKeyType = exports.RPCVoiceSettingsModeType = exports.RPCDeviceType = void 0;\nvar RPCDeviceType;\n(function (RPCDeviceType) {\n RPCDeviceType[\"AudioInput\"] = \"audioinput\";\n RPCDeviceType[\"AudioOutput\"] = \"audiooutput\";\n RPCDeviceType[\"VideoInput\"] = \"videoinput\";\n})(RPCDeviceType || (exports.RPCDeviceType = RPCDeviceType = {}));\nvar RPCVoiceSettingsModeType;\n(function (RPCVoiceSettingsModeType) {\n RPCVoiceSettingsModeType[\"PushToTalk\"] = \"PUSH_TO_TALK\";\n RPCVoiceSettingsModeType[\"VoiceActivity\"] = \"VOICE_ACTIVITY\";\n})(RPCVoiceSettingsModeType || (exports.RPCVoiceSettingsModeType = RPCVoiceSettingsModeType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/topics/rpc#getvoicesettings-key-types}\n */\nvar RPCVoiceShortcutKeyComboKeyType;\n(function (RPCVoiceShortcutKeyComboKeyType) {\n RPCVoiceShortcutKeyComboKeyType[RPCVoiceShortcutKeyComboKeyType[\"KeyboardKey\"] = 0] = \"KeyboardKey\";\n RPCVoiceShortcutKeyComboKeyType[RPCVoiceShortcutKeyComboKeyType[\"MouseButton\"] = 1] = \"MouseButton\";\n RPCVoiceShortcutKeyComboKeyType[RPCVoiceShortcutKeyComboKeyType[\"KeyboardModifierKey\"] = 2] = \"KeyboardModifierKey\";\n RPCVoiceShortcutKeyComboKeyType[RPCVoiceShortcutKeyComboKeyType[\"GamepadButton\"] = 3] = \"GamepadButton\";\n})(RPCVoiceShortcutKeyComboKeyType || (exports.RPCVoiceShortcutKeyComboKeyType = RPCVoiceShortcutKeyComboKeyType = {}));\nvar VoiceConnectionStates;\n(function (VoiceConnectionStates) {\n /**\n * TCP disconnected\n */\n VoiceConnectionStates[\"Disconnected\"] = \"DISCONNECTED\";\n /**\n * Waiting for voice endpoint\n */\n VoiceConnectionStates[\"AwaitingEndpoint\"] = \"AWAITING_ENDPOINT\";\n /**\n * TCP authenticating\n */\n VoiceConnectionStates[\"Authenticating\"] = \"AUTHENTICATING\";\n /**\n * TCP connecting\n */\n VoiceConnectionStates[\"Connecting\"] = \"CONNECTING\";\n /**\n * TCP connected\n */\n VoiceConnectionStates[\"Connected\"] = \"CONNECTED\";\n /**\n * TCP connected, Voice disconnected\n */\n VoiceConnectionStates[\"VoiceDisconnected\"] = \"VOICE_DISCONNECTED\";\n /**\n * TCP connected, Voice connecting\n */\n VoiceConnectionStates[\"VoiceConnecting\"] = \"VOICE_CONNECTING\";\n /**\n * TCP connected, Voice connected\n */\n VoiceConnectionStates[\"VoiceConnected\"] = \"VOICE_CONNECTED\";\n /**\n * No route to host\n */\n VoiceConnectionStates[\"NoRoute\"] = \"NO_ROUTE\";\n /**\n * WebRTC ice checking\n */\n VoiceConnectionStates[\"IceChecking\"] = \"ICE_CHECKING\";\n})(VoiceConnectionStates || (exports.VoiceConnectionStates = VoiceConnectionStates = {}));\n/**\n * @unstable\n */\nvar RelationshipType;\n(function (RelationshipType) {\n RelationshipType[RelationshipType[\"None\"] = 0] = \"None\";\n RelationshipType[RelationshipType[\"Friend\"] = 1] = \"Friend\";\n RelationshipType[RelationshipType[\"Blocked\"] = 2] = \"Blocked\";\n RelationshipType[RelationshipType[\"PendingIncoming\"] = 3] = \"PendingIncoming\";\n RelationshipType[RelationshipType[\"PendingOutgoing\"] = 4] = \"PendingOutgoing\";\n RelationshipType[RelationshipType[\"Implicit\"] = 5] = \"Implicit\";\n})(RelationshipType || (exports.RelationshipType = RelationshipType = {}));\n/**\n * @see {@link https://discord.com/developers/docs/topics/opcodes-and-status-codes#rpc-rpc-error-codes}\n */\nvar RPCErrorCodes;\n(function (RPCErrorCodes) {\n /**\n * An unknown error occurred.\n */\n RPCErrorCodes[RPCErrorCodes[\"UnknownError\"] = 1000] = \"UnknownError\";\n /**\n * @unstable\n */\n RPCErrorCodes[RPCErrorCodes[\"ServiceUnavailable\"] = 1001] = \"ServiceUnavailable\";\n /**\n * @unstable\n */\n RPCErrorCodes[RPCErrorCodes[\"TransactionAborted\"] = 1002] = \"TransactionAborted\";\n /**\n * You sent an invalid payload.\n */\n RPCErrorCodes[RPCErrorCodes[\"InvalidPayload\"] = 4000] = \"InvalidPayload\";\n /**\n * Invalid command name specified.\n */\n RPCErrorCodes[RPCErrorCodes[\"InvalidCommand\"] = 4002] = \"InvalidCommand\";\n /**\n * Invalid guild ID specified.\n */\n RPCErrorCodes[RPCErrorCodes[\"InvalidGuild\"] = 4003] = \"InvalidGuild\";\n /**\n * Invalid event name specified.\n */\n RPCErrorCodes[RPCErrorCodes[\"InvalidEvent\"] = 4004] = \"InvalidEvent\";\n /**\n * Invalid channel ID specified.\n */\n RPCErrorCodes[RPCErrorCodes[\"InvalidChannel\"] = 4005] = \"InvalidChannel\";\n /**\n * You lack permissions to access the given resource.\n */\n RPCErrorCodes[RPCErrorCodes[\"InvalidPermissions\"] = 4006] = \"InvalidPermissions\";\n /**\n * An invalid OAuth2 application ID was used to authorize or authenticate with.\n */\n RPCErrorCodes[RPCErrorCodes[\"InvalidClientId\"] = 4007] = \"InvalidClientId\";\n /**\n * An invalid OAuth2 application origin was used to authorize or authenticate with.\n */\n RPCErrorCodes[RPCErrorCodes[\"InvalidOrigin\"] = 4008] = \"InvalidOrigin\";\n /**\n * An invalid OAuth2 token was used to authorize or authenticate with.\n */\n RPCErrorCodes[RPCErrorCodes[\"InvalidToken\"] = 4009] = \"InvalidToken\";\n /**\n * The specified user ID was invalid.\n */\n RPCErrorCodes[RPCErrorCodes[\"InvalidUser\"] = 4010] = \"InvalidUser\";\n /**\n * @unstable\n */\n RPCErrorCodes[RPCErrorCodes[\"InvalidInvite\"] = 4011] = \"InvalidInvite\";\n /**\n * @unstable\n */\n RPCErrorCodes[RPCErrorCodes[\"InvalidActivityJoinRequest\"] = 4012] = \"InvalidActivityJoinRequest\";\n /**\n * @unstable\n */\n RPCErrorCodes[RPCErrorCodes[\"InvalidEntitlement\"] = 4013] = \"InvalidEntitlement\";\n /**\n * @unstable\n */\n RPCErrorCodes[RPCErrorCodes[\"InvalidGiftCode\"] = 4014] = \"InvalidGiftCode\";\n /**\n * A standard OAuth2 error occurred; check the data object for the OAuth2 error details.\n */\n RPCErrorCodes[RPCErrorCodes[\"OAuth2Error\"] = 5000] = \"OAuth2Error\";\n /**\n * An asynchronous `SELECT_TEXT_CHANNEL`/`SELECT_VOICE_CHANNEL` command timed out.\n */\n RPCErrorCodes[RPCErrorCodes[\"SelectChannelTimedOut\"] = 5001] = \"SelectChannelTimedOut\";\n /**\n * An asynchronous `GET_GUILD` command timed out.\n */\n RPCErrorCodes[RPCErrorCodes[\"GetGuildTimedOut\"] = 5002] = \"GetGuildTimedOut\";\n /**\n * You tried to join a user to a voice channel but the user was already in one.\n */\n RPCErrorCodes[RPCErrorCodes[\"SelectVoiceForceRequired\"] = 5003] = \"SelectVoiceForceRequired\";\n /**\n * You tried to capture more than one shortcut key at once.\n */\n RPCErrorCodes[RPCErrorCodes[\"CaptureShortcutAlreadyListening\"] = 5004] = \"CaptureShortcutAlreadyListening\";\n /**\n * @unstable\n */\n RPCErrorCodes[RPCErrorCodes[\"InvalidActivitySecret\"] = 5005] = \"InvalidActivitySecret\";\n /**\n * @unstable\n */\n RPCErrorCodes[RPCErrorCodes[\"NoEligibleActivity\"] = 5006] = \"NoEligibleActivity\";\n /**\n * @unstable\n */\n RPCErrorCodes[RPCErrorCodes[\"PurchaseCanceled\"] = 5007] = \"PurchaseCanceled\";\n /**\n * @unstable\n */\n RPCErrorCodes[RPCErrorCodes[\"PurchaseError\"] = 5008] = \"PurchaseError\";\n /**\n * @unstable\n */\n RPCErrorCodes[RPCErrorCodes[\"UnauthorizedForAchievement\"] = 5009] = \"UnauthorizedForAchievement\";\n /**\n * @unstable\n */\n RPCErrorCodes[RPCErrorCodes[\"RateLimited\"] = 5010] = \"RateLimited\";\n})(RPCErrorCodes || (exports.RPCErrorCodes = RPCErrorCodes = {}));\n/**\n * @see {@link https://discord.com/developers/docs/topics/opcodes-and-status-codes#rpc-rpc-close-event-codes}\n */\nvar RPCCloseEventCodes;\n(function (RPCCloseEventCodes) {\n /**\n * @unstable\n */\n RPCCloseEventCodes[RPCCloseEventCodes[\"CloseNormal\"] = 1000] = \"CloseNormal\";\n /**\n * @unstable\n */\n RPCCloseEventCodes[RPCCloseEventCodes[\"CloseUnsupported\"] = 1003] = \"CloseUnsupported\";\n /**\n * @unstable\n */\n RPCCloseEventCodes[RPCCloseEventCodes[\"CloseAbnormal\"] = 1006] = \"CloseAbnormal\";\n /**\n * You connected to the RPC server with an invalid client ID.\n */\n RPCCloseEventCodes[RPCCloseEventCodes[\"InvalidClientId\"] = 4000] = \"InvalidClientId\";\n /**\n * You connected to the RPC server with an invalid origin.\n */\n RPCCloseEventCodes[RPCCloseEventCodes[\"InvalidOrigin\"] = 4001] = \"InvalidOrigin\";\n /**\n * You are being rate limited.\n */\n RPCCloseEventCodes[RPCCloseEventCodes[\"RateLimited\"] = 4002] = \"RateLimited\";\n /**\n * The OAuth2 token associated with a connection was revoked, get a new one!\n */\n RPCCloseEventCodes[RPCCloseEventCodes[\"TokenRevoked\"] = 4003] = \"TokenRevoked\";\n /**\n * The RPC Server version specified in the connection string was not valid.\n */\n RPCCloseEventCodes[RPCCloseEventCodes[\"InvalidVersion\"] = 4004] = \"InvalidVersion\";\n /**\n * The encoding specified in the connection string was not valid.\n */\n RPCCloseEventCodes[RPCCloseEventCodes[\"InvalidEncoding\"] = 4005] = \"InvalidEncoding\";\n})(RPCCloseEventCodes || (exports.RPCCloseEventCodes = RPCCloseEventCodes = {}));\n//# sourceMappingURL=common.js.map",
|
|
81
|
+
"\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __exportStar = (this && this.__exportStar) || function(m, exports) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.RPCEvents = exports.RPCCommands = exports.RPCVersion = void 0;\n__exportStar(require(\"./common\"), exports);\nexports.RPCVersion = '1';\n/**\n * @see {@link https://discord.com/developers/docs/topics/rpc#commands-and-events-rpc-commands}\n */\nvar RPCCommands;\n(function (RPCCommands) {\n /**\n * @unstable\n */\n RPCCommands[\"AcceptActivityInvite\"] = \"ACCEPT_ACTIVITY_INVITE\";\n /**\n * @unstable\n */\n RPCCommands[\"ActivityInviteUser\"] = \"ACTIVITY_INVITE_USER\";\n /**\n * Used to authenticate an existing client with your app\n */\n RPCCommands[\"Authenticate\"] = \"AUTHENTICATE\";\n /**\n * Used to authorize a new client with your app\n */\n RPCCommands[\"Authorize\"] = \"AUTHORIZE\";\n /**\n * @unstable\n */\n RPCCommands[\"BraintreePopupBridgeCallback\"] = \"BRAINTREE_POPUP_BRIDGE_CALLBACK\";\n /**\n * @unstable\n */\n RPCCommands[\"BrowserHandoff\"] = \"BROWSER_HANDOFF\";\n /**\n * \tused to reject a Rich Presence Ask to Join request\n *\n * @unstable the documented similarly named command `CLOSE_ACTIVITY_REQUEST` does not exist, but `CLOSE_ACTIVITY_JOIN_REQUEST` does\n */\n RPCCommands[\"CloseActivityJoinRequest\"] = \"CLOSE_ACTIVITY_JOIN_REQUEST\";\n /**\n * @unstable\n */\n RPCCommands[\"ConnectionsCallback\"] = \"CONNECTIONS_CALLBACK\";\n RPCCommands[\"CreateChannelInvite\"] = \"CREATE_CHANNEL_INVITE\";\n /**\n * @unstable\n */\n RPCCommands[\"DeepLink\"] = \"DEEP_LINK\";\n /**\n * Event dispatch\n */\n RPCCommands[\"Dispatch\"] = \"DISPATCH\";\n /**\n * @unstable\n */\n RPCCommands[\"GetApplicationTicket\"] = \"GET_APPLICATION_TICKET\";\n /**\n * Used to retrieve channel information from the client\n */\n RPCCommands[\"GetChannel\"] = \"GET_CHANNEL\";\n /**\n * Used to retrieve a list of channels for a guild from the client\n */\n RPCCommands[\"GetChannels\"] = \"GET_CHANNELS\";\n /**\n * @unstable\n */\n RPCCommands[\"GetEntitlementTicket\"] = \"GET_ENTITLEMENT_TICKET\";\n /**\n * @unstable\n */\n RPCCommands[\"GetEntitlements\"] = \"GET_ENTITLEMENTS\";\n /**\n * Used to retrieve guild information from the client\n */\n RPCCommands[\"GetGuild\"] = \"GET_GUILD\";\n /**\n * Used to retrieve a list of guilds from the client\n */\n RPCCommands[\"GetGuilds\"] = \"GET_GUILDS\";\n /**\n * @unstable\n */\n RPCCommands[\"GetImage\"] = \"GET_IMAGE\";\n /**\n * @unstable\n */\n RPCCommands[\"GetNetworkingConfig\"] = \"GET_NETWORKING_CONFIG\";\n /**\n * @unstable\n */\n RPCCommands[\"GetRelationships\"] = \"GET_RELATIONSHIPS\";\n /**\n * Used to get the current voice channel the client is in\n */\n RPCCommands[\"GetSelectedVoiceChannel\"] = \"GET_SELECTED_VOICE_CHANNEL\";\n /**\n * @unstable\n */\n RPCCommands[\"GetSkus\"] = \"GET_SKUS\";\n /**\n * @unstable\n */\n RPCCommands[\"GetUser\"] = \"GET_USER\";\n /**\n * Used to retrieve the client's voice settings\n */\n RPCCommands[\"GetVoiceSettings\"] = \"GET_VOICE_SETTINGS\";\n /**\n * @unstable\n */\n RPCCommands[\"GiftCodeBrowser\"] = \"GIFT_CODE_BROWSER\";\n /**\n * @unstable\n */\n RPCCommands[\"GuildTemplateBrowser\"] = \"GUILD_TEMPLATE_BROWSER\";\n /**\n * @unstable\n */\n RPCCommands[\"InviteBrowser\"] = \"INVITE_BROWSER\";\n /**\n * @unstable\n */\n RPCCommands[\"NetworkingCreateToken\"] = \"NETWORKING_CREATE_TOKEN\";\n /**\n * @unstable\n */\n RPCCommands[\"NetworkingPeerMetrics\"] = \"NETWORKING_PEER_METRICS\";\n /**\n * @unstable\n */\n RPCCommands[\"NetworkingSystemMetrics\"] = \"NETWORKING_SYSTEM_METRICS\";\n /**\n * @unstable\n */\n RPCCommands[\"OpenOverlayActivityInvite\"] = \"OPEN_OVERLAY_ACTIVITY_INVITE\";\n /**\n * @unstable\n */\n RPCCommands[\"OpenOverlayGuildInvite\"] = \"OPEN_OVERLAY_GUILD_INVITE\";\n /**\n * @unstable\n */\n RPCCommands[\"OpenOverlayVoiceSettings\"] = \"OPEN_OVERLAY_VOICE_SETTINGS\";\n /**\n * @unstable\n */\n RPCCommands[\"Overlay\"] = \"OVERLAY\";\n /**\n * Used to join or leave a text channel, group dm, or dm\n */\n RPCCommands[\"SelectTextChannel\"] = \"SELECT_TEXT_CHANNEL\";\n /**\n * Used to join or leave a voice channel, group dm, or dm\n */\n RPCCommands[\"SelectVoiceChannel\"] = \"SELECT_VOICE_CHANNEL\";\n /**\n * Used to consent to a Rich Presence Ask to Join request\n */\n RPCCommands[\"SendActivityJoinInvite\"] = \"SEND_ACTIVITY_JOIN_INVITE\";\n /**\n * Used to update a user's Rich Presence\n */\n RPCCommands[\"SetActivity\"] = \"SET_ACTIVITY\";\n /**\n * Used to send info about certified hardware devices\n */\n RPCCommands[\"SetCertifiedDevices\"] = \"SET_CERTIFIED_DEVICES\";\n /**\n * @unstable\n */\n RPCCommands[\"SetOverlayLocked\"] = \"SET_OVERLAY_LOCKED\";\n /**\n * Used to change voice settings of users in voice channels\n */\n RPCCommands[\"SetUserVoiceSettings\"] = \"SET_USER_VOICE_SETTINGS\";\n RPCCommands[\"SetUserVoiceSettings2\"] = \"SET_USER_VOICE_SETTINGS_2\";\n /**\n * Used to set the client's voice settings\n */\n RPCCommands[\"SetVoiceSettings\"] = \"SET_VOICE_SETTINGS\";\n RPCCommands[\"SetVoiceSettings2\"] = \"SET_VOICE_SETTINGS_2\";\n /**\n * @unstable\n */\n RPCCommands[\"StartPurchase\"] = \"START_PURCHASE\";\n /**\n * Used to subscribe to an RPC event\n */\n RPCCommands[\"Subscribe\"] = \"SUBSCRIBE\";\n /**\n * Used to unsubscribe from an RPC event\n */\n RPCCommands[\"Unsubscribe\"] = \"UNSUBSCRIBE\";\n /**\n * @unstable\n */\n RPCCommands[\"ValidateApplication\"] = \"VALIDATE_APPLICATION\";\n})(RPCCommands || (exports.RPCCommands = RPCCommands = {}));\n/**\n * @see {@link https://discord.com/developers/docs/topics/rpc#commands-and-events-rpc-events}\n */\nvar RPCEvents;\n(function (RPCEvents) {\n /**\n * @unstable\n */\n RPCEvents[\"ActivityInvite\"] = \"ACTIVITY_INVITE\";\n RPCEvents[\"ActivityJoin\"] = \"ACTIVITY_JOIN\";\n RPCEvents[\"ActivityJoinRequest\"] = \"ACTIVITY_JOIN_REQUEST\";\n RPCEvents[\"ActivitySpectate\"] = \"ACTIVITY_SPECTATE\";\n RPCEvents[\"ChannelCreate\"] = \"CHANNEL_CREATE\";\n RPCEvents[\"CurrentUserUpdate\"] = \"CURRENT_USER_UPDATE\";\n /**\n * @unstable\n */\n RPCEvents[\"EntitlementCreate\"] = \"ENTITLEMENT_CREATE\";\n /**\n * @unstable\n */\n RPCEvents[\"EntitlementDelete\"] = \"ENTITLEMENT_DELETE\";\n RPCEvents[\"Error\"] = \"ERROR\";\n /**\n * @unstable\n */\n RPCEvents[\"GameJoin\"] = \"GAME_JOIN\";\n /**\n * @unstable\n */\n RPCEvents[\"GameSpectate\"] = \"GAME_SPECTATE\";\n RPCEvents[\"GuildCreate\"] = \"GUILD_CREATE\";\n RPCEvents[\"GuildStatus\"] = \"GUILD_STATUS\";\n /**\n * Dispatches message objects, with the exception of deletions, which only contains the id in the message object.\n */\n RPCEvents[\"MessageCreate\"] = \"MESSAGE_CREATE\";\n /**\n * Dispatches message objects, with the exception of deletions, which only contains the id in the message object.\n */\n RPCEvents[\"MessageDelete\"] = \"MESSAGE_DELETE\";\n /**\n * Dispatches message objects, with the exception of deletions, which only contains the id in the message object.\n */\n RPCEvents[\"MessageUpdate\"] = \"MESSAGE_UPDATE\";\n /**\n * This event requires the `rpc.notifications.read` {@link https://discord.com/developers/docs/topics/oauth2#shared-resources-oauth2-scopes | OAuth2 scope}.\n */\n RPCEvents[\"NotificationCreate\"] = \"NOTIFICATION_CREATE\";\n /**\n * @unstable\n */\n RPCEvents[\"Overlay\"] = \"OVERLAY\";\n /**\n * @unstable\n */\n RPCEvents[\"OverlayUpdate\"] = \"OVERLAY_UPDATE\";\n RPCEvents[\"Ready\"] = \"READY\";\n /**\n * @unstable\n */\n RPCEvents[\"RelationshipUpdate\"] = \"RELATIONSHIP_UPDATE\";\n RPCEvents[\"SpeakingStart\"] = \"SPEAKING_START\";\n RPCEvents[\"SpeakingStop\"] = \"SPEAKING_STOP\";\n RPCEvents[\"VoiceChannelSelect\"] = \"VOICE_CHANNEL_SELECT\";\n RPCEvents[\"VoiceConnectionStatus\"] = \"VOICE_CONNECTION_STATUS\";\n RPCEvents[\"VoiceSettingsUpdate\"] = \"VOICE_SETTINGS_UPDATE\";\n /**\n * @unstable\n */\n RPCEvents[\"VoiceSettingsUpdate2\"] = \"VOICE_SETTINGS_UPDATE_2\";\n /**\n * Dispatches channel voice state objects\n */\n RPCEvents[\"VoiceStateCreate\"] = \"VOICE_STATE_CREATE\";\n /**\n * Dispatches channel voice state objects\n */\n RPCEvents[\"VoiceStateDelete\"] = \"VOICE_STATE_DELETE\";\n /**\n * Dispatches channel voice state objects\n */\n RPCEvents[\"VoiceStateUpdate\"] = \"VOICE_STATE_UPDATE\";\n})(RPCEvents || (exports.RPCEvents = RPCEvents = {}));\n//# sourceMappingURL=v10.js.map",
|
|
82
|
+
"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.isDMInteraction = isDMInteraction;\nexports.isGuildInteraction = isGuildInteraction;\nexports.isApplicationCommandDMInteraction = isApplicationCommandDMInteraction;\nexports.isApplicationCommandGuildInteraction = isApplicationCommandGuildInteraction;\nexports.isMessageComponentDMInteraction = isMessageComponentDMInteraction;\nexports.isMessageComponentGuildInteraction = isMessageComponentGuildInteraction;\nexports.isLinkButton = isLinkButton;\nexports.isInteractionButton = isInteractionButton;\nexports.isMessageComponentInteraction = isMessageComponentInteraction;\nexports.isMessageComponentButtonInteraction = isMessageComponentButtonInteraction;\nexports.isMessageComponentSelectMenuInteraction = isMessageComponentSelectMenuInteraction;\nexports.isChatInputApplicationCommandInteraction = isChatInputApplicationCommandInteraction;\nexports.isContextMenuApplicationCommandInteraction = isContextMenuApplicationCommandInteraction;\nconst index_1 = require(\"../payloads/v10/index\");\n// Interactions\n/**\n * A type-guard check for DM interactions\n *\n * @param interaction - The interaction to check against\n * @returns A boolean that indicates if the interaction was received in a DM channel\n */\nfunction isDMInteraction(interaction) {\n return Reflect.has(interaction, 'user');\n}\n/**\n * A type-guard check for guild interactions\n *\n * @param interaction - The interaction to check against\n * @returns A boolean that indicates if the interaction was received in a guild\n */\nfunction isGuildInteraction(interaction) {\n return Reflect.has(interaction, 'guild_id');\n}\n// ApplicationCommandInteractions\n/**\n * A type-guard check for DM application command interactions\n *\n * @param interaction - The application command interaction to check against\n * @returns A boolean that indicates if the application command interaction was received in a DM channel\n */\nfunction isApplicationCommandDMInteraction(interaction) {\n return isDMInteraction(interaction);\n}\n/**\n * A type-guard check for guild application command interactions\n *\n * @param interaction - The interaction to check against\n * @returns A boolean that indicates if the application command interaction was received in a guild\n */\nfunction isApplicationCommandGuildInteraction(interaction) {\n return isGuildInteraction(interaction);\n}\n// MessageComponentInteractions\n/**\n * A type-guard check for DM message component interactions\n *\n * @param interaction - The message component interaction to check against\n * @returns A boolean that indicates if the message component interaction was received in a DM channel\n */\nfunction isMessageComponentDMInteraction(interaction) {\n return isDMInteraction(interaction);\n}\n/**\n * A type-guard check for guild message component interactions\n *\n * @param interaction - The interaction to check against\n * @returns A boolean that indicates if the message component interaction was received in a guild\n */\nfunction isMessageComponentGuildInteraction(interaction) {\n return isGuildInteraction(interaction);\n}\n// Buttons\n/**\n * A type-guard check for buttons that have a `url` attached to them.\n *\n * @param component - The button to check against\n * @returns A boolean that indicates if the button has a `url` attached to it\n */\nfunction isLinkButton(component) {\n return component.style === index_1.ButtonStyle.Link;\n}\n/**\n * A type-guard check for buttons that have a `custom_id` attached to them.\n *\n * @param component - The button to check against\n * @returns A boolean that indicates if the button has a `custom_id` attached to it\n */\nfunction isInteractionButton(component) {\n return ![index_1.ButtonStyle.Link, index_1.ButtonStyle.Premium].includes(component.style);\n}\n// Message Components\n/**\n * A type-guard check for message component interactions\n *\n * @param interaction - The interaction to check against\n * @returns A boolean that indicates if the interaction is a message component\n */\nfunction isMessageComponentInteraction(interaction) {\n return interaction.type === index_1.InteractionType.MessageComponent;\n}\n/**\n * A type-guard check for button message component interactions\n *\n * @param interaction - The message component interaction to check against\n * @returns A boolean that indicates if the message component is a button\n */\nfunction isMessageComponentButtonInteraction(interaction) {\n return interaction.data.component_type === index_1.ComponentType.Button;\n}\n/**\n * A type-guard check for select menu message component interactions\n *\n * @param interaction - The message component interaction to check against\n * @returns A boolean that indicates if the message component is a select menu\n */\nfunction isMessageComponentSelectMenuInteraction(interaction) {\n return [\n index_1.ComponentType.StringSelect,\n index_1.ComponentType.UserSelect,\n index_1.ComponentType.RoleSelect,\n index_1.ComponentType.MentionableSelect,\n index_1.ComponentType.ChannelSelect,\n ].includes(interaction.data.component_type);\n}\n// Application Commands\n/**\n * A type-guard check for chat input application commands.\n *\n * @param interaction - The interaction to check against\n * @returns A boolean that indicates if the interaction is a chat input application command\n */\nfunction isChatInputApplicationCommandInteraction(interaction) {\n return interaction.data.type === index_1.ApplicationCommandType.ChatInput;\n}\n/**\n * A type-guard check for context menu application commands.\n *\n * @param interaction - The interaction to check against\n * @returns A boolean that indicates if the interaction is a context menu application command\n */\nfunction isContextMenuApplicationCommandInteraction(interaction) {\n return (interaction.data.type === index_1.ApplicationCommandType.Message ||\n interaction.data.type === index_1.ApplicationCommandType.User);\n}\n//# sourceMappingURL=v10.js.map",
|
|
83
|
+
"\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __exportStar = (this && this.__exportStar) || function(m, exports) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.Utils = void 0;\n__exportStar(require(\"./gateway/v10\"), exports);\n__exportStar(require(\"./globals\"), exports);\n__exportStar(require(\"./payloads/v10/index\"), exports);\n__exportStar(require(\"./rest/v10/index\"), exports);\n__exportStar(require(\"./rpc/v10\"), exports);\n__exportStar(require(\"./utils/internals\"), exports);\nexports.Utils = require(\"./utils/v10\");\n//# sourceMappingURL=v10.js.map",
|
|
84
|
+
"import { type IAgentRuntime, logger, type Plugin } from \"@elizaos/core\";\nimport chatWithAttachments from \"./actions/chatWithAttachments\";\nimport createPoll from \"./actions/createPoll\";\nimport deleteMessage from \"./actions/deleteMessage\";\nimport { downloadMedia } from \"./actions/downloadMedia\";\nimport editMessage from \"./actions/editMessage\";\nimport getUserInfo from \"./actions/getUserInfo\";\nimport joinChannel from \"./actions/joinChannel\";\nimport leaveChannel from \"./actions/leaveChannel\";\nimport listChannels from \"./actions/listChannels\";\nimport pinMessage from \"./actions/pinMessage\";\nimport reactToMessage from \"./actions/reactToMessage\";\nimport readChannel from \"./actions/readChannel\";\nimport searchMessages from \"./actions/searchMessages\";\nimport sendDM from \"./actions/sendDM\";\nimport sendMessage from \"./actions/sendMessage\";\nimport serverInfo from \"./actions/serverInfo\";\nimport { summarize } from \"./actions/summarizeConversation\";\nimport { transcribeMedia } from \"./actions/transcribeMedia\";\nimport unpinMessage from \"./actions/unpinMessage\";\nimport { printBanner } from \"./banner\";\nimport { getPermissionValues } from \"./permissions\";\nimport { channelStateProvider } from \"./providers/channelState\";\nimport { guildInfoProvider } from \"./providers/guildInfo\";\nimport { voiceStateProvider } from \"./providers/voiceState\";\nimport { DiscordService } from \"./service\";\nimport { DiscordTestSuite } from \"./tests\";\n\nconst discordPlugin: Plugin = {\n\tname: \"discord\",\n\tdescription:\n\t\t\"Discord service plugin for integration with Discord servers and channels\",\n\tservices: [DiscordService],\n\tactions: [\n\t\tchatWithAttachments,\n\t\tdownloadMedia,\n\t\tjoinChannel,\n\t\tleaveChannel,\n\t\tlistChannels,\n\t\treadChannel,\n\t\tsendDM,\n\t\tsendMessage,\n\t\tsummarize,\n\t\ttranscribeMedia,\n\t\tsearchMessages,\n\t\tcreatePoll,\n\t\tgetUserInfo,\n\t\treactToMessage,\n\t\tpinMessage,\n\t\tunpinMessage,\n\t\tserverInfo,\n\t\teditMessage,\n\t\tdeleteMessage,\n\t],\n\tproviders: [channelStateProvider, voiceStateProvider, guildInfoProvider],\n\ttests: [new DiscordTestSuite()],\n\tinit: async (_config: Record<string, string>, runtime: IAgentRuntime) => {\n\t\tconst token = runtime.getSetting(\"DISCORD_API_TOKEN\") as string;\n\t\tconst applicationId = runtime.getSetting(\n\t\t\t\"DISCORD_APPLICATION_ID\",\n\t\t) as string;\n\t\tconst voiceChannelId = runtime.getSetting(\n\t\t\t\"DISCORD_VOICE_CHANNEL_ID\",\n\t\t) as string;\n\t\tconst channelIds = runtime.getSetting(\"CHANNEL_IDS\") as string;\n\t\tconst listenChannelIds = runtime.getSetting(\n\t\t\t\"DISCORD_LISTEN_CHANNEL_IDS\",\n\t\t) as string;\n\t\tconst ignoreBotMessages = runtime.getSetting(\n\t\t\t\"DISCORD_SHOULD_IGNORE_BOT_MESSAGES\",\n\t\t) as string;\n\t\tconst ignoreDirectMessages = runtime.getSetting(\n\t\t\t\"DISCORD_SHOULD_IGNORE_DIRECT_MESSAGES\",\n\t\t) as string;\n\t\tconst respondOnlyToMentions = runtime.getSetting(\n\t\t\t\"DISCORD_SHOULD_RESPOND_ONLY_TO_MENTIONS\",\n\t\t) as string;\n\n\t\tprintBanner({\n\t\t\tpluginName: \"plugin-discord\",\n\t\t\tdescription: \"Discord bot integration for servers and channels\",\n\t\t\tapplicationId: applicationId || undefined,\n\t\t\tdiscordPermissions: applicationId ? getPermissionValues() : undefined,\n\t\t\tsettings: [\n\t\t\t\t{\n\t\t\t\t\tname: \"DISCORD_API_TOKEN\",\n\t\t\t\t\tvalue: token,\n\t\t\t\t\tsensitive: true,\n\t\t\t\t\trequired: true,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: \"DISCORD_APPLICATION_ID\",\n\t\t\t\t\tvalue: applicationId,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: \"DISCORD_VOICE_CHANNEL_ID\",\n\t\t\t\t\tvalue: voiceChannelId,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: \"CHANNEL_IDS\",\n\t\t\t\t\tvalue: channelIds,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: \"DISCORD_LISTEN_CHANNEL_IDS\",\n\t\t\t\t\tvalue: listenChannelIds,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: \"DISCORD_SHOULD_IGNORE_BOT_MESSAGES\",\n\t\t\t\t\tvalue: ignoreBotMessages,\n\t\t\t\t\tdefaultValue: \"false\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: \"DISCORD_SHOULD_IGNORE_DIRECT_MESSAGES\",\n\t\t\t\t\tvalue: ignoreDirectMessages,\n\t\t\t\t\tdefaultValue: \"false\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: \"DISCORD_SHOULD_RESPOND_ONLY_TO_MENTIONS\",\n\t\t\t\t\tvalue: respondOnlyToMentions,\n\t\t\t\t\tdefaultValue: \"false\",\n\t\t\t\t},\n\t\t\t],\n\t\t\truntime,\n\t\t});\n\n\t\tif (!token || token.trim() === \"\") {\n\t\t\tlogger.warn(\n\t\t\t\t\"Discord API Token not provided - Discord plugin is loaded but will not be functional\",\n\t\t\t);\n\t\t\tlogger.warn(\n\t\t\t\t\"To enable Discord functionality, please provide DISCORD_API_TOKEN in your .eliza/.env file\",\n\t\t\t);\n\t\t}\n\t},\n};\n\nexport default discordPlugin;\n\n// Account management exports (runtime utilities)\nexport {\n\tDEFAULT_ACCOUNT_ID,\n\ttype DiscordMultiAccountConfig,\n\ttype DiscordTokenResolution,\n\ttype DiscordTokenSource,\n\tisMultiAccountEnabled,\n\tlistDiscordAccountIds,\n\tlistEnabledDiscordAccounts,\n\tnormalizeAccountId,\n\tnormalizeDiscordToken,\n\ttype ResolvedDiscordAccount,\n\tresolveDefaultDiscordAccountId,\n\tresolveDiscordAccount,\n\tresolveDiscordToken,\n} from \"./accounts\";\n// Allowlist exports\nexport {\n\ttype AllowListMatchSource,\n\tallowListMatches,\n\ttype ChannelMatchSource,\n\ttype DiscordAllowList,\n\ttype DiscordAllowListMatch,\n\ttype DiscordChannelConfigResolved,\n\tformatDiscordUserTag,\n\tisDiscordAutoThreadOwnedByBot,\n\tisDiscordGroupAllowedByPolicy,\n\tnormalizeDiscordAllowList,\n\tnormalizeDiscordSlug,\n\tresolveDiscordAllowListMatch,\n\tresolveDiscordChannelConfig,\n\tresolveDiscordChannelConfigWithFallback,\n\tresolveDiscordCommandAuthorized,\n\tresolveDiscordGuildEntry,\n\tresolveDiscordShouldRequireMention,\n\tresolveDiscordUserAllowed,\n\tresolveGroupDmAllow,\n\tshouldEmitDiscordReactionNotification,\n\tvalidateMessageAllowed,\n} from \"./allowlist\";\n// Channel configuration types (comprehensive config schema)\n// Re-export config types that were in accounts.ts for backward compatibility\nexport type {\n\tDiscordAccountConfig,\n\tDiscordActionConfig,\n\tDiscordChannelConfig,\n\tDiscordConfig,\n\tDiscordDmConfig,\n\tDiscordExecApprovalConfig,\n\tDiscordGuildChannelConfig,\n\tDiscordGuildEntry,\n\tDiscordIntentsConfig,\n\tDiscordPluralKitConfig,\n\tDiscordReactionNotificationMode,\n} from \"./config\";\nexport { DISCORD_SERVICE_NAME } from \"./constants\";\n// Messaging utilities exports\nexport {\n\tbuildChannelLink,\n\tbuildMessageLink,\n\ttype ChunkDiscordTextOpts,\n\tchunkDiscordText,\n\tchunkDiscordTextWithMode,\n\tescapeDiscordMarkdown,\n\textractAllChannelMentions,\n\textractAllRoleMentions,\n\textractAllUserMentions,\n\textractChannelIdFromMention,\n\textractRoleIdFromMention,\n\textractUserIdFromMention,\n\tformatDiscordChannelMention,\n\tformatDiscordReactionEmoji,\n\tformatDiscordRoleMention,\n\tformatDiscordTimestamp,\n\tformatDiscordUserMention,\n\tformatMessageReactionEmoji,\n\tmessageContainsMention,\n\tparseMessageLink,\n\tresolveDiscordSystemLocation,\n\tresolveTimestampMs,\n\tsanitizeThreadName,\n\tstripDiscordFormatting,\n\ttruncateText,\n\ttruncateUtf16Safe,\n} from \"./messaging\";\n// Native commands utilities exports\nexport {\n\ttype BuiltCommandOption,\n\tbuildCommandArgCustomId,\n\tbuildCommandArgMenu,\n\tbuildCommandText,\n\tbuildDiscordCommandOptions,\n\tbuildDiscordSlashCommand,\n\tCOMMAND_ARG_CUSTOM_ID_KEY,\n\ttype CommandArgButton,\n\ttype CommandArgButtonRow,\n\ttype CommandArgDefinition,\n\ttype CommandArgMenu,\n\ttype CommandArgs,\n\ttype CommandArgValues,\n\tcreateCommandArgs,\n\tdecodeCommandArgValue,\n\tencodeCommandArgValue,\n\tisUnknownInteractionError,\n\ttype NativeCommandSpec,\n\tparseCommandArgCustomId,\n\tsafeInteractionCall,\n\tserializeCommandArgs,\n} from \"./native-commands\";\nexport {\n\tELEVATED_PERMISSIONS,\n\thasElevatedPermissions,\n\tisElevatedRole,\n} from \"./permissionEvents\";\nexport {\n\ttype DiscordPermissionTier,\n\tDiscordPermissionTiers,\n\ttype DiscordPermissionValues,\n\tgenerateAllInviteUrls,\n\tgenerateInviteUrl,\n\tgetPermissionValues,\n} from \"./permissions\";\nexport type { DiscordService as IDiscordService } from \"./service\";\nexport { DiscordService } from \"./service\";\nexport type {\n\tAuditInfo,\n\tChannelPermissionsChangedPayload,\n\tMemberRolesChangedPayload,\n\tPermissionDiff,\n\tPermissionState,\n\tRoleLifecyclePayload,\n\tRolePermissionsChangedPayload,\n} from \"./types\";\nexport { DiscordEventTypes } from \"./types\";\n",
|
|
85
|
+
"import fs from \"node:fs\";\nimport {\n\ttype Action,\n\ttype ActionExample,\n\ttype ActionResult,\n\tChannelType,\n\ttype Content,\n\tContentType,\n\tcomposePromptFromState,\n\ttype HandlerCallback,\n\ttype HandlerOptions,\n\ttype IAgentRuntime,\n\ttype Media,\n\ttype Memory,\n\tMemoryType,\n\tModelType,\n\tparseJSONObjectFromText,\n\ttype State,\n\ttrimTokens,\n} from \"@elizaos/core\";\nimport {\n\tattachmentIdsTemplate,\n\tattachmentSummarizationTemplate as summarizationTemplate,\n} from \"../generated/prompts/typescript/prompts.js\";\nimport { requireActionSpec } from \"../generated/specs/spec-helpers\";\n\n/**\n * Retrieves attachment IDs from a model using a prompt generated from the current state and a template.\n * @param {IAgentRuntime} runtime - The agent runtime to use for interaction with models\n * @param {Memory} _message - The memory object\n * @param {State} state - The current state of the conversation\n * @returns {Promise<{ objective: string; attachmentIds: string[] } | null>} An object containing the objective and attachment IDs, or null if the data could not be retrieved after multiple attempts\n */\nconst getAttachmentIds = async (\n\truntime: IAgentRuntime,\n\t_message: Memory,\n\tstate: State,\n): Promise<{ objective: string; attachmentIds: string[] } | null> => {\n\tconst prompt = composePromptFromState({\n\t\tstate,\n\t\ttemplate: attachmentIdsTemplate,\n\t});\n\n\tfor (let i = 0; i < 5; i++) {\n\t\tconst response = await runtime.useModel(ModelType.TEXT_SMALL, {\n\t\t\tprompt,\n\t\t});\n\t\t// try parsing to a json object\n\t\tconst parsedResponse = parseJSONObjectFromText(response) as {\n\t\t\tobjective: string;\n\t\t\tattachmentIds: string[];\n\t\t} | null;\n\t\t// see if it contains objective and attachmentIds\n\t\tif (parsedResponse?.objective && parsedResponse.attachmentIds) {\n\t\t\treturn parsedResponse;\n\t\t}\n\t}\n\treturn null;\n};\n\n/**\n * Represents an action to summarize user request informed by specific attachments based on their IDs.\n * If a user asks to chat with a PDF, or wants more specific information about a link or video or anything else they've attached, this is the action to use.\n * @typedef {Object} summarizeAction\n * @property {string} name - The name of the action\n * @property {string[]} similes - Similar actions related to summarization with attachments\n * @property {string} description - Description of the action\n * @property {Function} validate - Validation function to check if the action should be triggered based on keywords in the message\n * @property {Function} handler - Handler function to process the user request, summarize attachments, and provide a summary\n * @property {Object[]} examples - Examples demonstrating how to use the action with message content and expected responses\n */\n\nconst spec = requireActionSpec(\"CHAT_WITH_ATTACHMENTS\");\n\nexport const chatWithAttachments: Action = {\n\tname: spec.name,\n\tsimiles: spec.similes ? [...spec.similes] : [],\n\tdescription: spec.description,\n\tvalidate: async (\n\t\truntime: any,\n\t\tmessage: any,\n\t\tstate?: any,\n\t\toptions?: any,\n\t): Promise<boolean> => {\n\t\tconst __avTextRaw =\n\t\t\ttypeof message?.content?.text === \"string\" ? message.content.text : \"\";\n\t\tconst __avText = __avTextRaw.toLowerCase();\n\t\tconst __avKeywords = [\"chat\", \"with\", \"attachments\"];\n\t\tconst __avKeywordOk =\n\t\t\t__avKeywords.length > 0 &&\n\t\t\t__avKeywords.some((word) => word.length > 0 && __avText.includes(word));\n\t\tconst __avRegex = /\\b(?:chat|with|attachments)\\b/i;\n\t\tconst __avRegexOk = __avRegex.test(__avText);\n\t\tconst __avSource = String(\n\t\t\tmessage?.content?.source ?? message?.source ?? \"\",\n\t\t);\n\t\tconst __avExpectedSource = \"\";\n\t\tconst __avSourceOk = __avExpectedSource\n\t\t\t? __avSource === __avExpectedSource\n\t\t\t: Boolean(\n\t\t\t\t\t__avSource ||\n\t\t\t\t\t\tstate ||\n\t\t\t\t\t\truntime?.agentId ||\n\t\t\t\t\t\truntime?.getService ||\n\t\t\t\t\t\truntime?.getSetting,\n\t\t\t\t);\n\t\tconst __avOptions = options && typeof options === \"object\" ? options : {};\n\t\tconst __avInputOk =\n\t\t\t__avText.trim().length > 0 ||\n\t\t\tObject.keys(__avOptions as Record<string, unknown>).length > 0 ||\n\t\t\tBoolean(message?.content && typeof message.content === \"object\");\n\n\t\tif (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst __avLegacyValidate = async (\n\t\t\t_runtime: IAgentRuntime,\n\t\t\tmessage: Memory,\n\t\t\t_state?: State,\n\t\t): Promise<boolean> => {\n\t\t\tconst room = await _runtime.getRoom(message.roomId);\n\n\t\t\t// Only validate for Discord GROUP channels - this action is Discord-specific\n\t\t\tif (\n\t\t\t\t!room ||\n\t\t\t\troom.type !== ChannelType.GROUP ||\n\t\t\t\troom.source !== \"discord\"\n\t\t\t) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// only show if one of the keywords are in the message\n\t\t\tconst keywords: string[] = [\n\t\t\t\t\"attachment\",\n\t\t\t\t\"summary\",\n\t\t\t\t\"summarize\",\n\t\t\t\t\"research\",\n\t\t\t\t\"pdf\",\n\t\t\t\t\"video\",\n\t\t\t\t\"audio\",\n\t\t\t\t\"image\",\n\t\t\t\t\"document\",\n\t\t\t\t\"link\",\n\t\t\t\t\"file\",\n\t\t\t\t\"attachment\",\n\t\t\t\t\"summarize\",\n\t\t\t\t\"code\",\n\t\t\t\t\"report\",\n\t\t\t\t\"write\",\n\t\t\t\t\"details\",\n\t\t\t\t\"information\",\n\t\t\t\t\"talk\",\n\t\t\t\t\"chat\",\n\t\t\t\t\"read\",\n\t\t\t\t\"listen\",\n\t\t\t\t\"watch\",\n\t\t\t];\n\t\t\tconst messageContentText = message.content.text;\n\t\t\treturn keywords.some((keyword) =>\n\t\t\t\tmessageContentText?.toLowerCase().includes(keyword.toLowerCase()),\n\t\t\t);\n\t\t};\n\t\ttry {\n\t\t\treturn Boolean(\n\t\t\t\tawait (__avLegacyValidate as any)(runtime, message, state, options),\n\t\t\t);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t},\n\thandler: async (\n\t\truntime: IAgentRuntime,\n\t\tmessage: Memory,\n\t\tstate?: State,\n\t\t_options?: HandlerOptions,\n\t\tcallback?: HandlerCallback,\n\t): Promise<ActionResult | undefined> => {\n\t\tif (!state) {\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"State is not available.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { success: false, error: \"State is not available\" };\n\t\t}\n\t\tconst callbackData: Content = {\n\t\t\ttext: \"\", // fill in later\n\t\t\tactions: [\"CHAT_WITH_ATTACHMENTS_RESPONSE\"],\n\t\t\tsource: message.content.source,\n\t\t\tattachments: [],\n\t\t};\n\n\t\t// 1. extract attachment IDs from the message\n\t\tconst attachmentData = await getAttachmentIds(runtime, message, state);\n\t\tif (!attachmentData) {\n\t\t\truntime.logger.warn(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:chat-with-attachments\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t},\n\t\t\t\t\"Could not get attachment IDs from message\",\n\t\t\t);\n\t\t\tawait runtime.createMemory(\n\t\t\t\t{\n\t\t\t\t\tentityId: message.entityId,\n\t\t\t\t\tagentId: message.agentId,\n\t\t\t\t\troomId: message.roomId,\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\tsource: message.content.source,\n\t\t\t\t\t\tthought:\n\t\t\t\t\t\t\t\"I tried to chat with attachments but I couldn't get attachment IDs\",\n\t\t\t\t\t\tactions: [\"CHAT_WITH_ATTACHMENTS_FAILED\"],\n\t\t\t\t\t},\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\ttype: MemoryType.CUSTOM,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t\"messages\",\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: \"Could not get attachment IDs from message\",\n\t\t\t};\n\t\t}\n\n\t\tconst { objective, attachmentIds } = attachmentData;\n\n\t\tconst conversationLength = runtime.getConversationLength();\n\n\t\tconst recentMessages = await runtime.getMemories({\n\t\t\ttableName: \"messages\",\n\t\t\troomId: message.roomId,\n\t\t\tcount: conversationLength,\n\t\t\tunique: false,\n\t\t});\n\n\t\t// This is pretty gross but it can catch cases where the returned generated UUID is stupidly wrong for some reason\n\t\tconst attachments = recentMessages\n\t\t\t.filter(\n\t\t\t\t(msg) => msg.content.attachments && msg.content.attachments.length > 0,\n\t\t\t)\n\t\t\t.flatMap((msg) => msg.content.attachments)\n\t\t\t// Ensure attachment is not undefined before accessing properties\n\t\t\t.filter(\n\t\t\t\t(attachment) =>\n\t\t\t\t\tattachment &&\n\t\t\t\t\t(attachmentIds\n\t\t\t\t\t\t.map((attch) => attch.toLowerCase().slice(0, 5))\n\t\t\t\t\t\t.includes(attachment.id.toLowerCase().slice(0, 5)) ||\n\t\t\t\t\t\t// or check the other way\n\t\t\t\t\t\tattachmentIds.some((id) => {\n\t\t\t\t\t\t\tconst attachmentId = id.toLowerCase().slice(0, 5);\n\t\t\t\t\t\t\t// Add check here too\n\t\t\t\t\t\t\treturn attachment?.id?.toLowerCase().includes(attachmentId);\n\t\t\t\t\t\t})),\n\t\t\t);\n\n\t\tconst attachmentsWithText = attachments\n\t\t\t// Ensure attachment is not undefined before accessing properties\n\t\t\t.filter(\n\t\t\t\t(attachment): attachment is NonNullable<typeof attachment> =>\n\t\t\t\t\t!!attachment,\n\t\t\t)\n\t\t\t.map((attachment) => `# ${attachment.title}\\n${attachment.text}`)\n\t\t\t.join(\"\\n\\n\");\n\n\t\tlet currentSummary = \"\";\n\n\t\tconst chunkSize = 8192;\n\n\t\tstate.values.attachmentsWithText = attachmentsWithText;\n\t\tstate.values.objective = objective;\n\t\tconst template = await trimTokens(\n\t\t\tsummarizationTemplate,\n\t\t\tchunkSize,\n\t\t\truntime,\n\t\t);\n\t\tconst prompt = composePromptFromState({\n\t\t\tstate,\n\t\t\t// make sure it fits, we can pad the tokens a bit\n\t\t\t// Get the model's tokenizer based on the current model being used\n\t\t\ttemplate,\n\t\t});\n\n\t\tconst summary = await runtime.useModel(ModelType.TEXT_SMALL, {\n\t\t\tprompt,\n\t\t});\n\n\t\tcurrentSummary = `${currentSummary}\\n${summary}`;\n\n\t\tif (!currentSummary) {\n\t\t\truntime.logger.warn(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:chat-with-attachments\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t},\n\t\t\t\t\"No summary found\",\n\t\t\t);\n\t\t\tawait runtime.createMemory(\n\t\t\t\t{\n\t\t\t\t\tentityId: message.entityId,\n\t\t\t\t\tagentId: message.agentId,\n\t\t\t\t\troomId: message.roomId,\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\tsource: message.content.source,\n\t\t\t\t\t\tthought:\n\t\t\t\t\t\t\t\"I tried to chat with attachments but I couldn't get a summary\",\n\t\t\t\t\t\tactions: [\"CHAT_WITH_ATTACHMENTS_FAILED\"],\n\t\t\t\t\t},\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\ttype: MemoryType.CUSTOM,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t\"messages\",\n\t\t\t);\n\t\t\treturn { success: false, error: \"No summary found\" };\n\t\t}\n\n\t\tcallbackData.text = currentSummary.trim();\n\t\tconst trimmedSummary = currentSummary.trim();\n\t\tif (\n\t\t\tcallbackData.text &&\n\t\t\t((trimmedSummary && trimmedSummary.split(\"\\n\").length < 4) ||\n\t\t\t\t(trimmedSummary && trimmedSummary.split(\" \").length < 100))\n\t\t) {\n\t\t\tcallbackData.text = `Here is the summary:\n\\`\\`\\`md\n${currentSummary.trim()}\n\\`\\`\\`\n`;\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.(callbackData);\n\t\t\t}\n\t\t\treturn { success: true, text: callbackData.text };\n\t\t} else if (currentSummary.trim()) {\n\t\t\tconst summaryDir = \"cache\";\n\t\t\tconst summaryFilename = `${summaryDir}/summary_${Date.now()}.md`;\n\t\t\ttry {\n\t\t\t\tawait fs.promises.mkdir(summaryDir, { recursive: true });\n\n\t\t\t\t// Write file directly first\n\t\t\t\tawait fs.promises.writeFile(summaryFilename, currentSummary, \"utf8\");\n\n\t\t\t\t// Then cache it\n\t\t\t\tawait runtime.setCache<string>(summaryFilename, currentSummary);\n\n\t\t\t\tif (callback) {\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\t...callbackData,\n\t\t\t\t\t\ttext: \"I've attached the summary of the requested attachments as a text file.\",\n\t\t\t\t\t\tattachments: [\n\t\t\t\t\t\t\t...(callbackData.attachments || []),\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tid: summaryFilename,\n\t\t\t\t\t\t\t\turl: summaryFilename,\n\t\t\t\t\t\t\t\ttitle: \"Summary\",\n\t\t\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\t\t\tcontentType: ContentType.DOCUMENT,\n\t\t\t\t\t\t\t} as Media,\n\t\t\t\t\t\t],\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn { success: true, text: `Summary saved to ${summaryFilename}` };\n\t\t\t} catch (error) {\n\t\t\t\truntime.logger.error(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord:action:chat-with-attachments\",\n\t\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t},\n\t\t\t\t\t\"Error in file/cache process\",\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t};\n\t\t\t}\n\t\t} else {\n\t\t\truntime.logger.warn(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:chat-with-attachments\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t},\n\t\t\t\t\"Empty response from chat with attachments action\",\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: \"Empty response from chat with attachments action\",\n\t\t\t};\n\t\t}\n\t},\n\texamples: (spec.examples ?? []) as ActionExample[][],\n};\n\nexport default chatWithAttachments;\n",
|
|
86
|
+
"/**\n * Auto-generated prompt templates\n * DO NOT EDIT - Generated from ../../../../prompts/*.txt\n *\n * These prompts use Handlebars-style template syntax:\n * - {{variableName}} for simple substitution\n * - {{#each items}}...{{/each}} for iteration\n * - {{#if condition}}...{{/if}} for conditionals\n */\n\nexport const attachmentIdsTemplate = `# Messages we are summarizing\n{{recentMessages}}\n\n# Instructions: {{senderName}} is requesting a summary of specific attachments. Your goal is to determine their objective, along with the list of attachment IDs to summarize.\nThe \"objective\" is a detailed description of what the user wants to summarize based on the conversation.\nThe \"attachmentIds\" is an array of attachment IDs that the user wants to summarize. If not specified, default to including all attachments from the conversation.\n\nYour response must be formatted as a JSON block with this structure:\n\\`\\`\\`json\n{\n \"objective\": \"<What the user wants to summarize>\",\n \"attachmentIds\": [\"<Attachment ID 1>\", \"<Attachment ID 2>\", ...]\n}\n\\`\\`\\``;\n\nexport const ATTACHMENT_IDS_TEMPLATE = attachmentIdsTemplate;\n\nexport const attachmentSummarizationTemplate = `# Summarized so far (we are adding to this)\n{{currentSummary}}\n\n# Current attachments we are summarizing\n{{attachmentsWithText}}\n\nSummarization objective: {{objective}}\n\n# Instructions: Summarize the attachments. Return the summary. Do not acknowledge this request, just summarize and continue the existing summary if there is one. Capture any important details based on the objective. Only respond with the new summary text.`;\n\nexport const ATTACHMENT_SUMMARIZATION_TEMPLATE =\n\tattachmentSummarizationTemplate;\n\nexport const channelInfoTemplate = `# Messages we are searching for channel information\n{{recentMessages}}\n\n# Instructions: {{senderName}} is requesting to read messages from a specific Discord channel. Your goal is to determine:\n1. The channel they want to read from (could be the current channel or a mentioned channel)\n2. How many messages they want to read (default to 10 if not specified)\n3. Whether they want a summary or just the messages\n4. If they're looking for messages from a specific person\n\nIf they say \"this channel\" or \"here\", use the current channel.\nIf they mention a specific channel name or ID, extract that.\nIf they ask to \"summarize\" or mention what someone is \"talking about\", set summarize to true.\n\nYour response must be formatted as a JSON block with this structure:\n\\`\\`\\`json\n{\n \"channelIdentifier\": \"<current|channel-name|channel-id>\",\n \"messageCount\": <number between 1 and 50>,\n \"summarize\": true/false,\n \"focusUser\": \"<username or null>\"\n}\n\\`\\`\\``;\n\nexport const CHANNEL_INFO_TEMPLATE = channelInfoTemplate;\n\nexport const createPollTemplate = `# Creating a Discord poll\n{{recentMessages}}\n\n# Instructions: {{senderName}} is requesting to create a poll. Extract:\n1. The poll question\n2. The poll options (2-10 options)\n3. Whether to use emoji reactions (default: true)\n\nExamples:\n- \"create a poll: What game should we play? Options: Minecraft, Fortnite, Among Us\" \n -> question: \"What game should we play?\", options: [\"Minecraft\", \"Fortnite\", \"Among Us\"]\n- \"poll: Should we have a meeting tomorrow? Yes/No\"\n -> question: \"Should we have a meeting tomorrow?\", options: [\"Yes\", \"No\"]\n\nYour response must be formatted as a JSON block:\n\\`\\`\\`json\n{\n \"question\": \"<poll question>\",\n \"options\": [\"<option1>\", \"<option2>\", ...],\n \"useEmojis\": true/false\n}\n\\`\\`\\``;\n\nexport const CREATE_POLL_TEMPLATE = createPollTemplate;\n\nexport const dateRangeTemplate = `# Messages we are summarizing (the conversation is continued after this)\n{{recentMessages}}\n\n# Instructions: {{senderName}} is requesting a summary of the conversation. Your goal is to determine their objective, along with the range of dates that their request covers.\nThe \"objective\" is a detailed description of what the user wants to summarize based on the conversation. If they just ask for a general summary, you can either base it off the conversation if the summary range is very recent, or set the object to be general, like \"a detailed summary of the conversation between all users\".\nThe \"start\" and \"end\" are the range of dates that the user wants to summarize, relative to the current time. The start and end should be relative to the current time, and measured in seconds, minutes, hours and days. The format is \"2 days ago\" or \"3 hours ago\" or \"4 minutes ago\" or \"5 seconds ago\", i.e. \"<integer> <unit> ago\".\nIf you aren't sure, you can use a default range of \"0 minutes ago\" to \"2 hours ago\" or more. Better to err on the side of including too much than too little.\n\nYour response must be formatted as a JSON block with this structure:\n\\`\\`\\`json\n{\n \"objective\": \"<What the user wants to summarize>\",\n \"start\": \"0 minutes ago\",\n \"end\": \"2 hours ago\"\n}\n\\`\\`\\``;\n\nexport const DATE_RANGE_TEMPLATE = dateRangeTemplate;\n\nexport const getUserInfoTemplate = `# Getting Discord user information\n{{recentMessages}}\n\n# Instructions: {{senderName}} is requesting information about a Discord user. Extract:\n1. The user identifier (username, user ID, or mention)\n2. Whether they want detailed server-specific info\n\nExamples:\n- \"who is @john?\" -> userIdentifier: \"john\", detailed: false\n- \"tell me about user 123456789\" -> userIdentifier: \"123456789\", detailed: false \n- \"get detailed info on @admin\" -> userIdentifier: \"admin\", detailed: true\n- \"who am I?\" -> userIdentifier: \"self\", detailed: false\n\nYour response must be formatted as a JSON block:\n\\`\\`\\`json\n{\n \"userIdentifier\": \"<username|user-id|mention|self>\",\n \"detailed\": true/false\n}\n\\`\\`\\``;\n\nexport const GET_USER_INFO_TEMPLATE = getUserInfoTemplate;\n\nexport const joinChannelTemplate = `# Messages we are searching for channel join information\n{{recentMessages}}\n\n# Instructions: {{senderName}} is requesting the bot to join a specific Discord channel (text or voice). Your goal is to determine which channel they want to join.\n\nExtract the channel identifier from their request:\n- If they mention a channel like #general or <#channelid>, extract that\n- If they provide a channel name, extract that\n- If they provide a channel ID (long number), extract that\n- If they mention \"voice\", \"vc\", \"voice channel\", include that as a hint\n\nYour response must be formatted as a JSON block with this structure:\n\\`\\`\\`json\n{\n \"channelIdentifier\": \"<channel-name|channel-id|#mention>\",\n \"isVoiceChannel\": true/false\n}\n\\`\\`\\``;\n\nexport const JOIN_CHANNEL_TEMPLATE = joinChannelTemplate;\n\nexport const leaveChannelTemplate = `# Messages we are searching for channel leave information\n{{recentMessages}}\n\n# Instructions: {{senderName}} is requesting the bot to leave a specific Discord channel (text or voice). Your goal is to determine which channel they want to leave.\n\nExtract the channel identifier from their request:\n- If they mention a channel like #general or <#channelid>, extract that\n- If they provide a channel name (like \"dev-voice\" or \"general\"), extract just the name\n- If they provide a channel ID (long number), extract that\n- If they say \"this channel\" or \"here\", use \"current\"\n- If they don't specify a channel but mention \"voice\", \"vc\", use \"current\" and mark as voice\n\nExamples:\n- \"leave the dev-voice channel\" -> channelIdentifier: \"dev-voice\", isVoiceChannel: true\n- \"leave #general\" -> channelIdentifier: \"general\", isVoiceChannel: false\n- \"leave voice\" -> channelIdentifier: \"current\", isVoiceChannel: true\n- \"stop listening to this channel\" -> channelIdentifier: \"current\", isVoiceChannel: false\n\nYour response must be formatted as a JSON block with this structure:\n\\`\\`\\`json\n{\n \"channelIdentifier\": \"<actual-channel-name-or-id-or-current>\",\n \"isVoiceChannel\": true/false\n}\n\\`\\`\\``;\n\nexport const LEAVE_CHANNEL_TEMPLATE = leaveChannelTemplate;\n\nexport const mediaAttachmentIdTemplate = `# Messages we are transcribing\n{{recentMessages}}\n\n# Instructions: {{senderName}} is requesting a transcription of a specific media file (audio or video). Your goal is to determine the ID of the attachment they want transcribed.\nThe \"attachmentId\" is the ID of the media file attachment that the user wants transcribed. If not specified, return null.\n\nYour response must be formatted as a JSON block with this structure:\n\\`\\`\\`json\n{\n \"attachmentId\": \"<Attachment ID>\"\n}\n\\`\\`\\``;\n\nexport const MEDIA_ATTACHMENT_ID_TEMPLATE = mediaAttachmentIdTemplate;\n\nexport const mediaUrlTemplate = `# Messages we are searching for a media URL\n{{recentMessages}}\n\n# Instructions: {{senderName}} is requesting to download a specific media file (video or audio). Your goal is to determine the URL of the media they want to download.\nThe \"mediaUrl\" is the URL of the media file that the user wants downloaded. If not specified, return null.\n\nYour response must be formatted as a JSON block with this structure:\n\\`\\`\\`json\n{\n \"mediaUrl\": \"<Media URL>\"\n}\n\\`\\`\\``;\n\nexport const MEDIA_URL_TEMPLATE = mediaUrlTemplate;\n\nexport const pinMessageTemplate = `# Pinning a Discord message\n{{recentMessages}}\n\n# Instructions: {{senderName}} wants to pin a message. Extract which message they want to pin.\n\nExamples:\n- \"pin that message\" -> messageRef: \"last\"\n- \"pin the last message\" -> messageRef: \"last\"\n- \"pin john's message about the meeting\" -> messageRef: \"john meeting\"\n- \"pin message 123456789\" -> messageRef: \"123456789\"\n\nYour response must be formatted as a JSON block:\n\\`\\`\\`json\n{\n \"messageRef\": \"<last|previous|message-id|search-text>\"\n}\n\\`\\`\\``;\n\nexport const PIN_MESSAGE_TEMPLATE = pinMessageTemplate;\n\nexport const reactToMessageTemplate = `# Adding reactions to Discord messages\n{{recentMessages}}\n\n# Instructions: {{senderName}} wants to add a reaction to a message. Extract:\n1. Which message to react to (last, specific message reference, or by content)\n2. What emoji/reaction to add\n\nExamples:\n- \"react with 👍 to the last message\" -> messageRef: \"last\", emoji: \"👍\"\n- \"add :fire: reaction\" -> messageRef: \"last\", emoji: \"🔥\" or \":fire:\"\n- \"react to that message with ❤️\" -> messageRef: \"previous\", emoji: \"❤️\"\n- \"add a thumbs up to john's message about the meeting\" -> messageRef: \"john meeting\", emoji: \"👍\"\n\nYour response must be formatted as a JSON block:\n\\`\\`\\`json\n{\n \"messageRef\": \"<last|previous|message-id|search-text>\",\n \"emoji\": \"<emoji-character|:emoji-name:>\"\n}\n\\`\\`\\``;\n\nexport const REACT_TO_MESSAGE_TEMPLATE = reactToMessageTemplate;\n\nexport const searchMessagesTemplate = `# Searching for Discord messages\n{{recentMessages}}\n\n# Instructions: {{senderName}} is requesting to search for messages in Discord. Extract:\n1. The search query/keywords\n2. The channel to search in (current if not specified)\n3. Optional filters like author, time range, or message count\n\nExamples:\n- \"search for messages containing 'meeting'\" -> query: \"meeting\", channelIdentifier: \"current\", NO author field\n- \"find messages from @user about bugs\" -> query: \"bugs\", channelIdentifier: \"current\", author: \"user\"\n- \"search #general for links from last week\" -> query: \"links\", channelIdentifier: \"general\", timeRange: \"week\"\n- \"search for messages about 'spartan' in this channel\" -> query: \"spartan\", channelIdentifier: \"current\"\n\nYour response must be formatted as a JSON block:\n\\`\\`\\`json\n{\n \"query\": \"<search keywords>\",\n \"channelIdentifier\": \"<channel-name|channel-id|current>\",\n \"author\": \"<username>\",\n \"timeRange\": \"<hour|day|week|month>\",\n \"limit\": <number between 1-100, default 20>\n}\n\\`\\`\\``;\n\nexport const SEARCH_MESSAGES_TEMPLATE = searchMessagesTemplate;\n\nexport const sendDmTemplate = `# Messages we are searching for DM information\n{{recentMessages}}\n\n# Instructions: {{senderName}} is requesting to send a direct message to a specific Discord user. Your goal is to determine:\n1. The recipient they want to message (could be a username, user ID, or mentioned user)\n2. The message content they want to send\n\nExtract the recipient identifier and the message content from their request.\n- If they mention a user like @username or <@userid>, extract that\n- If they provide a username or display name, extract that\n- If they provide a user ID (long number), extract that\n- Extract the complete message they want to send\n\nYour response must be formatted as a JSON block with this structure:\n\\`\\`\\`json\n{\n \"recipientIdentifier\": \"<username|user-id|@mention>\",\n \"messageContent\": \"<the message to send>\"\n}\n\\`\\`\\``;\n\nexport const SEND_DM_TEMPLATE = sendDmTemplate;\n\nexport const summarizationTemplate = `# Summarized so far (we are adding to this)\n{{currentSummary}}\n\n# Current conversation chunk we are summarizing (includes attachments)\n{{memoriesWithAttachments}}\n\nSummarization objective: {{objective}}\n\n# Instructions: Summarize the conversation so far. Return the summary. Do not acknowledge this request, just summarize and continue the existing summary if there is one. Capture any important details to the objective. Only respond with the new summary text.\nYour response should be extremely detailed and include any and all relevant information.`;\n\nexport const SUMMARIZATION_TEMPLATE = summarizationTemplate;\n\nexport const transcriptionTemplate = `# Transcription of media file\n{{mediaTranscript}}\n\n# Instructions: Return only the full transcript of the media file without any additional prompt or commentary.`;\n\nexport const TRANSCRIPTION_TEMPLATE = transcriptionTemplate;\n\nexport const unpinMessageTemplate = `# Unpinning a Discord message\n{{recentMessages}}\n\n# Instructions: {{senderName}} wants to unpin a message. Extract which message they want to unpin.\n\nExamples:\n- \"unpin that message\" -> messageRef: \"last_pinned\"\n- \"unpin the last pinned message\" -> messageRef: \"last_pinned\"\n- \"unpin john's message\" -> messageRef: \"john\"\n- \"unpin message about the meeting\" -> messageRef: \"meeting\"\n\nYour response must be formatted as a JSON block:\n\\`\\`\\`json\n{\n \"messageRef\": \"<last_pinned|message-id|search-text>\"\n}\n\\`\\`\\``;\n\nexport const UNPIN_MESSAGE_TEMPLATE = unpinMessageTemplate;\n",
|
|
87
|
+
"/**\n * Auto-generated canonical action/provider/evaluator docs for plugin-discord.\n * DO NOT EDIT - Generated from prompts/specs/**.\n */\n\nexport type ActionDoc = {\n\tname: string;\n\tdescription: string;\n\tsimiles?: readonly string[];\n\tparameters?: readonly unknown[];\n\texamples?: readonly (readonly unknown[])[];\n};\n\nexport type ProviderDoc = {\n\tname: string;\n\tdescription: string;\n\tposition?: number;\n\tdynamic?: boolean;\n};\n\nexport type EvaluatorDoc = {\n\tname: string;\n\tdescription: string;\n\tsimiles?: readonly string[];\n\talwaysRun?: boolean;\n\texamples?: readonly unknown[];\n};\n\nexport const coreActionsSpec = {\n\tversion: \"1.0.0\",\n\tactions: [\n\t\t{\n\t\t\tname: \"name\",\n\t\t\tdescription: \"\",\n\t\t\tparameters: [],\n\t\t},\n\t],\n} as const;\nexport const allActionsSpec = {\n\tversion: \"1.0.0\",\n\tactions: [\n\t\t{\n\t\t\tname: \"name\",\n\t\t\tdescription: \"\",\n\t\t\tparameters: [],\n\t\t},\n\t],\n} as const;\nexport const coreProvidersSpec = {\n\tversion: \"1.0.0\",\n\tproviders: [\n\t\t{\n\t\t\tname: \"channelState\",\n\t\t\tdescription:\n\t\t\t\t\"Provides information about the current Discord channel state, including whether it's a DM or group channel, channel name, and server name.\",\n\t\t\tdynamic: true,\n\t\t},\n\t\t{\n\t\t\tname: \"guildInfo\",\n\t\t\tdescription:\n\t\t\t\t\"Provides information about the current Discord server/guild including member count, creation date, channels, roles, and bot permissions.\",\n\t\t\tdynamic: true,\n\t\t},\n\t\t{\n\t\t\tname: \"voiceState\",\n\t\t\tdescription:\n\t\t\t\t\"Provides information about the voice state of the agent, including whether it is currently in a voice channel.\",\n\t\t\tdynamic: true,\n\t\t},\n\t],\n} as const;\nexport const allProvidersSpec = {\n\tversion: \"1.0.0\",\n\tproviders: [\n\t\t{\n\t\t\tname: \"channelState\",\n\t\t\tdescription:\n\t\t\t\t\"Provides information about the current Discord channel state, including whether it's a DM or group channel, channel name, and server name.\",\n\t\t\tdynamic: true,\n\t\t},\n\t\t{\n\t\t\tname: \"guildInfo\",\n\t\t\tdescription:\n\t\t\t\t\"Provides information about the current Discord server/guild including member count, creation date, channels, roles, and bot permissions.\",\n\t\t\tdynamic: true,\n\t\t},\n\t\t{\n\t\t\tname: \"voiceState\",\n\t\t\tdescription:\n\t\t\t\t\"Provides information about the voice state of the agent, including whether it is currently in a voice channel.\",\n\t\t\tdynamic: true,\n\t\t},\n\t],\n} as const;\nexport const coreEvaluatorsSpec = {\n\tversion: \"1.0.0\",\n\tevaluators: [],\n} as const;\nexport const allEvaluatorsSpec = {\n\tversion: \"1.0.0\",\n\tevaluators: [],\n} as const;\n\nexport const coreActionDocs: readonly ActionDoc[] = coreActionsSpec.actions;\nexport const allActionDocs: readonly ActionDoc[] = allActionsSpec.actions;\nexport const coreProviderDocs: readonly ProviderDoc[] =\n\tcoreProvidersSpec.providers;\nexport const allProviderDocs: readonly ProviderDoc[] =\n\tallProvidersSpec.providers;\nexport const coreEvaluatorDocs: readonly EvaluatorDoc[] =\n\tcoreEvaluatorsSpec.evaluators;\nexport const allEvaluatorDocs: readonly EvaluatorDoc[] =\n\tallEvaluatorsSpec.evaluators;\n",
|
|
88
|
+
"/**\n * Helper functions to lookup action/provider/evaluator specs by name.\n * These allow language-specific implementations to import their text content\n * (description, similes, examples) from the centralized specs.\n *\n * DO NOT EDIT the spec data - update prompts/actions.json, prompts/providers.json, prompts/evaluators.json and regenerate.\n */\n\nimport {\n\ttype ActionDoc,\n\tallActionDocs,\n\tallEvaluatorDocs,\n\tallProviderDocs,\n\tcoreActionDocs,\n\tcoreEvaluatorDocs,\n\tcoreProviderDocs,\n\ttype EvaluatorDoc,\n\ttype ProviderDoc,\n} from \"./specs\";\n\n// Build lookup maps for O(1) access\nconst coreActionMap = new Map<string, ActionDoc>(\n\tcoreActionDocs.map((doc) => [doc.name, doc]),\n);\nconst allActionMap = new Map<string, ActionDoc>(\n\tallActionDocs.map((doc) => [doc.name, doc]),\n);\nconst coreProviderMap = new Map<string, ProviderDoc>(\n\tcoreProviderDocs.map((doc) => [doc.name, doc]),\n);\nconst allProviderMap = new Map<string, ProviderDoc>(\n\tallProviderDocs.map((doc) => [doc.name, doc]),\n);\nconst coreEvaluatorMap = new Map<string, EvaluatorDoc>(\n\tcoreEvaluatorDocs.map((doc) => [doc.name, doc]),\n);\nconst allEvaluatorMap = new Map<string, EvaluatorDoc>(\n\tallEvaluatorDocs.map((doc) => [doc.name, doc]),\n);\n\n/**\n * Get an action spec by name from the core specs.\n * @param name - The action name\n * @returns The action spec or undefined if not found\n */\nexport function getActionSpec(name: string): ActionDoc | undefined {\n\treturn coreActionMap.get(name) ?? allActionMap.get(name);\n}\n\n/**\n * Get an action spec by name, throwing if not found.\n * @param name - The action name\n * @returns The action spec\n * @throws Error if the action is not found\n */\nexport function requireActionSpec(name: string): ActionDoc {\n\tconst spec = getActionSpec(name);\n\tif (!spec) {\n\t\treturn {\n\t\t\tname,\n\t\t\tdescription: `${name} action`,\n\t\t\tsimiles: [],\n\t\t\texamples: [],\n\t\t};\n\t}\n\treturn spec;\n}\n\n/**\n * Get a provider spec by name from the core specs.\n * @param name - The provider name\n * @returns The provider spec or undefined if not found\n */\nexport function getProviderSpec(name: string): ProviderDoc | undefined {\n\treturn coreProviderMap.get(name) ?? allProviderMap.get(name);\n}\n\n/**\n * Get a provider spec by name, throwing if not found.\n * @param name - The provider name\n * @returns The provider spec\n * @throws Error if the provider is not found\n */\nexport function requireProviderSpec(name: string): ProviderDoc {\n\tconst spec = getProviderSpec(name);\n\tif (!spec) {\n\t\tthrow new Error(`Provider spec not found: ${name}`);\n\t}\n\treturn spec;\n}\n\n/**\n * Get an evaluator spec by name from the core specs.\n * @param name - The evaluator name\n * @returns The evaluator spec or undefined if not found\n */\nexport function getEvaluatorSpec(name: string): EvaluatorDoc | undefined {\n\treturn coreEvaluatorMap.get(name) ?? allEvaluatorMap.get(name);\n}\n\n/**\n * Get an evaluator spec by name, throwing if not found.\n * @param name - The evaluator name\n * @returns The evaluator spec\n * @throws Error if the evaluator is not found\n */\nexport function requireEvaluatorSpec(name: string): EvaluatorDoc {\n\tconst spec = getEvaluatorSpec(name);\n\tif (!spec) {\n\t\tthrow new Error(`Evaluator spec not found: ${name}`);\n\t}\n\treturn spec;\n}\n\n// Re-export types for convenience\nexport type { ActionDoc, ProviderDoc, EvaluatorDoc };\n",
|
|
89
|
+
"import {\n\ttype Action,\n\ttype ActionExample,\n\ttype ActionResult,\n\ttype Content,\n\tcomposePromptFromState,\n\ttype HandlerCallback,\n\ttype HandlerOptions,\n\ttype IAgentRuntime,\n\ttype Memory,\n\tModelType,\n\tparseJSONObjectFromText,\n\ttype State,\n} from \"@elizaos/core\";\nimport type { TextChannel } from \"discord.js\";\nimport { DISCORD_SERVICE_NAME } from \"../constants\";\n// Import generated prompts\nimport { createPollTemplate } from \"../generated/prompts/typescript/prompts.js\";\nimport { requireActionSpec } from \"../generated/specs/spec-helpers\";\nimport type { DiscordService } from \"../service\";\n\nconst getPollInfo = async (\n\truntime: IAgentRuntime,\n\t_message: Memory,\n\tstate: State,\n): Promise<{\n\tquestion: string;\n\toptions: string[];\n\tuseEmojis: boolean;\n} | null> => {\n\tconst prompt = composePromptFromState({\n\t\tstate,\n\t\ttemplate: createPollTemplate,\n\t});\n\n\tfor (let i = 0; i < 3; i++) {\n\t\tconst response = await runtime.useModel(ModelType.TEXT_SMALL, {\n\t\t\tprompt,\n\t\t});\n\n\t\tconst parsedResponse = parseJSONObjectFromText(response);\n\t\tif (\n\t\t\tparsedResponse?.question &&\n\t\t\tArray.isArray(parsedResponse.options) &&\n\t\t\tparsedResponse.options.length >= 2\n\t\t) {\n\t\t\treturn {\n\t\t\t\tquestion: String(parsedResponse.question),\n\t\t\t\toptions: parsedResponse.options.slice(0, 10).map(String), // Max 10 options\n\t\t\t\tuseEmojis: parsedResponse.useEmojis !== false, // Default to true\n\t\t\t};\n\t\t}\n\t}\n\treturn null;\n};\n\n// Number emojis for poll options\nconst numberEmojis = [\"1️⃣\", \"2️⃣\", \"3️⃣\", \"4️⃣\", \"5️⃣\", \"6️⃣\", \"7️⃣\", \"8️⃣\", \"9️⃣\", \"🔟\"];\nconst letterEmojis = [\"🇦\", \"🇧\", \"🇨\", \"🇩\", \"🇪\", \"🇫\", \"🇬\", \"🇭\", \"🇮\", \"🇯\"];\nconst yesNoEmojis = [\"✅\", \"❌\"];\n\nconst spec = requireActionSpec(\"CREATE_POLL\");\n\nexport const createPoll: Action = {\n\tname: spec.name,\n\tsimiles: spec.similes ? [...spec.similes] : [],\n\tdescription: spec.description,\n\tvalidate: async (\n\t\truntime: any,\n\t\tmessage: any,\n\t\tstate?: any,\n\t\toptions?: any,\n\t): Promise<boolean> => {\n\t\tconst __avTextRaw =\n\t\t\ttypeof message?.content?.text === \"string\" ? message.content.text : \"\";\n\t\tconst __avText = __avTextRaw.toLowerCase();\n\t\tconst __avKeywords = [\"create\", \"poll\"];\n\t\tconst __avKeywordOk =\n\t\t\t__avKeywords.length > 0 &&\n\t\t\t__avKeywords.some((word) => word.length > 0 && __avText.includes(word));\n\t\tconst __avRegex = /\\b(?:create|poll)\\b/i;\n\t\tconst __avRegexOk = __avRegex.test(__avText);\n\t\tconst __avSource = String(\n\t\t\tmessage?.content?.source ?? message?.source ?? \"\",\n\t\t);\n\t\tconst __avExpectedSource = \"\";\n\t\tconst __avSourceOk = __avExpectedSource\n\t\t\t? __avSource === __avExpectedSource\n\t\t\t: Boolean(\n\t\t\t\t\t__avSource ||\n\t\t\t\t\t\tstate ||\n\t\t\t\t\t\truntime?.agentId ||\n\t\t\t\t\t\truntime?.getService ||\n\t\t\t\t\t\truntime?.getSetting,\n\t\t\t\t);\n\t\tconst __avOptions = options && typeof options === \"object\" ? options : {};\n\t\tconst __avInputOk =\n\t\t\t__avText.trim().length > 0 ||\n\t\t\tObject.keys(__avOptions as Record<string, unknown>).length > 0 ||\n\t\t\tBoolean(message?.content && typeof message.content === \"object\");\n\n\t\tif (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst __avLegacyValidate = async (\n\t\t\t_runtime: IAgentRuntime,\n\t\t\tmessage: Memory,\n\t\t\t_state?: State,\n\t\t): Promise<boolean> => {\n\t\t\treturn message.content.source === \"discord\";\n\t\t};\n\t\ttry {\n\t\t\treturn Boolean(\n\t\t\t\tawait (__avLegacyValidate as any)(runtime, message, state, options),\n\t\t\t);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t},\n\thandler: async (\n\t\truntime: IAgentRuntime,\n\t\tmessage: Memory,\n\t\tstate?: State,\n\t\t_options?: HandlerOptions,\n\t\tcallback?: HandlerCallback,\n\t): Promise<ActionResult | undefined> => {\n\t\tconst discordService = runtime.getService(\n\t\t\tDISCORD_SERVICE_NAME,\n\t\t) as DiscordService;\n\n\t\tif (!discordService || !discordService.client) {\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"Discord service is not available.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { success: false, error: \"Discord service is not available\" };\n\t\t}\n\n\t\tif (!state) {\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"State is not available.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { success: false, error: \"State is not available\" };\n\t\t}\n\n\t\tconst pollInfo = await getPollInfo(runtime, message, state);\n\t\tif (!pollInfo) {\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I couldn't understand the poll details. Please specify a question and at least 2 options.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { success: false, error: \"Could not parse poll details\" };\n\t\t}\n\n\t\ttry {\n\t\t\tconst stateData = state.data;\n\t\t\tconst room = stateData?.room || (await runtime.getRoom(message.roomId));\n\t\t\tif (!room || !room.channelId) {\n\t\t\t\tif (callback) {\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\ttext: \"I couldn't determine the current channel.\",\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn { success: false, error: \"Could not determine current channel\" };\n\t\t\t}\n\n\t\t\tconst channel = await discordService.client.channels.fetch(\n\t\t\t\troom.channelId,\n\t\t\t);\n\t\t\tif (!channel || !channel.isTextBased()) {\n\t\t\t\tif (callback) {\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\ttext: \"I can only create polls in text channels.\",\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn { success: false, error: \"Channel is not a text channel\" };\n\t\t\t}\n\n\t\t\tconst textChannel = channel as TextChannel;\n\n\t\t\t// Determine which emojis to use\n\t\t\tlet emojis: string[];\n\t\t\tif (\n\t\t\t\tpollInfo.options.length === 2 &&\n\t\t\t\tpollInfo.options.some((opt) => opt.toLowerCase().includes(\"yes\")) &&\n\t\t\t\tpollInfo.options.some((opt) => opt.toLowerCase().includes(\"no\"))\n\t\t\t) {\n\t\t\t\temojis = yesNoEmojis;\n\t\t\t} else if (pollInfo.useEmojis) {\n\t\t\t\temojis = numberEmojis.slice(0, pollInfo.options.length);\n\t\t\t} else {\n\t\t\t\temojis = letterEmojis.slice(0, pollInfo.options.length);\n\t\t\t}\n\n\t\t\t// Format the poll message\n\t\t\tconst pollMessage = [\n\t\t\t\t`📊 **POLL: ${pollInfo.question}**`,\n\t\t\t\t\"\",\n\t\t\t\t...pollInfo.options.map(\n\t\t\t\t\t(option, index) => `${emojis[index]} ${option}`,\n\t\t\t\t),\n\t\t\t\t\"\",\n\t\t\t\t\"_React to vote!_\",\n\t\t\t].join(\"\\n\");\n\n\t\t\t// Send the poll message\n\t\t\tconst sentMessage = await textChannel.send(pollMessage);\n\n\t\t\t// Add reactions\n\t\t\tfor (let i = 0; i < pollInfo.options.length; i++) {\n\t\t\t\ttry {\n\t\t\t\t\tawait sentMessage.react(emojis[i]);\n\t\t\t\t\t// Small delay to avoid rate limits\n\t\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, 250));\n\t\t\t\t} catch (error) {\n\t\t\t\t\truntime.logger.error(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord:action:create-poll\",\n\t\t\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\t\t\temoji: emojis[i],\n\t\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Failed to add reaction\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst response: Content = {\n\t\t\t\ttext: `I've created a poll with ${pollInfo.options.length} options. Users can vote by clicking the reaction emojis!`,\n\t\t\t\tsource: message.content.source,\n\t\t\t};\n\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.(response);\n\t\t\t}\n\t\t\treturn { success: true, text: response.text };\n\t\t} catch (error) {\n\t\t\truntime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:create-poll\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error creating poll\",\n\t\t\t);\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I encountered an error while creating the poll. Please make sure I have permission to send messages and add reactions.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t};\n\t\t}\n\t},\n\texamples: (spec.examples ?? []) as ActionExample[][],\n};\n\nexport default createPoll;\n",
|
|
90
|
+
"export const DISCORD_SERVICE_NAME = \"discord\";\n",
|
|
91
|
+
"import {\n\ttype Action,\n\ttype ActionExample,\n\ttype ActionResult,\n\tcomposePromptFromState,\n\ttype HandlerCallback,\n\ttype HandlerOptions,\n\ttype IAgentRuntime,\n\ttype Memory,\n\tModelType,\n\tparseJSONObjectFromText,\n\ttype State,\n} from \"@elizaos/core\";\nimport type { Message, TextChannel } from \"discord.js\";\nimport { DISCORD_SERVICE_NAME } from \"../constants\";\nimport type { DiscordService } from \"../service\";\n\nconst deleteMessageTemplate = `You are helping to extract delete message parameters.\n\nThe user wants to delete a Discord message.\n\nRecent conversation:\n{{recentMessages}}\n\nExtract the following:\n1. messageId: The ID of the message to delete\n2. channelRef: The channel where the message is (default: \"current\")\n\nRespond with a JSON object like:\n{\n \"messageId\": \"123456789\",\n \"channelRef\": \"current\"\n}\n\nOnly respond with the JSON object, no other text.`;\n\ninterface DeleteMessageParams {\n\tmessageId: string;\n\tchannelRef?: string;\n}\n\nconst deleteMessage: Action = {\n\tname: \"DELETE_MESSAGE\",\n\tsimiles: [\"REMOVE_MESSAGE\", \"UNSEND_MESSAGE\", \"DELETE_DISCORD_MESSAGE\"],\n\tdescription: \"Delete a message from a Discord channel\",\n\n\tvalidate: async (\n\t\t_runtime: IAgentRuntime,\n\t\tmessage: Memory,\n\t\t_state?: State,\n\t): Promise<boolean> => {\n\t\treturn message.content.source === \"discord\";\n\t},\n\thandler: async (\n\t\truntime: IAgentRuntime,\n\t\tmessage: Memory,\n\t\tstate?: State,\n\t\t_options?: HandlerOptions,\n\t\tcallback?: HandlerCallback,\n\t): Promise<ActionResult | undefined> => {\n\t\tconst discordService = runtime.getService(\n\t\t\tDISCORD_SERVICE_NAME,\n\t\t) as DiscordService;\n\n\t\tif (!discordService || !discordService.client) {\n\t\t\tawait callback?.({\n\t\t\t\ttext: \"Discord service is not available.\",\n\t\t\t\tsource: \"discord\",\n\t\t\t});\n\t\t\treturn { success: false, error: \"Discord service not available\" };\n\t\t}\n\n\t\t// Ensure state is available\n\t\tconst currentState = state ?? (await runtime.composeState(message));\n\n\t\t// Use LLM to extract delete parameters\n\t\tconst prompt = composePromptFromState({\n\t\t\tstate: currentState,\n\t\t\ttemplate: deleteMessageTemplate,\n\t\t});\n\n\t\tlet deleteParams: DeleteMessageParams | null = null;\n\n\t\tfor (let i = 0; i < 3; i++) {\n\t\t\tconst response = await runtime.useModel(ModelType.TEXT_SMALL, {\n\t\t\t\tprompt,\n\t\t\t});\n\n\t\t\tconst parsedResponse = parseJSONObjectFromText(response) as Record<\n\t\t\t\tstring,\n\t\t\t\tunknown\n\t\t\t> | null;\n\t\t\tif (parsedResponse && typeof parsedResponse.messageId === \"string\") {\n\t\t\t\tdeleteParams = {\n\t\t\t\t\tmessageId: parsedResponse.messageId,\n\t\t\t\t\tchannelRef:\n\t\t\t\t\t\ttypeof parsedResponse.channelRef === \"string\"\n\t\t\t\t\t\t\t? parsedResponse.channelRef\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t};\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (!deleteParams) {\n\t\t\tawait callback?.({\n\t\t\t\ttext: \"I couldn't determine which message to delete.\",\n\t\t\t\tsource: \"discord\",\n\t\t\t});\n\t\t\treturn { success: false, error: \"Failed to extract delete parameters\" };\n\t\t}\n\n\t\ttry {\n\t\t\t// Get the channel\n\t\t\tlet channel: TextChannel | null = null;\n\n\t\t\tif (!deleteParams.channelRef || deleteParams.channelRef === \"current\") {\n\t\t\t\tconst channelId = message.content.channelId as string;\n\t\t\t\tif (channelId) {\n\t\t\t\t\tchannel = discordService.client.channels.cache.get(\n\t\t\t\t\t\tchannelId,\n\t\t\t\t\t) as TextChannel;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Try to find channel by name or ID\n\t\t\t\tchannel = discordService.client.channels.cache.find(\n\t\t\t\t\t(c) =>\n\t\t\t\t\t\tc.id === deleteParams?.channelRef ||\n\t\t\t\t\t\t(c.isTextBased() &&\n\t\t\t\t\t\t\t\"name\" in c &&\n\t\t\t\t\t\t\tc.name === deleteParams?.channelRef),\n\t\t\t\t) as TextChannel;\n\t\t\t}\n\n\t\t\tif (!channel || !channel.isTextBased()) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I couldn't find the channel with that message.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t\treturn { success: false, error: \"Channel not found\" };\n\t\t\t}\n\n\t\t\t// Fetch and delete the message\n\t\t\tconst targetMessage = (await channel.messages.fetch(\n\t\t\t\tdeleteParams.messageId,\n\t\t\t)) as Message;\n\n\t\t\tif (!targetMessage) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I couldn't find the message to delete.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t\treturn { success: false, error: \"Message not found\" };\n\t\t\t}\n\n\t\t\t// Check if we have permission to delete\n\t\t\t// We can delete our own messages or messages in channels where we have MANAGE_MESSAGES\n\t\t\tconst botUser = discordService.client.user;\n\t\t\tconst hasManageMessages = botUser\n\t\t\t\t? (channel.permissionsFor(botUser)?.has(\"ManageMessages\") ?? false)\n\t\t\t\t: false;\n\t\t\tconst canDelete =\n\t\t\t\ttargetMessage.author.id === botUser?.id || hasManageMessages;\n\n\t\t\tif (!canDelete) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I don't have permission to delete that message.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t\treturn { success: false, error: \"No permission to delete message\" };\n\t\t\t}\n\n\t\t\tawait targetMessage.delete();\n\n\t\t\tawait callback?.({\n\t\t\t\ttext: \"I've deleted the message.\",\n\t\t\t\tsource: \"discord\",\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: {\n\t\t\t\t\tmessageId: deleteParams.messageId,\n\t\t\t\t\tchannelId: channel.id,\n\t\t\t\t},\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconst errorMessage =\n\t\t\t\terror instanceof Error ? error.message : String(error);\n\t\t\tawait callback?.({\n\t\t\t\ttext: `Failed to delete message: ${errorMessage}`,\n\t\t\t\tsource: \"discord\",\n\t\t\t});\n\t\t\treturn { success: false, error: errorMessage };\n\t\t}\n\t},\n\n\texamples: [\n\t\t[\n\t\t\t{\n\t\t\t\tname: \"{{name1}}\",\n\t\t\t\tcontent: {\n\t\t\t\t\ttext: \"Delete message 123456789\",\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"{{agentName}}\",\n\t\t\t\tcontent: {\n\t\t\t\t\ttext: \"I'll delete that message now.\",\n\t\t\t\t\tactions: [\"DELETE_MESSAGE\"],\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\t[\n\t\t\t{\n\t\t\t\tname: \"{{name1}}\",\n\t\t\t\tcontent: {\n\t\t\t\t\ttext: \"Remove that spam message\",\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"{{agentName}}\",\n\t\t\t\tcontent: {\n\t\t\t\t\ttext: \"I'll remove that message.\",\n\t\t\t\t\tactions: [\"DELETE_MESSAGE\"],\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t] as ActionExample[][],\n};\n\nexport default deleteMessage;\n",
|
|
92
|
+
"import {\n\ttype Action,\n\ttype ActionExample,\n\ttype ActionResult,\n\ttype Content,\n\tContentType,\n\tcomposePromptFromState,\n\ttype HandlerCallback,\n\ttype HandlerOptions,\n\ttype IAgentRuntime,\n\ttype Media,\n\ttype Memory,\n\tMemoryType,\n\tModelType,\n\tparseJSONObjectFromText,\n\ttype Service,\n\tServiceType,\n\ttype State,\n} from \"@elizaos/core\";\nimport { mediaUrlTemplate } from \"../generated/prompts/typescript/prompts.js\";\nimport { requireActionSpec } from \"../generated/specs/spec-helpers\";\n\n/**\n * Get a media URL from the user through text input using the provided runtime and state.\n * @param {IAgentRuntime} runtime - The runtime object to interact with the agent.\n * @param {Memory} _message - The memory object containing the input message.\n * @param {State} state - The state of the conversation.\n * @returns {Promise<string | null>} The media URL provided by the user or null if no valid URL is provided.\n */\nconst getMediaUrl = async (\n\truntime: IAgentRuntime,\n\t_message: Memory,\n\tstate: State,\n): Promise<string | null> => {\n\tconst prompt = composePromptFromState({\n\t\tstate,\n\t\ttemplate: mediaUrlTemplate,\n\t});\n\n\tfor (let i = 0; i < 5; i++) {\n\t\tconst response = await runtime.useModel(ModelType.TEXT_SMALL, {\n\t\t\tprompt,\n\t\t});\n\n\t\tconst parsedResponse = parseJSONObjectFromText(response) as {\n\t\t\tmediaUrl: string;\n\t\t} | null;\n\n\t\tif (parsedResponse?.mediaUrl) {\n\t\t\treturn parsedResponse.mediaUrl;\n\t\t}\n\t}\n\treturn null;\n};\n\nconst spec = requireActionSpec(\"DOWNLOAD_MEDIA\");\n\nexport const downloadMedia: Action = {\n\tname: spec.name,\n\tsimiles: spec.similes ? [...spec.similes] : [],\n\tdescription: spec.description,\n\tvalidate: async (\n\t\truntime: any,\n\t\tmessage: any,\n\t\tstate?: any,\n\t\toptions?: any,\n\t): Promise<boolean> => {\n\t\tconst __avTextRaw =\n\t\t\ttypeof message?.content?.text === \"string\" ? message.content.text : \"\";\n\t\tconst __avText = __avTextRaw.toLowerCase();\n\t\tconst __avKeywords = [\"download\", \"media\"];\n\t\tconst __avKeywordOk =\n\t\t\t__avKeywords.length > 0 &&\n\t\t\t__avKeywords.some((word) => word.length > 0 && __avText.includes(word));\n\t\tconst __avRegex = /\\b(?:download|media)\\b/i;\n\t\tconst __avRegexOk = __avRegex.test(__avText);\n\t\tconst __avSource = String(\n\t\t\tmessage?.content?.source ?? message?.source ?? \"\",\n\t\t);\n\t\tconst __avExpectedSource = \"\";\n\t\tconst __avSourceOk = __avExpectedSource\n\t\t\t? __avSource === __avExpectedSource\n\t\t\t: Boolean(\n\t\t\t\t\t__avSource ||\n\t\t\t\t\t\tstate ||\n\t\t\t\t\t\truntime?.agentId ||\n\t\t\t\t\t\truntime?.getService ||\n\t\t\t\t\t\truntime?.getSetting,\n\t\t\t\t);\n\t\tconst __avOptions = options && typeof options === \"object\" ? options : {};\n\t\tconst __avInputOk =\n\t\t\t__avText.trim().length > 0 ||\n\t\t\tObject.keys(__avOptions as Record<string, unknown>).length > 0 ||\n\t\t\tBoolean(message?.content && typeof message.content === \"object\");\n\n\t\tif (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst __avLegacyValidate = async (\n\t\t\t_runtime: IAgentRuntime,\n\t\t\tmessage: Memory,\n\t\t\t_state?: State,\n\t\t): Promise<boolean> => {\n\t\t\treturn message.content.source === \"discord\";\n\t\t};\n\t\ttry {\n\t\t\treturn Boolean(\n\t\t\t\tawait (__avLegacyValidate as any)(runtime, message, state, options),\n\t\t\t);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t},\n\thandler: async (\n\t\truntime: IAgentRuntime,\n\t\tmessage: Memory,\n\t\tstate?: State,\n\t\t_options?: HandlerOptions,\n\t\tcallback?: HandlerCallback,\n\t): Promise<ActionResult | undefined> => {\n\t\t// Define the expected video service interface\n\t\tinterface VideoServiceInterface extends Service {\n\t\t\tfetchVideoInfo: (\n\t\t\t\turl: string,\n\t\t\t) => Promise<{ title: string; description: string }>;\n\t\t\tdownloadVideo: (videoInfo: {\n\t\t\t\ttitle: string;\n\t\t\t\tdescription: string;\n\t\t\t}) => Promise<string>;\n\t\t}\n\n\t\tconst videoService = runtime.getService<VideoServiceInterface>(\n\t\t\tServiceType.VIDEO,\n\t\t);\n\n\t\tif (!videoService) {\n\t\t\truntime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:download-media\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t},\n\t\t\t\t\"Video service not found\",\n\t\t\t);\n\t\t\treturn { success: false, error: \"Video service not available\" };\n\t\t}\n\n\t\tif (!state) {\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"State is not available.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { success: false, error: \"State is not available\" };\n\t\t}\n\n\t\tconst mediaUrl = await getMediaUrl(runtime, message, state);\n\t\tif (!mediaUrl) {\n\t\t\truntime.logger.warn(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:download-media\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t},\n\t\t\t\t\"Could not get media URL from messages\",\n\t\t\t);\n\t\t\tawait runtime.createMemory(\n\t\t\t\t{\n\t\t\t\t\tentityId: message.entityId,\n\t\t\t\t\tagentId: message.agentId,\n\t\t\t\t\troomId: message.roomId,\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\tthought: \"I couldn't find the media URL in the message\",\n\t\t\t\t\t\tactions: [\"DOWNLOAD_MEDIA_FAILED\"],\n\t\t\t\t\t},\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\ttype: MemoryType.CUSTOM,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t\"messages\",\n\t\t\t);\n\t\t\treturn { success: false, error: \"Could not get media URL from messages\" };\n\t\t}\n\n\t\tconst videoInfo = await videoService.fetchVideoInfo(mediaUrl);\n\t\tconst mediaPath = await videoService.downloadVideo(videoInfo);\n\n\t\tconst response: Content = {\n\t\t\ttext: `I downloaded the video \"${videoInfo.title}\" and attached it below.`,\n\t\t\tactions: [\"DOWNLOAD_MEDIA_RESPONSE\"],\n\t\t\tsource: message.content.source,\n\t\t\tattachments: [],\n\t\t};\n\n\t\tconst maxRetries = 3;\n\t\tlet retries = 0;\n\n\t\twhile (retries < maxRetries) {\n\t\t\ttry {\n\t\t\t\tawait callback?.({\n\t\t\t\t\t...response,\n\t\t\t\t\tattachments: [\n\t\t\t\t\t\t...(response.attachments || []),\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tid: mediaPath,\n\t\t\t\t\t\t\turl: mediaPath,\n\t\t\t\t\t\t\ttitle: \"Downloaded Media\",\n\t\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\t\tcontentType: ContentType.DOCUMENT,\n\t\t\t\t\t\t} as Media,\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t} catch (error) {\n\t\t\t\tretries++;\n\t\t\t\truntime.logger.error(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord:action:download-media\",\n\t\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\t\tattempt: retries,\n\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t},\n\t\t\t\t\t\"Error sending message\",\n\t\t\t\t);\n\n\t\t\t\tif (retries === maxRetries) {\n\t\t\t\t\truntime.logger.error(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord:action:download-media\",\n\t\t\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\t\t\tmaxRetries,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Max retries reached, failed to send message with attachment\",\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t// Wait for a short delay before retrying\n\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, 2000));\n\t\t\t}\n\t\t}\n\n\t\treturn { success: true, ...response };\n\t},\n\texamples: (spec.examples ?? []) as ActionExample[][],\n};\n\nexport default downloadMedia;\n",
|
|
93
|
+
"import {\n\ttype Action,\n\ttype ActionExample,\n\ttype ActionResult,\n\tcomposePromptFromState,\n\ttype HandlerCallback,\n\ttype HandlerOptions,\n\ttype IAgentRuntime,\n\ttype Memory,\n\tModelType,\n\tparseJSONObjectFromText,\n\ttype State,\n} from \"@elizaos/core\";\nimport type { Message, TextChannel } from \"discord.js\";\nimport { DISCORD_SERVICE_NAME } from \"../constants\";\nimport type { DiscordService } from \"../service\";\n\nconst editMessageTemplate = `You are helping to extract edit message parameters.\n\nThe user wants to edit an existing Discord message.\n\nRecent conversation:\n{{recentMessages}}\n\nExtract the following:\n1. messageId: The ID of the message to edit\n2. newText: The new text content for the message\n3. channelRef: The channel where the message is (default: \"current\")\n\nRespond with a JSON object like:\n{\n \"messageId\": \"123456789\",\n \"newText\": \"The updated message text\",\n \"channelRef\": \"current\"\n}\n\nOnly respond with the JSON object, no other text.`;\n\ninterface EditMessageParams {\n\tmessageId: string;\n\tnewText: string;\n\tchannelRef?: string;\n}\n\nconst editMessage: Action = {\n\tname: \"EDIT_MESSAGE\",\n\tsimiles: [\n\t\t\"UPDATE_MESSAGE\",\n\t\t\"MODIFY_MESSAGE\",\n\t\t\"CHANGE_MESSAGE\",\n\t\t\"EDIT_DISCORD_MESSAGE\",\n\t],\n\tdescription: \"Edit an existing message in a Discord channel\",\n\n\tvalidate: async (\n\t\t_runtime: IAgentRuntime,\n\t\tmessage: Memory,\n\t\t_state?: State,\n\t): Promise<boolean> => {\n\t\treturn message.content.source === \"discord\";\n\t},\n\thandler: async (\n\t\truntime: IAgentRuntime,\n\t\tmessage: Memory,\n\t\tstate?: State,\n\t\t_options?: HandlerOptions,\n\t\tcallback?: HandlerCallback,\n\t): Promise<ActionResult | undefined> => {\n\t\tconst discordService = runtime.getService(\n\t\t\tDISCORD_SERVICE_NAME,\n\t\t) as DiscordService;\n\n\t\tif (!discordService || !discordService.client) {\n\t\t\tawait callback?.({\n\t\t\t\ttext: \"Discord service is not available.\",\n\t\t\t\tsource: \"discord\",\n\t\t\t});\n\t\t\treturn { success: false, error: \"Discord service not available\" };\n\t\t}\n\n\t\t// Ensure state is available\n\t\tconst currentState = state ?? (await runtime.composeState(message));\n\n\t\t// Use LLM to extract edit parameters\n\t\tconst prompt = composePromptFromState({\n\t\t\tstate: currentState,\n\t\t\ttemplate: editMessageTemplate,\n\t\t});\n\n\t\tlet editParams: EditMessageParams | null = null;\n\n\t\tfor (let i = 0; i < 3; i++) {\n\t\t\tconst response = await runtime.useModel(ModelType.TEXT_SMALL, {\n\t\t\t\tprompt,\n\t\t\t});\n\n\t\t\tconst parsedResponse = parseJSONObjectFromText(response) as Record<\n\t\t\t\tstring,\n\t\t\t\tunknown\n\t\t\t> | null;\n\t\t\tif (\n\t\t\t\tparsedResponse &&\n\t\t\t\ttypeof parsedResponse.messageId === \"string\" &&\n\t\t\t\ttypeof parsedResponse.newText === \"string\"\n\t\t\t) {\n\t\t\t\teditParams = {\n\t\t\t\t\tmessageId: parsedResponse.messageId,\n\t\t\t\t\tnewText: parsedResponse.newText,\n\t\t\t\t\tchannelRef:\n\t\t\t\t\t\ttypeof parsedResponse.channelRef === \"string\"\n\t\t\t\t\t\t\t? parsedResponse.channelRef\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t};\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (!editParams) {\n\t\t\tawait callback?.({\n\t\t\t\ttext: \"I couldn't determine which message to edit or what to change it to.\",\n\t\t\t\tsource: \"discord\",\n\t\t\t});\n\t\t\treturn { success: false, error: \"Failed to extract edit parameters\" };\n\t\t}\n\n\t\ttry {\n\t\t\t// Get the channel\n\t\t\tlet channel: TextChannel | null = null;\n\n\t\t\tif (!editParams.channelRef || editParams.channelRef === \"current\") {\n\t\t\t\tconst channelId = message.content.channelId as string;\n\t\t\t\tif (channelId) {\n\t\t\t\t\tchannel = discordService.client.channels.cache.get(\n\t\t\t\t\t\tchannelId,\n\t\t\t\t\t) as TextChannel;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Try to find channel by name or ID\n\t\t\t\tchannel = discordService.client.channels.cache.find(\n\t\t\t\t\t(c) =>\n\t\t\t\t\t\tc.id === editParams?.channelRef ||\n\t\t\t\t\t\t(c.isTextBased() &&\n\t\t\t\t\t\t\t\"name\" in c &&\n\t\t\t\t\t\t\tc.name === editParams?.channelRef),\n\t\t\t\t) as TextChannel;\n\t\t\t}\n\n\t\t\tif (!channel || !channel.isTextBased()) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I couldn't find the channel to edit the message in.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t\treturn { success: false, error: \"Channel not found\" };\n\t\t\t}\n\n\t\t\t// Fetch and edit the message\n\t\t\tconst targetMessage = (await channel.messages.fetch(\n\t\t\t\teditParams.messageId,\n\t\t\t)) as Message;\n\n\t\t\tif (!targetMessage) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I couldn't find the message to edit.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t\treturn { success: false, error: \"Message not found\" };\n\t\t\t}\n\n\t\t\t// Check if we can edit this message (must be our own message)\n\t\t\tif (targetMessage.author.id !== discordService.client.user?.id) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I can only edit my own messages.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: \"Cannot edit messages from other users\",\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tawait targetMessage.edit(editParams.newText);\n\n\t\t\tawait callback?.({\n\t\t\t\ttext: `I've edited the message to: \"${editParams.newText}\"`,\n\t\t\t\tsource: \"discord\",\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: {\n\t\t\t\t\tmessageId: editParams.messageId,\n\t\t\t\t\tchannelId: channel.id,\n\t\t\t\t\tnewText: editParams.newText,\n\t\t\t\t},\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconst errorMessage =\n\t\t\t\terror instanceof Error ? error.message : String(error);\n\t\t\tawait callback?.({\n\t\t\t\ttext: `Failed to edit message: ${errorMessage}`,\n\t\t\t\tsource: \"discord\",\n\t\t\t});\n\t\t\treturn { success: false, error: errorMessage };\n\t\t}\n\t},\n\n\texamples: [\n\t\t[\n\t\t\t{\n\t\t\t\tname: \"{{name1}}\",\n\t\t\t\tcontent: {\n\t\t\t\t\ttext: \"Edit message 123456789 to say 'Hello updated!'\",\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"{{agentName}}\",\n\t\t\t\tcontent: {\n\t\t\t\t\ttext: \"I'll edit that message now.\",\n\t\t\t\t\tactions: [\"EDIT_MESSAGE\"],\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\t[\n\t\t\t{\n\t\t\t\tname: \"{{name1}}\",\n\t\t\t\tcontent: {\n\t\t\t\t\ttext: \"Update the previous message to fix the typo\",\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"{{agentName}}\",\n\t\t\t\tcontent: {\n\t\t\t\t\ttext: \"I'll update that message.\",\n\t\t\t\t\tactions: [\"EDIT_MESSAGE\"],\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t] as ActionExample[][],\n};\n\nexport default editMessage;\n",
|
|
94
|
+
"import {\n\ttype Action,\n\ttype ActionExample,\n\ttype ActionResult,\n\ttype Content,\n\tcomposePromptFromState,\n\ttype HandlerCallback,\n\ttype HandlerOptions,\n\ttype IAgentRuntime,\n\ttype Memory,\n\tModelType,\n\tparseJSONObjectFromText,\n\ttype State,\n} from \"@elizaos/core\";\nimport type { GuildMember } from \"discord.js\";\nimport { DISCORD_SERVICE_NAME } from \"../constants\";\n// Import generated prompts\nimport { getUserInfoTemplate } from \"../generated/prompts/typescript/prompts.js\";\nimport { requireActionSpec } from \"../generated/specs/spec-helpers\";\nimport type { DiscordService } from \"../service\";\n\nconst getUserIdentifier = async (\n\truntime: IAgentRuntime,\n\t_message: Memory,\n\tstate: State,\n): Promise<{\n\tuserIdentifier: string;\n\tdetailed: boolean;\n} | null> => {\n\tconst prompt = composePromptFromState({\n\t\tstate,\n\t\ttemplate: getUserInfoTemplate,\n\t});\n\n\tfor (let i = 0; i < 3; i++) {\n\t\tconst response = await runtime.useModel(ModelType.TEXT_SMALL, {\n\t\t\tprompt,\n\t\t});\n\n\t\tconst parsedResponse = parseJSONObjectFromText(response);\n\t\tif (parsedResponse?.userIdentifier) {\n\t\t\treturn {\n\t\t\t\tuserIdentifier: String(parsedResponse.userIdentifier),\n\t\t\t\tdetailed: parsedResponse.detailed === true,\n\t\t\t};\n\t\t}\n\t}\n\treturn null;\n};\n\nconst formatUserInfo = (\n\tmember: GuildMember,\n\tdetailed: boolean = false,\n): string => {\n\tconst user = member.user;\n\tconst joinedAt = member.joinedAt\n\t\t? new Date(member.joinedAt).toLocaleDateString()\n\t\t: \"Unknown\";\n\tconst createdAt = new Date(user.createdAt).toLocaleDateString();\n\tconst roles =\n\t\tmember.roles.cache\n\t\t\t.filter((role) => role.name !== \"@everyone\")\n\t\t\t.map((role) => role.name)\n\t\t\t.join(\", \") || \"No roles\";\n\n\tconst basicInfo = [\n\t\t\"👤 **User Information**\",\n\t\t`**Username:** ${user.username}${user.discriminator !== \"0\" ? `#${user.discriminator}` : \"\"}`,\n\t\t`**Display Name:** ${member.displayName}`,\n\t\t`**ID:** ${user.id}`,\n\t\t`**Bot:** ${user.bot ? \"Yes\" : \"No\"}`,\n\t\t`**Account Created:** ${createdAt}`,\n\t];\n\n\tif (detailed) {\n\t\tconst serverInfo = [\n\t\t\t\"\",\n\t\t\t\"🏛️ **Server Information**\",\n\t\t\t`**Nickname:** ${member.nickname || \"None\"}`,\n\t\t\t`**Joined Server:** ${joinedAt}`,\n\t\t\t`**Roles:** ${roles}`,\n\t\t\t`**Highest Role:** ${member.roles.highest.name}`,\n\t\t\t`**Permissions:** ${member.permissions.toArray().slice(0, 5).join(\", \")}${member.permissions.toArray().length > 5 ? \"...\" : \"\"}`,\n\t\t\t`**Voice Channel:** ${member.voice.channel ? member.voice.channel.name : \"Not in voice\"}`,\n\t\t\t`**Status:** ${member.presence?.status || \"offline\"}`,\n\t\t];\n\t\treturn [...basicInfo, ...serverInfo].join(\"\\n\");\n\t}\n\n\treturn basicInfo.join(\"\\n\");\n};\n\nconst spec = requireActionSpec(\"GET_USER_INFO\");\n\nexport const getUserInfo: Action = {\n\tname: spec.name,\n\tsimiles: spec.similes ? [...spec.similes] : [],\n\tdescription: spec.description,\n\tvalidate: async (\n\t\truntime: any,\n\t\tmessage: any,\n\t\tstate?: any,\n\t\toptions?: any,\n\t): Promise<boolean> => {\n\t\tconst __avTextRaw =\n\t\t\ttypeof message?.content?.text === \"string\" ? message.content.text : \"\";\n\t\tconst __avText = __avTextRaw.toLowerCase();\n\t\tconst __avKeywords = [\"get\", \"user\", \"info\"];\n\t\tconst __avKeywordOk =\n\t\t\t__avKeywords.length > 0 &&\n\t\t\t__avKeywords.some((word) => word.length > 0 && __avText.includes(word));\n\t\tconst __avRegex = /\\b(?:get|user|info)\\b/i;\n\t\tconst __avRegexOk = __avRegex.test(__avText);\n\t\tconst __avSource = String(\n\t\t\tmessage?.content?.source ?? message?.source ?? \"\",\n\t\t);\n\t\tconst __avExpectedSource = \"\";\n\t\tconst __avSourceOk = __avExpectedSource\n\t\t\t? __avSource === __avExpectedSource\n\t\t\t: Boolean(\n\t\t\t\t\t__avSource ||\n\t\t\t\t\t\tstate ||\n\t\t\t\t\t\truntime?.agentId ||\n\t\t\t\t\t\truntime?.getService ||\n\t\t\t\t\t\truntime?.getSetting,\n\t\t\t\t);\n\t\tconst __avOptions = options && typeof options === \"object\" ? options : {};\n\t\tconst __avInputOk =\n\t\t\t__avText.trim().length > 0 ||\n\t\t\tObject.keys(__avOptions as Record<string, unknown>).length > 0 ||\n\t\t\tBoolean(message?.content && typeof message.content === \"object\");\n\n\t\tif (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst __avLegacyValidate = async (\n\t\t\t_runtime: IAgentRuntime,\n\t\t\tmessage: Memory,\n\t\t\t_state?: State,\n\t\t): Promise<boolean> => {\n\t\t\treturn message.content.source === \"discord\";\n\t\t};\n\t\ttry {\n\t\t\treturn Boolean(\n\t\t\t\tawait (__avLegacyValidate as any)(runtime, message, state, options),\n\t\t\t);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t},\n\thandler: async (\n\t\truntime: IAgentRuntime,\n\t\tmessage: Memory,\n\t\tstate?: State,\n\t\t_options?: HandlerOptions,\n\t\tcallback?: HandlerCallback,\n\t): Promise<ActionResult | undefined> => {\n\t\tconst discordService = runtime.getService(\n\t\t\tDISCORD_SERVICE_NAME,\n\t\t) as DiscordService;\n\n\t\tif (!discordService || !discordService.client) {\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"Discord service is not available.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { success: false, error: \"Discord service is not available\" };\n\t\t}\n\n\t\tif (!state) {\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"State is not available.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { success: false, error: \"State is not available\" };\n\t\t}\n\n\t\tconst userInfo = await getUserIdentifier(runtime, message, state);\n\t\tif (!userInfo) {\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I couldn't understand which user you want information about. Please specify a username or mention.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { success: false, error: \"Could not parse user identifier\" };\n\t\t}\n\n\t\ttry {\n\t\t\tconst room = state.data?.room || (await runtime.getRoom(message.roomId));\n\t\t\tconst serverId = room?.messageServerId;\n\t\t\tif (!serverId) {\n\t\t\t\tif (callback) {\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\ttext: \"I couldn't determine the current server.\",\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn { success: false, error: \"Could not determine current server\" };\n\t\t\t}\n\n\t\t\tconst guild = await discordService.client.guilds.fetch(serverId);\n\n\t\t\tlet member: GuildMember | null = null;\n\n\t\t\t// Handle \"self\" request\n\t\t\tif (userInfo.userIdentifier === \"self\") {\n\t\t\t\tconst content = message.content as {\n\t\t\t\t\tuser_id?: string;\n\t\t\t\t\tuserId?: string;\n\t\t\t\t};\n\t\t\t\tconst authorId = content.user_id || content.userId;\n\t\t\t\tif (authorId && typeof authorId === \"string\") {\n\t\t\t\t\tconst cleanId = authorId.replace(\"discord:\", \"\");\n\t\t\t\t\ttry {\n\t\t\t\t\t\tmember = await guild.members.fetch(cleanId);\n\t\t\t\t\t} catch (_e) {\n\t\t\t\t\t\t// User not found\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Remove mention formatting if present\n\t\t\t\tconst cleanIdentifier = userInfo.userIdentifier.replace(/[<@!>]/g, \"\");\n\n\t\t\t\t// Try to fetch by ID first\n\t\t\t\tif (/^\\d+$/.test(cleanIdentifier)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tmember = await guild.members.fetch(cleanIdentifier);\n\t\t\t\t\t} catch (_e) {\n\t\t\t\t\t\t// Not an ID or user not found\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If not found by ID, search by username or display name\n\t\t\t\tif (!member) {\n\t\t\t\t\tconst members = await guild.members.fetch();\n\t\t\t\t\tmember =\n\t\t\t\t\t\tmembers.find(\n\t\t\t\t\t\t\t(m) =>\n\t\t\t\t\t\t\t\tm.user.username.toLowerCase() ===\n\t\t\t\t\t\t\t\t\tuserInfo.userIdentifier.toLowerCase() ||\n\t\t\t\t\t\t\t\tm.displayName.toLowerCase() ===\n\t\t\t\t\t\t\t\t\tuserInfo.userIdentifier.toLowerCase() ||\n\t\t\t\t\t\t\t\t(m.user.discriminator !== \"0\" &&\n\t\t\t\t\t\t\t\t\t`${m.user.username}#${m.user.discriminator}`.toLowerCase() ===\n\t\t\t\t\t\t\t\t\t\tuserInfo.userIdentifier.toLowerCase()),\n\t\t\t\t\t\t) || null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!member) {\n\t\t\t\tif (callback) {\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\ttext: `I couldn't find a user with the identifier \"${userInfo.userIdentifier}\" in this server.`,\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: `User not found: ${userInfo.userIdentifier}`,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst infoText = formatUserInfo(member, userInfo.detailed);\n\n\t\t\tconst response: Content = {\n\t\t\t\ttext: infoText,\n\t\t\t\tsource: message.content.source,\n\t\t\t};\n\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.(response);\n\t\t\t}\n\t\t\treturn { success: true, text: response.text };\n\t\t} catch (error) {\n\t\t\truntime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:get-user-info\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error getting user info\",\n\t\t\t);\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I encountered an error while getting user information. Please try again.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t};\n\t\t}\n\t},\n\texamples: (spec.examples ?? []) as ActionExample[][],\n};\n\nexport default getUserInfo;\n",
|
|
95
|
+
"import {\n\ttype Action,\n\ttype ActionExample,\n\ttype ActionResult,\n\ttype Content,\n\tcomposePromptFromState,\n\tcreateUniqueUuid,\n\ttype HandlerCallback,\n\ttype HandlerOptions,\n\ttype IAgentRuntime,\n\ttype Memory,\n\tMemoryType,\n\tModelType,\n\tparseJSONObjectFromText,\n\ttype State,\n} from \"@elizaos/core\";\nimport type { BaseGuildVoiceChannel, TextChannel } from \"discord.js\";\nimport { ChannelType as DiscordChannelType } from \"discord.js\";\nimport { DISCORD_SERVICE_NAME } from \"../constants\";\nimport { joinChannelTemplate } from \"../generated/prompts/typescript/prompts.js\";\nimport { requireActionSpec } from \"../generated/specs/spec-helpers\";\nimport type { DiscordService } from \"../service\";\nimport type { VoiceManager } from \"../voice\";\n\n/**\n * Get channel information from the user's request\n * @param {IAgentRuntime} runtime - The runtime object to interact with the agent.\n * @param {Memory} _message - The memory object containing the input message.\n * @param {State} state - The state of the conversation.\n * @returns {Promise<{channelIdentifier: string, isVoiceChannel: boolean} | null>} Channel info or null if not parseable.\n */\nconst getJoinChannelInfo = async (\n\truntime: IAgentRuntime,\n\t_message: Memory,\n\tstate: State,\n): Promise<{ channelIdentifier: string; isVoiceChannel: boolean } | null> => {\n\tconst prompt = composePromptFromState({\n\t\tstate,\n\t\ttemplate: joinChannelTemplate,\n\t});\n\n\tfor (let i = 0; i < 3; i++) {\n\t\tconst response = await runtime.useModel(ModelType.TEXT_SMALL, {\n\t\t\tprompt,\n\t\t});\n\n\t\tconst parsedResponse = parseJSONObjectFromText(response) as {\n\t\t\tchannelIdentifier: string;\n\t\t\tisVoiceChannel: boolean;\n\t\t} | null;\n\n\t\tif (parsedResponse?.channelIdentifier) {\n\t\t\treturn parsedResponse;\n\t\t}\n\t}\n\treturn null;\n};\n\n/**\n * Find a Discord channel by various identifiers\n * @param {DiscordService} discordService - The Discord service instance\n * @param {string} identifier - The channel identifier (name, ID, or mention)\n * @param {string} currentServerId - The current server ID to search in\n * @param {boolean} isVoiceChannel - Whether to look for voice channels\n * @returns {Promise<TextChannel | BaseGuildVoiceChannel | null>} The found channel or null\n */\nconst findChannel = async (\n\tdiscordService: DiscordService,\n\tidentifier: string,\n\tcurrentServerId?: string,\n\tisVoiceChannel?: boolean,\n): Promise<TextChannel | BaseGuildVoiceChannel | null> => {\n\tif (!discordService.client) {\n\t\treturn null;\n\t}\n\n\t// Remove channel mention formatting if present\n\tconst cleanId = identifier.replace(/[<#>]/g, \"\");\n\n\ttry {\n\t\t// Try to fetch by ID first\n\t\tif (/^\\d+$/.test(cleanId)) {\n\t\t\ttry {\n\t\t\t\tconst channel = await discordService.client.channels.fetch(cleanId);\n\t\t\t\tif (\n\t\t\t\t\tisVoiceChannel &&\n\t\t\t\t\tchannel &&\n\t\t\t\t\tchannel.type === DiscordChannelType.GuildVoice\n\t\t\t\t) {\n\t\t\t\t\treturn channel as BaseGuildVoiceChannel;\n\t\t\t\t} else if (\n\t\t\t\t\t!isVoiceChannel &&\n\t\t\t\t\tchannel &&\n\t\t\t\t\tchannel.isTextBased() &&\n\t\t\t\t\t!channel.isVoiceBased()\n\t\t\t\t) {\n\t\t\t\t\treturn channel as TextChannel;\n\t\t\t\t}\n\t\t\t} catch (_e) {\n\t\t\t\t// ID not found, continue to name search\n\t\t\t}\n\t\t}\n\n\t\t// Search in the current server if available\n\t\tif (currentServerId) {\n\t\t\tconst guild = await discordService.client.guilds.fetch(currentServerId);\n\t\t\tconst channels = await guild.channels.fetch();\n\n\t\t\t// Search by channel name\n\t\t\tconst channel = channels.find((ch) => {\n\t\t\t\tconst nameMatch =\n\t\t\t\t\tch?.name.toLowerCase() === identifier.toLowerCase() ||\n\t\t\t\t\tch?.name.toLowerCase().replace(/[^a-z0-9 ]/g, \"\") ===\n\t\t\t\t\t\tidentifier.toLowerCase().replace(/[^a-z0-9 ]/g, \"\");\n\n\t\t\t\tif (isVoiceChannel) {\n\t\t\t\t\treturn nameMatch && ch.type === DiscordChannelType.GuildVoice;\n\t\t\t\t} else {\n\t\t\t\t\treturn nameMatch && ch.isTextBased() && !ch.isVoiceBased();\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif (channel) {\n\t\t\t\treturn channel as TextChannel | BaseGuildVoiceChannel;\n\t\t\t}\n\t\t}\n\n\t\t// Search in all guilds the bot is in\n\t\tconst guilds = Array.from(discordService.client.guilds.cache.values());\n\t\tfor (const guild of guilds) {\n\t\t\ttry {\n\t\t\t\tconst channels = await guild.channels.fetch();\n\t\t\t\tconst channel = channels.find((ch) => {\n\t\t\t\t\tconst nameMatch =\n\t\t\t\t\t\tch?.name?.toLowerCase() === identifier.toLowerCase() ||\n\t\t\t\t\t\tch?.name?.toLowerCase().replace(/[^a-z0-9 ]/g, \"\") ===\n\t\t\t\t\t\t\tidentifier.toLowerCase().replace(/[^a-z0-9 ]/g, \"\");\n\n\t\t\t\t\tif (isVoiceChannel) {\n\t\t\t\t\t\treturn nameMatch && ch.type === DiscordChannelType.GuildVoice;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn nameMatch && ch.isTextBased() && !ch.isVoiceBased();\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tif (channel) {\n\t\t\t\t\treturn channel as TextChannel | BaseGuildVoiceChannel;\n\t\t\t\t}\n\t\t\t} catch (_e) {\n\t\t\t\t// Continue searching in other guilds\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t} catch (_error) {\n\t\t// Standalone function - error handled by caller\n\t\treturn null;\n\t}\n};\n\nconst spec = requireActionSpec(\"JOIN_CHANNEL\");\n\nexport const joinChannel: Action = {\n\tname: spec.name,\n\tsimiles: spec.similes ? [...spec.similes] : [],\n\tdescription: spec.description,\n\tvalidate: async (\n\t\truntime: any,\n\t\tmessage: any,\n\t\tstate?: any,\n\t\toptions?: any,\n\t): Promise<boolean> => {\n\t\tconst __avTextRaw =\n\t\t\ttypeof message?.content?.text === \"string\" ? message.content.text : \"\";\n\t\tconst __avText = __avTextRaw.toLowerCase();\n\t\tconst __avKeywords = [\"join\", \"channel\"];\n\t\tconst __avKeywordOk =\n\t\t\t__avKeywords.length > 0 &&\n\t\t\t__avKeywords.some((word) => word.length > 0 && __avText.includes(word));\n\t\tconst __avRegex = /\\b(?:join|channel)\\b/i;\n\t\tconst __avRegexOk = __avRegex.test(__avText);\n\t\tconst __avSource = String(\n\t\t\tmessage?.content?.source ?? message?.source ?? \"\",\n\t\t);\n\t\tconst __avExpectedSource = \"\";\n\t\tconst __avSourceOk = __avExpectedSource\n\t\t\t? __avSource === __avExpectedSource\n\t\t\t: Boolean(\n\t\t\t\t\t__avSource ||\n\t\t\t\t\t\tstate ||\n\t\t\t\t\t\truntime?.agentId ||\n\t\t\t\t\t\truntime?.getService ||\n\t\t\t\t\t\truntime?.getSetting,\n\t\t\t\t);\n\t\tconst __avOptions = options && typeof options === \"object\" ? options : {};\n\t\tconst __avInputOk =\n\t\t\t__avText.trim().length > 0 ||\n\t\t\tObject.keys(__avOptions as Record<string, unknown>).length > 0 ||\n\t\t\tBoolean(message?.content && typeof message.content === \"object\");\n\n\t\tif (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst __avLegacyValidate = async (\n\t\t\t_runtime: IAgentRuntime,\n\t\t\tmessage: Memory,\n\t\t\t_state?: State,\n\t\t): Promise<boolean> => {\n\t\t\treturn message.content.source === \"discord\";\n\t\t};\n\t\ttry {\n\t\t\treturn Boolean(\n\t\t\t\tawait (__avLegacyValidate as any)(runtime, message, state, options),\n\t\t\t);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t},\n\thandler: async (\n\t\truntime: IAgentRuntime,\n\t\tmessage: Memory,\n\t\tstate?: State,\n\t\t_options?: HandlerOptions,\n\t\tcallback?: HandlerCallback,\n\t): Promise<ActionResult | undefined> => {\n\t\tconst discordService = runtime.getService(\n\t\t\tDISCORD_SERVICE_NAME,\n\t\t) as DiscordService;\n\n\t\tif (!discordService || !discordService.client) {\n\t\t\truntime.logger.error(\n\t\t\t\t{ src: \"plugin:discord:action:join-channel\", agentId: runtime.agentId },\n\t\t\t\t\"Discord service not found or not initialized\",\n\t\t\t);\n\t\t\treturn { success: false, error: \"Discord service not available\" };\n\t\t}\n\n\t\tif (!state) {\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"State is not available.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { success: false, error: \"State is not available\" };\n\t\t}\n\n\t\tconst channelInfo = await getJoinChannelInfo(runtime, message, state);\n\t\tif (!channelInfo) {\n\t\t\truntime.logger.warn(\n\t\t\t\t{ src: \"plugin:discord:action:join-channel\", agentId: runtime.agentId },\n\t\t\t\t\"Could not parse channel information from message\",\n\t\t\t);\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I couldn't understand which channel you want me to join. Please specify the channel name or ID.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { success: false, error: \"Could not parse channel information\" };\n\t\t}\n\n\t\ttry {\n\t\t\tconst stateData = state.data;\n\t\t\tconst room = stateData?.room || (await runtime.getRoom(message.roomId));\n\t\t\tconst currentServerId = room?.messageServerId;\n\n\t\t\t// First, try the user's approach - if they said voice/vc, look for voice channels\n\t\t\tconst messageContentText = message.content.text;\n\t\t\tconst messageText = messageContentText?.toLowerCase() || \"\";\n\t\t\tconst isVoiceRequest =\n\t\t\t\tchannelInfo.isVoiceChannel ||\n\t\t\t\tmessageText.includes(\"voice\") ||\n\t\t\t\tmessageText.includes(\"vc\") ||\n\t\t\t\tmessageText.includes(\"hop in\");\n\n\t\t\t// Find the channel (try voice first if it's a voice request)\n\t\t\tlet targetChannel = isVoiceRequest\n\t\t\t\t? await findChannel(\n\t\t\t\t\t\tdiscordService,\n\t\t\t\t\t\tchannelInfo.channelIdentifier,\n\t\t\t\t\t\tcurrentServerId,\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t)\n\t\t\t\t: await findChannel(\n\t\t\t\t\t\tdiscordService,\n\t\t\t\t\t\tchannelInfo.channelIdentifier,\n\t\t\t\t\t\tcurrentServerId,\n\t\t\t\t\t\tfalse,\n\t\t\t\t\t);\n\n\t\t\t// If not found, try the opposite type\n\t\t\tif (!targetChannel) {\n\t\t\t\ttargetChannel = isVoiceRequest\n\t\t\t\t\t? await findChannel(\n\t\t\t\t\t\t\tdiscordService,\n\t\t\t\t\t\t\tchannelInfo.channelIdentifier,\n\t\t\t\t\t\t\tcurrentServerId,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t)\n\t\t\t\t\t: await findChannel(\n\t\t\t\t\t\t\tdiscordService,\n\t\t\t\t\t\t\tchannelInfo.channelIdentifier,\n\t\t\t\t\t\t\tcurrentServerId,\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (!targetChannel) {\n\t\t\t\t// If the user is in a voice channel and no specific channel was found, join their voice channel\n\t\t\t\tif (isVoiceRequest && currentServerId) {\n\t\t\t\t\tconst guild = discordService.client.guilds.cache.get(currentServerId);\n\t\t\t\t\tconst members = guild?.members?.cache;\n\t\t\t\t\tconst member = members?.find(\n\t\t\t\t\t\t(member) =>\n\t\t\t\t\t\t\tcreateUniqueUuid(runtime, member.id) === message.entityId,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst memberVoice = member?.voice;\n\t\t\t\t\tif (memberVoice?.channel) {\n\t\t\t\t\t\ttargetChannel = member.voice.channel as BaseGuildVoiceChannel;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!targetChannel) {\n\t\t\t\tif (callback) {\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\ttext: `I couldn't find a channel with the identifier \"${channelInfo.channelIdentifier}\". Please make sure the channel name or ID is correct and I have access to it.`,\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: `Channel not found: ${channelInfo.channelIdentifier}`,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Handle voice channels\n\t\t\tif (targetChannel.type === DiscordChannelType.GuildVoice) {\n\t\t\t\tconst voiceChannel = targetChannel as BaseGuildVoiceChannel;\n\t\t\t\tconst voiceManager = discordService.voiceManager as VoiceManager;\n\n\t\t\t\tif (!voiceManager) {\n\t\t\t\t\tif (callback) {\n\t\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\t\ttext: \"Voice functionality is not available at the moment.\",\n\t\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn { success: false, error: \"Voice functionality not available\" };\n\t\t\t\t}\n\n\t\t\t\t// Join the voice channel\n\t\t\t\tawait voiceManager.joinChannel(voiceChannel);\n\n\t\t\t\tawait runtime.createMemory(\n\t\t\t\t\t{\n\t\t\t\t\t\tentityId: message.entityId,\n\t\t\t\t\t\tagentId: message.agentId,\n\t\t\t\t\t\troomId: message.roomId,\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\t\tthought: `I joined the voice channel ${voiceChannel.name}`,\n\t\t\t\t\t\t\tactions: [\"JOIN_VOICE_STARTED\"],\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmetadata: {\n\t\t\t\t\t\t\ttype: MemoryType.CUSTOM,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t\"messages\",\n\t\t\t\t);\n\n\t\t\t\tconst response: Content = {\n\t\t\t\t\ttext: `I've joined the voice channel ${voiceChannel.name}!`,\n\t\t\t\t\tactions: [\"JOIN_CHANNEL_RESPONSE\"],\n\t\t\t\t\tsource: message.content.source,\n\t\t\t\t};\n\n\t\t\t\tif (callback) {\n\t\t\t\t\tawait callback?.(response);\n\t\t\t\t}\n\t\t\t\treturn { success: true, text: response.text };\n\t\t\t} else {\n\t\t\t\t// Handle text channels\n\t\t\t\tconst textChannel = targetChannel as TextChannel;\n\n\t\t\t\t// Check if we're already listening to this channel\n\t\t\t\tconst currentChannels = discordService.getAllowedChannels();\n\t\t\t\tif (currentChannels.includes(textChannel.id)) {\n\t\t\t\t\tif (callback) {\n\t\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\t\ttext: `I'm already listening to ${textChannel.name} (<#${textChannel.id}>).`,\n\t\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\ttext: `Already listening to ${textChannel.name}`,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t// Add the channel to the allowed list\n\t\t\t\tconst success = discordService.addAllowedChannel(textChannel.id);\n\n\t\t\t\tif (success) {\n\t\t\t\t\tconst response: Content = {\n\t\t\t\t\t\ttext: `I've started listening to ${textChannel.name} (<#${textChannel.id}>). I'll now respond to messages in that channel.`,\n\t\t\t\t\t\tactions: [\"JOIN_CHANNEL_RESPONSE\"],\n\t\t\t\t\t\tsource: message.content.source,\n\t\t\t\t\t};\n\n\t\t\t\t\tif (callback) {\n\t\t\t\t\t\tawait callback?.(response);\n\t\t\t\t\t}\n\t\t\t\t\treturn { success: true, text: response.text };\n\t\t\t\t} else {\n\t\t\t\t\tif (callback) {\n\t\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\t\ttext: `I couldn't add ${textChannel.name} to my listening list. Please try again.`,\n\t\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\terror: `Could not add ${textChannel.name} to listening list`,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\truntime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:join-channel\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error joining channel\",\n\t\t\t);\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I encountered an error while trying to join the channel. Please make sure I have the necessary permissions.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t};\n\t\t}\n\t},\n\texamples: (spec.examples ?? []) as ActionExample[][],\n};\n\nexport default joinChannel;\n",
|
|
96
|
+
"import {\n\ttype Action,\n\ttype ActionExample,\n\ttype ActionResult,\n\ttype Content,\n\tcomposePromptFromState,\n\tcreateUniqueUuid,\n\ttype HandlerCallback,\n\ttype IAgentRuntime,\n\ttype Memory,\n\tMemoryType,\n\tModelType,\n\tparseJSONObjectFromText,\n\ttype State,\n} from \"@elizaos/core\";\nimport {\n\tBaseGuildVoiceChannel,\n\tChannelType as DiscordChannelType,\n\ttype TextChannel,\n} from \"discord.js\";\nimport { DISCORD_SERVICE_NAME } from \"../constants\";\nimport { leaveChannelTemplate } from \"../generated/prompts/typescript/prompts.js\";\nimport type { DiscordService } from \"../service\";\nimport type { VoiceManager } from \"../voice\";\n\n/**\n * Get channel information from the user's request\n * @param {IAgentRuntime} runtime - The runtime object to interact with the agent.\n * @param {Memory} _message - The memory object containing the input message.\n * @param {State} state - The state of the conversation.\n * @returns {Promise<{channelIdentifier: string, isVoiceChannel: boolean} | null>} Channel info or null if not parseable.\n */\nconst getLeaveChannelInfo = async (\n\truntime: IAgentRuntime,\n\t_message: Memory,\n\tstate: State,\n): Promise<{ channelIdentifier: string; isVoiceChannel: boolean } | null> => {\n\tconst prompt = composePromptFromState({\n\t\tstate,\n\t\ttemplate: leaveChannelTemplate,\n\t});\n\n\tfor (let i = 0; i < 3; i++) {\n\t\tconst response = await runtime.useModel(ModelType.TEXT_SMALL, {\n\t\t\tprompt,\n\t\t});\n\n\t\tconst parsedResponse = parseJSONObjectFromText(response) as {\n\t\t\tchannelIdentifier: string;\n\t\t\tisVoiceChannel: boolean;\n\t\t} | null;\n\n\t\tif (parsedResponse?.channelIdentifier) {\n\t\t\treturn parsedResponse;\n\t\t}\n\t}\n\treturn null;\n};\n\n/**\n * Find a Discord channel by various identifiers\n * @param {DiscordService} discordService - The Discord service instance\n * @param {string} identifier - The channel identifier (name, ID, or mention)\n * @param {string} currentChannelId - The current channel ID if \"current\" is specified\n * @param {string} currentServerId - The current server ID to search in\n * @param {boolean} isVoiceChannel - Whether to look for voice channels\n * @returns {Promise<TextChannel | BaseGuildVoiceChannel | null>} The found channel or null\n */\nconst findChannel = async (\n\tdiscordService: DiscordService,\n\tidentifier: string,\n\tcurrentChannelId?: string,\n\tcurrentServerId?: string,\n\tisVoiceChannel?: boolean,\n): Promise<TextChannel | BaseGuildVoiceChannel | null> => {\n\tif (!discordService.client) {\n\t\treturn null;\n\t}\n\n\t// Handle \"current\" channel\n\tif (identifier === \"current\" && currentChannelId) {\n\t\ttry {\n\t\t\tconst channel =\n\t\t\t\tawait discordService.client.channels.fetch(currentChannelId);\n\t\t\tif (\n\t\t\t\tisVoiceChannel &&\n\t\t\t\tchannel &&\n\t\t\t\tchannel.type === DiscordChannelType.GuildVoice\n\t\t\t) {\n\t\t\t\treturn channel as BaseGuildVoiceChannel;\n\t\t\t} else if (\n\t\t\t\t!isVoiceChannel &&\n\t\t\t\tchannel &&\n\t\t\t\tchannel.isTextBased() &&\n\t\t\t\t!channel.isVoiceBased()\n\t\t\t) {\n\t\t\t\treturn channel as TextChannel;\n\t\t\t}\n\t\t} catch (_e) {\n\t\t\t// Current channel not found\n\t\t}\n\t}\n\n\t// Remove channel mention formatting if present\n\tconst cleanId = identifier.replace(/[<#>]/g, \"\");\n\n\ttry {\n\t\t// Try to fetch by ID first\n\t\tif (/^\\d+$/.test(cleanId)) {\n\t\t\ttry {\n\t\t\t\tconst channel = await discordService.client.channels.fetch(cleanId);\n\t\t\t\tif (\n\t\t\t\t\tisVoiceChannel &&\n\t\t\t\t\tchannel &&\n\t\t\t\t\tchannel.type === DiscordChannelType.GuildVoice\n\t\t\t\t) {\n\t\t\t\t\treturn channel as BaseGuildVoiceChannel;\n\t\t\t\t} else if (\n\t\t\t\t\t!isVoiceChannel &&\n\t\t\t\t\tchannel &&\n\t\t\t\t\tchannel.isTextBased() &&\n\t\t\t\t\t!channel.isVoiceBased()\n\t\t\t\t) {\n\t\t\t\t\treturn channel as TextChannel;\n\t\t\t\t}\n\t\t\t} catch (_e) {\n\t\t\t\t// ID not found, continue to name search\n\t\t\t}\n\t\t}\n\n\t\t// Search in the current server if available\n\t\tif (currentServerId) {\n\t\t\tconst guild = await discordService.client.guilds.fetch(currentServerId);\n\t\t\tconst channels = await guild.channels.fetch();\n\n\t\t\t// Search by channel name\n\t\t\tconst channel = channels.find((ch) => {\n\t\t\t\tconst nameMatch =\n\t\t\t\t\tch?.name?.toLowerCase() === identifier.toLowerCase() ||\n\t\t\t\t\tch?.name?.toLowerCase().replace(/[^a-z0-9 ]/g, \"\") ===\n\t\t\t\t\t\tidentifier.toLowerCase().replace(/[^a-z0-9 ]/g, \"\");\n\n\t\t\t\tif (isVoiceChannel) {\n\t\t\t\t\treturn nameMatch && ch.type === DiscordChannelType.GuildVoice;\n\t\t\t\t} else {\n\t\t\t\t\treturn nameMatch && ch.isTextBased() && !ch.isVoiceBased();\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif (channel) {\n\t\t\t\treturn channel as TextChannel | BaseGuildVoiceChannel;\n\t\t\t}\n\t\t}\n\n\t\t// Search in all guilds the bot is in\n\t\tconst guilds = Array.from(discordService.client.guilds.cache.values());\n\t\tfor (const guild of guilds) {\n\t\t\ttry {\n\t\t\t\tconst channels = await guild.channels.fetch();\n\t\t\t\tconst channel = channels.find((ch) => {\n\t\t\t\t\tconst nameMatch =\n\t\t\t\t\t\tch?.name?.toLowerCase() === identifier.toLowerCase() ||\n\t\t\t\t\t\tch?.name?.toLowerCase().replace(/[^a-z0-9 ]/g, \"\") ===\n\t\t\t\t\t\t\tidentifier.toLowerCase().replace(/[^a-z0-9 ]/g, \"\");\n\n\t\t\t\t\tif (isVoiceChannel) {\n\t\t\t\t\t\treturn nameMatch && ch.type === DiscordChannelType.GuildVoice;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn nameMatch && ch.isTextBased() && !ch.isVoiceBased();\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tif (channel) {\n\t\t\t\t\treturn channel as TextChannel | BaseGuildVoiceChannel;\n\t\t\t\t}\n\t\t\t} catch (_e) {\n\t\t\t\t// Continue searching in other guilds\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t} catch (_error) {\n\t\t// Standalone function - error handled by caller\n\t\treturn null;\n\t}\n};\n\nimport type { HandlerOptions } from \"@elizaos/core\";\nimport { requireActionSpec } from \"../generated/specs/spec-helpers\";\n\nconst spec = requireActionSpec(\"LEAVE_CHANNEL\");\n\nexport const leaveChannel: Action = {\n\tname: spec.name,\n\tsimiles: spec.similes ? [...spec.similes] : [],\n\tdescription: spec.description,\n\tvalidate: async (\n\t\truntime: any,\n\t\tmessage: any,\n\t\tstate?: any,\n\t\toptions?: any,\n\t): Promise<boolean> => {\n\t\tconst __avTextRaw =\n\t\t\ttypeof message?.content?.text === \"string\" ? message.content.text : \"\";\n\t\tconst __avText = __avTextRaw.toLowerCase();\n\t\tconst __avKeywords = [\"leave\", \"channel\"];\n\t\tconst __avKeywordOk =\n\t\t\t__avKeywords.length > 0 &&\n\t\t\t__avKeywords.some((word) => word.length > 0 && __avText.includes(word));\n\t\tconst __avRegex = /\\b(?:leave|channel)\\b/i;\n\t\tconst __avRegexOk = __avRegex.test(__avText);\n\t\tconst __avSource = String(\n\t\t\tmessage?.content?.source ?? message?.source ?? \"\",\n\t\t);\n\t\tconst __avExpectedSource = \"\";\n\t\tconst __avSourceOk = __avExpectedSource\n\t\t\t? __avSource === __avExpectedSource\n\t\t\t: Boolean(\n\t\t\t\t\t__avSource ||\n\t\t\t\t\t\tstate ||\n\t\t\t\t\t\truntime?.agentId ||\n\t\t\t\t\t\truntime?.getService ||\n\t\t\t\t\t\truntime?.getSetting,\n\t\t\t\t);\n\t\tconst __avOptions = options && typeof options === \"object\" ? options : {};\n\t\tconst __avInputOk =\n\t\t\t__avText.trim().length > 0 ||\n\t\t\tObject.keys(__avOptions as Record<string, unknown>).length > 0 ||\n\t\t\tBoolean(message?.content && typeof message.content === \"object\");\n\n\t\tif (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst __avLegacyValidate = async (\n\t\t\t_runtime: IAgentRuntime,\n\t\t\tmessage: Memory,\n\t\t\t_state?: State,\n\t\t): Promise<boolean> => {\n\t\t\treturn message.content.source === \"discord\";\n\t\t};\n\t\ttry {\n\t\t\treturn Boolean(\n\t\t\t\tawait (__avLegacyValidate as any)(runtime, message, state, options),\n\t\t\t);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t},\n\thandler: async (\n\t\truntime: IAgentRuntime,\n\t\tmessage: Memory,\n\t\tstate?: State,\n\t\t_options?: HandlerOptions,\n\t\tcallback?: HandlerCallback,\n\t): Promise<ActionResult | undefined> => {\n\t\tconst discordService = runtime.getService(\n\t\t\tDISCORD_SERVICE_NAME,\n\t\t) as DiscordService;\n\n\t\tif (!discordService || !discordService.client) {\n\t\t\truntime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:leave-channel\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t},\n\t\t\t\t\"Discord service not found or not initialized\",\n\t\t\t);\n\t\t\tawait callback?.({\n\t\t\t\ttext: \"Discord service is not available.\",\n\t\t\t\tsource: \"discord\",\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst channelInfo = await getLeaveChannelInfo(runtime, message, state);\n\n\t\ttry {\n\t\t\tconst stateData = state.data;\n\t\t\tconst room = stateData?.room || (await runtime.getRoom(message.roomId));\n\t\t\tconst currentServerId = room?.messageServerId;\n\t\t\tconst currentChannelId = room?.channelId;\n\n\t\t\t// Check if trying to leave voice without specifying channel\n\t\t\tconst messageContentText = message.content.text;\n\t\t\tconst messageText = messageContentText?.toLowerCase() || \"\";\n\t\t\tconst isVoiceRequest =\n\t\t\t\tchannelInfo?.isVoiceChannel ||\n\t\t\t\tmessageText.includes(\"voice\") ||\n\t\t\t\tmessageText.includes(\"vc\") ||\n\t\t\t\tmessageText.includes(\"call\");\n\n\t\t\t// If it's a generic voice leave request, handle current voice channel\n\t\t\tif (\n\t\t\t\tisVoiceRequest &&\n\t\t\t\t(!channelInfo || channelInfo.channelIdentifier === \"current\")\n\t\t\t) {\n\t\t\t\tconst voiceManager = discordService.voiceManager as VoiceManager;\n\n\t\t\t\tif (!voiceManager) {\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\ttext: \"Voice functionality is not available at the moment.\",\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t});\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\tif (currentServerId) {\n\t\t\t\t\tconst guild = discordService.client.guilds.cache.get(currentServerId);\n\t\t\t\t\tconst guildMembers = guild?.members;\n\t\t\t\t\tconst guildMembersMe = guildMembers?.me;\n\t\t\t\t\tconst guildMembersMeVoice = guildMembersMe?.voice;\n\t\t\t\t\tconst voiceChannel = guildMembersMeVoice?.channel;\n\n\t\t\t\t\tif (\n\t\t\t\t\t\t!voiceChannel ||\n\t\t\t\t\t\t!(voiceChannel instanceof BaseGuildVoiceChannel)\n\t\t\t\t\t) {\n\t\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\t\ttext: \"I'm not currently in a voice channel.\",\n\t\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst connection = voiceManager.getVoiceConnection(guild.id);\n\t\t\t\t\tif (!connection) {\n\t\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\t\ttext: \"No active voice connection found.\",\n\t\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\tvoiceManager.leaveChannel(voiceChannel);\n\n\t\t\t\t\tawait runtime.createMemory(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tentityId: message.entityId,\n\t\t\t\t\t\t\tagentId: message.agentId,\n\t\t\t\t\t\t\troomId: createUniqueUuid(runtime, voiceChannel.id),\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\t\t\tthought: `I left the voice channel ${voiceChannel.name}`,\n\t\t\t\t\t\t\t\tactions: [\"LEAVE_VOICE_STARTED\"],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tmetadata: {\n\t\t\t\t\t\t\t\ttype: MemoryType.CUSTOM,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"messages\",\n\t\t\t\t\t);\n\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\ttext: `I've left the voice channel ${voiceChannel.name}.`,\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!channelInfo) {\n\t\t\t\truntime.logger.warn(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord:action:leave-channel\",\n\t\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\t},\n\t\t\t\t\t\"Could not parse channel information from message\",\n\t\t\t\t);\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I couldn't understand which channel you want me to leave. Please specify the channel name or ID.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\t// Find the channel (try voice first if it's a voice request)\n\t\t\tlet targetChannel = isVoiceRequest\n\t\t\t\t? await findChannel(\n\t\t\t\t\t\tdiscordService,\n\t\t\t\t\t\tchannelInfo.channelIdentifier,\n\t\t\t\t\t\tcurrentChannelId,\n\t\t\t\t\t\tcurrentServerId,\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t)\n\t\t\t\t: await findChannel(\n\t\t\t\t\t\tdiscordService,\n\t\t\t\t\t\tchannelInfo.channelIdentifier,\n\t\t\t\t\t\tcurrentChannelId,\n\t\t\t\t\t\tcurrentServerId,\n\t\t\t\t\t\tfalse,\n\t\t\t\t\t);\n\n\t\t\t// If not found, try the opposite type\n\t\t\tif (!targetChannel) {\n\t\t\t\ttargetChannel = isVoiceRequest\n\t\t\t\t\t? await findChannel(\n\t\t\t\t\t\t\tdiscordService,\n\t\t\t\t\t\t\tchannelInfo.channelIdentifier,\n\t\t\t\t\t\t\tcurrentChannelId,\n\t\t\t\t\t\t\tcurrentServerId,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t)\n\t\t\t\t\t: await findChannel(\n\t\t\t\t\t\t\tdiscordService,\n\t\t\t\t\t\t\tchannelInfo.channelIdentifier,\n\t\t\t\t\t\t\tcurrentChannelId,\n\t\t\t\t\t\t\tcurrentServerId,\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (!targetChannel) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: `I couldn't find a channel with the identifier \"${channelInfo.channelIdentifier}\". Please make sure the channel name or ID is correct.`,\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\t// Handle voice channels\n\t\t\tif (targetChannel.type === DiscordChannelType.GuildVoice) {\n\t\t\t\tconst voiceChannel = targetChannel as BaseGuildVoiceChannel;\n\t\t\t\tconst voiceManager = discordService.voiceManager as VoiceManager;\n\n\t\t\t\tif (!voiceManager) {\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\ttext: \"Voice functionality is not available at the moment.\",\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t});\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\tconst guild = voiceChannel.guild;\n\t\t\t\tconst guildMembersMe = guild.members?.me;\n\t\t\t\tconst guildMembersMeVoice = guildMembersMe?.voice;\n\t\t\t\tconst currentVoiceChannel = guildMembersMeVoice?.channel;\n\n\t\t\t\tif (\n\t\t\t\t\t!currentVoiceChannel ||\n\t\t\t\t\tcurrentVoiceChannel.id !== voiceChannel.id\n\t\t\t\t) {\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\ttext: `I'm not currently in the voice channel ${voiceChannel.name}.`,\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t});\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\tvoiceManager.leaveChannel(voiceChannel);\n\n\t\t\t\tawait runtime.createMemory(\n\t\t\t\t\t{\n\t\t\t\t\t\tentityId: message.entityId,\n\t\t\t\t\t\tagentId: message.agentId,\n\t\t\t\t\t\troomId: createUniqueUuid(runtime, voiceChannel.id),\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\t\tthought: `I left the voice channel ${voiceChannel.name}`,\n\t\t\t\t\t\t\tactions: [\"LEAVE_VOICE_STARTED\"],\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmetadata: {\n\t\t\t\t\t\t\ttype: MemoryType.CUSTOM,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t\"messages\",\n\t\t\t\t);\n\n\t\t\t\tconst response: Content = {\n\t\t\t\t\ttext: `I've left the voice channel ${voiceChannel.name}.`,\n\t\t\t\t\tactions: [\"LEAVE_CHANNEL_RESPONSE\"],\n\t\t\t\t\tsource: message.content.source,\n\t\t\t\t};\n\n\t\t\t\tawait callback?.(response);\n\t\t\t} else {\n\t\t\t\t// Handle text channels\n\t\t\t\tconst textChannel = targetChannel as TextChannel;\n\n\t\t\t\t// Check if we're listening to this channel\n\t\t\t\tconst currentChannels = discordService.getAllowedChannels();\n\t\t\t\tif (!currentChannels.includes(textChannel.id)) {\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\ttext: `I'm not currently listening to ${textChannel.name} (<#${textChannel.id}>).`,\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t});\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\t// Remove the channel from the allowed list\n\t\t\t\tconst success = discordService.removeAllowedChannel(textChannel.id);\n\n\t\t\t\tif (success) {\n\t\t\t\t\tconst response: Content = {\n\t\t\t\t\t\ttext: `I've stopped listening to ${textChannel.name} (<#${textChannel.id}>). I will no longer respond to messages in that channel.`,\n\t\t\t\t\t\tactions: [\"LEAVE_CHANNEL_RESPONSE\"],\n\t\t\t\t\t\tsource: message.content.source,\n\t\t\t\t\t};\n\n\t\t\t\t\tawait callback?.(response);\n\t\t\t\t} else {\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\ttext: `I couldn't remove ${textChannel.name} from my listening list. This channel might be configured in my environment settings and cannot be removed dynamically.`,\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t});\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\truntime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:leave-channel\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error leaving channel\",\n\t\t\t);\n\t\t\tawait callback?.({\n\t\t\t\ttext: \"I encountered an error while trying to leave the channel. Please try again.\",\n\t\t\t\tsource: \"discord\",\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\t},\n\texamples: (spec.examples ?? []) as ActionExample[][],\n};\n\nexport default leaveChannel;\n",
|
|
97
|
+
"import type {\n\tAction,\n\tActionExample,\n\tActionResult,\n\tContent,\n\tHandlerCallback,\n\tHandlerOptions,\n\tIAgentRuntime,\n\tMemory,\n\tState,\n} from \"@elizaos/core\";\nimport { DISCORD_SERVICE_NAME } from \"../constants\";\nimport { requireActionSpec } from \"../generated/specs/spec-helpers\";\nimport type { DiscordService } from \"../service\";\n\nconst spec = requireActionSpec(\"LIST_CHANNELS\");\n\nexport const listChannels: Action = {\n\tname: spec.name,\n\tsimiles: spec.similes ? [...spec.similes] : [],\n\tdescription: spec.description,\n\tvalidate: async (\n\t\truntime: any,\n\t\tmessage: any,\n\t\tstate?: any,\n\t\toptions?: any,\n\t): Promise<boolean> => {\n\t\tconst __avTextRaw =\n\t\t\ttypeof message?.content?.text === \"string\" ? message.content.text : \"\";\n\t\tconst __avText = __avTextRaw.toLowerCase();\n\t\tconst __avKeywords = [\"list\", \"channels\"];\n\t\tconst __avKeywordOk =\n\t\t\t__avKeywords.length > 0 &&\n\t\t\t__avKeywords.some((word) => word.length > 0 && __avText.includes(word));\n\t\tconst __avRegex = /\\b(?:list|channels)\\b/i;\n\t\tconst __avRegexOk = __avRegex.test(__avText);\n\t\tconst __avSource = String(\n\t\t\tmessage?.content?.source ?? message?.source ?? \"\",\n\t\t);\n\t\tconst __avExpectedSource = \"\";\n\t\tconst __avSourceOk = __avExpectedSource\n\t\t\t? __avSource === __avExpectedSource\n\t\t\t: Boolean(\n\t\t\t\t\t__avSource ||\n\t\t\t\t\t\tstate ||\n\t\t\t\t\t\truntime?.agentId ||\n\t\t\t\t\t\truntime?.getService ||\n\t\t\t\t\t\truntime?.getSetting,\n\t\t\t\t);\n\t\tconst __avOptions = options && typeof options === \"object\" ? options : {};\n\t\tconst __avInputOk =\n\t\t\t__avText.trim().length > 0 ||\n\t\t\tObject.keys(__avOptions as Record<string, unknown>).length > 0 ||\n\t\t\tBoolean(message?.content && typeof message.content === \"object\");\n\n\t\tif (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst __avLegacyValidate = async (\n\t\t\t_runtime: IAgentRuntime,\n\t\t\tmessage: Memory,\n\t\t\t_state?: State,\n\t\t): Promise<boolean> => {\n\t\t\treturn message.content.source === \"discord\";\n\t\t};\n\t\ttry {\n\t\t\treturn Boolean(\n\t\t\t\tawait (__avLegacyValidate as any)(runtime, message, state, options),\n\t\t\t);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t},\n\thandler: async (\n\t\truntime: IAgentRuntime,\n\t\tmessage: Memory,\n\t\t_state?: State,\n\t\t_options?: HandlerOptions,\n\t\tcallback?: HandlerCallback,\n\t): Promise<ActionResult | undefined> => {\n\t\tconst discordService = runtime.getService(\n\t\t\tDISCORD_SERVICE_NAME,\n\t\t) as DiscordService;\n\n\t\tif (!discordService || !discordService.client) {\n\t\t\truntime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:list-channels\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t},\n\t\t\t\t\"Discord service not found or not initialized\",\n\t\t\t);\n\t\t\treturn { success: false, error: \"Discord service not available\" };\n\t\t}\n\n\t\ttry {\n\t\t\t// Get all allowed channels\n\t\t\tconst allowedChannelIds = discordService.getAllowedChannels();\n\n\t\t\tif (allowedChannelIds.length === 0) {\n\t\t\t\tif (callback) {\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\ttext: \"I'm currently listening to all channels (no restrictions are set).\",\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\ttext: \"Listening to all channels (no restrictions)\",\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Fetch channel information for each allowed channel\n\t\t\tconst channelInfoPromises = allowedChannelIds.map(async (channelId) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst client = discordService.client;\n\t\t\t\t\tconst channel = client && (await client.channels.fetch(channelId));\n\t\t\t\t\tif (channel?.isTextBased() && !channel.isVoiceBased()) {\n\t\t\t\t\t\tconst guild = \"guild\" in channel ? channel.guild : null;\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tid: channelId,\n\t\t\t\t\t\t\tname: \"name\" in channel ? channel.name : \"DM\",\n\t\t\t\t\t\t\tmention: `<#${channelId}>`,\n\t\t\t\t\t\t\tserver: guild?.name || \"Direct Message\",\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t} catch (_e) {\n\t\t\t\t\t// Channel might have been deleted or bot lost access\n\t\t\t\t\treturn {\n\t\t\t\t\t\tid: channelId,\n\t\t\t\t\t\tname: \"Unknown\",\n\t\t\t\t\t\tmention: channelId,\n\t\t\t\t\t\tserver: \"Unknown or Deleted\",\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t});\n\n\t\t\tconst channelInfos = (await Promise.all(channelInfoPromises)).filter(\n\t\t\t\tBoolean,\n\t\t\t);\n\n\t\t\t// Format the response\n\t\t\tlet responseText = `I'm currently listening to ${channelInfos.length} channel${channelInfos.length !== 1 ? \"s\" : \"\"}:\\n\\n`;\n\n\t\t\t// Group by server\n\t\t\tconst channelsByServer = channelInfos.reduce(\n\t\t\t\t(acc, channel) => {\n\t\t\t\t\tif (!channel) {\n\t\t\t\t\t\treturn acc;\n\t\t\t\t\t}\n\t\t\t\t\tif (!acc[channel.server]) {\n\t\t\t\t\t\tacc[channel.server] = [];\n\t\t\t\t\t}\n\t\t\t\t\tacc[channel.server].push(channel);\n\t\t\t\t\treturn acc;\n\t\t\t\t},\n\t\t\t\t{} as Record<string, typeof channelInfos>,\n\t\t\t);\n\n\t\t\t// Format by server\n\t\t\tfor (const [serverName, channels] of Object.entries(channelsByServer)) {\n\t\t\t\tresponseText += `**${serverName}**\\n`;\n\t\t\t\tfor (const channel of channels) {\n\t\t\t\t\tif (channel) {\n\t\t\t\t\t\tresponseText += `• ${channel.name} (${channel.mention})\\n`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tresponseText += \"\\n\";\n\t\t\t}\n\n\t\t\t// Check if CHANNEL_IDS is set\n\t\t\tconst envChannelIds = runtime.getSetting(\"CHANNEL_IDS\") as string;\n\t\t\tif (envChannelIds) {\n\t\t\t\tresponseText +=\n\t\t\t\t\t\"\\n*Some channels are configured in environment settings and cannot be removed dynamically.*\";\n\t\t\t}\n\n\t\t\tconst response: Content = {\n\t\t\t\ttext: responseText.trim(),\n\t\t\t\tactions: [\"LIST_CHANNELS_RESPONSE\"],\n\t\t\t\tsource: message.content.source,\n\t\t\t};\n\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.(response);\n\t\t\t}\n\t\t\treturn { success: true, text: response.text };\n\t\t} catch (error) {\n\t\t\truntime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:list-channels\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error listing channels\",\n\t\t\t);\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I encountered an error while trying to list the channels. Please try again.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t};\n\t\t}\n\t},\n\texamples: (spec.examples ?? []) as ActionExample[][],\n};\n\nexport default listChannels;\n",
|
|
98
|
+
"import {\n\ttype Action,\n\ttype ActionExample,\n\ttype ActionResult,\n\ttype Content,\n\tcomposePromptFromState,\n\ttype HandlerCallback,\n\ttype HandlerOptions,\n\ttype IAgentRuntime,\n\ttype Memory,\n\tModelType,\n\tparseJSONObjectFromText,\n\ttype State,\n} from \"@elizaos/core\";\nimport {\n\ttype Message,\n\tPermissionsBitField,\n\ttype TextChannel,\n} from \"discord.js\";\nimport { DISCORD_SERVICE_NAME } from \"../constants\";\nimport { pinMessageTemplate } from \"../generated/prompts/typescript/prompts.js\";\nimport { requireActionSpec } from \"../generated/specs/spec-helpers\";\nimport type { DiscordService } from \"../service\";\n\nconst getMessageRef = async (\n\truntime: IAgentRuntime,\n\t_message: Memory,\n\tstate: State,\n): Promise<{\n\tmessageRef: string;\n} | null> => {\n\tconst prompt = composePromptFromState({\n\t\tstate,\n\t\ttemplate: pinMessageTemplate,\n\t});\n\n\tfor (let i = 0; i < 3; i++) {\n\t\tconst response = await runtime.useModel(ModelType.TEXT_SMALL, {\n\t\t\tprompt,\n\t\t});\n\n\t\tconst parsedResponse = parseJSONObjectFromText(response);\n\t\tif (parsedResponse?.messageRef) {\n\t\t\treturn {\n\t\t\t\tmessageRef: String(parsedResponse.messageRef),\n\t\t\t};\n\t\t}\n\t}\n\treturn null;\n};\n\nconst spec = requireActionSpec(\"PIN_MESSAGE\");\n\nexport const pinMessage: Action = {\n\tname: spec.name,\n\tsimiles: spec.similes ? [...spec.similes] : [],\n\tdescription: spec.description,\n\tvalidate: async (\n\t\truntime: any,\n\t\tmessage: any,\n\t\tstate?: any,\n\t\toptions?: any,\n\t): Promise<boolean> => {\n\t\tconst __avTextRaw =\n\t\t\ttypeof message?.content?.text === \"string\" ? message.content.text : \"\";\n\t\tconst __avText = __avTextRaw.toLowerCase();\n\t\tconst __avKeywords = [\"pin\", \"message\"];\n\t\tconst __avKeywordOk =\n\t\t\t__avKeywords.length > 0 &&\n\t\t\t__avKeywords.some((word) => word.length > 0 && __avText.includes(word));\n\t\tconst __avRegex = /\\b(?:pin|message)\\b/i;\n\t\tconst __avRegexOk = __avRegex.test(__avText);\n\t\tconst __avSource = String(\n\t\t\tmessage?.content?.source ?? message?.source ?? \"\",\n\t\t);\n\t\tconst __avExpectedSource = \"\";\n\t\tconst __avSourceOk = __avExpectedSource\n\t\t\t? __avSource === __avExpectedSource\n\t\t\t: Boolean(\n\t\t\t\t\t__avSource ||\n\t\t\t\t\t\tstate ||\n\t\t\t\t\t\truntime?.agentId ||\n\t\t\t\t\t\truntime?.getService ||\n\t\t\t\t\t\truntime?.getSetting,\n\t\t\t\t);\n\t\tconst __avOptions = options && typeof options === \"object\" ? options : {};\n\t\tconst __avInputOk =\n\t\t\t__avText.trim().length > 0 ||\n\t\t\tObject.keys(__avOptions as Record<string, unknown>).length > 0 ||\n\t\t\tBoolean(message?.content && typeof message.content === \"object\");\n\n\t\tif (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst __avLegacyValidate = async (\n\t\t\t_runtime: IAgentRuntime,\n\t\t\tmessage: Memory,\n\t\t\t_state?: State,\n\t\t): Promise<boolean> => {\n\t\t\treturn message.content.source === \"discord\";\n\t\t};\n\t\ttry {\n\t\t\treturn Boolean(\n\t\t\t\tawait (__avLegacyValidate as any)(runtime, message, state, options),\n\t\t\t);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t},\n\thandler: async (\n\t\truntime: IAgentRuntime,\n\t\tmessage: Memory,\n\t\tstate?: State,\n\t\t_options?: HandlerOptions,\n\t\tcallback?: HandlerCallback,\n\t): Promise<ActionResult | undefined> => {\n\t\tconst discordService = runtime.getService(\n\t\t\tDISCORD_SERVICE_NAME,\n\t\t) as DiscordService;\n\n\t\tif (!discordService || !discordService.client) {\n\t\t\tawait callback?.({\n\t\t\t\ttext: \"Discord service is not available.\",\n\t\t\t\tsource: \"discord\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tconst messageInfo = await getMessageRef(runtime, message, state);\n\t\tif (!messageInfo) {\n\t\t\tawait callback?.({\n\t\t\t\ttext: \"I couldn't understand which message you want to pin. Please be more specific.\",\n\t\t\t\tsource: \"discord\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst stateData = state.data;\n\t\t\tconst room = stateData?.room || (await runtime.getRoom(message.roomId));\n\t\t\tif (!room || !room.channelId) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I couldn't determine the current channel.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst channel = await discordService.client.channels.fetch(\n\t\t\t\troom.channelId,\n\t\t\t);\n\t\t\tif (!channel || !channel.isTextBased()) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I can only pin messages in text channels.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst textChannel = channel as TextChannel;\n\n\t\t\t// Check bot permissions\n\t\t\tconst textChannelGuild = textChannel.guild;\n\t\t\tconst discordServiceClient = discordService.client;\n\t\t\tconst discordServiceClientUser = discordServiceClient?.user;\n\t\t\tconst botMember = textChannelGuild?.members.cache.get(\n\t\t\t\tdiscordServiceClientUser?.id,\n\t\t\t);\n\t\t\tif (botMember) {\n\t\t\t\tconst permissions = textChannel.permissionsFor(botMember);\n\t\t\t\tif (\n\t\t\t\t\t!permissions ||\n\t\t\t\t\t!permissions.has(PermissionsBitField.Flags.ManageMessages)\n\t\t\t\t) {\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\ttext: \"I don't have permission to pin messages in this channel. I need the 'Manage Messages' permission.\",\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet targetMessage: Message | null = null;\n\n\t\t\t// Find the target message\n\t\t\tif (\n\t\t\t\tmessageInfo.messageRef === \"last\" ||\n\t\t\t\tmessageInfo.messageRef === \"previous\"\n\t\t\t) {\n\t\t\t\t// Get the last few messages - fetch max allowed by Discord API\n\t\t\t\tconst messages = await textChannel.messages.fetch({ limit: 100 });\n\t\t\t\tconst sortedMessages = Array.from(messages.values()).sort(\n\t\t\t\t\t(a, b) => b.createdTimestamp - a.createdTimestamp,\n\t\t\t\t);\n\n\t\t\t\t// Skip the bot's own message and the command message\n\t\t\t\tconst discordServiceClient = discordService.client;\n\t\t\t\tconst discordServiceClientUser = discordServiceClient?.user;\n\t\t\t\ttargetMessage =\n\t\t\t\t\tsortedMessages.find(\n\t\t\t\t\t\t(msg) =>\n\t\t\t\t\t\t\tmsg.id !== message.content.id &&\n\t\t\t\t\t\t\tmsg.author.id !== discordServiceClientUser?.id,\n\t\t\t\t\t) || null;\n\t\t\t} else if (/^\\d+$/.test(messageInfo.messageRef)) {\n\t\t\t\t// It's a message ID\n\t\t\t\ttry {\n\t\t\t\t\ttargetMessage = await textChannel.messages.fetch(\n\t\t\t\t\t\tmessageInfo.messageRef,\n\t\t\t\t\t);\n\t\t\t\t} catch (_e) {\n\t\t\t\t\t// Message not found\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Search for message by content/author - fetch max allowed by Discord API\n\t\t\t\tconst messages = await textChannel.messages.fetch({ limit: 100 });\n\t\t\t\tconst searchLower = messageInfo.messageRef.toLowerCase();\n\n\t\t\t\ttargetMessage =\n\t\t\t\t\tArray.from(messages.values()).find((msg) => {\n\t\t\t\t\t\tconst contentMatch = msg.content\n\t\t\t\t\t\t\t.toLowerCase()\n\t\t\t\t\t\t\t.includes(searchLower);\n\t\t\t\t\t\tconst authorMatch = msg.author.username\n\t\t\t\t\t\t\t.toLowerCase()\n\t\t\t\t\t\t\t.includes(searchLower);\n\t\t\t\t\t\treturn contentMatch || authorMatch;\n\t\t\t\t\t}) || null;\n\t\t\t}\n\n\t\t\tif (!targetMessage) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I couldn't find the message you want to pin. Try being more specific or use 'last message'.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Check if already pinned\n\t\t\tif (targetMessage.pinned) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"That message is already pinned.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Pin the message\n\t\t\ttry {\n\t\t\t\tawait targetMessage.pin();\n\n\t\t\t\tconst response: Content = {\n\t\t\t\t\ttext: `I've pinned the message from ${targetMessage.author.username}.`,\n\t\t\t\t\tsource: message.content.source,\n\t\t\t\t};\n\n\t\t\t\tawait callback?.(response);\n\t\t\t} catch (error) {\n\t\t\t\truntime.logger.error(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord:action:pin-message\",\n\t\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t},\n\t\t\t\t\t\"Failed to pin message\",\n\t\t\t\t);\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I couldn't pin that message. The channel might have reached the maximum number of pinned messages (50).\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (error) {\n\t\t\truntime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:pin-message\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error pinning message\",\n\t\t\t);\n\t\t\tawait callback?.({\n\t\t\t\ttext: \"I encountered an error while trying to pin the message. Please make sure I have the necessary permissions.\",\n\t\t\t\tsource: \"discord\",\n\t\t\t});\n\t\t}\n\t},\n\texamples: (spec.examples ?? []) as ActionExample[][],\n};\n\nexport default pinMessage;\n",
|
|
99
|
+
"import {\n\ttype Action,\n\ttype ActionExample,\n\ttype ActionResult,\n\ttype Content,\n\tcomposePromptFromState,\n\ttype HandlerCallback,\n\ttype HandlerOptions,\n\ttype IAgentRuntime,\n\ttype Memory,\n\tModelType,\n\tparseJSONObjectFromText,\n\ttype State,\n} from \"@elizaos/core\";\nimport type { Message, TextChannel } from \"discord.js\";\nimport { DISCORD_SERVICE_NAME } from \"../constants\";\nimport { reactToMessageTemplate } from \"../generated/prompts/typescript/prompts.js\";\nimport { requireActionSpec } from \"../generated/specs/spec-helpers\";\nimport type { DiscordService } from \"../service\";\n\n/**\n * Extracts emoji tokens from a string in the order they appear.\n *\n * Captures standard Unicode emoji sequences (including multi-codepoint sequences joined by zero-width joiners) and Discord custom emoji tokens in the form `<:name:id>` or `<a:name:id>`.\n *\n * @param text - The input text to scan for emojis\n * @returns An array of emoji strings found in `text`, in the order they appear (empty if none)\n */\nfunction extractEmojisFromText(text: string): string[] {\n\tif (!text) {\n\t\treturn [];\n\t}\n\n\t// Collect all emoji matches with their positions to preserve order\n\tconst matches: { index: number; emoji: string }[] = [];\n\n\t// Match Unicode emojis (including multi-codepoint sequences)\n\tconst unicodeEmojiRegex =\n\t\t/(?:\\p{Emoji_Presentation}|\\p{Extended_Pictographic})(?:\\uFE0F)?(?:\\u200D(?:\\p{Emoji_Presentation}|\\p{Extended_Pictographic})(?:\\uFE0F)?)*/gu;\n\tlet match: RegExpExecArray | null = null;\n\tmatch = unicodeEmojiRegex.exec(text);\n\twhile (match !== null) {\n\t\tmatches.push({ index: match.index, emoji: match[0] });\n\t\tmatch = unicodeEmojiRegex.exec(text);\n\t}\n\n\t// Match Discord custom emojis <:name:id> or <a:name:id>\n\tconst customEmojiRegex = /<a?:\\w+:\\d+>/g;\n\tmatch = customEmojiRegex.exec(text);\n\twhile (match !== null) {\n\t\tmatches.push({ index: match.index, emoji: match[0] });\n\t\tmatch = customEmojiRegex.exec(text);\n\t}\n\n\t// Sort by position and return just the emojis\n\treturn matches.sort((a, b) => a.index - b.index).map((m) => m.emoji);\n}\n\n/**\n * Determines whether a message explicitly requests adding a reaction or specifies a target.\n *\n * @param text - The message text to inspect for reaction-related keywords or target patterns\n * @returns `true` if the text contains reaction keywords OR specifies a message target; `false` otherwise.\n */\nfunction isExplicitReactionRequest(text: string): boolean {\n\tif (!text) {\n\t\treturn false;\n\t}\n\tconst lower = text.toLowerCase();\n\n\t// Keywords indicating user explicitly requested a reaction\n\tif (/\\b(react|reaction|emoji)\\b/.test(lower)) {\n\t\treturn true;\n\t}\n\n\t// Patterns indicating a specific message target (e.g., \"add thumbs up to john's message\")\n\t// These require LLM to extract the correct messageRef\n\tif (/\\w+'s\\s+message\\b/.test(lower)) {\n\t\treturn true;\n\t} // \"john's message\"\n\tif (/message\\s+(about|from|where)\\b/.test(lower)) {\n\t\treturn true;\n\t} // \"message about X\"\n\tif (/\\bto\\s+\\w+'s\\b/.test(lower)) {\n\t\treturn true;\n\t} // \"to john's\"\n\tif (/\\bthat\\s+message\\b/.test(lower)) {\n\t\treturn true;\n\t} // \"that message\"\n\n\treturn false;\n}\n\n// Common Discord emoji mappings\nconst emojiMap: Record<string, string> = {\n\t\":thumbsup:\": \"👍\",\n\t\":thumbs_up:\": \"👍\",\n\t\":+1:\": \"👍\",\n\t\":thumbsdown:\": \"👎\",\n\t\":thumbs_down:\": \"👎\",\n\t\":-1:\": \"👎\",\n\t\":heart:\": \"❤️\",\n\t\":fire:\": \"🔥\",\n\t\":star:\": \"⭐\",\n\t\":check:\": \"✅\",\n\t\":white_check_mark:\": \"✅\",\n\t\":x:\": \"❌\",\n\t\":cross:\": \"❌\",\n\t\":smile:\": \"😄\",\n\t\":laughing:\": \"😆\",\n\t\":thinking:\": \"🤔\",\n\t\":eyes:\": \"👀\",\n\t\":clap:\": \"👏\",\n\t\":wave:\": \"👋\",\n\t\":ok:\": \"👌\",\n\t\":ok_hand:\": \"👌\",\n\t\":raised_hands:\": \"🙌\",\n\t\":pray:\": \"🙏\",\n\t\":100:\": \"💯\",\n\t\":rocket:\": \"🚀\",\n};\n\nconst spec = requireActionSpec(\"REACT_TO_MESSAGE\");\n\nexport const reactToMessage: Action = {\n\tname: spec.name,\n\tsimiles: spec.similes ? [...spec.similes] : [],\n\tdescription: spec.description,\n\tvalidate: async (\n\t\truntime: any,\n\t\tmessage: any,\n\t\tstate?: any,\n\t\toptions?: any,\n\t): Promise<boolean> => {\n\t\tconst __avTextRaw =\n\t\t\ttypeof message?.content?.text === \"string\" ? message.content.text : \"\";\n\t\tconst __avText = __avTextRaw.toLowerCase();\n\t\tconst __avKeywords = [\"react\", \"message\"];\n\t\tconst __avKeywordOk =\n\t\t\t__avKeywords.length > 0 &&\n\t\t\t__avKeywords.some((word) => word.length > 0 && __avText.includes(word));\n\t\tconst __avRegex = /\\b(?:react|message)\\b/i;\n\t\tconst __avRegexOk = __avRegex.test(__avText);\n\t\tconst __avSource = String(\n\t\t\tmessage?.content?.source ?? message?.source ?? \"\",\n\t\t);\n\t\tconst __avExpectedSource = \"\";\n\t\tconst __avSourceOk = __avExpectedSource\n\t\t\t? __avSource === __avExpectedSource\n\t\t\t: Boolean(\n\t\t\t\t\t__avSource ||\n\t\t\t\t\t\tstate ||\n\t\t\t\t\t\truntime?.agentId ||\n\t\t\t\t\t\truntime?.getService ||\n\t\t\t\t\t\truntime?.getSetting,\n\t\t\t\t);\n\t\tconst __avOptions = options && typeof options === \"object\" ? options : {};\n\t\tconst __avInputOk =\n\t\t\t__avText.trim().length > 0 ||\n\t\t\tObject.keys(__avOptions as Record<string, unknown>).length > 0 ||\n\t\t\tBoolean(message?.content && typeof message.content === \"object\");\n\n\t\tif (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst __avLegacyValidate = async (\n\t\t\t_runtime: IAgentRuntime,\n\t\t\tmessage: Memory,\n\t\t\t_state?: State,\n\t\t): Promise<boolean> => {\n\t\t\treturn message.content.source === \"discord\";\n\t\t};\n\t\ttry {\n\t\t\treturn Boolean(\n\t\t\t\tawait (__avLegacyValidate as any)(runtime, message, state, options),\n\t\t\t);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t},\n\thandler: async (\n\t\truntime: IAgentRuntime,\n\t\tmessage: Memory,\n\t\tstate?: State,\n\t\t_options?: HandlerOptions,\n\t\tcallback?: HandlerCallback,\n\t): Promise<ActionResult | undefined> => {\n\t\tconst discordService = runtime.getService(\n\t\t\tDISCORD_SERVICE_NAME,\n\t\t) as DiscordService;\n\n\t\tif (!discordService || !discordService.client) {\n\t\t\tawait callback?.({\n\t\t\t\ttext: \"Discord service is not available.\",\n\t\t\t\tsource: \"discord\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// ============================================================================\n\t\t// Extract reaction info - use fast path when appropriate, LLM otherwise\n\t\t// ============================================================================\n\t\tlet reactionInfo: { messageRef: string; emoji: string } | null = null;\n\n\t\t// Check if user explicitly requested a reaction (needs LLM for accuracy)\n\t\t// vs agent spontaneously reacting (fast path to \"last message\" is correct)\n\t\tconst messageContent = message.content;\n\t\tconst userText = messageContent?.text || \"\";\n\t\tconst needsLLM = isExplicitReactionRequest(userText);\n\n\t\tif (!needsLLM) {\n\t\t\t// FAST PATH: Agent spontaneously reacting - target is always \"last message\"\n\t\t\tconst stateData = state.data as Record<string, unknown> | undefined;\n\t\t\tconst stateWithResponseText = state as State & { responseText?: string };\n\t\t\tconst responseText = String(\n\t\t\t\tstateData?.responseText ||\n\t\t\t\t\tstateData?.text ||\n\t\t\t\t\tstateWithResponseText.responseText ||\n\t\t\t\t\t\"\",\n\t\t\t);\n\n\t\t\tif (responseText) {\n\t\t\t\tconst emojis = extractEmojisFromText(responseText);\n\t\t\t\tif (emojis.length > 0) {\n\t\t\t\t\truntime.logger.debug(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord:action:react\",\n\t\t\t\t\t\t\temoji: emojis[0],\n\t\t\t\t\t\t\tsource: \"responseText\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"[REACT_TO_MESSAGE] Found emoji in response text (fast path)\",\n\t\t\t\t\t);\n\t\t\t\t\treactionInfo = { messageRef: \"last\", emoji: emojis[0] };\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!reactionInfo) {\n\t\t\t\t// Check recent messages for this agent's last message\n\t\t\t\tconst stateData = state.data;\n\t\t\t\tconst recentMessages = (stateData?.recentMessages || []) as Memory[];\n\t\t\t\tconst agentLastMessage = recentMessages\n\t\t\t\t\t.filter((m) => m.entityId === runtime.agentId)\n\t\t\t\t\t.pop();\n\n\t\t\t\tconst agentLastMessageContent = agentLastMessage?.content;\n\t\t\t\tif (agentLastMessageContent?.text) {\n\t\t\t\t\tconst emojis = extractEmojisFromText(agentLastMessageContent.text);\n\t\t\t\t\tif (emojis.length > 0) {\n\t\t\t\t\t\truntime.logger.debug(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsrc: \"plugin:discord:action:react\",\n\t\t\t\t\t\t\t\temoji: emojis[0],\n\t\t\t\t\t\t\t\tsource: \"agentLastMessage\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"[REACT_TO_MESSAGE] Found emoji in agent's last message (fast path)\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\treactionInfo = { messageRef: \"last\", emoji: emojis[0] };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!reactionInfo) {\n\t\t\t// LLM PATH: Use when fast path fails or user specified a specific target\n\t\t\tconst prompt = composePromptFromState({\n\t\t\t\tstate,\n\t\t\t\ttemplate: reactToMessageTemplate,\n\t\t\t});\n\n\t\t\tfor (let i = 0; i < 3; i++) {\n\t\t\t\tconst response = await runtime.useModel(ModelType.TEXT_SMALL, {\n\t\t\t\t\tprompt,\n\t\t\t\t});\n\n\t\t\t\tconst parsedResponse = parseJSONObjectFromText(response);\n\t\t\t\tif (parsedResponse?.emoji) {\n\t\t\t\t\treactionInfo = {\n\t\t\t\t\t\tmessageRef: String(parsedResponse.messageRef || \"last\"),\n\t\t\t\t\t\temoji: String(parsedResponse.emoji),\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!reactionInfo) {\n\t\t\truntime.logger.debug(\n\t\t\t\t{ src: \"plugin:discord:action:react\" },\n\t\t\t\t\"[REACT_TO_MESSAGE] Could not extract reaction info\",\n\t\t\t);\n\t\t\t// Only show error to user if they explicitly requested a reaction\n\t\t\t// Silent failure is appropriate when agent spontaneously decides to react\n\t\t\tif (needsLLM) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I couldn't understand which message to react to or what emoji to use. Try being more specific, like 'react with 👍 to the last message'.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst stateData = state.data;\n\t\t\tconst room = stateData?.room || (await runtime.getRoom(message.roomId));\n\t\t\tif (!room || !room.channelId) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I couldn't determine the current channel.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst channel = await discordService.client.channels.fetch(\n\t\t\t\troom.channelId,\n\t\t\t);\n\t\t\tif (!channel || !channel.isTextBased()) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I can only react to messages in text channels.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst textChannel = channel as TextChannel;\n\n\t\t\tlet targetMessage: Message | null = null;\n\n\t\t\t// Find the target message\n\t\t\tif (\n\t\t\t\treactionInfo.messageRef === \"last\" ||\n\t\t\t\treactionInfo.messageRef === \"previous\"\n\t\t\t) {\n\t\t\t\t// Get the last few messages - fetch max allowed by Discord API\n\t\t\t\tconst messages = await textChannel.messages.fetch({ limit: 100 });\n\t\t\t\tconst sortedMessages = Array.from(messages.values()).sort(\n\t\t\t\t\t(a, b) => b.createdTimestamp - a.createdTimestamp,\n\t\t\t\t);\n\n\t\t\t\t// Skip the bot's own message and the command message\n\t\t\t\tconst clientUser = discordService.client.user;\n\t\t\t\ttargetMessage =\n\t\t\t\t\tsortedMessages.find(\n\t\t\t\t\t\t(msg) =>\n\t\t\t\t\t\t\tmsg.id !== message.content.id && msg.author.id !== clientUser?.id,\n\t\t\t\t\t) || null;\n\t\t\t} else if (/^\\d+$/.test(reactionInfo.messageRef)) {\n\t\t\t\t// It's a message ID\n\t\t\t\ttry {\n\t\t\t\t\ttargetMessage = await textChannel.messages.fetch(\n\t\t\t\t\t\treactionInfo.messageRef,\n\t\t\t\t\t);\n\t\t\t\t} catch (_e) {\n\t\t\t\t\t// Message not found\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Search for message by content/author - fetch max allowed by Discord API\n\t\t\t\tconst messages = await textChannel.messages.fetch({ limit: 100 });\n\t\t\t\tconst searchLower = reactionInfo.messageRef.toLowerCase();\n\n\t\t\t\ttargetMessage =\n\t\t\t\t\tArray.from(messages.values()).find((msg) => {\n\t\t\t\t\t\tconst contentMatch = msg.content\n\t\t\t\t\t\t\t.toLowerCase()\n\t\t\t\t\t\t\t.includes(searchLower);\n\t\t\t\t\t\tconst authorMatch = msg.author.username\n\t\t\t\t\t\t\t.toLowerCase()\n\t\t\t\t\t\t\t.includes(searchLower);\n\t\t\t\t\t\treturn contentMatch || authorMatch;\n\t\t\t\t\t}) || null;\n\t\t\t}\n\n\t\t\tif (!targetMessage) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I couldn't find the message you want me to react to. Try being more specific or use 'last message'.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Normalize the emoji\n\t\t\tlet emoji = reactionInfo.emoji;\n\t\t\tif (!/\\p{Emoji}/u.test(emoji)) {\n\t\t\t\tconst mapped = emojiMap[emoji.toLowerCase()];\n\t\t\t\tif (mapped) {\n\t\t\t\t\temoji = mapped;\n\t\t\t\t} else if (!/<a?:\\w+:\\d+>/.test(emoji)) {\n\t\t\t\t\t// Not a custom emoji, remove colons\n\t\t\t\t\temoji = emoji.replace(/:/g, \"\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add the reaction\n\t\t\ttry {\n\t\t\t\tawait targetMessage.react(emoji);\n\n\t\t\t\tconst response: Content = {\n\t\t\t\t\ttext: `I've added a ${emoji} reaction to the message.`,\n\t\t\t\t\tsource: message.content.source,\n\t\t\t\t};\n\n\t\t\t\tawait callback?.(response);\n\t\t\t} catch (error) {\n\t\t\t\truntime.logger.error(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord:action:react-to-message\",\n\t\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\t\temoji: reactionInfo.emoji,\n\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t},\n\t\t\t\t\t\"Failed to add reaction\",\n\t\t\t\t);\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: `I couldn't add that reaction. Make sure the emoji \"${reactionInfo.emoji}\" is valid and I have permission to add reactions.`,\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (error) {\n\t\t\truntime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:react-to-message\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error in react to message\",\n\t\t\t);\n\t\t\tawait callback?.({\n\t\t\t\ttext: \"I encountered an error while trying to react to the message. Please make sure I have the necessary permissions.\",\n\t\t\t\tsource: \"discord\",\n\t\t\t});\n\t\t}\n\t},\n\texamples: (spec.examples ?? []) as ActionExample[][],\n};\n\nexport default reactToMessage;\n",
|
|
100
|
+
"import {\n\ttype Action,\n\ttype ActionExample,\n\ttype ActionResult,\n\ttype Content,\n\tcomposePromptFromState,\n\ttype HandlerCallback,\n\ttype HandlerOptions,\n\ttype IAgentRuntime,\n\ttype Memory,\n\tModelType,\n\tparseJSONObjectFromText,\n\ttype State,\n} from \"@elizaos/core\";\nimport { PermissionsBitField, type TextChannel } from \"discord.js\";\nimport { DISCORD_SERVICE_NAME } from \"../constants\";\nimport { channelInfoTemplate } from \"../generated/prompts/typescript/prompts.js\";\nimport { requireActionSpec } from \"../generated/specs/spec-helpers\";\nimport type { DiscordService } from \"../service\";\n\n/**\n * Get channel information from the user's request\n * @param {IAgentRuntime} runtime - The runtime object to interact with the agent.\n * @param {Memory} _message - The memory object containing the input message.\n * @param {State} state - The state of the conversation.\n * @returns {Promise<{channelIdentifier: string, messageCount: number} | null>} Channel info or null if not parseable.\n */\nconst getChannelInfo = async (\n\truntime: IAgentRuntime,\n\t_message: Memory,\n\tstate: State,\n): Promise<{\n\tchannelIdentifier: string;\n\tmessageCount: number;\n\tsummarize: boolean;\n\tfocusUser: string | null;\n} | null> => {\n\tconst prompt = composePromptFromState({\n\t\tstate,\n\t\ttemplate: channelInfoTemplate,\n\t});\n\n\tfor (let i = 0; i < 3; i++) {\n\t\tconst response = await runtime.useModel(ModelType.TEXT_SMALL, {\n\t\t\tprompt,\n\t\t});\n\n\t\tconst parsedResponse = parseJSONObjectFromText(response) as {\n\t\t\tchannelIdentifier: string;\n\t\t\tmessageCount: number;\n\t\t\tsummarize?: boolean;\n\t\t\tfocusUser?: string | null;\n\t\t} | null;\n\n\t\tif (parsedResponse?.channelIdentifier) {\n\t\t\t// Ensure messageCount is within bounds\n\t\t\tconst messageCount = Math.min(\n\t\t\t\tMath.max(parsedResponse.messageCount || 10, 1),\n\t\t\t\t50,\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tchannelIdentifier: parsedResponse.channelIdentifier,\n\t\t\t\tmessageCount,\n\t\t\t\tsummarize: parsedResponse.summarize || false,\n\t\t\t\tfocusUser: parsedResponse.focusUser || null,\n\t\t\t};\n\t\t}\n\t}\n\treturn null;\n};\n\nconst fallbackSpec = {\n\tname: \"READ_CHANNEL\",\n\tdescription: \"Read recent messages from a Discord channel.\",\n\tsimiles: [\"SHOW_MESSAGES\", \"CHECK_CHANNEL\"],\n\texamples: [] as ActionExample[][],\n};\n\nconst spec = (() => {\n\ttry {\n\t\treturn requireActionSpec(\"READ_CHANNEL\");\n\t} catch {\n\t\treturn fallbackSpec;\n\t}\n})();\n\nexport const readChannel: Action = {\n\tname: spec.name,\n\tsimiles: spec.similes ? [...spec.similes] : [],\n\tdescription: spec.description,\n\tvalidate: async (\n\t\truntime: any,\n\t\tmessage: any,\n\t\tstate?: any,\n\t\toptions?: any,\n\t): Promise<boolean> => {\n\t\tconst __avTextRaw =\n\t\t\ttypeof message?.content?.text === \"string\" ? message.content.text : \"\";\n\t\tconst __avText = __avTextRaw.toLowerCase();\n\t\tconst __avKeywords = [\"read\", \"channel\"];\n\t\tconst __avKeywordOk =\n\t\t\t__avKeywords.length > 0 &&\n\t\t\t__avKeywords.some((word) => word.length > 0 && __avText.includes(word));\n\t\tconst __avRegex = /\\b(?:read|channel)\\b/i;\n\t\tconst __avRegexOk = __avRegex.test(__avText);\n\t\tconst __avSource = String(\n\t\t\tmessage?.content?.source ?? message?.source ?? \"\",\n\t\t);\n\t\tconst __avExpectedSource = \"\";\n\t\tconst __avSourceOk = __avExpectedSource\n\t\t\t? __avSource === __avExpectedSource\n\t\t\t: Boolean(\n\t\t\t\t\t__avSource ||\n\t\t\t\t\t\tstate ||\n\t\t\t\t\t\truntime?.agentId ||\n\t\t\t\t\t\truntime?.getService ||\n\t\t\t\t\t\truntime?.getSetting,\n\t\t\t\t);\n\t\tconst __avOptions = options && typeof options === \"object\" ? options : {};\n\t\tconst __avInputOk =\n\t\t\t__avText.trim().length > 0 ||\n\t\t\tObject.keys(__avOptions as Record<string, unknown>).length > 0 ||\n\t\t\tBoolean(message?.content && typeof message.content === \"object\");\n\n\t\tif (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst __avLegacyValidate = async (\n\t\t\t_runtime: IAgentRuntime,\n\t\t\tmessage: Memory,\n\t\t\t_state?: State,\n\t\t): Promise<boolean> => {\n\t\t\treturn message.content.source === \"discord\";\n\t\t};\n\t\ttry {\n\t\t\treturn Boolean(\n\t\t\t\tawait (__avLegacyValidate as any)(runtime, message, state, options),\n\t\t\t);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t},\n\thandler: async (\n\t\truntime: IAgentRuntime,\n\t\tmessage: Memory,\n\t\tstate?: State,\n\t\t_options?: HandlerOptions,\n\t\tcallback?: HandlerCallback,\n\t): Promise<ActionResult | undefined> => {\n\t\tconst discordService = runtime.getService(\n\t\t\tDISCORD_SERVICE_NAME,\n\t\t) as DiscordService;\n\n\t\tif (!discordService || !discordService.client) {\n\t\t\truntime.logger.error(\n\t\t\t\t{ src: \"plugin:discord:action:read-channel\", agentId: runtime.agentId },\n\t\t\t\t\"Discord service not found or not initialized\",\n\t\t\t);\n\t\t\treturn { success: false, error: \"Discord service not available\" };\n\t\t}\n\n\t\tif (!state) {\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"State is not available.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { success: false, error: \"State is not available\" };\n\t\t}\n\n\t\tconst channelInfo = await getChannelInfo(runtime, message, state);\n\t\tif (!channelInfo) {\n\t\t\truntime.logger.warn(\n\t\t\t\t{ src: \"plugin:discord:action:read-channel\", agentId: runtime.agentId },\n\t\t\t\t\"Could not parse channel information from message\",\n\t\t\t);\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I couldn't understand which channel you want me to read from. Please specify the channel name or say 'this channel' for the current channel.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { success: false, error: \"Could not parse channel information\" };\n\t\t}\n\n\t\ttry {\n\t\t\tlet targetChannel: TextChannel | null = null;\n\t\t\tconst stateData = state.data;\n\t\t\tconst room = stateData?.room || (await runtime.getRoom(message.roomId));\n\n\t\t\t// Determine the target channel\n\t\t\tif (\n\t\t\t\tchannelInfo.channelIdentifier === \"current\" ||\n\t\t\t\tchannelInfo.channelIdentifier === \"this\" ||\n\t\t\t\tchannelInfo.channelIdentifier === \"here\"\n\t\t\t) {\n\t\t\t\t// Use current channel\n\t\t\t\tif (room?.channelId) {\n\t\t\t\t\ttargetChannel = (await discordService.client.channels.fetch(\n\t\t\t\t\t\troom.channelId,\n\t\t\t\t\t)) as TextChannel;\n\t\t\t\t}\n\t\t\t} else if (channelInfo.channelIdentifier.match(/^\\d+$/)) {\n\t\t\t\t// It's a channel ID\n\t\t\t\ttargetChannel = (await discordService.client.channels.fetch(\n\t\t\t\t\tchannelInfo.channelIdentifier,\n\t\t\t\t)) as TextChannel;\n\t\t\t} else {\n\t\t\t\t// It's a channel name - search in the current server\n\t\t\t\tconst serverId = room?.messageServerId;\n\t\t\t\tif (!serverId) {\n\t\t\t\t\tif (callback) {\n\t\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\t\ttext: \"I couldn't determine which server to search for that channel.\",\n\t\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn { success: false, error: \"Could not determine server\" };\n\t\t\t\t}\n\t\t\t\tconst guild = await discordService.client.guilds.fetch(serverId);\n\t\t\t\tconst channels = await guild.channels.fetch();\n\n\t\t\t\ttargetChannel =\n\t\t\t\t\t(channels.find(\n\t\t\t\t\t\t(channel) =>\n\t\t\t\t\t\t\tchannel?.name\n\t\t\t\t\t\t\t\t.toLowerCase()\n\t\t\t\t\t\t\t\t.includes(channelInfo.channelIdentifier.toLowerCase()) &&\n\t\t\t\t\t\t\tchannel.isTextBased(),\n\t\t\t\t\t) as TextChannel | undefined) || null;\n\t\t\t}\n\n\t\t\tif (!targetChannel || !targetChannel.isTextBased()) {\n\t\t\t\tif (callback) {\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\ttext: \"I couldn't find that channel or I don't have access to it. Make sure the channel exists and I have permission to read messages there.\",\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn { success: false, error: \"Channel not found or not accessible\" };\n\t\t\t}\n\n\t\t\t// Check permissions\n\t\t\tconst targetChannelGuild = targetChannel.guild;\n\t\t\tconst clientUser = discordService.client.user;\n\t\t\tconst botMember = targetChannelGuild?.members.cache.get(clientUser?.id);\n\t\t\tif (botMember) {\n\t\t\t\tconst permissions = targetChannel.permissionsFor(botMember);\n\t\t\t\tif (\n\t\t\t\t\t!permissions ||\n\t\t\t\t\t!permissions.has(PermissionsBitField.Flags.ReadMessageHistory)\n\t\t\t\t) {\n\t\t\t\t\tif (callback) {\n\t\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\t\ttext: \"I don't have permission to read message history in that channel.\",\n\t\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\terror: \"Missing ReadMessageHistory permission\",\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Fetch messages - get more for summarization to have better context\n\t\t\t// Discord API limits to 100 messages per fetch\n\t\t\tconst requestedLimit = channelInfo.summarize\n\t\t\t\t? Math.max(channelInfo.messageCount * 2, 50)\n\t\t\t\t: channelInfo.messageCount;\n\t\t\tconst fetchLimit = Math.min(requestedLimit, 100);\n\n\t\t\truntime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:read-channel\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\tchannelName: targetChannel.name,\n\t\t\t\t\tfetchLimit,\n\t\t\t\t\trequestedLimit,\n\t\t\t\t\tsummarize: channelInfo.summarize,\n\t\t\t\t\tfocusUser: channelInfo.focusUser,\n\t\t\t\t},\n\t\t\t\t\"Fetching messages\",\n\t\t\t);\n\n\t\t\tconst messages = await targetChannel.messages.fetch({\n\t\t\t\tlimit: fetchLimit,\n\t\t\t});\n\n\t\t\tif (messages.size === 0) {\n\t\t\t\tif (callback) {\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\ttext: `No messages found in <#${targetChannel.id}>.`,\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn { success: true, text: `No messages found in channel` };\n\t\t\t}\n\n\t\t\t// If summarization is requested\n\t\t\tif (channelInfo.summarize) {\n\t\t\t\tconst sortedMessages = Array.from(messages.values()).reverse();\n\n\t\t\t\t// Filter by user if specified\n\t\t\t\tconst relevantMessages = channelInfo.focusUser\n\t\t\t\t\t? sortedMessages.filter((msg) => {\n\t\t\t\t\t\t\tconst focusUserLower = channelInfo.focusUser?.toLowerCase();\n\t\t\t\t\t\t\tconst msgMember = msg.member;\n\t\t\t\t\t\t\tconst msgMemberDisplayName = msgMember?.displayName;\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\tmsg.author.username\n\t\t\t\t\t\t\t\t\t.toLowerCase()\n\t\t\t\t\t\t\t\t\t.includes(focusUserLower || \"\") ||\n\t\t\t\t\t\t\t\tmsgMemberDisplayName\n\t\t\t\t\t\t\t\t\t?.toLowerCase()\n\t\t\t\t\t\t\t\t\t.includes(focusUserLower || \"\")\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})\n\t\t\t\t\t: sortedMessages;\n\n\t\t\t\tif (channelInfo.focusUser && relevantMessages.length === 0) {\n\t\t\t\t\tif (callback) {\n\t\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\t\ttext: `I couldn't find any messages from \"${channelInfo.focusUser}\" in the recent messages from <#${targetChannel.id}>.`,\n\t\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\ttext: `No messages found from ${channelInfo.focusUser}`,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t// Prepare messages for summarization\n\t\t\t\tconst messagesToSummarize = relevantMessages\n\t\t\t\t\t.slice(0, channelInfo.messageCount)\n\t\t\t\t\t.map((msg) => ({\n\t\t\t\t\t\tauthor: msg.author.username,\n\t\t\t\t\t\tcontent: msg.content || \"[No text content]\",\n\t\t\t\t\t\ttimestamp: new Date(msg.createdTimestamp).toLocaleString(),\n\t\t\t\t\t}));\n\n\t\t\t\t// Create a summary prompt\n\t\t\t\tconst summaryPrompt = channelInfo.focusUser\n\t\t\t\t\t? `Please summarize what ${channelInfo.focusUser} has been discussing based on these messages from the Discord channel \"${targetChannel.name}\":\\n\\n${messagesToSummarize\n\t\t\t\t\t\t\t.map((m) => `${m.author} (${m.timestamp}): ${m.content}`)\n\t\t\t\t\t\t\t.join(\n\t\t\t\t\t\t\t\t\"\\n\\n\",\n\t\t\t\t\t\t\t)}\\n\\nProvide a concise summary focusing on:\\n1. Main topics ${channelInfo.focusUser} discussed\\n2. Key points or proposals they made\\n3. Any questions they asked or issues they raised\\n\\nIf ${channelInfo.focusUser} didn't appear in these messages, please note that.`\n\t\t\t\t\t: `Please summarize the recent conversation in the Discord channel \"${targetChannel.name}\" based on these messages:\\n\\n${messagesToSummarize\n\t\t\t\t\t\t\t.map((m) => `${m.author} (${m.timestamp}): ${m.content}`)\n\t\t\t\t\t\t\t.join(\n\t\t\t\t\t\t\t\t\"\\n\\n\",\n\t\t\t\t\t\t\t)}\\n\\nProvide a concise summary that includes:\\n1. Main topics discussed\\n2. Key decisions or conclusions\\n3. Who contributed what (mention specific usernames)\\n4. Any action items or next steps mentioned`;\n\n\t\t\t\tconst summary = await runtime.useModel(ModelType.TEXT_LARGE, {\n\t\t\t\t\tprompt: summaryPrompt,\n\t\t\t\t});\n\n\t\t\t\tconst response: Content = {\n\t\t\t\t\ttext: channelInfo.focusUser\n\t\t\t\t\t\t? `Summary of what ${channelInfo.focusUser} has been discussing in <#${targetChannel.id}>:\\n\\n${summary}`\n\t\t\t\t\t\t: `Summary of recent conversation in <#${targetChannel.id}>:\\n\\n${summary}`,\n\t\t\t\t\tactions: [\"READ_CHANNEL_RESPONSE\"],\n\t\t\t\t\tsource: message.content.source,\n\t\t\t\t};\n\n\t\t\t\tif (callback) {\n\t\t\t\t\tawait callback?.(response);\n\t\t\t\t}\n\t\t\t\treturn { success: true, text: response.text };\n\t\t\t} else {\n\t\t\t\t// Format messages for display (original behavior)\n\t\t\t\tconst formattedMessages = Array.from(messages.values())\n\t\t\t\t\t.reverse() // Show oldest first\n\t\t\t\t\t.map((msg) => {\n\t\t\t\t\t\tconst timestamp = new Date(msg.createdTimestamp).toLocaleString();\n\t\t\t\t\t\tconst author = msg.author.username;\n\t\t\t\t\t\tconst content = msg.content || \"[No text content]\";\n\t\t\t\t\t\tconst attachments =\n\t\t\t\t\t\t\tmsg.attachments.size > 0\n\t\t\t\t\t\t\t\t? `\\n📎 Attachments: ${msg.attachments.map((a) => a.name || \"unnamed\").join(\", \")}`\n\t\t\t\t\t\t\t\t: \"\";\n\n\t\t\t\t\t\treturn `**${author}** (${timestamp}):\\n${content}${attachments}`;\n\t\t\t\t\t})\n\t\t\t\t\t.join(\"\\n\\n---\\n\\n\");\n\n\t\t\t\tconst response: Content = {\n\t\t\t\t\ttext: `Here are the last ${messages.size} messages from <#${targetChannel.id}>:\\n\\n${formattedMessages}`,\n\t\t\t\t\tactions: [\"READ_CHANNEL_RESPONSE\"],\n\t\t\t\t\tsource: message.content.source,\n\t\t\t\t};\n\n\t\t\t\tif (callback) {\n\t\t\t\t\tawait callback?.(response);\n\t\t\t\t}\n\t\t\t\treturn { success: true, text: response.text };\n\t\t\t}\n\t\t} catch (error) {\n\t\t\truntime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:read-channel\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error reading channel\",\n\t\t\t);\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I encountered an error while trying to read the channel messages. Please make sure I have the necessary permissions and try again.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t};\n\t\t}\n\t},\n\texamples: (spec.examples ?? []) as ActionExample[][],\n};\n\nexport default readChannel;\n",
|
|
101
|
+
"import {\n\ttype Action,\n\ttype ActionExample,\n\ttype ActionResult,\n\ttype Content,\n\tcomposePromptFromState,\n\ttype HandlerCallback,\n\ttype HandlerOptions,\n\ttype IAgentRuntime,\n\ttype Memory,\n\tModelType,\n\tparseJSONObjectFromText,\n\ttype State,\n} from \"@elizaos/core\";\nimport type { Collection, Message, TextChannel } from \"discord.js\";\nimport { DISCORD_SERVICE_NAME } from \"../constants\";\nimport { searchMessagesTemplate } from \"../generated/prompts/typescript/prompts.js\";\nimport { requireActionSpec } from \"../generated/specs/spec-helpers\";\nimport type { DiscordService } from \"../service\";\n\nconst getSearchParams = async (\n\truntime: IAgentRuntime,\n\t_message: Memory,\n\tstate: State,\n): Promise<{\n\tquery: string;\n\tchannelIdentifier: string;\n\tauthor: string | null;\n\ttimeRange: string | null;\n\tlimit: number;\n} | null> => {\n\tconst prompt = composePromptFromState({\n\t\tstate,\n\t\ttemplate: searchMessagesTemplate,\n\t});\n\n\tfor (let i = 0; i < 3; i++) {\n\t\tconst response = await runtime.useModel(ModelType.TEXT_SMALL, {\n\t\t\tprompt,\n\t\t});\n\n\t\tconst parsedResponse = parseJSONObjectFromText(response);\n\t\tif (parsedResponse?.query) {\n\t\t\t// Remove quotes from query if present\n\t\t\tconst cleanQuery = String(parsedResponse.query).replace(\n\t\t\t\t/^[\"']|[\"']$/g,\n\t\t\t\t\"\",\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tquery: cleanQuery,\n\t\t\t\tchannelIdentifier: String(\n\t\t\t\t\tparsedResponse.channelIdentifier || \"current\",\n\t\t\t\t),\n\t\t\t\tauthor: parsedResponse.author ? String(parsedResponse.author) : null,\n\t\t\t\ttimeRange: parsedResponse.timeRange\n\t\t\t\t\t? String(parsedResponse.timeRange)\n\t\t\t\t\t: null,\n\t\t\t\tlimit: Math.min(Math.max(Number(parsedResponse.limit) || 20, 1), 100),\n\t\t\t};\n\t\t}\n\t}\n\treturn null;\n};\n\nconst searchInMessages = (\n\tmessages: Collection<string, Message>,\n\tquery: string,\n\tauthor?: string | null,\n): Message[] => {\n\tconst queryLower = query.toLowerCase().trim();\n\tconst isLinkSearch =\n\t\tqueryLower.includes(\"link\") || queryLower.includes(\"url\");\n\n\treturn Array.from(messages.values()).filter((msg) => {\n\t\t// Skip system messages\n\t\tif (msg.system) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Filter by author if specified\n\t\tif (author && author !== \"null\" && author !== \"undefined\") {\n\t\t\tconst authorLower = author.toLowerCase();\n\t\t\tconst matchesUsername = msg.author.username\n\t\t\t\t.toLowerCase()\n\t\t\t\t.includes(authorLower);\n\t\t\tconst matchesDisplayName =\n\t\t\t\tmsg.member?.displayName?.toLowerCase().includes(authorLower) || false;\n\t\t\tif (!matchesUsername && !matchesDisplayName) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// Special handling for link searches\n\t\tif (isLinkSearch) {\n\t\t\tconst urlRegex = /(https?:\\/\\/[^\\s]+)/g;\n\t\t\treturn urlRegex.test(msg.content);\n\t\t}\n\n\t\t// Search in message content (case-insensitive)\n\t\tconst contentMatch = msg.content.toLowerCase().includes(queryLower);\n\n\t\t// Search in embeds\n\t\tconst embedMatch = msg.embeds.some(\n\t\t\t(embed) =>\n\t\t\t\tembed.title?.toLowerCase().includes(queryLower) ||\n\t\t\t\tembed.description?.toLowerCase().includes(queryLower) ||\n\t\t\t\tembed.author?.name?.toLowerCase().includes(queryLower) ||\n\t\t\t\tembed.fields?.some(\n\t\t\t\t\t(field) =>\n\t\t\t\t\t\tfield.name?.toLowerCase().includes(queryLower) ||\n\t\t\t\t\t\tfield.value?.toLowerCase().includes(queryLower),\n\t\t\t\t),\n\t\t);\n\n\t\t// Search in attachments\n\t\tconst attachmentMatch = msg.attachments.some(\n\t\t\t(att) =>\n\t\t\t\tatt.name?.toLowerCase().includes(queryLower) ||\n\t\t\t\tatt.description?.toLowerCase().includes(queryLower),\n\t\t);\n\n\t\treturn contentMatch || embedMatch || attachmentMatch;\n\t});\n};\n\nconst fallbackSpec = {\n\tname: \"SEARCH_MESSAGES\",\n\tdescription: \"Search for messages in a Discord channel.\",\n\tsimiles: [\"FIND_MESSAGES\", \"LOOKUP_MESSAGES\"],\n\texamples: [] as ActionExample[][],\n};\n\nconst spec = (() => {\n\ttry {\n\t\treturn requireActionSpec(\"SEARCH_MESSAGES\");\n\t} catch {\n\t\treturn fallbackSpec;\n\t}\n})();\n\nexport const searchMessages: Action = {\n\tname: spec.name,\n\tsimiles: spec.similes ? [...spec.similes] : [],\n\tdescription: spec.description,\n\tvalidate: async (\n\t\truntime: any,\n\t\tmessage: any,\n\t\tstate?: any,\n\t\toptions?: any,\n\t): Promise<boolean> => {\n\t\tconst __avTextRaw =\n\t\t\ttypeof message?.content?.text === \"string\" ? message.content.text : \"\";\n\t\tconst __avText = __avTextRaw.toLowerCase();\n\t\tconst __avKeywords = [\"search\", \"messages\"];\n\t\tconst __avKeywordOk =\n\t\t\t__avKeywords.length > 0 &&\n\t\t\t__avKeywords.some((word) => word.length > 0 && __avText.includes(word));\n\t\tconst __avRegex = /\\b(?:search|messages)\\b/i;\n\t\tconst __avRegexOk = __avRegex.test(__avText);\n\t\tconst __avSource = String(\n\t\t\tmessage?.content?.source ?? message?.source ?? \"\",\n\t\t);\n\t\tconst __avExpectedSource = \"\";\n\t\tconst __avSourceOk = __avExpectedSource\n\t\t\t? __avSource === __avExpectedSource\n\t\t\t: Boolean(\n\t\t\t\t\t__avSource ||\n\t\t\t\t\t\tstate ||\n\t\t\t\t\t\truntime?.agentId ||\n\t\t\t\t\t\truntime?.getService ||\n\t\t\t\t\t\truntime?.getSetting,\n\t\t\t\t);\n\t\tconst __avOptions = options && typeof options === \"object\" ? options : {};\n\t\tconst __avInputOk =\n\t\t\t__avText.trim().length > 0 ||\n\t\t\tObject.keys(__avOptions as Record<string, unknown>).length > 0 ||\n\t\t\tBoolean(message?.content && typeof message.content === \"object\");\n\n\t\tif (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst __avLegacyValidate = async (\n\t\t\t_runtime: IAgentRuntime,\n\t\t\tmessage: Memory,\n\t\t\t_state?: State,\n\t\t): Promise<boolean> => {\n\t\t\treturn message.content.source === \"discord\";\n\t\t};\n\t\ttry {\n\t\t\treturn Boolean(\n\t\t\t\tawait (__avLegacyValidate as any)(runtime, message, state, options),\n\t\t\t);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t},\n\thandler: async (\n\t\truntime: IAgentRuntime,\n\t\tmessage: Memory,\n\t\tstate?: State,\n\t\t_options?: HandlerOptions,\n\t\tcallback?: HandlerCallback,\n\t): Promise<ActionResult | undefined> => {\n\t\tconst discordService = runtime.getService(\n\t\t\tDISCORD_SERVICE_NAME,\n\t\t) as DiscordService;\n\n\t\tif (!discordService || !discordService.client) {\n\t\t\tawait callback?.({\n\t\t\t\ttext: \"Discord service is not available.\",\n\t\t\t\tsource: \"discord\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tconst searchParams = await getSearchParams(runtime, message, state);\n\t\tif (!searchParams) {\n\t\t\tawait callback?.({\n\t\t\t\ttext: \"I couldn't understand what you want to search for. Please specify what to search.\",\n\t\t\t\tsource: \"discord\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tlet targetChannel: TextChannel | null = null;\n\t\t\tconst stateData = state.data;\n\t\t\tconst room = stateData?.room || (await runtime.getRoom(message.roomId));\n\n\t\t\t// Determine the target channel\n\t\t\tif (searchParams.channelIdentifier === \"current\") {\n\t\t\t\tif (room?.channelId) {\n\t\t\t\t\ttargetChannel = (await discordService.client.channels.fetch(\n\t\t\t\t\t\troom.channelId,\n\t\t\t\t\t)) as TextChannel;\n\t\t\t\t}\n\t\t\t} else if (searchParams.channelIdentifier.match(/^\\d+$/)) {\n\t\t\t\ttargetChannel = (await discordService.client.channels.fetch(\n\t\t\t\t\tsearchParams.channelIdentifier,\n\t\t\t\t)) as TextChannel;\n\t\t\t} else {\n\t\t\t\t// It's a channel name - search in the current server\n\t\t\t\tconst serverId = room?.messageServerId;\n\t\t\t\tif (!serverId) {\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\ttext: \"I couldn't determine which server to search for that channel.\",\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst guild = await discordService.client.guilds.fetch(serverId);\n\t\t\t\tconst channels = await guild.channels.fetch();\n\t\t\t\ttargetChannel =\n\t\t\t\t\t(channels.find(\n\t\t\t\t\t\t(channel) =>\n\t\t\t\t\t\t\tchannel?.name\n\t\t\t\t\t\t\t\t?.toLowerCase()\n\t\t\t\t\t\t\t\t.includes(searchParams.channelIdentifier.toLowerCase()) &&\n\t\t\t\t\t\t\tchannel.isTextBased(),\n\t\t\t\t\t) as TextChannel | undefined) || null;\n\t\t\t}\n\n\t\t\tif (!targetChannel || !targetChannel.isTextBased()) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I couldn't find that channel or I don't have access to it.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Calculate time limit\n\t\t\tlet before: number | undefined;\n\t\t\tif (searchParams.timeRange) {\n\t\t\t\tconst now = Date.now();\n\t\t\t\tconst timeMap: Record<string, number> = {\n\t\t\t\t\thour: 60 * 60 * 1000,\n\t\t\t\t\tday: 24 * 60 * 60 * 1000,\n\t\t\t\t\tweek: 7 * 24 * 60 * 60 * 1000,\n\t\t\t\t\tmonth: 30 * 24 * 60 * 60 * 1000,\n\t\t\t\t};\n\t\t\t\tif (timeMap[searchParams.timeRange]) {\n\t\t\t\t\tbefore = now - timeMap[searchParams.timeRange];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Fetch messages - Discord API limit is 100 per request\n\t\t\tconst messages = await targetChannel.messages.fetch({\n\t\t\t\tlimit: 100, // Discord API max limit\n\t\t\t\tbefore: before?.toString(),\n\t\t\t});\n\n\t\t\t// Search through messages\n\t\t\tconst results = searchInMessages(\n\t\t\t\tmessages,\n\t\t\t\tsearchParams.query,\n\t\t\t\tsearchParams.author,\n\t\t\t);\n\t\t\truntime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:search-messages\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\tquery: searchParams.query,\n\t\t\t\t\tresultsCount: results.length,\n\t\t\t\t\tchannelName: targetChannel.name,\n\t\t\t\t},\n\t\t\t\t\"Search completed\",\n\t\t\t);\n\n\t\t\t// Sort by timestamp (newest first) and limit\n\t\t\tconst sortedResults = results.sort(\n\t\t\t\t(a, b) => b.createdTimestamp - a.createdTimestamp,\n\t\t\t);\n\t\t\tconst limitedResults = sortedResults.slice(0, searchParams.limit);\n\n\t\t\tif (limitedResults.length === 0) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: `No messages found matching \"${searchParams.query}\" in <#${targetChannel.id}>.`,\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Format results\n\t\t\tconst formattedResults = limitedResults\n\t\t\t\t.map((msg, index) => {\n\t\t\t\t\tconst timestamp = new Date(msg.createdTimestamp).toLocaleString();\n\t\t\t\t\tconst preview =\n\t\t\t\t\t\tmsg.content.length > 100\n\t\t\t\t\t\t\t? `${msg.content.substring(0, 100)}...`\n\t\t\t\t\t\t\t: msg.content;\n\t\t\t\t\tconst attachments =\n\t\t\t\t\t\tmsg.attachments.size > 0\n\t\t\t\t\t\t\t? `\\n📎 ${msg.attachments.size} attachment(s)`\n\t\t\t\t\t\t\t: \"\";\n\n\t\t\t\t\treturn `**${index + 1}.** ${msg.author.username} (${timestamp})\\n${preview}${attachments}\\n[Jump to message](${msg.url})`;\n\t\t\t\t})\n\t\t\t\t.join(\"\\n\\n\");\n\n\t\t\tconst response: Content = {\n\t\t\t\ttext: `Found ${limitedResults.length} message${limitedResults.length !== 1 ? \"s\" : \"\"} matching \"${searchParams.query}\" in <#${targetChannel.id}>:\\n\\n${formattedResults}`,\n\t\t\t\tsource: message.content.source,\n\t\t\t};\n\n\t\t\tawait callback?.(response);\n\t\t} catch (error) {\n\t\t\truntime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:search-messages\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error searching messages\",\n\t\t\t);\n\t\t\tawait callback?.({\n\t\t\t\ttext: \"I encountered an error while searching for messages. Please try again.\",\n\t\t\t\tsource: \"discord\",\n\t\t\t});\n\t\t}\n\t},\n\texamples: (spec.examples ?? []) as ActionExample[][],\n};\n\nexport default searchMessages;\n",
|
|
102
|
+
"import {\n\ttype Action,\n\ttype ActionExample,\n\ttype ActionResult,\n\ttype Content,\n\tcomposePromptFromState,\n\ttype HandlerCallback,\n\ttype HandlerOptions,\n\ttype IAgentRuntime,\n\ttype Memory,\n\tModelType,\n\tparseJSONObjectFromText,\n\ttype State,\n} from \"@elizaos/core\";\nimport type { User } from \"discord.js\";\nimport { DISCORD_SERVICE_NAME } from \"../constants\";\n// Import generated prompts\nimport { sendDmTemplate } from \"../generated/prompts/typescript/prompts.js\";\nimport { requireActionSpec } from \"../generated/specs/spec-helpers\";\nimport type { DiscordService } from \"../service\";\n\n/**\n * Get DM information from the user's request\n * @param {IAgentRuntime} runtime - The runtime object to interact with the agent.\n * @param {Memory} _message - The memory object containing the input message.\n * @param {State} state - The state of the conversation.\n * @returns {Promise<{recipientIdentifier: string, messageContent: string} | null>} DM info or null if not parseable.\n */\nconst getDMInfo = async (\n\truntime: IAgentRuntime,\n\t_message: Memory,\n\tstate: State,\n): Promise<{ recipientIdentifier: string; messageContent: string } | null> => {\n\tconst prompt = composePromptFromState({\n\t\tstate,\n\t\ttemplate: sendDmTemplate,\n\t});\n\n\tfor (let i = 0; i < 3; i++) {\n\t\tconst response = await runtime.useModel(ModelType.TEXT_SMALL, {\n\t\t\tprompt,\n\t\t});\n\n\t\tconst parsedResponse = parseJSONObjectFromText(response) as {\n\t\t\trecipientIdentifier: string;\n\t\t\tmessageContent: string;\n\t\t} | null;\n\n\t\tif (parsedResponse?.recipientIdentifier && parsedResponse.messageContent) {\n\t\t\treturn parsedResponse;\n\t\t}\n\t}\n\treturn null;\n};\n\n/**\n * Find a Discord user by various identifiers\n * @param {DiscordService} discordService - The Discord service instance\n * @param {string} identifier - The user identifier (username, ID, or mention)\n * @param {string} currentServerId - The current server ID to search in\n * @returns {Promise<User | null>} The found user or null\n */\nconst findUser = async (\n\tdiscordService: DiscordService,\n\tidentifier: string,\n\tcurrentServerId?: string,\n): Promise<User | null> => {\n\tif (!discordService.client) {\n\t\treturn null;\n\t}\n\n\t// Remove mention formatting if present\n\tconst cleanId = identifier.replace(/[<@!>]/g, \"\");\n\n\ttry {\n\t\t// Try to fetch by ID first\n\t\tif (/^\\d+$/.test(cleanId)) {\n\t\t\ttry {\n\t\t\t\treturn await discordService.client.users.fetch(cleanId);\n\t\t\t} catch (_e) {\n\t\t\t\t// ID not found, continue to username search\n\t\t\t}\n\t\t}\n\n\t\t// Search in the current server if available\n\t\tif (currentServerId) {\n\t\t\tconst guild = await discordService.client.guilds.fetch(currentServerId);\n\t\t\tconst members = await guild.members.fetch();\n\n\t\t\t// Search by username or display name\n\t\t\tconst member = members.find(\n\t\t\t\t(m) =>\n\t\t\t\t\tm.user.username.toLowerCase() === identifier.toLowerCase() ||\n\t\t\t\t\tm.displayName.toLowerCase() === identifier.toLowerCase() ||\n\t\t\t\t\tm.user.tag.toLowerCase() === identifier.toLowerCase(),\n\t\t\t);\n\n\t\t\tif (member) {\n\t\t\t\treturn member.user;\n\t\t\t}\n\t\t}\n\n\t\t// Search in all guilds the bot is in\n\t\tconst guilds = Array.from(discordService.client.guilds.cache.values());\n\t\tfor (const guild of guilds) {\n\t\t\ttry {\n\t\t\t\tconst members = await guild.members.fetch();\n\t\t\t\tconst member = members.find(\n\t\t\t\t\t(m) =>\n\t\t\t\t\t\tm.user.username.toLowerCase() === identifier.toLowerCase() ||\n\t\t\t\t\t\tm.displayName.toLowerCase() === identifier.toLowerCase() ||\n\t\t\t\t\t\tm.user.tag.toLowerCase() === identifier.toLowerCase(),\n\t\t\t\t);\n\n\t\t\t\tif (member) {\n\t\t\t\t\treturn member.user;\n\t\t\t\t}\n\t\t\t} catch (_e) {\n\t\t\t\t// Continue searching in other guilds\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t} catch (_error) {\n\t\t// Standalone function - error handled by caller\n\t\treturn null;\n\t}\n};\n\nconst spec = requireActionSpec(\"SEND_DM\");\n\nexport const sendDM: Action = {\n\tname: spec.name,\n\tsimiles: spec.similes ? [...spec.similes] : [],\n\tdescription: spec.description,\n\tvalidate: async (\n\t\t_runtime: IAgentRuntime,\n\t\tmessage: Memory,\n\t\t_state?: State,\n\t): Promise<boolean> => {\n\t\treturn message.content.source === \"discord\";\n\t},\n\thandler: async (\n\t\truntime: IAgentRuntime,\n\t\tmessage: Memory,\n\t\tstate?: State,\n\t\t_options?: HandlerOptions,\n\t\tcallback?: HandlerCallback,\n\t): Promise<ActionResult | undefined> => {\n\t\tconst discordService = runtime.getService(\n\t\t\tDISCORD_SERVICE_NAME,\n\t\t) as DiscordService;\n\n\t\tif (!discordService || !discordService.client) {\n\t\t\truntime.logger.error(\n\t\t\t\t{ src: \"plugin:discord:action:send-dm\", agentId: runtime.agentId },\n\t\t\t\t\"Discord service not found or not initialized\",\n\t\t\t);\n\t\t\treturn { success: false, error: \"Discord service is not available\" };\n\t\t}\n\n\t\tif (!state) {\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"State is not available.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { success: false, error: \"State is not available\" };\n\t\t}\n\n\t\tconst dmInfo = await getDMInfo(runtime, message, state);\n\t\tif (!dmInfo) {\n\t\t\truntime.logger.warn(\n\t\t\t\t{ src: \"plugin:discord:action:send-dm\", agentId: runtime.agentId },\n\t\t\t\t\"Could not parse DM information from message\",\n\t\t\t);\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I couldn't understand who you want me to message or what to send. Please specify the recipient and the message content.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { success: false, error: \"Could not parse DM information\" };\n\t\t}\n\n\t\ttry {\n\t\t\tconst room = state.data?.room || (await runtime.getRoom(message.roomId));\n\t\t\tconst currentServerId = room?.messageServerId;\n\n\t\t\t// Find the user\n\t\t\tconst targetUser = await findUser(\n\t\t\t\tdiscordService,\n\t\t\t\tdmInfo.recipientIdentifier,\n\t\t\t\tcurrentServerId,\n\t\t\t);\n\n\t\t\tif (!targetUser) {\n\t\t\t\tif (callback) {\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\ttext: `I couldn't find a user with the identifier \"${dmInfo.recipientIdentifier}\". Please make sure the username or ID is correct.`,\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: `User not found: ${dmInfo.recipientIdentifier}`,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Check if we can send DMs to this user\n\t\t\tif (targetUser.bot) {\n\t\t\t\tif (callback) {\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\ttext: \"I cannot send direct messages to other bots.\",\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn { success: false, error: \"Cannot send DMs to bots\" };\n\t\t\t}\n\n\t\t\t// Create or get DM channel\n\t\t\tconst dmChannel = await targetUser.createDM();\n\n\t\t\t// Send the message\n\t\t\tawait dmChannel.send(dmInfo.messageContent);\n\n\t\t\tconst response: Content = {\n\t\t\t\ttext: `I've sent your message to ${targetUser.username}: \"${dmInfo.messageContent}\"`,\n\t\t\t\tactions: [\"SEND_DM_RESPONSE\"],\n\t\t\t\tsource: message.content.source,\n\t\t\t};\n\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.(response);\n\t\t\t}\n\t\t\treturn { success: true, text: response.text };\n\t\t} catch (error) {\n\t\t\truntime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:send-dm\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error sending DM\",\n\t\t\t);\n\n\t\t\t// Handle specific Discord API errors\n\t\t\tif (error instanceof Error) {\n\t\t\t\tif (error.message.includes(\"Cannot send messages to this user\")) {\n\t\t\t\t\tif (callback) {\n\t\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\t\ttext: \"I couldn't send a message to that user. They may have DMs disabled or we don't share a server.\",\n\t\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (callback) {\n\t\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\t\ttext: \"I encountered an error while trying to send the direct message. Please make sure I have the necessary permissions.\",\n\t\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t};\n\t\t}\n\t},\n\texamples: (spec.examples ?? []) as ActionExample[][],\n};\n\nexport default sendDM;\n",
|
|
103
|
+
"import {\n\ttype Action,\n\ttype ActionExample,\n\ttype ActionResult,\n\ttype Content,\n\tcomposePromptFromState,\n\ttype HandlerCallback,\n\ttype HandlerOptions,\n\ttype IAgentRuntime,\n\ttype Memory,\n\tModelType,\n\tparseJSONObjectFromText,\n\ttype State,\n} from \"@elizaos/core\";\nimport type { TextChannel } from \"discord.js\";\nimport { DISCORD_SERVICE_NAME } from \"../constants\";\nimport { requireActionSpec } from \"../generated/specs/spec-helpers\";\nimport type { DiscordService } from \"../service\";\n\nconst sendMessageTemplate = `You are helping to extract send message parameters.\n\nThe user wants to send a message to a Discord channel.\n\nRecent conversation:\n{{recentMessages}}\n\nExtract the following:\n1. text: The message text to send\n2. channelRef: The channel to send to (default: \"current\" for the current channel)\n\nRespond with a JSON object like:\n{\n \"text\": \"The message to send\",\n \"channelRef\": \"current\"\n}\n\nOnly respond with the JSON object, no other text.`;\n\nconst spec = requireActionSpec(\"SEND_MESSAGE\");\n\nexport const sendMessage: Action = {\n\tname: spec.name,\n\tsimiles: spec.similes ? [...spec.similes] : [],\n\tdescription: spec.description,\n\tvalidate: async (\n\t\t_runtime: IAgentRuntime,\n\t\tmessage: Memory,\n\t\t_state?: State,\n\t): Promise<boolean> => {\n\t\treturn message.content.source === \"discord\";\n\t},\n\thandler: async (\n\t\truntime: IAgentRuntime,\n\t\tmessage: Memory,\n\t\tstate?: State,\n\t\t_options?: HandlerOptions,\n\t\tcallback?: HandlerCallback,\n\t): Promise<ActionResult | undefined> => {\n\t\tconst discordService = runtime.getService(\n\t\t\tDISCORD_SERVICE_NAME,\n\t\t) as DiscordService;\n\n\t\tif (!discordService || !discordService.client) {\n\t\t\tawait callback?.({\n\t\t\t\ttext: \"Discord service is not available.\",\n\t\t\t\tsource: \"discord\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Use LLM to extract message parameters\n\t\tconst prompt = composePromptFromState({\n\t\t\tstate,\n\t\t\ttemplate: sendMessageTemplate,\n\t\t});\n\n\t\tlet messageInfo: { text: string; channelRef?: string } | null = null;\n\n\t\tfor (let i = 0; i < 3; i++) {\n\t\t\tconst response = await runtime.useModel(ModelType.TEXT_SMALL, {\n\t\t\t\tprompt,\n\t\t\t});\n\n\t\t\tconst parsedResponse = parseJSONObjectFromText(response);\n\t\t\tif (parsedResponse?.text) {\n\t\t\t\tmessageInfo = {\n\t\t\t\t\ttext: String(parsedResponse.text),\n\t\t\t\t\tchannelRef: parsedResponse.channelRef\n\t\t\t\t\t\t? String(parsedResponse.channelRef)\n\t\t\t\t\t\t: \"current\",\n\t\t\t\t};\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (!messageInfo || !messageInfo.text) {\n\t\t\truntime.logger.debug(\n\t\t\t\t{ src: \"plugin:discord:action:send-message\" },\n\t\t\t\t\"[SEND_MESSAGE] Could not extract message info\",\n\t\t\t);\n\t\t\tawait callback?.({\n\t\t\t\ttext: \"I couldn't understand what message you want me to send. Please try again with a clearer request.\",\n\t\t\t\tsource: \"discord\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst stateData = state?.data;\n\t\t\tconst room = stateData?.room || (await runtime.getRoom(message.roomId));\n\n\t\t\tif (!room || !room.channelId) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I couldn't determine the current channel.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet targetChannelId = room.channelId;\n\n\t\t\t// If a specific channel was referenced (not \"current\"), try to find it\n\t\t\tif (messageInfo.channelRef && messageInfo.channelRef !== \"current\") {\n\t\t\t\tconst guild = discordService.client.guilds.cache.first();\n\t\t\t\tif (guild) {\n\t\t\t\t\tconst channels = await guild.channels.fetch();\n\t\t\t\t\tconst targetChannel = channels.find((ch) => {\n\t\t\t\t\t\tif (!ch || !ch.isTextBased()) return false;\n\t\t\t\t\t\tconst channelName = ch.name?.toLowerCase() || \"\";\n\t\t\t\t\t\tconst searchTerm = messageInfo?.channelRef?.toLowerCase() || \"\";\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\tchannelName === searchTerm ||\n\t\t\t\t\t\t\tchannelName.includes(searchTerm) ||\n\t\t\t\t\t\t\tch.id === messageInfo?.channelRef\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\t\t\t\t\tif (targetChannel) {\n\t\t\t\t\t\ttargetChannelId = targetChannel.id;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst channel =\n\t\t\t\tawait discordService.client.channels.fetch(targetChannelId);\n\t\t\tif (!channel || !channel.isTextBased()) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I can only send messages to text channels.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst textChannel = channel as TextChannel;\n\n\t\t\t// Send the message\n\t\t\tconst sentMessage = await textChannel.send(messageInfo.text);\n\n\t\t\tconst response: Content = {\n\t\t\t\ttext: `Message sent successfully.`,\n\t\t\t\tsource: message.content.source,\n\t\t\t};\n\n\t\t\truntime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:send-message\",\n\t\t\t\t\tmessageId: sentMessage.id,\n\t\t\t\t\tchannelId: targetChannelId,\n\t\t\t\t},\n\t\t\t\t\"[SEND_MESSAGE] Message sent successfully\",\n\t\t\t);\n\n\t\t\tawait callback?.(response);\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: {\n\t\t\t\t\tmessageId: sentMessage.id,\n\t\t\t\t\tchannelId: targetChannelId,\n\t\t\t\t},\n\t\t\t};\n\t\t} catch (error) {\n\t\t\truntime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:send-message\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error sending message\",\n\t\t\t);\n\t\t\tawait callback?.({\n\t\t\t\ttext: \"I encountered an error while trying to send the message. Please make sure I have the necessary permissions.\",\n\t\t\t\tsource: \"discord\",\n\t\t\t});\n\t\t}\n\t},\n\texamples: (spec.examples ?? []) as ActionExample[][],\n};\n\nexport default sendMessage;\n",
|
|
104
|
+
"import type {\n\tAction,\n\tActionExample,\n\tActionResult,\n\tContent,\n\tHandlerCallback,\n\tHandlerOptions,\n\tIAgentRuntime,\n\tMemory,\n\tState,\n} from \"@elizaos/core\";\nimport type { Guild } from \"discord.js\";\nimport { DISCORD_SERVICE_NAME } from \"../constants\";\nimport { requireActionSpec } from \"../generated/specs/spec-helpers\";\nimport type { DiscordService } from \"../service\";\n\nconst formatServerInfo = (guild: Guild, detailed: boolean = false): string => {\n\tconst createdAt = new Date(guild.createdAt).toLocaleDateString();\n\tconst memberCount = guild.memberCount.toLocaleString();\n\tconst channelCount = guild.channels.cache.size.toLocaleString();\n\tconst roleCount = guild.roles.cache.size.toLocaleString();\n\tconst emojiCount = guild.emojis.cache.size.toLocaleString();\n\tconst boostLevel = guild.premiumTier;\n\tconst boostCount = (guild.premiumSubscriptionCount || 0).toLocaleString();\n\n\tconst basicInfo = [\n\t\t`🏛️ **Server Information for ${guild.name}**`,\n\t\t`**ID:** ${guild.id}`,\n\t\t`**Owner:** <@${guild.ownerId}>`,\n\t\t`**Created:** ${createdAt}`,\n\t\t`**Members:** ${memberCount}`,\n\t\t`**Channels:** ${channelCount}`,\n\t\t`**Roles:** ${roleCount}`,\n\t\t`**Server Level:** ${boostLevel} (${boostCount} boosts)`,\n\t];\n\n\tif (detailed) {\n\t\tconst textChannels = guild.channels.cache\n\t\t\t.filter((ch) => ch.isTextBased())\n\t\t\t.size.toLocaleString();\n\t\tconst voiceChannels = guild.channels.cache\n\t\t\t.filter((ch) => ch.isVoiceBased())\n\t\t\t.size.toLocaleString();\n\t\tconst categories = guild.channels.cache\n\t\t\t.filter((ch) => ch.type === 4)\n\t\t\t.size.toLocaleString(); // CategoryChannel type\n\t\tconst activeThreads = guild.channels.cache\n\t\t\t.filter((ch) => ch.isThread() && !ch.archived)\n\t\t\t.size.toLocaleString();\n\t\tconst stickerCount = guild.stickers.cache.size.toLocaleString();\n\n\t\tconst features =\n\t\t\tguild.features.length > 0\n\t\t\t\t? guild.features\n\t\t\t\t\t\t.map((f) => f.toLowerCase().replace(/_/g, \" \"))\n\t\t\t\t\t\t.join(\", \")\n\t\t\t\t: \"None\";\n\n\t\tconst detailedInfo = [\n\t\t\t\"\",\n\t\t\t\"📊 **Detailed Statistics**\",\n\t\t\t`**Text Channels:** ${textChannels}`,\n\t\t\t`**Voice Channels:** ${voiceChannels}`,\n\t\t\t`**Categories:** ${categories}`,\n\t\t\t`**Active Threads:** ${activeThreads}`,\n\t\t\t`**Custom Emojis:** ${emojiCount}`,\n\t\t\t`**Stickers:** ${stickerCount}`,\n\t\t\t\"\",\n\t\t\t\"🎯 **Server Features**\",\n\t\t\t`**Verification Level:** ${guild.verificationLevel}`,\n\t\t\t`**Content Filter:** ${guild.explicitContentFilter}`,\n\t\t\t`**2FA Requirement:** ${guild.mfaLevel === 1 ? \"Enabled\" : \"Disabled\"}`,\n\t\t\t`**Features:** ${features}`,\n\t\t];\n\n\t\tif (guild.description) {\n\t\t\tdetailedInfo.push(`**Description:** ${guild.description}`);\n\t\t}\n\n\t\tif (guild.vanityURLCode) {\n\t\t\tdetailedInfo.push(`**Vanity URL:** discord.gg/${guild.vanityURLCode}`);\n\t\t}\n\n\t\treturn [...basicInfo, ...detailedInfo].join(\"\\n\");\n\t}\n\n\treturn basicInfo.join(\"\\n\");\n};\n\nconst spec = requireActionSpec(\"SERVER_INFO\");\n\nexport const serverInfo: Action = {\n\tname: spec.name,\n\tsimiles: spec.similes ? [...spec.similes] : [],\n\tdescription: spec.description,\n\tvalidate: async (\n\t\truntime: any,\n\t\tmessage: any,\n\t\tstate?: any,\n\t\toptions?: any,\n\t): Promise<boolean> => {\n\t\tconst __avTextRaw =\n\t\t\ttypeof message?.content?.text === \"string\" ? message.content.text : \"\";\n\t\tconst __avText = __avTextRaw.toLowerCase();\n\t\tconst __avKeywords = [\"server\", \"info\"];\n\t\tconst __avKeywordOk =\n\t\t\t__avKeywords.length > 0 &&\n\t\t\t__avKeywords.some((word) => word.length > 0 && __avText.includes(word));\n\t\tconst __avRegex = /\\b(?:server|info)\\b/i;\n\t\tconst __avRegexOk = __avRegex.test(__avText);\n\t\tconst __avSource = String(\n\t\t\tmessage?.content?.source ?? message?.source ?? \"\",\n\t\t);\n\t\tconst __avExpectedSource = \"\";\n\t\tconst __avSourceOk = __avExpectedSource\n\t\t\t? __avSource === __avExpectedSource\n\t\t\t: Boolean(\n\t\t\t\t\t__avSource ||\n\t\t\t\t\t\tstate ||\n\t\t\t\t\t\truntime?.agentId ||\n\t\t\t\t\t\truntime?.getService ||\n\t\t\t\t\t\truntime?.getSetting,\n\t\t\t\t);\n\t\tconst __avOptions = options && typeof options === \"object\" ? options : {};\n\t\tconst __avInputOk =\n\t\t\t__avText.trim().length > 0 ||\n\t\t\tObject.keys(__avOptions as Record<string, unknown>).length > 0 ||\n\t\t\tBoolean(message?.content && typeof message.content === \"object\");\n\n\t\tif (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst __avLegacyValidate = async (\n\t\t\t_runtime: IAgentRuntime,\n\t\t\tmessage: Memory,\n\t\t\t_state?: State,\n\t\t): Promise<boolean> => {\n\t\t\treturn message.content.source === \"discord\";\n\t\t};\n\t\ttry {\n\t\t\treturn Boolean(\n\t\t\t\tawait (__avLegacyValidate as any)(runtime, message, state, options),\n\t\t\t);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t},\n\thandler: async (\n\t\truntime: IAgentRuntime,\n\t\tmessage: Memory,\n\t\tstate?: State,\n\t\t_options?: HandlerOptions,\n\t\tcallback?: HandlerCallback,\n\t): Promise<ActionResult | undefined> => {\n\t\tconst discordService = runtime.getService(\n\t\t\tDISCORD_SERVICE_NAME,\n\t\t) as DiscordService;\n\n\t\tif (!discordService || !discordService.client) {\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"Discord service is not available.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { success: false, error: \"Discord service is not available\" };\n\t\t}\n\n\t\tif (!state) {\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"State is not available.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { success: false, error: \"State is not available\" };\n\t\t}\n\n\t\ttry {\n\t\t\tconst stateData = state.data;\n\t\t\tconst room = stateData?.room || (await runtime.getRoom(message.roomId));\n\t\t\tconst serverId = room?.messageServerId;\n\t\t\tif (!serverId) {\n\t\t\t\tif (callback) {\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\ttext: \"I couldn't determine the current server.\",\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn { success: false, error: \"Could not determine current server\" };\n\t\t\t}\n\n\t\t\tconst guild = await discordService.client.guilds.fetch(serverId);\n\n\t\t\t// Check if the request is for detailed info\n\t\t\tconst messageContentText = message.content.text;\n\t\t\tconst messageText = messageContentText?.toLowerCase() || \"\";\n\t\t\tconst isDetailed =\n\t\t\t\tmessageText.includes(\"detailed\") ||\n\t\t\t\tmessageText.includes(\"full\") ||\n\t\t\t\tmessageText.includes(\"stats\") ||\n\t\t\t\tmessageText.includes(\"statistics\");\n\n\t\t\tconst infoText = formatServerInfo(guild, isDetailed);\n\n\t\t\tconst response: Content = {\n\t\t\t\ttext: infoText,\n\t\t\t\tsource: message.content.source,\n\t\t\t};\n\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.(response);\n\t\t\t}\n\t\t\treturn { success: true, text: response.text };\n\t\t} catch (error) {\n\t\t\truntime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:server-info\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error getting server info\",\n\t\t\t);\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I encountered an error while getting server information. Please try again.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t};\n\t\t}\n\t},\n\texamples: (spec.examples ?? []) as ActionExample[][],\n};\n\nexport default serverInfo;\n",
|
|
105
|
+
"import fs from \"node:fs\";\nimport {\n\ttype Action,\n\ttype ActionExample,\n\ttype ActionResult,\n\ttype Content,\n\tContentType,\n\tcomposePromptFromState,\n\tgetEntityDetails,\n\ttype HandlerCallback,\n\ttype HandlerOptions,\n\ttype IAgentRuntime,\n\tlogger,\n\ttype Media,\n\ttype Memory,\n\tMemoryType,\n\tModelType,\n\tparseJSONObjectFromText,\n\ttype State,\n\tsplitChunks,\n\ttrimTokens,\n} from \"@elizaos/core\";\nimport { requireActionSpec } from \"../generated/specs/spec-helpers\";\n\n/**\n * Normalizes a numeric timestamp to milliseconds.\n * Detects whether the input is likely in seconds or milliseconds based on magnitude.\n *\n * Heuristic: Unix timestamps in seconds are ~10 digits (e.g., 1703001600 for 2023)\n * Unix timestamps in milliseconds are ~13 digits (e.g., 1703001600000 for 2023)\n * We use a threshold: if the number represents a date before year 2000 when interpreted\n * as milliseconds, it's likely in seconds and needs conversion.\n *\n * @param {number} timestamp - The numeric timestamp to normalize\n * @returns {number} Timestamp in milliseconds\n */\nfunction normalizeTimestamp(timestamp: number): number {\n\t// Threshold: Jan 1, 2000 in milliseconds = 946684800000\n\t// If timestamp is less than this, it's likely in seconds (or an invalid/ancient date)\n\t// A Unix timestamp in seconds for year 2000+ would be > 946684800 (~10 digits)\n\t// which when treated as ms would be < Jan 12, 1970\n\tconst year2000InMs = 946684800000;\n\n\tif (timestamp > 0 && timestamp < year2000InMs) {\n\t\t// Likely in seconds - convert to milliseconds\n\t\t// Additional sanity check: result should be a reasonable date (after 2000, before 2100)\n\t\tconst asMs = timestamp * 1000;\n\t\tconst year2100InMs = 4102444800000;\n\t\tif (asMs >= year2000InMs && asMs <= year2100InMs) {\n\t\t\treturn asMs;\n\t\t}\n\t}\n\n\treturn timestamp;\n}\n\n/**\n * Parses various time formats into a Unix timestamp (milliseconds).\n * Supports:\n * - Absolute timestamps (number or numeric string): 1234567890000 or 1234567890 (auto-detects seconds vs ms)\n * - Relative time strings: \"5 minutes ago\", \"2 hours ago\", \"3 days ago\"\n * - ISO date strings: \"2024-01-15T10:30:00Z\"\n *\n * Month and year calculations use approximate values (30/365 days) to ensure inclusive time ranges.\n *\n * @param {string | number} input - The time value to parse\n * @returns {number} Unix timestamp in milliseconds\n */\nfunction parseTimeToTimestamp(input: string | number): number {\n\t// If already a number, normalize and return\n\tif (typeof input === \"number\") {\n\t\treturn normalizeTimestamp(input);\n\t}\n\n\t// Try parsing as a direct numeric string (timestamp)\n\tconst asNumber = Number(input);\n\tif (!Number.isNaN(asNumber) && asNumber > 0) {\n\t\treturn normalizeTimestamp(asNumber);\n\t}\n\n\t// Try parsing as ISO date\n\tconst isoDate = Date.parse(input);\n\tif (!Number.isNaN(isoDate)) {\n\t\treturn isoDate;\n\t}\n\n\t// Parse relative time format: \"<number> <unit> ago\", e.g. \"5 minutes ago\", \"2 hours ago\"\n\tconst relativeMatch = input.match(\n\t\t/(\\d+\\.?\\d*)\\s*(second|minute|hour|day|week|month|year)s?\\s+ago/i,\n\t);\n\tif (relativeMatch) {\n\t\tconst value = parseFloat(relativeMatch[1]);\n\t\tconst unit = relativeMatch[2].toLowerCase();\n\n\t\t// Approximate multipliers for time units\n\t\t// Month = 30 days, Year = 365 days (no leap year handling)\n\t\t// This provides consistent, inclusive time ranges for conversation retrieval\n\t\tconst multipliers: Record<string, number> = {\n\t\t\tsecond: 1000,\n\t\t\tminute: 60 * 1000,\n\t\t\thour: 3600 * 1000,\n\t\t\tday: 86400 * 1000,\n\t\t\tweek: 7 * 86400 * 1000,\n\t\t\tmonth: 30 * 86400 * 1000, // Approximation: actual months vary 28-31 days\n\t\t\tyear: 365 * 86400 * 1000, // Approximation: ignores leap years\n\t\t};\n\n\t\tconst milliseconds = value * (multipliers[unit] || 0);\n\n\t\t// \"<number> <unit> ago\" means subtract from now\n\t\treturn Date.now() - milliseconds;\n\t}\n\n\t// Fallback: return current time if we can't parse\n\t// Log warning for malformed model output\n\tlogger.warn(\n\t\t`[parseTimeToTimestamp] Could not parse time value, using current time: ${input}`,\n\t);\n\treturn Date.now();\n}\n\n// Import generated prompts\nimport {\n\tdateRangeTemplate,\n\tsummarizationTemplate,\n} from \"../generated/prompts/typescript/prompts.js\";\n\n/**\n * Function to get a date range from user input.\n *\n * @param {IAgentRuntime} runtime - The Agent Runtime object.\n * @param {Memory} _message - The Memory object.\n * @param {State} state - The State object.\n * @return {Promise<{ objective: string; start: number; end: number; } | null>} Parsed user input containing objective, start, and end timestamps, or null.\n */\nconst getDateRange = async (\n\truntime: IAgentRuntime,\n\t_message: Memory,\n\tstate: State,\n): Promise<{ objective: string; start: number; end: number } | null> => {\n\tconst prompt = composePromptFromState({\n\t\tstate,\n\t\ttemplate: dateRangeTemplate,\n\t});\n\n\tfor (let i = 0; i < 5; i++) {\n\t\tconst response = await runtime.useModel(ModelType.TEXT_SMALL, {\n\t\t\tprompt,\n\t\t});\n\n\t\t// try parsing to a json object\n\t\tconst parsedResponse = parseJSONObjectFromText(response) as {\n\t\t\tobjective: string;\n\t\t\tstart: string | number;\n\t\t\tend: string | number;\n\t\t} | null;\n\t\t// see if it contains objective, start and end\n\t\tif (parsedResponse) {\n\t\t\tif (\n\t\t\t\tparsedResponse.objective &&\n\t\t\t\tparsedResponse.start &&\n\t\t\t\tparsedResponse.end\n\t\t\t) {\n\t\t\t\t// Parse start and end into proper timestamps (returns numbers)\n\t\t\t\tconst startRaw = parseTimeToTimestamp(parsedResponse.start);\n\t\t\t\tconst endRaw = parseTimeToTimestamp(parsedResponse.end);\n\n\t\t\t\t// Validate that both timestamps are finite numbers\n\t\t\t\tif (!Number.isFinite(startRaw) || !Number.isFinite(endRaw)) {\n\t\t\t\t\tlogger.warn(\n\t\t\t\t\t\t`[getDateRange] Invalid timestamps parsed: start=${startRaw}, end=${endRaw}, retrying...`,\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Normalize: ensure start <= end (swap if model returned them inverted)\n\t\t\t\tlet start = startRaw <= endRaw ? startRaw : endRaw;\n\t\t\t\tconst end = startRaw <= endRaw ? endRaw : startRaw;\n\n\t\t\t\t// If start === end, widen the window by 1 hour to avoid empty queries\n\t\t\t\tif (start === end) {\n\t\t\t\t\tstart = end - 3600 * 1000; // 1 hour before end\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tobjective: parsedResponse.objective,\n\t\t\t\t\tstart,\n\t\t\t\t\tend,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\treturn null;\n};\n\n/**\n * Action to summarize a conversation and attachments.\n *\n * @typedef {Action} summarizeAction\n * @property {string} name - The name of the action.\n * @property {string[]} similes - Array of related terms.\n * @property {string} description - Description of the action.\n * @property {Function} validate - Asynchronous function to validate the action.\n * @property {Function} handler - Asynchronous function to handle the action.\n * @property {ActionExample[][]} examples - Array of examples demonstrating the action.\n */\nconst spec = requireActionSpec(\"SUMMARIZE_CONVERSATION\");\n\nexport const summarize: Action = {\n\tname: spec.name,\n\tsimiles: spec.similes ? [...spec.similes] : [],\n\tdescription: spec.description,\n\tvalidate: async (\n\t\truntime: any,\n\t\tmessage: any,\n\t\tstate?: any,\n\t\toptions?: any,\n\t): Promise<boolean> => {\n\t\tconst __avTextRaw =\n\t\t\ttypeof message?.content?.text === \"string\" ? message.content.text : \"\";\n\t\tconst __avText = __avTextRaw.toLowerCase();\n\t\tconst __avKeywords = [\"summarize\", \"conversation\"];\n\t\tconst __avKeywordOk =\n\t\t\t__avKeywords.length > 0 &&\n\t\t\t__avKeywords.some((word) => word.length > 0 && __avText.includes(word));\n\t\tconst __avRegex = /\\b(?:summarize|conversation)\\b/i;\n\t\tconst __avRegexOk = __avRegex.test(__avText);\n\t\tconst __avSource = String(\n\t\t\tmessage?.content?.source ?? message?.source ?? \"\",\n\t\t);\n\t\tconst __avExpectedSource = \"\";\n\t\tconst __avSourceOk = __avExpectedSource\n\t\t\t? __avSource === __avExpectedSource\n\t\t\t: Boolean(\n\t\t\t\t\t__avSource ||\n\t\t\t\t\t\tstate ||\n\t\t\t\t\t\truntime?.agentId ||\n\t\t\t\t\t\truntime?.getService ||\n\t\t\t\t\t\truntime?.getSetting,\n\t\t\t\t);\n\t\tconst __avOptions = options && typeof options === \"object\" ? options : {};\n\t\tconst __avInputOk =\n\t\t\t__avText.trim().length > 0 ||\n\t\t\tObject.keys(__avOptions as Record<string, unknown>).length > 0 ||\n\t\t\tBoolean(message?.content && typeof message.content === \"object\");\n\n\t\tif (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst __avLegacyValidate = async (\n\t\t\t_runtime: IAgentRuntime,\n\t\t\tmessage: Memory,\n\t\t\t_state?: State,\n\t\t): Promise<boolean> => {\n\t\t\tif (message.content.source !== \"discord\") {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// only show if one of the keywords are in the message\n\t\t\tconst keywords: string[] = [\n\t\t\t\t\"summarize\",\n\t\t\t\t\"summarization\",\n\t\t\t\t\"summary\",\n\t\t\t\t\"recap\",\n\t\t\t\t\"report\",\n\t\t\t\t\"overview\",\n\t\t\t\t\"review\",\n\t\t\t\t\"rundown\",\n\t\t\t\t\"wrap-up\",\n\t\t\t\t\"brief\",\n\t\t\t\t\"debrief\",\n\t\t\t\t\"abstract\",\n\t\t\t\t\"synopsis\",\n\t\t\t\t\"outline\",\n\t\t\t\t\"digest\",\n\t\t\t\t\"abridgment\",\n\t\t\t\t\"condensation\",\n\t\t\t\t\"encapsulation\",\n\t\t\t\t\"essence\",\n\t\t\t\t\"gist\",\n\t\t\t\t\"main points\",\n\t\t\t\t\"key points\",\n\t\t\t\t\"key takeaways\",\n\t\t\t\t\"bulletpoint\",\n\t\t\t\t\"highlights\",\n\t\t\t\t\"tldr\",\n\t\t\t\t\"tl;dr\",\n\t\t\t\t\"in a nutshell\",\n\t\t\t\t\"bottom line\",\n\t\t\t\t\"long story short\",\n\t\t\t\t\"sum up\",\n\t\t\t\t\"sum it up\",\n\t\t\t\t\"short version\",\n\t\t\t\t\"bring me up to speed\",\n\t\t\t\t\"catch me up\",\n\t\t\t];\n\t\t\treturn keywords.some((keyword) =>\n\t\t\t\tmessage.content.text?.toLowerCase().includes(keyword.toLowerCase()),\n\t\t\t);\n\t\t};\n\t\ttry {\n\t\t\treturn Boolean(\n\t\t\t\tawait (__avLegacyValidate as any)(runtime, message, state, options),\n\t\t\t);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t},\n\thandler: async (\n\t\truntime: IAgentRuntime,\n\t\tmessage: Memory,\n\t\tstate?: State,\n\t\t_options?: HandlerOptions,\n\t\tcallback?: HandlerCallback,\n\t): Promise<ActionResult | undefined> => {\n\t\tif (!state) {\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"State is not available.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { success: false, error: \"State is not available\" };\n\t\t}\n\n\t\tconst callbackData: Content = {\n\t\t\ttext: \"\", // fill in later\n\t\t\tactions: [\"SUMMARIZATION_RESPONSE\"],\n\t\t\tsource: message.content.source,\n\t\t\tattachments: [],\n\t\t};\n\t\tconst { roomId } = message;\n\n\t\t// 1. extract date range from the message\n\t\tconst dateRange = await getDateRange(runtime, message, state);\n\t\tif (!dateRange) {\n\t\t\truntime.logger.warn(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:summarize-conversation\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t},\n\t\t\t\t\"Could not get date range from message\",\n\t\t\t);\n\t\t\tawait runtime.createMemory(\n\t\t\t\t{\n\t\t\t\t\tentityId: message.entityId,\n\t\t\t\t\tagentId: message.agentId,\n\t\t\t\t\troomId: message.roomId,\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\tthought: \"I couldn't get the date range from the message\",\n\t\t\t\t\t\tactions: [\"SUMMARIZE_CONVERSATION_FAILED\"],\n\t\t\t\t\t},\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\ttype: MemoryType.CUSTOM,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t\"messages\",\n\t\t\t);\n\t\t\treturn { success: false, error: \"Could not get date range from message\" };\n\t\t}\n\n\t\tconst { objective, start, end } = dateRange;\n\n\t\t// 2. get these memories from the database (start/end are absolute ms timestamps)\n\t\tconst memories = await runtime.getMemories({\n\t\t\ttableName: \"messages\",\n\t\t\troomId,\n\t\t\tstart,\n\t\t\tend,\n\t\t\tcount: 10000,\n\t\t\tunique: false,\n\t\t});\n\n\t\tconst entities = (await getEntityDetails({\n\t\t\truntime: runtime as IAgentRuntime,\n\t\t\troomId,\n\t\t})) as Array<{ id: string; name?: string; names: string[] }>;\n\n\t\tconst actorMap = new Map(entities.map((entity) => [entity.id, entity]));\n\n\t\tconst formattedMemories = memories\n\t\t\t.map((memory) => {\n\t\t\t\tconst memoryAttachments = memory.content.attachments;\n\t\t\t\tconst attachments =\n\t\t\t\t\tmemoryAttachments\n\t\t\t\t\t\t?.map((attachment: Media) => {\n\t\t\t\t\t\t\treturn `---\\nAttachment: ${attachment.id}\\n${attachment.description}\\n${attachment.text}\\n---`;\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.join(\"\\n\") || \"\";\n\t\t\t\tconst entity = actorMap.get(memory.entityId);\n\t\t\t\tconst entityName = entity?.name ?? entity?.names?.[0] ?? \"Unknown User\";\n\t\t\t\tconst entityUsername = \"\";\n\t\t\t\treturn `${entityName} (${entityUsername}): ${memory.content.text}\\n${attachments}`;\n\t\t\t})\n\t\t\t.join(\"\\n\");\n\n\t\tlet currentSummary = \"\";\n\n\t\tconst chunkSize = 8000;\n\n\t\tconst chunks = await splitChunks(formattedMemories, chunkSize, 0);\n\n\t\t//const _datestr = new Date().toUTCString().replace(/:/g, \"-\");\n\n\t\tstate.values.memoriesWithAttachments = formattedMemories;\n\t\tstate.values.objective = objective;\n\n\t\tfor (let i = 0; i < chunks.length; i++) {\n\t\t\tconst chunk = chunks[i];\n\t\t\tstate.values.currentSummary = currentSummary;\n\t\t\tstate.values.currentChunk = chunk;\n\t\t\tconst template = await trimTokens(\n\t\t\t\tsummarizationTemplate,\n\t\t\t\tchunkSize + 500,\n\t\t\t\truntime,\n\t\t\t);\n\t\t\tconst prompt = composePromptFromState({\n\t\t\t\tstate,\n\t\t\t\t// make sure it fits, we can pad the tokens a bit\n\t\t\t\ttemplate,\n\t\t\t});\n\n\t\t\tconst summary = await runtime.useModel(ModelType.TEXT_SMALL, {\n\t\t\t\tprompt,\n\t\t\t});\n\n\t\t\tcurrentSummary = `${currentSummary}\\n${summary}`;\n\t\t}\n\n\t\tif (!currentSummary) {\n\t\t\truntime.logger.warn(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:summarize-conversation\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t},\n\t\t\t\t\"No summary found\",\n\t\t\t);\n\t\t\tawait runtime.createMemory(\n\t\t\t\t{\n\t\t\t\t\tentityId: message.entityId,\n\t\t\t\t\tagentId: message.agentId,\n\t\t\t\t\troomId: message.roomId,\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\tthought: \"I couldn't summarize the conversation\",\n\t\t\t\t\t\tactions: [\"SUMMARIZE_CONVERSATION_FAILED\"],\n\t\t\t\t\t},\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\ttype: MemoryType.CUSTOM,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t\"messages\",\n\t\t\t);\n\t\t\treturn { success: false, error: \"Could not summarize conversation\" };\n\t\t}\n\n\t\tcallbackData.text = currentSummary.trim();\n\t\tconst trimmedSummary = currentSummary.trim();\n\t\tif (\n\t\t\tcallbackData.text &&\n\t\t\t((trimmedSummary && trimmedSummary.split(\"\\n\").length < 4) ||\n\t\t\t\t(trimmedSummary && trimmedSummary.split(\" \").length < 100))\n\t\t) {\n\t\t\tcallbackData.text = `Here is the summary:\n\\`\\`\\`md\n${currentSummary.trim()}\n\\`\\`\\`\n`;\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.(callbackData);\n\t\t\t}\n\t\t\treturn { success: true, text: callbackData.text };\n\t\t} else if (currentSummary.trim()) {\n\t\t\tconst summaryDir = \"cache\";\n\t\t\tconst summaryFilename = `${summaryDir}/conversation_summary_${Date.now()}`;\n\t\t\tawait runtime.setCache<string>(summaryFilename, currentSummary);\n\t\t\tawait fs.promises.mkdir(summaryDir, { recursive: true });\n\n\t\t\tawait fs.promises.writeFile(summaryFilename, currentSummary, \"utf8\");\n\t\t\t// save the summary to a file\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\t...callbackData,\n\t\t\t\t\ttext: `I've attached the summary of the conversation from \\`${new Date(start).toString()}\\` to \\`${new Date(end).toString()}\\` as a text file.`,\n\t\t\t\t\tattachments: [\n\t\t\t\t\t\t...(callbackData.attachments || []),\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tid: summaryFilename,\n\t\t\t\t\t\t\turl: summaryFilename,\n\t\t\t\t\t\t\ttitle: \"Conversation Summary\",\n\t\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\t\tcontentType: ContentType.DOCUMENT,\n\t\t\t\t\t\t} as Media,\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { success: true, text: `Summary saved to ${summaryFilename}` };\n\t\t} else {\n\t\t\truntime.logger.warn(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:summarize-conversation\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t},\n\t\t\t\t\"Empty response from summarize conversation action\",\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: \"Empty response from summarize conversation action\",\n\t\t\t};\n\t\t}\n\t},\n\texamples: (spec.examples ?? []) as ActionExample[][],\n};\n\nexport default summarize;\n",
|
|
106
|
+
"import {\n\ttype Action,\n\ttype ActionExample,\n\ttype ActionResult,\n\ttype Content,\n\tContentType,\n\tcomposePromptFromState,\n\ttype HandlerCallback,\n\ttype HandlerOptions,\n\ttype IAgentRuntime,\n\ttype Media,\n\ttype Memory,\n\tMemoryType,\n\tModelType,\n\tparseJSONObjectFromText,\n\ttype State,\n} from \"@elizaos/core\";\nimport { mediaAttachmentIdTemplate } from \"../generated/prompts/typescript/prompts.js\";\nimport { requireActionSpec } from \"../generated/specs/spec-helpers\";\n\n/**\n * Asynchronous function to get the media attachment ID from the user input.\n *\n * @param {IAgentRuntime} runtime - The agent runtime object.\n * @param {Memory} _message - The memory object.\n * @param {State} state - The current state of the conversation.\n * @returns {Promise<string | null>} A promise that resolves with the media attachment ID or null.\n */\nconst getMediaAttachmentId = async (\n\truntime: IAgentRuntime,\n\t_message: Memory,\n\tstate: State,\n): Promise<string | null> => {\n\tconst prompt = composePromptFromState({\n\t\tstate,\n\t\ttemplate: mediaAttachmentIdTemplate,\n\t});\n\n\tfor (let i = 0; i < 5; i++) {\n\t\tconst response = await runtime.useModel(ModelType.TEXT_SMALL, {\n\t\t\tprompt,\n\t\t});\n\n\t\tconst parsedResponse = parseJSONObjectFromText(response) as {\n\t\t\tattachmentId: string;\n\t\t} | null;\n\n\t\tif (parsedResponse?.attachmentId) {\n\t\t\treturn parsedResponse.attachmentId;\n\t\t}\n\t}\n\treturn null;\n};\n\n/**\n * Action for transcribing the full text of an audio or video file that the user has attached.\n *\n * @typedef {Object} Action\n * @property {string} name - The name of the action.\n * @property {string[]} similes - Similes associated with the action.\n * @property {string} description - Description of the action.\n * @property {Function} validate - Validation function for the action.\n * @property {Function} handler - Handler function for the action.\n * @property {ActionExample[][]} examples - Examples demonstrating the action.\n */\nconst spec = requireActionSpec(\"TRANSCRIBE_MEDIA\");\n\nexport const transcribeMedia: Action = {\n\tname: spec.name,\n\tsimiles: spec.similes ? [...spec.similes] : [],\n\tdescription: spec.description,\n\tvalidate: async (\n\t\truntime: any,\n\t\tmessage: any,\n\t\tstate?: any,\n\t\toptions?: any,\n\t): Promise<boolean> => {\n\t\tconst __avTextRaw =\n\t\t\ttypeof message?.content?.text === \"string\" ? message.content.text : \"\";\n\t\tconst __avText = __avTextRaw.toLowerCase();\n\t\tconst __avKeywords = [\"transcribe\", \"media\"];\n\t\tconst __avKeywordOk =\n\t\t\t__avKeywords.length > 0 &&\n\t\t\t__avKeywords.some((word) => word.length > 0 && __avText.includes(word));\n\t\tconst __avRegex = /\\b(?:transcribe|media)\\b/i;\n\t\tconst __avRegexOk = __avRegex.test(__avText);\n\t\tconst __avSource = String(\n\t\t\tmessage?.content?.source ?? message?.source ?? \"\",\n\t\t);\n\t\tconst __avExpectedSource = \"\";\n\t\tconst __avSourceOk = __avExpectedSource\n\t\t\t? __avSource === __avExpectedSource\n\t\t\t: Boolean(\n\t\t\t\t\t__avSource ||\n\t\t\t\t\t\tstate ||\n\t\t\t\t\t\truntime?.agentId ||\n\t\t\t\t\t\truntime?.getService ||\n\t\t\t\t\t\truntime?.getSetting,\n\t\t\t\t);\n\t\tconst __avOptions = options && typeof options === \"object\" ? options : {};\n\t\tconst __avInputOk =\n\t\t\t__avText.trim().length > 0 ||\n\t\t\tObject.keys(__avOptions as Record<string, unknown>).length > 0 ||\n\t\t\tBoolean(message?.content && typeof message.content === \"object\");\n\n\t\tif (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst __avLegacyValidate = async (\n\t\t\t_runtime: IAgentRuntime,\n\t\t\tmessage: Memory,\n\t\t\t_state?: State,\n\t\t): Promise<boolean> => {\n\t\t\tif (message.content.source !== \"discord\") {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tconst keywords: string[] = [\n\t\t\t\t\"transcribe\",\n\t\t\t\t\"transcript\",\n\t\t\t\t\"audio\",\n\t\t\t\t\"video\",\n\t\t\t\t\"media\",\n\t\t\t\t\"youtube\",\n\t\t\t\t\"meeting\",\n\t\t\t\t\"recording\",\n\t\t\t\t\"podcast\",\n\t\t\t\t\"call\",\n\t\t\t\t\"conference\",\n\t\t\t\t\"interview\",\n\t\t\t\t\"speech\",\n\t\t\t\t\"lecture\",\n\t\t\t\t\"presentation\",\n\t\t\t];\n\t\t\treturn keywords.some((keyword) =>\n\t\t\t\tmessage.content.text?.toLowerCase().includes(keyword.toLowerCase()),\n\t\t\t);\n\t\t};\n\t\ttry {\n\t\t\treturn Boolean(\n\t\t\t\tawait (__avLegacyValidate as any)(runtime, message, state, options),\n\t\t\t);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t},\n\thandler: async (\n\t\truntime: IAgentRuntime,\n\t\tmessage: Memory,\n\t\tstate?: State,\n\t\t_options?: HandlerOptions,\n\t\tcallback?: HandlerCallback,\n\t): Promise<ActionResult | undefined> => {\n\t\tconst callbackData: Content = {\n\t\t\ttext: \"\", // fill in later\n\t\t\tactions: [\"TRANSCRIBE_MEDIA_RESPONSE\"],\n\t\t\tsource: message.content.source,\n\t\t\tattachments: [],\n\t\t};\n\n\t\tconst attachmentId = await getMediaAttachmentId(runtime, message, state);\n\t\tif (!attachmentId) {\n\t\t\truntime.logger.warn(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:transcribe-media\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t},\n\t\t\t\t\"Could not get media attachment ID from message\",\n\t\t\t);\n\t\t\tawait runtime.createMemory(\n\t\t\t\t{\n\t\t\t\t\tentityId: message.entityId,\n\t\t\t\t\tagentId: message.agentId,\n\t\t\t\t\troomId: message.roomId,\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\tthought: \"I couldn't find the media attachment ID in the message\",\n\t\t\t\t\t\tactions: [\"TRANSCRIBE_MEDIA_FAILED\"],\n\t\t\t\t\t},\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\ttype: MemoryType.CUSTOM,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t\"messages\",\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tconst conversationLength = runtime.getConversationLength();\n\n\t\tconst recentMessages = await runtime.getMemories({\n\t\t\ttableName: \"messages\",\n\t\t\troomId: message.roomId,\n\t\t\tcount: conversationLength,\n\t\t\tunique: false,\n\t\t});\n\n\t\tconst attachment = recentMessages\n\t\t\t.filter(\n\t\t\t\t(msg) => msg.content.attachments && msg.content.attachments.length > 0,\n\t\t\t)\n\t\t\t.flatMap((msg) => msg.content.attachments)\n\t\t\t.find(\n\t\t\t\t(attachment) =>\n\t\t\t\t\tattachment &&\n\t\t\t\t\tattachment.id.toLowerCase() === attachmentId.toLowerCase(),\n\t\t\t);\n\n\t\tif (!attachment) {\n\t\t\truntime.logger.warn(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:transcribe-media\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\tattachmentId,\n\t\t\t\t},\n\t\t\t\t\"Could not find attachment\",\n\t\t\t);\n\t\t\tawait runtime.createMemory(\n\t\t\t\t{\n\t\t\t\t\tentityId: message.entityId,\n\t\t\t\t\tagentId: message.agentId,\n\t\t\t\t\troomId: message.roomId,\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\tthought: `I couldn't find the media attachment with ID ${attachmentId}`,\n\t\t\t\t\t\tactions: [\"TRANSCRIBE_MEDIA_FAILED\"],\n\t\t\t\t\t},\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\ttype: MemoryType.CUSTOM,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t\"messages\",\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tconst mediaTranscript = attachment.text;\n\n\t\tcallbackData.text = mediaTranscript?.trim();\n\n\t\t// if callbackData.text is < 4 lines or < 100 words, then we we callback with normal message wrapped in markdown block\n\t\tif (\n\t\t\tcallbackData.text &&\n\t\t\t(callbackData.text.split(\"\\n\").length < 4 ||\n\t\t\t\tcallbackData.text.split(\" \").length < 100)\n\t\t) {\n\t\t\tcallbackData.text = `Here is the transcript:\n\\`\\`\\`md\n${mediaTranscript?.trim() || \"\"}\n\\`\\`\\`\n`;\n\t\t\tawait callback?.(callbackData);\n\t\t}\n\t\t// if text is big, let's send as an attachment\n\t\telse if (callbackData.text) {\n\t\t\tconst transcriptFilename = `content/transcript_${Date.now()}`;\n\n\t\t\t// save the transcript to a file\n\t\t\tawait runtime.setCache<string>(transcriptFilename, callbackData.text);\n\n\t\t\tawait callback?.({\n\t\t\t\t...callbackData,\n\t\t\t\ttext: \"I've attached the transcript as a text file.\",\n\t\t\t\tattachments: [\n\t\t\t\t\t...(callbackData.attachments || []),\n\t\t\t\t\t{\n\t\t\t\t\t\tid: transcriptFilename,\n\t\t\t\t\t\turl: transcriptFilename,\n\t\t\t\t\t\ttitle: \"Transcript\",\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\tcontentType: ContentType.DOCUMENT,\n\t\t\t\t\t} as Media,\n\t\t\t\t],\n\t\t\t});\n\t\t} else {\n\t\t\truntime.logger.warn(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:transcribe-media\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t},\n\t\t\t\t\"Empty response from transcribe media action\",\n\t\t\t);\n\t\t}\n\n\t\treturn { success: true, text: callbackData.text };\n\t},\n\texamples: (spec.examples ?? []) as ActionExample[][],\n};\n\nexport default transcribeMedia;\n",
|
|
107
|
+
"import {\n\ttype Action,\n\ttype ActionExample,\n\ttype ActionResult,\n\ttype Content,\n\tcomposePromptFromState,\n\ttype HandlerCallback,\n\ttype HandlerOptions,\n\ttype IAgentRuntime,\n\ttype Memory,\n\tModelType,\n\tparseJSONObjectFromText,\n\ttype State,\n} from \"@elizaos/core\";\nimport {\n\ttype Message,\n\tPermissionsBitField,\n\ttype TextChannel,\n} from \"discord.js\";\nimport { DISCORD_SERVICE_NAME } from \"../constants\";\nimport { unpinMessageTemplate } from \"../generated/prompts/typescript/prompts.js\";\nimport { requireActionSpec } from \"../generated/specs/spec-helpers\";\nimport type { DiscordService } from \"../service\";\n\nconst getMessageRef = async (\n\truntime: IAgentRuntime,\n\t_message: Memory,\n\tstate: State,\n): Promise<{\n\tmessageRef: string;\n} | null> => {\n\tconst prompt = composePromptFromState({\n\t\tstate,\n\t\ttemplate: unpinMessageTemplate,\n\t});\n\n\tfor (let i = 0; i < 3; i++) {\n\t\tconst response = await runtime.useModel(ModelType.TEXT_SMALL, {\n\t\t\tprompt,\n\t\t});\n\n\t\tconst parsedResponse = parseJSONObjectFromText(response);\n\t\tif (parsedResponse?.messageRef) {\n\t\t\treturn {\n\t\t\t\tmessageRef: String(parsedResponse.messageRef),\n\t\t\t};\n\t\t}\n\t}\n\treturn null;\n};\n\nconst spec = requireActionSpec(\"UNPIN_MESSAGE\");\n\nexport const unpinMessage: Action = {\n\tname: spec.name,\n\tsimiles: spec.similes ? [...spec.similes] : [],\n\tdescription: spec.description,\n\tvalidate: async (\n\t\truntime: any,\n\t\tmessage: any,\n\t\tstate?: any,\n\t\toptions?: any,\n\t): Promise<boolean> => {\n\t\tconst __avTextRaw =\n\t\t\ttypeof message?.content?.text === \"string\" ? message.content.text : \"\";\n\t\tconst __avText = __avTextRaw.toLowerCase();\n\t\tconst __avKeywords = [\"unpin\", \"message\"];\n\t\tconst __avKeywordOk =\n\t\t\t__avKeywords.length > 0 &&\n\t\t\t__avKeywords.some((word) => word.length > 0 && __avText.includes(word));\n\t\tconst __avRegex = /\\b(?:unpin|message)\\b/i;\n\t\tconst __avRegexOk = __avRegex.test(__avText);\n\t\tconst __avSource = String(\n\t\t\tmessage?.content?.source ?? message?.source ?? \"\",\n\t\t);\n\t\tconst __avExpectedSource = \"\";\n\t\tconst __avSourceOk = __avExpectedSource\n\t\t\t? __avSource === __avExpectedSource\n\t\t\t: Boolean(\n\t\t\t\t\t__avSource ||\n\t\t\t\t\t\tstate ||\n\t\t\t\t\t\truntime?.agentId ||\n\t\t\t\t\t\truntime?.getService ||\n\t\t\t\t\t\truntime?.getSetting,\n\t\t\t\t);\n\t\tconst __avOptions = options && typeof options === \"object\" ? options : {};\n\t\tconst __avInputOk =\n\t\t\t__avText.trim().length > 0 ||\n\t\t\tObject.keys(__avOptions as Record<string, unknown>).length > 0 ||\n\t\t\tBoolean(message?.content && typeof message.content === \"object\");\n\n\t\tif (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst __avLegacyValidate = async (\n\t\t\t_runtime: IAgentRuntime,\n\t\t\tmessage: Memory,\n\t\t\t_state?: State,\n\t\t): Promise<boolean> => {\n\t\t\treturn message.content.source === \"discord\";\n\t\t};\n\t\ttry {\n\t\t\treturn Boolean(\n\t\t\t\tawait (__avLegacyValidate as any)(runtime, message, state, options),\n\t\t\t);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t},\n\thandler: async (\n\t\truntime: IAgentRuntime,\n\t\tmessage: Memory,\n\t\tstate?: State,\n\t\t_options?: HandlerOptions,\n\t\tcallback?: HandlerCallback,\n\t): Promise<ActionResult | undefined> => {\n\t\tconst discordService = runtime.getService(\n\t\t\tDISCORD_SERVICE_NAME,\n\t\t) as DiscordService;\n\n\t\tif (!discordService || !discordService.client) {\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"Discord service is not available.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { success: false, error: \"Discord service is not available\" };\n\t\t}\n\n\t\tif (!state) {\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"State is not available.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { success: false, error: \"State is not available\" };\n\t\t}\n\n\t\tconst messageInfo = await getMessageRef(runtime, message, state);\n\t\tif (!messageInfo) {\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I couldn't understand which message you want to unpin. Please be more specific.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { success: false, error: \"Could not parse message reference\" };\n\t\t}\n\n\t\ttry {\n\t\t\tconst room = state.data?.room || (await runtime.getRoom(message.roomId));\n\t\t\tif (!room?.channelId) {\n\t\t\t\tif (callback) {\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\ttext: \"I couldn't determine the current channel.\",\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn { success: false, error: \"Could not determine current channel\" };\n\t\t\t}\n\n\t\t\tconst channel = await discordService.client.channels.fetch(\n\t\t\t\troom.channelId,\n\t\t\t);\n\t\t\tif (!channel || !channel.isTextBased()) {\n\t\t\t\tif (callback) {\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\ttext: \"I can only unpin messages in text channels.\",\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn { success: false, error: \"Channel is not a text channel\" };\n\t\t\t}\n\n\t\t\tconst textChannel = channel as TextChannel;\n\n\t\t\t// Check bot permissions\n\t\t\tconst clientUser = discordService.client.user;\n\t\t\tconst botMember = textChannel.guild?.members.cache.get(clientUser?.id);\n\t\t\tif (botMember) {\n\t\t\t\tconst permissions = textChannel.permissionsFor(botMember);\n\t\t\t\tif (\n\t\t\t\t\tpermissions &&\n\t\t\t\t\t!permissions.has(PermissionsBitField.Flags.ManageMessages)\n\t\t\t\t) {\n\t\t\t\t\tif (callback) {\n\t\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\t\ttext: \"I don't have permission to unpin messages in this channel. I need the 'Manage Messages' permission.\",\n\t\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn { success: false, error: \"Missing ManageMessages permission\" };\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet targetMessage: Message | null = null;\n\n\t\t\t// Get pinned messages\n\t\t\tconst pinnedMessages = await textChannel.messages.fetchPinned();\n\n\t\t\tif (pinnedMessages.size === 0) {\n\t\t\t\tif (callback) {\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\ttext: \"There are no pinned messages in this channel.\",\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn { success: true, text: \"No pinned messages in channel\" };\n\t\t\t}\n\n\t\t\t// Find the target message\n\t\t\tif (\n\t\t\t\tmessageInfo.messageRef === \"last_pinned\" ||\n\t\t\t\tmessageInfo.messageRef === \"last\"\n\t\t\t) {\n\t\t\t\t// Get the most recently created pinned message (since we can't sort by pin time)\n\t\t\t\ttargetMessage = Array.from(pinnedMessages.values()).sort(\n\t\t\t\t\t(a, b) => b.createdTimestamp - a.createdTimestamp,\n\t\t\t\t)[0];\n\t\t\t} else if (/^\\d+$/.test(messageInfo.messageRef)) {\n\t\t\t\t// It's a message ID\n\t\t\t\ttargetMessage = pinnedMessages.get(messageInfo.messageRef) || null;\n\t\t\t} else {\n\t\t\t\t// Search for message by content/author in pinned messages\n\t\t\t\tconst searchLower = messageInfo.messageRef.toLowerCase();\n\n\t\t\t\ttargetMessage =\n\t\t\t\t\tArray.from(pinnedMessages.values()).find((msg) => {\n\t\t\t\t\t\tconst contentMatch = msg.content\n\t\t\t\t\t\t\t.toLowerCase()\n\t\t\t\t\t\t\t.includes(searchLower);\n\t\t\t\t\t\tconst authorMatch = msg.author.username\n\t\t\t\t\t\t\t.toLowerCase()\n\t\t\t\t\t\t\t.includes(searchLower);\n\t\t\t\t\t\treturn contentMatch || authorMatch;\n\t\t\t\t\t}) || null;\n\t\t\t}\n\n\t\t\tif (!targetMessage) {\n\t\t\t\tif (callback) {\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\ttext: \"I couldn't find a pinned message matching your description.\",\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: \"Could not find matching pinned message\",\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Unpin the message\n\t\t\ttry {\n\t\t\t\tawait targetMessage.unpin();\n\n\t\t\t\tconst response: Content = {\n\t\t\t\t\ttext: `I've unpinned the message from ${targetMessage.author.username}.`,\n\t\t\t\t\tsource: message.content.source,\n\t\t\t\t};\n\n\t\t\t\tif (callback) {\n\t\t\t\t\tawait callback?.(response);\n\t\t\t\t}\n\t\t\t\treturn { success: true, text: response.text };\n\t\t\t} catch (error) {\n\t\t\t\truntime.logger.error(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord:action:unpin-message\",\n\t\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t},\n\t\t\t\t\t\"Failed to unpin message\",\n\t\t\t\t);\n\t\t\t\tif (callback) {\n\t\t\t\t\tawait callback?.({\n\t\t\t\t\t\ttext: \"I couldn't unpin that message. Please try again.\",\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t};\n\t\t\t}\n\t\t} catch (error) {\n\t\t\truntime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:action:unpin-message\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error unpinning message\",\n\t\t\t);\n\t\t\tif (callback) {\n\t\t\t\tawait callback?.({\n\t\t\t\t\ttext: \"I encountered an error while trying to unpin the message. Please make sure I have the necessary permissions.\",\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t};\n\t\t}\n\t},\n\texamples: (spec.examples ?? []) as ActionExample[][],\n};\n\nexport default unpinMessage;\n",
|
|
108
|
+
"const Permissions = {\n\tAddReactions: 1n << 6n,\n\tPrioritySpeaker: 1n << 8n,\n\tStream: 1n << 9n,\n\tViewChannel: 1n << 10n,\n\tSendMessages: 1n << 11n,\n\tSendTTSMessages: 1n << 12n,\n\tManageMessages: 1n << 13n,\n\tEmbedLinks: 1n << 14n,\n\tAttachFiles: 1n << 15n,\n\tReadMessageHistory: 1n << 16n,\n\tMentionEveryone: 1n << 17n,\n\tUseExternalEmojis: 1n << 18n,\n\tConnect: 1n << 20n,\n\tSpeak: 1n << 21n,\n\tMuteMembers: 1n << 22n,\n\tDeafenMembers: 1n << 23n,\n\tMoveMembers: 1n << 24n,\n\tUseVAD: 1n << 25n,\n\tKickMembers: 1n << 1n,\n\tBanMembers: 1n << 2n,\n\tChangeNickname: 1n << 26n,\n\tManageNicknames: 1n << 27n,\n\tManageChannels: 1n << 4n,\n\tManageRoles: 1n << 28n,\n\tManageWebhooks: 1n << 29n,\n\tManageGuildExpressions: 1n << 30n,\n\tUseApplicationCommands: 1n << 31n,\n\tManageThreads: 1n << 34n,\n\tCreatePublicThreads: 1n << 35n,\n\tCreatePrivateThreads: 1n << 36n,\n\tUseExternalStickers: 1n << 37n,\n\tSendMessagesInThreads: 1n << 38n,\n\tUseEmbeddedActivities: 1n << 39n,\n\tModerateMembers: 1n << 40n,\n\tSendVoiceMessages: 1n << 46n,\n\tSendPolls: 1n << 47n,\n} as const;\n\nconst TEXT_BASIC =\n\tPermissions.ViewChannel |\n\tPermissions.AddReactions |\n\tPermissions.SendMessages |\n\tPermissions.EmbedLinks |\n\tPermissions.AttachFiles |\n\tPermissions.UseExternalEmojis |\n\tPermissions.ReadMessageHistory |\n\tPermissions.SendMessagesInThreads |\n\tPermissions.UseApplicationCommands;\n\nconst TEXT_MODERATOR =\n\tTEXT_BASIC |\n\tPermissions.ManageMessages |\n\tPermissions.MentionEveryone |\n\tPermissions.CreatePublicThreads |\n\tPermissions.CreatePrivateThreads |\n\tPermissions.ManageThreads |\n\tPermissions.UseExternalStickers |\n\tPermissions.SendPolls |\n\tPermissions.ModerateMembers;\n\nconst TEXT_ADMIN =\n\tTEXT_MODERATOR |\n\tPermissions.KickMembers |\n\tPermissions.BanMembers |\n\tPermissions.ManageNicknames |\n\tPermissions.ManageChannels |\n\tPermissions.ManageRoles |\n\tPermissions.ManageWebhooks |\n\tPermissions.ManageGuildExpressions;\n\nconst VOICE_ADDON =\n\tPermissions.Connect |\n\tPermissions.Speak |\n\tPermissions.UseVAD |\n\tPermissions.PrioritySpeaker |\n\tPermissions.Stream |\n\tPermissions.SendVoiceMessages;\n\nconst VOICE_ADMIN_ADDON =\n\tVOICE_ADDON |\n\tPermissions.MuteMembers |\n\tPermissions.DeafenMembers |\n\tPermissions.MoveMembers;\n\nexport const PERMISSIONS_BASIC = TEXT_BASIC;\nexport const PERMISSIONS_BASIC_VOICE = TEXT_BASIC | VOICE_ADDON;\nexport const PERMISSIONS_MODERATOR = TEXT_MODERATOR;\nexport const PERMISSIONS_MODERATOR_VOICE = TEXT_MODERATOR | VOICE_ADDON;\nexport const PERMISSIONS_ADMIN = TEXT_ADMIN;\nexport const PERMISSIONS_ADMIN_VOICE = TEXT_ADMIN | VOICE_ADMIN_ADDON;\n\nexport const DiscordPermissionTiers = {\n\tBASIC: Number(PERMISSIONS_BASIC),\n\tBASIC_VOICE: Number(PERMISSIONS_BASIC_VOICE),\n\tMODERATOR: Number(PERMISSIONS_MODERATOR),\n\tMODERATOR_VOICE: Number(PERMISSIONS_MODERATOR_VOICE),\n\tADMIN: Number(PERMISSIONS_ADMIN),\n\tADMIN_VOICE: Number(PERMISSIONS_ADMIN_VOICE),\n} as const;\n\nexport type DiscordPermissionTier = keyof typeof DiscordPermissionTiers;\n\nexport function generateInviteUrl(\n\tapplicationId: string,\n\ttier: DiscordPermissionTier = \"MODERATOR_VOICE\",\n): string {\n\tconst permissions = DiscordPermissionTiers[tier];\n\treturn `https://discord.com/api/oauth2/authorize?client_id=${applicationId}&permissions=${permissions}&scope=bot%20applications.commands`;\n}\n\nexport interface DiscordPermissionValues {\n\tbasic: number;\n\tbasicVoice: number;\n\tmoderator: number;\n\tmoderatorVoice: number;\n\tadmin: number;\n\tadminVoice: number;\n}\n\nexport function getPermissionValues(): DiscordPermissionValues {\n\treturn {\n\t\tbasic: DiscordPermissionTiers.BASIC,\n\t\tbasicVoice: DiscordPermissionTiers.BASIC_VOICE,\n\t\tmoderator: DiscordPermissionTiers.MODERATOR,\n\t\tmoderatorVoice: DiscordPermissionTiers.MODERATOR_VOICE,\n\t\tadmin: DiscordPermissionTiers.ADMIN,\n\t\tadminVoice: DiscordPermissionTiers.ADMIN_VOICE,\n\t};\n}\n\nexport interface DiscordInviteUrls {\n\tbasic: string;\n\tbasicVoice: string;\n\tmoderator: string;\n\tmoderatorVoice: string;\n\tadmin: string;\n\tadminVoice: string;\n}\n\nexport function generateAllInviteUrls(\n\tapplicationId: string,\n): DiscordInviteUrls {\n\treturn {\n\t\tbasic: generateInviteUrl(applicationId, \"BASIC\"),\n\t\tbasicVoice: generateInviteUrl(applicationId, \"BASIC_VOICE\"),\n\t\tmoderator: generateInviteUrl(applicationId, \"MODERATOR\"),\n\t\tmoderatorVoice: generateInviteUrl(applicationId, \"MODERATOR_VOICE\"),\n\t\tadmin: generateInviteUrl(applicationId, \"ADMIN\"),\n\t\tadminVoice: generateInviteUrl(applicationId, \"ADMIN_VOICE\"),\n\t};\n}\n\nexport const REQUIRED_PERMISSIONS = PERMISSIONS_MODERATOR_VOICE;\n",
|
|
109
|
+
"/**\n * Discord Plugin Settings Banner\n * Beautiful ANSI art display for configuration on startup\n * Includes tiered permission system for invite URLs\n */\n\nimport type { IAgentRuntime } from \"@elizaos/core\";\nimport {\n\ttype DiscordPermissionValues,\n\tgetPermissionValues,\n} from \"./permissions\";\n\nconst ANSI = {\n\treset: \"\\x1b[0m\",\n\tbold: \"\\x1b[1m\",\n\tdim: \"\\x1b[2m\",\n\tblue: \"\\x1b[34m\",\n\tbrightRed: \"\\x1b[91m\",\n\tbrightGreen: \"\\x1b[92m\",\n\tbrightYellow: \"\\x1b[93m\",\n\tbrightBlue: \"\\x1b[94m\",\n\tbrightMagenta: \"\\x1b[95m\",\n\tbrightCyan: \"\\x1b[96m\",\n\tbrightWhite: \"\\x1b[97m\",\n};\n\nexport interface PluginSetting {\n\tname: string;\n\tvalue: unknown;\n\tdefaultValue?: unknown;\n\tsensitive?: boolean;\n\trequired?: boolean;\n}\n\nexport interface BannerOptions {\n\tpluginName: string;\n\tdescription?: string;\n\tsettings: PluginSetting[];\n\truntime: IAgentRuntime;\n\t/** Discord Application ID for generating invite URLs */\n\tapplicationId?: string;\n\t/** Permission values for the 3x2 tier matrix */\n\tdiscordPermissions?: DiscordPermissionValues;\n}\n\nfunction mask(v: string): string {\n\tif (!v || v.length <= 8) {\n\t\treturn \"••••••••\";\n\t}\n\treturn `${v.slice(0, 4)}${\"•\".repeat(Math.min(12, v.length - 8))}${v.slice(-4)}`;\n}\n\n/**\n * Format a value for display in the banner.\n *\n * @param value - The value to format; may be `undefined`, `null`, or an empty string.\n * @param sensitive - Whether the value should be obfuscated for display.\n * @param maxLen - Maximum allowed length of the returned string; longer values are truncated with an ellipsis.\n * @returns A display string: `'(not set)'` if `value` is `undefined`, `null`, or an empty string; a masked representation if `sensitive` is true; otherwise the stringified value truncated to at most `maxLen` characters (truncated strings end with `'...'`).\n */\nfunction fmtVal(value: unknown, sensitive: boolean, maxLen: number): string {\n\tlet s: string;\n\tif (value === undefined || value === null || value === \"\") {\n\t\ts = \"(not set)\";\n\t} else if (sensitive) {\n\t\ts = mask(String(value));\n\t} else {\n\t\ts = String(value);\n\t}\n\tif (s.length > maxLen) {\n\t\ts = `${s.slice(0, maxLen - 3)}...`;\n\t}\n\treturn s;\n}\n\n// biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escape codes are required for terminal formatting\nconst ANSI_PATTERN = /\\x1b\\[[0-9;]*m/g;\n\n/**\n * Pads a string with trailing spaces until its visible (ANSI-stripped) length is at least the given width.\n *\n * @param s - The input string which may contain ANSI escape sequences.\n * @param n - The target visible width (number of characters) after padding.\n * @returns The original string if its visible length is >= `n`, otherwise the string with trailing spaces appended so its visible length equals `n`.\n */\nfunction pad(s: string, n: number): string {\n\tconst len = s.replace(ANSI_PATTERN, \"\").length;\n\tif (len >= n) {\n\t\treturn s;\n\t}\n\treturn s + \" \".repeat(n - len);\n}\n\nfunction line(content: string): string {\n\tconst len = content.replace(ANSI_PATTERN, \"\").length;\n\n\tif (len <= 78) {\n\t\treturn content + \" \".repeat(78 - len);\n\t}\n\n\t// Truncate based on visible character count, not raw string position\n\t// This avoids cutting in the middle of ANSI escape sequences\n\tlet visibleCount = 0;\n\tlet result = \"\";\n\tlet i = 0;\n\n\twhile (i < content.length && visibleCount < 78) {\n\t\tconst remaining = content.slice(i);\n\t\t// biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escape codes are required for terminal formatting\n\t\tconst match = remaining.match(/^\\x1b\\[[0-9;]*m/);\n\n\t\tif (match) {\n\t\t\t// Include ANSI sequence without counting toward visible length\n\t\t\tresult += match[0];\n\t\t\ti += match[0].length;\n\t\t} else {\n\t\t\t// Regular visible character\n\t\t\tresult += content[i];\n\t\t\tvisibleCount++;\n\t\t\ti++;\n\t\t}\n\t}\n\n\t// Reset any unclosed ANSI sequences after truncation\n\treturn result + ANSI.reset;\n}\n\n/**\n * Render a framed ANSI banner that displays plugin settings and, when available, tiered Discord invite URLs.\n *\n * The banner lists each setting with masked or truncated values, a status (custom/default/unset/required),\n * and an optional Discord invite section generated from `applicationId` and `discordPermissions`.\n *\n * @param options - Configuration for the banner, including `settings`, the `runtime` used to emit the banner,\n * and optional Discord invite data (`applicationId`, `discordPermissions`).\n */\nexport function printBanner(options: BannerOptions): void {\n\tconst { settings, runtime } = options;\n\tconst R = ANSI.reset,\n\t\tD = ANSI.dim,\n\t\tB = ANSI.bold;\n\tconst c1 = ANSI.brightBlue,\n\t\tc2 = ANSI.brightCyan,\n\t\tc3 = ANSI.brightMagenta;\n\n\tconst top = `${c1}╔${\"═\".repeat(78)}╗${R}`;\n\tconst mid = `${c1}╠${\"═\".repeat(78)}╣${R}`;\n\tconst bot = `${c1}╚${\"═\".repeat(78)}╝${R}`;\n\tconst row = (s: string) => `${c1}║${R}${line(s)}${c1}║${R}`;\n\n\tconst lines: string[] = [\"\"];\n\tlines.push(top);\n\tlines.push(row(` ${B}Character: ${runtime.character.name}${R}`));\n\tlines.push(mid);\n\tlines.push(\n\t\trow(\n\t\t\t`${c2} ██████╗ ██╗███████╗ ██████╗ ██████╗ ██████╗ ██████╗ ${c3}◖ ◗${R}`,\n\t\t),\n\t);\n\tlines.push(\n\t\trow(\n\t\t\t`${c2} ██╔══██╗██║██╔════╝██╔════╝██╔═══██╗██╔══██╗██╔══██╗ ${c3}◖===◗${R}`,\n\t\t),\n\t);\n\tlines.push(\n\t\trow(\n\t\t\t`${c2} ██║ ██║██║███████╗██║ ██║ ██║██████╔╝██║ ██║ ${c3}╰─╯${R}`,\n\t\t),\n\t);\n\tlines.push(\n\t\trow(\n\t\t\t`${c2} ██████╔╝██║╚════██║╚██████╗╚██████╔╝██║ ██║██████╔╝ ${c3}(◠◠)${R}`,\n\t\t),\n\t);\n\tlines.push(\n\t\trow(\n\t\t\t`${c2} ╚═════╝ ╚═╝╚══════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═════╝ ${c3}‿‿${R}`,\n\t\t),\n\t);\n\tlines.push(\n\t\trow(\n\t\t\t`${D} Bot Integration • Servers • Channels • Voice${R}`,\n\t\t),\n\t);\n\tlines.push(mid);\n\n\tconst NW = 34,\n\t\tVW = 26,\n\t\tSW = 8;\n\tlines.push(\n\t\trow(\n\t\t\t` ${B}${pad(\"ENV VARIABLE\", NW)} ${pad(\"VALUE\", VW)} ${pad(\"STATUS\", SW)}${R}`,\n\t\t),\n\t);\n\tlines.push(\n\t\trow(` ${D}${\"-\".repeat(NW)} ${\"-\".repeat(VW)} ${\"-\".repeat(SW)}${R}`),\n\t);\n\n\tfor (const s of settings) {\n\t\tconst set = s.value !== undefined && s.value !== null && s.value !== \"\";\n\t\t// Normalize to string for comparison (e.g., boolean false vs string 'false')\n\t\tconst isDefault =\n\t\t\tset &&\n\t\t\ts.defaultValue !== undefined &&\n\t\t\tString(s.value) === String(s.defaultValue);\n\n\t\tlet ico: string, st: string;\n\t\tif (!set && s.required) {\n\t\t\tico = `${ANSI.brightRed}◆${R}`;\n\t\t\tst = `${ANSI.brightRed}REQUIRED${R}`;\n\t\t} else if (!set) {\n\t\t\tico = `${D}○${R}`;\n\t\t\tst = `${D}unset${R}`;\n\t\t} else if (isDefault) {\n\t\t\tico = `${ANSI.brightBlue}●${R}`;\n\t\t\tst = `${ANSI.brightBlue}default${R}`;\n\t\t} else {\n\t\t\tico = `${ANSI.brightGreen}✓${R}`;\n\t\t\tst = `${ANSI.brightGreen}custom${R}`;\n\t\t}\n\n\t\tconst name = pad(s.name, NW - 2);\n\t\tconst val = pad(\n\t\t\tfmtVal(s.value ?? s.defaultValue, s.sensitive ?? false, VW),\n\t\t\tVW,\n\t\t);\n\t\tconst status = pad(st, SW);\n\t\tlines.push(row(` ${ico} ${c2}${name}${R} ${val} ${status}`));\n\t}\n\n\tlines.push(mid);\n\tlines.push(\n\t\trow(\n\t\t\t` ${D}${ANSI.brightGreen}✓${D} custom ${ANSI.brightBlue}●${D} default ○ unset ${ANSI.brightRed}◆${D} required → Set in .env${R}`,\n\t\t),\n\t);\n\tlines.push(bot);\n\n\t// Add Discord invite links organized by voice capability\n\tif (options.applicationId && options.discordPermissions) {\n\t\tconst p = options.discordPermissions;\n\t\tconst baseUrl = `https://discord.com/api/oauth2/authorize?client_id=${options.applicationId}&scope=bot%20applications.commands&permissions=`;\n\n\t\tlines.push(\"\");\n\t\tlines.push(`${B}${ANSI.brightCyan}🔗 Discord Bot Invite${R}`);\n\t\tlines.push(\"\");\n\t\tlines.push(` ${B}🎙️ With Voice:${R}`);\n\t\tlines.push(\n\t\t\t` ${ANSI.brightGreen}● Basic${R} ${baseUrl}${p.basicVoice}`,\n\t\t);\n\t\tlines.push(\n\t\t\t` ${ANSI.brightYellow}● Moderator${R} ${baseUrl}${p.moderatorVoice}`,\n\t\t);\n\t\tlines.push(\n\t\t\t` ${ANSI.brightRed}● Admin${R} ${baseUrl}${p.adminVoice}`,\n\t\t);\n\t\tlines.push(\"\");\n\t\tlines.push(` ${B}💬 Without Voice:${R}`);\n\t\tlines.push(` ${ANSI.brightCyan}○ Basic${R} ${baseUrl}${p.basic}`);\n\t\tlines.push(\n\t\t\t` ${ANSI.brightMagenta}○ Moderator${R} ${baseUrl}${p.moderator}`,\n\t\t);\n\t\tlines.push(` ${ANSI.brightBlue}○ Admin${R} ${baseUrl}${p.admin}`);\n\t}\n\n\tlines.push(\"\");\n\n\truntime.logger.info(lines.join(\"\\n\"));\n}\n\n/**\n * Print the Discord plugin banner with current settings.\n */\nexport function printDiscordBanner(runtime: IAgentRuntime): void {\n\t// Get settings\n\tconst apiToken = runtime.getSetting(\"DISCORD_API_TOKEN\");\n\tconst applicationId = runtime.getSetting(\"DISCORD_APPLICATION_ID\");\n\tconst ignoreBots = runtime.getSetting(\"DISCORD_SHOULD_IGNORE_BOT_MESSAGES\");\n\tconst ignoreDMs = runtime.getSetting(\"DISCORD_SHOULD_IGNORE_DIRECT_MESSAGES\");\n\tconst onlyMentions = runtime.getSetting(\n\t\t\"DISCORD_SHOULD_RESPOND_ONLY_TO_MENTIONS\",\n\t);\n\tconst listenChannels = runtime.getSetting(\"DISCORD_LISTEN_CHANNEL_IDS\");\n\tconst voiceChannelId = runtime.getSetting(\"DISCORD_VOICE_CHANNEL_ID\");\n\n\tprintBanner({\n\t\tpluginName: \"plugin-discord\",\n\t\tdescription: \"Discord bot integration for servers and channels\",\n\t\tapplicationId: applicationId ? String(applicationId) : undefined,\n\t\tdiscordPermissions: applicationId ? getPermissionValues() : undefined,\n\t\tsettings: [\n\t\t\t{\n\t\t\t\tname: \"DISCORD_API_TOKEN\",\n\t\t\t\tvalue: apiToken,\n\t\t\t\tsensitive: true,\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\t{ name: \"DISCORD_APPLICATION_ID\", value: applicationId },\n\t\t\t{ name: \"DISCORD_VOICE_CHANNEL_ID\", value: voiceChannelId },\n\t\t\t{ name: \"DISCORD_LISTEN_CHANNEL_IDS\", value: listenChannels },\n\t\t\t{\n\t\t\t\tname: \"DISCORD_SHOULD_IGNORE_BOT_MESSAGES\",\n\t\t\t\tvalue: ignoreBots,\n\t\t\t\tdefaultValue: \"false\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"DISCORD_SHOULD_IGNORE_DIRECT_MESSAGES\",\n\t\t\t\tvalue: ignoreDMs,\n\t\t\t\tdefaultValue: \"false\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"DISCORD_SHOULD_RESPOND_ONLY_TO_MENTIONS\",\n\t\t\t\tvalue: onlyMentions,\n\t\t\t\tdefaultValue: \"false\",\n\t\t\t},\n\t\t],\n\t\truntime,\n\t});\n}\n",
|
|
110
|
+
"import type { IAgentRuntime, Memory, Provider, State } from \"@elizaos/core\";\nimport { ChannelType } from \"@elizaos/core\";\nimport type { GuildChannel } from \"discord.js\";\nimport { requireProviderSpec } from \"../generated/specs/spec-helpers\";\nimport type { DiscordService } from \"../service\";\nimport { ServiceType } from \"../types\";\n\nconst spec = requireProviderSpec(\"channelState\");\n\n/**\n * Represents a provider for retrieving channel state information.\n * @type {Provider}\n * @property {string} name - The name of the channel state provider.\n * @property {Function} get - Asynchronous function that retrieves channel state information based on the provided runtime, message, and optional state parameters.\n * @param {IAgentRuntime} runtime - The agent runtime.\n * @param {Memory} message - The message object.\n * @param {State} [state] - Optional state object.\n * @returns {Promise<Object>} A promise that resolves to an object containing channel state data, values, and text.\n */\nexport const channelStateProvider: Provider = {\n\tname: spec.name,\n\tdynamic: true,\n\tget: async (runtime: IAgentRuntime, message: Memory, state: State) => {\n\t\tconst room = state.data?.room ?? (await runtime.getRoom(message.roomId));\n\t\tif (!room) {\n\t\t\tthrow new Error(\"No room found\");\n\t\t}\n\n\t\t// if message source is not discord, return\n\t\tif (message.content.source !== \"discord\") {\n\t\t\treturn {\n\t\t\t\tdata: {},\n\t\t\t\tvalues: {},\n\t\t\t\ttext: \"\",\n\t\t\t};\n\t\t}\n\n\t\tconst agentName = state?.agentName || \"The agent\";\n\t\tconst senderName = state?.senderName || \"someone\";\n\n\t\tlet responseText = \"\";\n\t\tlet channelType = \"\";\n\t\tlet serverName = \"\";\n\t\tconst channelId = room.channelId ?? \"\";\n\n\t\tif (room.type === ChannelType.DM) {\n\t\t\tchannelType = \"DM\";\n\t\t\tresponseText = `${agentName} is currently in a direct message conversation with ${senderName}. ${agentName} should engage in conversation, should respond to messages that are addressed to them and only ignore messages that seem to not require a response.`;\n\t\t} else {\n\t\t\tchannelType = \"GROUP\";\n\n\t\t\tif (!channelId) {\n\t\t\t\truntime.logger.error(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord:provider:channelState\",\n\t\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\t\troomId: room.id,\n\t\t\t\t\t},\n\t\t\t\t\t\"No channel ID found\",\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tdata: {\n\t\t\t\t\t\troom,\n\t\t\t\t\t\tchannelType,\n\t\t\t\t\t},\n\t\t\t\t\tvalues: {\n\t\t\t\t\t\tchannelType,\n\t\t\t\t\t},\n\t\t\t\t\ttext: \"\",\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst discordService = runtime.getService(\n\t\t\t\tServiceType.DISCORD,\n\t\t\t) as DiscordService;\n\t\t\tif (!discordService) {\n\t\t\t\truntime.logger.warn(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord:provider:channelState\",\n\t\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\t\tchannelId,\n\t\t\t\t\t},\n\t\t\t\t\t\"No discord client found\",\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tdata: {\n\t\t\t\t\t\troom,\n\t\t\t\t\t\tchannelType,\n\t\t\t\t\t\tchannelId,\n\t\t\t\t\t},\n\t\t\t\t\tvalues: {\n\t\t\t\t\t\tchannelType,\n\t\t\t\t\t\tchannelId,\n\t\t\t\t\t},\n\t\t\t\t\ttext: \"\",\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Look up guild via channel instead of serverId (which is now a UUID)\n\t\t\t// Try cache first, then fetch if not cached (handles cold start / partial cache scenarios)\n\t\t\tlet channel = discordService.client?.channels.cache.get(channelId) as\n\t\t\t\t| GuildChannel\n\t\t\t\t| undefined;\n\t\t\tif (!channel && discordService.client) {\n\t\t\t\ttry {\n\t\t\t\t\tchannel = (await discordService.client.channels.fetch(channelId)) as\n\t\t\t\t\t\t| GuildChannel\n\t\t\t\t\t\t| undefined;\n\t\t\t\t} catch (fetchError) {\n\t\t\t\t\truntime.logger.debug(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord:provider:channelState\",\n\t\t\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\t\t\tchannelId,\n\t\t\t\t\t\t\terror:\n\t\t\t\t\t\t\t\tfetchError instanceof Error\n\t\t\t\t\t\t\t\t\t? fetchError.message\n\t\t\t\t\t\t\t\t\t: String(fetchError),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Failed to fetch channel\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst guild = channel?.guild;\n\t\t\tif (!guild) {\n\t\t\t\truntime.logger.warn(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord:provider:channelState\",\n\t\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\t\tchannelId,\n\t\t\t\t\t},\n\t\t\t\t\t\"Guild not found for channel (not in cache and fetch failed)\",\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tdata: {\n\t\t\t\t\t\troom,\n\t\t\t\t\t\tchannelType,\n\t\t\t\t\t\tchannelId,\n\t\t\t\t\t},\n\t\t\t\t\tvalues: {\n\t\t\t\t\t\tchannelType,\n\t\t\t\t\t\tchannelId,\n\t\t\t\t\t},\n\t\t\t\t\ttext: \"\",\n\t\t\t\t};\n\t\t\t}\n\t\t\tserverName = guild.name;\n\n\t\t\tresponseText = `${agentName} is currently having a conversation in the channel \\`#${channel?.name || channelId}\\` in the server \\`${serverName}\\``;\n\t\t\tresponseText += `\\n${agentName} is in a room with other users and should be self-conscious and only participate when directly addressed or when the conversation is relevant to them.`;\n\t\t}\n\n\t\treturn {\n\t\t\tdata: {\n\t\t\t\troom,\n\t\t\t\tchannelType,\n\t\t\t\tserverName,\n\t\t\t\tchannelId,\n\t\t\t},\n\t\t\tvalues: {\n\t\t\t\tchannelType,\n\t\t\t\tserverName,\n\t\t\t\tchannelId,\n\t\t\t},\n\t\t\ttext: responseText,\n\t\t};\n\t},\n};\n\nexport default channelStateProvider;\n",
|
|
111
|
+
"import type {\n\tChannelType,\n\tCharacter,\n\tEntityPayload,\n\tEventPayload,\n\tIAgentRuntime,\n\tMedia,\n\tMemory,\n\tMessagePayload,\n\tWorldPayload,\n} from \"@elizaos/core\";\nimport type {\n\tChannel,\n\tClient as DiscordJsClient,\n\tGuild,\n\tGuildMember,\n\tInteraction,\n\tMessage,\n\tMessageReaction,\n\tUser,\n\tVoiceState,\n} from \"discord.js\";\n\n/**\n * Discord-specific event types\n */\nexport enum DiscordEventTypes {\n\tMESSAGE_RECEIVED = \"DISCORD_MESSAGE_RECEIVED\",\n\tMESSAGE_SENT = \"DISCORD_MESSAGE_SENT\",\n\tSLASH_COMMAND = \"DISCORD_SLASH_COMMAND\",\n\tMODAL_SUBMIT = \"DISCORD_MODAL_SUBMIT\",\n\tREACTION_RECEIVED = \"DISCORD_REACTION_RECEIVED\",\n\tREACTION_REMOVED = \"DISCORD_REACTION_REMOVED\",\n\tWORLD_JOINED = \"DISCORD_WORLD_JOINED\",\n\tWORLD_CONNECTED = \"DISCORD_SERVER_CONNECTED\",\n\tENTITY_JOINED = \"DISCORD_USER_JOINED\",\n\tENTITY_LEFT = \"DISCORD_USER_LEFT\",\n\tVOICE_STATE_CHANGED = \"DISCORD_VOICE_STATE_CHANGED\",\n\tCHANNEL_PERMISSIONS_CHANGED = \"DISCORD_CHANNEL_PERMISSIONS_CHANGED\",\n\tROLE_PERMISSIONS_CHANGED = \"DISCORD_ROLE_PERMISSIONS_CHANGED\",\n\tMEMBER_ROLES_CHANGED = \"DISCORD_MEMBER_ROLES_CHANGED\",\n\tROLE_CREATED = \"DISCORD_ROLE_CREATED\",\n\tROLE_DELETED = \"DISCORD_ROLE_DELETED\",\n\tLISTEN_CHANNEL_MESSAGE = \"DISCORD_LISTEN_CHANNEL_MESSAGE\",\n\tNOT_IN_CHANNELS_MESSAGE = \"DISCORD_NOT_IN_CHANNELS_MESSAGE\",\n}\n\nexport interface DiscordMessageReceivedPayload extends MessagePayload {\n\toriginalMessage: Message;\n}\n\nexport interface DiscordMessageSentPayload extends MessagePayload {\n\toriginalMessages: Message[];\n}\n\nexport interface DiscordReactionPayload extends MessagePayload {\n\toriginalReaction: MessageReaction;\n\tuser: User;\n}\n\nexport interface DiscordServerPayload extends WorldPayload {\n\tserver: Guild;\n}\n\nexport interface DiscordUserJoinedPayload extends EntityPayload {\n\tmember: GuildMember;\n}\n\nexport interface DiscordUserLeftPayload extends EntityPayload {\n\tmember: GuildMember;\n}\n\nexport interface DiscordVoiceStateChangedPayload {\n\tvoiceState: VoiceState;\n}\n\nexport interface DiscordListenChannelPayload {\n\truntime: IAgentRuntime;\n\tmessage: Memory;\n\tsource: string;\n}\n\nexport interface DiscordNotInChannelsPayload {\n\truntime: IAgentRuntime;\n\tmessage: Message;\n\tsource: string;\n}\n\nexport type PermissionState = \"ALLOW\" | \"DENY\" | \"NEUTRAL\";\n\nexport interface PermissionDiff {\n\tpermission: string;\n\toldState: PermissionState;\n\tnewState: PermissionState;\n}\n\nexport interface AuditInfo {\n\texecutorId: string;\n\texecutorTag: string;\n\treason: string | null;\n}\n\nexport interface ChannelPermissionsChangedPayload extends EventPayload {\n\tguild: { id: string; name: string };\n\tchannel: { id: string; name: string };\n\ttarget: { type: \"role\" | \"user\"; id: string; name: string };\n\taction: \"CREATE\" | \"UPDATE\" | \"DELETE\";\n\tchanges: PermissionDiff[];\n\taudit: AuditInfo | null;\n}\n\nexport interface RolePermissionsChangedPayload extends EventPayload {\n\tguild: { id: string; name: string };\n\trole: { id: string; name: string };\n\tchanges: PermissionDiff[];\n\taudit: AuditInfo | null;\n}\n\nexport interface MemberRolesChangedPayload extends EventPayload {\n\tguild: { id: string; name: string };\n\tmember: { id: string; tag: string };\n\tadded: Array<{ id: string; name: string; permissions: string[] }>;\n\tremoved: Array<{ id: string; name: string; permissions: string[] }>;\n\taudit: AuditInfo | null;\n}\n\nexport interface RoleLifecyclePayload extends EventPayload {\n\tguild: { id: string; name: string };\n\trole: { id: string; name: string; permissions: string[] };\n\taudit: AuditInfo | null;\n}\n\nexport interface DiscordSlashCommand {\n\tname: string;\n\tdescription: string;\n\toptions?: Array<{\n\t\tname: string;\n\t\ttype: number;\n\t\tdescription: string;\n\t\trequired?: boolean;\n\t\tchannel_types?: number[];\n\t}>;\n\tguildOnly?: boolean;\n\tbypassChannelWhitelist?: boolean;\n\trequiredPermissions?: bigint | string | null;\n\tcontexts?: number[];\n\tguildIds?: string[];\n\tvalidator?: (\n\t\tinteraction: Interaction,\n\t\truntime: IAgentRuntime,\n\t) => Promise<boolean>;\n}\n\nexport interface DiscordRegisterCommandsPayload extends EventPayload {\n\tcommands: DiscordSlashCommand[];\n}\n\nexport interface DiscordSlashCommandPayload extends EventPayload {\n\tinteraction: Interaction;\n\tclient: DiscordJsClient;\n\tcommands: DiscordSlashCommand[];\n}\n\nexport interface DiscordEventPayloadMap {\n\t[DiscordEventTypes.MESSAGE_RECEIVED]: DiscordMessageReceivedPayload;\n\t[DiscordEventTypes.MESSAGE_SENT]: DiscordMessageSentPayload;\n\t[DiscordEventTypes.REACTION_RECEIVED]: DiscordReactionPayload;\n\t[DiscordEventTypes.REACTION_REMOVED]: DiscordReactionPayload;\n\t[DiscordEventTypes.WORLD_JOINED]: DiscordServerPayload;\n\t[DiscordEventTypes.WORLD_CONNECTED]: DiscordServerPayload;\n\t[DiscordEventTypes.ENTITY_JOINED]: DiscordUserJoinedPayload;\n\t[DiscordEventTypes.ENTITY_LEFT]: DiscordUserLeftPayload;\n\t[DiscordEventTypes.SLASH_COMMAND]: DiscordSlashCommandPayload;\n\t[DiscordEventTypes.MODAL_SUBMIT]: DiscordSlashCommandPayload;\n\t[DiscordEventTypes.VOICE_STATE_CHANGED]: DiscordVoiceStateChangedPayload;\n\t[DiscordEventTypes.CHANNEL_PERMISSIONS_CHANGED]: ChannelPermissionsChangedPayload;\n\t[DiscordEventTypes.ROLE_PERMISSIONS_CHANGED]: RolePermissionsChangedPayload;\n\t[DiscordEventTypes.MEMBER_ROLES_CHANGED]: MemberRolesChangedPayload;\n\t[DiscordEventTypes.ROLE_CREATED]: RoleLifecyclePayload;\n\t[DiscordEventTypes.ROLE_DELETED]: RoleLifecyclePayload;\n\t[DiscordEventTypes.LISTEN_CHANNEL_MESSAGE]: DiscordListenChannelPayload;\n\t[DiscordEventTypes.NOT_IN_CHANNELS_MESSAGE]: DiscordNotInChannelsPayload;\n}\n\nexport type JsonValue =\n\t| string\n\t| number\n\t| boolean\n\t| null\n\t| JsonValue[]\n\t| { [key: string]: JsonValue };\n\nexport type JsonObject = { [key: string]: JsonValue };\n\nexport interface BuildMemoryFromMessageOptions {\n\tprocessedContent?: string;\n\tprocessedAttachments?: Media[];\n\textraContent?: JsonObject;\n\textraMetadata?: JsonObject;\n}\n\nexport interface IDiscordService {\n\tclient: DiscordJsClient | null;\n\tcharacter: Character;\n\tgetChannelType: (channel: Channel) => Promise<ChannelType>;\n\tbuildMemoryFromMessage: (\n\t\tmessage: Message,\n\t\toptions?: BuildMemoryFromMessageOptions,\n\t) => Promise<Memory | null>;\n}\n\nexport const DISCORD_SERVICE_NAME = \"discord\";\n\nexport const ServiceType = {\n\tDISCORD: \"discord\",\n} as const;\n\nexport interface DiscordComponentOptions {\n\ttype: number;\n\tcustom_id: string;\n\tlabel?: string;\n\tstyle?: number;\n\tplaceholder?: string;\n\tmin_values?: number;\n\tmax_values?: number;\n\toptions?: Array<{\n\t\tlabel: string;\n\t\tvalue: string;\n\t\tdescription?: string;\n\t}>;\n}\n\nexport interface DiscordActionRow {\n\ttype: 1;\n\tcomponents: DiscordComponentOptions[];\n}\n\n/**\n * DM access policy for Discord messages.\n * - \"open\": Allow all DMs\n * - \"allowlist\": Only allow DMs from users in allowFrom list\n * - \"pairing\": Require pairing code approval for new DM senders\n * - \"disabled\": Ignore all DMs\n */\nexport type DiscordDmPolicy = \"open\" | \"allowlist\" | \"pairing\" | \"disabled\";\n\nexport interface DiscordSettings {\n\tallowedChannelIds?: string[];\n\tshouldIgnoreBotMessages?: boolean;\n\tshouldIgnoreDirectMessages?: boolean;\n\tshouldRespondOnlyToMentions?: boolean;\n\t/** DM access policy (default: \"open\") */\n\tdmPolicy?: DiscordDmPolicy;\n\t/** List of allowed Discord user IDs for allowlist policy */\n\tallowFrom?: string[];\n}\n\nexport interface ChannelSpiderState {\n\tchannelId: string;\n\toldestMessageId?: string;\n\tnewestMessageId?: string;\n\toldestMessageTimestamp?: number;\n\tnewestMessageTimestamp?: number;\n\tlastSpideredAt: number;\n\tfullyBackfilled: boolean;\n}\n\nexport type BatchHandler = (\n\tbatch: Memory[],\n\tstats: { page: number; totalFetched: number; totalStored: number },\n) => Promise<boolean | undefined> | boolean | undefined;\n\nexport interface ChannelHistoryOptions {\n\tlimit?: number;\n\tforce?: boolean;\n\tonBatch?: BatchHandler;\n\tbefore?: string;\n\tafter?: string;\n}\n\nexport interface ChannelHistoryResult {\n\tmessages: Memory[];\n\tstats: {\n\t\tfetched: number;\n\t\tstored: number;\n\t\tpages: number;\n\t\tfullyBackfilled: boolean;\n\t};\n}\n\nexport interface DiscordApiCommand {\n\tname: string;\n\tdescription: string;\n\toptions?: DiscordCommandOption[];\n\tdefault_member_permissions?: string | null;\n\tcontexts?: number[];\n}\n\nexport interface DiscordCommandOption {\n\tname: string;\n\ttype: number;\n\tdescription: string;\n\trequired?: boolean;\n\tchannel_types?: number[];\n}\n\nexport interface UserSelectionState {\n\t[key: string]: string | number | boolean | string[];\n}\n\nexport interface DiscordMessageSendOptions {\n\tcontent: string;\n\treply?: {\n\t\tmessageReference: string;\n\t};\n\tfiles?: Array<{ attachment: Buffer | string; name: string }>;\n\tcomponents?: DiscordActionRow[];\n}\n\nexport class DiscordPluginError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly code: string,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"DiscordPluginError\";\n\t}\n}\n\nexport class DiscordServiceNotInitializedError extends DiscordPluginError {\n\tconstructor() {\n\t\tsuper(\"Discord service is not initialized\", \"SERVICE_NOT_INITIALIZED\");\n\t\tthis.name = \"DiscordServiceNotInitializedError\";\n\t}\n}\n\nexport class DiscordClientNotAvailableError extends DiscordPluginError {\n\tconstructor() {\n\t\tsuper(\"Discord client is not available\", \"CLIENT_NOT_AVAILABLE\");\n\t\tthis.name = \"DiscordClientNotAvailableError\";\n\t}\n}\n\nexport class DiscordConfigurationError extends DiscordPluginError {\n\tconstructor(missingConfig: string) {\n\t\tsuper(`Missing required configuration: ${missingConfig}`, \"MISSING_CONFIG\");\n\t\tthis.name = \"DiscordConfigurationError\";\n\t}\n}\n\nexport class DiscordApiError extends DiscordPluginError {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly apiErrorCode?: number,\n\t) {\n\t\tsuper(message, \"API_ERROR\");\n\t\tthis.name = \"DiscordApiError\";\n\t}\n}\n\nexport type DiscordSnowflake = string & {\n\treadonly __brand: \"DiscordSnowflake\";\n};\n\nexport function validateSnowflake(id: string): DiscordSnowflake {\n\tif (!/^\\d{17,19}$/.test(id)) {\n\t\tthrow new DiscordPluginError(\n\t\t\t`Invalid Discord snowflake ID: ${id}`,\n\t\t\t\"INVALID_SNOWFLAKE\",\n\t\t);\n\t}\n\treturn id as DiscordSnowflake;\n}\n\nexport function isValidSnowflake(id: string): id is DiscordSnowflake {\n\treturn /^\\d{17,19}$/.test(id);\n}\n",
|
|
112
|
+
"import type { IAgentRuntime, Memory, Provider, State } from \"@elizaos/core\";\nimport type { Guild, GuildChannel, Role } from \"discord.js\";\nimport { requireProviderSpec } from \"../generated/specs/spec-helpers\";\nimport type { DiscordService } from \"../service\";\nimport { ServiceType } from \"../types\";\n\nconst spec = requireProviderSpec(\"guildInfo\");\n\n/**\n * Represents a provider for retrieving guild/server information.\n * @type {Provider}\n * @property {string} name - The name of the guild info provider.\n * @property {Function} get - Asynchronous function that retrieves guild information\n * based on the provided runtime, message, and optional state parameters.\n * @param {IAgentRuntime} runtime - The agent runtime.\n * @param {Memory} message - The message object.\n * @param {State} [state] - Optional state object.\n * @returns {Promise<Object>} A promise that resolves to an object containing guild data, values, and text.\n */\nexport const guildInfoProvider: Provider = {\n\tname: spec.name,\n\tdynamic: true,\n\tget: async (runtime: IAgentRuntime, message: Memory, state: State) => {\n\t\t// If message source is not discord, return empty\n\t\tif (message.content.source !== \"discord\") {\n\t\t\treturn {\n\t\t\t\tdata: {},\n\t\t\t\tvalues: {},\n\t\t\t\ttext: \"\",\n\t\t\t};\n\t\t}\n\n\t\tconst room = state.data?.room ?? (await runtime.getRoom(message.roomId));\n\t\tif (!room) {\n\t\t\treturn {\n\t\t\t\tdata: { isInGuild: false },\n\t\t\t\tvalues: { isInGuild: false },\n\t\t\t\ttext: \"\",\n\t\t\t};\n\t\t}\n\n\t\tconst channelId = room.channelId ?? \"\";\n\t\tif (!channelId) {\n\t\t\treturn {\n\t\t\t\tdata: { isInGuild: false },\n\t\t\t\tvalues: { isInGuild: false },\n\t\t\t\ttext: \"\",\n\t\t\t};\n\t\t}\n\n\t\tconst discordService = runtime.getService(\n\t\t\tServiceType.DISCORD,\n\t\t) as DiscordService;\n\t\tif (!discordService?.client) {\n\t\t\truntime.logger.warn(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:provider:guildInfo\",\n\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\tchannelId,\n\t\t\t\t},\n\t\t\t\t\"No discord client found\",\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tdata: { isInGuild: false },\n\t\t\t\tvalues: { isInGuild: false },\n\t\t\t\ttext: \"\",\n\t\t\t};\n\t\t}\n\n\t\t// Try to get the channel to find the guild\n\t\tlet channel = discordService.client.channels.cache.get(channelId) as\n\t\t\t| GuildChannel\n\t\t\t| undefined;\n\t\tif (!channel) {\n\t\t\ttry {\n\t\t\t\tchannel = (await discordService.client.channels.fetch(channelId)) as\n\t\t\t\t\t| GuildChannel\n\t\t\t\t\t| undefined;\n\t\t\t} catch (fetchError) {\n\t\t\t\truntime.logger.debug(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord:provider:guildInfo\",\n\t\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\t\tchannelId,\n\t\t\t\t\t\terror:\n\t\t\t\t\t\t\tfetchError instanceof Error\n\t\t\t\t\t\t\t\t? fetchError.message\n\t\t\t\t\t\t\t\t: String(fetchError),\n\t\t\t\t\t},\n\t\t\t\t\t\"Failed to fetch channel\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst guild = channel?.guild;\n\t\tif (!guild) {\n\t\t\treturn {\n\t\t\t\tdata: { isInGuild: false, channelId },\n\t\t\t\tvalues: { isInGuild: false },\n\t\t\t\ttext: \"\",\n\t\t\t};\n\t\t}\n\n\t\t// Fetch guild info\n\t\tconst guildInfo = await getGuildInfo(guild, discordService);\n\n\t\tconst responseText = formatGuildInfoText(guild, guildInfo);\n\n\t\treturn {\n\t\t\tdata: {\n\t\t\t\tisInGuild: true,\n\t\t\t\tguildId: guild.id,\n\t\t\t\tguild: guildInfo,\n\t\t\t},\n\t\t\tvalues: {\n\t\t\t\tisInGuild: true,\n\t\t\t\tguildId: guild.id,\n\t\t\t\tguildName: guild.name,\n\t\t\t\tmemberCount: guildInfo.memberCount,\n\t\t\t\tchannelCount: guildInfo.channelCount,\n\t\t\t},\n\t\t\ttext: responseText,\n\t\t};\n\t},\n};\n\ninterface GuildInfo {\n\tname: string;\n\tmemberCount: number;\n\tchannelCount: number;\n\troleCount: number;\n\townerId: string;\n\townerName: string;\n\tdescription: string | null;\n\tcreatedAt: string;\n\tpremiumTier: number;\n\tpremiumSubscriptionCount: number;\n\tchannels: {\n\t\ttext: Array<{ id: string; name: string }>;\n\t\tvoice: Array<{ id: string; name: string }>;\n\t\tcategories: Array<{ id: string; name: string }>;\n\t};\n\troles: Array<{ id: string; name: string; color: string }>;\n\tbotPermissions: {\n\t\tadministrator: boolean;\n\t\tmanageMessages: boolean;\n\t\tmanageChannels: boolean;\n\t\tmanageRoles: boolean;\n\t};\n}\n\nasync function getGuildInfo(\n\tguild: Guild,\n\tdiscordService: DiscordService,\n): Promise<GuildInfo> {\n\t// Get owner\n\tlet ownerName = \"Unknown\";\n\ttry {\n\t\tconst owner = await guild.fetchOwner();\n\t\townerName = owner.user.username;\n\t} catch (_e) {\n\t\t// Ignore\n\t}\n\n\t// Get bot member for permissions\n\tconst botMember = discordService.client?.user?.id\n\t\t? guild.members.cache.get(discordService.client.user.id)\n\t\t: undefined;\n\n\tconst botPermissions = {\n\t\tadministrator: botMember?.permissions.has(\"Administrator\") ?? false,\n\t\tmanageMessages: botMember?.permissions.has(\"ManageMessages\") ?? false,\n\t\tmanageChannels: botMember?.permissions.has(\"ManageChannels\") ?? false,\n\t\tmanageRoles: botMember?.permissions.has(\"ManageRoles\") ?? false,\n\t};\n\n\t// Categorize channels\n\tconst textChannels: Array<{ id: string; name: string }> = [];\n\tconst voiceChannels: Array<{ id: string; name: string }> = [];\n\tconst categories: Array<{ id: string; name: string }> = [];\n\n\tguild.channels.cache.forEach((channel) => {\n\t\tconst channelData = { id: channel.id, name: channel.name };\n\t\tif (channel.type === 0) {\n\t\t\t// GUILD_TEXT\n\t\t\ttextChannels.push(channelData);\n\t\t} else if (channel.type === 2) {\n\t\t\t// GUILD_VOICE\n\t\t\tvoiceChannels.push(channelData);\n\t\t} else if (channel.type === 4) {\n\t\t\t// GUILD_CATEGORY\n\t\t\tcategories.push(channelData);\n\t\t}\n\t});\n\n\t// Get roles (exclude @everyone)\n\tconst roles = guild.roles.cache\n\t\t.filter((role: Role) => role.name !== \"@everyone\")\n\t\t.map((role: Role) => ({\n\t\t\tid: role.id,\n\t\t\tname: role.name,\n\t\t\tcolor: role.hexColor,\n\t\t}));\n\n\treturn {\n\t\tname: guild.name,\n\t\tmemberCount: guild.memberCount,\n\t\tchannelCount: guild.channels.cache.size,\n\t\troleCount: guild.roles.cache.size,\n\t\townerId: guild.ownerId,\n\t\townerName,\n\t\tdescription: guild.description,\n\t\tcreatedAt: guild.createdAt.toISOString(),\n\t\tpremiumTier: guild.premiumTier,\n\t\tpremiumSubscriptionCount: guild.premiumSubscriptionCount ?? 0,\n\t\tchannels: {\n\t\t\ttext: textChannels,\n\t\t\tvoice: voiceChannels,\n\t\t\tcategories,\n\t\t},\n\t\troles: Array.from(roles),\n\t\tbotPermissions,\n\t};\n}\n\nfunction formatGuildInfoText(guild: Guild, info: GuildInfo): string {\n\tconst lines = [\n\t\t`The current server is \"${guild.name}\" with ${info.memberCount} members.`,\n\t\t`The server was created on ${new Date(info.createdAt).toLocaleDateString()}.`,\n\t];\n\n\tif (info.description) {\n\t\tlines.push(`Server description: ${info.description}`);\n\t}\n\n\tlines.push(\n\t\t`The server has ${info.channels.text.length} text channels, ${info.channels.voice.length} voice channels, and ${info.roleCount} roles.`,\n\t);\n\n\tif (info.premiumTier > 0) {\n\t\tlines.push(\n\t\t\t`The server is boosted to tier ${info.premiumTier} with ${info.premiumSubscriptionCount} boosts.`,\n\t\t);\n\t}\n\n\treturn lines.join(\" \");\n}\n\nexport default guildInfoProvider;\n",
|
|
113
|
+
"import { getVoiceConnection } from \"@discordjs/voice\";\nimport type {\n\tIAgentRuntime,\n\tMemory,\n\tProvider,\n\tProviderResult,\n\tState,\n\tUUID,\n} from \"@elizaos/core\";\nimport { ChannelType } from \"@elizaos/core\";\nimport type { GuildChannel } from \"discord.js\";\nimport { requireProviderSpec } from \"../generated/specs/spec-helpers\";\nimport type { DiscordService } from \"../service\";\nimport { ServiceType } from \"../types\";\n\nconst spec = requireProviderSpec(\"voiceState\");\n\n/**\n * Provides information about the voice state of the user, including whether they are currently in a voice channel.\n *\n * @param {IAgentRuntime} runtime - The runtime object for the agent\n * @param {Memory} message - The message object containing room ID\n * @param {State} [state] - Optional state object for the user\n * @returns {Object} An object containing information about the voice state of the user\n */\nexport const voiceStateProvider: Provider = {\n\tname: spec.name,\n\tdynamic: true,\n\tget: async (runtime: IAgentRuntime, message: Memory, state?: State) => {\n\t\t// Voice doesn't get a discord message, so we need to use the channel for guild data\n\t\tconst room = await runtime.getRoom(message.roomId);\n\t\tif (!room) {\n\t\t\tthrow new Error(\"No room found\");\n\t\t}\n\n\t\tif (room.type !== ChannelType.GROUP) {\n\t\t\t// only handle in a group scenario for now\n\t\t\treturn {\n\t\t\t\tdata: {\n\t\t\t\t\tisInVoiceChannel: false,\n\t\t\t\t\troomId: room.id,\n\t\t\t\t},\n\t\t\t\tvalues: {\n\t\t\t\t\tisInVoiceChannel: \"false\",\n\t\t\t\t\troomType: room.type,\n\t\t\t\t},\n\t\t\t\ttext: \"\",\n\t\t\t} as ProviderResult;\n\t\t}\n\n\t\tconst channelId = room.channelId;\n\t\tconst agentName = state?.agentName || \"The agent\";\n\n\t\tif (!channelId) {\n\t\t\truntime.logger.warn(\n\t\t\t\t{ src: \"plugin:discord:provider:voiceState\", roomId: room.id },\n\t\t\t\t\"No channel ID found\",\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tdata: {\n\t\t\t\t\tisInVoiceChannel: false,\n\t\t\t\t\troomId: room.id,\n\t\t\t\t},\n\t\t\t\tvalues: {\n\t\t\t\t\tisInVoiceChannel: \"false\",\n\t\t\t\t\troomType: room.type,\n\t\t\t\t},\n\t\t\t\ttext: `${agentName} is not currently in a voice channel`,\n\t\t\t} as ProviderResult;\n\t\t}\n\n\t\t// Look up guild via channel to get the Discord guild ID for voice connection\n\t\tconst discordService = runtime.getService(\n\t\t\tServiceType.DISCORD,\n\t\t) as DiscordService;\n\t\tif (!discordService || !discordService.client) {\n\t\t\truntime.logger.warn(\n\t\t\t\t{ src: \"plugin:discord:provider:voiceState\" },\n\t\t\t\t\"Discord service not available\",\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tdata: {\n\t\t\t\t\tisInVoiceChannel: false,\n\t\t\t\t\troomId: room.id,\n\t\t\t\t},\n\t\t\t\tvalues: {\n\t\t\t\t\tisInVoiceChannel: \"false\",\n\t\t\t\t},\n\t\t\t\ttext: `${agentName} is not currently in a voice channel`,\n\t\t\t} as ProviderResult;\n\t\t}\n\n\t\t// Try cache first, then fetch if not cached (handles cold start / partial cache scenarios)\n\t\tlet channel = discordService.client.channels.cache.get(channelId) as\n\t\t\t| GuildChannel\n\t\t\t| undefined;\n\t\tif (!channel) {\n\t\t\ttry {\n\t\t\t\tchannel = (await discordService.client.channels.fetch(channelId)) as\n\t\t\t\t\t| GuildChannel\n\t\t\t\t\t| undefined;\n\t\t\t} catch (fetchError) {\n\t\t\t\truntime.logger.debug(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord:provider:voiceState\",\n\t\t\t\t\t\tchannelId,\n\t\t\t\t\t\terror:\n\t\t\t\t\t\t\tfetchError instanceof Error\n\t\t\t\t\t\t\t\t? fetchError.message\n\t\t\t\t\t\t\t\t: String(fetchError),\n\t\t\t\t\t},\n\t\t\t\t\t\"Failed to fetch channel\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tconst guildId = channel?.guild?.id;\n\n\t\tif (!guildId) {\n\t\t\truntime.logger.warn(\n\t\t\t\t{ src: \"plugin:discord:provider:voiceState\", channelId },\n\t\t\t\t\"Could not find guild for channel (not in cache and fetch failed)\",\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tdata: {\n\t\t\t\t\tisInVoiceChannel: false,\n\t\t\t\t\troomId: room.id,\n\t\t\t\t},\n\t\t\t\tvalues: {\n\t\t\t\t\tisInVoiceChannel: \"false\",\n\t\t\t\t},\n\t\t\t\ttext: `${agentName} is not currently in a voice channel`,\n\t\t\t} as ProviderResult;\n\t\t}\n\n\t\tconst connection = getVoiceConnection(guildId);\n\n\t\tif (!connection) {\n\t\t\treturn {\n\t\t\t\tdata: {\n\t\t\t\t\tisInVoiceChannel: false,\n\t\t\t\t\troomId: room.id,\n\t\t\t\t},\n\t\t\t\tvalues: {\n\t\t\t\t\tisInVoiceChannel: \"false\",\n\t\t\t\t},\n\t\t\t\ttext: `${agentName} is not currently in a voice channel`,\n\t\t\t} as ProviderResult;\n\t\t}\n\n\t\tconst worldId = room.worldId;\n\n\t\t// get the world from the runtime.getWorld\n\t\tconst world = await runtime.getWorld(worldId as UUID);\n\n\t\tif (!world) {\n\t\t\tthrow new Error(\"No world found\");\n\t\t}\n\n\t\tconst worldName = world.name;\n\t\tconst roomType = room.type;\n\t\tconst channelName = room.name;\n\n\t\treturn {\n\t\t\tdata: {\n\t\t\t\tisInVoiceChannel: true,\n\t\t\t\troomId: room.id,\n\t\t\t\tworldId: world.id,\n\t\t\t\tchannelId,\n\t\t\t\tchannelName,\n\t\t\t},\n\t\t\tvalues: {\n\t\t\t\tisInVoiceChannel: \"true\",\n\t\t\t\tworldName,\n\t\t\t\troomType,\n\t\t\t\tchannelId,\n\t\t\t\tchannelName,\n\t\t\t},\n\t\t\ttext: `${agentName} is currently in the voice channel: ${channelName} (ID: ${channelId})`,\n\t\t} as ProviderResult;\n\t},\n};\n\nexport default voiceStateProvider;\n",
|
|
114
|
+
"import {\n\tChannelType,\n\ttype Character,\n\ttype Content,\n\ttype CustomMetadata,\n\tcreateUniqueUuid,\n\ttype Entity,\n\ttype EventPayload,\n\tEventType,\n\ttype HandlerCallback,\n\ttype IAgentRuntime,\n\ttype Media,\n\ttype Memory,\n\tMemoryType,\n\ttype Room,\n\tService,\n\tstringToUuid,\n\ttype TargetInfo,\n\ttype UUID,\n\ttype World,\n} from \"@elizaos/core\";\n\n/**\n * IMPORTANT: Discord ID Handling - Why stringToUuid() instead of asUUID()\n *\n * Discord uses \"snowflake\" IDs - large 64-bit integers represented as strings\n * (e.g., \"1253563208833433701\"). These are NOT valid UUIDs.\n *\n * UUID format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (8-4-4-4-12 hex digits with dashes)\n * Discord ID: 1253563208833433701 (plain number string)\n *\n * The two UUID-related functions behave differently:\n *\n * - `asUUID(str)` - VALIDATES that the string is already a valid UUID format.\n * If not, it throws: \"Error: Invalid UUID format: 1253563208833433701\"\n * Use only when you're certain the input is already a valid UUID.\n *\n * - `stringToUuid(str)` - CONVERTS any string into a deterministic UUID by hashing it.\n * Always succeeds. The same input always produces the same UUID output.\n * Use this for Discord snowflake IDs.\n *\n * When working with Discord IDs in ElizaOS:\n *\n * 1. `stringToUuid(discordId)` - For storing Discord IDs in UUID fields (e.g., `messageServerId`).\n *\n * 2. `createUniqueUuid(runtime, discordId)` - For `worldId` and `roomId`. This adds the agent's\n * ID to the hash, ensuring each agent has its own unique namespace for the same Discord server.\n *\n * 3. `messageServerId` - The correct property name for server IDs on Room and World objects.\n *\n * 4. Discord-specific events (e.g., DiscordEventTypes.VOICE_STATE_UPDATE) are not in core's\n * EventPayloadMap. When emitting these events, cast to `string[]` and payload to `any`\n * to use the generic emitEvent overload.\n */\nimport {\n\ttype ApplicationCommandData,\n\ttype ApplicationCommandDataResolvable,\n\tAttachmentBuilder,\n\tAuditLogEvent,\n\ttype Channel,\n\ttype ChatInputApplicationCommandData,\n\ttype Collection,\n\tChannelType as DiscordChannelType,\n\tClient as DiscordJsClient,\n\ttype Role as DiscordRole,\n\tEvents,\n\tGatewayIntentBits,\n\ttype Guild,\n\ttype GuildChannel,\n\ttype GuildMember,\n\ttype GuildTextBasedChannel,\n\ttype Interaction,\n\ttype Message,\n\ttype MessageReaction,\n\ttype PartialMessageReaction,\n\tPartials,\n\ttype PartialUser,\n\tPermissionsBitField,\n\ttype TextChannel,\n\ttype User,\n} from \"discord.js\";\nimport {\n\tcreateCompatRuntime,\n\ttype ICompatRuntime,\n\ttype WorldCompat,\n} from \"./compat\";\nimport { DISCORD_SERVICE_NAME } from \"./constants\";\nimport { getDiscordSettings } from \"./environment\";\nimport {\n\tbuildDiscordEntityMetadata,\n\tbuildDiscordWorldMetadata,\n} from \"./identity\";\nimport { MessageManager } from \"./messages\";\nimport {\n\tdiffMemberRoles,\n\tdiffOverwrites,\n\tdiffRolePermissions,\n\tfetchAuditEntry,\n} from \"./permissionEvents\";\nimport { generateInviteUrl } from \"./permissions\";\nimport {\n\ttype ChannelHistoryOptions,\n\ttype ChannelHistoryResult,\n\ttype ChannelSpiderState,\n\tDiscordEventTypes,\n\ttype DiscordListenChannelPayload,\n\ttype DiscordNotInChannelsPayload,\n\ttype DiscordReactionPayload,\n\ttype DiscordRegisterCommandsPayload,\n\ttype DiscordSettings,\n\ttype DiscordSlashCommand,\n\ttype DiscordSlashCommandPayload,\n\ttype IDiscordService,\n} from \"./types\";\nimport {\n\tgetAttachmentFileName,\n\tMAX_MESSAGE_LENGTH,\n\tsplitMessage,\n} from \"./utils\";\nimport { VoiceManager } from \"./voice\";\n\n/**\n * DiscordService class representing a service for interacting with Discord.\n * @extends Service\n * @implements IDiscordService\n * @property {string} serviceType - The type of service, set to DISCORD_SERVICE_NAME.\n * @property {string} capabilityDescription - A description of the service's capabilities.\n * @property {DiscordJsClient} client - The DiscordJsClient used for communication.\n * @property {Character} character - The character associated with the service.\n * @property {MessageManager} messageManager - The manager for handling messages.\n * @property {VoiceManager} voiceManager - The manager for handling voice communication.\n */\n\nexport class DiscordService extends Service implements IDiscordService {\n\t// Override runtime type for messageServerId cross-core compatibility (see compat.ts)\n\tprotected declare runtime: ICompatRuntime;\n\n\tstatic serviceType: string = DISCORD_SERVICE_NAME;\n\tcapabilityDescription =\n\t\t\"The agent is able to send and receive messages on discord\";\n\tclient: DiscordJsClient | null;\n\tcharacter: Character;\n\tmessageManager?: MessageManager;\n\tvoiceManager?: VoiceManager;\n\tprivate discordSettings: DiscordSettings;\n\tprivate userSelections: Map<string, Record<string, unknown>> = new Map();\n\tprivate timeouts: ReturnType<typeof setTimeout>[] = [];\n\tpublic clientReadyPromise: Promise<void> | null = null;\n\tprivate slashCommands: DiscordSlashCommand[] = [];\n\tprivate commandRegistrationQueue: Promise<void> = Promise.resolve();\n\t/**\n\t * Slash command names that should bypass allowed channel restrictions.\n\t */\n\tprivate allowAllSlashCommands: Set<string> = new Set();\n\t/**\n\t * List of allowed channel IDs (parsed from CHANNEL_IDS env var).\n\t * If undefined, all channels are allowed.\n\t */\n\tprivate allowedChannelIds?: string[];\n\n\t/**\n\t * Set of dynamically added channel IDs through joinChannel action.\n\t * These are merged with allowedChannelIds for runtime channel management.\n\t */\n\tprivate dynamicChannelIds: Set<string> = new Set();\n\n\t/**\n\t * Constructor for Discord client.\n\t * Initializes the Discord client with specified intents and partials,\n\t * sets up event listeners, and ensures all servers exist.\n\t *\n\t * @param {IAgentRuntime} runtime - The AgentRuntime instance\n\t */\n\tconstructor(runtime: IAgentRuntime) {\n\t\tsuper(runtime);\n\n\t\t// Load Discord settings with proper priority (env vars > character settings > defaults)\n\t\tthis.discordSettings = getDiscordSettings(runtime);\n\n\t\tthis.character = runtime.character;\n\n\t\t// Parse CHANNEL_IDS env var to restrict the bot to specific channels\n\t\tconst channelIdsRaw = runtime.getSetting(\"CHANNEL_IDS\") as\n\t\t\t| string\n\t\t\t| undefined;\n\t\tif (\n\t\t\tchannelIdsRaw &&\n\t\t\ttypeof channelIdsRaw === \"string\" &&\n\t\t\tchannelIdsRaw.trim &&\n\t\t\ttypeof channelIdsRaw.trim === \"function\" &&\n\t\t\tchannelIdsRaw.trim()\n\t\t) {\n\t\t\tthis.allowedChannelIds = channelIdsRaw\n\t\t\t\t.split(\",\")\n\t\t\t\t.map((s) => s.trim())\n\t\t\t\t.filter((s) => s.length > 0);\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tallowedChannelIds: this.allowedChannelIds,\n\t\t\t\t},\n\t\t\t\t\"Channel restrictions enabled\",\n\t\t\t);\n\t\t}\n\n\t\t// Check if Discord API token is available and valid\n\t\tconst token = runtime.getSetting(\"DISCORD_API_TOKEN\") as string;\n\t\tconst tokenTrimmed =\n\t\t\ttoken &&\n\t\t\ttypeof token === \"string\" &&\n\t\t\ttoken.trim &&\n\t\t\ttypeof token.trim === \"function\"\n\t\t\t\t? token.trim()\n\t\t\t\t: token;\n\t\tif (!token || tokenTrimmed === \"\" || token === null) {\n\t\t\tthis.runtime.logger.warn(\"Discord API Token not provided\");\n\t\t\tthis.client = null;\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst client = new DiscordJsClient({\n\t\t\t\tintents: [\n\t\t\t\t\tGatewayIntentBits.Guilds,\n\t\t\t\t\tGatewayIntentBits.GuildMembers,\n\t\t\t\t\tGatewayIntentBits.GuildPresences,\n\t\t\t\t\tGatewayIntentBits.DirectMessages,\n\t\t\t\t\tGatewayIntentBits.GuildVoiceStates,\n\t\t\t\t\tGatewayIntentBits.MessageContent,\n\t\t\t\t\tGatewayIntentBits.GuildMessages,\n\t\t\t\t\tGatewayIntentBits.DirectMessageTyping,\n\t\t\t\t\tGatewayIntentBits.GuildMessageTyping,\n\t\t\t\t\tGatewayIntentBits.GuildMessageReactions,\n\t\t\t\t],\n\t\t\t\tpartials: [\n\t\t\t\t\tPartials.Channel,\n\t\t\t\t\tPartials.Message,\n\t\t\t\t\tPartials.User,\n\t\t\t\t\tPartials.Reaction,\n\t\t\t\t],\n\t\t\t});\n\t\t\tthis.client = client;\n\n\t\t\tthis.runtime = createCompatRuntime(runtime);\n\t\t\tthis.voiceManager = new VoiceManager(this, this.runtime);\n\t\t\tthis.messageManager = new MessageManager(this, this.runtime);\n\n\t\t\tthis.clientReadyPromise = new Promise((resolve, reject) => {\n\t\t\t\t// once logged in\n\t\t\t\tclient.once(Events.ClientReady, async (readyClient) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.onReady(readyClient);\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t\t\t`Error in onReady: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\treject(error);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t// Handle client errors that might prevent ready event\n\t\t\t\tclient.once(Events.Error, (error) => {\n\t\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t\t`Discord client error: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\t);\n\t\t\t\t\treject(error);\n\t\t\t\t});\n\t\t\t\t// now start login\n\t\t\t\tclient.login(token).catch((error) => {\n\t\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t\t`Failed to login to Discord: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\t);\n\t\t\t\t\tif (this.client) {\n\t\t\t\t\t\tthis.client.destroy().catch(() => {});\n\t\t\t\t\t}\n\t\t\t\t\tthis.client = null;\n\t\t\t\t\treject(error);\n\t\t\t\t});\n\t\t\t});\n\n\t\t\t// Attach error handler to prevent unhandled promise rejection\n\t\t\t// This ensures the promise rejection is handled even if no one awaits it immediately\n\t\t\tthis.clientReadyPromise.catch((_error) => {\n\t\t\t\t// Error is already logged in the promise handlers above\n\t\t\t\t// This catch prevents unhandled promise rejection warnings\n\t\t\t\t// The promise is public and may be awaited elsewhere, but we need to handle\n\t\t\t\t// the case where it's not immediately awaited\n\t\t\t});\n\n\t\t\tthis.setupEventListeners();\n\t\t\t// Send handler registered via runtime.registerSendHandlers()\n\t\t} catch (error) {\n\t\t\truntime.logger.error(\n\t\t\t\t`Error initializing Discord client: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t\tthis.client = null;\n\t\t}\n\t}\n\n\tstatic async start(runtime: IAgentRuntime) {\n\t\tconst service = new DiscordService(runtime);\n\t\treturn service;\n\t}\n\n\t/**\n\t * The SendHandlerFunction implementation for Discord.\n\t * @param {IAgentRuntime} runtime - The runtime instance.\n\t * @param {TargetInfo} target - The target information for the message.\n\t * @param {Content} content - The content of the message to send.\n\t * @returns {Promise<void>} A promise that resolves when the message is sent or rejects on error.\n\t * @throws {Error} If the client is not ready, target is invalid, or sending fails.\n\t */\n\tasync handleSendMessage(\n\t\t// why we have this.runtime on the agent itself and this isn't a static\n\t\truntime: IAgentRuntime,\n\t\ttarget: TargetInfo,\n\t\tcontent: Content,\n\t): Promise<void> {\n\t\tif (!this.client || !this.client.isReady()) {\n\t\t\truntime.logger.error(\"Client not ready\");\n\t\t\tthrow new Error(\"Discord client is not ready.\");\n\t\t}\n\t\t// After the check above, client is guaranteed to exist and be ready\n\t\tconst client = this.client;\n\n\t\t// Skip sending if channel restrictions are set and target channel is not allowed\n\t\tif (\n\t\t\ttarget.channelId &&\n\t\t\tthis.allowedChannelIds &&\n\t\t\t!this.isChannelAllowed(target.channelId)\n\t\t) {\n\t\t\truntime.logger.warn(\n\t\t\t\t`Channel ${target.channelId} not in allowed list, skipping send`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tlet targetChannel: Channel | undefined | null = null;\n\n\t\ttry {\n\t\t\t// Determine target based on provided info\n\t\t\tif (target.channelId) {\n\t\t\t\ttargetChannel = await client.channels.fetch(target.channelId);\n\t\t\t} else if (target.entityId) {\n\t\t\t\t// Attempt to convert runtime UUID to Discord snowflake ID\n\t\t\t\t// NOTE: This assumes a mapping exists or the UUID *is* the snowflake ID\n\t\t\t\tconst discordUserId = target.entityId as string; // May need more robust conversion\n\t\t\t\tconst user = await client.users.fetch(discordUserId);\n\t\t\t\tif (user) {\n\t\t\t\t\t// user.dmChannel is a property (DMChannel | null), not a promise\n\t\t\t\t\ttargetChannel = user.dmChannel ?? (await user.createDM());\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"Discord SendHandler requires channelId or entityId.\");\n\t\t\t}\n\n\t\t\tif (!targetChannel) {\n\t\t\t\t// Safely serialize target for error message (target only contains strings, but be defensive)\n\t\t\t\tconst targetStr = JSON.stringify(target, (_key, value) => {\n\t\t\t\t\t// Convert BigInt to string if somehow present\n\t\t\t\t\tif (typeof value === \"bigint\") {\n\t\t\t\t\t\treturn value.toString();\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t});\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Could not find target Discord channel/DM for target: ${targetStr}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Type guard to ensure the channel is text-based\n\t\t\tif (targetChannel.isTextBased() && !targetChannel.isVoiceBased()) {\n\t\t\t\t// Further check if it's a channel where bots can send messages\n\t\t\t\tif (\n\t\t\t\t\t\"send\" in targetChannel &&\n\t\t\t\t\ttypeof targetChannel.send === \"function\"\n\t\t\t\t) {\n\t\t\t\t\t// Convert Media attachments to Discord AttachmentBuilder format\n\t\t\t\t\tconst files: AttachmentBuilder[] = [];\n\t\t\t\t\tif (content.attachments && content.attachments.length > 0) {\n\t\t\t\t\t\tfor (const media of content.attachments) {\n\t\t\t\t\t\t\tif (media.url) {\n\t\t\t\t\t\t\t\tconst fileName = getAttachmentFileName(media);\n\t\t\t\t\t\t\t\tfiles.push(\n\t\t\t\t\t\t\t\t\tnew AttachmentBuilder(media.url, { name: fileName }),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst sentMessages: Message[] = [];\n\t\t\t\t\tconst roomId = createUniqueUuid(runtime, targetChannel.id);\n\t\t\t\t\tconst channelType = await this.getChannelType(\n\t\t\t\t\t\ttargetChannel as Channel,\n\t\t\t\t\t);\n\n\t\t\t\t\t// Send message with text and/or attachments\n\t\t\t\t\tif (content.text || files.length > 0) {\n\t\t\t\t\t\tif (content.text) {\n\t\t\t\t\t\t\t// Split message if longer than Discord limit (uses safe buffer)\n\t\t\t\t\t\t\tconst chunks = splitMessage(content.text, MAX_MESSAGE_LENGTH);\n\t\t\t\t\t\t\tif (chunks.length > 1) {\n\t\t\t\t\t\t\t\t// Send all chunks except the last one without files\n\t\t\t\t\t\t\t\tfor (let i = 0; i < chunks.length - 1; i++) {\n\t\t\t\t\t\t\t\t\tconst sent = await targetChannel.send(chunks[i]);\n\t\t\t\t\t\t\t\t\tsentMessages.push(sent);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Send the last chunk with files (if any)\n\t\t\t\t\t\t\t\tconst sent = await targetChannel.send({\n\t\t\t\t\t\t\t\t\tcontent: chunks[chunks.length - 1],\n\t\t\t\t\t\t\t\t\tfiles: files.length > 0 ? files : undefined,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tsentMessages.push(sent);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// Single chunk - send with files (if any)\n\t\t\t\t\t\t\t\tconst sent = await targetChannel.send({\n\t\t\t\t\t\t\t\t\tcontent: chunks[0],\n\t\t\t\t\t\t\t\t\tfiles: files.length > 0 ? files : undefined,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tsentMessages.push(sent);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Only attachments, no text\n\t\t\t\t\t\t\tconst sent = await targetChannel.send({\n\t\t\t\t\t\t\t\tfiles,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tsentMessages.push(sent);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\truntime.logger.warn(\"No text content or attachments provided\");\n\t\t\t\t\t}\n\n\t\t\t\t\t// Ensure room/world/participant exist before saving to memory (FK constraints)\n\t\t\t\t\tconst targetChannelGuild =\n\t\t\t\t\t\t\"guild\" in targetChannel ? targetChannel.guild : null;\n\t\t\t\t\tconst serverId = targetChannelGuild?.id\n\t\t\t\t\t\t? targetChannelGuild.id\n\t\t\t\t\t\t: targetChannel.id;\n\t\t\t\t\tconst worldId = createUniqueUuid(runtime, serverId) as UUID;\n\t\t\t\t\tconst worldName = targetChannelGuild?.name\n\t\t\t\t\t\t? targetChannelGuild.name\n\t\t\t\t\t\t: undefined;\n\n\t\t\t\t\tconst clientUser = client.user;\n\t\t\t\t\tawait this.runtime.ensureConnection({\n\t\t\t\t\t\tentityId: runtime.agentId,\n\t\t\t\t\t\troomId,\n\t\t\t\t\t\tuserName: clientUser?.username ? clientUser.username : undefined,\n\t\t\t\t\t\tname: clientUser?.displayName || clientUser?.username || undefined,\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\tchannelId: targetChannel.id,\n\t\t\t\t\t\tmessageServerId: stringToUuid(serverId),\n\t\t\t\t\t\ttype: channelType,\n\t\t\t\t\t\tworldId,\n\t\t\t\t\t\tworldName,\n\t\t\t\t\t});\n\n\t\t\t\t\t// Save sent messages to memory\n\t\t\t\t\tfor (const sentMsg of sentMessages) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Only include attachments/actions in memory for messages that actually have attachments\n\t\t\t\t\t\t\tconst hasAttachments = sentMsg.attachments.size > 0;\n\n\t\t\t\t\t\t\tconst memory: Memory = {\n\t\t\t\t\t\t\t\tid: createUniqueUuid(runtime, sentMsg.id),\n\t\t\t\t\t\t\t\tentityId: runtime.agentId,\n\t\t\t\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\t\t\t\troomId,\n\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\ttext: sentMsg.content || content.text || \" \",\n\t\t\t\t\t\t\t\t\turl: sentMsg.url,\n\t\t\t\t\t\t\t\t\tchannelType,\n\t\t\t\t\t\t\t\t\t// Only include attachments for messages that actually have attachments\n\t\t\t\t\t\t\t\t\t...(hasAttachments && content.attachments\n\t\t\t\t\t\t\t\t\t\t? { attachments: content.attachments }\n\t\t\t\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t\t\t\t// Include action whenever it exists, regardless of attachments\n\t\t\t\t\t\t\t\t\t...(content.action ? { action: content.action } : {}),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tmetadata: {\n\t\t\t\t\t\t\t\t\ttype: MemoryType.MESSAGE,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tcreatedAt: sentMsg.createdTimestamp || Date.now(),\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\tawait runtime.createMemory(memory, \"messages\");\n\t\t\t\t\t\t\truntime.logger.debug(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\t\tagentId: runtime.agentId,\n\t\t\t\t\t\t\t\t\tmessageId: sentMsg.id,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"Saved sent message to memory\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\truntime.logger.warn(\n\t\t\t\t\t\t\t\t`Failed to save sent message ${sentMsg.id} to memory: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Target channel ${targetChannel.id} does not have a send method.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Target channel ${targetChannel.id} is not a valid text-based channel for sending messages.`,\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\truntime.logger.error(\n\t\t\t\t`Error sending message to ${JSON.stringify(target)}: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * Set up event listeners for the client.\n\t * @private\n\t */\n\tprivate setupEventListeners() {\n\t\tif (!this.client) {\n\t\t\treturn; // Skip if client is not available\n\t\t}\n\n\t\tconst listenCidsRaw = this.runtime.getSetting(\n\t\t\t\"DISCORD_LISTEN_CHANNEL_IDS\",\n\t\t) as string | string[] | undefined;\n\t\tconst listenCids = Array.isArray(listenCidsRaw)\n\t\t\t? listenCidsRaw\n\t\t\t: listenCidsRaw &&\n\t\t\t\t\ttypeof listenCidsRaw === \"string\" &&\n\t\t\t\t\tlistenCidsRaw.trim()\n\t\t\t\t? listenCidsRaw\n\t\t\t\t\t\t.trim()\n\t\t\t\t\t\t.split(\",\")\n\t\t\t\t\t\t.map((s) => s.trim())\n\t\t\t\t\t\t.filter((s) => s.length > 0)\n\t\t\t\t: [];\n\n\t\t// Setup handling for direct messages\n\t\tthis.client.on(\"messageCreate\", async (message) => {\n\t\t\t// Skip if we're sending the message or in deleted state\n\t\t\tconst clientUser = this.client?.user;\n\t\t\tif (\n\t\t\t\t(clientUser && message.author.id === clientUser.id) ||\n\t\t\t\t(message.author.bot && this.discordSettings.shouldIgnoreBotMessages)\n\t\t\t) {\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tauthorId: message.author.id,\n\t\t\t\t\t\tisBot: message.author.bot,\n\t\t\t\t\t},\n\t\t\t\t\t\"Ignoring message from bot or self\",\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (listenCids.includes(message.channel.id) && message) {\n\t\t\t\t// Use the reusable buildMemoryFromMessage method\n\t\t\t\tconst newMessage = await this.buildMemoryFromMessage(message);\n\n\t\t\t\tif (!newMessage) {\n\t\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\tmessageId: message.id,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Failed to build memory from listen channel message\",\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Emit event for listen channel handlers\n\t\t\t\tconst listenPayload: DiscordListenChannelPayload = {\n\t\t\t\t\truntime: this.runtime,\n\t\t\t\t\tmessage: newMessage,\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t};\n\t\t\t\tthis.runtime.emitEvent(\n\t\t\t\t\tDiscordEventTypes.LISTEN_CHANNEL_MESSAGE,\n\t\t\t\t\tlistenPayload,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Skip if channel restrictions are set and this channel is not allowed\n\t\t\tif (\n\t\t\t\tthis.allowedChannelIds &&\n\t\t\t\t!this.isChannelAllowed(message.channel.id)\n\t\t\t) {\n\t\t\t\t// check first whether the channel is a thread...\n\t\t\t\tconst channel = this.client\n\t\t\t\t\t? await this.client.channels.fetch(message.channel.id)\n\t\t\t\t\t: null;\n\n\t\t\t\tconst notInChannelsPayload: DiscordNotInChannelsPayload = {\n\t\t\t\t\truntime: this.runtime,\n\t\t\t\t\tmessage: message,\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t};\n\t\t\t\tthis.runtime.emitEvent(\n\t\t\t\t\tDiscordEventTypes.NOT_IN_CHANNELS_MESSAGE,\n\t\t\t\t\tnotInChannelsPayload,\n\t\t\t\t);\n\n\t\t\t\tif (!channel) {\n\t\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\tchannelId: message.channel.id,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Channel not found\",\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (channel.isThread()) {\n\t\t\t\t\tif (!channel.parentId || !this.isChannelAllowed(channel.parentId)) {\n\t\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\tparentChannelId: channel.parentId,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Thread not in allowed channel\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (\n\t\t\t\t\t\tchannel?.isTextBased &&\n\t\t\t\t\t\ttypeof channel.isTextBased === \"function\" &&\n\t\t\t\t\t\tchannel.isTextBased()\n\t\t\t\t\t) {\n\t\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\tchannelId: channel.id,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Channel not allowed\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\t// Ensure messageManager exists\n\t\t\t\tif (this.messageManager) {\n\t\t\t\t\tthis.messageManager.handleMessage(message);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t},\n\t\t\t\t\t\"Error handling message\",\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\n\t\t// Setup handling for reactions\n\t\tthis.client.on(\"messageReactionAdd\", async (reaction, user) => {\n\t\t\tconst clientUser = this.client?.user;\n\t\t\tif (clientUser && user.id === clientUser.id) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Skip if channel restrictions are set and this reaction is not in an allowed channel\n\t\t\tif (\n\t\t\t\tthis.allowedChannelIds &&\n\t\t\t\treaction.message.channel &&\n\t\t\t\t!this.isChannelAllowed(reaction.message.channel.id)\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait this.handleReactionAdd(reaction, user);\n\t\t\t} catch (error) {\n\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t},\n\t\t\t\t\t\"Error handling reaction add\",\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\n\t\t// Handle reaction removal\n\t\tthis.client.on(\"messageReactionRemove\", async (reaction, user) => {\n\t\t\tconst clientUser = this.client?.user;\n\t\t\tif (clientUser && user.id === clientUser.id) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Skip if channel restrictions are set and this reaction is not in an allowed channel\n\t\t\tif (\n\t\t\t\tthis.allowedChannelIds &&\n\t\t\t\treaction.message.channel &&\n\t\t\t\t!this.isChannelAllowed(reaction.message.channel.id)\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait this.handleReactionRemove(reaction, user);\n\t\t\t} catch (error) {\n\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t},\n\t\t\t\t\t\"Error handling reaction remove\",\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\n\t\t// Setup guild (server) event handlers\n\t\tthis.client.on(\"guildCreate\", async (guild) => {\n\t\t\ttry {\n\t\t\t\tawait this.handleGuildCreate(guild);\n\t\t\t} catch (error) {\n\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t},\n\t\t\t\t\t\"Error handling guild create\",\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\n\t\t// Setup member (user) joining handlers\n\t\tthis.client.on(\"guildMemberAdd\", async (member) => {\n\t\t\ttry {\n\t\t\t\tawait this.handleGuildMemberAdd(member);\n\t\t\t} catch (error) {\n\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t},\n\t\t\t\t\t\"Error handling guild member add\",\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\n\t\t// Interaction handlers\n\t\t//\n\t\t// Permission Check Flow for Slash Commands:\n\t\t// 1. Discord native checks (before this event fires):\n\t\t// - User has required permissions (default_member_permissions)\n\t\t// - Command is available in this context (guild vs DM)\n\t\t// 2. ElizaOS channel whitelist (here):\n\t\t// - If CHANNEL_IDS is set, check if channel is allowed\n\t\t// - Unless command has bypassChannelWhitelist flag\n\t\t// 3. Custom validator (here):\n\t\t// - Run command's validator function if provided\n\t\t// - Full programmatic control for complex logic\n\t\t//\n\t\t// Why this order?\n\t\t// - Discord's checks are free (handled before interaction fires)\n\t\t// - Channel whitelist is cheap (Set lookup)\n\t\t// - Custom validators can be expensive (async, database calls, etc.)\n\t\tthis.client.on(\"interactionCreate\", async (interaction) => {\n\t\t\tconst isSlashCommand = interaction.isCommand();\n\t\t\tconst isModalSubmit = interaction.isModalSubmit();\n\t\t\tconst isComponent = interaction.isMessageComponent();\n\n\t\t\t// Check if this slash command has bypass enabled\n\t\t\tconst bypassChannelRestriction =\n\t\t\t\tisSlashCommand &&\n\t\t\t\tthis.allowAllSlashCommands.has(interaction.commandName ?? \"\");\n\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tinteractionType: interaction.type,\n\t\t\t\t\tcommandName: isSlashCommand ? interaction.commandName : undefined,\n\t\t\t\t\tchannelId: interaction.channelId,\n\t\t\t\t\tinGuild: interaction.inGuild(),\n\t\t\t\t\tbypassChannelRestriction,\n\t\t\t\t},\n\t\t\t\t\"[DiscordService] interactionCreate received\",\n\t\t\t);\n\n\t\t\t// ElizaOS Channel Whitelist Check\n\t\t\t// Follow-up interactions (modals, buttons, autocomplete) always bypass the channel whitelist\n\t\t\t// since they are responses to commands initiated by the user.\n\t\t\t// Slash commands respect the whitelist unless bypassChannelWhitelist: true.\n\t\t\tconst isFollowUpInteraction = Boolean(\n\t\t\t\tinteraction.isModalSubmit() ||\n\t\t\t\t\tinteraction.isMessageComponent() ||\n\t\t\t\t\tinteraction.isAutocomplete(),\n\t\t\t);\n\n\t\t\t// Skip if channel restrictions are set and this interaction is not in an allowed channel\n\t\t\t// - Follow-up interactions (modals, components, autocomplete) always bypass\n\t\t\t// - Slash commands respect whitelist unless they have bypassChannelWhitelist: true\n\t\t\tif (\n\t\t\t\t!isFollowUpInteraction &&\n\t\t\t\tthis.allowedChannelIds &&\n\t\t\t\tinteraction.channelId &&\n\t\t\t\t!this.isChannelAllowed(interaction.channelId) &&\n\t\t\t\t!bypassChannelRestriction\n\t\t\t) {\n\t\t\t\t// For slash commands, send a response to avoid Discord's \"application did not respond\" error\n\t\t\t\t// Other interaction types (non-slash) can fail silently\n\t\t\t\tif (isSlashCommand && interaction.isCommand()) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait interaction.reply({\n\t\t\t\t\t\t\tcontent: \"This command is not available in this channel.\",\n\t\t\t\t\t\t\tephemeral: true,\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (responseError) {\n\t\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\terror:\n\t\t\t\t\t\t\t\t\tresponseError instanceof Error\n\t\t\t\t\t\t\t\t\t\t? responseError.message\n\t\t\t\t\t\t\t\t\t\t: String(responseError),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Could not send channel restriction response\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tchannelId: interaction.channelId,\n\t\t\t\t\t\tallowedChannelIds: this.allowedChannelIds,\n\t\t\t\t\t\tisSlashCommand,\n\t\t\t\t\t\tisModalSubmit,\n\t\t\t\t\t\tisComponent,\n\t\t\t\t\t\tbypassChannelRestriction,\n\t\t\t\t\t},\n\t\t\t\t\t\"[DiscordService] interactionCreate ignored (channel not allowed)\",\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Run custom validator if provided for slash commands\n\t\t\t// This is the final permission check layer, after Discord's native checks\n\t\t\t// and our channel whitelist checks have already passed.\n\t\t\t//\n\t\t\t// Why validators?\n\t\t\t// - ElizaOS-specific permission systems (when implemented)\n\t\t\t// - Complex business logic (rate limiting, feature flags, etc.)\n\t\t\t// - Dynamic permissions based on runtime state\n\t\t\t// - Anything that can't be expressed via Discord's native permissions\n\t\t\tif (isSlashCommand && interaction.commandName) {\n\t\t\t\tconst command = this.slashCommands.find(\n\t\t\t\t\t(cmd) => cmd.name === interaction.commandName,\n\t\t\t\t);\n\t\t\t\tif (command?.validator) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst isValid = await command.validator(interaction, this.runtime);\n\t\t\t\t\t\tif (!isValid) {\n\t\t\t\t\t\t\t// Send default response if validator didn't respond\n\t\t\t\t\t\t\t// This prevents Discord from showing \"Interaction failed\" after 3 seconds\n\t\t\t\t\t\t\t// or leaving a \"thinking\" indicator if the validator called deferReply()\n\t\t\t\t\t\t\tif (!interaction.replied) {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tconst errorMessage =\n\t\t\t\t\t\t\t\t\t\t\"You do not have permission to use this command.\";\n\t\t\t\t\t\t\t\t\tif (interaction.deferred) {\n\t\t\t\t\t\t\t\t\t\t// Validator called deferReply() - use editReply() to resolve the deferred state\n\t\t\t\t\t\t\t\t\t\tawait interaction.editReply({ content: errorMessage });\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tawait interaction.reply({\n\t\t\t\t\t\t\t\t\t\t\tcontent: errorMessage,\n\t\t\t\t\t\t\t\t\t\t\tephemeral: true,\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} catch (responseError) {\n\t\t\t\t\t\t\t\t\t// Validator may have already responded or interaction expired\n\t\t\t\t\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\t\t\t\tcommandName: interaction.commandName,\n\t\t\t\t\t\t\t\t\t\t\terror:\n\t\t\t\t\t\t\t\t\t\t\t\tresponseError instanceof Error\n\t\t\t\t\t\t\t\t\t\t\t\t\t? responseError.message\n\t\t\t\t\t\t\t\t\t\t\t\t\t: String(responseError),\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\"Could not send validator rejection response (may have already responded)\",\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\t\tcommandName: interaction.commandName,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"[DiscordService] interactionCreate ignored (custom validator returned false)\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t// Send error response if validator threw and didn't respond\n\t\t\t\t\t\t// or left a \"thinking\" indicator via deferReply()\n\t\t\t\t\t\tif (!interaction.replied) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst errorMessage =\n\t\t\t\t\t\t\t\t\t\"An error occurred while validating this command.\";\n\t\t\t\t\t\t\t\tif (interaction.deferred) {\n\t\t\t\t\t\t\t\t\t// Validator called deferReply() - use editReply() to resolve the deferred state\n\t\t\t\t\t\t\t\t\tawait interaction.editReply({ content: errorMessage });\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tawait interaction.reply({\n\t\t\t\t\t\t\t\t\t\tcontent: errorMessage,\n\t\t\t\t\t\t\t\t\t\tephemeral: true,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (responseError) {\n\t\t\t\t\t\t\t\t// Validator may have already responded or interaction expired\n\t\t\t\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\t\t\tcommandName: interaction.commandName,\n\t\t\t\t\t\t\t\t\t\terror:\n\t\t\t\t\t\t\t\t\t\t\tresponseError instanceof Error\n\t\t\t\t\t\t\t\t\t\t\t\t? responseError.message\n\t\t\t\t\t\t\t\t\t\t\t\t: String(responseError),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"Could not send validator error response (may have already responded)\",\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\tcommandName: interaction.commandName,\n\t\t\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"[DiscordService] Custom validator threw error\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tawait this.handleInteractionCreate(interaction);\n\t\t\t} catch (error) {\n\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t},\n\t\t\t\t\t\"Error handling interaction\",\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\n\t\tthis.client.on(\n\t\t\t\"userStream\",\n\t\t\t(entityId, name, userName, channel, opusDecoder) => {\n\t\t\t\tconst clientUser = this.client?.user;\n\t\t\t\tif (clientUser && entityId !== clientUser.id) {\n\t\t\t\t\t// Ensure voiceManager exists\n\t\t\t\t\tif (this.voiceManager) {\n\t\t\t\t\t\tthis.voiceManager.handleUserStream(\n\t\t\t\t\t\t\tentityId,\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\tuserName,\n\t\t\t\t\t\t\tchannel,\n\t\t\t\t\t\t\topusDecoder,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\n\t\t// =========================================================================\n\t\t// Permission Audit Events (controlled by DISCORD_AUDIT_LOG_ENABLED setting)\n\t\t// =========================================================================\n\t\tconst auditLogSetting = this.runtime.getSetting(\n\t\t\t\"DISCORD_AUDIT_LOG_ENABLED\",\n\t\t);\n\t\tconst isAuditLogEnabled =\n\t\t\tauditLogSetting !== \"false\" && auditLogSetting !== false;\n\n\t\tif (isAuditLogEnabled) {\n\t\t\t// Channel permission overwrites changed\n\t\t\tthis.client.on(\"channelUpdate\", async (oldChannel, newChannel) => {\n\t\t\t\ttry {\n\t\t\t\t\t// Handle partials\n\t\t\t\t\tlet channel = newChannel;\n\t\t\t\t\tif (channel.partial) {\n\t\t\t\t\t\tchannel = await channel.fetch();\n\t\t\t\t\t}\n\n\t\t\t\t\t// Only process guild channels with permission overwrites\n\t\t\t\t\tif (\n\t\t\t\t\t\t!(\"permissionOverwrites\" in oldChannel) ||\n\t\t\t\t\t\t!(\"guild\" in channel)\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst guildChannel = channel as GuildChannel;\n\t\t\t\t\tconst oldGuildChannel = oldChannel as GuildChannel;\n\t\t\t\t\tconst oldOverwrites = oldGuildChannel.permissionOverwrites.cache;\n\t\t\t\t\tconst newOverwrites = guildChannel.permissionOverwrites.cache;\n\n\t\t\t\t\t// Check all overwrites (old and new) to catch deletions\n\t\t\t\t\tconst allIds = new Set([\n\t\t\t\t\t\t...oldOverwrites.keys(),\n\t\t\t\t\t\t...newOverwrites.keys(),\n\t\t\t\t\t]);\n\n\t\t\t\t\tfor (const id of allIds) {\n\t\t\t\t\t\tconst oldOw = oldOverwrites.get(id);\n\t\t\t\t\t\tconst newOw = newOverwrites.get(id);\n\t\t\t\t\t\tconst { changes, action } = diffOverwrites(oldOw, newOw);\n\n\t\t\t\t\t\tif (changes.length === 0) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Determine audit log action type\n\t\t\t\t\t\tconst auditAction =\n\t\t\t\t\t\t\taction === \"DELETE\"\n\t\t\t\t\t\t\t\t? AuditLogEvent.ChannelOverwriteDelete\n\t\t\t\t\t\t\t\t: action === \"CREATE\"\n\t\t\t\t\t\t\t\t\t? AuditLogEvent.ChannelOverwriteCreate\n\t\t\t\t\t\t\t\t\t: AuditLogEvent.ChannelOverwriteUpdate;\n\n\t\t\t\t\t\tconst audit = await fetchAuditEntry(\n\t\t\t\t\t\t\tguildChannel.guild,\n\t\t\t\t\t\t\tauditAction,\n\t\t\t\t\t\t\tguildChannel.id,\n\t\t\t\t\t\t\tthis.runtime,\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// Skip if bot made this change\n\t\t\t\t\t\tconst clientUser = this.client?.user;\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\taudit?.executorId &&\n\t\t\t\t\t\t\tclientUser &&\n\t\t\t\t\t\t\taudit.executorId === clientUser.id\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Determine target info\n\t\t\t\t\t\tconst oldOwType =\n\t\t\t\t\t\t\toldOw && oldOw.type !== undefined ? oldOw.type : null;\n\t\t\t\t\t\tconst newOwType =\n\t\t\t\t\t\t\tnewOw && newOw.type !== undefined ? newOw.type : null;\n\t\t\t\t\t\tconst targetType =\n\t\t\t\t\t\t\t(oldOwType ?? newOwType ?? 1) === 0 ? \"role\" : \"user\";\n\t\t\t\t\t\tlet targetName: string;\n\t\t\t\t\t\tif (targetType === \"role\") {\n\t\t\t\t\t\t\tconst role = guildChannel.guild.roles.cache.get(id);\n\t\t\t\t\t\t\ttargetName = role?.name ?? \"Unknown\";\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst user = this.client\n\t\t\t\t\t\t\t\t? await this.client.users.fetch(id).catch(() => null)\n\t\t\t\t\t\t\t\t: null;\n\t\t\t\t\t\t\ttargetName = user?.tag ?? \"Unknown\";\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tthis.runtime.emitEvent(\n\t\t\t\t\t\t\tDiscordEventTypes.CHANNEL_PERMISSIONS_CHANGED,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\truntime: this.runtime,\n\t\t\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\t\t\tguild: {\n\t\t\t\t\t\t\t\t\tid: guildChannel.guild.id,\n\t\t\t\t\t\t\t\t\tname: guildChannel.guild.name,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tchannel: { id: guildChannel.id, name: guildChannel.name },\n\t\t\t\t\t\t\t\ttarget: { type: targetType, id, name: targetName },\n\t\t\t\t\t\t\t\taction,\n\t\t\t\t\t\t\t\tchanges,\n\t\t\t\t\t\t\t\taudit,\n\t\t\t\t\t\t\t} as EventPayload,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Error in channelUpdate handler\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Role permission changes\n\t\t\tthis.client.on(\"roleUpdate\", async (oldRole, newRole) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst changes = diffRolePermissions(oldRole, newRole);\n\t\t\t\t\tif (changes.length === 0) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst audit = await fetchAuditEntry(\n\t\t\t\t\t\tnewRole.guild,\n\t\t\t\t\t\tAuditLogEvent.RoleUpdate,\n\t\t\t\t\t\tnewRole.id,\n\t\t\t\t\t\tthis.runtime,\n\t\t\t\t\t);\n\n\t\t\t\t\t// Skip if bot made this change\n\t\t\t\t\tconst clientUser = this.client?.user;\n\t\t\t\t\tif (\n\t\t\t\t\t\taudit?.executorId &&\n\t\t\t\t\t\tclientUser &&\n\t\t\t\t\t\taudit.executorId === clientUser.id\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.runtime.emitEvent(DiscordEventTypes.ROLE_PERMISSIONS_CHANGED, {\n\t\t\t\t\t\truntime: this.runtime,\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\tguild: { id: newRole.guild.id, name: newRole.guild.name },\n\t\t\t\t\t\trole: { id: newRole.id, name: newRole.name },\n\t\t\t\t\t\tchanges,\n\t\t\t\t\t\taudit,\n\t\t\t\t\t} as EventPayload);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Error in roleUpdate handler\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Member role changes\n\t\t\tthis.client.on(\"guildMemberUpdate\", async (oldMember, newMember) => {\n\t\t\t\ttry {\n\t\t\t\t\t// oldMember can be partial, need to fetch if so\n\t\t\t\t\tif (!oldMember) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Fetch full member if partial\n\t\t\t\t\tlet fullOldMember = oldMember;\n\t\t\t\t\tif (oldMember.partial) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tfullOldMember = await oldMember.fetch();\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\treturn; // Can't compare without full member data\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst { added, removed } = diffMemberRoles(\n\t\t\t\t\t\tfullOldMember as GuildMember,\n\t\t\t\t\t\tnewMember,\n\t\t\t\t\t);\n\t\t\t\t\tif (added.length === 0 && removed.length === 0) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst audit = await fetchAuditEntry(\n\t\t\t\t\t\tnewMember.guild,\n\t\t\t\t\t\tAuditLogEvent.MemberRoleUpdate,\n\t\t\t\t\t\tnewMember.id,\n\t\t\t\t\t\tthis.runtime,\n\t\t\t\t\t);\n\n\t\t\t\t\t// Skip if bot made this change\n\t\t\t\t\tconst clientUser = this.client?.user;\n\t\t\t\t\tif (\n\t\t\t\t\t\taudit?.executorId &&\n\t\t\t\t\t\tclientUser &&\n\t\t\t\t\t\taudit.executorId === clientUser.id\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.runtime.emitEvent(DiscordEventTypes.MEMBER_ROLES_CHANGED, {\n\t\t\t\t\t\truntime: this.runtime,\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\tguild: { id: newMember.guild.id, name: newMember.guild.name },\n\t\t\t\t\t\tmember: { id: newMember.id, tag: newMember.user.tag },\n\t\t\t\t\t\tadded: added.map((r: DiscordRole) => ({\n\t\t\t\t\t\t\tid: r.id,\n\t\t\t\t\t\t\tname: r.name,\n\t\t\t\t\t\t\tpermissions: r.permissions.toArray(),\n\t\t\t\t\t\t})),\n\t\t\t\t\t\tremoved: removed.map((r: DiscordRole) => ({\n\t\t\t\t\t\t\tid: r.id,\n\t\t\t\t\t\t\tname: r.name,\n\t\t\t\t\t\t\tpermissions: r.permissions.toArray(),\n\t\t\t\t\t\t})),\n\t\t\t\t\t\taudit,\n\t\t\t\t\t} as EventPayload);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Error in guildMemberUpdate handler\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Role creation\n\t\t\tthis.client.on(\"roleCreate\", async (role) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst audit = await fetchAuditEntry(\n\t\t\t\t\t\trole.guild,\n\t\t\t\t\t\tAuditLogEvent.RoleCreate,\n\t\t\t\t\t\trole.id,\n\t\t\t\t\t\tthis.runtime,\n\t\t\t\t\t);\n\n\t\t\t\t\t// Skip if bot made this change\n\t\t\t\t\tconst clientUser = this.client?.user;\n\t\t\t\t\tif (\n\t\t\t\t\t\taudit?.executorId &&\n\t\t\t\t\t\tclientUser &&\n\t\t\t\t\t\taudit.executorId === clientUser.id\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.runtime.emitEvent(DiscordEventTypes.ROLE_CREATED, {\n\t\t\t\t\t\truntime: this.runtime,\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\tguild: { id: role.guild.id, name: role.guild.name },\n\t\t\t\t\t\trole: {\n\t\t\t\t\t\t\tid: role.id,\n\t\t\t\t\t\t\tname: role.name,\n\t\t\t\t\t\t\tpermissions: role.permissions.toArray(),\n\t\t\t\t\t\t},\n\t\t\t\t\t\taudit,\n\t\t\t\t\t} as EventPayload);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Error in roleCreate handler\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Role deletion\n\t\t\tthis.client.on(\"roleDelete\", async (role) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst audit = await fetchAuditEntry(\n\t\t\t\t\t\trole.guild,\n\t\t\t\t\t\tAuditLogEvent.RoleDelete,\n\t\t\t\t\t\trole.id,\n\t\t\t\t\t\tthis.runtime,\n\t\t\t\t\t);\n\n\t\t\t\t\t// Skip if bot made this change\n\t\t\t\t\tconst clientUser = this.client?.user;\n\t\t\t\t\tif (\n\t\t\t\t\t\taudit?.executorId &&\n\t\t\t\t\t\tclientUser &&\n\t\t\t\t\t\taudit.executorId === clientUser.id\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.runtime.emitEvent(DiscordEventTypes.ROLE_DELETED, {\n\t\t\t\t\t\truntime: this.runtime,\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\tguild: { id: role.guild.id, name: role.guild.name },\n\t\t\t\t\t\trole: {\n\t\t\t\t\t\t\tid: role.id,\n\t\t\t\t\t\t\tname: role.name,\n\t\t\t\t\t\t\tpermissions: role.permissions.toArray(),\n\t\t\t\t\t\t},\n\t\t\t\t\t\taudit,\n\t\t\t\t\t} as EventPayload);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Error in roleDelete handler\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\t\t} // end if (isAuditLogEnabled)\n\t}\n\n\t/**\n\t * Handles the event when a new member joins a guild.\n\t *\n\t * **Event Design Note:**\n\t * We intentionally do NOT emit the standardized `EventType.ENTITY_JOINED` here.\n\t * In ElizaOS's abstraction model:\n\t * - A Discord \"guild\" maps to a \"world\" (the server/community)\n\t * - A Discord \"channel\" maps to a \"room\" (a specific conversation space)\n\t *\n\t * `EventType.ENTITY_JOINED` requires a `roomId` because the bootstrap plugin's\n\t * handler calls `syncSingleUser()` to sync the entity to a specific room. When\n\t * a member joins a guild, they've joined the \"world\" but haven't joined any\n\t * specific \"room\" yet - they're just a potential participant.\n\t *\n\t * The entity will be properly synced to rooms when they first interact:\n\t * - First message in a channel → message handler calls `ensureConnection()`\n\t * - Joining a voice channel → voice handler syncs them to that room\n\t *\n\t * We still emit the Discord-specific `DiscordEventTypes.ENTITY_JOINED` so that\n\t * Discord-aware plugins can react to guild member joins (e.g., welcome messages,\n\t * role assignment, moderation checks).\n\t *\n\t * @param {GuildMember} member - The GuildMember object representing the new member.\n\t * @returns {Promise<void>} - A Promise that resolves once the event handling is complete.\n\t * @private\n\t */\n\tprivate async handleGuildMemberAdd(member: GuildMember) {\n\t\tthis.runtime.logger.info(\n\t\t\t`New member joined: ${member.user.username} (${member.id})`,\n\t\t);\n\n\t\tconst guild = member.guild;\n\n\t\tconst tag = member.user.bot\n\t\t\t? `${member.user.username}#${member.user.discriminator}`\n\t\t\t: member.user.username;\n\n\t\tconst worldId = createUniqueUuid(this.runtime, guild.id);\n\t\tconst entityId = createUniqueUuid(this.runtime, member.id);\n\n\t\t// Emit Discord-specific event for plugins that want to handle guild member joins.\n\t\t// This is NOT the standardized EventType.ENTITY_JOINED because:\n\t\t// 1. ENTITY_JOINED requires a roomId (which channel did they join?)\n\t\t// 2. Guild membership != room membership; users join rooms when they interact\n\t\t// 3. The bootstrap handler would fail without roomId anyway\n\t\t// Discord-aware plugins can listen to DiscordEventTypes.ENTITY_JOINED instead.\n\t\tthis.runtime.emitEvent([DiscordEventTypes.ENTITY_JOINED], {\n\t\t\truntime: this.runtime,\n\t\t\tentityId,\n\t\t\tworldId,\n\t\t\tsource: \"discord\",\n\t\t\tmetadata: {\n\t\t\t\ttype: member.user.bot ? \"bot\" : \"user\",\n\t\t\t\toriginalId: member.id,\n\t\t\t\tusername: tag,\n\t\t\t\tdisplayName: member.displayName || member.user.username,\n\t\t\t\troles: member.roles.cache.map((r) => r.name),\n\t\t\t\tjoinedAt: member.joinedAt?.getTime\n\t\t\t\t\t? member.joinedAt.getTime()\n\t\t\t\t\t: undefined,\n\t\t\t},\n\t\t\tmember, // Include raw Discord.js member for Discord-specific handling\n\t\t} as EventPayload);\n\t}\n\n\t/**\n\t * Registers slash commands with Discord.\n\t *\n\t * This method uses a hybrid permission system that combines:\n\t * 1. Discord's native permission features (default_member_permissions, contexts)\n\t * 2. ElizaOS channel whitelist bypass (bypassChannelWhitelist flag)\n\t * 3. Custom validation functions (validator callback)\n\t *\n\t * ## Design Decisions\n\t *\n\t * ### Why Hybrid Approach?\n\t * - Discord's native permissions are powerful but limited to role-based access\n\t * - ElizaOS needs programmatic control for channel restrictions and custom logic\n\t * - Combining both gives developers the best of both worlds\n\t *\n\t * ### Why Transform Simple Flags?\n\t * - Developer experience: `guildOnly: true` is clearer than `contexts: [0]`\n\t * - Abstraction: Shields developers from Discord API changes\n\t * - Sensible defaults: Zero config should \"just work\"\n\t *\n\t * ### Why Three Registration Categories?\n\t *\n\t * Commands are categorized based on where they should be available:\n\t *\n\t * 1. **Global commands** (no guildOnly, no guildIds):\n\t * - Registered globally via `application.commands.set()` for DM access\n\t * - ALSO registered per-guild for instant availability in guilds\n\t * - Guild version overrides global (no duplicates shown in Discord)\n\t * - Best of both worlds: instant in guilds + works in DMs\n\t *\n\t * 2. **Guild-only commands** (guildOnly: true or contexts: [0]):\n\t * - Registered per-guild via `application.commands.set(cmds, guildId)`\n\t * - NOT available in DMs (correct behavior)\n\t * - Instant availability in guilds\n\t * - New guilds get commands via guildCreate event\n\t *\n\t * 3. **Targeted commands** (has guildIds array):\n\t * - Registered only to specified guilds via `.create()` or `.edit()`\n\t * - Useful for testing or server-specific features\n\t * - Instant updates\n\t *\n\t * ### Why Register Global Commands Both Globally AND Per-Guild?\n\t * - Global registration alone takes up to 1 hour to propagate (Discord limitation)\n\t * - Per-guild registration gives instant availability\n\t * - Guild commands override global ones in that guild (no duplicates)\n\t * - Global registration still needed for DM access (no guild context in DMs)\n\t *\n\t * ### Why Not Register Everything Per-Guild Only?\n\t * - Commands that work in DMs MUST be registered globally\n\t * - There's no guild context in DMs, so per-guild commands don't appear there\n\t *\n\t * @param commands - Array of slash commands to register\n\t * @returns Promise that resolves when registration is complete\n\t * @private\n\t */\n\tprivate async registerSlashCommands(\n\t\tcommands: DiscordSlashCommand[],\n\t): Promise<void> {\n\t\t// Wait for the client to be ready before processing\n\t\tawait this.clientReadyPromise;\n\n\t\t// Helper function to sanitize commands for logging (converts BigInt to string)\n\t\tconst sanitizeCommandForLogging = (\n\t\t\tcmd: DiscordSlashCommand,\n\t\t): Record<string, unknown> => {\n\t\t\tconst sanitized: Record<string, unknown> = {\n\t\t\t\tname: cmd.name,\n\t\t\t\tdescription: cmd.description,\n\t\t\t\toptions: cmd.options,\n\t\t\t\tcontexts: cmd.contexts,\n\t\t\t\tguildOnly: cmd.guildOnly,\n\t\t\t\tbypassChannelWhitelist: cmd.bypassChannelWhitelist,\n\t\t\t\tvalidator: cmd.validator ? \"[Function]\" : undefined,\n\t\t\t};\n\n\t\t\tif (cmd.requiredPermissions !== undefined) {\n\t\t\t\tsanitized.requiredPermissions =\n\t\t\t\t\ttypeof cmd.requiredPermissions === \"bigint\"\n\t\t\t\t\t\t? cmd.requiredPermissions.toString()\n\t\t\t\t\t\t: cmd.requiredPermissions;\n\t\t\t}\n\n\t\t\tif (cmd.guildIds) {\n\t\t\t\tsanitized.guildIds = cmd.guildIds;\n\t\t\t}\n\n\t\t\treturn sanitized;\n\t\t};\n\n\t\t// Sanitize commands for logging to handle BigInt values\n\t\tconst sanitizedCommands = commands.map(sanitizeCommandForLogging);\n\t\tthis.runtime.logger.debug(\n\t\t\t{\n\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\tcommandCount: commands.length,\n\t\t\t\tcommands: sanitizedCommands,\n\t\t\t},\n\t\t\t\"Registering Discord commands\",\n\t\t);\n\n\t\tconst clientApplication = this.client?.application;\n\t\tif (!clientApplication) {\n\t\t\tthis.runtime.logger.warn(\n\t\t\t\t{ src: \"plugin:discord\", agentId: this.runtime.agentId },\n\t\t\t\t\"Cannot register commands - Discord client application not available\",\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!Array.isArray(commands) || commands.length === 0) {\n\t\t\tthis.runtime.logger.warn(\n\t\t\t\t{ src: \"plugin:discord\", agentId: this.runtime.agentId },\n\t\t\t\t\"Cannot register commands - no commands provided\",\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// Validate all commands\n\t\tfor (const cmd of commands) {\n\t\t\tif (!cmd.name || !cmd.description) {\n\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tcommand: sanitizeCommandForLogging(cmd),\n\t\t\t\t\t},\n\t\t\t\t\t\"Cannot register commands - invalid command (missing name or description)\",\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Queue this registration to prevent race conditions\n\t\tlet registrationError: Error | null = null;\n\t\tlet registrationFailed = false;\n\n\t\tthis.commandRegistrationQueue = this.commandRegistrationQueue\n\t\t\t.then(async () => {\n\t\t\t\t// Deduplicate commands by name: merge existing and incoming commands into a map\n\t\t\t\t// Incoming commands override existing ones with the same name\n\t\t\t\tconst commandMap = new Map<string, DiscordSlashCommand>();\n\n\t\t\t\tfor (const cmd of this.slashCommands) {\n\t\t\t\t\tif (cmd.name) {\n\t\t\t\t\t\tcommandMap.set(cmd.name, cmd);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (const cmd of commands) {\n\t\t\t\t\tif (cmd.name) {\n\t\t\t\t\t\tcommandMap.set(cmd.name, cmd);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tthis.slashCommands = Array.from(commandMap.values());\n\n\t\t\t\t// Rebuild allowAllSlashCommands from the final merged commands\n\t\t\t\t// This ensures the Set always reflects the authoritative command definitions\n\t\t\t\t// (handles cases where a command is re-registered without the bypass flag)\n\t\t\t\tthis.allowAllSlashCommands.clear();\n\t\t\t\tfor (const cmd of this.slashCommands) {\n\t\t\t\t\tif (cmd.bypassChannelWhitelist) {\n\t\t\t\t\t\tthis.allowAllSlashCommands.add(cmd.name);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tbypassCommands: Array.from(this.allowAllSlashCommands),\n\t\t\t\t\t},\n\t\t\t\t\t\"[DiscordService] Rebuilt bypassChannelWhitelist set from merged commands\",\n\t\t\t\t);\n\n\t\t\t\t// Categorize commands for appropriate registration strategy:\n\t\t\t\t//\n\t\t\t\t// generalCommands: Commands without specific guildIds (most commands)\n\t\t\t\t// ├── globalCommands: Can work in DMs → register globally\n\t\t\t\t// └── guildOnlyCommands: Guild-only → register per-guild for instant availability\n\t\t\t\t//\n\t\t\t\t// targetedGuildCommands: Commands with specific guildIds → register only to those guilds\n\t\t\t\tconst generalCommands = this.slashCommands.filter(\n\t\t\t\t\t(cmd) => !cmd.guildIds || cmd.guildIds.length === 0,\n\t\t\t\t);\n\t\t\t\tconst globalCommands = generalCommands.filter(\n\t\t\t\t\t(cmd) => !this.isGuildOnlyCommand(cmd),\n\t\t\t\t);\n\t\t\t\tconst guildOnlyCommands = generalCommands.filter((cmd) =>\n\t\t\t\t\tthis.isGuildOnlyCommand(cmd),\n\t\t\t\t);\n\t\t\t\tconst targetedGuildCommands = this.slashCommands.filter(\n\t\t\t\t\t(cmd) => cmd.guildIds && cmd.guildIds.length > 0,\n\t\t\t\t);\n\n\t\t\t\tconst transformedGlobalCommands = globalCommands.map((cmd) =>\n\t\t\t\t\tthis.transformCommandToDiscordApi(cmd),\n\t\t\t\t);\n\t\t\t\tconst transformedGuildOnlyCommands = guildOnlyCommands.map((cmd) =>\n\t\t\t\t\tthis.transformCommandToDiscordApi(cmd),\n\t\t\t\t);\n\t\t\t\t// All general commands (global + guild-only) for per-guild registration\n\t\t\t\tconst transformedAllGeneralCommands = [\n\t\t\t\t\t...transformedGlobalCommands,\n\t\t\t\t\t...transformedGuildOnlyCommands,\n\t\t\t\t];\n\n\t\t\t\tconst clientApplication = this.client?.application;\n\t\t\t\tif (!clientApplication) {\n\t\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t\t{ src: \"plugin:discord\", agentId: this.runtime.agentId },\n\t\t\t\t\t\t\"Cannot register commands - Discord client application is not available\",\n\t\t\t\t\t);\n\t\t\t\t\tthrow new Error(\"Discord client application is not available\");\n\t\t\t\t}\n\n\t\t\t\tlet globalCommandsRegistered = false;\n\t\t\t\tlet perGuildSucceeded = 0;\n\t\t\t\tlet perGuildFailed = 0;\n\t\t\t\tlet targetedCommandsRegistered = 0;\n\t\t\t\tlet targetedCommandsFailed = 0;\n\n\t\t\t\t// 1. Register global commands globally (for DM access)\n\t\t\t\t// DMs require global registration - there's no guild context.\n\t\t\t\t// Global commands take up to 1 hour to propagate (Discord limitation),\n\t\t\t\t// but we also register them per-guild below for instant availability.\n\t\t\t\t// Always call .set() even with empty array to clear stale global commands\n\t\t\t\t// (e.g., when all commands become guild-only).\n\t\t\t\ttry {\n\t\t\t\t\tawait this.client.application.commands.set(transformedGlobalCommands);\n\t\t\t\t\tglobalCommandsRegistered = true;\n\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\tcount: transformedGlobalCommands.length,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttransformedGlobalCommands.length > 0\n\t\t\t\t\t\t\t? \"Global commands registered (for DM access)\"\n\t\t\t\t\t\t\t: \"Global commands cleared (all commands are now guild-only)\",\n\t\t\t\t\t);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Failed to register/clear global commands\",\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// 2. Register ALL general commands per-guild for instant availability\n\t\t\t\t// Why both global AND guild-only?\n\t\t\t\t// - Guild-only commands: Don't work in DMs, so per-guild is the only option\n\t\t\t\t// - Global commands: Also registered per-guild for INSTANT availability in guilds\n\t\t\t\t// (guild commands override global ones, so no duplicates are shown)\n\t\t\t\t// This gives us the best of both worlds:\n\t\t\t\t// - Instant availability in current guilds\n\t\t\t\t// - DM access via global registration (step 1)\n\t\t\t\t// - New guilds get commands via guildCreate event\n\t\t\t\t// Parallel registration for performance.\n\t\t\t\tconst guilds = this.client.guilds.cache;\n\n\t\t\t\tif (transformedAllGeneralCommands.length > 0) {\n\t\t\t\t\tconst guildRegistrations: Promise<{\n\t\t\t\t\t\tguildId: string;\n\t\t\t\t\t\tguildName: string;\n\t\t\t\t\t\tsuccess: boolean;\n\t\t\t\t\t}>[] = [];\n\n\t\t\t\t\tfor (const [guildId, guild] of guilds) {\n\t\t\t\t\t\tguildRegistrations.push(\n\t\t\t\t\t\t\tthis.client.application.commands\n\t\t\t\t\t\t\t\t.set(transformedAllGeneralCommands, guildId)\n\t\t\t\t\t\t\t\t.then(() => {\n\t\t\t\t\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\t\t\t\tguildId,\n\t\t\t\t\t\t\t\t\t\t\tguildName: guild.name,\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\"Commands registered to guild\",\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\treturn { guildId, guildName: guild.name, success: true };\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.catch((err) => {\n\t\t\t\t\t\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\t\t\t\tguildId,\n\t\t\t\t\t\t\t\t\t\t\tguildName: guild.name,\n\t\t\t\t\t\t\t\t\t\t\terror: err.message,\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\"Failed to register commands to guild\",\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\treturn { guildId, guildName: guild.name, success: false };\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst perGuildResults = await Promise.all(guildRegistrations);\n\t\t\t\t\tperGuildSucceeded = perGuildResults.filter((r) => r.success).length;\n\t\t\t\t\tperGuildFailed = perGuildResults.filter((r) => !r.success).length;\n\t\t\t\t}\n\n\t\t\t\t// 3. Register targeted guild commands (commands with specific guildIds)\n\t\t\t\t// Why individual registration? These commands only go to specific guilds,\n\t\t\t\t// so we use .create() or .edit() to add them individually rather than\n\t\t\t\t// replacing all commands in those guilds.\n\t\t\t\tif (targetedGuildCommands.length > 0) {\n\t\t\t\t\tconst targetedRegistrations: Promise<void>[] = [];\n\n\t\t\t\t\tfor (const cmd of targetedGuildCommands) {\n\t\t\t\t\t\tconst transformedCmd = this.transformCommandToDiscordApi(cmd);\n\t\t\t\t\t\tif (cmd.guildIds) {\n\t\t\t\t\t\t\tfor (const guildId of cmd.guildIds) {\n\t\t\t\t\t\t\t\tconst guild = guilds.get(guildId);\n\t\t\t\t\t\t\t\tif (!guild) {\n\t\t\t\t\t\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\t\t\t\tcommandName: cmd.name,\n\t\t\t\t\t\t\t\t\t\t\tguildId,\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\"Cannot register targeted command - bot is not a member of the specified guild\",\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\ttargetedRegistrations.push(\n\t\t\t\t\t\t\t\t\t(async () => {\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\tconst fullGuild = await guild.fetch();\n\t\t\t\t\t\t\t\t\t\t\tconst existingCommands = await fullGuild.commands.fetch();\n\t\t\t\t\t\t\t\t\t\t\tconst existingCommand = existingCommands.find(\n\t\t\t\t\t\t\t\t\t\t\t\t(c) => c.name === cmd.name,\n\t\t\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\t\t\t\tif (existingCommand) {\n\t\t\t\t\t\t\t\t\t\t\t\tawait existingCommand.edit(\n\t\t\t\t\t\t\t\t\t\t\t\t\ttransformedCmd as Partial<ApplicationCommandData>,\n\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tcommandName: cmd.name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tguildId: fullGuild.id,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tguildName: fullGuild.name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Updated existing targeted command in guild\",\n\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\tawait fullGuild.commands.create(transformedCmd);\n\t\t\t\t\t\t\t\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tcommandName: cmd.name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tguildId: fullGuild.id,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tguildName: fullGuild.name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Registered targeted command in guild\",\n\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\ttargetedCommandsRegistered++;\n\t\t\t\t\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\t\t\t\t\ttargetedCommandsFailed++;\n\t\t\t\t\t\t\t\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\t\t\t\t\t\tcommandName: cmd.name,\n\t\t\t\t\t\t\t\t\t\t\t\t\tguildId,\n\t\t\t\t\t\t\t\t\t\t\t\t\terror:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? error.message\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: String(error),\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"Failed to register targeted command in guild\",\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t})(),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tawait Promise.all(targetedRegistrations);\n\t\t\t\t}\n\n\t\t\t\tthis.runtime.logger.info(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tnewCommands: commands.length,\n\t\t\t\t\t\ttotalCommands: this.slashCommands.length,\n\t\t\t\t\t\tglobalCommands: transformedGlobalCommands.length,\n\t\t\t\t\t\tglobalCommandsRegisteredForDMs: globalCommandsRegistered,\n\t\t\t\t\t\tguildOnlyCommands: transformedGuildOnlyCommands.length,\n\t\t\t\t\t\tcommandsPerGuild: transformedAllGeneralCommands.length,\n\t\t\t\t\t\tguildsSucceeded: perGuildSucceeded,\n\t\t\t\t\t\tguildsFailed: perGuildFailed,\n\t\t\t\t\t\ttargetedCommands: targetedGuildCommands.length,\n\t\t\t\t\t\ttargetedCommandsRegistered,\n\t\t\t\t\t\ttargetedCommandsFailed,\n\t\t\t\t\t},\n\t\t\t\t\t\"Commands registered\",\n\t\t\t\t);\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tregistrationFailed = true;\n\t\t\t\tregistrationError =\n\t\t\t\t\terror instanceof Error ? error : new Error(String(error));\n\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\terror: registrationError.message,\n\t\t\t\t\t},\n\t\t\t\t\t\"Error registering Discord commands\",\n\t\t\t\t);\n\t\t\t});\n\n\t\tawait this.commandRegistrationQueue;\n\n\t\tif (registrationFailed && registrationError) {\n\t\t\tthrow registrationError;\n\t\t}\n\t}\n\n\t/**\n\t * Transforms an ElizaOS slash command to Discord API format.\n\t * This bridges our developer-friendly API with Discord's native requirements.\n\t * @param {DiscordSlashCommand} cmd - The ElizaOS command definition\n\t * @returns {object} Discord API compatible command object\n\t * @private\n\t */\n\tprivate transformCommandToDiscordApi(\n\t\tcmd: DiscordSlashCommand,\n\t): ApplicationCommandDataResolvable {\n\t\t// Build the base command structure that Discord.js expects\n\t\tconst discordCmd: ChatInputApplicationCommandData & {\n\t\t\tcontexts?: number[];\n\t\t\tdefault_member_permissions?: string;\n\t\t} = {\n\t\t\tname: cmd.name,\n\t\t\tdescription: cmd.description,\n\t\t\toptions: cmd.options,\n\t\t};\n\n\t\t// Transform contexts and guildOnly to Discord's contexts array\n\t\t// contexts overrides guildOnly if provided (as documented)\n\t\t// Discord contexts: 0=Guild, 1=BotDM, 2=PrivateChannel\n\t\tif (cmd.contexts) {\n\t\t\t// Allow raw contexts for advanced use cases - takes precedence over guildOnly\n\t\t\tdiscordCmd.contexts = cmd.contexts;\n\t\t} else if (cmd.guildOnly) {\n\t\t\t// Transform guildOnly flag to Discord's contexts array\n\t\t\t// Why: `guildOnly: true` is more intuitive than `contexts: [0]`\n\t\t\tdiscordCmd.contexts = [0]; // 0 = Guild only (no DMs)\n\t\t}\n\n\t\t// Transform requiredPermissions to Discord's default_member_permissions\n\t\t// Why: Leverages Discord's native permission system for role-based access\n\t\t// Discord handles the permission checks before the interaction even fires\n\t\tif (cmd.requiredPermissions !== undefined) {\n\t\t\tdiscordCmd.default_member_permissions =\n\t\t\t\ttypeof cmd.requiredPermissions === \"bigint\"\n\t\t\t\t\t? cmd.requiredPermissions.toString()\n\t\t\t\t\t: cmd.requiredPermissions;\n\t\t}\n\n\t\treturn discordCmd;\n\t}\n\n\t/**\n\t * Checks if a command is guild-only (shouldn't appear in DMs).\n\t *\n\t * A command is considered guild-only if:\n\t * - `contexts: [0]` is set (Discord's native format, where 0 = Guild only)\n\t * - `guildOnly: true` is set AND no contexts override is provided\n\t *\n\t * `contexts` takes precedence over `guildOnly` to be consistent with\n\t * `transformCommandToDiscordApi`. { guildOnly: true, contexts: [0, 1] }\n\t * will correctly enable DM access (not be treated as guild-only).\n\t *\n\t * @param {DiscordSlashCommand} cmd - The command to check\n\t * @returns {boolean} True if the command should only be available in guilds\n\t * @private\n\t */\n\tprivate isGuildOnlyCommand(cmd: DiscordSlashCommand): boolean {\n\t\t// If contexts is provided, it overrides guildOnly (consistent with transformCommandToDiscordApi)\n\t\tif (cmd.contexts) {\n\t\t\t// Guild-only if contexts only includes 0 (Guild)\n\t\t\treturn cmd.contexts.length === 1 && cmd.contexts[0] === 0;\n\t\t}\n\t\t// Fall back to guildOnly flag\n\t\treturn !!cmd.guildOnly;\n\t}\n\n\t/**\n\t * Handles the event when the bot joins a guild. It logs the guild name, fetches additional information about the guild, scans the guild for voice data, creates standardized world data structure, generates unique IDs, and emits events to the runtime.\n\t * @param {Guild} guild - The guild that the bot has joined.\n\t * @returns {Promise<void>} A promise that resolves when the guild creation is handled.\n\t * @private\n\t */\n\tprivate async handleGuildCreate(guild: Guild) {\n\t\tthis.runtime.logger.info(`Joined guild: ${guild.name} (${guild.id})`);\n\t\tconst fullGuild = await guild.fetch();\n\t\t// Disabled automatic voice joining - now controlled by joinVoiceChannel action\n\t\t// this.voiceManager?.scanGuild(guild);\n\n\t\t// Register commands to the newly joined guild\n\t\t// This ensures commands are available immediately when the bot joins a new server\n\t\tconst clientApplication = this.client?.application;\n\t\tif (this.slashCommands.length > 0 && clientApplication) {\n\t\t\ttry {\n\t\t\t\t// 1. General commands (not targeted to specific guilds) - register all of them\n\t\t\t\t// Why register global commands per-guild too?\n\t\t\t\t// - Guild commands override global ones (no duplicates shown)\n\t\t\t\t// - Instant availability vs waiting for global propagation (up to 1 hour)\n\t\t\t\t// - Global registration still needed for DM access (already done at startup)\n\t\t\t\tconst generalCommands = this.slashCommands.filter(\n\t\t\t\t\t(cmd) => !cmd.guildIds || cmd.guildIds.length === 0,\n\t\t\t\t);\n\n\t\t\t\t// 2. Targeted commands that include this guild - these may have been skipped\n\t\t\t\t// during initial registration if the bot wasn't in this guild yet\n\t\t\t\tconst targetedCommandsForThisGuild = this.slashCommands.filter((cmd) =>\n\t\t\t\t\tcmd.guildIds?.includes(fullGuild.id),\n\t\t\t\t);\n\n\t\t\t\t// Combine and deduplicate (in case a command appears in both somehow)\n\t\t\t\tconst commandMap = new Map<string, (typeof this.slashCommands)[0]>();\n\t\t\t\tfor (const cmd of [\n\t\t\t\t\t...generalCommands,\n\t\t\t\t\t...targetedCommandsForThisGuild,\n\t\t\t\t]) {\n\t\t\t\t\tif (cmd.name) {\n\t\t\t\t\t\tcommandMap.set(cmd.name, cmd);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst commandsToRegister = Array.from(commandMap.values());\n\n\t\t\t\tif (commandsToRegister.length > 0) {\n\t\t\t\t\t// Transform to Discord API format (preserves guildOnly, requiredPermissions, contexts)\n\t\t\t\t\tconst discordCommands = commandsToRegister.map((cmd) =>\n\t\t\t\t\t\tthis.transformCommandToDiscordApi(cmd),\n\t\t\t\t\t);\n\n\t\t\t\t\tawait this.client.application.commands.set(\n\t\t\t\t\t\tdiscordCommands,\n\t\t\t\t\t\tfullGuild.id,\n\t\t\t\t\t);\n\t\t\t\t\tthis.runtime.logger.info(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\tguildId: fullGuild.id,\n\t\t\t\t\t\t\tguildName: fullGuild.name,\n\t\t\t\t\t\t\tgeneralCount: generalCommands.length,\n\t\t\t\t\t\t\ttargetedCount: targetedCommandsForThisGuild.length,\n\t\t\t\t\t\t\ttotalCount: discordCommands.length,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Commands registered to newly joined guild\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tguildId: fullGuild.id,\n\t\t\t\t\t\tguildName: fullGuild.name,\n\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t},\n\t\t\t\t\t\"Failed to register commands to newly joined guild\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// Create standardized world data structure\n\t\tconst worldId = createUniqueUuid(this.runtime, fullGuild.id);\n\t\tconst standardizedData = {\n\t\t\truntime: this.runtime,\n\t\t\trooms: await this.buildStandardizedRooms(fullGuild, worldId),\n\t\t\tentities: await this.buildStandardizedUsers(fullGuild),\n\t\t\tworld: {\n\t\t\t\tid: worldId,\n\t\t\t\tname: fullGuild.name,\n\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\tserverId: fullGuild.id,\n\t\t\t\tmetadata: {\n\t\t\t\t\t...buildDiscordWorldMetadata(this.runtime, fullGuild.ownerId),\n\t\t\t\t},\n\t\t\t} as World,\n\t\t\tsource: \"discord\",\n\t\t};\n\n\t\t// Emit both Discord-specific and standardized events with the same data structure\n\t\tthis.runtime.emitEvent([DiscordEventTypes.WORLD_JOINED], {\n\t\t\truntime: this.runtime,\n\t\t\tsource: \"discord\",\n\t\t\tworld: standardizedData.world,\n\t\t\trooms: standardizedData.rooms,\n\t\t\tentities: standardizedData.entities,\n\t\t\tserver: fullGuild,\n\t\t} as EventPayload);\n\n\t\t// Emit standardized event with the same structure as WORLD_CONNECTED\n\t\tthis.runtime.emitEvent([EventType.WORLD_JOINED], standardizedData);\n\t}\n\n\t/**\n\t * Handles interactions created by the user, specifically commands and message components.\n\t * @param {Interaction} interaction - The interaction object received.\n\t * @returns {Promise<void>} A promise that resolves when the interaction is handled.\n\t * @private\n\t */\n\tprivate async handleInteractionCreate(interaction: Interaction) {\n\t\tconst entityId = createUniqueUuid(this.runtime, interaction.user.id);\n\t\t//this.runtime.logger.debug(`User ${interaction.user.id} => entityId ${entityId}`);\n\t\tconst userName = interaction.user.bot\n\t\t\t? `${interaction.user.username}#${interaction.user.discriminator}`\n\t\t\t: interaction.user.username;\n\t\tconst name = interaction.user.displayName;\n\t\tconst interactionChannelId = interaction.channel?.id;\n\t\tconst roomId = createUniqueUuid(\n\t\t\tthis.runtime,\n\t\t\tinteractionChannelId || userName,\n\t\t);\n\n\t\t// can't be null\n\t\tlet type: ChannelType;\n\t\tlet serverId: string | undefined;\n\n\t\tif (interaction.guild) {\n\t\t\tconst guild = await interaction.guild.fetch();\n\t\t\ttype = await this.getChannelType(interaction.channel as Channel);\n\t\t\tif (type === null) {\n\t\t\t\t// usually a forum type post\n\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tchannelId: interactionChannelId,\n\t\t\t\t\t},\n\t\t\t\t\t\"Null channel type for interaction\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tserverId = guild.id;\n\t\t} else {\n\t\t\ttype = ChannelType.DM;\n\t\t\t// really can't be undefined because bootstrap's choice action\n\t\t\tserverId = interactionChannelId;\n\t\t}\n\n\t\tawait this.runtime.ensureConnection({\n\t\t\tentityId,\n\t\t\troomId,\n\t\t\tuserName,\n\t\t\tname,\n\t\t\tsource: \"discord\",\n\t\t\tchannelId: interactionChannelId,\n\t\t\t// Discord snowflake IDs must be converted to UUIDs using stringToUuid()\n\t\t\t// because messageServerId expects a UUID type, not a raw string\n\t\t\tmessageServerId: serverId ? stringToUuid(serverId) : undefined,\n\t\t\ttype,\n\t\t\tworldId: createUniqueUuid(this.runtime, serverId ?? roomId) as UUID,\n\t\t\tworldName: interaction.guild?.name || undefined,\n\t\t\tuserId: interaction.user.id as unknown as UUID,\n\t\t\tmetadata: buildDiscordWorldMetadata(\n\t\t\t\tthis.runtime,\n\t\t\t\tinteraction.guild?.ownerId,\n\t\t\t),\n\t\t});\n\n\t\tif (interaction.isCommand()) {\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tcommandName: interaction.commandName,\n\t\t\t\t\ttype: interaction.commandType,\n\t\t\t\t\tchannelId: interaction.channelId,\n\t\t\t\t\tinGuild: interaction.inGuild(),\n\t\t\t\t},\n\t\t\t\t\"[DiscordService] Slash command received\",\n\t\t\t);\n\n\t\t\ttry {\n\t\t\t\t// can't interaction.deferReply if we want to allow custom apps (showModal)\n\t\t\t\tif (!this.client) {\n\t\t\t\t\treturn; // Skip if client is not available\n\t\t\t\t}\n\t\t\t\tconst slashPayload: DiscordSlashCommandPayload = {\n\t\t\t\t\truntime: this.runtime,\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\tinteraction,\n\t\t\t\t\tclient: this.client,\n\t\t\t\t\tcommands: this.slashCommands,\n\t\t\t\t};\n\t\t\t\tthis.runtime.emitEvent(DiscordEventTypes.SLASH_COMMAND, slashPayload);\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tcommandName: interaction.commandName,\n\t\t\t\t\t},\n\t\t\t\t\t\"[DiscordService] Slash command emitted to runtime\",\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tcommandName: interaction.commandName,\n\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t},\n\t\t\t\t\t\"[DiscordService] Failed to emit slash command\",\n\t\t\t\t);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\tif (interaction.isModalSubmit()) {\n\t\t\t// this modal.id is stored in interaction.customId\n\t\t\tif (!this.client) {\n\t\t\t\treturn; // Skip if client is not available\n\t\t\t}\n\t\t\tconst modalPayload: DiscordSlashCommandPayload = {\n\t\t\t\truntime: this.runtime,\n\t\t\t\tsource: \"discord\",\n\t\t\t\tinteraction,\n\t\t\t\tclient: this.client,\n\t\t\t\tcommands: this.slashCommands,\n\t\t\t};\n\t\t\tthis.runtime.emitEvent(DiscordEventTypes.MODAL_SUBMIT, modalPayload);\n\t\t}\n\n\t\t// Handle message component interactions (buttons, dropdowns, etc.)\n\t\tif (interaction.isMessageComponent()) {\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tcustomId: interaction.customId,\n\t\t\t\t},\n\t\t\t\t\"Received component interaction\",\n\t\t\t);\n\t\t\tconst interactionUser = interaction.user;\n\t\t\tconst userId = interactionUser?.id;\n\t\t\tconst interactionMessage = interaction.message;\n\t\t\tconst messageId = interactionMessage?.id;\n\n\t\t\t// Initialize user's selections if not exists\n\t\t\tif (!this.userSelections.has(userId)) {\n\t\t\t\tthis.userSelections.set(userId, {});\n\t\t\t}\n\t\t\tconst userSelections = this.userSelections.get(userId);\n\t\t\tif (!userSelections) {\n\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tentityId: userId,\n\t\t\t\t\t},\n\t\t\t\t\t\"User selections map unexpectedly missing\",\n\t\t\t\t);\n\t\t\t\treturn; // Should not happen\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\t// For select menus (type 3), store the values\n\t\t\t\tif (interaction.isStringSelectMenu()) {\n\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\tentityId: userId,\n\t\t\t\t\t\t\tcustomId: interaction.customId,\n\t\t\t\t\t\t\tvalues: interaction.values,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Values selected\",\n\t\t\t\t\t);\n\n\t\t\t\t\t// Store values with messageId to scope them to this specific form\n\t\t\t\t\tconst existingSelections =\n\t\t\t\t\t\t(userSelections[messageId] as Record<string, unknown>) || {};\n\t\t\t\t\tuserSelections[messageId] = {\n\t\t\t\t\t\t...existingSelections,\n\t\t\t\t\t\t[interaction.customId]: interaction.values,\n\t\t\t\t\t};\n\t\t\t\t\t// No need to call set again, modification is in place\n\n\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\tmessageId,\n\t\t\t\t\t\t\tselections: userSelections[messageId],\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Current selections for message\",\n\t\t\t\t\t);\n\n\t\t\t\t\t// Acknowledge the selection\n\t\t\t\t\tawait interaction.deferUpdate();\n\t\t\t\t\t// await interaction.followUp({\n\t\t\t\t\t// content: 'Selection saved!',\n\t\t\t\t\t// ephemeral: true,\n\t\t\t\t\t// });\n\t\t\t\t}\n\n\t\t\t\t// For button interactions (type 2), use stored values\n\t\t\t\tif (interaction.isButton()) {\n\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\tentityId: userId,\n\t\t\t\t\t\t\tcustomId: interaction.customId,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Button pressed\",\n\t\t\t\t\t);\n\t\t\t\t\tconst formSelections = userSelections[messageId] || {};\n\n\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\tformSelections,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Form data being submitted\",\n\t\t\t\t\t);\n\n\t\t\t\t\t// Set up fallback acknowledgement after 2.5 seconds if handler doesn't respond\n\t\t\t\t\t// This prevents \"Interaction failed\" errors while still allowing handlers to show modals\n\t\t\t\t\t// Handlers that want to show modals should do so immediately (within 3 seconds)\n\t\t\t\t\tconst fallbackTimeout = setTimeout(async () => {\n\t\t\t\t\t\t// Remove timeout from array after execution to prevent memory leak\n\t\t\t\t\t\tconst index = this.timeouts.indexOf(fallbackTimeout);\n\t\t\t\t\t\tif (index > -1) {\n\t\t\t\t\t\t\tthis.timeouts.splice(index, 1);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Check if interaction has already been handled\n\t\t\t\t\t\tif (!interaction.replied && !interaction.deferred) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait interaction.deferUpdate();\n\t\t\t\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\t\t\tcustomId: interaction.customId,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"Acknowledged button interaction via fallback\",\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} catch (ackError) {\n\t\t\t\t\t\t\t\t// Interaction may have already been acknowledged, expired, or handler responded\n\t\t\t\t\t\t\t\t// This is expected and not an error\n\t\t\t\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\t\t\terror:\n\t\t\t\t\t\t\t\t\t\t\tackError instanceof Error\n\t\t\t\t\t\t\t\t\t\t\t\t? ackError.message\n\t\t\t\t\t\t\t\t\t\t\t\t: String(ackError),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"Fallback acknowledgement skipped\",\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 2500);\n\t\t\t\t\t// Store timeout for cleanup on service stop\n\t\t\t\t\tthis.timeouts.push(fallbackTimeout);\n\n\t\t\t\t\t// Set up a one-time check to clear the timeout early if interaction is acknowledged\n\t\t\t\t\t// This prevents unnecessary timeout execution and reduces memory usage\n\t\t\t\t\tconst earlyCheckTimeout = setTimeout(() => {\n\t\t\t\t\t\tif (interaction.replied || interaction.deferred) {\n\t\t\t\t\t\t\tclearTimeout(fallbackTimeout);\n\t\t\t\t\t\t\t// Remove timeout from array since it's been cleared early\n\t\t\t\t\t\t\tconst index = this.timeouts.indexOf(fallbackTimeout);\n\t\t\t\t\t\t\tif (index > -1) {\n\t\t\t\t\t\t\t\tthis.timeouts.splice(index, 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Remove the early check timeout itself from the array\n\t\t\t\t\t\tconst earlyIndex = this.timeouts.indexOf(earlyCheckTimeout);\n\t\t\t\t\t\tif (earlyIndex > -1) {\n\t\t\t\t\t\t\tthis.timeouts.splice(earlyIndex, 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 2000); // Check once after 2 seconds (before fallback fires)\n\t\t\t\t\t// Store early check timeout for cleanup\n\t\t\t\t\tthis.timeouts.push(earlyCheckTimeout);\n\n\t\t\t\t\t// Emit an event with the interaction data and stored selections\n\t\t\t\t\tconst interactionPayload: EventPayload & {\n\t\t\t\t\t\tinteraction: {\n\t\t\t\t\t\t\tcustomId: string;\n\t\t\t\t\t\t\tcomponentType: number;\n\t\t\t\t\t\t\ttype: number;\n\t\t\t\t\t\t\tuser: string;\n\t\t\t\t\t\t\tmessageId: string;\n\t\t\t\t\t\t\tselections: Record<string, unknown>;\n\t\t\t\t\t\t};\n\t\t\t\t\t\tdiscordInteraction: Interaction;\n\t\t\t\t\t} = {\n\t\t\t\t\t\truntime: this.runtime,\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\tinteraction: {\n\t\t\t\t\t\t\tcustomId: interaction.customId,\n\t\t\t\t\t\t\tcomponentType: interaction.componentType,\n\t\t\t\t\t\t\ttype: interaction.type,\n\t\t\t\t\t\t\tuser: userId,\n\t\t\t\t\t\t\tmessageId,\n\t\t\t\t\t\t\tselections: formSelections as Record<string, unknown>,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdiscordInteraction: interaction,\n\t\t\t\t\t};\n\t\t\t\t\tthis.runtime.emitEvent([\"DISCORD_INTERACTION\"], interactionPayload);\n\n\t\t\t\t\t// Clear selections for this form only\n\t\t\t\t\tdelete userSelections[messageId];\n\t\t\t\t\t// No need to call set again\n\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t{ src: \"plugin:discord\", agentId: this.runtime.agentId, messageId },\n\t\t\t\t\t\t\"Cleared selections for message\",\n\t\t\t\t\t);\n\n\t\t\t\t\t// Fallback timeout acknowledges interaction if handler doesn't.\n\t\t\t\t\t// Modal handlers must respond within 3 seconds.\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t},\n\t\t\t\t\t\"Error handling component interaction\",\n\t\t\t\t);\n\t\t\t\ttry {\n\t\t\t\t\tawait interaction.followUp({\n\t\t\t\t\t\tcontent: \"There was an error processing your interaction.\",\n\t\t\t\t\t\tephemeral: true,\n\t\t\t\t\t});\n\t\t\t\t} catch (followUpError) {\n\t\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\terror:\n\t\t\t\t\t\t\t\tfollowUpError instanceof Error\n\t\t\t\t\t\t\t\t\t? followUpError.message\n\t\t\t\t\t\t\t\t\t: String(followUpError),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Error sending follow-up message\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Builds a standardized list of rooms from Discord guild channels.\n\t *\n\t * @param {Guild} guild The guild to build rooms for.\n\t * @param {UUID} _worldId The ID of the world to associate with the rooms (currently unused in favor of direct channel to room mapping).\n\t * @returns {Promise<Array<{ id: UUID; name: string; type: ChannelType; channelId: string; participants: UUID[] }>>} An array of standardized room objects.\n\t * @private\n\t */\n\tprivate async buildStandardizedRooms(\n\t\tguild: Guild,\n\t\t_worldId: UUID,\n\t): Promise<Room[]> {\n\t\tconst rooms: Room[] = [];\n\n\t\tfor (const [channelId, channel] of guild.channels.cache) {\n\t\t\t// Only process text and voice channels\n\t\t\tif (\n\t\t\t\tchannel.type === DiscordChannelType.GuildText ||\n\t\t\t\tchannel.type === DiscordChannelType.GuildVoice\n\t\t\t) {\n\t\t\t\tconst roomId = createUniqueUuid(this.runtime, channelId);\n\t\t\t\tlet channelType: ChannelType;\n\n\t\t\t\tswitch (channel.type) {\n\t\t\t\t\tcase DiscordChannelType.GuildText:\n\t\t\t\t\t\tchannelType = ChannelType.GROUP;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DiscordChannelType.GuildVoice:\n\t\t\t\t\t\tchannelType = ChannelType.VOICE_GROUP;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tchannelType = ChannelType.GROUP;\n\t\t\t\t}\n\n\t\t\t\t// For text channels, we could potentially get member permissions\n\t\t\t\t// But for performance reasons, keep this light for large guilds\n\t\t\t\tlet participants: UUID[] = [];\n\n\t\t\t\tif (\n\t\t\t\t\tguild.memberCount < 1000 &&\n\t\t\t\t\tchannel.type === DiscordChannelType.GuildText\n\t\t\t\t) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// Only attempt this for smaller guilds\n\t\t\t\t\t\t// Get members with read permissions for this channel\n\t\t\t\t\t\tparticipants = Array.from(guild.members.cache.values())\n\t\t\t\t\t\t\t.filter((member: GuildMember) =>\n\t\t\t\t\t\t\t\tchannel\n\t\t\t\t\t\t\t\t\t.permissionsFor(member)\n\t\t\t\t\t\t\t\t\t?.has(PermissionsBitField.Flags.ViewChannel),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.map((member: GuildMember) =>\n\t\t\t\t\t\t\t\tcreateUniqueUuid(this.runtime, member.id),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\tchannelId: channel.id,\n\t\t\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Failed to get participants for channel\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\trooms.push({\n\t\t\t\t\tid: roomId,\n\t\t\t\t\tname: channel.name,\n\t\t\t\t\ttype: channelType,\n\t\t\t\t\tchannelId: channel.id,\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t/**\n\t\t\t\t\t * Channel topic exposed via metadata for plugin-content-seeder\n\t\t\t\t\t *\n\t\t\t\t\t * WHY: Discord text channels have an optional \"topic\" field (the description\n\t\t\t\t\t * shown at the top of the channel). This is valuable context for content\n\t\t\t\t\t * seeding - it tells us what the channel is actually FOR.\n\t\t\t\t\t *\n\t\t\t\t\t * We expose it in room metadata so plugins don't need Discord-specific code\n\t\t\t\t\t * to access it. This maintains separation of concerns.\n\t\t\t\t\t */\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\ttopic:\n\t\t\t\t\t\t\t\"topic\" in channel ? (channel as TextChannel).topic : undefined,\n\t\t\t\t\t\tparticipants, // Store participants in metadata for backward compatibility\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn rooms;\n\t}\n\n\t/**\n\t * Builds a standardized list of users (entities) from Discord guild members.\n\t * Implements different strategies based on guild size for performance.\n\t *\n\t * @param {Guild} guild - The guild from which to build the user list.\n\t * @returns {Promise<Entity[]>} A promise that resolves with an array of standardized entity objects.\n\t * @private\n\t */\n\tprivate async buildStandardizedUsers(guild: Guild): Promise<Entity[]> {\n\t\tconst entities: Entity[] = [];\n\t\tconst clientUser = this.client?.user;\n\t\tconst botId = clientUser?.id;\n\n\t\t// Strategy based on guild size\n\t\tif (guild.memberCount > 1000) {\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tguildId: guild.id,\n\t\t\t\t\tmemberCount: guild.memberCount.toLocaleString(),\n\t\t\t\t},\n\t\t\t\t\"Using optimized user sync for large guild\",\n\t\t\t);\n\n\t\t\t// For large guilds, prioritize members already in cache + online members\n\t\t\ttry {\n\t\t\t\t// Use cache first\n\t\t\t\tfor (const [, member] of guild.members.cache) {\n\t\t\t\t\tconst tag = member.user.bot\n\t\t\t\t\t\t? `${member.user.username}#${member.user.discriminator}`\n\t\t\t\t\t\t: member.user.username;\n\n\t\t\t\t\tif (member.id !== botId) {\n\t\t\t\t\t\tentities.push({\n\t\t\t\t\t\t\tid: createUniqueUuid(this.runtime, member.id),\n\t\t\t\t\t\t\tnames: Array.from(\n\t\t\t\t\t\t\t\tnew Set(\n\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\tmember.user.username,\n\t\t\t\t\t\t\t\t\t\tmember.displayName,\n\t\t\t\t\t\t\t\t\t\tmember.user.globalName,\n\t\t\t\t\t\t\t\t\t].filter(Boolean) as string[],\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\tmetadata: buildDiscordEntityMetadata(\n\t\t\t\t\t\t\t\tmember.id,\n\t\t\t\t\t\t\t\ttag,\n\t\t\t\t\t\t\t\tmember.displayName || member.user.username,\n\t\t\t\t\t\t\t\tmember.user.globalName ?? undefined,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If cache has very few members, try to get online members\n\t\t\t\tif (entities.length < 100) {\n\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\tguildId: guild.id,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Adding online members\",\n\t\t\t\t\t);\n\t\t\t\t\t// This is a more targeted fetch that is less likely to hit rate limits\n\t\t\t\t\tconst onlineMembers = await guild.members.fetch({ limit: 100 });\n\n\t\t\t\t\tfor (const [, member] of onlineMembers) {\n\t\t\t\t\t\tif (member.id !== botId) {\n\t\t\t\t\t\t\tconst entityId = createUniqueUuid(this.runtime, member.id);\n\t\t\t\t\t\t\t// Avoid duplicates\n\t\t\t\t\t\t\tif (!entities.some((u) => u.id === entityId)) {\n\t\t\t\t\t\t\t\tconst tag = member.user.bot\n\t\t\t\t\t\t\t\t\t? `${member.user.username}#${member.user.discriminator}`\n\t\t\t\t\t\t\t\t\t: member.user.username;\n\n\t\t\t\t\t\t\t\tentities.push({\n\t\t\t\t\t\t\t\t\tid: entityId,\n\t\t\t\t\t\t\t\t\tnames: Array.from(\n\t\t\t\t\t\t\t\t\t\tnew Set(\n\t\t\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t\t\tmember.user.username,\n\t\t\t\t\t\t\t\t\t\t\t\tmember.displayName,\n\t\t\t\t\t\t\t\t\t\t\t\tmember.user.globalName,\n\t\t\t\t\t\t\t\t\t\t\t].filter(Boolean) as string[],\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\t\tmetadata: buildDiscordEntityMetadata(\n\t\t\t\t\t\t\t\t\t\tmember.id,\n\t\t\t\t\t\t\t\t\t\ttag,\n\t\t\t\t\t\t\t\t\t\tmember.displayName || member.user.username,\n\t\t\t\t\t\t\t\t\t\tmember.user.globalName ?? undefined,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tguildId: guild.id,\n\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t},\n\t\t\t\t\t\"Error fetching members\",\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\t// For smaller guilds, we can fetch all members\n\t\t\ttry {\n\t\t\t\tlet members = guild.members.cache;\n\t\t\t\tif (members.size === 0) {\n\t\t\t\t\tmembers = await guild.members.fetch();\n\t\t\t\t}\n\n\t\t\t\tfor (const [, member] of members) {\n\t\t\t\t\tif (member.id !== botId) {\n\t\t\t\t\t\tconst tag = member.user.bot\n\t\t\t\t\t\t\t? `${member.user.username}#${member.user.discriminator}`\n\t\t\t\t\t\t\t: member.user.username;\n\n\t\t\t\t\t\tentities.push({\n\t\t\t\t\t\t\tid: createUniqueUuid(this.runtime, member.id),\n\t\t\t\t\t\t\tnames: Array.from(\n\t\t\t\t\t\t\t\tnew Set(\n\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\tmember.user.username,\n\t\t\t\t\t\t\t\t\t\tmember.displayName,\n\t\t\t\t\t\t\t\t\t\tmember.user.globalName,\n\t\t\t\t\t\t\t\t\t].filter(Boolean) as string[],\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\tmetadata: buildDiscordEntityMetadata(\n\t\t\t\t\t\t\t\tmember.id,\n\t\t\t\t\t\t\t\ttag,\n\t\t\t\t\t\t\t\tmember.displayName || member.user.username,\n\t\t\t\t\t\t\t\tmember.user.globalName ?? undefined,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tguildId: guild.id,\n\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t},\n\t\t\t\t\t\"Error fetching members\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\treturn entities;\n\t}\n\n\t/**\n\t * Handles tasks to be performed once the Discord client is fully ready and connected.\n\t * This includes fetching guilds, scanning for voice data, and emitting connection events.\n\t * @private\n\t * @returns {Promise<void>} A promise that resolves when all on-ready tasks are completed.\n\t */\n\tprivate async onReady(readyClient) {\n\t\tthis.runtime.logger.success(\"Discord client ready\");\n\n\t\t// Initialize slash commands array (empty initially - commands registered via DISCORD_REGISTER_COMMANDS)\n\t\tthis.slashCommands = [];\n\n\t\t/**\n\t\t * DISCORD_REGISTER_COMMANDS event handler\n\t\t *\n\t\t * Delegates to registerSlashCommands() method.\n\t\t *\n\t\t * @param params.commands - Array of commands to register\n\t\t */\n\t\tthis.runtime.registerEvent(\n\t\t\t\"DISCORD_REGISTER_COMMANDS\",\n\t\t\tasync (params: DiscordRegisterCommandsPayload) => {\n\t\t\t\tawait this.registerSlashCommands(params.commands);\n\t\t\t},\n\t\t);\n\n\t\t// Check if audit log tracking is enabled (for permission change events)\n\t\tconst auditLogSettingForInvite = this.runtime.getSetting(\n\t\t\t\"DISCORD_AUDIT_LOG_ENABLED\",\n\t\t);\n\t\tconst isAuditLogEnabledForInvite =\n\t\t\tauditLogSettingForInvite !== \"false\" &&\n\t\t\tauditLogSettingForInvite !== false;\n\n\t\t// Generate invite URL using centralized permission tiers (MODERATOR_VOICE is recommended default)\n\t\t// If DISCORD_AUDIT_LOG_ENABLED, manually grant ViewAuditLog permission per-server after joining.\n\t\tconst readyClientUser = readyClient.user;\n\t\tconst inviteUrl = readyClientUser?.id\n\t\t\t? generateInviteUrl(readyClientUser.id, \"MODERATOR_VOICE\")\n\t\t\t: undefined;\n\n\t\t// Log a note if audit log tracking is enabled\n\t\tif (isAuditLogEnabledForInvite) {\n\t\t\tthis.runtime.logger.info(\n\t\t\t\t{ src: \"plugin:discord\", agentId: this.runtime.agentId },\n\t\t\t\t\"Audit log tracking enabled - ensure bot has ViewAuditLog permission in server settings\",\n\t\t\t);\n\t\t}\n\n\t\t// Use character name if available, otherwise fallback to username, then agentId\n\t\tconst agentName =\n\t\t\tthis.runtime.character.name ||\n\t\t\treadyClientUser?.username ||\n\t\t\tthis.runtime.agentId;\n\n\t\tif (inviteUrl) {\n\t\t\tthis.runtime.logger.info(\n\t\t\t\t{ src: \"plugin:discord\", agentId: this.runtime.agentId, inviteUrl },\n\t\t\t\t\"Bot invite URL generated\",\n\t\t\t);\n\t\t\tthis.runtime.logger.info(\n\t\t\t\t`Use this URL to add the \"${agentName}\" bot to your Discord server: ${inviteUrl}`,\n\t\t\t);\n\t\t} else {\n\t\t\tthis.runtime.logger.warn(\n\t\t\t\t{ src: \"plugin:discord\", agentId: this.runtime.agentId },\n\t\t\t\t\"Could not generate invite URL - bot user ID unavailable\",\n\t\t\t);\n\t\t}\n\n\t\tthis.runtime.logger.success(\n\t\t\t`Discord client logged in successfully as ${readyClientUser?.username || agentName}`,\n\t\t);\n\n\t\tconst guilds = this.client ? await this.client.guilds.fetch() : null;\n\t\tif (!guilds) {\n\t\t\tthis.runtime.logger.warn(\"Could not fetch guilds\");\n\t\t\treturn;\n\t\t}\n\t\tfor (const [, guild] of guilds) {\n\t\t\t// Disabled automatic voice joining - now controlled by joinVoiceChannel action\n\t\t\t// await this.voiceManager?.scanGuild(fullGuild);\n\n\t\t\t// Send after a brief delay\n\t\t\tconst timeoutId = setTimeout(async () => {\n\t\t\t\t// For each server the client is in, fire a connected event\n\t\t\t\ttry {\n\t\t\t\t\tconst fullGuild = await guild.fetch();\n\t\t\t\t\tthis.runtime.logger.info(\n\t\t\t\t\t\t`Discord server connected: ${fullGuild.name} (${fullGuild.id})`,\n\t\t\t\t\t);\n\n\t\t\t\t\t// Create platform-agnostic world data structure with simplified structure\n\t\t\t\t\tconst worldId = createUniqueUuid(this.runtime, fullGuild.id);\n\t\t\t\t\tconst standardizedData = {\n\t\t\t\t\t\tname: fullGuild.name,\n\t\t\t\t\t\truntime: this.runtime,\n\t\t\t\t\t\trooms: await this.buildStandardizedRooms(fullGuild, worldId),\n\t\t\t\t\t\tentities: await this.buildStandardizedUsers(fullGuild),\n\t\t\t\t\t\tworld: {\n\t\t\t\t\t\t\tid: worldId,\n\t\t\t\t\t\t\tname: fullGuild.name,\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\tserverId: fullGuild.id,\n\t\t\t\t\t\t\tmetadata: {\n\t\t\t\t\t\t\t\t...buildDiscordWorldMetadata(this.runtime, fullGuild.ownerId),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t} as World,\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t};\n\n\t\t\t\t\t// Emit Discord-specific event with full guild object\n\t\t\t\t\tthis.runtime.emitEvent([DiscordEventTypes.WORLD_CONNECTED], {\n\t\t\t\t\t\truntime: this.runtime,\n\t\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\t\tworld: standardizedData.world,\n\t\t\t\t\t\trooms: standardizedData.rooms,\n\t\t\t\t\t\tentities: standardizedData.entities,\n\t\t\t\t\t\tserver: fullGuild,\n\t\t\t\t\t} as EventPayload);\n\n\t\t\t\t\t// Emit standardized event\n\t\t\t\t\tthis.runtime.emitEvent([EventType.WORLD_CONNECTED], standardizedData);\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// Add error handling to prevent crashes if the client is already destroyed\n\t\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Error during Discord world connection\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}, 1000);\n\n\t\t\t// Store the timeout reference to be able to cancel it when stopping\n\t\t\tthis.timeouts.push(timeoutId);\n\t\t}\n\n\t\t// Validate audit log access for permission tracking (if enabled)\n\t\tconst auditLogEnabled = this.runtime.getSetting(\n\t\t\t\"DISCORD_AUDIT_LOG_ENABLED\",\n\t\t);\n\t\tif (auditLogEnabled !== \"false\" && auditLogEnabled !== false) {\n\t\t\ttry {\n\t\t\t\tconst testGuild = guilds.first();\n\t\t\t\tif (testGuild) {\n\t\t\t\t\tconst fullGuild = await testGuild.fetch();\n\t\t\t\t\tawait fullGuild.fetchAuditLogs({ limit: 1 });\n\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t\"Audit log access verified for permission tracking\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t},\n\t\t\t\t\t\"Cannot access audit logs - permission change alerts will not include executor info\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif (this.client) {\n\t\t\tthis.client.emit(\"voiceManagerReady\");\n\t\t}\n\t}\n\n\t/**\n\t * Registers send handlers for the Discord service instance.\n\t * This allows the runtime to correctly dispatch messages to this service.\n\t * @param {IAgentRuntime} runtime - The agent runtime instance.\n\t * @param {DiscordService} serviceInstance - The instance of the DiscordService.\n\t * @static\n\t */\n\tstatic registerSendHandlers(\n\t\truntime: IAgentRuntime,\n\t\tserviceInstance: DiscordService,\n\t) {\n\t\tif (serviceInstance) {\n\t\t\truntime.registerSendHandler(\n\t\t\t\t\"discord\",\n\t\t\t\tserviceInstance.handleSendMessage.bind(serviceInstance),\n\t\t\t);\n\t\t\truntime.logger.info(\"Registered send handler\");\n\t\t}\n\t}\n\n\t/**\n\t * Fetches all members who have access to a specific text channel.\n\t *\n\t * @param {string} channelId - The Discord ID of the text channel.\n\t * @param {boolean} [useCache=true] - Whether to prioritize cached data. Defaults to true.\n\t * @returns {Promise<Array<{id: string, username: string, displayName: string}>>} A promise that resolves with an array of channel member objects, each containing id, username, and displayName.\n\t */\n\tpublic async getTextChannelMembers(\n\t\tchannelId: string,\n\t\tuseCache: boolean = true,\n\t): Promise<Array<{ id: string; username: string; displayName: string }>> {\n\t\tthis.runtime.logger.debug(\n\t\t\t{\n\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\tchannelId,\n\t\t\t\tuseCache,\n\t\t\t},\n\t\t\t\"Fetching members for text channel\",\n\t\t);\n\n\t\ttry {\n\t\t\t// Fetch the channel\n\t\t\tconst channel = this.client\n\t\t\t\t? ((await this.client.channels.fetch(channelId)) as TextChannel)\n\t\t\t\t: null;\n\n\t\t\t// Validate channel\n\t\t\tif (!channel) {\n\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t{ src: \"plugin:discord\", agentId: this.runtime.agentId, channelId },\n\t\t\t\t\t\"Channel not found\",\n\t\t\t\t);\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\tif (channel.type !== DiscordChannelType.GuildText) {\n\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t{ src: \"plugin:discord\", agentId: this.runtime.agentId, channelId },\n\t\t\t\t\t\"Channel is not a text channel\",\n\t\t\t\t);\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\tconst guild = channel.guild;\n\t\t\tif (!guild) {\n\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t{ src: \"plugin:discord\", agentId: this.runtime.agentId, channelId },\n\t\t\t\t\t\"Channel is not in a guild\",\n\t\t\t\t);\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\t// Determine strategy based on guild size and cache preference\n\t\t\tconst useCacheOnly = useCache && guild.memberCount > 1000;\n\t\t\tlet members: Collection<string, GuildMember>;\n\n\t\t\tif (useCacheOnly) {\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tguildId: guild.id,\n\t\t\t\t\t\tmemberCount: guild.memberCount.toLocaleString(),\n\t\t\t\t\t},\n\t\t\t\t\t\"Using cached members for large guild\",\n\t\t\t\t);\n\t\t\t\tmembers = guild.members.cache;\n\t\t\t} else {\n\t\t\t\t// For smaller guilds or when cache is not preferred, fetch members\n\t\t\t\ttry {\n\t\t\t\t\tif (useCache && guild.members.cache.size > 0) {\n\t\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\tcacheSize: guild.members.cache.size,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Using cached members\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tmembers = guild.members.cache;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\tguildId: guild.id,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Fetching members for guild\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tmembers = await guild.members.fetch();\n\t\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\tmemberCount: members.size.toLocaleString(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Fetched members\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Error fetching members\",\n\t\t\t\t\t);\n\t\t\t\t\t// Fallback to cache if fetch fails\n\t\t\t\t\tmembers = guild.members.cache;\n\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\tcacheSize: members.size,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Fallback to cache\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Filter members by permission to view the channel\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tchannelId: channel.id,\n\t\t\t\t},\n\t\t\t\t\"Filtering members for channel access\",\n\t\t\t);\n\t\t\t// Explicitly type the array from values()\n\t\t\tconst memberArray: GuildMember[] = Array.from(members.values());\n\t\t\tconst channelMembers = memberArray\n\t\t\t\t.filter((member: GuildMember) => {\n\t\t\t\t\t// Skip bots except our own bot\n\t\t\t\t\t// Add null check for client and client.user\n\t\t\t\t\tconst clientUser = this.client?.user;\n\t\t\t\t\tif (member.user.bot && clientUser && member.id !== clientUser.id) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check if the member can view the channel\n\t\t\t\t\treturn (\n\t\t\t\t\t\tchannel\n\t\t\t\t\t\t\t.permissionsFor(member)\n\t\t\t\t\t\t\t?.has(PermissionsBitField.Flags.ViewChannel) || false\n\t\t\t\t\t);\n\t\t\t\t})\n\t\t\t\t.map((member: GuildMember) => ({\n\t\t\t\t\tid: member.id,\n\t\t\t\t\tusername: member.user.username,\n\t\t\t\t\tdisplayName: member.displayName || member.user.username,\n\t\t\t\t}));\n\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tchannelId: channel.id,\n\t\t\t\t\tmemberCount: channelMembers.length.toLocaleString(),\n\t\t\t\t},\n\t\t\t\t\"Found members with channel access\",\n\t\t\t);\n\t\t\treturn channelMembers;\n\t\t} catch (error) {\n\t\t\tthis.runtime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error fetching channel members\",\n\t\t\t);\n\t\t\treturn [];\n\t\t}\n\t}\n\n\t/**\n\t * Fetches the topic/description of a Discord text channel.\n\t *\n\t * WHY THIS METHOD EXISTS:\n\t * =======================\n\t * Room metadata contains topic from initial sync, but channel topics can change.\n\t * This method lets plugins fetch FRESH topic data directly from Discord API.\n\t *\n\t * Used by plugin-content-seeder to get authoritative topic data for discussion seeding.\n\t *\n\t * WHY NOT JUST USE METADATA:\n\t * Room.metadata.topic is set at sync time and may be stale if the Discord admin\n\t * updates the channel topic. For plugins that care about freshness, this method\n\t * provides a way to get current data.\n\t *\n\t * TRADEOFF: This makes an API call, so it's slower than reading metadata.\n\t * Use metadata for most cases, this method when freshness matters.\n\t *\n\t * @param {string} channelId - The Discord ID of the text channel.\n\t * @returns {Promise<string | null>} The channel topic, or null if not available.\n\t */\n\tpublic async getChannelTopic(channelId: string): Promise<string | null> {\n\t\ttry {\n\t\t\tconst channel = this.client\n\t\t\t\t? await this.client.channels.fetch(channelId)\n\t\t\t\t: null;\n\t\t\tif (channel && \"topic\" in channel) {\n\t\t\t\treturn (channel as TextChannel).topic;\n\t\t\t}\n\t\t\treturn null;\n\t\t} catch (error) {\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tchannelId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Failed to fetch channel topic\",\n\t\t\t);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Generic handler for reaction events (add/remove).\n\t * @private\n\t */\n\tprivate async handleReaction(\n\t\treaction: MessageReaction | PartialMessageReaction,\n\t\tuser: User | PartialUser,\n\t\ttype: \"add\" | \"remove\",\n\t) {\n\t\ttry {\n\t\t\tconst actionVerb = type === \"add\" ? \"added\" : \"removed\";\n\t\t\tconst actionText = type === \"add\" ? \"Added\" : \"Removed\";\n\t\t\tconst preposition = type === \"add\" ? \"to\" : \"from\";\n\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{ src: \"plugin:discord\", agentId: this.runtime.agentId, type },\n\t\t\t\t`Reaction ${actionVerb}`,\n\t\t\t);\n\n\t\t\t// Early returns\n\t\t\tif (!reaction || !user) {\n\t\t\t\tthis.runtime.logger.warn(\"Invalid reaction or user\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Get emoji info\n\t\t\tlet emoji = reaction.emoji.name;\n\t\t\tif (!emoji && reaction.emoji.id) {\n\t\t\t\temoji = `<:${reaction.emoji.name}:${reaction.emoji.id}>`;\n\t\t\t}\n\n\t\t\t// Fetch full message if partial\n\t\t\tif (reaction.partial) {\n\t\t\t\ttry {\n\t\t\t\t\tawait reaction.fetch();\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Failed to fetch partial reaction\",\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Generate IDs with timestamp to ensure uniqueness\n\t\t\tconst timestamp = Date.now();\n\t\t\tconst roomId = createUniqueUuid(\n\t\t\t\tthis.runtime,\n\t\t\t\treaction.message.channel.id,\n\t\t\t);\n\t\t\tconst entityId = createUniqueUuid(this.runtime, user.id);\n\t\t\tconst reactionUUID = createUniqueUuid(\n\t\t\t\tthis.runtime,\n\t\t\t\t`${reaction.message.id}-${user.id}-${emoji}-${timestamp}`,\n\t\t\t);\n\n\t\t\t// Validate IDs\n\t\t\tif (!entityId || !roomId) {\n\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tentityId,\n\t\t\t\t\t\troomId,\n\t\t\t\t\t},\n\t\t\t\t\t\"Invalid user ID or room ID\",\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Process message content\n\t\t\tconst messageContent = reaction.message.content || \"\";\n\t\t\tconst truncatedContent =\n\t\t\t\tmessageContent.length > 50\n\t\t\t\t\t? `${messageContent.substring(0, 50)}...`\n\t\t\t\t\t: messageContent;\n\t\t\tconst reactionMessage = `*${actionText} <${emoji}> ${preposition}: \\\\\"${truncatedContent}\\\\\"*`;\n\n\t\t\t// Get user info from the reacting user (not the message author)\n\t\t\tconst reactionMessageAuthor = reaction.message.author;\n\t\t\tconst userName =\n\t\t\t\t(\"username\" in user && (user as User).username) ||\n\t\t\t\treactionMessageAuthor?.username ||\n\t\t\t\t\"unknown\";\n\t\t\tconst name =\n\t\t\t\t// Prefer any display/global name if present\n\t\t\t\t(\"globalName\" in user && typeof user.globalName === \"string\"\n\t\t\t\t\t? user.globalName\n\t\t\t\t\t: undefined) ||\n\t\t\t\t(reactionMessageAuthor &&\n\t\t\t\t\"displayName\" in reactionMessageAuthor &&\n\t\t\t\ttypeof reactionMessageAuthor.displayName === \"string\"\n\t\t\t\t\t? reactionMessageAuthor.displayName\n\t\t\t\t\t: undefined) ||\n\t\t\t\tuserName;\n\n\t\t\t// Get channel type once and reuse\n\t\t\tconst channelType = await this.getChannelType(\n\t\t\t\treaction.message.channel as Channel,\n\t\t\t);\n\n\t\t\tawait this.runtime.ensureConnection({\n\t\t\t\tentityId,\n\t\t\t\troomId,\n\t\t\t\tuserName,\n\t\t\t\tworldId: createUniqueUuid(\n\t\t\t\t\tthis.runtime,\n\t\t\t\t\treaction.message.guild?.id ?? roomId,\n\t\t\t\t) as UUID,\n\t\t\t\tworldName: reaction.message.guild?.name || undefined,\n\t\t\t\tname,\n\t\t\t\tsource: \"discord\",\n\t\t\t\tchannelId: reaction.message.channel.id,\n\t\t\t\tmessageServerId: reaction.message.guild?.id\n\t\t\t\t\t? stringToUuid(reaction.message.guild.id)\n\t\t\t\t\t: undefined,\n\t\t\t\ttype: channelType,\n\t\t\t\tuserId: user.id as unknown as UUID,\n\t\t\t\tmetadata: buildDiscordWorldMetadata(\n\t\t\t\t\tthis.runtime,\n\t\t\t\t\treaction.message.guild?.ownerId,\n\t\t\t\t),\n\t\t\t});\n\n\t\t\tconst inReplyTo = createUniqueUuid(this.runtime, reaction.message.id);\n\n\t\t\tconst memory: Memory = {\n\t\t\t\tid: reactionUUID,\n\t\t\t\tentityId,\n\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\tcontent: {\n\t\t\t\t\ttext: reactionMessage,\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\tinReplyTo,\n\t\t\t\t\tchannelType,\n\t\t\t\t},\n\t\t\t\troomId,\n\t\t\t\tcreatedAt: timestamp,\n\t\t\t};\n\n\t\t\tconst callback: HandlerCallback = async (content): Promise<Memory[]> => {\n\t\t\t\tif (!reaction.message.channel) {\n\t\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t\t{ src: \"plugin:discord\", agentId: this.runtime.agentId },\n\t\t\t\t\t\t\"No channel found for reaction message\",\n\t\t\t\t\t);\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t\tawait (reaction.message.channel as TextChannel).send(\n\t\t\t\t\tcontent.text ?? \"\",\n\t\t\t\t);\n\t\t\t\treturn [];\n\t\t\t};\n\n\t\t\t// Emit appropriate events based on type (both Discord-specific and core events)\n\t\t\t// New core only has REACTION_RECEIVED (no REACTION_REMOVED).\n\t\t\t// For forward compat, removals only emit Discord-specific event.\n\t\t\tconst events =\n\t\t\t\ttype === \"add\"\n\t\t\t\t\t? [DiscordEventTypes.REACTION_RECEIVED, EventType.REACTION_RECEIVED]\n\t\t\t\t\t: [DiscordEventTypes.REACTION_REMOVED];\n\n\t\t\tconst reactionPayload: DiscordReactionPayload & EventPayload = {\n\t\t\t\truntime: this.runtime,\n\t\t\t\tmessage: memory,\n\t\t\t\toriginalReaction: reaction as MessageReaction,\n\t\t\t\tuser: user as User,\n\t\t\t\tsource: \"discord\",\n\t\t\t\tcallback,\n\t\t\t};\n\t\t\tthis.runtime.emitEvent(events, reactionPayload);\n\t\t} catch (error) {\n\t\t\tthis.runtime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error handling reaction\",\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Handles reaction addition.\n\t * @private\n\t */\n\tprivate async handleReactionAdd(\n\t\treaction: MessageReaction | PartialMessageReaction,\n\t\tuser: User | PartialUser,\n\t) {\n\t\tawait this.handleReaction(reaction, user, \"add\");\n\t}\n\n\t/**\n\t * Handles reaction removal.\n\t * @private\n\t */\n\tprivate async handleReactionRemove(\n\t\treaction: MessageReaction | PartialMessageReaction,\n\t\tuser: User | PartialUser,\n\t) {\n\t\tawait this.handleReaction(reaction, user, \"remove\");\n\t}\n\n\t/**\n\t * Checks if a channel ID is allowed based on both env config and dynamic additions.\n\t * @param {string} channelId - The channel ID to check\n\t * @returns {boolean} Whether the channel is allowed\n\t */\n\tpublic isChannelAllowed(channelId: string): boolean {\n\t\t// If no restrictions are set, allow all channels\n\t\tif (!this.allowedChannelIds) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Check if channel is in the env-configured list or dynamically added\n\t\treturn (\n\t\t\tthis.allowedChannelIds.includes(channelId) ||\n\t\t\tthis.dynamicChannelIds.has(channelId)\n\t\t);\n\t}\n\n\t/**\n\t * Adds a channel to the dynamic allowed list.\n\t * @param {string} channelId - The channel ID to add\n\t * @returns {boolean} Whether the channel was successfully added\n\t */\n\tpublic addAllowedChannel(channelId: string): boolean {\n\t\t// Validate the channel exists\n\t\tif (!this.client || !this.client.channels.cache.has(channelId)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.dynamicChannelIds.add(channelId);\n\t\treturn true;\n\t}\n\n\t/**\n\t * Removes a channel from the dynamic allowed list.\n\t * @param {string} channelId - The channel ID to remove\n\t * @returns {boolean} Whether the channel was in the list and removed\n\t */\n\tpublic removeAllowedChannel(channelId: string): boolean {\n\t\t// Don't allow removing channels that are in the env config\n\t\tif (this.allowedChannelIds?.includes(channelId)) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn this.dynamicChannelIds.delete(channelId);\n\t}\n\n\t/**\n\t * Gets the list of all allowed channels (env + dynamic).\n\t * @returns {string[]} Array of allowed channel IDs\n\t */\n\tpublic getAllowedChannels(): string[] {\n\t\tconst envChannels = this.allowedChannelIds || [];\n\t\tconst dynamicChannels = Array.from(this.dynamicChannelIds);\n\t\treturn [...new Set([...envChannels, ...dynamicChannels])];\n\t}\n\n\t/**\n\t * Type guard to check if a channel is a guild text-based channel\n\t * @private\n\t */\n\tprivate isGuildTextBasedChannel(\n\t\tchannel: Channel | null,\n\t): channel is GuildTextBasedChannel {\n\t\treturn (\n\t\t\t!!channel &&\n\t\t\t\"isTextBased\" in channel &&\n\t\t\ttypeof channel.isTextBased === \"function\" &&\n\t\t\tchannel.isTextBased() &&\n\t\t\t\"guild\" in channel &&\n\t\t\tchannel.guild !== null\n\t\t);\n\t}\n\n\t/**\n\t * Helper to delay execution\n\t * @private\n\t */\n\tprivate delay(ms: number): Promise<void> {\n\t\treturn new Promise((resolve) => setTimeout(resolve, ms));\n\t}\n\n\t/**\n\t * Get spider state for a channel from the database\n\t * @private\n\t */\n\tprivate async getSpiderState(\n\t\tchannelId: string,\n\t): Promise<ChannelSpiderState | null> {\n\t\ttry {\n\t\t\t// Create a deterministic UUID for this channel's spider state\n\t\t\tconst stateId = createUniqueUuid(\n\t\t\t\tthis.runtime,\n\t\t\t\t`discord-spider-state-${channelId}`,\n\t\t\t);\n\n\t\t\t// Try to get the state memory from the database\n\t\t\tconst stateMemory = await this.runtime.getMemoryById(stateId);\n\n\t\t\tconst stateMemoryContent = stateMemory?.content;\n\t\t\tif (stateMemoryContent?.text) {\n\t\t\t\tconst state = JSON.parse(\n\t\t\t\t\tstateMemory.content.text,\n\t\t\t\t) as ChannelSpiderState;\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tchannelId,\n\t\t\t\t\t\tstate,\n\t\t\t\t\t},\n\t\t\t\t\t\"Loaded spider state from database\",\n\t\t\t\t);\n\t\t\t\treturn state;\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.runtime.logger.warn(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\tchannelId,\n\t\t\t\t},\n\t\t\t\t\"Failed to load spider state from database\",\n\t\t\t);\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * Save spider state for a channel to the database\n\t * @private\n\t */\n\tprivate async saveSpiderState(state: ChannelSpiderState): Promise<void> {\n\t\ttry {\n\t\t\t// Create a deterministic UUID for this channel's spider state\n\t\t\tconst stateId = createUniqueUuid(\n\t\t\t\tthis.runtime,\n\t\t\t\t`discord-spider-state-${state.channelId}`,\n\t\t\t);\n\t\t\tconst roomId = createUniqueUuid(this.runtime, state.channelId);\n\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t`[SpiderState] Saving channel=${state.channelId} stateId=${stateId}`,\n\t\t\t);\n\n\t\t\t// Check if state already exists - if so, delete it first\n\t\t\tlet existing: Memory | null = null;\n\t\t\ttry {\n\t\t\t\texisting = await this.runtime.getMemoryById(stateId);\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t`[SpiderState] getMemoryById: ${existing ? \"EXISTS\" : \"NOT_FOUND\"}`,\n\t\t\t\t);\n\t\t\t} catch (lookupError) {\n\t\t\t\tconst lookupErrorMessage =\n\t\t\t\t\tlookupError instanceof Error\n\t\t\t\t\t\t? lookupError.message\n\t\t\t\t\t\t: String(lookupError);\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t`[SpiderState] getMemoryById error: ${lookupErrorMessage}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (existing) {\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\"[SpiderState] Deleting existing state before insert\",\n\t\t\t\t);\n\t\t\t\ttry {\n\t\t\t\t\tawait this.runtime.deleteMemory(stateId);\n\t\t\t\t\tthis.runtime.logger.debug(\"[SpiderState] Delete successful\");\n\t\t\t\t} catch (deleteError) {\n\t\t\t\t\tconst deleteErrorMessage =\n\t\t\t\t\t\tdeleteError instanceof Error\n\t\t\t\t\t\t\t? deleteError.message\n\t\t\t\t\t\t\t: String(deleteError);\n\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t`[SpiderState] Delete error: ${deleteErrorMessage}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Ensure the world, room, entity, and connection exist before saving\n\t\t\t// This is required because the memories table has foreign key constraints\n\t\t\t// on roomId and entityId\n\t\t\tlet serverId: string | undefined;\n\t\t\tlet worldId: UUID;\n\t\t\tlet channelName = state.channelId;\n\n\t\t\t// Try to get channel info from Discord to get serverId\n\t\t\ttry {\n\t\t\t\tif (this.client?.isReady?.()) {\n\t\t\t\t\tconst channel = await this.client.channels.fetch(state.channelId);\n\t\t\t\t\tif (channel && \"guild\" in channel && channel.guild) {\n\t\t\t\t\t\tserverId = channel.guild.id;\n\t\t\t\t\t\tchannelName =\n\t\t\t\t\t\t\t\"name\" in channel\n\t\t\t\t\t\t\t\t? (channel.name ?? state.channelId)\n\t\t\t\t\t\t\t\t: state.channelId;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// If we can't fetch the channel, use a default serverId\n\t\t\t}\n\n\t\t\t// Create worldId based on serverId or channelId\n\t\t\tworldId = createUniqueUuid(this.runtime, serverId ?? state.channelId);\n\n\t\t\t// Ensure the entity exists (use agent as entity for spider state)\n\t\t\tconst entityId = this.runtime.agentId;\n\t\t\ttry {\n\t\t\t\tconst entity = await this.runtime.getEntityById(entityId);\n\t\t\t\tif (!entity) {\n\t\t\t\t\t// Create the entity for the agent\n\t\t\t\t\tawait this.runtime.createEntity({\n\t\t\t\t\t\tid: entityId,\n\t\t\t\t\t\tnames: [\"Spider\"],\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tmetadata: { source: \"discord-spider\" },\n\t\t\t\t\t});\n\t\t\t\t\tthis.runtime.logger.debug(\"[SpiderState] Created entity for agent\");\n\t\t\t\t}\n\t\t\t} catch (entityError) {\n\t\t\t\t// Entity might already exist (duplicate key), which is fine\n\t\t\t\tconst entityErrorMessage =\n\t\t\t\t\tentityError instanceof Error\n\t\t\t\t\t\t? entityError.message\n\t\t\t\t\t\t: String(entityError);\n\t\t\t\tif (!entityErrorMessage.includes(\"duplicate key\")) {\n\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t`[SpiderState] Entity ensure error: ${entityErrorMessage}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Ensure world exists\n\t\t\ttry {\n\t\t\t\tawait this.runtime.ensureWorldExists({\n\t\t\t\t\tid: worldId,\n\t\t\t\t\tname: serverId\n\t\t\t\t\t\t? `Discord Server ${serverId}`\n\t\t\t\t\t\t: `Spider World ${state.channelId}`,\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tmessageServerId: stringToUuid(serverId ?? state.channelId),\n\t\t\t\t});\n\t\t\t\tthis.runtime.logger.debug(`[SpiderState] World ensured: ${worldId}`);\n\t\t\t} catch (worldError) {\n\t\t\t\tconst worldErrorMessage =\n\t\t\t\t\tworldError instanceof Error ? worldError.message : String(worldError);\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t`[SpiderState] World ensure error: ${worldErrorMessage}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Ensure room exists\n\t\t\ttry {\n\t\t\t\tawait this.runtime.ensureRoomExists({\n\t\t\t\t\tid: roomId,\n\t\t\t\t\tname: channelName,\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\ttype: ChannelType.GROUP,\n\t\t\t\t\tchannelId: state.channelId,\n\t\t\t\t\tmessageServerId: stringToUuid(serverId ?? state.channelId),\n\t\t\t\t\tworldId,\n\t\t\t\t});\n\t\t\t\tthis.runtime.logger.debug(`[SpiderState] Room ensured: ${roomId}`);\n\t\t\t} catch (roomError) {\n\t\t\t\tconst roomErrorMessage =\n\t\t\t\t\troomError instanceof Error ? roomError.message : String(roomError);\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t`[SpiderState] Room ensure error: ${roomErrorMessage}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Ensure participant (connection) exists\n\t\t\ttry {\n\t\t\t\tawait this.runtime.ensureParticipantInRoom(entityId, roomId);\n\t\t\t\tthis.runtime.logger.debug(\"[SpiderState] Participant ensured in room\");\n\t\t\t} catch (participantError) {\n\t\t\t\t// Try addParticipant as fallback\n\t\t\t\ttry {\n\t\t\t\t\tawait this.runtime.addParticipant(entityId, roomId);\n\t\t\t\t\tthis.runtime.logger.debug(\"[SpiderState] Participant added to room\");\n\t\t\t\t} catch {\n\t\t\t\t\tconst participantErrorMessage = participantError?.message\n\t\t\t\t\t\t? participantError.message\n\t\t\t\t\t\t: String(participantError);\n\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t`[SpiderState] Participant ensure error: ${participantErrorMessage}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Create the state memory\n\t\t\tconst stateMemory: Memory = {\n\t\t\t\tid: stateId,\n\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\tentityId,\n\t\t\t\troomId,\n\t\t\t\tcontent: {\n\t\t\t\t\ttext: JSON.stringify(state),\n\t\t\t\t\tsource: \"discord-spider\",\n\t\t\t\t},\n\t\t\t\tmetadata: {\n\t\t\t\t\ttype: MemoryType.CUSTOM,\n\t\t\t\t\tsource: \"discord-spider-state\",\n\t\t\t\t\tchannelId: state.channelId,\n\t\t\t\t\tfullyBackfilled: state.fullyBackfilled,\n\t\t\t\t} satisfies CustomMetadata,\n\t\t\t\tcreatedAt: Date.now(),\n\t\t\t};\n\n\t\t\t// Store in the database\n\t\t\tthis.runtime.logger.debug(\"[SpiderState] Inserting new state\");\n\t\t\tawait this.runtime.createMemory(stateMemory, \"custom\");\n\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t`[SpiderState] Save successful for channel ${state.channelId}`,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\t// Extract the underlying cause from DrizzleQueryError\n\t\t\tconst errorCause =\n\t\t\t\terror &&\n\t\t\t\t(\n\t\t\t\t\terror as {\n\t\t\t\t\t\tcause?: { message?: string; code?: string; detail?: string };\n\t\t\t\t\t}\n\t\t\t\t).cause;\n\t\t\tconst causeMsg =\n\t\t\t\terrorCause?.message || (errorCause ? String(errorCause) : \"\");\n\t\t\tconst causeCode = errorCause?.code || \"\";\n\t\t\tconst causeDetail = errorCause?.detail || \"\";\n\n\t\t\t// Check if this is a duplicate key error\n\t\t\tif (\n\t\t\t\terrorMsg.includes(\"duplicate key\") ||\n\t\t\t\terrorMsg.includes(\"unique constraint\") ||\n\t\t\t\tString(causeMsg).includes(\"duplicate key\") ||\n\t\t\t\tString(causeMsg).includes(\"unique constraint\")\n\t\t\t) {\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\"[SpiderState] Duplicate key - state already saved by another operation\",\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\terror: errorMsg,\n\t\t\t\t\t\tcause: String(causeMsg),\n\t\t\t\t\t\tcauseCode,\n\t\t\t\t\t\tcauseDetail,\n\t\t\t\t\t\tchannelId: state.channelId,\n\t\t\t\t\t},\n\t\t\t\t\t\"Failed to save spider state to database\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Fetches and persists message history from a Discord channel.\n\t * Supports pagination, state tracking, and streaming via callback.\n\t *\n\t * Persistence behavior:\n\t * - When `onBatch` callback is NOT provided: Messages are automatically persisted\n\t * to the database and accumulated in the returned `messages` array.\n\t * - When `onBatch` callback IS provided: Messages are passed to the callback and\n\t * the caller is responsible for persistence. This allows for custom handling.\n\t *\n\t * @param {string} channelId - The Discord channel ID to fetch from\n\t * @param {ChannelHistoryOptions} options - Options for the fetch operation\n\t * @returns {Promise<ChannelHistoryResult>} The result with messages and stats\n\t */\n\tpublic async fetchChannelHistory(\n\t\tchannelId: string,\n\t\toptions: ChannelHistoryOptions = {},\n\t): Promise<ChannelHistoryResult> {\n\t\tif (!this.client || !this.client.isReady || !this.client.isReady()) {\n\t\t\tthis.runtime.logger.warn(\n\t\t\t\t{ src: \"plugin:discord\", agentId: this.runtime.agentId, channelId },\n\t\t\t\t\"Discord client not ready for history fetch\",\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tmessages: [],\n\t\t\t\tstats: { fetched: 0, stored: 0, pages: 0, fullyBackfilled: false },\n\t\t\t};\n\t\t}\n\n\t\t// Fetch the channel\n\t\tconst fetchedChannel = await this.client.channels.fetch(channelId);\n\t\tif (!this.isGuildTextBasedChannel(fetchedChannel)) {\n\t\t\tthis.runtime.logger.warn(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tchannelId,\n\t\t\t\t\tchannelType: fetchedChannel?.type ?? null,\n\t\t\t\t},\n\t\t\t\t\"Channel is not a guild text-based channel\",\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tmessages: [],\n\t\t\t\tstats: { fetched: 0, stored: 0, pages: 0, fullyBackfilled: false },\n\t\t\t};\n\t\t}\n\n\t\tconst channel = fetchedChannel as GuildTextBasedChannel;\n\t\tconst serverId =\n\t\t\t\"guild\" in channel && channel.guild\n\t\t\t\t? channel.guild.id\n\t\t\t\t: \"guildId\" in channel && channel.guildId\n\t\t\t\t\t? channel.guildId\n\t\t\t\t\t: channel.id;\n\t\tconst worldId = serverId\n\t\t\t? createUniqueUuid(this.runtime, serverId)\n\t\t\t: this.runtime.agentId;\n\n\t\t// Ensure world and room exist\n\t\tawait this.runtime.ensureWorldExists({\n\t\t\tid: worldId,\n\t\t\tagentId: this.runtime.agentId,\n\t\t\tmessageServerId: stringToUuid(serverId),\n\t\t\tname: (() => {\n\t\t\t\tconst channelGuild = \"guild\" in channel ? channel.guild : null;\n\t\t\t\treturn channelGuild?.name || \"Discord\";\n\t\t\t})(),\n\t\t});\n\n\t\tawait this.runtime.ensureRoomExists({\n\t\t\tid: createUniqueUuid(this.runtime, channel.id),\n\t\t\tagentId: this.runtime.agentId,\n\t\t\tname: (\"name\" in channel && channel.name) || channel.id,\n\t\t\tsource: \"discord\",\n\t\t\ttype: await this.getChannelType(channel as Channel),\n\t\t\tchannelId: channel.id,\n\t\t\tmessageServerId: stringToUuid(serverId),\n\t\t\tworldId,\n\t\t});\n\n\t\t// Load spider state\n\t\tconst spiderState = options.force\n\t\t\t? null\n\t\t\t: await this.getSpiderState(channelId);\n\t\tconst channelName = (\"name\" in channel && channel.name) || channelId;\n\n\t\tlet consecutiveNoNew = 0;\n\t\tlet totalStored = 0;\n\t\tlet totalFetched = 0;\n\t\tlet pagesProcessed = 0;\n\t\tconst allMessages: Memory[] = [];\n\t\tconst startTime = Date.now();\n\t\t// Track entity IDs we've already ensured connections for (optimization across batches)\n\t\tconst ensuredEntityIds = new Set<string>();\n\n\t\t// Initialize from spider state if available, otherwise from options\n\t\tlet oldestMessageId: string | undefined =\n\t\t\tspiderState?.oldestMessageId ?? options.before;\n\t\tlet newestMessageId: string | undefined =\n\t\t\tspiderState?.newestMessageId ?? options.after;\n\t\tlet oldestMessageTimestamp: number | undefined =\n\t\t\tspiderState?.oldestMessageTimestamp;\n\t\tlet newestMessageTimestamp: number | undefined =\n\t\t\tspiderState?.newestMessageTimestamp;\n\t\tlet reachedEnd = false;\n\n\t\t// Phase 1: If we have previous state, first catch up on new messages\n\t\t// This ensures we don't miss messages that arrived while spider was stopped\n\t\t// We paginate BACKWARD from the present to our known history to avoid\n\t\t// Discord's `after` pagination issues where newest messages are returned first\n\t\tif (!options.force && spiderState && spiderState.newestMessageId) {\n\t\t\tconst lastDate = spiderState.newestMessageTimestamp\n\t\t\t\t? new Date(spiderState.newestMessageTimestamp)\n\t\t\t\t\t\t.toISOString()\n\t\t\t\t\t\t.split(\"T\")[0]\n\t\t\t\t: \"unknown\";\n\t\t\tthis.runtime.logger.info(\n\t\t\t\t`#${channelName}: Catching up on new messages since ${lastDate}`,\n\t\t\t);\n\n\t\t\t// Collect all catch-up batches first (paginating backward from present)\n\t\t\tconst catchUpBatches: Message[][] = [];\n\t\t\tlet catchUpBefore: string | undefined; // Start from present (no before = newest messages)\n\t\t\tlet _catchUpPages = 0;\n\t\t\tlet reachedKnownHistory = false;\n\n\t\t\twhile (!reachedKnownHistory) {\n\t\t\t\t_catchUpPages++;\n\t\t\t\tconst fetchParams: { limit: number; before?: string } = { limit: 100 };\n\t\t\t\tif (catchUpBefore) {\n\t\t\t\t\tfetchParams.before = catchUpBefore;\n\t\t\t\t}\n\n\t\t\t\tconst batch = await channel.messages.fetch(fetchParams);\n\t\t\t\tif (batch.size === 0) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tconst messages = Array.from(\n\t\t\t\t\tbatch.values() as IterableIterator<Message>,\n\t\t\t\t).sort((a, b) => (a.createdTimestamp ?? 0) - (b.createdTimestamp ?? 0));\n\n\t\t\t\t// Check if we've reached or passed our known newest message\n\t\t\t\tconst knownNewestTimestamp = spiderState.newestMessageTimestamp ?? 0;\n\t\t\t\tconst knownNewestId = spiderState.newestMessageId;\n\t\t\t\tconst filteredMessages: Message[] = [];\n\t\t\t\tfor (const msg of messages) {\n\t\t\t\t\tconst msgTimestamp = msg.createdTimestamp ?? 0;\n\t\t\t\t\t// Include messages NEWER than our known newest, OR same timestamp but different ID\n\t\t\t\t\t// This handles the edge case where multiple messages share the same millisecond timestamp\n\t\t\t\t\tif (msgTimestamp > knownNewestTimestamp) {\n\t\t\t\t\t\tfilteredMessages.push(msg);\n\t\t\t\t\t} else if (\n\t\t\t\t\t\tmsgTimestamp === knownNewestTimestamp &&\n\t\t\t\t\t\tmsg.id !== knownNewestId\n\t\t\t\t\t) {\n\t\t\t\t\t\t// Same timestamp but different message - include it (could be a concurrent message)\n\t\t\t\t\t\tfilteredMessages.push(msg);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// We've reached our known history (exact match or older)\n\t\t\t\t\t\treachedKnownHistory = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (filteredMessages.length > 0) {\n\t\t\t\t\tcatchUpBatches.push(filteredMessages);\n\t\t\t\t}\n\n\t\t\t\t// If batch was full and we haven't reached known history, continue backward\n\t\t\t\tif (batch.size < 100 || reachedKnownHistory) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t// Advance backward: get messages before the oldest in current batch\n\t\t\t\tconst batchLast = batch.last();\n\t\t\t\tcatchUpBefore = batchLast?.id;\n\t\t\t\tawait this.delay(250);\n\t\t\t}\n\n\t\t\t// Process catch-up batches in chronological order (oldest first)\n\t\t\t// Reverse because we collected backward (newest batches first)\n\t\t\tcatchUpBatches.reverse();\n\n\t\t\tlet catchUpBatchIndex = 0;\n\t\t\tfor (let messages of catchUpBatches) {\n\t\t\t\tcatchUpBatchIndex++;\n\n\t\t\t\t// Enforce limit by slicing batch if we're close to the limit\n\t\t\t\tif (options.limit) {\n\t\t\t\t\tconst remaining = options.limit - totalFetched;\n\t\t\t\t\tif (remaining <= 0) {\n\t\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\tchannelId,\n\t\t\t\t\t\t\t\tlimit: options.limit,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Reached fetch limit during catch-up\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (messages.length > remaining) {\n\t\t\t\t\t\tmessages = messages.slice(0, remaining);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\ttotalFetched += messages.length;\n\t\t\t\tpagesProcessed++;\n\n\t\t\t\t// Update newest tracking\n\t\t\t\tif (messages.length > 0) {\n\t\t\t\t\tconst lastMsg = messages[messages.length - 1];\n\t\t\t\t\tconst lastTimestamp = lastMsg.createdTimestamp ?? 0;\n\t\t\t\t\tif (\n\t\t\t\t\t\t!newestMessageTimestamp ||\n\t\t\t\t\t\tlastTimestamp > newestMessageTimestamp\n\t\t\t\t\t) {\n\t\t\t\t\t\tnewestMessageId = lastMsg.id;\n\t\t\t\t\t\tnewestMessageTimestamp = lastTimestamp;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Build and process memories, tracking new vs existing\n\t\t\t\tlet catchUpNewCount = 0;\n\t\t\t\tlet catchUpExistingCount = 0;\n\t\t\t\tconst catchUpBatchMemories: Memory[] = [];\n\n\t\t\t\t// Build all memories first\n\t\t\t\tconst allMemories: Memory[] = [];\n\t\t\t\tfor (const discordMessage of messages) {\n\t\t\t\t\tconst memory = await this.buildMemoryFromMessage(discordMessage);\n\t\t\t\t\tif (memory?.id) {\n\t\t\t\t\t\tallMemories.push(memory);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Batch check which memories already exist (single DB query)\n\t\t\t\tif (allMemories.length > 0) {\n\t\t\t\t\tconst memoryIds = allMemories\n\t\t\t\t\t\t.map((m) => m.id)\n\t\t\t\t\t\t.filter((id): id is UUID => id !== undefined);\n\t\t\t\t\tconst existingMemories = await this.runtime.getMemoriesByIds(\n\t\t\t\t\t\tmemoryIds,\n\t\t\t\t\t\t\"messages\",\n\t\t\t\t\t);\n\t\t\t\t\tconst existingIdSet = new Set(existingMemories.map((m) => m.id));\n\n\t\t\t\t\t// Filter to only new memories\n\t\t\t\t\tfor (const memory of allMemories) {\n\t\t\t\t\t\tif (memory.id && existingIdSet.has(memory.id)) {\n\t\t\t\t\t\t\tcatchUpExistingCount++;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcatchUpNewCount++;\n\t\t\t\t\t\t\tcatchUpBatchMemories.push(memory);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Process batch via callback or persist and accumulate\n\t\t\t\tif (options.onBatch) {\n\t\t\t\t\t// Caller handles persistence via callback\n\t\t\t\t\tconst shouldContinue = await options.onBatch(catchUpBatchMemories, {\n\t\t\t\t\t\tpage: pagesProcessed,\n\t\t\t\t\t\ttotalFetched,\n\t\t\t\t\t\ttotalStored: totalStored + catchUpBatchMemories.length,\n\t\t\t\t\t});\n\n\t\t\t\t\t// Assume caller persists all memories when using onBatch\n\t\t\t\t\ttotalStored += catchUpBatchMemories.length;\n\n\t\t\t\t\tif (shouldContinue === false) {\n\t\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\tchannelId,\n\t\t\t\t\t\t\t\tpage: pagesProcessed,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Batch handler requested early stop during catch-up\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Ensure entity connections exist before persisting (prevents FK constraint failures)\n\t\t\t\t\tawait this.ensureConnectionsForMessages(messages, ensuredEntityIds);\n\n\t\t\t\t\t// Persist memories to database, only count successfully persisted\n\t\t\t\t\tconst successfullyPersisted: Memory[] = [];\n\t\t\t\t\tfor (const memory of catchUpBatchMemories) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait this.runtime.createMemory(memory, \"messages\");\n\t\t\t\t\t\t\tsuccessfullyPersisted.push(memory);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\t\tmemoryId: memory.id,\n\t\t\t\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"Failed to persist memory during catch-up\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tallMessages.push(...successfullyPersisted);\n\t\t\t\t\ttotalStored += successfullyPersisted.length;\n\t\t\t\t}\n\n\t\t\t\t// Determine HIT (all existed) or MISS (had new messages)\n\t\t\t\tconst catchUpHitMiss =\n\t\t\t\t\tcatchUpExistingCount > 0 && catchUpNewCount === 0\n\t\t\t\t\t\t? \"HIT\"\n\t\t\t\t\t\t: catchUpNewCount > 0\n\t\t\t\t\t\t\t? \"MISS\"\n\t\t\t\t\t\t\t: \"EMPTY\";\n\n\t\t\t\t// Save progress\n\t\t\t\tawait this.saveSpiderState({\n\t\t\t\t\tchannelId,\n\t\t\t\t\toldestMessageId,\n\t\t\t\t\tnewestMessageId,\n\t\t\t\t\toldestMessageTimestamp,\n\t\t\t\t\tnewestMessageTimestamp,\n\t\t\t\t\tlastSpideredAt: Date.now(),\n\t\t\t\t\tfullyBackfilled: spiderState.fullyBackfilled,\n\t\t\t\t});\n\n\t\t\t\t// Debug log for each catch-up batch\n\t\t\t\tconst newestDate = newestMessageTimestamp\n\t\t\t\t\t? new Date(newestMessageTimestamp).toISOString().split(\"T\")[0]\n\t\t\t\t\t: \"?\";\n\t\t\t\tconst elapsedSec = ((Date.now() - startTime) / 1000).toFixed(1);\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t`#${channelName}: Catch-up batch ${catchUpBatchIndex}/${catchUpBatches.length} [${catchUpHitMiss}], ${messages.length} msgs fetched (${catchUpNewCount} new, ${catchUpExistingCount} existing), ${totalFetched} total fetched, ${totalStored} total stored, newest date ${newestDate} (${elapsedSec}s)`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (catchUpBatches.length > 0) {\n\t\t\t\tthis.runtime.logger.info(\n\t\t\t\t\t`#${channelName}: Caught up ${catchUpBatches.length} batches of new messages`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// Phase 2: Determine backfill direction\n\t\tlet before: string | undefined = options.before;\n\t\tlet after: string | undefined = options.after;\n\n\t\tif (!options.force && spiderState) {\n\t\t\tif (spiderState.fullyBackfilled) {\n\t\t\t\t// Already caught up above, we're done with fetching\n\t\t\t\treachedEnd = true;\n\t\t\t} else {\n\t\t\t\t// Continue backfilling from where we left off\n\t\t\t\tbefore = spiderState.oldestMessageId;\n\t\t\t\tconst oldestDate = spiderState.oldestMessageTimestamp\n\t\t\t\t\t? new Date(spiderState.oldestMessageTimestamp)\n\t\t\t\t\t\t\t.toISOString()\n\t\t\t\t\t\t\t.split(\"T\")[0]\n\t\t\t\t\t: \"unknown\";\n\t\t\t\tthis.runtime.logger.info(\n\t\t\t\t\t`#${channelName}: Resuming backfill from ${oldestDate}`,\n\t\t\t\t);\n\t\t\t}\n\t\t} else if (!spiderState) {\n\t\t\tthis.runtime.logger.info(`#${channelName}: Starting fresh history fetch`);\n\t\t}\n\n\t\t// Phase 3: Backfill older messages (skip if already fully backfilled)\n\t\twhile (!reachedEnd) {\n\t\t\t// Check limit before fetching to avoid unnecessary API calls\n\t\t\tif (options.limit && totalFetched >= options.limit) {\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tchannelId,\n\t\t\t\t\t\tlimit: options.limit,\n\t\t\t\t\t},\n\t\t\t\t\t\"Reached fetch limit before backfill batch\",\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tpagesProcessed += 1;\n\t\t\t// Adjust fetch limit based on remaining quota to avoid exceeding options.limit\n\t\t\tconst remaining = options.limit ? options.limit - totalFetched : 100;\n\t\t\tconst fetchLimit = Math.min(100, remaining);\n\t\t\tconst fetchParams: Record<string, unknown> = { limit: fetchLimit };\n\n\t\t\tif (after) {\n\t\t\t\tfetchParams.after = after;\n\t\t\t} else if (before) {\n\t\t\t\tfetchParams.before = before;\n\t\t\t}\n\n\t\t\tconst batch = await channel.messages.fetch(fetchParams);\n\t\t\tif (batch.size === 0) {\n\t\t\t\treachedEnd = true;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tconst messages = Array.from(batch.values()).sort(\n\t\t\t\t(a, b) => (a.createdTimestamp ?? 0) - (b.createdTimestamp ?? 0),\n\t\t\t);\n\t\t\ttotalFetched += messages.length;\n\n\t\t\t// Track oldest and newest messages by comparing timestamps\n\t\t\tif (messages.length > 0) {\n\t\t\t\tconst firstMsg = messages[0];\n\t\t\t\tconst lastMsg = messages[messages.length - 1];\n\t\t\t\tconst firstTimestamp = firstMsg.createdTimestamp ?? 0;\n\t\t\t\tconst lastTimestamp = lastMsg.createdTimestamp ?? 0;\n\n\t\t\t\t// Update oldest message if this is older than what we have\n\t\t\t\tif (\n\t\t\t\t\t!oldestMessageTimestamp ||\n\t\t\t\t\tfirstTimestamp < oldestMessageTimestamp\n\t\t\t\t) {\n\t\t\t\t\toldestMessageId = firstMsg.id;\n\t\t\t\t\toldestMessageTimestamp = firstTimestamp;\n\t\t\t\t}\n\n\t\t\t\t// Update newest message if this is newer than what we have\n\t\t\t\tif (!newestMessageTimestamp || lastTimestamp > newestMessageTimestamp) {\n\t\t\t\t\tnewestMessageId = lastMsg.id;\n\t\t\t\t\tnewestMessageTimestamp = lastTimestamp;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Build memories for this batch and check if they already exist\n\t\t\tconst batchMemories: Memory[] = [];\n\t\t\tlet newCount = 0;\n\t\t\tlet existingCount = 0;\n\n\t\t\t// Build all memories first\n\t\t\tconst allMemories: Memory[] = [];\n\t\t\tfor (const discordMessage of messages) {\n\t\t\t\tconst memory = await this.buildMemoryFromMessage(discordMessage);\n\t\t\t\tif (memory?.id) {\n\t\t\t\t\tallMemories.push(memory);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Batch check which memories already exist (single DB query)\n\t\t\tif (allMemories.length > 0) {\n\t\t\t\tconst memoryIds = allMemories\n\t\t\t\t\t.map((m) => m.id)\n\t\t\t\t\t.filter((id): id is UUID => id !== undefined);\n\t\t\t\tconst existingMemories = await this.runtime.getMemoriesByIds(\n\t\t\t\t\tmemoryIds,\n\t\t\t\t\t\"messages\",\n\t\t\t\t);\n\t\t\t\tconst existingIdSet = new Set(existingMemories.map((m) => m.id));\n\n\t\t\t\t// Filter to only new memories\n\t\t\t\tfor (const memory of allMemories) {\n\t\t\t\t\tif (memory.id && existingIdSet.has(memory.id)) {\n\t\t\t\t\t\texistingCount++;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnewCount++;\n\t\t\t\t\t\tbatchMemories.push(memory);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Determine HIT (all existed) or MISS (had new messages)\n\t\t\tconst hitMiss =\n\t\t\t\texistingCount > 0 && newCount === 0\n\t\t\t\t\t? \"HIT\"\n\t\t\t\t\t: newCount > 0\n\t\t\t\t\t\t? \"MISS\"\n\t\t\t\t\t\t: \"EMPTY\";\n\n\t\t\t// Process batch via callback or persist and accumulate\n\t\t\tif (options.onBatch) {\n\t\t\t\t// Caller handles persistence via callback\n\t\t\t\tconst shouldContinue = await options.onBatch(batchMemories, {\n\t\t\t\t\tpage: pagesProcessed,\n\t\t\t\t\ttotalFetched,\n\t\t\t\t\ttotalStored: totalStored + batchMemories.length,\n\t\t\t\t});\n\n\t\t\t\t// Assume caller persists all memories when using onBatch\n\t\t\t\ttotalStored += batchMemories.length;\n\n\t\t\t\tif (shouldContinue === false) {\n\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\tchannelId,\n\t\t\t\t\t\t\tpage: pagesProcessed,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Batch handler requested early stop\",\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Ensure entity connections exist before persisting (prevents FK constraint failures)\n\t\t\t\tawait this.ensureConnectionsForMessages(messages, ensuredEntityIds);\n\n\t\t\t\t// Persist memories to database, only count successfully persisted\n\t\t\t\tconst successfullyPersisted: Memory[] = [];\n\t\t\t\tfor (const memory of batchMemories) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.runtime.createMemory(memory, \"messages\");\n\t\t\t\t\t\tsuccessfullyPersisted.push(memory);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\tmemoryId: memory.id,\n\t\t\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Failed to persist memory during backfill\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tallMessages.push(...successfullyPersisted);\n\t\t\t\ttotalStored += successfullyPersisted.length;\n\t\t\t}\n\t\t\tconsecutiveNoNew = batchMemories.length === 0 ? consecutiveNoNew + 1 : 0;\n\n\t\t\t// Save state after every page so we can resume if interrupted\n\t\t\tconst incrementalState: ChannelSpiderState = {\n\t\t\t\tchannelId,\n\t\t\t\toldestMessageId,\n\t\t\t\tnewestMessageId,\n\t\t\t\toldestMessageTimestamp,\n\t\t\t\tnewestMessageTimestamp,\n\t\t\t\tlastSpideredAt: Date.now(),\n\t\t\t\tfullyBackfilled: false, // Not complete yet, still in progress\n\t\t\t};\n\t\t\tawait this.saveSpiderState(incrementalState);\n\n\t\t\t// Debug log for each page\n\t\t\tconst oldestDate = oldestMessageTimestamp\n\t\t\t\t? new Date(oldestMessageTimestamp).toISOString().split(\"T\")[0]\n\t\t\t\t: \"?\";\n\t\t\tconst newestDate = newestMessageTimestamp\n\t\t\t\t? new Date(newestMessageTimestamp).toISOString().split(\"T\")[0]\n\t\t\t\t: \"?\";\n\t\t\tconst elapsedSec = ((Date.now() - startTime) / 1000).toFixed(1);\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t`#${channelName}: Page ${pagesProcessed} [${hitMiss}], ${messages.length} msgs fetched (${newCount} new, ${existingCount} existing), ${batchMemories.length} stored, ${totalFetched} total fetched, ${totalStored} total stored, dates ${oldestDate} to ${newestDate} (${elapsedSec}s)`,\n\t\t\t);\n\n\t\t\t// Log progress every 10 pages (1000 messages) or on first page at info level\n\t\t\tif (pagesProcessed === 1 || pagesProcessed % 10 === 0) {\n\t\t\t\tthis.runtime.logger.info(\n\t\t\t\t\t`#${channelName}: Page ${pagesProcessed}, ${totalFetched} msgs fetched, ${totalStored} stored, dates ${oldestDate} to ${newestDate} (${elapsedSec}s)`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tchannelId,\n\t\t\t\t\tbatchSize: batch.size,\n\t\t\t\t\tstoredThisBatch: batchMemories.length,\n\t\t\t\t\ttotalStored,\n\t\t\t\t\ttotalFetched,\n\t\t\t\t\tpage: pagesProcessed,\n\t\t\t\t},\n\t\t\t\t\"Processed channel history batch\",\n\t\t\t);\n\n\t\t\t// Check stop conditions\n\t\t\tif (options.limit && totalFetched >= options.limit) {\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tchannelId,\n\t\t\t\t\t\tlimit: options.limit,\n\t\t\t\t\t},\n\t\t\t\t\t\"Reached fetch limit\",\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Check if we've reached the actual end of channel history\n\t\t\tif (batch.size < 100) {\n\t\t\t\treachedEnd = true;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Stop if we've hit 3 consecutive pages of existing messages (optimization)\n\t\t\t// But DON'T mark as fullyBackfilled - we may have more older history to fetch\n\t\t\tif (consecutiveNoNew >= 3) {\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t{ src: \"plugin:discord\", agentId: this.runtime.agentId, channelId },\n\t\t\t\t\t\"Stopping backfill: 3 consecutive pages of existing messages (will resume from oldest on next run)\",\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Update pagination cursor using the sorted messages array (oldest-first)\n\t\t\t// This ensures correct cursor advancement regardless of Discord's response order\n\t\t\tif (after) {\n\t\t\t\t// Forward pagination: advance to the newest message we've processed\n\t\t\t\t// Use sorted array: messages[last] = newest after sorting by timestamp\n\t\t\t\tconst lastMessage = messages[messages.length - 1];\n\t\t\t\tafter = lastMessage?.id;\n\t\t\t} else {\n\t\t\t\t// Backward pagination: advance to the oldest message we've processed\n\t\t\t\t// Use sorted array: messages[0] = oldest after sorting by timestamp\n\t\t\t\tconst firstMessage = messages[0];\n\t\t\t\tbefore = firstMessage?.id;\n\t\t\t}\n\n\t\t\t// Rate limiting\n\t\t\tawait this.delay(250);\n\t\t}\n\n\t\t// Update spider state\n\t\tconst newState: ChannelSpiderState = {\n\t\t\tchannelId,\n\t\t\toldestMessageId,\n\t\t\tnewestMessageId,\n\t\t\toldestMessageTimestamp,\n\t\t\tnewestMessageTimestamp,\n\t\t\tlastSpideredAt: Date.now(),\n\t\t\t// Preserve fullyBackfilled if already true, or mark as backfilled if we reached the end going backwards\n\t\t\tfullyBackfilled: spiderState?.fullyBackfilled || (reachedEnd && !after),\n\t\t};\n\t\tawait this.saveSpiderState(newState);\n\n\t\tconst elapsedSec = ((Date.now() - startTime) / 1000).toFixed(1);\n\t\tconst dateRange =\n\t\t\toldestMessageTimestamp && newestMessageTimestamp\n\t\t\t\t? `${new Date(oldestMessageTimestamp).toISOString().split(\"T\")[0]} to ${new Date(newestMessageTimestamp).toISOString().split(\"T\")[0]}`\n\t\t\t\t: \"no messages\";\n\t\tconst status = newState.fullyBackfilled ? \"✓ complete\" : \"↻ partial\";\n\t\tthis.runtime.logger.info(\n\t\t\t`#${channelName}: ${status} - ${totalFetched} msgs, ${pagesProcessed} pages, ${dateRange} (${elapsedSec}s)`,\n\t\t);\n\n\t\treturn {\n\t\t\tmessages: allMessages,\n\t\t\tstats: {\n\t\t\t\tfetched: totalFetched,\n\t\t\t\tstored: totalStored,\n\t\t\t\tpages: pagesProcessed,\n\t\t\t\tfullyBackfilled: newState.fullyBackfilled,\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * Builds a Memory object from a Discord Message.\n\t * This is a reusable helper for converting Discord messages to ElizaOS Memory format.\n\t *\n\t * @param {Message} message - The Discord message to convert\n\t * @param {Object} options - Optional parameters\n\t * @param {string} options.processedContent - Pre-processed text content (if already processed, to avoid double-processing)\n\t * @param {Media[]} options.processedAttachments - Pre-processed attachments (if already processed)\n\t * @param {Object} options.extraContent - Additional content fields to merge into the memory content\n\t * @param {Object} options.extraMetadata - Additional metadata fields to merge into the memory metadata\n\t * @returns {Promise<Memory | null>} The Memory object, or null if the message is invalid\n\t */\n\tpublic async buildMemoryFromMessage(\n\t\tmessage: Message,\n\t\toptions?: {\n\t\t\tprocessedContent?: string;\n\t\t\tprocessedAttachments?: Media[];\n\t\t\textraContent?: Record<string, unknown>;\n\t\t\textraMetadata?: Record<string, unknown>;\n\t\t},\n\t): Promise<Memory | null> {\n\t\tif (!message.author || !message.channel) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst entityId = createUniqueUuid(this.runtime, message.author.id);\n\t\tconst roomId = createUniqueUuid(this.runtime, message.channel.id);\n\t\tconst channel = message.channel;\n\t\tconst channelType = await this.getChannelType(channel as Channel);\n\t\tconst channelGuild = \"guild\" in channel ? channel.guild : null;\n\t\tconst serverId = channelGuild?.id\n\t\t\t? channelGuild.id\n\t\t\t: (message.guild?.id ?? message.channel.id);\n\t\tconst worldId = serverId\n\t\t\t? createUniqueUuid(this.runtime, serverId)\n\t\t\t: this.runtime.agentId;\n\n\t\t// Use pre-processed content if provided, otherwise process now\n\t\tlet textContent: string;\n\t\tlet attachments: Media[];\n\n\t\tconst optionsProcessedContent = options?.processedContent;\n\t\tconst optionsProcessedAttachments = options?.processedAttachments;\n\t\tif (\n\t\t\toptionsProcessedContent !== undefined ||\n\t\t\toptionsProcessedAttachments !== undefined\n\t\t) {\n\t\t\ttextContent = options.processedContent || \" \";\n\t\t\tattachments = options.processedAttachments || [];\n\t\t} else {\n\t\t\tconst processed = this.messageManager\n\t\t\t\t? await this.messageManager.processMessage(message)\n\t\t\t\t: { processedContent: message.content, attachments: [] };\n\n\t\t\tconst processedContent = processed?.processedContent;\n\t\t\ttextContent =\n\t\t\t\tprocessedContent && processedContent.trim().length > 0\n\t\t\t\t\t? processedContent\n\t\t\t\t\t: message.content || \" \";\n\t\t\tattachments = processed?.attachments ?? [];\n\t\t}\n\n\t\tconst metadata = {\n\t\t\ttype: \"custom\" as const,\n\t\t\tentityName:\n\t\t\t\t(message.member &&\n\t\t\t\t\"displayName\" in message.member &&\n\t\t\t\ttypeof message.member.displayName === \"string\"\n\t\t\t\t\t? message.member.displayName\n\t\t\t\t\t: undefined) ??\n\t\t\t\t(\"globalName\" in message.author &&\n\t\t\t\ttypeof message.author.globalName === \"string\"\n\t\t\t\t\t? message.author.globalName\n\t\t\t\t\t: undefined) ??\n\t\t\t\tmessage.author.username,\n\t\t\tfromBot: message.author.bot,\n\t\t\tfromId: message.author.id,\n\t\t\tsourceId: entityId,\n\t\t\t// Raw Discord IDs for cross-agent correlation (not transformed by createUniqueUuid)\n\t\t\tdiscordMessageId: message.id,\n\t\t\tdiscordChannelId: message.channel.id,\n\t\t\tdiscordServerId: (() => {\n\t\t\t\tconst messageChannelGuild =\n\t\t\t\t\t\"guild\" in message.channel ? message.channel.guild : null;\n\t\t\t\treturn messageChannelGuild?.id || message.guild?.id || undefined;\n\t\t\t})(),\n\t\t\ttags: [] as string[],\n\t\t\t...(options?.extraMetadata ? options.extraMetadata : {}),\n\t\t};\n\n\t\tconst memory: Memory = {\n\t\t\tid: createUniqueUuid(this.runtime, message.id),\n\t\t\tentityId,\n\t\t\tagentId: this.runtime.agentId,\n\t\t\troomId,\n\t\t\tcontent: {\n\t\t\t\ttext: textContent || \" \",\n\t\t\t\tattachments,\n\t\t\t\tsource: \"discord\",\n\t\t\t\tchannelType,\n\t\t\t\turl: message.url,\n\t\t\t\tinReplyTo: message.reference?.messageId\n\t\t\t\t\t? createUniqueUuid(this.runtime, message.reference.messageId)\n\t\t\t\t\t: undefined,\n\t\t\t\t...(options?.extraContent ? options.extraContent : {}),\n\t\t\t},\n\t\t\tmetadata: metadata as unknown as Memory[\"metadata\"],\n\t\t\tcreatedAt: message.createdTimestamp ?? Date.now(),\n\t\t\tworldId,\n\t\t};\n\n\t\treturn memory;\n\t}\n\n\t/**\n\t * Ensures entity connections exist for a batch of Discord messages using batch API.\n\t * This should be called before persisting memories to avoid FK constraint failures.\n\t *\n\t * @param {Message[]} messages - The Discord messages to ensure connections for\n\t * @param {Set<string>} ensuredEntityIds - Optional set of already-ensured entity IDs (for caching across batches)\n\t * @returns {Promise<void>}\n\t */\n\tprivate async ensureConnectionsForMessages(\n\t\tmessages: Message[],\n\t\tensuredEntityIds: Set<string> = new Set(),\n\t): Promise<void> {\n\t\tif (messages.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Collect unique authors that haven't been ensured yet\n\t\tconst uniqueAuthors = new Map<string, Message>();\n\t\tfor (const message of messages) {\n\t\t\tif (message.author && !ensuredEntityIds.has(message.author.id)) {\n\t\t\t\tuniqueAuthors.set(message.author.id, message);\n\t\t\t}\n\t\t}\n\n\t\tif (uniqueAuthors.size === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\t// Use the first message to determine room and world (all messages are from the same channel)\n\t\t\tconst firstMessage = messages[0];\n\t\t\tconst channelType = await this.getChannelType(\n\t\t\t\tfirstMessage.channel as Channel,\n\t\t\t);\n\t\t\tconst firstMessageChannelGuild =\n\t\t\t\t\"guild\" in firstMessage.channel ? firstMessage.channel.guild : null;\n\t\t\tconst serverId = firstMessageChannelGuild?.id\n\t\t\t\t? firstMessageChannelGuild.id\n\t\t\t\t: (firstMessage.guild?.id ?? firstMessage.channel.id);\n\t\t\tconst worldId = serverId\n\t\t\t\t? createUniqueUuid(this.runtime, serverId)\n\t\t\t\t: this.runtime.agentId;\n\n\t\t\t// Build entities array for batch API\n\t\t\tconst entities = Array.from(uniqueAuthors.entries()).map(\n\t\t\t\t([authorId, message]) => {\n\t\t\t\t\tconst userName = message.author.username;\n\t\t\t\t\tconst name =\n\t\t\t\t\t\t(message.member &&\n\t\t\t\t\t\t\"displayName\" in message.member &&\n\t\t\t\t\t\ttypeof message.member.displayName === \"string\"\n\t\t\t\t\t\t\t? message.member.displayName\n\t\t\t\t\t\t\t: undefined) ??\n\t\t\t\t\t\t(\"globalName\" in message.author &&\n\t\t\t\t\t\ttypeof message.author.globalName === \"string\"\n\t\t\t\t\t\t\t? message.author.globalName\n\t\t\t\t\t\t\t: undefined) ??\n\t\t\t\t\t\tuserName;\n\t\t\t\t\treturn {\n\t\t\t\t\t\tid: createUniqueUuid(this.runtime, authorId),\n\t\t\t\t\t\tnames: [userName, name].filter(\n\t\t\t\t\t\t\t(n): n is string => typeof n === \"string\" && n.length > 0,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tmetadata: buildDiscordEntityMetadata(authorId, userName, name),\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t);\n\n\t\t\t// Build rooms array (single room for history fetch)\n\t\t\tconst rooms = [\n\t\t\t\t{\n\t\t\t\t\tid: createUniqueUuid(this.runtime, firstMessage.channel.id),\n\t\t\t\t\tchannelId: firstMessage.channel.id,\n\t\t\t\t\ttype: channelType,\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t},\n\t\t\t];\n\n\t\t\t// Build world object\n\t\t\t// For DMs, include channel ID in name for observability when debugging multiple DM worlds\n\t\t\tconst world: WorldCompat = {\n\t\t\t\tid: worldId,\n\t\t\t\tmessageServerId: stringToUuid(serverId),\n\t\t\t\tname: firstMessage.guild?.name ?? `DM-${firstMessage.channel.id}`,\n\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\tmetadata: buildDiscordWorldMetadata(\n\t\t\t\t\tthis.runtime,\n\t\t\t\t\tfirstMessageChannelGuild?.ownerId ??\n\t\t\t\t\t\tfirstMessage.guild?.ownerId ??\n\t\t\t\t\t\tundefined,\n\t\t\t\t),\n\t\t\t};\n\n\t\t\t// Use batch API for efficient database operations\n\t\t\tawait this.runtime.ensureConnections(entities, rooms, \"discord\", world);\n\n\t\t\t// Mark all authors as ensured\n\t\t\tfor (const authorId of uniqueAuthors.keys()) {\n\t\t\t\tensuredEntityIds.add(authorId);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Log but don't fail - the memory creation will fail with a clearer error if needed\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tauthorCount: uniqueAuthors.size,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Failed to ensure batch connections for message authors during history fetch\",\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Stops the Discord service and cleans up resources.\n\t * Implements the abstract method from the Service class.\n\t */\n\tpublic async stop(): Promise<void> {\n\t\tthis.runtime.logger.info(\"Stopping Discord service\");\n\t\tthis.timeouts.forEach(clearTimeout); // Clear any pending timeouts\n\t\tthis.timeouts = [];\n\t\tif (this.client) {\n\t\t\tawait this.client.destroy();\n\t\t\tthis.client = null;\n\t\t\tthis.runtime.logger.info(\"Discord client destroyed\");\n\t\t}\n\t\t// Additional cleanup if needed (e.g., voice manager)\n\t\tif (this.voiceManager) {\n\t\t\t// Assuming voiceManager has a stop or cleanup method\n\t\t\t// await this.voiceManager.stop();\n\t\t}\n\t\tthis.runtime.logger.info(\"Discord service stopped\");\n\t}\n\n\t/**\n\t * Asynchronously retrieves the type of a given channel.\n\t *\n\t * @param {Channel} channel - The channel for which to determine the type.\n\t * @returns {Promise<ChannelType>} A Promise that resolves with the type of the channel.\n\t */\n\tasync getChannelType(channel: Channel): Promise<ChannelType> {\n\t\tswitch (channel.type) {\n\t\t\tcase DiscordChannelType.DM:\n\t\t\t\treturn ChannelType.DM;\n\n\t\t\tcase DiscordChannelType.GroupDM:\n\t\t\t\treturn ChannelType.DM; // Group DMs treated as DM\n\n\t\t\tcase DiscordChannelType.GuildText:\n\t\t\tcase DiscordChannelType.GuildNews: // Announcement channels\n\t\t\tcase DiscordChannelType.PublicThread:\n\t\t\tcase DiscordChannelType.PrivateThread:\n\t\t\tcase DiscordChannelType.AnnouncementThread:\n\t\t\tcase DiscordChannelType.GuildForum: // Forum channels\n\t\t\t\treturn ChannelType.GROUP;\n\n\t\t\tcase DiscordChannelType.GuildVoice:\n\t\t\tcase DiscordChannelType.GuildStageVoice: // Stage channels\n\t\t\t\treturn ChannelType.VOICE_GROUP;\n\n\t\t\tdefault:\n\t\t\t\t// Fallback for any unrecognized channel types\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tchannelType: channel.type,\n\t\t\t\t\t},\n\t\t\t\t\t\"Unknown channel type, defaulting to GROUP\",\n\t\t\t\t);\n\t\t\t\treturn ChannelType.GROUP;\n\t\t}\n\t}\n}\n\nexport default DiscordService;\n",
|
|
115
|
+
"/**\n * Runtime compatibility layer for old/new core.\n *\n * Automatically adds serverId when messageServerId is provided,\n * making plugin code work with both core versions unchanged.\n *\n * Old core expects: serverId (string)\n * New core expects: messageServerId (UUID)\n *\n * NOTE: UUID function usage for Discord IDs:\n * - `stringToUuid(str)` - CONVERTS any string to a deterministic UUID by hashing.\n * Use this for Discord snowflake IDs (always succeeds, same input = same output).\n * - `asUUID(str)` - VALIDATES that string is already a valid UUID format.\n * Throws if not a valid UUID. Only use when input is already a UUID.\n *\n * REMOVAL: Delete this file and remove createCompatRuntime() call in service.ts\n */\nimport type {\n\tChannelType,\n\tEntity,\n\tIAgentRuntime,\n\tMetadata,\n\tRoom,\n\tUUID,\n\tWorld,\n} from \"@elizaos/core\";\n\n/**\n * Extended types that support messageServerId for cross-core compatibility.\n * These allow TypeScript to accept messageServerId in object literals.\n */\nexport type WorldCompat = Omit<World, \"serverId\"> & {\n\tserverId?: string;\n\tmessageServerId?: UUID;\n};\n\nexport type RoomCompat = Omit<Room, \"serverId\"> & {\n\tserverId?: string;\n\tmessageServerId?: UUID;\n};\n\nexport interface EnsureConnectionParams {\n\tentityId: UUID;\n\troomId: UUID;\n\tuserName?: string;\n\tname?: string;\n\tworldName?: string;\n\tsource?: string;\n\tchannelId?: string;\n\tserverId?: string;\n\tmessageServerId?: UUID;\n\ttype?: ChannelType | string;\n\tworldId?: UUID;\n\tuserId?: UUID;\n\tmetadata?: Metadata;\n}\n\n/**\n * Extended runtime interface that accepts messageServerId in method parameters.\n */\nexport interface ICompatRuntime\n\textends Omit<\n\t\tIAgentRuntime,\n\t\t| \"ensureWorldExists\"\n\t\t| \"ensureRoomExists\"\n\t\t| \"ensureConnection\"\n\t\t| \"ensureConnections\"\n\t> {\n\tensureWorldExists(world: WorldCompat): Promise<void>;\n\tensureRoomExists(room: RoomCompat): Promise<void>;\n\tensureConnection(params: EnsureConnectionParams): Promise<void>;\n\tensureConnections(\n\t\tentities: Entity[],\n\t\trooms: RoomCompat[],\n\t\tsource: string,\n\t\tworld: WorldCompat,\n\t): Promise<void>;\n}\n\nfunction addServerId<T extends Record<string, unknown>>(obj: T): T {\n\tif (!obj?.messageServerId) {\n\t\treturn obj;\n\t}\n\treturn { ...obj, serverId: obj.serverId ?? obj.messageServerId };\n}\n\nexport function createCompatRuntime(runtime: IAgentRuntime): ICompatRuntime {\n\treturn new Proxy(runtime, {\n\t\tget(target, prop, receiver) {\n\t\t\tconst value = Reflect.get(target, prop, receiver);\n\t\t\tif (typeof value !== \"function\") {\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t\tif (prop === \"ensureWorldExists\") {\n\t\t\t\treturn (world: unknown) =>\n\t\t\t\t\tvalue.call(target, addServerId(world as Record<string, unknown>));\n\t\t\t}\n\t\t\tif (prop === \"ensureRoomExists\") {\n\t\t\t\treturn (room: unknown) =>\n\t\t\t\t\tvalue.call(target, addServerId(room as Record<string, unknown>));\n\t\t\t}\n\t\t\tif (prop === \"ensureConnection\") {\n\t\t\t\treturn (params: unknown) =>\n\t\t\t\t\tvalue.call(target, addServerId(params as Record<string, unknown>));\n\t\t\t}\n\t\t\tif (prop === \"ensureConnections\") {\n\t\t\t\treturn (\n\t\t\t\t\tentities: unknown[],\n\t\t\t\t\trooms: unknown[],\n\t\t\t\t\tsource: string,\n\t\t\t\t\tworld: unknown,\n\t\t\t\t) =>\n\t\t\t\t\tvalue.call(\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t\tentities,\n\t\t\t\t\t\trooms.map((r) => addServerId(r as Record<string, unknown>)),\n\t\t\t\t\t\tsource,\n\t\t\t\t\t\taddServerId(world as Record<string, unknown>),\n\t\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn value;\n\t\t},\n\t});\n}\n",
|
|
116
|
+
"import type { IAgentRuntime } from \"@elizaos/core\";\nimport { parseBooleanFromText } from \"@elizaos/core\";\nimport { z } from \"zod\";\nimport type { DiscordSettings } from \"./types\";\n\nfunction getEnvBoolean(name: string, fallback: boolean): boolean {\n\tconst value = process.env?.[name];\n\tif (!value) {\n\t\treturn fallback;\n\t}\n\treturn value.toLowerCase() === \"true\";\n}\n\nfunction getEnvArray(name: string, fallback: string[]): string[] {\n\tconst value = process.env?.[name];\n\tif (!value || value.trim() === \"\") {\n\t\treturn fallback;\n\t}\n\treturn value\n\t\t.split(\",\")\n\t\t.map((item) => item.trim())\n\t\t.filter((item) => item.length > 0);\n}\n\nexport const DISCORD_DEFAULTS = {\n\tSHOULD_IGNORE_BOT_MESSAGES: getEnvBoolean(\n\t\t\"DISCORD_SHOULD_IGNORE_BOT_MESSAGES\",\n\t\tfalse,\n\t),\n\tSHOULD_IGNORE_DIRECT_MESSAGES: getEnvBoolean(\n\t\t\"DISCORD_SHOULD_IGNORE_DIRECT_MESSAGES\",\n\t\tfalse,\n\t),\n\tSHOULD_RESPOND_ONLY_TO_MENTIONS: getEnvBoolean(\n\t\t\"DISCORD_SHOULD_RESPOND_ONLY_TO_MENTIONS\",\n\t\tfalse,\n\t),\n\tALLOWED_CHANNEL_IDS: getEnvArray(\"CHANNEL_IDS\", []),\n\tDM_POLICY: (process.env?.DISCORD_DM_POLICY || \"open\") as\n\t\t| \"open\"\n\t\t| \"allowlist\"\n\t\t| \"pairing\"\n\t\t| \"disabled\",\n\tALLOW_FROM: getEnvArray(\"DISCORD_ALLOW_FROM\", []),\n} as const;\n\nexport const discordEnvSchema = z.object({\n\tDISCORD_API_TOKEN: z.string().min(1, \"Discord API token is required\"),\n\tCHANNEL_IDS: z\n\t\t.string()\n\t\t.nullish()\n\t\t.transform((val) =>\n\t\t\tval\n\t\t\t\t? val\n\t\t\t\t\t\t.split(\",\")\n\t\t\t\t\t\t.map((s) => s.trim())\n\t\t\t\t\t\t.filter((s) => s.length > 0)\n\t\t\t\t: undefined,\n\t\t),\n\tDISCORD_SHOULD_IGNORE_BOT_MESSAGES: z\n\t\t.string()\n\t\t.nullish()\n\t\t.transform((val) => (val ? parseBooleanFromText(val) : undefined)),\n\tDISCORD_SHOULD_IGNORE_DIRECT_MESSAGES: z\n\t\t.string()\n\t\t.nullish()\n\t\t.transform((val) => (val ? parseBooleanFromText(val) : undefined)),\n\tDISCORD_SHOULD_RESPOND_ONLY_TO_MENTIONS: z\n\t\t.string()\n\t\t.nullish()\n\t\t.transform((val) => (val ? parseBooleanFromText(val) : undefined)),\n});\n\nexport type DiscordConfig = z.infer<typeof discordEnvSchema>;\n\nexport function getDiscordSettings(runtime: IAgentRuntime): DiscordSettings {\n\tconst characterSettings =\n\t\t(runtime.character.settings &&\n\t\t\t(runtime.character.settings.discord as DiscordSettings)) ||\n\t\t{};\n\n\tconst resolveSetting = <T>(\n\t\tenvKey: string,\n\t\tcharacterValue: T | undefined,\n\t\tdefaultValue: T,\n\t\ttransform?: (value: string) => T,\n\t): T => {\n\t\tconst runtimeValue = runtime.getSetting(envKey);\n\t\tif (runtimeValue !== undefined && runtimeValue !== null) {\n\t\t\tconst normalized =\n\t\t\t\ttypeof runtimeValue === \"string\" ? runtimeValue : String(runtimeValue);\n\t\t\treturn transform ? transform(normalized) : (runtimeValue as T);\n\t\t}\n\t\treturn characterValue ?? defaultValue;\n\t};\n\n\tconst resolvedAllowedChannelIds = resolveSetting<string[]>(\n\t\t\"CHANNEL_IDS\",\n\t\tcharacterSettings.allowedChannelIds,\n\t\tDISCORD_DEFAULTS.ALLOWED_CHANNEL_IDS,\n\t\t(value: string) =>\n\t\t\tvalue\n\t\t\t\t.split(\",\")\n\t\t\t\t.map((s) => s.trim())\n\t\t\t\t.filter((s) => s.length > 0),\n\t);\n\n\treturn {\n\t\t...characterSettings,\n\t\tshouldIgnoreBotMessages: resolveSetting(\n\t\t\t\"DISCORD_SHOULD_IGNORE_BOT_MESSAGES\",\n\t\t\tcharacterSettings.shouldIgnoreBotMessages,\n\t\t\tDISCORD_DEFAULTS.SHOULD_IGNORE_BOT_MESSAGES,\n\t\t\tparseBooleanFromText,\n\t\t),\n\n\t\tshouldIgnoreDirectMessages: resolveSetting(\n\t\t\t\"DISCORD_SHOULD_IGNORE_DIRECT_MESSAGES\",\n\t\t\tcharacterSettings.shouldIgnoreDirectMessages,\n\t\t\tDISCORD_DEFAULTS.SHOULD_IGNORE_DIRECT_MESSAGES,\n\t\t\tparseBooleanFromText,\n\t\t),\n\n\t\tshouldRespondOnlyToMentions: resolveSetting(\n\t\t\t\"DISCORD_SHOULD_RESPOND_ONLY_TO_MENTIONS\",\n\t\t\tcharacterSettings.shouldRespondOnlyToMentions,\n\t\t\tDISCORD_DEFAULTS.SHOULD_RESPOND_ONLY_TO_MENTIONS,\n\t\t\tparseBooleanFromText,\n\t\t),\n\n\t\tallowedChannelIds:\n\t\t\tresolvedAllowedChannelIds.length > 0\n\t\t\t\t? resolvedAllowedChannelIds\n\t\t\t\t: undefined,\n\n\t\tdmPolicy: resolveSetting(\n\t\t\t\"DISCORD_DM_POLICY\",\n\t\t\tcharacterSettings.dmPolicy,\n\t\t\tDISCORD_DEFAULTS.DM_POLICY,\n\t\t\t(value: string) => {\n\t\t\t\tconst normalized = value.toLowerCase().trim();\n\t\t\t\tif ([\"open\", \"allowlist\", \"pairing\", \"disabled\"].includes(normalized)) {\n\t\t\t\t\treturn normalized as \"open\" | \"allowlist\" | \"pairing\" | \"disabled\";\n\t\t\t\t}\n\t\t\t\treturn DISCORD_DEFAULTS.DM_POLICY;\n\t\t\t},\n\t\t),\n\n\t\tallowFrom: resolveSetting<string[]>(\n\t\t\t\"DISCORD_ALLOW_FROM\",\n\t\t\tcharacterSettings.allowFrom,\n\t\t\tDISCORD_DEFAULTS.ALLOW_FROM,\n\t\t\t(value: string) =>\n\t\t\t\tvalue\n\t\t\t\t\t.split(\",\")\n\t\t\t\t\t.map((s) => s.trim())\n\t\t\t\t\t.filter((s) => s.length > 0),\n\t\t),\n\t};\n}\n\nexport async function validateDiscordConfig(\n\truntime: IAgentRuntime,\n): Promise<DiscordConfig> {\n\ttry {\n\t\tconst config = {\n\t\t\tDISCORD_API_TOKEN: runtime.getSetting(\"DISCORD_API_TOKEN\"),\n\t\t\tCHANNEL_IDS: runtime.getSetting(\"CHANNEL_IDS\"),\n\t\t\tDISCORD_SHOULD_IGNORE_BOT_MESSAGES: runtime.getSetting(\n\t\t\t\t\"DISCORD_SHOULD_IGNORE_BOT_MESSAGES\",\n\t\t\t),\n\t\t\tDISCORD_SHOULD_IGNORE_DIRECT_MESSAGES: runtime.getSetting(\n\t\t\t\t\"DISCORD_SHOULD_IGNORE_DIRECT_MESSAGES\",\n\t\t\t),\n\t\t\tDISCORD_SHOULD_RESPOND_ONLY_TO_MENTIONS: runtime.getSetting(\n\t\t\t\t\"DISCORD_SHOULD_RESPOND_ONLY_TO_MENTIONS\",\n\t\t\t),\n\t\t};\n\n\t\treturn discordEnvSchema.parse(config);\n\t} catch (error) {\n\t\tif (error instanceof z.ZodError) {\n\t\t\tconst errorMessages = error.issues\n\t\t\t\t.map((err) => `${err.path.join(\".\")}: ${err.message}`)\n\t\t\t\t.join(\"\\n\");\n\t\t\tthrow new Error(\n\t\t\t\t`Discord configuration validation failed:\\n${errorMessages}`,\n\t\t\t);\n\t\t}\n\t\tthrow error;\n\t}\n}\n",
|
|
117
|
+
"import {\n\tcreateUniqueUuid,\n\ttype IAgentRuntime,\n\ttype Metadata,\n\tRole,\n} from \"@elizaos/core\";\n\nconst CANONICAL_OWNER_SETTING_KEY = \"MILADY_ADMIN_ENTITY_ID\";\n\nfunction getCanonicalOwnerId(runtime: IAgentRuntime): string | undefined {\n\tconst value = runtime.getSetting?.(CANONICAL_OWNER_SETTING_KEY);\n\tif (typeof value !== \"string\") {\n\t\treturn undefined;\n\t}\n\tconst trimmed = value.trim();\n\treturn trimmed.length > 0 ? trimmed : undefined;\n}\n\nexport function buildDiscordWorldMetadata(\n\truntime: IAgentRuntime,\n\tguildOwnerId: string | undefined,\n): Metadata | undefined {\n\tconst ownerId = getCanonicalOwnerId(runtime);\n\tif (ownerId) {\n\t\treturn {\n\t\t\townership: { ownerId },\n\t\t\troles: {\n\t\t\t\t[ownerId]: Role.OWNER,\n\t\t\t},\n\t\t};\n\t}\n\n\tif (!guildOwnerId) {\n\t\treturn undefined;\n\t}\n\n\tconst discordOwnerId = createUniqueUuid(runtime, guildOwnerId);\n\treturn {\n\t\townership: { ownerId: discordOwnerId },\n\t\troles: {\n\t\t\t[discordOwnerId]: Role.OWNER,\n\t\t},\n\t};\n}\n\nexport function buildDiscordEntityMetadata(\n\tuserId: string,\n\tuserName: string,\n\tname: string,\n\tglobalName?: string,\n): Metadata {\n\treturn {\n\t\tdefault: {\n\t\t\tusername: userName,\n\t\t\tname,\n\t\t},\n\t\tdiscord: {\n\t\t\tid: userId,\n\t\t\tuserId,\n\t\t\tuserName,\n\t\t\tusername: userName,\n\t\t\tname,\n\t\t\t...(typeof globalName === \"string\" && globalName.length > 0\n\t\t\t\t? { globalName }\n\t\t\t\t: {}),\n\t\t},\n\t\toriginalId: userId,\n\t\tusername: userName,\n\t\tdisplayName: name,\n\t};\n}\n",
|
|
118
|
+
"import {\n\tChannelType,\n\ttype Content,\n\tcheckPairingAllowed,\n\tcreateUniqueUuid,\n\tEventType,\n\ttype HandlerCallback,\n\ttype IAgentRuntime,\n\tisInAllowlist,\n\ttype Media,\n\ttype Memory,\n\ttype Service,\n\tServiceType,\n\tstringToUuid,\n\ttype UUID,\n} from \"@elizaos/core\";\nimport {\n\tAttachmentBuilder,\n\ttype Channel,\n\ttype Client,\n\tChannelType as DiscordChannelType,\n\ttype Message as DiscordMessage,\n\ttype TextChannel,\n} from \"discord.js\";\nimport { AttachmentManager } from \"./attachments\";\n// See service.ts for detailed documentation on Discord ID handling.\n// Key point: Discord snowflake IDs (e.g., \"1253563208833433701\") are NOT valid UUIDs.\n// Use stringToUuid() to convert them, not asUUID() which would throw an error.\nimport type { ICompatRuntime } from \"./compat\";\nimport { getDiscordSettings } from \"./environment\";\nimport { buildDiscordWorldMetadata } from \"./identity\";\nimport type { DiscordSettings, IDiscordService } from \"./types\";\nimport {\n\tcanSendMessage,\n\textractUrls,\n\tgetAttachmentFileName,\n\tgetMessageService,\n\tgetMessagingAPI,\n\tsendMessageInChunks,\n} from \"./utils\";\n\n/**\n * Class representing a Message Manager for handling Discord messages.\n */\n\nexport class MessageManager {\n\tprivate client: Client;\n\tprivate runtime: ICompatRuntime;\n\tprivate attachmentManager: AttachmentManager;\n\tprivate getChannelType: (channel: Channel) => Promise<ChannelType>;\n\tprivate discordSettings: DiscordSettings;\n\tprivate discordService: IDiscordService;\n\t/**\n\t * Constructor for a new instance of MessageManager.\n\t * @param {IDiscordService} discordService - The Discord service instance.\n\t * @param {ICompatRuntime} runtime - The agent runtime instance (with cross-core compat).\n\t * @throws {Error} If the Discord client is not initialized\n\t */\n\tconstructor(discordService: IDiscordService, runtime: ICompatRuntime) {\n\t\t// Guard against null client - fail fast with a clear error\n\t\tif (!discordService.client) {\n\t\t\tconst errorMsg =\n\t\t\t\t\"Discord client not initialized - cannot create MessageManager\";\n\t\t\truntime.logger.error(\n\t\t\t\t{ src: \"plugin:discord\", agentId: runtime.agentId },\n\t\t\t\terrorMsg,\n\t\t\t);\n\t\t\tthrow new Error(errorMsg);\n\t\t}\n\n\t\tthis.client = discordService.client;\n\t\tthis.runtime = runtime;\n\t\tthis.attachmentManager = new AttachmentManager(this.runtime);\n\t\tthis.getChannelType = discordService.getChannelType;\n\t\tthis.discordService = discordService;\n\t\t// Load Discord settings with proper priority (env vars > character settings > defaults)\n\t\tthis.discordSettings = getDiscordSettings(this.runtime);\n\t}\n\n\t/**\n\t * Check DM access based on the configured dmPolicy.\n\t *\n\t * @param message - The Discord DM message\n\t * @returns Access check result with allowed status and optional reply message\n\t */\n\tprivate async checkDmAccess(message: DiscordMessage): Promise<{\n\t\tallowed: boolean;\n\t\treplyMessage?: string;\n\t}> {\n\t\tconst policy = this.discordSettings.dmPolicy ?? \"open\";\n\t\tconst userId = message.author.id;\n\n\t\t// Disabled policy - block all DMs\n\t\tif (policy === \"disabled\") {\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tuserId,\n\t\t\t\t},\n\t\t\t\t\"DM blocked: policy is disabled\",\n\t\t\t);\n\t\t\treturn { allowed: false };\n\t\t}\n\n\t\t// Open policy - allow all DMs\n\t\tif (policy === \"open\") {\n\t\t\treturn { allowed: true };\n\t\t}\n\n\t\t// Allowlist policy - check static allowFrom list and dynamic pairing allowlist\n\t\tif (policy === \"allowlist\") {\n\t\t\t// Check static allowlist first\n\t\t\tif (this.discordSettings.allowFrom?.includes(userId)) {\n\t\t\t\treturn { allowed: true };\n\t\t\t}\n\n\t\t\t// Check dynamic pairing allowlist\n\t\t\tconst inDynamicAllowlist = await isInAllowlist(\n\t\t\t\tthis.runtime,\n\t\t\t\t\"discord\",\n\t\t\t\tuserId,\n\t\t\t);\n\t\t\tif (inDynamicAllowlist) {\n\t\t\t\treturn { allowed: true };\n\t\t\t}\n\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tuserId,\n\t\t\t\t},\n\t\t\t\t\"DM blocked: user not in allowlist\",\n\t\t\t);\n\t\t\treturn { allowed: false };\n\t\t}\n\n\t\t// Pairing policy - use PairingService\n\t\tif (policy === \"pairing\") {\n\t\t\t// Check static allowlist first (if configured, allow bypass of pairing)\n\t\t\tif (this.discordSettings.allowFrom?.includes(userId)) {\n\t\t\t\treturn { allowed: true };\n\t\t\t}\n\n\t\t\t// Use the PairingService for pairing workflow\n\t\t\tconst result = await checkPairingAllowed(this.runtime, {\n\t\t\t\tchannel: \"discord\",\n\t\t\t\tsenderId: userId,\n\t\t\t\tmetadata: {\n\t\t\t\t\tusername: message.author.username,\n\t\t\t\t\tdisplayName: message.author.displayName ?? message.author.username,\n\t\t\t\t\tdiscriminator: message.author.discriminator ?? \"\",\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tif (result.allowed) {\n\t\t\t\treturn { allowed: true };\n\t\t\t}\n\n\t\t\t// Not allowed - return pairing reply message only for new requests\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tuserId,\n\t\t\t\t\tpairingCode: result.pairingCode,\n\t\t\t\t\tnewRequest: result.newRequest,\n\t\t\t\t},\n\t\t\t\t\"DM blocked: pairing required\",\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tallowed: false,\n\t\t\t\t// Only send reply for new pairing requests (avoid spamming on every message)\n\t\t\t\treplyMessage: result.newRequest ? result.replyMessage : undefined,\n\t\t\t};\n\t\t}\n\n\t\t// Default: allow\n\t\treturn { allowed: true };\n\t}\n\n\t/**\n\t * Handles incoming Discord messages and processes them accordingly.\n\t *\n\t * @param {DiscordMessage} message - The Discord message to be handled\n\t */\n\tasync handleMessage(message: DiscordMessage) {\n\t\t// this filtering is already done in setupEventListeners\n\t\t/*\n if (\n (this.discordSettings.allowedChannelIds && this.discordSettings.allowedChannelIds.length) &&\n !this.discordSettings.allowedChannelIds.some((id: string) => id === message.channel.id)\n ) {\n return;\n }\n */\n\n\t\tconst clientUser = this.client.user;\n\t\tif (\n\t\t\tmessage.interaction ||\n\t\t\t(clientUser && message.author.id === clientUser.id)\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (\n\t\t\tthis.discordSettings.shouldIgnoreBotMessages &&\n\t\t\tmessage.author &&\n\t\t\tmessage.author.bot\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (\n\t\t\tthis.discordSettings.shouldIgnoreDirectMessages &&\n\t\t\tmessage.channel.type === DiscordChannelType.DM\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\t// DM policy check - applies access control policies for direct messages\n\t\tif (message.channel.type === DiscordChannelType.DM) {\n\t\t\tconst accessCheck = await this.checkDmAccess(message);\n\t\t\tif (!accessCheck.allowed) {\n\t\t\t\t// If a reply message was generated (new pairing request), send it\n\t\t\t\tif (accessCheck.replyMessage) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait message.author.send(accessCheck.replyMessage);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\tuserId: message.author.id,\n\t\t\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Failed to send pairing reply\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tconst isBotMentioned = !!(\n\t\t\tclientUser?.id &&\n\t\t\tmessage.mentions.users &&\n\t\t\tmessage.mentions.users.has(clientUser.id)\n\t\t);\n\t\tconst isReplyToBot =\n\t\t\t!!message.reference?.messageId &&\n\t\t\tmessage.mentions.repliedUser?.id === clientUser?.id;\n\t\tconst mentionedOtherUsers = message.mentions.users\n\t\t\t? Array.from(message.mentions.users.values()).some(\n\t\t\t\t\t(user) => user.id !== clientUser?.id && user.id !== message.author.id,\n\t\t\t\t)\n\t\t\t: false;\n\t\tconst isReplyToOtherUser =\n\t\t\t!!message.reference?.messageId &&\n\t\t\t!!message.mentions.repliedUser?.id &&\n\t\t\tmessage.mentions.repliedUser.id !== clientUser?.id &&\n\t\t\tmessage.mentions.repliedUser.id !== message.author.id;\n\t\tconst isInThread = message.channel.isThread();\n\t\tconst isDM = message.channel.type === DiscordChannelType.DM;\n\t\tif (!isDM && (mentionedOtherUsers || isReplyToOtherUser)) {\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tchannelId: message.channel.id,\n\t\t\t\t},\n\t\t\t\t\"Ignoring message that targets another mentioned user\",\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.discordSettings.shouldRespondOnlyToMentions) {\n\t\t\tconst shouldProcess = isDM || isBotMentioned || isReplyToBot;\n\n\t\t\tif (!shouldProcess) {\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tchannelId: message.channel.id,\n\t\t\t\t\t},\n\t\t\t\t\t\"Strict mode: ignoring message (no mention or reply)\",\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tchannelId: message.channel.id,\n\t\t\t\t},\n\t\t\t\t\"Strict mode: processing message\",\n\t\t\t);\n\t\t}\n\n\t\tconst entityId = createUniqueUuid(this.runtime, message.author.id);\n\t\tconst userName = message.author.bot\n\t\t\t? `${message.author.username}#${message.author.discriminator}`\n\t\t\t: message.author.username;\n\t\tconst name = message.author.displayName;\n\t\tconst channelId = message.channel.id;\n\t\tconst roomId = createUniqueUuid(this.runtime, channelId);\n\n\t\t// Determine channel type and server ID for ensureConnection\n\t\t// messageServerId is a Discord snowflake string, converted to UUID when needed\n\t\tlet type: ChannelType;\n\t\tlet messageServerId: string | undefined;\n\n\t\tif (message.guild) {\n\t\t\tconst guild = await message.guild.fetch();\n\t\t\ttype = await this.getChannelType(message.channel as Channel);\n\t\t\tif (type === null) {\n\t\t\t\t// usually a forum type post\n\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tchannelId: message.channel.id,\n\t\t\t\t\t},\n\t\t\t\t\t\"Null channel type\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tmessageServerId = guild.id;\n\t\t} else {\n\t\t\ttype = ChannelType.DM;\n\t\t\tmessageServerId = message.channel.id;\n\t\t}\n\n\t\tawait this.runtime.ensureConnection({\n\t\t\tentityId,\n\t\t\troomId,\n\t\t\tuserName,\n\t\t\tname,\n\t\t\tsource: \"discord\",\n\t\t\tchannelId: message.channel.id,\n\t\t\t// Convert Discord snowflake to UUID (see service.ts header for why stringToUuid not asUUID)\n\t\t\tmessageServerId: messageServerId\n\t\t\t\t? stringToUuid(messageServerId)\n\t\t\t\t: undefined,\n\t\t\ttype,\n\t\t\tworldId: createUniqueUuid(this.runtime, messageServerId ?? roomId),\n\t\t\tworldName: message.guild?.name,\n\t\t\t// Preserve the raw Discord user id in source metadata for role and allowlist checks.\n\t\t\tuserId: message.author.id as unknown as UUID,\n\t\t\tmetadata: buildDiscordWorldMetadata(\n\t\t\t\tthis.runtime,\n\t\t\t\tmessage.guild?.ownerId ?? undefined,\n\t\t\t),\n\t\t});\n\t\ttry {\n\t\t\tconst canSendResult = canSendMessage(message.channel);\n\t\t\tif (!canSendResult.canSend) {\n\t\t\t\treturn this.runtime.logger.warn(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tchannelId: message.channel.id,\n\t\t\t\t\t\treason: canSendResult.reason,\n\t\t\t\t\t},\n\t\t\t\t\t\"Cannot send message to channel\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst { processedContent, attachments } =\n\t\t\t\tawait this.processMessage(message);\n\t\t\t// Audio attachments already processed in processMessage via attachmentManager\n\n\t\t\tif (!processedContent && !attachments?.length) {\n\t\t\t\t// Only process messages that are not empty\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst channel = message.channel as TextChannel;\n\n\t\t\t// Store the typing data to be used by the callback\n\t\t\tconst typingData = {\n\t\t\t\tinterval: null as ReturnType<typeof setInterval> | null,\n\t\t\t\tcleared: false,\n\t\t\t\tstarted: false,\n\t\t\t};\n\n\t\t\t// Use the service's buildMemoryFromMessage method with pre-processed content\n\t\t\tconst newMessage = await this.discordService.buildMemoryFromMessage(\n\t\t\t\tmessage,\n\t\t\t\t{\n\t\t\t\t\tprocessedContent,\n\t\t\t\t\tprocessedAttachments: attachments,\n\t\t\t\t\textraContent: {\n\t\t\t\t\t\tmentionContext: {\n\t\t\t\t\t\t\tisMention: isBotMentioned,\n\t\t\t\t\t\t\tisReply: isReplyToBot,\n\t\t\t\t\t\t\tisThread: isInThread,\n\t\t\t\t\t\t\tmentionType: isBotMentioned\n\t\t\t\t\t\t\t\t? \"platform_mention\"\n\t\t\t\t\t\t\t\t: isReplyToBot\n\t\t\t\t\t\t\t\t\t? \"reply\"\n\t\t\t\t\t\t\t\t\t: isInThread\n\t\t\t\t\t\t\t\t\t\t? \"thread\"\n\t\t\t\t\t\t\t\t\t\t: \"none\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\textraMetadata: {\n\t\t\t\t\t\t// Reply attribution for cross-agent filtering\n\t\t\t\t\t\t// WHY: When user replies to another bot's message, we need to know\n\t\t\t\t\t\t// so other agents can ignore it (only the replied-to agent should respond)\n\t\t\t\t\t\treplyToAuthor: message.mentions.repliedUser\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\tid: message.mentions.repliedUser.id,\n\t\t\t\t\t\t\t\t\tusername: message.mentions.repliedUser.username,\n\t\t\t\t\t\t\t\t\tisBot: message.mentions.repliedUser.bot,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!newMessage) {\n\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tmessageId: message.id,\n\t\t\t\t\t},\n\t\t\t\t\t\"Failed to build memory from message\",\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst messageId = newMessage.id;\n\n\t\t\tconst callback: HandlerCallback = async (content: Content) => {\n\t\t\t\ttry {\n\t\t\t\t\t// target is set but not addressed to us handling\n\t\t\t\t\tif (\n\t\t\t\t\t\tcontent.target &&\n\t\t\t\t\t\ttypeof content.target === \"string\" &&\n\t\t\t\t\t\tcontent.target.toLowerCase() !== \"discord\"\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\t// Start typing indicator only when we're actually going to respond\n\t\t\t\t\tif (!typingData.started) {\n\t\t\t\t\t\ttypingData.started = true;\n\n\t\t\t\t\t\tconst startTyping = () => {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t// sendTyping is not available at test time\n\t\t\t\t\t\t\t\tif (channel.sendTyping) {\n\t\t\t\t\t\t\t\t\tchannel.sendTyping();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"Error sending typing indicator\",\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\t// Start typing immediately\n\t\t\t\t\t\tstartTyping();\n\n\t\t\t\t\t\t// Create interval to keep the typing indicator active while processing\n\t\t\t\t\t\ttypingData.interval = setInterval(startTyping, 8000); // there is no stop typing, it times out after 10s\n\n\t\t\t\t\t\t// Add a small delay to ensure typing indicator is visible\n\t\t\t\t\t\t// This simulates the bot \"thinking\" before responding\n\t\t\t\t\t\t//await new Promise((resolve) => setTimeout(resolve, 1500));\n\t\t\t\t\t}\n\n\t\t\t\t\tif (message.id && !content.inReplyTo) {\n\t\t\t\t\t\tcontent.inReplyTo = createUniqueUuid(this.runtime, message.id);\n\t\t\t\t\t}\n\n\t\t\t\t\tlet messages: DiscordMessage[] = [];\n\t\t\t\t\tif (content && content.channelType === \"DM\") {\n\t\t\t\t\t\tconst u = await this.client.users.fetch(message.author.id);\n\t\t\t\t\t\tif (!u) {\n\t\t\t\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\t\tentityId: message.author.id,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"User not found for DM\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn [];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Convert Media attachments to Discord AttachmentBuilder format for DMs\n\t\t\t\t\t\tconst files: AttachmentBuilder[] = [];\n\t\t\t\t\t\tif (content.attachments && content.attachments.length > 0) {\n\t\t\t\t\t\t\tfor (const media of content.attachments) {\n\t\t\t\t\t\t\t\tif (media.url) {\n\t\t\t\t\t\t\t\t\tconst fileName = getAttachmentFileName(media);\n\t\t\t\t\t\t\t\t\tfiles.push(\n\t\t\t\t\t\t\t\t\t\tnew AttachmentBuilder(media.url, { name: fileName }),\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst textContent = content.text ?? \"\";\n\t\t\t\t\t\tconst hasText = textContent.trim().length > 0;\n\t\t\t\t\t\tif (!hasText && files.length === 0) {\n\t\t\t\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t\t\t\t{ src: \"plugin:discord\", agentId: this.runtime.agentId },\n\t\t\t\t\t\t\t\t\"Skipping DM response: no text or attachments\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn [];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst dmMessage = await u.send({\n\t\t\t\t\t\t\tcontent: textContent,\n\t\t\t\t\t\t\tfiles: files.length > 0 ? files : undefined,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tmessages = [dmMessage];\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Convert Media attachments to Discord AttachmentBuilder format\n\t\t\t\t\t\tconst files: AttachmentBuilder[] = [];\n\t\t\t\t\t\tif (content.attachments && content.attachments.length > 0) {\n\t\t\t\t\t\t\tfor (const media of content.attachments) {\n\t\t\t\t\t\t\t\tif (media.url) {\n\t\t\t\t\t\t\t\t\tconst fileName = getAttachmentFileName(media);\n\t\t\t\t\t\t\t\t\tfiles.push(\n\t\t\t\t\t\t\t\t\t\tnew AttachmentBuilder(media.url, { name: fileName }),\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Pass runtime to enable smart (LLM-assisted) splitting for complex content\n\t\t\t\t\t\tif (!message.id) {\n\t\t\t\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t\t\t\t{ src: \"plugin:discord\", agentId: this.runtime.agentId },\n\t\t\t\t\t\t\t\t\"Cannot send message: message.id is missing\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn [];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmessages = await sendMessageInChunks(\n\t\t\t\t\t\t\tchannel,\n\t\t\t\t\t\t\tcontent.text ?? \"\",\n\t\t\t\t\t\t\tmessage.id,\n\t\t\t\t\t\t\tfiles,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tthis.runtime,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst memories: Memory[] = [];\n\t\t\t\t\tfor (const m of messages) {\n\t\t\t\t\t\tconst actions = content.actions;\n\t\t\t\t\t\t// Only attach files to the memory for the message that actually carries them\n\t\t\t\t\t\tconst hasAttachments = m.attachments?.size > 0;\n\n\t\t\t\t\t\tconst memory: Memory = {\n\t\t\t\t\t\t\tid: createUniqueUuid(this.runtime, m.id),\n\t\t\t\t\t\t\tentityId: this.runtime.agentId,\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t...content,\n\t\t\t\t\t\t\t\ttext: m.content || content.text || \" \",\n\t\t\t\t\t\t\t\tactions,\n\t\t\t\t\t\t\t\tinReplyTo: messageId,\n\t\t\t\t\t\t\t\turl: m.url,\n\t\t\t\t\t\t\t\tchannelType: type,\n\t\t\t\t\t\t\t\t// Only include attachments for the message chunk that actually has them\n\t\t\t\t\t\t\t\tattachments:\n\t\t\t\t\t\t\t\t\thasAttachments && content.attachments\n\t\t\t\t\t\t\t\t\t\t? content.attachments\n\t\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\troomId,\n\t\t\t\t\t\t\tcreatedAt: m.createdTimestamp,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tmemories.push(memory);\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (const m of memories) {\n\t\t\t\t\t\tawait this.runtime.createMemory(m, \"messages\");\n\t\t\t\t\t}\n\n\t\t\t\t\t// Clear typing indicator when done\n\t\t\t\t\tif (typingData.interval && !typingData.cleared) {\n\t\t\t\t\t\tclearInterval(typingData.interval);\n\t\t\t\t\t\ttypingData.cleared = true;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn memories;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Error handling message callback\",\n\t\t\t\t\t);\n\t\t\t\t\t// Clear typing indicator on error\n\t\t\t\t\tif (typingData.interval && !typingData.cleared) {\n\t\t\t\t\t\tclearInterval(typingData.interval);\n\t\t\t\t\t\ttypingData.cleared = true;\n\t\t\t\t\t}\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// Use messaging API if available, otherwise fall back to direct message service\n\t\t\t// This provides a clearer, more traceable flow for message processing\n\t\t\tconst messagingAPI = getMessagingAPI(this.runtime);\n\t\t\tconst messageService = getMessageService(this.runtime);\n\n\t\t\tif (messagingAPI) {\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t{ src: \"plugin:discord\", agentId: this.runtime.agentId },\n\t\t\t\t\t\"Using messaging API\",\n\t\t\t\t);\n\t\t\t\tawait messagingAPI.sendMessage(this.runtime.agentId, newMessage, {\n\t\t\t\t\tonResponse: callback,\n\t\t\t\t});\n\t\t\t} else if (messageService) {\n\t\t\t\t// Newer core with messageService\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t{ src: \"plugin:discord\", agentId: this.runtime.agentId },\n\t\t\t\t\t\"Using messageService API\",\n\t\t\t\t);\n\t\t\t\tawait messageService.handleMessage(this.runtime, newMessage, callback);\n\t\t\t} else {\n\t\t\t\t// Older core - use event-based message handling (backwards compatible)\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t{ src: \"plugin:discord\", agentId: this.runtime.agentId },\n\t\t\t\t\t\"Using event-based message handling\",\n\t\t\t\t);\n\t\t\t\tawait this.runtime.emitEvent([EventType.MESSAGE_RECEIVED], {\n\t\t\t\t\truntime: this.runtime,\n\t\t\t\t\tmessage: newMessage,\n\t\t\t\t\tcallback,\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Failsafe: clear typing indicator after 30 seconds if it was started and something goes wrong\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (typingData.started && typingData.interval && !typingData.cleared) {\n\t\t\t\t\tclearInterval(typingData.interval);\n\t\t\t\t\ttypingData.cleared = true;\n\t\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t\t{ src: \"plugin:discord\", agentId: this.runtime.agentId },\n\t\t\t\t\t\t\"Typing indicator failsafe timeout triggered\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}, 30000);\n\t\t} catch (error) {\n\t\t\tthis.runtime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error handling message\",\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Processes the message content, mentions, code blocks, attachments, and URLs to generate\n\t * processed content and media attachments.\n\t *\n\t * @param {DiscordMessage} message The message to process\n\t * @returns {Promise<{ processedContent: string; attachments: Media[] }>} Processed content and media attachments\n\t */\n\tasync processMessage(\n\t\tmessage: DiscordMessage,\n\t): Promise<{ processedContent: string; attachments: Media[] }> {\n\t\tlet processedContent = message.content;\n\t\tlet attachments: Media[] = [];\n\n\t\tif (message.embeds?.length) {\n\t\t\tfor (const i in message.embeds) {\n\t\t\t\tconst embed = message.embeds[i];\n\t\t\t\t// type: rich\n\t\t\t\tprocessedContent += `\\nEmbed #${parseInt(i, 10) + 1}:\\n`;\n\t\t\t\tprocessedContent += ` Title:${embed.title ?? \"(none)\"}\\n`;\n\t\t\t\tprocessedContent += ` Description:${embed.description ?? \"(none)\"}\\n`;\n\t\t\t}\n\t\t}\n\t\tif (message.reference) {\n\t\t\tlet messageId: string | undefined;\n\t\t\tif (message.reference.messageId) {\n\t\t\t\tmessageId = createUniqueUuid(this.runtime, message.reference.messageId);\n\t\t\t} else {\n\t\t\t\t// optional: try to fetch the referenced message to get a definite id\n\t\t\t\ttry {\n\t\t\t\t\tconst refMsg = await message.fetchReference(); // throws if missing\n\t\t\t\t\tmessageId = createUniqueUuid(this.runtime, refMsg.id);\n\t\t\t\t} catch {\n\t\t\t\t\t// no referenced message available — handle gracefully\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (messageId) {\n\t\t\t\t// context currently doesn't know message ID\n\t\t\t\tprocessedContent += `\\nReferencing MessageID ${messageId} (discord: ${\n\t\t\t\t\tmessage.reference.messageId\n\t\t\t\t})`;\n\t\t\t\t// in our channel\n\t\t\t\tif (message.reference.channelId !== message.channel.id) {\n\t\t\t\t\tconst roomId = createUniqueUuid(\n\t\t\t\t\t\tthis.runtime,\n\t\t\t\t\t\tmessage.reference.channelId,\n\t\t\t\t\t);\n\t\t\t\t\tprocessedContent += ` in channel ${roomId}`;\n\t\t\t\t}\n\t\t\t\t// in our guild\n\t\t\t\tif (\n\t\t\t\t\tmessage.reference.guildId &&\n\t\t\t\t\tmessage.guild &&\n\t\t\t\t\tmessage.reference.guildId !== message.guild.id\n\t\t\t\t) {\n\t\t\t\t\tprocessedContent += ` in guild ${message.reference.guildId}`;\n\t\t\t\t}\n\t\t\t\tprocessedContent += \"\\n\";\n\t\t\t}\n\t\t}\n\n\t\tconst mentionRegex = /<@!?(\\d+)>/g;\n\t\tprocessedContent = processedContent.replace(\n\t\t\tmentionRegex,\n\t\t\t(match, entityId) => {\n\t\t\t\tconst user = message.mentions.users.get(entityId);\n\t\t\t\tif (user) {\n\t\t\t\t\treturn `${user.username} (@${entityId})`;\n\t\t\t\t}\n\t\t\t\treturn match;\n\t\t\t},\n\t\t);\n\n\t\tconst codeBlockRegex = /```([\\s\\S]*?)```/g;\n\t\tlet match: RegExpExecArray | null = codeBlockRegex.exec(processedContent);\n\t\twhile (match !== null) {\n\t\t\tconst fullMatch = match[0];\n\t\t\tconst codeBlock = match[1];\n\t\t\tconst lines = codeBlock.split(\"\\n\");\n\t\t\tconst title = lines[0];\n\t\t\tconst description = lines.slice(0, 3).join(\"\\n\");\n\t\t\tconst attachmentId =\n\t\t\t\t`code-${Date.now()}-${Math.floor(Math.random() * 1000)}`.slice(-5);\n\t\t\tattachments.push({\n\t\t\t\tid: attachmentId,\n\t\t\t\turl: \"\",\n\t\t\t\ttitle: title || \"Code Block\",\n\t\t\t\tsource: \"Code\",\n\t\t\t\tdescription,\n\t\t\t\ttext: codeBlock,\n\t\t\t});\n\t\t\tprocessedContent = processedContent.replace(\n\t\t\t\tfullMatch,\n\t\t\t\t`Code Block (${attachmentId})`,\n\t\t\t);\n\t\t\tmatch = codeBlockRegex.exec(processedContent);\n\t\t}\n\n\t\tif (message.attachments.size > 0) {\n\t\t\tattachments = await this.attachmentManager.processAttachments(\n\t\t\t\tmessage.attachments,\n\t\t\t);\n\t\t}\n\n\t\t// Extract and clean URLs from the message content\n\t\tconst urls = extractUrls(processedContent, this.runtime);\n\n\t\tfor (const url of urls) {\n\t\t\t// Use string literal type for getService, assume methods exist at runtime\n\t\t\tconst videoService = this.runtime.getService(ServiceType.VIDEO) as\n\t\t\t\t| ({\n\t\t\t\t\t\tisVideoUrl?: (url: string) => boolean;\n\t\t\t\t\t\tprocessVideo?: (\n\t\t\t\t\t\t\turl: string,\n\t\t\t\t\t\t\truntime: IAgentRuntime,\n\t\t\t\t\t\t) => Promise<{\n\t\t\t\t\t\t\ttitle: string;\n\t\t\t\t\t\t\tdescription: string;\n\t\t\t\t\t\t\ttext: string;\n\t\t\t\t\t\t}>;\n\t\t\t\t } & Service)\n\t\t\t\t| null;\n\t\t\tif (videoService?.isVideoUrl(url)) {\n\t\t\t\ttry {\n\t\t\t\t\tconst videoInfo = await videoService.processVideo(url, this.runtime);\n\n\t\t\t\t\tattachments.push({\n\t\t\t\t\t\tid: `youtube-${Date.now()}`,\n\t\t\t\t\t\turl,\n\t\t\t\t\t\ttitle: videoInfo.title,\n\t\t\t\t\t\tsource: \"YouTube\",\n\t\t\t\t\t\tdescription: videoInfo.description,\n\t\t\t\t\t\ttext: videoInfo.text,\n\t\t\t\t\t});\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// Handle video processing errors gracefully - the URL is still preserved in the message\n\t\t\t\t\tconst errorMsg =\n\t\t\t\t\t\terror instanceof Error ? error.message : String(error);\n\t\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t\t`Failed to process video ${url}: ${errorMsg}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Use string literal type for getService, assume methods exist at runtime\n\t\t\t\tconst browserService = this.runtime.getService(ServiceType.BROWSER) as\n\t\t\t\t\t| ({\n\t\t\t\t\t\t\tgetPageContent?: (\n\t\t\t\t\t\t\t\turl: string,\n\t\t\t\t\t\t\t\truntime: IAgentRuntime,\n\t\t\t\t\t\t\t) => Promise<{ title?: string; description?: string }>;\n\t\t\t\t\t } & Service)\n\t\t\t\t\t| null;\n\t\t\t\tif (!browserService) {\n\t\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t\t{ src: \"plugin:discord\", agentId: this.runtime.agentId },\n\t\t\t\t\t\t\"Browser service not found\",\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t`Fetching page content for cleaned URL: \"${url}\"`,\n\t\t\t\t\t);\n\t\t\t\t\tconst { title, description: summary } =\n\t\t\t\t\t\tawait browserService.getPageContent(url, this.runtime);\n\n\t\t\t\t\tattachments.push({\n\t\t\t\t\t\tid: `webpage-${Date.now()}`,\n\t\t\t\t\t\turl,\n\t\t\t\t\t\ttitle: title || \"Web Page\",\n\t\t\t\t\t\tsource: \"Web\",\n\t\t\t\t\t\tdescription: summary,\n\t\t\t\t\t\ttext: summary,\n\t\t\t\t\t});\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// Silently handle browser errors (certificate issues, timeouts, dead sites, etc.)\n\t\t\t\t\t// The URL is still preserved in the message content, just without scraped metadata\n\t\t\t\t\tconst errorMsg =\n\t\t\t\t\t\terror instanceof Error ? error.message : String(error);\n\t\t\t\t\tconst errorString = String(error);\n\n\t\t\t\t\t// Check for common expected failures that don't need logging\n\t\t\t\t\tconst isExpectedFailure =\n\t\t\t\t\t\terrorMsg.includes(\"ERR_CERT\") ||\n\t\t\t\t\t\terrorString.includes(\"ERR_CERT\") ||\n\t\t\t\t\t\terrorMsg.includes(\"Timeout\") ||\n\t\t\t\t\t\terrorString.includes(\"Timeout\") ||\n\t\t\t\t\t\terrorMsg.includes(\"ERR_NAME_NOT_RESOLVED\") ||\n\t\t\t\t\t\terrorString.includes(\"ERR_NAME_NOT_RESOLVED\") ||\n\t\t\t\t\t\terrorMsg.includes(\"ERR_HTTP_RESPONSE_CODE_FAILURE\") ||\n\t\t\t\t\t\terrorString.includes(\"ERR_HTTP_RESPONSE_CODE_FAILURE\");\n\n\t\t\t\t\tif (!isExpectedFailure) {\n\t\t\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t\t\t`Failed to fetch page content for ${url}: ${errorMsg}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\t// Expected failures are silently handled - no logging needed\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn { processedContent, attachments };\n\t}\n\n\t/**\n\t * Asynchronously fetches the bot's username and discriminator from Discord API.\n\t *\n\t * @param {string} botToken The token of the bot to authenticate the request\n\t * @returns {Promise<string>} A promise that resolves with the bot's username and discriminator\n\t * @throws {Error} If there is an error while fetching the bot details\n\t */\n\n\tasync fetchBotName(botToken: string) {\n\t\tconst url = \"https://discord.com/api/v10/users/@me\";\n\t\tconst response = await fetch(url, {\n\t\t\tmethod: \"GET\",\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bot ${botToken}`,\n\t\t\t},\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(`Error fetching bot details: ${response.statusText}`);\n\t\t}\n\n\t\tconst data = await response.json();\n\t\tconst discriminator = data.discriminator;\n\t\treturn (\n\t\t\t(data as { username: string }).username +\n\t\t\t(discriminator ? `#${discriminator}` : \"\")\n\t\t);\n\t}\n}\n",
|
|
119
|
+
"import fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport {\n\ttype IAgentRuntime,\n\ttype Media,\n\tModelType,\n\ttype Service,\n\tServiceType,\n} from \"@elizaos/core\";\nimport { type Attachment, Collection } from \"discord.js\";\nimport ffmpeg from \"fluent-ffmpeg\";\nimport { generateSummary } from \"./utils\";\n\n/**\n * Class representing an Attachment Manager.\n */\nexport class AttachmentManager {\n\tprivate attachmentCache: Map<string, Media> = new Map();\n\tprivate runtime: IAgentRuntime;\n\n\t/**\n\t * Constructor for creating a new instance of the class.\n\t *\n\t * @param {IAgentRuntime} runtime The runtime object to be injected into the instance.\n\t */\n\tconstructor(runtime: IAgentRuntime) {\n\t\tthis.runtime = runtime;\n\t}\n\n\t/**\n\t * Processes attachments and returns an array of Media objects.\n\t * @param {Collection<string, Attachment> | Attachment[]} attachments - The attachments to be processed\n\t * @returns {Promise<Media[]>} - An array of processed Media objects\n\t */\n\tasync processAttachments(\n\t\tattachments: Collection<string, Attachment> | Attachment[],\n\t): Promise<Media[]> {\n\t\tconst processedAttachments: Media[] = [];\n\t\tconst attachmentCollection =\n\t\t\tattachments instanceof Collection\n\t\t\t\t? attachments\n\t\t\t\t: new Collection(attachments.map((att) => [att.id, att]));\n\n\t\tfor (const [, attachment] of attachmentCollection) {\n\t\t\tconst media = await this.processAttachment(attachment);\n\t\t\tif (media) {\n\t\t\t\tprocessedAttachments.push(media);\n\t\t\t}\n\t\t}\n\n\t\treturn processedAttachments;\n\t}\n\n\t/**\n\t * Processes the provided attachment to generate a media object.\n\t * If the media for the attachment URL is already cached, it will return the cached media.\n\t * Otherwise, it will determine the type of attachment (PDF, text, audio, video, image, generic)\n\t * and call the corresponding processing method to generate the media object.\n\t *\n\t * @param attachment The attachment to process\n\t * @returns A promise that resolves to a Media object representing the attachment, or null if the attachment could not be processed\n\t */\n\tasync processAttachment(attachment: Attachment): Promise<Media | null> {\n\t\tconst cached = this.attachmentCache.get(attachment.url);\n\t\tif (cached) {\n\t\t\treturn cached;\n\t\t}\n\n\t\tlet media: Media | null = null;\n\t\tif (attachment.contentType?.startsWith(\"application/pdf\")) {\n\t\t\tmedia = await this.processPdfAttachment(attachment);\n\t\t} else if (attachment.contentType?.startsWith(\"text/plain\")) {\n\t\t\tmedia = await this.processPlaintextAttachment(attachment);\n\t\t} else if (\n\t\t\tattachment.contentType?.startsWith(\"audio/\") ||\n\t\t\tattachment.contentType?.startsWith(\"video/mp4\")\n\t\t) {\n\t\t\tmedia = await this.processAudioVideoAttachment(attachment);\n\t\t} else if (attachment.contentType?.startsWith(\"image/\")) {\n\t\t\tmedia = await this.processImageAttachment(attachment);\n\t\t} else if (attachment.contentType?.startsWith(\"video/\")) {\n\t\t\tmedia = await this.processVideoAttachment(attachment);\n\t\t} else {\n\t\t\tconst videoService = this.runtime.getService(ServiceType.VIDEO) as\n\t\t\t\t| ({ isVideoUrl?: (url: string) => boolean } & Service)\n\t\t\t\t| null;\n\t\t\tif (videoService?.isVideoUrl?.(attachment.url)) {\n\t\t\t\tmedia = await this.processVideoAttachment(attachment);\n\t\t\t} else {\n\t\t\t\tmedia = await this.processGenericAttachment(attachment);\n\t\t\t}\n\t\t}\n\n\t\tif (media) {\n\t\t\tthis.attachmentCache.set(attachment.url, media);\n\t\t}\n\t\treturn media;\n\t}\n\n\t/**\n\t * Asynchronously processes an audio or video attachment provided as input and returns a Media object.\n\t * @param {Attachment} attachment - The attachment object containing information about the audio/video file.\n\t * @returns {Promise<Media>} A Promise that resolves to a Media object representing the processed audio/video attachment.\n\t */\n\tprivate async processAudioVideoAttachment(\n\t\tattachment: Attachment,\n\t): Promise<Media> {\n\t\ttry {\n\t\t\tconst response = await fetch(attachment.url);\n\t\t\tconst audioVideoArrayBuffer = await response.arrayBuffer();\n\n\t\t\tlet audioBuffer: Buffer;\n\t\t\tlet audioFileName: string;\n\t\t\tlet audioMimeType: string;\n\n\t\t\tif (attachment.contentType?.startsWith(\"audio/\")) {\n\t\t\t\taudioBuffer = Buffer.from(audioVideoArrayBuffer);\n\t\t\t\taudioFileName = attachment.name || \"audio.mp3\";\n\t\t\t\taudioMimeType = attachment.contentType;\n\t\t\t} else if (attachment.contentType?.startsWith(\"video/mp4\")) {\n\t\t\t\taudioBuffer = await this.extractAudioFromMP4(audioVideoArrayBuffer);\n\t\t\t\taudioFileName = \"extracted_audio.mp3\";\n\t\t\t\taudioMimeType = \"audio/mpeg\";\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"Unsupported audio/video format\");\n\t\t\t}\n\n\t\t\t// Convert Buffer to File object for transcription API\n\t\t\tconst audioBlob = new Blob([new Uint8Array(audioBuffer)], {\n\t\t\t\ttype: audioMimeType,\n\t\t\t});\n\t\t\tconst audioFile = new File([audioBlob], audioFileName, {\n\t\t\t\ttype: audioMimeType,\n\t\t\t});\n\n\t\t\t// Convert File to Buffer for transcription\n\t\t\tconst transcriptionBuffer = Buffer.from(await audioFile.arrayBuffer());\n\t\t\tconst transcription = await this.runtime.useModel(\n\t\t\t\tModelType.TRANSCRIPTION,\n\t\t\t\ttranscriptionBuffer,\n\t\t\t);\n\n\t\t\t// Assess transcription length before summarizing\n\t\t\tconst transcriptionLength = transcription?.length || 0;\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tattachmentId: attachment.id,\n\t\t\t\t\tcontentType: attachment.contentType,\n\t\t\t\t\ttranscriptionLength,\n\t\t\t\t},\n\t\t\t\t\"Assessing transcription length before summarization\",\n\t\t\t);\n\n\t\t\t// Only summarize if transcription is meaningful (not empty and long enough)\n\t\t\tlet title: string | undefined;\n\t\t\tlet description: string | undefined;\n\n\t\t\tif (!transcription || transcriptionLength === 0) {\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tattachmentId: attachment.id,\n\t\t\t\t\t},\n\t\t\t\t\t\"Transcription is empty, skipping summarization\",\n\t\t\t\t);\n\t\t\t\ttitle = undefined;\n\t\t\t\tdescription =\n\t\t\t\t\t\"User-uploaded audio/video attachment (no transcription available)\";\n\t\t\t} else if (transcriptionLength < 1000) {\n\t\t\t\t// Short transcriptions don't benefit from summarization\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tattachmentId: attachment.id,\n\t\t\t\t\t\ttranscriptionLength,\n\t\t\t\t\t},\n\t\t\t\t\t\"Transcription is short, skipping summarization\",\n\t\t\t\t);\n\t\t\t\ttitle = undefined;\n\t\t\t\tdescription = transcription;\n\t\t\t} else {\n\t\t\t\t// Transcription is long enough to benefit from summarization\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tattachmentId: attachment.id,\n\t\t\t\t\t\ttranscriptionLength,\n\t\t\t\t\t},\n\t\t\t\t\t\"Summarizing transcription\",\n\t\t\t\t);\n\t\t\t\tconst summary = await generateSummary(this.runtime, transcription);\n\t\t\t\ttitle = summary.title;\n\t\t\t\tdescription = summary.description;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tid: attachment.id,\n\t\t\t\turl: attachment.url,\n\t\t\t\ttitle: title || \"Audio/Video Attachment\",\n\t\t\t\tsource: attachment.contentType?.startsWith(\"audio/\")\n\t\t\t\t\t? \"Audio\"\n\t\t\t\t\t: \"Video\",\n\t\t\t\tdescription:\n\t\t\t\t\tdescription ||\n\t\t\t\t\t\"User-uploaded audio/video attachment which has been transcribed\",\n\t\t\t\ttext: transcription || \"Audio/video content not available\",\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tthis.runtime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tattachmentId: attachment.id,\n\t\t\t\t\tcontentType: attachment.contentType,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error processing audio/video attachment\",\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tid: attachment.id,\n\t\t\t\turl: attachment.url,\n\t\t\t\ttitle: \"Audio/Video Attachment\",\n\t\t\t\tsource: attachment.contentType?.startsWith(\"audio/\")\n\t\t\t\t\t? \"Audio\"\n\t\t\t\t\t: \"Video\",\n\t\t\t\tdescription: \"An audio/video attachment (transcription failed)\",\n\t\t\t\ttext: `This is an audio/video attachment. File name: ${attachment.name}, Size: ${attachment.size} bytes, Content type: ${attachment.contentType}`,\n\t\t\t};\n\t\t}\n\t}\n\n\t/**\n\t * Extracts the audio stream from the provided MP4 data and converts it to MP3 format.\n\t *\n\t * @param {ArrayBuffer} mp4Data - The MP4 data to extract audio from\n\t * @returns {Promise<Buffer>} - A Promise that resolves with the converted audio data as a Buffer\n\t */\n\tprivate async extractAudioFromMP4(mp4Data: ArrayBuffer): Promise<Buffer> {\n\t\t// Use fluent-ffmpeg to extract the audio stream from the MP4 data\n\t\t// and convert it to MP3 format\n\t\tconst tmpDir = os.tmpdir();\n\t\tconst timestamp = Date.now();\n\t\tconst tempMP4File = path.join(tmpDir, `discord_video_${timestamp}.mp4`);\n\t\tconst tempAudioFile = path.join(tmpDir, `discord_audio_${timestamp}.mp3`);\n\n\t\ttry {\n\t\t\t// Write the MP4 data to a temporary file\n\t\t\tfs.writeFileSync(tempMP4File, Buffer.from(mp4Data));\n\n\t\t\t// Check if file has audio stream using ffprobe\n\t\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\t\tffmpeg.ffprobe(tempMP4File, (err, metadata) => {\n\t\t\t\t\tif (err) {\n\t\t\t\t\t\treject(err);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!metadata.streams || !Array.isArray(metadata.streams)) {\n\t\t\t\t\t\treject(\n\t\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t\t\"File metadata does not contain valid streams information\",\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst hasAudio = metadata.streams.some(\n\t\t\t\t\t\t(stream) => stream.codec_type === \"audio\",\n\t\t\t\t\t);\n\t\t\t\t\tif (!hasAudio) {\n\t\t\t\t\t\treject(new Error(\"File does not contain any audio streams\"));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tresolve();\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\ttempMP4File,\n\t\t\t\t\ttempAudioFile,\n\t\t\t\t},\n\t\t\t\t\"Extracting audio from MP4\",\n\t\t\t);\n\n\t\t\t// Extract the audio stream and convert it to MP3\n\t\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\t\tffmpeg(tempMP4File)\n\t\t\t\t\t.noVideo() // Disable video output\n\t\t\t\t\t.audioCodec(\"libmp3lame\") // Set audio codec to MP3\n\t\t\t\t\t.toFormat(\"mp3\") // Explicitly set output format\n\t\t\t\t\t.on(\"end\", () => {\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t})\n\t\t\t\t\t.on(\"error\", (err) => {\n\t\t\t\t\t\treject(err);\n\t\t\t\t\t})\n\t\t\t\t\t.output(tempAudioFile)\n\t\t\t\t\t.run();\n\t\t\t});\n\n\t\t\t// Read the converted audio file and return it as a Buffer\n\t\t\tconst audioData = fs.readFileSync(tempAudioFile);\n\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\taudioDataSize: audioData.length,\n\t\t\t\t},\n\t\t\t\t\"Successfully extracted audio from MP4\",\n\t\t\t);\n\n\t\t\treturn audioData;\n\t\t} finally {\n\t\t\t// Clean up the temporary files\n\t\t\ttry {\n\t\t\t\tif (fs.existsSync(tempMP4File)) {\n\t\t\t\t\tfs.unlinkSync(tempMP4File);\n\t\t\t\t}\n\t\t\t\tif (fs.existsSync(tempAudioFile)) {\n\t\t\t\t\tfs.unlinkSync(tempAudioFile);\n\t\t\t\t}\n\t\t\t} catch (cleanupError) {\n\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\terror:\n\t\t\t\t\t\t\tcleanupError instanceof Error\n\t\t\t\t\t\t\t\t? cleanupError.message\n\t\t\t\t\t\t\t\t: String(cleanupError),\n\t\t\t\t\t},\n\t\t\t\t\t\"Failed to cleanup temp files\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Processes a PDF attachment by fetching the PDF file from the specified URL,\n\t * converting it to text, generating a summary, and returning a Media object\n\t * with the extracted information.\n\t * If an error occurs during processing, a placeholder Media object is returned\n\t * with an error message.\n\t *\n\t * @param {Attachment} attachment - The PDF attachment to process.\n\t * @returns {Promise<Media>} A promise that resolves to a Media object representing\n\t * the processed PDF attachment.\n\t */\n\tprivate async processPdfAttachment(attachment: Attachment): Promise<Media> {\n\t\ttry {\n\t\t\tconst response = await fetch(attachment.url);\n\t\t\tconst pdfBuffer = await response.arrayBuffer();\n\t\t\tconst pdfService = this.runtime.getService(ServiceType.PDF) as\n\t\t\t\t| ({ convertPdfToText: (buffer: Buffer) => Promise<string> } & Service)\n\t\t\t\t| null;\n\t\t\tif (!pdfService) {\n\t\t\t\tthrow new Error(\"PDF service not found\");\n\t\t\t}\n\t\t\tconst text = await pdfService.convertPdfToText(Buffer.from(pdfBuffer));\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tattachmentId: attachment.id,\n\t\t\t\t\ttextLength: text?.length,\n\t\t\t\t},\n\t\t\t\t\"Summarizing PDF content\",\n\t\t\t);\n\t\t\tconst { title, description } = await generateSummary(this.runtime, text);\n\n\t\t\treturn {\n\t\t\t\tid: attachment.id,\n\t\t\t\turl: attachment.url,\n\t\t\t\ttitle: title || \"PDF Attachment\",\n\t\t\t\tsource: \"PDF\",\n\t\t\t\tdescription: description || \"A PDF document\",\n\t\t\t\ttext,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tthis.runtime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tattachmentId: attachment.id,\n\t\t\t\t\tcontentType: attachment.contentType,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error processing PDF attachment\",\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tid: attachment.id,\n\t\t\t\turl: attachment.url,\n\t\t\t\ttitle: \"PDF Attachment (conversion failed)\",\n\t\t\t\tsource: \"PDF\",\n\t\t\t\tdescription: \"A PDF document that could not be converted to text\",\n\t\t\t\ttext: `This is a PDF attachment. File name: ${attachment.name}, Size: ${attachment.size} bytes`,\n\t\t\t};\n\t\t}\n\t}\n\n\t/**\n\t * Processes a plaintext attachment by fetching its content, generating a summary, and returning a Media object.\n\t * @param {Attachment} attachment - The attachment object to process.\n\t * @returns {Promise<Media>} A promise that resolves to a Media object representing the processed plaintext attachment.\n\t */\n\tprivate async processPlaintextAttachment(\n\t\tattachment: Attachment,\n\t): Promise<Media> {\n\t\ttry {\n\t\t\tconst response = await fetch(attachment.url);\n\t\t\tconst text = await response.text();\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tattachmentId: attachment.id,\n\t\t\t\t\ttextLength: text?.length,\n\t\t\t\t},\n\t\t\t\t\"Summarizing plaintext content\",\n\t\t\t);\n\t\t\tconst { title, description } = await generateSummary(this.runtime, text);\n\n\t\t\treturn {\n\t\t\t\tid: attachment.id,\n\t\t\t\turl: attachment.url,\n\t\t\t\ttitle: title || \"Plaintext Attachment\",\n\t\t\t\tsource: \"Plaintext\",\n\t\t\t\tdescription: description || \"A plaintext document\",\n\t\t\t\ttext,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tthis.runtime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tattachmentId: attachment.id,\n\t\t\t\t\tcontentType: attachment.contentType,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error processing plaintext attachment\",\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tid: attachment.id,\n\t\t\t\turl: attachment.url,\n\t\t\t\ttitle: \"Plaintext Attachment (retrieval failed)\",\n\t\t\t\tsource: \"Plaintext\",\n\t\t\t\tdescription: \"A plaintext document that could not be retrieved\",\n\t\t\t\ttext: `This is a plaintext attachment. File name: ${attachment.name}, Size: ${attachment.size} bytes`,\n\t\t\t};\n\t\t}\n\t}\n\n\t/**\n\t * Process the image attachment by fetching description and title using the IMAGE_DESCRIPTION model.\n\t * If successful, returns a Media object populated with the details. If unsuccessful, creates a fallback\n\t * Media object and logs the error.\n\t *\n\t * @param {Attachment} attachment - The attachment object containing the image details.\n\t * @returns {Promise<Media>} A promise that resolves to a Media object.\n\t */\n\tprivate async processImageAttachment(attachment: Attachment): Promise<Media> {\n\t\ttry {\n\t\t\tconst { description, title } = await this.runtime.useModel(\n\t\t\t\tModelType.IMAGE_DESCRIPTION,\n\t\t\t\tattachment.url,\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tid: attachment.id,\n\t\t\t\turl: attachment.url,\n\t\t\t\ttitle: title || \"Image Attachment\",\n\t\t\t\tsource: \"Image\",\n\t\t\t\tdescription: description || \"An image attachment\",\n\t\t\t\ttext: description || \"Image content not available\",\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tthis.runtime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tattachmentId: attachment.id,\n\t\t\t\t\tcontentType: attachment.contentType,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error processing image attachment\",\n\t\t\t);\n\n\t\t\treturn this.createFallbackImageMedia(attachment);\n\t\t}\n\t}\n\n\t/**\n\t * Creates a fallback Media object for image attachments that could not be recognized.\n\t *\n\t * @param {Attachment} attachment - The attachment object containing image details.\n\t * @returns {Media} - The fallback Media object with basic information about the image attachment.\n\t */\n\n\tprivate createFallbackImageMedia(attachment: Attachment): Media {\n\t\treturn {\n\t\t\tid: attachment.id,\n\t\t\turl: attachment.url,\n\t\t\ttitle: \"Image Attachment\",\n\t\t\tsource: \"Image\",\n\t\t\tdescription: \"An image attachment (recognition failed)\",\n\t\t\ttext: `This is an image attachment. File name: ${attachment.name}, Size: ${attachment.size} bytes, Content type: ${attachment.contentType}`,\n\t\t};\n\t}\n\n\t/**\n\t * Process a video attachment to extract video information.\n\t * @param {Attachment} attachment - The attachment object containing video information.\n\t * @returns {Promise<Media>} A promise that resolves to a Media object with video details.\n\t * @throws {Error} If video service is not available.\n\t */\n\tprivate async processVideoAttachment(attachment: Attachment): Promise<Media> {\n\t\tconst videoService = this.runtime.getService(ServiceType.VIDEO) as\n\t\t\t| ({\n\t\t\t\t\tisVideoUrl?: (url: string) => boolean;\n\t\t\t\t\tprocessVideo?: (\n\t\t\t\t\t\turl: string,\n\t\t\t\t\t\truntime: IAgentRuntime,\n\t\t\t\t\t) => Promise<{\n\t\t\t\t\t\ttitle: string;\n\t\t\t\t\t\tdescription: string;\n\t\t\t\t\t\ttext: string;\n\t\t\t\t\t}>;\n\t\t\t } & Service)\n\t\t\t| null;\n\n\t\tif (!videoService) {\n\t\t\treturn {\n\t\t\t\tid: attachment.id,\n\t\t\t\turl: attachment.url,\n\t\t\t\ttitle: \"Video Attachment (Service Unavailable)\",\n\t\t\t\tsource: \"Video\",\n\t\t\t\tdescription:\n\t\t\t\t\t\"Could not process video attachment because the required service is not available.\",\n\t\t\t\ttext: \"Video content not available\",\n\t\t\t};\n\t\t}\n\n\t\tif (\n\t\t\ttypeof videoService.isVideoUrl === \"function\" &&\n\t\t\tvideoService.isVideoUrl(attachment.url)\n\t\t) {\n\t\t\tconst videoInfo = await videoService.processVideo(\n\t\t\t\tattachment.url,\n\t\t\t\tthis.runtime,\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tid: attachment.id,\n\t\t\t\turl: attachment.url,\n\t\t\t\ttitle: videoInfo.title,\n\t\t\t\tsource: \"YouTube\",\n\t\t\t\tdescription: videoInfo.description,\n\t\t\t\ttext: videoInfo.text,\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tid: attachment.id,\n\t\t\turl: attachment.url,\n\t\t\ttitle: \"Video Attachment\",\n\t\t\tsource: \"Video\",\n\t\t\tdescription: \"A video attachment\",\n\t\t\ttext: \"Video content not available\",\n\t\t};\n\t}\n\n\t/**\n\t * Process a generic attachment and return a Media object with specified properties.\n\t * @param {Attachment} attachment - The attachment object to process.\n\t * @returns {Promise<Media>} A Promise that resolves to a Media object with specified properties.\n\t */\n\tprivate async processGenericAttachment(\n\t\tattachment: Attachment,\n\t): Promise<Media> {\n\t\treturn {\n\t\t\tid: attachment.id,\n\t\t\turl: attachment.url,\n\t\t\ttitle: \"Generic Attachment\",\n\t\t\tsource: \"Generic\",\n\t\t\tdescription: \"A generic attachment\",\n\t\t\ttext: \"Attachment content not available\",\n\t\t};\n\t}\n}\n",
|
|
120
|
+
"import {\n\ttype IAgentRuntime,\n\tlogger,\n\ttype Media,\n\tModelType,\n\tparseJSONObjectFromText,\n\ttrimTokens,\n} from \"@elizaos/core\";\nimport {\n\tActionRowBuilder,\n\ttype AttachmentBuilder,\n\tButtonBuilder,\n\tChannelType,\n\ttype Message as DiscordMessage,\n\ttype MessageActionRowComponentBuilder,\n\ttype MessageCreateOptions,\n\tPermissionsBitField,\n\tStringSelectMenuBuilder,\n\ttype TextChannel,\n\tThreadChannel,\n} from \"discord.js\";\nimport type {\n\tDiscordActionRow,\n\tDiscordComponentOptions,\n\tJsonValue,\n} from \"./types\";\n\nexport interface MessagingAPI {\n\tsendMessage: (\n\t\tagentId: string,\n\t\tmessage: unknown,\n\t\toptions?: { onResponse?: unknown },\n\t) => Promise<unknown>;\n}\n\nexport interface MessageServiceAPI {\n\thandleMessage: (\n\t\truntime: IAgentRuntime,\n\t\tmessage: unknown,\n\t\tcallback: unknown,\n\t) => Promise<unknown>;\n}\n\ninterface RuntimeWithMessagingAPI extends IAgentRuntime {\n\telizaOS: MessagingAPI;\n}\n\nexport function hasMessagingAPI(\n\truntime: IAgentRuntime,\n): runtime is RuntimeWithMessagingAPI {\n\treturn (\n\t\t\"elizaOS\" in runtime &&\n\t\ttypeof (runtime as { elizaOS?: { sendMessage?: unknown } }).elizaOS ===\n\t\t\t\"object\" &&\n\t\truntime.elizaOS !== null &&\n\t\ttypeof (runtime.elizaOS as { sendMessage?: unknown }).sendMessage ===\n\t\t\t\"function\"\n\t);\n}\n\nexport function hasMessageService(runtime: IAgentRuntime): boolean {\n\treturn (\n\t\truntime.messageService !== null &&\n\t\ttypeof runtime.messageService?.handleMessage === \"function\"\n\t);\n}\n\nexport function getMessagingAPI(runtime: IAgentRuntime): MessagingAPI | null {\n\tif (hasMessagingAPI(runtime)) {\n\t\treturn runtime.elizaOS;\n\t}\n\treturn null;\n}\n\nexport function getMessageService(\n\truntime: IAgentRuntime,\n): MessageServiceAPI | null {\n\tif (hasMessageService(runtime)) {\n\t\treturn runtime.messageService;\n\t}\n\treturn null;\n}\n\nexport const MAX_MESSAGE_LENGTH = 1900;\n\nexport function cleanUrl(url: string): string {\n\tlet clean = url;\n\n\tclean = clean.replace(/\\\\([._\\-~])/g, \"$1\");\n\n\tif (clean.startsWith(\"](\")) {\n\t\tclean = clean.substring(2);\n\t} else {\n\t\tconst markdownLinkPattern = /\\]\\(/;\n\t\tconst markdownPatternIdx = clean.search(markdownLinkPattern);\n\t\tif (markdownPatternIdx > -1) {\n\t\t\tclean = clean.substring(0, markdownPatternIdx);\n\t\t}\n\t}\n\n\tlet prev = \"\";\n\twhile (prev !== clean) {\n\t\tprev = clean;\n\t\tclean = clean.replace(/[)\\]>.,;!*_]+$/, \"\");\n\t\tclean = clean.replace(\n\t\t\t/[()[]【】{}《》〈〉「」『』、。,.;:!?~~]+$/,\n\t\t\t\"\",\n\t\t);\n\t}\n\n\treturn clean;\n}\n\nexport function extractUrls(text: string, runtime?: IAgentRuntime): string[] {\n\tconst urlRegex = /(https?:\\/\\/[^\\s]+)/g;\n\tconst rawUrls = text.match(urlRegex) || [];\n\n\treturn rawUrls\n\t\t.map((url) => {\n\t\t\tconst original = url;\n\t\t\tconst clean = cleanUrl(url);\n\n\t\t\tif (runtime && original !== clean) {\n\t\t\t\truntime.logger.debug(`URL cleaned: \"${original}\" -> \"${clean}\"`);\n\t\t\t}\n\n\t\t\treturn clean;\n\t\t})\n\t\t.filter((url) => {\n\t\t\ttry {\n\t\t\t\tnew URL(url);\n\t\t\t\treturn true;\n\t\t\t} catch {\n\t\t\t\tif (runtime) {\n\t\t\t\t\truntime.logger.debug(`Invalid URL after cleanup, skipping: \"${url}\"`);\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n}\n\nexport function getAttachmentFileName(media: Media): string {\n\tlet extension = \"\";\n\ttry {\n\t\tconst urlPath = new URL(media.url).pathname;\n\t\tconst urlExtension = urlPath.substring(urlPath.lastIndexOf(\".\"));\n\t\tif (urlExtension && urlExtension.length > 1 && urlExtension.length <= 5) {\n\t\t\textension = urlExtension;\n\t\t}\n\t} catch {\n\t\tconst lastDot = media.url.lastIndexOf(\".\");\n\t\tconst queryStart = media.url.indexOf(\"?\", lastDot);\n\t\tif (lastDot > 0 && (queryStart === -1 || queryStart > lastDot + 1)) {\n\t\t\tconst potentialExt = media.url.substring(\n\t\t\t\tlastDot,\n\t\t\t\tqueryStart > -1 ? queryStart : undefined,\n\t\t\t);\n\t\t\tif (potentialExt.length > 1 && potentialExt.length <= 5) {\n\t\t\t\textension = potentialExt;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!extension && media.contentType) {\n\t\tconst contentTypeMap: Record<string, string> = {\n\t\t\timage: \".png\",\n\t\t\tvideo: \".mp4\",\n\t\t\taudio: \".mp3\",\n\t\t\tdocument: \".txt\",\n\t\t\tlink: \".html\",\n\t\t};\n\t\textension = contentTypeMap[media.contentType] || \"\";\n\t}\n\n\tif (!extension) {\n\t\textension = \".txt\";\n\t}\n\n\tconst baseName = media.title || media.id || \"attachment\";\n\tconst hasExtension = /\\.\\w{1,5}$/i.test(baseName);\n\n\treturn hasExtension ? baseName : `${baseName}${extension}`;\n}\n\nexport async function generateSummary(\n\truntime: IAgentRuntime,\n\ttext: string,\n): Promise<{ title: string; description: string }> {\n\ttext = await trimTokens(text, 100000, runtime);\n\n\tif (!text) {\n\t\treturn {\n\t\t\ttitle: \"\",\n\t\t\tdescription: \"\",\n\t\t};\n\t}\n\n\tif (text.length < 1000) {\n\t\treturn {\n\t\t\ttitle: \"\",\n\t\t\tdescription: text,\n\t\t};\n\t}\n\n\truntime.logger.info(\n\t\t`[Summarization] Calling TEXT_SMALL for ${text.length} chars: \"${text.substring(0, 50).replace(/\\n/g, \" \")}...\"`,\n\t);\n\n\tconst prompt = `Please generate a concise summary for the following text:\n\n Text: \"\"\"\n ${text}\n \"\"\"\n\n Respond with a JSON object in the following format:\n \\`\\`\\`json\n {\n \"title\": \"Generated Title\",\n \"summary\": \"Generated summary and/or description of the text\"\n }\n \\`\\`\\``;\n\n\tconst response = await runtime.useModel(ModelType.TEXT_SMALL, {\n\t\tprompt,\n\t});\n\n\tconst parsedResponse = parseJSONObjectFromText(response) as {\n\t\ttitle?: string;\n\t\tsummary?: string;\n\t} | null;\n\n\tif (\n\t\tparsedResponse &&\n\t\ttypeof parsedResponse.title === \"string\" &&\n\t\ttypeof parsedResponse.summary === \"string\"\n\t) {\n\t\treturn {\n\t\t\ttitle: parsedResponse.title,\n\t\t\tdescription: parsedResponse.summary,\n\t\t};\n\t}\n\n\treturn {\n\t\ttitle: \"\",\n\t\tdescription: \"\",\n\t};\n}\n\n/**\n * Discord API error structure\n */\ninterface DiscordAPIError extends Error {\n\tcode?: number;\n}\n\n/**\n * Type guard for Discord API errors\n */\nfunction isDiscordAPIError(error: unknown): error is DiscordAPIError {\n\treturn error instanceof Error && \"code\" in error;\n}\n\n/**\n * Discord.js component with toJSON method\n */\ninterface DiscordJsComponent {\n\ttoJSON(): JsonValue;\n}\n\n/**\n * Type guard for Discord.js components\n */\nfunction isDiscordJsComponent(\n\tcomponent: unknown,\n): component is DiscordJsComponent {\n\treturn (\n\t\tcomponent !== null &&\n\t\ttypeof component === \"object\" &&\n\t\t\"toJSON\" in component &&\n\t\ttypeof (component as DiscordJsComponent).toJSON === \"function\"\n\t);\n}\n\n/**\n * Type guard for arrays of Discord.js components (ActionRowBuilder)\n */\nfunction isDiscordJsComponentArray(\n\tcomponents: unknown[],\n): components is ActionRowBuilder<MessageActionRowComponentBuilder>[] {\n\treturn components.length > 0 && components.every(isDiscordJsComponent);\n}\n\n/**\n * Safe JSON stringify that handles BigInt values\n */\nfunction safeStringify(obj: unknown): string {\n\treturn JSON.stringify(obj, (_, value) =>\n\t\ttypeof value === \"bigint\" ? value.toString() : value,\n\t);\n}\n\n/**\n * Message send options for Discord\n */\ninterface MessageSendOptions {\n\tcontent: string;\n\treply?: {\n\t\tmessageReference: string;\n\t};\n\tfiles?: Array<\n\t\tAttachmentBuilder | { attachment: Buffer | string; name: string }\n\t>;\n\tcomponents?: ActionRowBuilder<MessageActionRowComponentBuilder>[];\n}\n\nexport async function sendMessageInChunks(\n\tchannel: TextChannel,\n\tcontent: string,\n\tinReplyTo: string,\n\tfiles: Array<\n\t\tAttachmentBuilder | { attachment: Buffer | string; name: string }\n\t>,\n\tcomponents?: DiscordActionRow[],\n\truntime?: IAgentRuntime,\n): Promise<DiscordMessage[]> {\n\tconst sentMessages: DiscordMessage[] = [];\n\n\tlet messages: string[];\n\tif (\n\t\truntime &&\n\t\tcontent.length > MAX_MESSAGE_LENGTH &&\n\t\tneedsSmartSplit(content)\n\t) {\n\t\tmessages = await smartSplitMessage(runtime, content);\n\t} else {\n\t\tmessages = splitMessage(content);\n\t}\n\ttry {\n\t\tfor (let i = 0; i < messages.length; i++) {\n\t\t\tconst message = messages[i];\n\t\t\tif (\n\t\t\t\tmessage.trim().length > 0 ||\n\t\t\t\t(i === messages.length - 1 && files && files.length > 0) ||\n\t\t\t\tcomponents\n\t\t\t) {\n\t\t\t\tconst options: MessageSendOptions = {\n\t\t\t\t\tcontent: message.trim(),\n\t\t\t\t};\n\n\t\t\t\tif (i === 0 && inReplyTo) {\n\t\t\t\t\toptions.reply = {\n\t\t\t\t\t\tmessageReference: inReplyTo,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tif (i === messages.length - 1 && files && files.length > 0) {\n\t\t\t\t\toptions.files = files;\n\t\t\t\t}\n\n\t\t\t\tif (i === messages.length - 1 && components && components.length > 0) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlogger.info(`Components received: ${safeStringify(components)}`);\n\n\t\t\t\t\t\tif (!Array.isArray(components)) {\n\t\t\t\t\t\t\tlogger.warn(\n\t\t\t\t\t\t\t\t\"Components is not an array, skipping component processing\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} else if (isDiscordJsComponentArray(components)) {\n\t\t\t\t\t\t\toptions.components = components;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst discordComponents = (components as DiscordActionRow[])\n\t\t\t\t\t\t\t\t.map((row: DiscordActionRow) => {\n\t\t\t\t\t\t\t\t\tif (!row || typeof row !== \"object\" || row.type !== 1) {\n\t\t\t\t\t\t\t\t\t\tlogger.warn(\"Invalid component row structure, skipping\");\n\t\t\t\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif (row.type === 1) {\n\t\t\t\t\t\t\t\t\t\tconst actionRow =\n\t\t\t\t\t\t\t\t\t\t\tnew ActionRowBuilder<MessageActionRowComponentBuilder>();\n\n\t\t\t\t\t\t\t\t\t\tif (!Array.isArray(row.components)) {\n\t\t\t\t\t\t\t\t\t\t\tlogger.warn(\"Row components is not an array, skipping\");\n\t\t\t\t\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tconst validComponents = row.components\n\t\t\t\t\t\t\t\t\t\t\t.map((comp: DiscordComponentOptions) => {\n\t\t\t\t\t\t\t\t\t\t\t\tif (!comp || typeof comp !== \"object\") {\n\t\t\t\t\t\t\t\t\t\t\t\t\tlogger.warn(\"Invalid component, skipping\");\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (comp.type === 2) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn new ButtonBuilder()\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.setCustomId(comp.custom_id)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.setLabel(comp.label || \"\")\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.setStyle(comp.style || 1);\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (comp.type === 3) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst selectMenu = new StringSelectMenuBuilder()\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.setCustomId(comp.custom_id)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.setPlaceholder(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcomp.placeholder || \"Select an option\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (typeof comp.min_values === \"number\") {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tselectMenu.setMinValues(comp.min_values);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (typeof comp.max_values === \"number\") {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tselectMenu.setMaxValues(comp.max_values);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (Array.isArray(comp.options)) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tselectMenu.addOptions(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcomp.options.map((option) => ({\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlabel: option.label,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: option.value,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: option.description,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn selectMenu;\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tlogger.error(`Error creating component: ${err}`);\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t\t.filter(Boolean);\n\n\t\t\t\t\t\t\t\t\t\tif (validComponents.length > 0) {\n\t\t\t\t\t\t\t\t\t\t\tactionRow.addComponents(validComponents);\n\t\t\t\t\t\t\t\t\t\t\treturn actionRow;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.filter(Boolean);\n\n\t\t\t\t\t\t\tif (discordComponents.length > 0) {\n\t\t\t\t\t\t\t\toptions.components = discordComponents;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tlogger.error(`Error processing components: ${error}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tconst m = await channel.send(options as MessageCreateOptions);\n\t\t\t\t\tsentMessages.push(m);\n\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tisDiscordAPIError(error) &&\n\t\t\t\t\t\terror.code === 50035 &&\n\t\t\t\t\t\terror.message &&\n\t\t\t\t\t\terror.message.includes(\"Unknown message\")\n\t\t\t\t\t) {\n\t\t\t\t\t\tlogger.warn(\n\t\t\t\t\t\t\t\"Message reference no longer valid (message may have been deleted). Sending without reply threading.\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst optionsWithoutReply = { ...options };\n\t\t\t\t\t\tdelete optionsWithoutReply.reply;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst m = await channel.send(\n\t\t\t\t\t\t\t\toptionsWithoutReply as MessageCreateOptions,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tsentMessages.push(m);\n\t\t\t\t\t\t} catch (retryError: unknown) {\n\t\t\t\t\t\t\tconst errorMessage =\n\t\t\t\t\t\t\t\tretryError instanceof Error\n\t\t\t\t\t\t\t\t\t? retryError.message\n\t\t\t\t\t\t\t\t\t: String(retryError);\n\t\t\t\t\t\t\tlogger.error(\n\t\t\t\t\t\t\t\t`Error sending message after removing reply reference: ${errorMessage}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tthrow retryError;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\tlogger.error(`Error sending message: ${error}`);\n\t}\n\n\treturn sentMessages;\n}\n\nexport function needsSmartSplit(content: string): boolean {\n\tconst codeBlockCount = (content.match(/```/g) || []).length;\n\tif (codeBlockCount >= 2) {\n\t\treturn true;\n\t}\n\n\tif (/^#{1,3}\\s/m.test(content)) {\n\t\treturn true;\n\t}\n\n\tif (/^\\d+\\.\\s/m.test(content)) {\n\t\treturn true;\n\t}\n\n\tconst lines = content.split(\"\\n\");\n\tconst hasLongUnbreakableLines = lines.some(\n\t\t(line) => line.length > 500 && !line.includes(\". \") && !line.includes(\", \"),\n\t);\n\tif (hasLongUnbreakableLines) {\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nfunction parseJSONArrayFromText(text: string): JsonValue[] | null {\n\tconst jsonBlockPattern = /```json\\n([\\s\\S]*?)\\n```/;\n\tlet jsonData: JsonValue = null;\n\tconst jsonBlockMatch = text.match(jsonBlockPattern);\n\n\ttry {\n\t\tif (jsonBlockMatch) {\n\t\t\tjsonData = JSON.parse(jsonBlockMatch[1].trim()) as JsonValue;\n\t\t} else {\n\t\t\tjsonData = JSON.parse(text.trim()) as JsonValue;\n\t\t}\n\t} catch (_e) {\n\t\treturn null;\n\t}\n\n\tif (Array.isArray(jsonData)) {\n\t\treturn jsonData;\n\t}\n\n\treturn null;\n}\n\nexport async function smartSplitMessage(\n\truntime: IAgentRuntime,\n\tcontent: string,\n\tmaxLength: number = MAX_MESSAGE_LENGTH,\n): Promise<string[]> {\n\tif (content.length <= maxLength) {\n\t\treturn [content];\n\t}\n\n\tconst estimatedChunks = Math.ceil(content.length / (maxLength - 100));\n\n\ttry {\n\t\truntime.logger.debug(\n\t\t\t`Smart splitting ${content.length} chars into ~${estimatedChunks} chunks`,\n\t\t);\n\n\t\tconst prompt = `Split the following text into ${estimatedChunks} parts for Discord messages (max ${maxLength} chars each).\nKeep related content together (don't split code blocks, keep list items with their headers, etc.).\nReturn ONLY a JSON array of strings, no explanation.\n\nText to split:\n\"\"\"\n${content}\n\"\"\"\n\nReturn format: [\"chunk1\", \"chunk2\", ...]`;\n\n\t\tconst response = await runtime.useModel(ModelType.TEXT_SMALL, { prompt });\n\n\t\tconst parsed = parseJSONArrayFromText(response);\n\t\tif (Array.isArray(parsed)) {\n\t\t\tconst validChunks = parsed.filter(\n\t\t\t\t(chunk: unknown): chunk is string =>\n\t\t\t\t\ttypeof chunk === \"string\" &&\n\t\t\t\t\tchunk.trim().length > 0 &&\n\t\t\t\t\tchunk.length <= maxLength,\n\t\t\t);\n\n\t\t\tif (validChunks.length > 0) {\n\t\t\t\treturn validChunks;\n\t\t\t}\n\n\t\t\truntime.logger.debug(\n\t\t\t\t\"Smart split returned empty or invalid chunks, falling back to simple split\",\n\t\t\t);\n\t\t}\n\t} catch (error) {\n\t\truntime.logger.debug(\n\t\t\t`Smart split failed, falling back to simple split: ${error}`,\n\t\t);\n\t}\n\n\treturn splitMessage(content, maxLength);\n}\n\nexport function splitMessage(\n\tcontent: string,\n\tmaxLength: number = MAX_MESSAGE_LENGTH,\n): string[] {\n\tif (!content || content.length <= maxLength) {\n\t\treturn content ? [content] : [];\n\t}\n\n\tconst messages: string[] = [];\n\tlet currentMessage = \"\";\n\n\tconst rawLines = content.split(\"\\n\");\n\tconst lines = rawLines.flatMap((line) => {\n\t\tconst chunks: string[] = [];\n\t\twhile (line.length > maxLength) {\n\t\t\tlet splitIdx = maxLength;\n\t\t\tconst lastSpace = line.lastIndexOf(\" \", maxLength);\n\n\t\t\tif (lastSpace > maxLength * 0.7) {\n\t\t\t\tsplitIdx = lastSpace;\n\t\t\t} else if (lastSpace > maxLength * 0.3) {\n\t\t\t\tsplitIdx = lastSpace;\n\t\t\t}\n\n\t\t\tchunks.push(line.slice(0, splitIdx));\n\t\t\tline = line.slice(splitIdx).trimStart();\n\t\t}\n\t\tchunks.push(line);\n\t\treturn chunks;\n\t});\n\n\tfor (const line of lines) {\n\t\tif (currentMessage.length + line.length + 1 > maxLength) {\n\t\t\tif (currentMessage.trim().length > 0) {\n\t\t\t\tmessages.push(currentMessage.trim());\n\t\t\t}\n\t\t\tcurrentMessage = \"\";\n\t\t}\n\t\tcurrentMessage += `${line}\\n`;\n\t}\n\n\tif (currentMessage.trim().length > 0) {\n\t\tmessages.push(currentMessage.trim());\n\t}\n\n\tif (messages.length === 0 && content.length > 0) {\n\t\tmessages.push(\" \");\n\t}\n\n\treturn messages;\n}\n\nexport interface CanSendMessageResult {\n\tcanSend: boolean;\n\treason: string | null;\n\tmissingPermissions?: bigint[];\n}\n\ntype SendableChannel = TextChannel | ThreadChannel | { type: ChannelType };\n\nexport function canSendMessage(\n\tchannel: SendableChannel | null | undefined,\n): CanSendMessageResult {\n\tif (!channel) {\n\t\treturn {\n\t\t\tcanSend: false,\n\t\t\treason: \"No channel given\",\n\t\t};\n\t}\n\tif (channel.type === ChannelType.DM) {\n\t\treturn {\n\t\t\tcanSend: true,\n\t\t\treason: null,\n\t\t};\n\t}\n\n\tif (!(\"guild\" in channel) || !channel.guild) {\n\t\treturn {\n\t\t\tcanSend: false,\n\t\t\treason: \"Not a guild channel\",\n\t\t};\n\t}\n\n\tconst guildChannel = channel as TextChannel | ThreadChannel;\n\tconst botMember = guildChannel.guild.members.cache.get(\n\t\tguildChannel.client.user.id,\n\t);\n\n\tif (!botMember) {\n\t\treturn {\n\t\t\tcanSend: false,\n\t\t\treason: \"Bot member not found in guild\",\n\t\t};\n\t}\n\n\tconst requiredPermissions: bigint[] = [\n\t\tPermissionsBitField.Flags.ViewChannel,\n\t\tPermissionsBitField.Flags.SendMessages,\n\t\tPermissionsBitField.Flags.ReadMessageHistory,\n\t];\n\n\tif (guildChannel instanceof ThreadChannel) {\n\t\trequiredPermissions.push(PermissionsBitField.Flags.SendMessagesInThreads);\n\t}\n\n\tconst permissions = guildChannel.permissionsFor(botMember);\n\n\tif (!permissions) {\n\t\treturn {\n\t\t\tcanSend: false,\n\t\t\treason: \"Could not retrieve permissions\",\n\t\t};\n\t}\n\n\tconst missingPermissions = requiredPermissions.filter(\n\t\t(perm) => !permissions.has(perm),\n\t);\n\n\treturn {\n\t\tcanSend: missingPermissions.length === 0,\n\t\tmissingPermissions,\n\t\treason:\n\t\t\tmissingPermissions.length > 0\n\t\t\t\t? `Missing permissions: ${missingPermissions.map((p) => String(p)).join(\", \")}`\n\t\t\t\t: null,\n\t};\n}\n",
|
|
121
|
+
"import type { IAgentRuntime } from \"@elizaos/core\";\nimport type {\n\tAuditLogEvent,\n\tGuild,\n\tGuildMember,\n\tPermissionOverwrites,\n\tRole,\n} from \"discord.js\";\nimport type { AuditInfo, PermissionDiff, PermissionState } from \"./types\";\n\n/**\n * Permissions that indicate moderation/admin capabilities.\n * Changes to these permissions are considered elevated and worth tracking.\n */\nexport const ELEVATED_PERMISSIONS = [\n\t\"Administrator\",\n\t\"ManageGuild\",\n\t\"ManageChannels\",\n\t\"ManageRoles\",\n\t\"KickMembers\",\n\t\"BanMembers\",\n\t\"ModerateMembers\",\n\t\"ManageMessages\",\n\t\"ManageWebhooks\",\n\t\"ManageNicknames\",\n\t\"MuteMembers\",\n\t\"DeafenMembers\",\n\t\"MoveMembers\",\n\t\"ManageEvents\",\n\t\"ManageThreads\",\n] as const;\n\n/**\n * Check if a role has any elevated (moderation/admin) permissions\n */\nexport function isElevatedRole(role: Role): boolean {\n\treturn ELEVATED_PERMISSIONS.some((p) => role.permissions.has(p));\n}\n\n/**\n * Check if an array of permission names contains any elevated permissions\n */\nexport function hasElevatedPermissions(permissions: string[]): boolean {\n\treturn permissions.some((p) =>\n\t\tELEVATED_PERMISSIONS.includes(p as (typeof ELEVATED_PERMISSIONS)[number]),\n\t);\n}\n\n/**\n * Fetch the most recent matching audit log entry for an action.\n * Matches by target ID and filters to entries within 10 seconds.\n * Returns null gracefully on errors (rate limits, missing permissions, etc.)\n */\nexport async function fetchAuditEntry(\n\tguild: Guild,\n\tactionType: AuditLogEvent,\n\ttarget: string,\n\truntime: IAgentRuntime,\n): Promise<AuditInfo | null> {\n\ttry {\n\t\tconst logs = await guild.fetchAuditLogs({ type: actionType, limit: 5 });\n\t\tconst now = Date.now();\n\n\t\tfor (const entry of logs.entries.values()) {\n\t\t\t// Match by target and ensure entry is recent (within 10 seconds)\n\t\t\t// Type guard: entry.target can be various types, not all have 'id'\n\t\t\tconst targetId =\n\t\t\t\tentry.target && \"id\" in entry.target ? entry.target.id : undefined;\n\t\t\tif (targetId === target && now - entry.createdTimestamp < 10000) {\n\t\t\t\treturn {\n\t\t\t\t\texecutorId: entry.executor?.id ?? \"unknown\",\n\t\t\t\t\texecutorTag: entry.executor?.tag ?? \"Unknown\",\n\t\t\t\t\treason: entry.reason,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t} catch (err) {\n\t\t// Graceful degradation - rate limits, missing permissions, etc.\n\t\truntime.logger.debug(`Audit log fetch failed (non-critical): ${err}`);\n\t}\n\treturn null;\n}\n\n/**\n * Get the permission state from allow/deny arrays\n */\nfunction getState(\n\tperm: string,\n\tallow: string[],\n\tdeny: string[],\n): PermissionState {\n\tif (allow.includes(perm)) {\n\t\treturn \"ALLOW\";\n\t}\n\tif (deny.includes(perm)) {\n\t\treturn \"DENY\";\n\t}\n\treturn \"NEUTRAL\";\n}\n\n/**\n * Convert an overwrite to a list of changes (used for CREATE/DELETE)\n * For CREATE: from NEUTRAL to the actual state (ALLOW/DENY)\n * For DELETE: from the actual state (ALLOW/DENY) to NEUTRAL\n */\nfunction overwriteToChanges(\n\tow: PermissionOverwrites,\n\tisDelete: boolean = false,\n): PermissionDiff[] {\n\tconst changes: PermissionDiff[] = [];\n\tfor (const p of ow.allow.toArray()) {\n\t\tchanges.push({\n\t\t\tpermission: p,\n\t\t\toldState: isDelete ? \"ALLOW\" : \"NEUTRAL\",\n\t\t\tnewState: isDelete ? \"NEUTRAL\" : \"ALLOW\",\n\t\t});\n\t}\n\tfor (const p of ow.deny.toArray()) {\n\t\tchanges.push({\n\t\t\tpermission: p,\n\t\t\toldState: isDelete ? \"DENY\" : \"NEUTRAL\",\n\t\t\tnewState: isDelete ? \"NEUTRAL\" : \"DENY\",\n\t\t});\n\t}\n\treturn changes;\n}\n\n/**\n * Diff two permission overwrites and determine what changed.\n * Returns the list of changes and the action type (CREATE/UPDATE/DELETE).\n */\nexport function diffOverwrites(\n\toldOw: PermissionOverwrites | undefined | null,\n\tnewOw: PermissionOverwrites | undefined | null,\n): { changes: PermissionDiff[]; action: \"CREATE\" | \"UPDATE\" | \"DELETE\" } {\n\t// Both null - no change\n\tif (!oldOw && !newOw) {\n\t\treturn { changes: [], action: \"UPDATE\" };\n\t}\n\n\t// Created new overwrite\n\tif (!oldOw && newOw) {\n\t\treturn { changes: overwriteToChanges(newOw, false), action: \"CREATE\" };\n\t}\n\n\t// Deleted overwrite\n\tif (oldOw && !newOw) {\n\t\treturn { changes: overwriteToChanges(oldOw, true), action: \"DELETE\" };\n\t}\n\n\t// Updated overwrite - compare old and new\n\tconst changes: PermissionDiff[] = [];\n\tconst oldAllow = oldOw?.allow.toArray();\n\tconst oldDeny = oldOw?.deny.toArray();\n\tconst newAllow = newOw?.allow.toArray();\n\tconst newDeny = newOw?.deny.toArray();\n\n\t// Get all permissions that exist in either old or new\n\tconst allPerms = new Set([...oldAllow, ...oldDeny, ...newAllow, ...newDeny]);\n\n\tfor (const perm of allPerms) {\n\t\tconst oldState = getState(perm, oldAllow, oldDeny);\n\t\tconst newState = getState(perm, newAllow, newDeny);\n\t\tif (oldState !== newState) {\n\t\t\tchanges.push({ permission: perm, oldState, newState });\n\t\t}\n\t}\n\n\treturn { changes, action: \"UPDATE\" };\n}\n\n/**\n * Diff two role permission sets and return what changed.\n */\nexport function diffRolePermissions(\n\toldRole: Role,\n\tnewRole: Role,\n): PermissionDiff[] {\n\tconst oldPerms = oldRole.permissions.toArray();\n\tconst newPerms = newRole.permissions.toArray();\n\tconst changes: PermissionDiff[] = [];\n\n\t// Find added permissions\n\tfor (const p of newPerms) {\n\t\tif (!oldPerms.includes(p)) {\n\t\t\tchanges.push({ permission: p, oldState: \"NEUTRAL\", newState: \"ALLOW\" });\n\t\t}\n\t}\n\n\t// Find removed permissions\n\tfor (const p of oldPerms) {\n\t\tif (!newPerms.includes(p)) {\n\t\t\tchanges.push({ permission: p, oldState: \"ALLOW\", newState: \"NEUTRAL\" });\n\t\t}\n\t}\n\n\treturn changes;\n}\n\n/**\n * Diff member roles to find added and removed roles.\n */\nexport function diffMemberRoles(\n\toldMember: GuildMember,\n\tnewMember: GuildMember,\n): { added: Role[]; removed: Role[] } {\n\tconst oldRoles = oldMember.roles.cache;\n\tconst newRoles = newMember.roles.cache;\n\n\treturn {\n\t\tadded: [...newRoles.filter((r) => !oldRoles.has(r.id)).values()],\n\t\tremoved: [...oldRoles.filter((r) => !newRoles.has(r.id)).values()],\n\t};\n}\n",
|
|
122
|
+
"import { EventEmitter } from \"node:events\";\nimport { pipeline, Readable, type Transform } from \"node:stream\";\nimport {\n\ttype AudioPlayer,\n\ttype AudioReceiveStream,\n\tcreateAudioPlayer,\n\tcreateAudioResource,\n\tentersState,\n\tgetVoiceConnections,\n\tjoinVoiceChannel,\n\tNoSubscriberBehavior,\n\tStreamType,\n\ttype VoiceConnection,\n\tVoiceConnectionStatus,\n} from \"@discordjs/voice\";\nimport {\n\tChannelType,\n\ttype Content,\n\tcreateUniqueUuid,\n\tEventType,\n\ttype HandlerCallback,\n\tlogger,\n\ttype Memory,\n\tModelType,\n\tstringToUuid,\n\ttype UUID,\n} from \"@elizaos/core\";\nimport {\n\ttype BaseGuildVoiceChannel,\n\ttype Channel,\n\ttype Client,\n\tChannelType as DiscordChannelType,\n\ttype Guild,\n\ttype GuildMember,\n\ttype VoiceChannel,\n\ttype VoiceState,\n} from \"discord.js\";\nimport prism from \"prism-media\";\n// See service.ts for detailed documentation on Discord ID handling.\n// Key point: Discord snowflake IDs (e.g., \"1253563208833433701\") are NOT valid UUIDs.\n// Use stringToUuid() to convert them, not asUUID() which would throw an error.\nimport type { ICompatRuntime } from \"./compat\";\nimport type { DiscordService } from \"./service\";\nimport { getMessageService } from \"./utils\";\n\n// These values are chosen for compatibility with picovoice components\nconst DECODE_FRAME_SIZE = 1024;\nconst DECODE_SAMPLE_RATE = 16000;\n\n/**\n * Creates an opus decoder with fallback handling for different opus libraries\n * @param options - Decoder options including channels, rate, and frameSize\n * @returns An opus decoder instance or null if creation fails\n */\nfunction createOpusDecoder(options: {\n\tchannels: number;\n\trate: number;\n\tframeSize: number;\n}): Transform {\n\ttry {\n\t\t// First try to create decoder with prism-media\n\t\treturn new prism.opus.Decoder(options);\n\t} catch (error) {\n\t\t// Standalone function - no runtime context available\n\t\tlogger.warn(\n\t\t\t{\n\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t},\n\t\t\t\"Failed to create opus decoder\",\n\t\t);\n\n\t\t// Log available opus libraries for debugging\n\t\ttry {\n\t\t\tconst { generateDependencyReport } = require(\"@discordjs/voice\");\n\t\t\tconst report = generateDependencyReport();\n\t\t\tlogger.debug(\n\t\t\t\t{ src: \"plugin:discord:service:voice\", report },\n\t\t\t\t\"Voice dependency report\",\n\t\t\t);\n\t\t} catch (reportError) {\n\t\t\tlogger.warn(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\terror:\n\t\t\t\t\t\treportError instanceof Error\n\t\t\t\t\t\t\t? reportError.message\n\t\t\t\t\t\t\t: String(reportError),\n\t\t\t\t},\n\t\t\t\t\"Could not generate dependency report\",\n\t\t\t);\n\t\t}\n\n\t\tthrow error;\n\t}\n}\n\n/**\n * Generates a WAV file header based on the provided audio parameters.\n * @param {number} audioLength - The length of the audio data in bytes.\n * @param {number} sampleRate - The sample rate of the audio.\n * @param {number} [channelCount=1] - The number of channels (default is 1).\n * @param {number} [bitsPerSample=16] - The number of bits per sample (default is 16).\n * @returns {Buffer} The WAV file header as a Buffer object.\n */\nfunction getWavHeader(\n\taudioLength: number,\n\tsampleRate: number,\n\tchannelCount = 1,\n\tbitsPerSample = 16,\n): Buffer {\n\tconst wavHeader = Buffer.alloc(44);\n\twavHeader.write(\"RIFF\", 0);\n\twavHeader.writeUInt32LE(36 + audioLength, 4); // Length of entire file in bytes minus 8\n\twavHeader.write(\"WAVE\", 8);\n\twavHeader.write(\"fmt \", 12);\n\twavHeader.writeUInt32LE(16, 16); // Length of format data\n\twavHeader.writeUInt16LE(1, 20); // Type of format (1 is PCM)\n\twavHeader.writeUInt16LE(channelCount, 22); // Number of channels\n\twavHeader.writeUInt32LE(sampleRate, 24); // Sample rate\n\twavHeader.writeUInt32LE((sampleRate * bitsPerSample * channelCount) / 8, 28); // Byte rate\n\twavHeader.writeUInt16LE((bitsPerSample * channelCount) / 8, 32); // Block align ((BitsPerSample * Channels) / 8)\n\twavHeader.writeUInt16LE(bitsPerSample, 34); // Bits per sample\n\twavHeader.write(\"data\", 36); // Data chunk header\n\twavHeader.writeUInt32LE(audioLength, 40); // Data chunk size\n\treturn wavHeader;\n}\n\n/**\n * Class representing an AudioMonitor that listens for audio data from a Readable stream.\n */\nexport class AudioMonitor {\n\tprivate readable: Readable;\n\tprivate buffers: Buffer[] = [];\n\tprivate maxSize: number;\n\tprivate lastFlagged = -1;\n\tprivate ended = false;\n\n\t/**\n\t * Constructs an AudioMonitor instance.\n\t * @param {Readable} readable - The readable stream to monitor for audio data.\n\t * @param {number} maxSize - The maximum size of the audio buffer.\n\t * @param {function} onStart - The callback function to be called when audio starts.\n\t * @param {function} callback - The callback function to process audio data.\n\t */\n\tconstructor(\n\t\treadable: Readable,\n\t\tmaxSize: number,\n\t\tonStart: () => void,\n\t\tcallback: (buffer: Buffer) => void,\n\t) {\n\t\tthis.readable = readable;\n\t\tthis.maxSize = maxSize;\n\t\tthis.readable.on(\"data\", (chunk: Buffer) => {\n\t\t\tif (this.lastFlagged < 0) {\n\t\t\t\tthis.lastFlagged = this.buffers.length;\n\t\t\t}\n\t\t\tthis.buffers.push(chunk);\n\t\t\tconst currentSize = this.buffers.reduce(\n\t\t\t\t(acc, cur) => acc + cur.length,\n\t\t\t\t0,\n\t\t\t);\n\t\t\twhile (currentSize > this.maxSize) {\n\t\t\t\tthis.buffers.shift();\n\t\t\t\tthis.lastFlagged--;\n\t\t\t}\n\t\t});\n\t\tthis.readable.on(\"end\", () => {\n\t\t\tlogger.debug(\n\t\t\t\t{ src: \"plugin:discord:service:voice\" },\n\t\t\t\t\"AudioMonitor ended\",\n\t\t\t);\n\t\t\tthis.ended = true;\n\t\t\tif (this.lastFlagged < 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcallback(this.getBufferFromStart());\n\t\t\tthis.lastFlagged = -1;\n\t\t});\n\t\tthis.readable.on(\"speakingStopped\", () => {\n\t\t\tif (this.ended) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlogger.debug({ src: \"plugin:discord:service:voice\" }, \"Speaking stopped\");\n\t\t\tif (this.lastFlagged < 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcallback(this.getBufferFromStart());\n\t\t});\n\t\tthis.readable.on(\"speakingStarted\", () => {\n\t\t\tif (this.ended) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tonStart();\n\t\t\tlogger.debug({ src: \"plugin:discord:service:voice\" }, \"Speaking started\");\n\t\t\tthis.reset();\n\t\t});\n\t}\n\n\t/**\n\t * Stops listening to \"data\", \"end\", \"speakingStopped\", and \"speakingStarted\" events on the readable stream.\n\t */\n\tstop() {\n\t\tthis.readable.removeAllListeners(\"data\");\n\t\tthis.readable.removeAllListeners(\"end\");\n\t\tthis.readable.removeAllListeners(\"speakingStopped\");\n\t\tthis.readable.removeAllListeners(\"speakingStarted\");\n\t}\n\n\t/**\n\t * Check if the item is flagged.\n\t * @returns {boolean} True if the item was flagged, false otherwise.\n\t */\n\tisFlagged() {\n\t\treturn this.lastFlagged >= 0;\n\t}\n\n\t/**\n\t * Returns a Buffer containing all buffers starting from the last flagged index.\n\t * If the last flagged index is less than 0, returns null.\n\t *\n\t * @returns {Buffer | null} The concatenated Buffer or null\n\t */\n\tgetBufferFromFlag() {\n\t\tif (this.lastFlagged < 0) {\n\t\t\treturn null;\n\t\t}\n\t\tconst buffer = Buffer.concat(this.buffers.slice(this.lastFlagged));\n\t\treturn buffer;\n\t}\n\n\t/**\n\t * Concatenates all buffers in the array and returns a single buffer.\n\t *\n\t * @returns {Buffer} The concatenated buffer from the start.\n\t */\n\tgetBufferFromStart() {\n\t\tconst buffer = Buffer.concat(this.buffers);\n\t\treturn buffer;\n\t}\n\n\t/**\n\t * Resets the buffers array and sets lastFlagged to -1.\n\t */\n\treset() {\n\t\tthis.buffers = [];\n\t\tthis.lastFlagged = -1;\n\t}\n\n\t/**\n\t * Check if the object has ended.\n\t * @returns {boolean} Returns true if the object has ended; false otherwise.\n\t */\n\tisEnded() {\n\t\treturn this.ended;\n\t}\n}\n\n/**\n * Class representing a VoiceManager that extends EventEmitter.\n * @extends EventEmitter\n */\nexport class VoiceManager extends EventEmitter {\n\tprivate processingVoice = false;\n\tprivate transcriptionTimeout: ReturnType<typeof setTimeout> | null = null;\n\tprivate userStates: Map<\n\t\tstring,\n\t\t{\n\t\t\tbuffers: Buffer[];\n\t\t\ttotalLength: number;\n\t\t\tlastActive: number;\n\t\t\ttranscriptionText: string;\n\t\t}\n\t> = new Map();\n\tprivate activeAudioPlayer: AudioPlayer | null = null;\n\tprivate client: Client | null;\n\tprivate runtime: ICompatRuntime;\n\tprivate streams: Map<string, Readable> = new Map();\n\tprivate connections: Map<string, VoiceConnection> = new Map();\n\tprivate activeMonitors: Map<\n\t\tstring,\n\t\t{ channel: BaseGuildVoiceChannel; monitor: AudioMonitor }\n\t> = new Map();\n\tprivate ready: boolean;\n\n\t/**\n\t * Constructor for initializing a new instance of the class.\n\t *\n\t * @param {DiscordService} service - The Discord service to use.\n\t * @param {ICompatRuntime} runtime - The runtime for the agent (with cross-core compat).\n\t */\n\tconstructor(service: DiscordService, runtime: ICompatRuntime) {\n\t\tsuper();\n\t\tthis.client = service.client;\n\t\tthis.runtime = runtime;\n\t\tthis.ready = false;\n\n\t\tif (this.client) {\n\t\t\tthis.client.on(\"voiceManagerReady\", () => {\n\t\t\t\tthis.setReady(true);\n\t\t\t});\n\t\t} else {\n\t\t\tthis.runtime.logger.error(\n\t\t\t\t{ src: \"plugin:discord:service:voice\", agentId: this.runtime.agentId },\n\t\t\t\t\"Discord client not available for voiceManagerReady event\",\n\t\t\t);\n\t\t\tthis.ready = false;\n\t\t}\n\t}\n\n\t/**\n\t * Asynchronously retrieves the type of the channel.\n\t * @param {Channel} channel - The channel to get the type for.\n\t * @returns {Promise<ChannelType>} The type of the channel.\n\t */\n\tasync getChannelType(channel: Channel): Promise<ChannelType> {\n\t\tswitch (channel.type) {\n\t\t\tcase DiscordChannelType.GuildVoice:\n\t\t\tcase DiscordChannelType.GuildStageVoice:\n\t\t\t\treturn ChannelType.VOICE_GROUP;\n\t\t\tdefault:\n\t\t\t\t// This function should only be called with GuildVoice or GuildStageVoice channels\n\t\t\t\t// If it receives another type, it's an unexpected error.\n\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tchannelId: channel.id,\n\t\t\t\t\t\tchannelType: channel.type,\n\t\t\t\t\t},\n\t\t\t\t\t\"Unexpected channel type\",\n\t\t\t\t);\n\t\t\t\tthrow new Error(`Unexpected channel type encountered: ${channel.type}`);\n\t\t}\n\t}\n\n\t/**\n\t * Set the ready status of the VoiceManager.\n\t * @param {boolean} status - The status to set.\n\t */\n\tprivate setReady(status: boolean) {\n\t\tthis.ready = status;\n\t\tthis.emit(\"ready\");\n\t\tthis.runtime.logger.debug(\n\t\t\t{\n\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\tready: this.ready,\n\t\t\t},\n\t\t\t\"VoiceManager ready status changed\",\n\t\t);\n\t}\n\n\t/**\n\t * Check if the object is ready.\n\t *\n\t * @returns {boolean} True if the object is ready, false otherwise.\n\t */\n\tisReady() {\n\t\treturn this.ready;\n\t}\n\n\t/**\n\t * Handle voice state update event.\n\t * @param {VoiceState} oldState - The old voice state of the member.\n\t * @param {VoiceState} newState - The new voice state of the member.\n\t * @returns {void}\n\t */\n\tasync handleVoiceStateUpdate(oldState: VoiceState, newState: VoiceState) {\n\t\tconst oldChannelId = oldState.channelId;\n\t\tconst newChannelId = newState.channelId;\n\t\tconst member = newState.member;\n\t\tif (!member) {\n\t\t\treturn;\n\t\t}\n\t\tconst clientUser = this.client?.user;\n\t\tif (clientUser && member.id === clientUser.id) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Ignore mute/unmute events\n\t\tif (oldChannelId === newChannelId) {\n\t\t\treturn;\n\t\t}\n\n\t\t// User leaving a channel where the bot is present\n\t\tif (oldChannelId && this.connections.has(oldChannelId)) {\n\t\t\tthis.stopMonitoringMember(member.id);\n\t\t}\n\n\t\t// User joining a channel where the bot is present\n\t\tif (newChannelId && this.connections.has(newChannelId)) {\n\t\t\tawait this.monitorMember(\n\t\t\t\tmember,\n\t\t\t\tnewState.channel as BaseGuildVoiceChannel,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Joins a voice channel and sets up the necessary connection and event listeners.\n\t * @param {BaseGuildVoiceChannel} channel - The voice channel to join\n\t */\n\tasync joinChannel(channel: BaseGuildVoiceChannel) {\n\t\tconst oldConnection = this.getVoiceConnection(channel.guildId as string);\n\t\tif (oldConnection) {\n\t\t\ttry {\n\t\t\t\toldConnection.destroy();\n\t\t\t\t// Remove all associated streams and monitors\n\t\t\t\tthis.streams.clear();\n\t\t\t\tthis.activeMonitors.clear();\n\t\t\t} catch (error) {\n\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t},\n\t\t\t\t\t\"Error leaving voice channel\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst connection = joinVoiceChannel({\n\t\t\tchannelId: channel.id,\n\t\t\tguildId: channel.guild.id,\n\t\t\tadapterCreator: channel.guild.voiceAdapterCreator,\n\t\t\tselfDeaf: false,\n\t\t\tselfMute: false,\n\t\t\tgroup: this.client?.user?.id ?? \"default-group\",\n\t\t});\n\n\t\ttry {\n\t\t\t// Wait for either Ready or Signalling state\n\t\t\tawait Promise.race([\n\t\t\t\tentersState(connection, VoiceConnectionStatus.Ready, 20_000),\n\t\t\t\tentersState(connection, VoiceConnectionStatus.Signalling, 20_000),\n\t\t\t]);\n\n\t\t\t// Log connection success\n\t\t\tthis.runtime.logger.info(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tstatus: connection.state.status,\n\t\t\t\t},\n\t\t\t\t\"Voice connection established\",\n\t\t\t);\n\n\t\t\t// Set up ongoing state change monitoring\n\t\t\tconnection.on(\"stateChange\", async (oldState, newState) => {\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\toldState: oldState.status,\n\t\t\t\t\t\tnewState: newState.status,\n\t\t\t\t\t},\n\t\t\t\t\t\"Voice connection state changed\",\n\t\t\t\t);\n\n\t\t\t\tif (newState.status === VoiceConnectionStatus.Disconnected) {\n\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Handling disconnection\",\n\t\t\t\t\t);\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// Try to reconnect if disconnected\n\t\t\t\t\t\tawait Promise.race([\n\t\t\t\t\t\t\tentersState(connection, VoiceConnectionStatus.Signalling, 5_000),\n\t\t\t\t\t\t\tentersState(connection, VoiceConnectionStatus.Connecting, 5_000),\n\t\t\t\t\t\t]);\n\t\t\t\t\t\t// Seems to be reconnecting to a new channel\n\t\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Reconnecting to channel\",\n\t\t\t\t\t\t);\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t// Seems to be a real disconnect, destroy and cleanup\n\t\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\terror: e instanceof Error ? e.message : String(e),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Disconnection confirmed - cleaning up\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconnection.destroy();\n\t\t\t\t\t\tthis.connections.delete(channel.id);\n\t\t\t\t\t}\n\t\t\t\t} else if (newState.status === VoiceConnectionStatus.Destroyed) {\n\t\t\t\t\tthis.connections.delete(channel.id);\n\t\t\t\t} else if (\n\t\t\t\t\t!this.connections.has(channel.id) &&\n\t\t\t\t\t(newState.status === VoiceConnectionStatus.Ready ||\n\t\t\t\t\t\tnewState.status === VoiceConnectionStatus.Signalling)\n\t\t\t\t) {\n\t\t\t\t\tthis.connections.set(channel.id, connection);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tconnection.on(\"error\", (error) => {\n\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t},\n\t\t\t\t\t\"Voice connection error\",\n\t\t\t\t);\n\t\t\t\t// Don't immediately destroy - let the state change handler deal with it\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t},\n\t\t\t\t\t\"Will attempt to recover\",\n\t\t\t\t);\n\t\t\t});\n\n\t\t\t// Store the connection\n\t\t\tthis.connections.set(channel.id, connection);\n\n\t\t\t// Continue with voice state modifications\n\t\t\tconst me = channel.guild.members.me;\n\t\t\tconst meVoice = me?.voice;\n\t\t\tif (meVoice && me.permissions.has(\"DeafenMembers\")) {\n\t\t\t\ttry {\n\t\t\t\t\tawait meVoice.setDeaf(false);\n\t\t\t\t\tawait meVoice.setMute(false);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Failed to modify voice state\",\n\t\t\t\t\t);\n\t\t\t\t\t// Continue even if this fails\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconnection.receiver.speaking.on(\"start\", async (entityId: string) => {\n\t\t\t\tlet user = channel.members.get(entityId);\n\t\t\t\tif (!user) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tuser = await channel.guild.members.fetch(entityId);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\t\tentityId,\n\t\t\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Failed to fetch user\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst userUser = user?.user;\n\t\t\t\tif (user && userUser && !userUser.bot) {\n\t\t\t\t\tthis.monitorMember(user as GuildMember, channel);\n\t\t\t\t\tconst entityStream = this.streams.get(entityId);\n\t\t\t\t\tif (entityStream) {\n\t\t\t\t\t\tentityStream.emit(\"speakingStarted\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tconnection.receiver.speaking.on(\"end\", async (entityId: string) => {\n\t\t\t\tconst user = channel.members.get(entityId);\n\t\t\t\tconst userUser = user?.user;\n\t\t\t\tif (user && userUser && !userUser.bot) {\n\t\t\t\t\tconst entityStream = this.streams.get(entityId);\n\t\t\t\t\tif (entityStream) {\n\t\t\t\t\t\tentityStream.emit(\"speakingStopped\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tthis.runtime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tchannelId: channel.id,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Failed to establish voice connection\",\n\t\t\t);\n\t\t\tconnection.destroy();\n\t\t\tthis.connections.delete(channel.id);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * Retrieves the voice connection for a given guild ID.\n\t * @param {string} guildId - The ID of the guild to get the voice connection for.\n\t * @returns {VoiceConnection | undefined} The voice connection for the specified guild ID, or undefined if not found.\n\t */\n\tgetVoiceConnection(guildId: string) {\n\t\tconst clientUser = this.client?.user;\n\t\tconst userId = clientUser?.id;\n\t\tif (!userId) {\n\t\t\tthis.runtime.logger.error(\n\t\t\t\t{ src: \"plugin:discord:service:voice\", agentId: this.runtime.agentId },\n\t\t\t\t\"Client user ID not available\",\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t\tconst connections = getVoiceConnections(userId);\n\t\tif (!connections) {\n\t\t\treturn;\n\t\t}\n\t\tconst connection = [...connections.values()].find(\n\t\t\t(connection) => connection.joinConfig.guildId === guildId,\n\t\t);\n\t\treturn connection;\n\t}\n\n\t/**\n\t * Monitor a member's audio stream for volume activity and speaking thresholds.\n\t *\n\t * @param {GuildMember} member - The member whose audio stream is being monitored.\n\t * @param {BaseGuildVoiceChannel} channel - The voice channel in which the member is connected.\n\t */\n\tprivate async monitorMember(\n\t\tmember: GuildMember,\n\t\tchannel: BaseGuildVoiceChannel,\n\t) {\n\t\tconst entityId = member?.id;\n\t\tconst memberUser = member?.user;\n\t\tconst userName = memberUser?.username;\n\t\tconst name = memberUser?.displayName;\n\t\tconst memberGuild = member?.guild;\n\t\tconst memberGuildId = memberGuild?.id;\n\t\tconst connection = this.getVoiceConnection(memberGuildId);\n\n\t\tconst connectionReceiver = connection?.receiver;\n\t\tconst receiveStream = connectionReceiver?.subscribe(entityId, {\n\t\t\tautoDestroy: true,\n\t\t\temitClose: true,\n\t\t});\n\t\tif (!receiveStream || receiveStream.readableLength === 0) {\n\t\t\tthis.runtime.logger.warn(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tentityId,\n\t\t\t\t},\n\t\t\t\t\"No receiveStream or empty stream\",\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tlet opusDecoder: ReturnType<typeof createOpusDecoder>;\n\t\ttry {\n\t\t\t// Try to create opus decoder with error handling for Node.js 23 compatibility\n\t\t\topusDecoder = createOpusDecoder({\n\t\t\t\tchannels: 1,\n\t\t\t\trate: DECODE_SAMPLE_RATE,\n\t\t\t\tframeSize: DECODE_FRAME_SIZE,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tthis.runtime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tentityId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Failed to create opus decoder\",\n\t\t\t);\n\t\t\t// For now, log the error and return early.\n\t\t\t// In production, you might want to implement a PCM fallback or other audio processing\n\t\t\treturn;\n\t\t}\n\n\t\tconst volumeBuffer: number[] = [];\n\t\tconst VOLUME_WINDOW_SIZE = 30;\n\t\tconst SPEAKING_THRESHOLD = 0.05;\n\t\topusDecoder.on(\"data\", (pcmData: Buffer) => {\n\t\t\t// Monitor the audio volume while the agent is speaking.\n\t\t\t// If the average volume of the user's audio exceeds the defined threshold, it indicates active speaking.\n\t\t\t// When active speaking is detected, stop the agent's current audio playbook to avoid overlap.\n\n\t\t\tif (this.activeAudioPlayer) {\n\t\t\t\tconst samples = new Int16Array(\n\t\t\t\t\tpcmData.buffer,\n\t\t\t\t\tpcmData.byteOffset,\n\t\t\t\t\tpcmData.length / 2,\n\t\t\t\t);\n\t\t\t\tconst maxAmplitude = Math.max(...samples.map(Math.abs)) / 32768;\n\t\t\t\tvolumeBuffer.push(maxAmplitude);\n\n\t\t\t\tif (volumeBuffer.length > VOLUME_WINDOW_SIZE) {\n\t\t\t\t\tvolumeBuffer.shift();\n\t\t\t\t}\n\t\t\t\tconst avgVolume =\n\t\t\t\t\tvolumeBuffer.reduce((sum, v) => sum + v, 0) / VOLUME_WINDOW_SIZE;\n\n\t\t\t\tif (avgVolume > SPEAKING_THRESHOLD) {\n\t\t\t\t\tvolumeBuffer.length = 0;\n\t\t\t\t\tthis.cleanupAudioPlayer(this.activeAudioPlayer);\n\t\t\t\t\tthis.processingVoice = false;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tif (!opusDecoder) {\n\t\t\tthis.runtime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t},\n\t\t\t\t\"Opus decoder not available\",\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tpipeline(\n\t\t\treceiveStream as AudioReceiveStream,\n\t\t\topusDecoder,\n\t\t\t(err: Error | null) => {\n\t\t\t\tif (err) {\n\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\tentityId,\n\t\t\t\t\t\t\terror: err.message,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Opus decoding pipeline error\",\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\tentityId,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Opus decoding pipeline finished\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\t\tthis.streams.set(entityId, opusDecoder);\n\t\tthis.connections.set(entityId, connection as VoiceConnection);\n\t\topusDecoder.on(\"error\", (err: Error) => {\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t},\n\t\t\t\t\"Opus decoding error\",\n\t\t\t);\n\t\t});\n\t\tconst errorHandler = (err: Error) => {\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t},\n\t\t\t\t\"Opus decoding error\",\n\t\t\t);\n\t\t};\n\t\tconst streamCloseHandler = () => {\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tmember: member?.displayName || undefined,\n\t\t\t\t},\n\t\t\t\t\"Voice stream closed\",\n\t\t\t);\n\t\t\tthis.streams.delete(entityId);\n\t\t\tthis.connections.delete(entityId);\n\t\t};\n\t\tconst closeHandler = () => {\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tmember: member?.displayName || undefined,\n\t\t\t\t},\n\t\t\t\t\"Opus decoder closed\",\n\t\t\t);\n\t\t\topusDecoder.removeListener(\"error\", errorHandler);\n\t\t\topusDecoder.removeListener(\"close\", closeHandler);\n\t\t\tif (receiveStream) {\n\t\t\t\treceiveStream.removeListener(\"close\", streamCloseHandler);\n\t\t\t}\n\t\t};\n\t\topusDecoder.on(\"error\", errorHandler);\n\t\topusDecoder.on(\"close\", closeHandler);\n\t\tif (receiveStream) {\n\t\t\treceiveStream.on(\"close\", streamCloseHandler);\n\t\t}\n\n\t\tif (this.client) {\n\t\t\tthis.client.emit(\n\t\t\t\t\"userStream\",\n\t\t\t\tentityId,\n\t\t\t\tname,\n\t\t\t\tuserName,\n\t\t\t\tchannel,\n\t\t\t\topusDecoder,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Leaves the specified voice channel and stops monitoring all members in that channel.\n\t * If there is an active connection in the channel, it will be destroyed.\n\t *\n\t * @param {BaseGuildVoiceChannel} channel - The voice channel to leave.\n\t */\n\tleaveChannel(channel: BaseGuildVoiceChannel) {\n\t\tconst connection = this.connections.get(channel.id);\n\t\tif (connection) {\n\t\t\tconnection.destroy();\n\t\t\tthis.connections.delete(channel.id);\n\t\t}\n\n\t\t// Stop monitoring all members in this channel\n\t\tfor (const [memberId, monitorInfo] of this.activeMonitors) {\n\t\t\tif (\n\t\t\t\tmonitorInfo.channel.id === channel.id &&\n\t\t\t\tmemberId !== this.client?.user?.id\n\t\t\t) {\n\t\t\t\tthis.stopMonitoringMember(memberId);\n\t\t\t}\n\t\t}\n\n\t\tthis.runtime.logger.debug(\n\t\t\t{\n\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\tchannelId: channel.id,\n\t\t\t\tchannelName: channel.name,\n\t\t\t},\n\t\t\t\"Left voice channel\",\n\t\t);\n\t}\n\n\t/**\n\t * Stop monitoring a specific member by their member ID.\n\t * @param {string} memberId - The ID of the member to stop monitoring.\n\t */\n\tstopMonitoringMember(memberId: string) {\n\t\tconst monitorInfo = this.activeMonitors.get(memberId);\n\t\tif (monitorInfo) {\n\t\t\tmonitorInfo.monitor.stop();\n\t\t\tthis.activeMonitors.delete(memberId);\n\t\t\tthis.streams.delete(memberId);\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tmemberId,\n\t\t\t\t},\n\t\t\t\t\"Stopped monitoring user\",\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Asynchronously debounces the process transcription function to prevent rapid execution.\n\t *\n\t * @param {UUID} entityId - The ID of the entity related to the transcription.\n\t * @param {string} name - The name of the entity for transcription.\n\t * @param {string} userName - The username of the user initiating the transcription.\n\t * @param {BaseGuildVoiceChannel} channel - The voice channel where the transcription is happening.\n\t */\n\n\tasync debouncedProcessTranscription(\n\t\tentityId: UUID,\n\t\tname: string,\n\t\tuserName: string,\n\t\tchannel: BaseGuildVoiceChannel,\n\t) {\n\t\tconst DEBOUNCE_TRANSCRIPTION_THRESHOLD = 1500; // wait for 1.5 seconds of silence\n\n\t\tconst activeAudioPlayer = this.activeAudioPlayer;\n\t\tconst activeAudioPlayerState = activeAudioPlayer?.state;\n\t\tif (activeAudioPlayerState && activeAudioPlayerState.status === \"idle\") {\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{ src: \"plugin:discord:service:voice\", agentId: this.runtime.agentId },\n\t\t\t\t\"Cleaning up idle audio player\",\n\t\t\t);\n\t\t\tthis.cleanupAudioPlayer(this.activeAudioPlayer);\n\t\t}\n\n\t\tif (this.activeAudioPlayer || this.processingVoice) {\n\t\t\tconst state = this.userStates.get(entityId);\n\t\t\tif (state) {\n\t\t\t\tstate.buffers.length = 0;\n\t\t\t\tstate.totalLength = 0;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.transcriptionTimeout) {\n\t\t\tclearTimeout(this.transcriptionTimeout);\n\t\t}\n\n\t\tthis.transcriptionTimeout = setTimeout(async () => {\n\t\t\tthis.processingVoice = true;\n\t\t\ttry {\n\t\t\t\tawait this.processTranscription(\n\t\t\t\t\tentityId,\n\t\t\t\t\tchannel.id,\n\t\t\t\t\tchannel,\n\t\t\t\t\tname,\n\t\t\t\t\tuserName,\n\t\t\t\t);\n\n\t\t\t\t// Clean all users' previous buffers\n\t\t\t\tthis.userStates.forEach((state, _) => {\n\t\t\t\t\tstate.buffers.length = 0;\n\t\t\t\t\tstate.totalLength = 0;\n\t\t\t\t});\n\t\t\t} finally {\n\t\t\t\tthis.processingVoice = false;\n\t\t\t}\n\t\t}, DEBOUNCE_TRANSCRIPTION_THRESHOLD);\n\t}\n\n\t/**\n\t * Handle user audio stream for monitoring purposes.\n\t *\n\t * @param {UUID} userId - The unique identifier of the user.\n\t * @param {string} name - The name of the user.\n\t * @param {string} userName - The username of the user.\n\t * @param {BaseGuildVoiceChannel} channel - The voice channel the user is in.\n\t * @param {Readable} audioStream - The audio stream to monitor.\n\t */\n\tasync handleUserStream(\n\t\tentityId: UUID,\n\t\tname: string,\n\t\tuserName: string,\n\t\tchannel: BaseGuildVoiceChannel,\n\t\taudioStream: Readable,\n\t) {\n\t\tthis.runtime.logger.debug(\n\t\t\t{\n\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\tentityId,\n\t\t\t},\n\t\t\t\"Starting audio monitor\",\n\t\t);\n\t\tif (!this.userStates.has(entityId)) {\n\t\t\tthis.userStates.set(entityId, {\n\t\t\t\tbuffers: [],\n\t\t\t\ttotalLength: 0,\n\t\t\t\tlastActive: Date.now(),\n\t\t\t\ttranscriptionText: \"\",\n\t\t\t});\n\t\t}\n\n\t\tconst state = this.userStates.get(entityId);\n\n\t\tconst processBuffer = async (buffer: Buffer) => {\n\t\t\ttry {\n\t\t\t\tif (state?.buffers) {\n\t\t\t\t\tstate.buffers.push(buffer);\n\t\t\t\t\tstate.totalLength += buffer.length;\n\t\t\t\t}\n\t\t\t\tif (state) {\n\t\t\t\t\tstate.lastActive = Date.now();\n\t\t\t\t}\n\t\t\t\tthis.debouncedProcessTranscription(entityId, name, userName, channel);\n\t\t\t} catch (error) {\n\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tentityId,\n\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t},\n\t\t\t\t\t\"Error processing buffer\",\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\n\t\tnew AudioMonitor(\n\t\t\taudioStream,\n\t\t\t10000000,\n\t\t\t() => {\n\t\t\t\tif (this.transcriptionTimeout) {\n\t\t\t\t\tclearTimeout(this.transcriptionTimeout);\n\t\t\t\t}\n\t\t\t},\n\t\t\tasync (buffer) => {\n\t\t\t\tif (!buffer) {\n\t\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Received empty buffer\",\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tawait processBuffer(buffer);\n\t\t\t},\n\t\t);\n\t}\n\n\t/**\n\t * Process the transcription of audio data for a user.\n\t *\n\t * @param {UUID} entityId - The unique ID of the user entity.\n\t * @param {string} channelId - The ID of the channel where the transcription is taking place.\n\t * @param {BaseGuildVoiceChannel} channel - The voice channel where the user is speaking.\n\t * @param {string} name - The name of the user.\n\t * @param {string} userName - The username of the user.\n\t * @returns {Promise<void>}\n\t */\n\tprivate async processTranscription(\n\t\tentityId: UUID,\n\t\tchannelId: string,\n\t\tchannel: BaseGuildVoiceChannel,\n\t\tname: string,\n\t\tuserName: string,\n\t) {\n\t\tconst state = this.userStates.get(entityId);\n\t\tif (!state || state.buffers.length === 0) {\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tconst inputBuffer = Buffer.concat(state.buffers, state.totalLength);\n\n\t\t\tstate.buffers.length = 0; // Clear the buffers\n\t\t\tstate.totalLength = 0;\n\t\t\t// Convert Opus to WAV\n\t\t\tconst wavBuffer = await this.convertOpusToWav(inputBuffer);\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{ src: \"plugin:discord:service:voice\", agentId: this.runtime.agentId },\n\t\t\t\t\"Starting transcription\",\n\t\t\t);\n\n\t\t\tconst transcriptionText = await this.runtime.useModel(\n\t\t\t\tModelType.TRANSCRIPTION,\n\t\t\t\twavBuffer,\n\t\t\t);\n\t\t\tfunction isValidTranscription(text: string): boolean {\n\t\t\t\tif (!text || text.includes(\"[BLANK_AUDIO]\")) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tif (transcriptionText && isValidTranscription(transcriptionText)) {\n\t\t\t\tstate.transcriptionText += transcriptionText;\n\t\t\t}\n\n\t\t\tif (state.transcriptionText.length) {\n\t\t\t\tthis.cleanupAudioPlayer(this.activeAudioPlayer);\n\t\t\t\tconst finalText = state.transcriptionText;\n\t\t\t\tstate.transcriptionText = \"\";\n\t\t\t\tawait this.handleMessage(\n\t\t\t\t\tfinalText,\n\t\t\t\t\tentityId,\n\t\t\t\t\tchannelId,\n\t\t\t\t\tchannel,\n\t\t\t\t\tname,\n\t\t\t\t\tuserName,\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.runtime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tentityId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error transcribing audio\",\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Handles a voice message received in a Discord channel.\n\t *\n\t * @param {string} message - The message content.\n\t * @param {UUID} entityId - The entity ID associated with the message.\n\t * @param {string} channelId - The ID of the Discord channel where the message was received.\n\t * @param {BaseGuildVoiceChannel} channel - The Discord channel where the message was received.\n\t * @param {string} name - The name associated with the message.\n\t * @param {string} userName - The user name associated with the message.\n\t * @returns {Promise<{text: string, actions: string[]}>} Object containing the resulting text and actions.\n\t */\n\tprivate async handleMessage(\n\t\tmessage: string,\n\t\tentityId: UUID,\n\t\tchannelId: string,\n\t\tchannel: BaseGuildVoiceChannel,\n\t\tname: string,\n\t\tuserName: string,\n\t) {\n\t\ttry {\n\t\t\tif (!message || message.trim() === \"\" || message.length < 3) {\n\t\t\t\treturn { text: \"\", actions: [\"IGNORE\"] };\n\t\t\t}\n\n\t\t\tconst roomId = createUniqueUuid(this.runtime, channelId);\n\t\t\tconst uniqueEntityId = createUniqueUuid(this.runtime, entityId);\n\t\t\tconst type = await this.getChannelType(channel as Channel);\n\n\t\t\tawait this.runtime.ensureConnection({\n\t\t\t\tentityId: uniqueEntityId,\n\t\t\t\troomId,\n\t\t\t\tuserName,\n\t\t\t\tname,\n\t\t\t\tsource: \"discord\",\n\t\t\t\tchannelId,\n\t\t\t\t// Convert Discord snowflake to UUID (see service.ts header for why stringToUuid not asUUID)\n\t\t\t\tmessageServerId: stringToUuid(channel.guild.id),\n\t\t\t\ttype,\n\t\t\t\tworldId: createUniqueUuid(this.runtime, channel.guild.id) as UUID,\n\t\t\t\tworldName: channel.guild.name,\n\t\t\t});\n\n\t\t\tconst memory: Memory = {\n\t\t\t\tid: createUniqueUuid(\n\t\t\t\t\tthis.runtime,\n\t\t\t\t\t`${channelId}-voice-message-${Date.now()}`,\n\t\t\t\t),\n\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\tentityId: uniqueEntityId,\n\t\t\t\troomId,\n\t\t\t\tcontent: {\n\t\t\t\t\ttext: message,\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t\turl: channel.url,\n\t\t\t\t\tname,\n\t\t\t\t\tuserName,\n\t\t\t\t\tisVoiceMessage: true,\n\t\t\t\t\tchannelType: type,\n\t\t\t\t},\n\t\t\t\tcreatedAt: Date.now(),\n\t\t\t};\n\n\t\t\tconst callback: HandlerCallback = async (\n\t\t\t\tcontent: Content,\n\t\t\t\t_actionName?: string,\n\t\t\t) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst responseMemory: Memory = {\n\t\t\t\t\t\tid: createUniqueUuid(\n\t\t\t\t\t\t\tthis.runtime,\n\t\t\t\t\t\t\t`${memory.id}-voice-response-${Date.now()}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tentityId: this.runtime.agentId,\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t...content,\n\t\t\t\t\t\t\tname: this.runtime.character.name,\n\t\t\t\t\t\t\tinReplyTo: memory.id,\n\t\t\t\t\t\t\tisVoiceMessage: true,\n\t\t\t\t\t\t\tchannelType: type,\n\t\t\t\t\t\t},\n\t\t\t\t\t\troomId,\n\t\t\t\t\t\tcreatedAt: Date.now(),\n\t\t\t\t\t};\n\n\t\t\t\t\tconst responseMemoryContentText = responseMemory.content.text;\n\t\t\t\t\tif (responseMemoryContentText?.trim()) {\n\t\t\t\t\t\tawait this.runtime.createMemory(responseMemory, \"messages\");\n\n\t\t\t\t\t\tif (content.text) {\n\t\t\t\t\t\t\tconst responseStream = await this.runtime.useModel(\n\t\t\t\t\t\t\t\tModelType.TEXT_TO_SPEECH,\n\t\t\t\t\t\t\t\tcontent.text,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (responseStream) {\n\t\t\t\t\t\t\t\t// Convert Buffer/ArrayBuffer to Readable stream\n\t\t\t\t\t\t\t\tconst buffer = Buffer.isBuffer(responseStream)\n\t\t\t\t\t\t\t\t\t? responseStream\n\t\t\t\t\t\t\t\t\t: Buffer.from(responseStream as ArrayBuffer);\n\t\t\t\t\t\t\t\tconst readable = Readable.from(buffer);\n\t\t\t\t\t\t\t\tawait this.playAudioStream(entityId, readable);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn [responseMemory];\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Error in voice message callback\",\n\t\t\t\t\t);\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// Process voice message - try messageService first (newer core), fall back to events (older core)\n\t\t\tconst messageService = getMessageService(this.runtime);\n\t\t\tif (messageService) {\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t{ src: \"plugin:discord:voice\", agentId: this.runtime.agentId },\n\t\t\t\t\t\"Using messageService API for voice\",\n\t\t\t\t);\n\t\t\t\tawait messageService.handleMessage(this.runtime, memory, callback);\n\t\t\t} else {\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t{ src: \"plugin:discord:voice\", agentId: this.runtime.agentId },\n\t\t\t\t\t\"Using event-based handling for voice\",\n\t\t\t\t);\n\t\t\t\tawait this.runtime.emitEvent([EventType.VOICE_MESSAGE_RECEIVED], {\n\t\t\t\t\truntime: this.runtime,\n\t\t\t\t\tmessage: memory,\n\t\t\t\t\tcallback,\n\t\t\t\t\tsource: \"discord\",\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.runtime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error processing voice message\",\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Asynchronously converts an Opus audio Buffer to a WAV audio Buffer.\n\t *\n\t * @param {Buffer} pcmBuffer - The Opus audio Buffer to convert to WAV.\n\t * @returns {Promise<Buffer>} A Promise that resolves with the converted WAV audio Buffer.\n\t */\n\tprivate async convertOpusToWav(pcmBuffer: Buffer): Promise<Buffer> {\n\t\ttry {\n\t\t\t// Generate the WAV header\n\t\t\tconst wavHeader = getWavHeader(pcmBuffer.length, DECODE_SAMPLE_RATE);\n\n\t\t\t// Concatenate the WAV header and PCM data\n\t\t\tconst wavBuffer = Buffer.concat([wavHeader, pcmBuffer]);\n\n\t\t\treturn wavBuffer;\n\t\t} catch (error) {\n\t\t\tthis.runtime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error converting PCM to WAV\",\n\t\t\t);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * Scans the given Discord guild to select a suitable voice channel to join.\n\t *\n\t * @param {Guild} guild The Discord guild to scan for voice channels.\n\t */\n\tasync scanGuild(guild: Guild) {\n\t\tlet chosenChannel: BaseGuildVoiceChannel | null = null;\n\n\t\ttry {\n\t\t\tconst channelId = this.runtime.getSetting(\n\t\t\t\t\"DISCORD_VOICE_CHANNEL_ID\",\n\t\t\t) as string;\n\t\t\tif (channelId) {\n\t\t\t\tconst channel = await guild.channels.fetch(channelId);\n\t\t\t\tif (channel?.isVoiceBased?.()) {\n\t\t\t\t\tchosenChannel = channel as BaseGuildVoiceChannel;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!chosenChannel) {\n\t\t\t\tconst channels = (await guild.channels.fetch()).filter(\n\t\t\t\t\t(channel) =>\n\t\t\t\t\t\tchannel && channel.type === DiscordChannelType.GuildVoice,\n\t\t\t\t);\n\t\t\t\tfor (const [, channel] of channels) {\n\t\t\t\t\tconst voiceChannel = channel as BaseGuildVoiceChannel;\n\t\t\t\t\tif (\n\t\t\t\t\t\tvoiceChannel.members.size > 0 &&\n\t\t\t\t\t\t(chosenChannel === null ||\n\t\t\t\t\t\t\tvoiceChannel.members.size > chosenChannel.members.size)\n\t\t\t\t\t) {\n\t\t\t\t\t\tchosenChannel = voiceChannel;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (chosenChannel) {\n\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\tchannelName: chosenChannel.name,\n\t\t\t\t\t},\n\t\t\t\t\t\"Joining channel\",\n\t\t\t\t);\n\t\t\t\tawait this.joinChannel(chosenChannel);\n\t\t\t} else {\n\t\t\t\tthis.runtime.logger.warn(\n\t\t\t\t\t{\n\t\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t},\n\t\t\t\t\t\"No suitable voice channel found to join\",\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.runtime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error selecting or joining a voice channel\",\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Play an audio stream for a given entity ID.\n\t *\n\t * @param {UUID} entityId - The ID of the entity to play the audio for.\n\t * @param {Readable} audioStream - The audio stream to play.\n\t * @returns {void}\n\t */\n\tasync playAudioStream(entityId: UUID, audioStream: Readable) {\n\t\tconst connection = this.connections.get(entityId);\n\t\tif (connection == null) {\n\t\t\tthis.runtime.logger.debug(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\tentityId,\n\t\t\t\t},\n\t\t\t\t\"No connection for user\",\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tthis.cleanupAudioPlayer(this.activeAudioPlayer);\n\t\tconst audioPlayer = createAudioPlayer({\n\t\t\tbehaviors: {\n\t\t\t\tnoSubscriber: NoSubscriberBehavior.Pause,\n\t\t\t},\n\t\t});\n\t\tthis.activeAudioPlayer = audioPlayer;\n\t\tconnection.subscribe(audioPlayer);\n\n\t\tconst audioStartTime = Date.now();\n\n\t\tconst resource = createAudioResource(audioStream, {\n\t\t\tinputType: StreamType.Arbitrary,\n\t\t});\n\t\taudioPlayer.play(resource);\n\n\t\taudioPlayer.on(\"error\", (err: Error) => {\n\t\t\tthis.runtime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t},\n\t\t\t\t\"Audio player error\",\n\t\t\t);\n\t\t});\n\n\t\taudioPlayer.on(\n\t\t\t\"stateChange\",\n\t\t\t(_oldState: unknown, newState: { status: string }) => {\n\t\t\t\tif (newState.status === \"idle\") {\n\t\t\t\t\tconst idleTime = Date.now();\n\t\t\t\t\tthis.runtime.logger.debug(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\tdurationMs: idleTime - audioStartTime,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Audio playback completed\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\t}\n\n\t/**\n\t * Cleans up the provided audio player by stopping it, removing all listeners,\n\t * and resetting the active audio player if it matches the provided player.\n\t *\n\t * @param {AudioPlayer} audioPlayer - The audio player to be cleaned up.\n\t */\n\tcleanupAudioPlayer(audioPlayer: AudioPlayer | null) {\n\t\tif (!audioPlayer) {\n\t\t\treturn;\n\t\t}\n\n\t\taudioPlayer.stop();\n\t\taudioPlayer.removeAllListeners();\n\t\tif (audioPlayer === this.activeAudioPlayer) {\n\t\t\tthis.activeAudioPlayer = null;\n\t\t}\n\t}\n\n\t/**\n\t * Asynchronously handles the join channel command in an interaction.\n\t *\n\t * @param interaction - The interaction object representing the user's input.\n\t * @returns A promise that resolves once the join channel command is handled.\n\t */\n\tasync handleJoinChannelCommand(interaction: {\n\t\tdeferReply: () => Promise<void>;\n\t\toptions: {\n\t\t\tget: (name: string) => { value: string } | null;\n\t\t};\n\t\tguild: Guild | null;\n\t\teditReply: (message: string) => Promise<void>;\n\t}) {\n\t\ttry {\n\t\t\t// Defer the reply immediately to prevent interaction timeout\n\t\t\tawait interaction.deferReply();\n\n\t\t\tconst interactionOptionsChannel = interaction.options.get(\"channel\");\n\t\t\tconst channelId = interactionOptionsChannel?.value as string;\n\t\t\tif (!channelId) {\n\t\t\t\tawait interaction.editReply(\"Please provide a voice channel to join.\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst guild = interaction.guild;\n\t\t\tif (!guild) {\n\t\t\t\tawait interaction.editReply(\"Could not find guild.\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst voiceChannel = interaction.guild.channels.cache.find(\n\t\t\t\t(channel: VoiceChannel) =>\n\t\t\t\t\tchannel.id === channelId &&\n\t\t\t\t\tchannel.type === DiscordChannelType.GuildVoice,\n\t\t\t);\n\n\t\t\tif (!voiceChannel) {\n\t\t\t\tawait interaction.editReply(\"Voice channel not found!\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tawait this.joinChannel(voiceChannel as BaseGuildVoiceChannel);\n\t\t\tawait interaction.editReply(`Joined voice channel: ${voiceChannel.name}`);\n\t\t} catch (error) {\n\t\t\tthis.runtime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error joining voice channel\",\n\t\t\t);\n\t\t\t// Use editReply instead of reply for the error case\n\t\t\tawait interaction\n\t\t\t\t.editReply(\"Failed to join the voice channel.\")\n\t\t\t\t.catch((err: Error) => {\n\t\t\t\t\tthis.runtime.logger.error(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\t\t\terror: err.message,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Failed to send error reply\",\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Handles the leave channel command by destroying the voice connection if it exists.\n\t *\n\t * @param interaction - The interaction object representing the command invocation.\n\t * @returns A promise that resolves once the leave channel command is handled.\n\t */\n\tasync handleLeaveChannelCommand(interaction: {\n\t\tguildId: string | null;\n\t\treply: (message: string) => Promise<void>;\n\t}) {\n\t\tif (!interaction.guildId) {\n\t\t\tawait interaction.reply(\"This command can only be used in a server.\");\n\t\t\treturn;\n\t\t}\n\t\tconst connection = this.getVoiceConnection(interaction.guildId);\n\n\t\tif (!connection) {\n\t\t\tawait interaction.reply(\"Not currently in a voice channel.\");\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconnection.destroy();\n\t\t\tawait interaction.reply(\"Left the voice channel.\");\n\t\t} catch (error) {\n\t\t\tthis.runtime.logger.error(\n\t\t\t\t{\n\t\t\t\t\tsrc: \"plugin:discord:service:voice\",\n\t\t\t\t\tagentId: this.runtime.agentId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t},\n\t\t\t\t\"Error leaving voice channel\",\n\t\t\t);\n\t\t\tawait interaction.reply(\"Failed to leave the voice channel.\");\n\t\t}\n\t}\n}\n",
|
|
123
|
+
"import type { Readable } from \"node:stream\";\nimport {\n\tAudioPlayerStatus,\n\tcreateAudioPlayer,\n\tcreateAudioResource,\n\tentersState,\n\tNoSubscriberBehavior,\n\ttype VoiceConnection,\n\tVoiceConnectionStatus,\n} from \"@discordjs/voice\";\nimport {\n\ttype IAgentRuntime,\n\tlogger,\n\tModelType,\n\ttype TestSuite,\n} from \"@elizaos/core\";\nimport {\n\tAttachmentBuilder,\n\tChannelType,\n\tEvents,\n\ttype Guild,\n\ttype Message,\n\ttype TextChannel,\n} from \"discord.js\";\nimport type { DiscordService } from \"./service\";\nimport { ServiceType } from \"./types\";\nimport { sendMessageInChunks } from \"./utils\";\n\nconst TEST_IMAGE_URL =\n\t\"https://github.com/elizaOS/awesome-eliza/blob/main/assets/eliza-logo.jpg?raw=true\";\n\n/**\n * Represents a test suite for Discord functionality.\n * @class DiscordTestSuite\n * @implements TestSuite\n * @property {string} name - The name of the test suite\n * @property {DiscordService | null} discordClient - The Discord client instance\n * @property {Array<{ name: string; fn: (runtime: IAgentRuntime) => Promise<void> }>} tests - Array of test functions\n */\nexport class DiscordTestSuite implements TestSuite {\n\tname = \"discord\";\n\tprivate discordClient!: DiscordService; // Use definite assignment assertion\n\ttests: { name: string; fn: (runtime: IAgentRuntime) => Promise<void> }[];\n\n\t/**\n\t * Constructor for initializing the tests array with test cases to be executed.\n\t *\n\t * @constructor\n\t * @this {TestSuite}\n\t */\n\tconstructor() {\n\t\tthis.tests = [\n\t\t\t{\n\t\t\t\tname: \"Initialize Discord Client\",\n\t\t\t\tfn: this.testCreatingDiscordClient.bind(this),\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"Slash Commands - Join Voice\",\n\t\t\t\tfn: this.testJoinVoiceSlashCommand.bind(this),\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"Voice Playback & TTS\",\n\t\t\t\tfn: this.testTextToSpeechPlayback.bind(this),\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"Send Message with Attachments\",\n\t\t\t\tfn: this.testSendingTextMessage.bind(this),\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"Handle Incoming Messages\",\n\t\t\t\tfn: this.testHandlingMessage.bind(this),\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"Slash Commands - Leave Voice\",\n\t\t\t\tfn: this.testLeaveVoiceSlashCommand.bind(this),\n\t\t\t},\n\t\t];\n\t}\n\n\t/**\n\t * Asynchronously tests the creation of Discord client using the provided runtime.\n\t *\n\t * @param {IAgentRuntime} runtime - The agent runtime used to obtain the Discord service.\n\t * @returns {Promise<void>} - A Promise that resolves once the Discord client is ready.\n\t * @throws {Error} - If an error occurs while creating the Discord client.\n\t */\n\tasync testCreatingDiscordClient(runtime: IAgentRuntime) {\n\t\ttry {\n\t\t\tthis.discordClient = runtime.getService(\n\t\t\t\tServiceType.DISCORD,\n\t\t\t) as DiscordService;\n\t\t\tif (!this.discordClient) {\n\t\t\t\tthrow new Error(\"Failed to get DiscordService from runtime.\");\n\t\t\t}\n\n\t\t\t// Wait for the bot to be ready before proceeding\n\t\t\tconst discordClient = this.discordClient.client;\n\t\t\tif (discordClient?.isReady()) {\n\t\t\t\tlogger.success(\"DiscordService is already ready.\");\n\t\t\t} else {\n\t\t\t\tlogger.info(\"Waiting for DiscordService to be ready...\");\n\t\t\t\tif (!discordClient) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"Discord client instance is missing within the service.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tawait new Promise((resolve, reject) => {\n\t\t\t\t\tif (discordClient) {\n\t\t\t\t\t\tdiscordClient.once(Events.ClientReady, resolve);\n\t\t\t\t\t\tdiscordClient.once(Events.Error, reject);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthrow new Error(`Error in test creating Discord client: ${error}`);\n\t\t}\n\t}\n\n\t/**\n\t * Asynchronously tests the join voice slash command functionality.\n\t *\n\t * @param {IAgentRuntime} runtime - The runtime environment for the agent.\n\t * @returns {Promise<void>} - A promise that resolves once the test is complete.\n\t * @throws {Error} - If there is an error in executing the slash command test.\n\t */\n\tasync testJoinVoiceSlashCommand(runtime: IAgentRuntime) {\n\t\tif (!this.discordClient) {\n\t\t\tthrow new Error(\"Discord client not initialized.\");\n\t\t}\n\t\ttry {\n\t\t\tawait this.waitForVoiceManagerReady(this.discordClient);\n\n\t\t\tconst channel = await this.getTestChannel(runtime);\n\t\t\tif (!channel || !channel.isTextBased()) {\n\t\t\t\tthrow new Error(\"Invalid test channel for slash command test.\");\n\t\t\t}\n\n\t\t\t// Simulate a join channel slash command interaction\n\t\t\tinterface MockJoinInteraction {\n\t\t\t\tisCommand: () => boolean;\n\t\t\t\tcommandName: string;\n\t\t\t\toptions: {\n\t\t\t\t\tget: (name: string) => { value: string } | null;\n\t\t\t\t};\n\t\t\t\tguild: Guild;\n\t\t\t\tdeferReply: () => Promise<void>;\n\t\t\t\teditReply: (message: string) => Promise<void>;\n\t\t\t}\n\t\t\tconst fakeJoinInteraction: MockJoinInteraction = {\n\t\t\t\tisCommand: () => true,\n\t\t\t\tcommandName: \"joinchannel\",\n\t\t\t\toptions: {\n\t\t\t\t\tget: (name: string) =>\n\t\t\t\t\t\tname === \"channel\" ? { value: channel.id } : null,\n\t\t\t\t},\n\t\t\t\tguild: (channel as TextChannel).guild,\n\t\t\t\tdeferReply: async () => {},\n\t\t\t\teditReply: async (message: string) => {\n\t\t\t\t\tlogger.info(`JoinChannel Slash Command Response: ${message}`);\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tif (!this.discordClient.voiceManager) {\n\t\t\t\tthrow new Error(\"VoiceManager is not available on the Discord client.\");\n\t\t\t}\n\t\t\tawait this.discordClient.voiceManager.handleJoinChannelCommand(\n\t\t\t\tfakeJoinInteraction,\n\t\t\t);\n\n\t\t\tlogger.success(\"Join voice slash command test completed successfully.\");\n\t\t} catch (error) {\n\t\t\tthrow new Error(`Error in join voice slash commands test: ${error}`);\n\t\t}\n\t}\n\n\t/**\n\t * Asynchronously tests the leave voice channel slash command.\n\t *\n\t * @param {IAgentRuntime} runtime - The Agent Runtime instance.\n\t * @returns {Promise<void>} A promise that resolves when the test is complete.\n\t */\n\tasync testLeaveVoiceSlashCommand(runtime: IAgentRuntime) {\n\t\tif (!this.discordClient) {\n\t\t\tthrow new Error(\"Discord client not initialized.\");\n\t\t}\n\t\ttry {\n\t\t\tawait this.waitForVoiceManagerReady(this.discordClient);\n\n\t\t\tconst channel = await this.getTestChannel(runtime);\n\t\t\tif (!channel || !channel.isTextBased()) {\n\t\t\t\tthrow new Error(\"Invalid test channel for slash command test.\");\n\t\t\t}\n\n\t\t\t// Simulate a leave channel slash command interaction\n\t\t\tinterface LeaveChannelInteraction {\n\t\t\t\tguildId: string | null;\n\t\t\t\treply: (message: string) => Promise<void>;\n\t\t\t}\n\t\t\tconst fakeLeaveInteraction: LeaveChannelInteraction = {\n\t\t\t\tguildId: (channel as TextChannel).guildId,\n\t\t\t\treply: async (message: string) => {\n\t\t\t\t\tlogger.info(`LeaveChannel Slash Command Response: ${message}`);\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tif (!this.discordClient.voiceManager) {\n\t\t\t\tthrow new Error(\"VoiceManager is not available on the Discord client.\");\n\t\t\t}\n\t\t\tawait this.discordClient.voiceManager.handleLeaveChannelCommand(\n\t\t\t\tfakeLeaveInteraction,\n\t\t\t);\n\n\t\t\tlogger.success(\"Leave voice slash command test completed successfully.\");\n\t\t} catch (error) {\n\t\t\tthrow new Error(`Error in leave voice slash commands test: ${error}`);\n\t\t}\n\t}\n\n\t/**\n\t * Test Text to Speech playback.\n\t * @param {IAgentRuntime} runtime - The Agent Runtime instance.\n\t * @throws {Error} - If voice channel is invalid, voice connection fails to become ready, or no text to speech service found.\n\t */\n\tasync testTextToSpeechPlayback(runtime: IAgentRuntime) {\n\t\tif (!this.discordClient) {\n\t\t\tthrow new Error(\"Discord client not initialized.\");\n\t\t}\n\t\ttry {\n\t\t\tawait this.waitForVoiceManagerReady(this.discordClient);\n\n\t\t\tconst channel = await this.getTestChannel(runtime);\n\t\t\tif (!channel || channel.type !== ChannelType.GuildVoice) {\n\t\t\t\tthrow new Error(\"Invalid voice channel.\");\n\t\t\t}\n\n\t\t\tif (!this.discordClient.voiceManager) {\n\t\t\t\tthrow new Error(\"VoiceManager is not available on the Discord client.\");\n\t\t\t}\n\t\t\tawait this.discordClient.voiceManager.joinChannel(channel);\n\n\t\t\tconst guild = await this.getActiveGuild(this.discordClient);\n\t\t\tconst guildId = guild.id;\n\n\t\t\tif (!this.discordClient.voiceManager) {\n\t\t\t\tthrow new Error(\"VoiceManager is not available on the Discord client.\");\n\t\t\t}\n\t\t\tconst connection =\n\t\t\t\tthis.discordClient.voiceManager.getVoiceConnection(guildId);\n\n\t\t\tif (!connection) {\n\t\t\t\tthrow new Error(`No voice connection found for guild: ${guildId}`);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tawait entersState(connection, VoiceConnectionStatus.Ready, 10_000);\n\t\t\t\tlogger.success(`Voice connection is ready in guild: ${guildId}`);\n\t\t\t} catch (error) {\n\t\t\t\tthrow new Error(`Voice connection failed to become ready: ${error}`);\n\t\t\t}\n\n\t\t\tlet responseStream = null;\n\n\t\t\ttry {\n\t\t\t\tresponseStream = await runtime.useModel(\n\t\t\t\t\tModelType.TEXT_TO_SPEECH,\n\t\t\t\t\t`Hi! I'm ${runtime.character.name}! How are you doing today?`,\n\t\t\t\t);\n\t\t\t} catch (_error) {\n\t\t\t\tthrow new Error(\"No text to speech service found\");\n\t\t\t}\n\n\t\t\tif (!responseStream) {\n\t\t\t\tthrow new Error(\"TTS response stream is null or undefined.\");\n\t\t\t}\n\n\t\t\tawait this.playAudioStream(responseStream, connection);\n\t\t} catch (error) {\n\t\t\tthrow new Error(`Error in TTS playback test: ${error}`);\n\t\t}\n\t}\n\n\t/**\n\t * Asynchronously tests sending a text message to a specified channel.\n\t *\n\t * @param {IAgentRuntime} runtime - The runtime for the agent.\n\t * @returns {Promise<void>} A Promise that resolves when the message is sent successfully.\n\t * @throws {Error} If there is an error in sending the text message.\n\t */\n\tasync testSendingTextMessage(runtime: IAgentRuntime) {\n\t\tif (!this.discordClient) {\n\t\t\tthrow new Error(\"Discord client not initialized.\");\n\t\t}\n\t\ttry {\n\t\t\tconst channel = await this.getTestChannel(runtime);\n\t\t\tif (!channel || !channel.isTextBased()) {\n\t\t\t\tthrow new Error(\"Cannot send message to a non-text channel.\");\n\t\t\t}\n\t\t\tconst attachment = new AttachmentBuilder(TEST_IMAGE_URL);\n\t\t\tawait this.sendMessageToChannel(\n\t\t\t\tchannel as TextChannel,\n\t\t\t\t\"Testing Message\",\n\t\t\t\t[attachment],\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tthrow new Error(`Error in sending text message: ${error}`);\n\t\t}\n\t}\n\n\t/**\n\t * Asynchronously handles sending a test message using the given runtime and mock user data.\n\t *\n\t * @param {IAgentRuntime} runtime - The agent runtime object.\n\t * @returns {Promise<void>} A Promise that resolves once the message is handled.\n\t */\n\tasync testHandlingMessage(runtime: IAgentRuntime) {\n\t\tif (!this.discordClient) {\n\t\t\tthrow new Error(\"Discord client not initialized.\");\n\t\t}\n\t\ttry {\n\t\t\tconst channel = await this.getTestChannel(runtime);\n\n\t\t\t// Create a mock message that satisfies the Message interface requirements\n\t\t\tinterface MockMessage {\n\t\t\t\tcontent: string;\n\t\t\t\tauthor: {\n\t\t\t\t\tid: string;\n\t\t\t\t\tusername: string;\n\t\t\t\t\tbot: boolean;\n\t\t\t\t};\n\t\t\t\tchannel: typeof channel;\n\t\t\t\tid: string;\n\t\t\t\tcreatedTimestamp: number;\n\t\t\t\tmentions: {\n\t\t\t\t\thas: (id: string) => boolean;\n\t\t\t\t};\n\t\t\t\treference: { messageId?: string } | null;\n\t\t\t\tattachments: unknown[];\n\t\t\t\tinteraction?: unknown;\n\t\t\t}\n\t\t\tconst fakeMessage: MockMessage = {\n\t\t\t\tcontent: `Hello, ${runtime.character.name}! How are you?`,\n\t\t\t\tauthor: {\n\t\t\t\t\tid: \"mock-user-id\",\n\t\t\t\t\tusername: \"MockUser\",\n\t\t\t\t\tbot: false,\n\t\t\t\t},\n\t\t\t\tchannel,\n\t\t\t\tid: \"mock-message-id\",\n\t\t\t\tcreatedTimestamp: Date.now(),\n\t\t\t\tmentions: {\n\t\t\t\t\thas: () => false,\n\t\t\t\t},\n\t\t\t\treference: null,\n\t\t\t\tattachments: [],\n\t\t\t};\n\t\t\tif (!this.discordClient.messageManager) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"MessageManager is not available on the Discord client.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\t// Type assertion through unknown is needed because MockMessage is a minimal test stub\n\t\t\tawait this.discordClient.messageManager.handleMessage(\n\t\t\t\tfakeMessage as unknown as Message<boolean>,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tthrow new Error(`Error in handling message test: ${error}`);\n\t\t}\n\t}\n\n\t// #############################\n\t// Utility Functions\n\t// #############################\n\n\t/**\n\t * Asynchronously retrieves the test channel associated with the provided runtime.\n\t *\n\t * @param {IAgentRuntime} runtime - The runtime object containing necessary information.\n\t * @returns {Promise<Channel>} The test channel retrieved from the Discord client.\n\t * @throws {Error} If no test channel is found.\n\t */\n\tasync getTestChannel(runtime: IAgentRuntime) {\n\t\tif (!this.discordClient) {\n\t\t\tthrow new Error(\"Discord client not initialized.\");\n\t\t}\n\t\tconst channelId = this.validateChannelId(runtime);\n\t\tconst discordClient = this.discordClient.client;\n\t\tconst channel =\n\t\t\tdiscordClient && (await discordClient.channels.fetch(channelId));\n\n\t\tif (!channel) {\n\t\t\tthrow new Error(\"no test channel found!\");\n\t\t}\n\n\t\treturn channel;\n\t}\n\n\t/**\n\t * Async function to send a message to a text-based channel.\n\t *\n\t * @param {TextChannel} channel - The text-based channel the message is being sent to.\n\t * @param {string} messageContent - The content of the message being sent.\n\t * @param {AttachmentBuilder[]} files - An array of files to include in the message.\n\t * @throws {Error} If the channel is not a text-based channel or does not exist.\n\t * @throws {Error} If there is an error sending the message.\n\t */\n\tasync sendMessageToChannel(\n\t\tchannel: TextChannel,\n\t\tmessageContent: string,\n\t\tfiles: AttachmentBuilder[],\n\t) {\n\t\ttry {\n\t\t\tif (!channel || !channel.isTextBased()) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"Channel is not a text-based channel or does not exist.\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Pass empty string for _inReplyTo as it expects a string\n\t\t\tawait sendMessageInChunks(\n\t\t\t\tchannel as TextChannel,\n\t\t\t\tmessageContent,\n\t\t\t\t\"\",\n\t\t\t\tfiles,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tthrow new Error(`Error sending message: ${error}`);\n\t\t}\n\t}\n\n\t/**\n\t * Play an audio stream from a given response stream using the provided VoiceConnection.\n\t *\n\t * @param responseStream - The response stream to play as audio.\n\t * @param connection - The VoiceConnection to use for playing the audio.\n\t * @returns A Promise that resolves when the TTS playback is finished.\n\t */\n\tasync playAudioStream(\n\t\tresponseStream: ReadableStream | NodeJS.ReadableStream | Readable,\n\t\tconnection: VoiceConnection,\n\t) {\n\t\tconst audioPlayer = createAudioPlayer({\n\t\t\tbehaviors: {\n\t\t\t\tnoSubscriber: NoSubscriberBehavior.Pause,\n\t\t\t},\n\t\t});\n\n\t\tconst audioResource = createAudioResource(responseStream as Readable);\n\n\t\taudioPlayer.play(audioResource);\n\t\tconnection.subscribe(audioPlayer);\n\n\t\tlogger.success(\"TTS playback started successfully.\");\n\n\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\taudioPlayer.once(AudioPlayerStatus.Idle, () => {\n\t\t\t\tlogger.info(\"TTS playback finished.\");\n\t\t\t\tresolve();\n\t\t\t});\n\n\t\t\taudioPlayer.once(\"error\", (error) => {\n\t\t\t\treject(error);\n\t\t\t\tthrow new Error(`TTS playback error: ${error}`);\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Retrieves the active guild where the bot is currently connected to a voice channel.\n\t *\n\t * @param {DiscordService} discordClient The DiscordService instance used to interact with the Discord API.\n\t * @returns {Promise<Guild>} The active guild where the bot is currently connected to a voice channel.\n\t * @throws {Error} If no active voice connection is found for the bot.\n\t */\n\tasync getActiveGuild(discordClient: DiscordService) {\n\t\tif (!discordClient.client) {\n\t\t\tthrow new Error(\"Discord client instance is missing within the service.\");\n\t\t}\n\t\tconst guilds = await discordClient.client.guilds.fetch();\n\t\tconst fullGuilds = await Promise.all(guilds.map((guild) => guild.fetch())); // Fetch full guild data\n\n\t\tconst activeGuild = fullGuilds.find((g) => {\n\t\t\tconst membersMe = g.members.me;\n\t\t\treturn membersMe?.voice?.channelId;\n\t\t});\n\t\tif (!activeGuild) {\n\t\t\tthrow new Error(\"No active voice connection found for the bot.\");\n\t\t}\n\t\treturn activeGuild;\n\t}\n\n\t/**\n\t * Waits for the VoiceManager in the Discord client to be ready.\n\t *\n\t * @param {DiscordService} discordClient - The Discord client to check for VoiceManager readiness.\n\t * @throws {Error} If the Discord client is not initialized.\n\t * @returns {Promise<void>} A promise that resolves when the VoiceManager is ready.\n\t */\n\tprivate async waitForVoiceManagerReady(discordClient: DiscordService) {\n\t\tif (!discordClient) {\n\t\t\t// This check might be redundant if called after the initial test setup check, but safe to keep.\n\t\t\tthrow new Error(\"Discord client is not initialized.\");\n\t\t}\n\n\t\tif (!discordClient.voiceManager) {\n\t\t\tthrow new Error(\"VoiceManager is not available on the Discord client.\");\n\t\t}\n\n\t\tconst voiceManager = discordClient.voiceManager;\n\t\tif (!voiceManager || !voiceManager.isReady()) {\n\t\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\t\tif (voiceManager) {\n\t\t\t\t\tvoiceManager.once(\"ready\", resolve);\n\t\t\t\t\tvoiceManager.once(\"error\", reject);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Validates the Discord test channel ID by checking if it is set in the runtime or environment variables.\n\t * If the test channel ID is not set, an error is thrown.\n\t *\n\t * @param {IAgentRuntime} runtime The runtime object containing the settings and environment variables.\n\t * @returns {string} The validated Discord test channel ID.\n\t */\n\tprivate validateChannelId(runtime: IAgentRuntime) {\n\t\tconst testChannelId =\n\t\t\truntime.getSetting(\"DISCORD_TEST_CHANNEL_ID\") ||\n\t\t\tprocess.env.DISCORD_TEST_CHANNEL_ID;\n\t\tif (!testChannelId) {\n\t\t\tthrow new Error(\n\t\t\t\t\"DISCORD_TEST_CHANNEL_ID is not set. Please provide a valid channel ID in the environment variables.\",\n\t\t\t);\n\t\t}\n\t\treturn testChannelId as string; // Assert as string since we check for falsy above\n\t}\n}\n",
|
|
124
|
+
"import type { IAgentRuntime } from \"@elizaos/core\";\n\n/**\n * Default account identifier used when no specific account is configured\n */\nexport const DEFAULT_ACCOUNT_ID = \"default\";\n\n/**\n * Source of the Discord token\n */\nexport type DiscordTokenSource = \"env\" | \"config\" | \"character\" | \"none\";\n\n/**\n * Result of token resolution\n */\nexport interface DiscordTokenResolution {\n\ttoken: string;\n\tsource: DiscordTokenSource;\n}\n\n/**\n * Configuration for a single Discord account\n */\nexport interface DiscordAccountConfig {\n\t/** Optional display name for this account */\n\tname?: string;\n\t/** If false, do not start this Discord account */\n\tenabled?: boolean;\n\t/** Discord bot token for this account */\n\ttoken?: string;\n\t/** Allow bot-authored messages to trigger replies */\n\tallowBots?: boolean;\n\t/** Controls how guild channel messages are handled */\n\tgroupPolicy?: \"open\" | \"disabled\" | \"allowlist\";\n\t/** Outbound text chunk size (chars) */\n\ttextChunkLimit?: number;\n\t/** Max lines per message */\n\tmaxLinesPerMessage?: number;\n\t/** Max media size in MB */\n\tmediaMaxMb?: number;\n\t/** History limit for context */\n\thistoryLimit?: number;\n\t/** Max DM turns to keep as history context */\n\tdmHistoryLimit?: number;\n\t/** DM configuration */\n\tdm?: DiscordDmConfig;\n\t/** Per-guild configuration */\n\tguilds?: Record<string, DiscordGuildEntry>;\n\t/** Channel IDs to allow */\n\tchannelIds?: string[];\n\t/** Listen-only channel IDs */\n\tlistenChannelIds?: string[];\n\t/** Whether to ignore bot messages */\n\tshouldIgnoreBotMessages?: boolean;\n\t/** Whether to ignore direct messages */\n\tshouldIgnoreDirectMessages?: boolean;\n\t/** Whether to respond only to mentions */\n\tshouldRespondOnlyToMentions?: boolean;\n}\n\n/**\n * DM-specific configuration\n */\nexport interface DiscordDmConfig {\n\t/** If false, ignore all incoming Discord DMs */\n\tenabled?: boolean;\n\t/** Direct message access policy */\n\tpolicy?: \"open\" | \"disabled\" | \"allowlist\" | \"pairing\";\n\t/** Allowlist for DM senders (ids or names) */\n\tallowFrom?: Array<string | number>;\n\t/** If true, allow group DMs */\n\tgroupEnabled?: boolean;\n\t/** Optional allowlist for group DM channels */\n\tgroupChannels?: Array<string | number>;\n}\n\n/**\n * Channel-specific configuration within a guild\n */\nexport interface DiscordGuildChannelConfig {\n\t/** Whether this channel is allowed */\n\tallow?: boolean;\n\t/** Require bot mention to respond */\n\trequireMention?: boolean;\n\t/** Skills to load for this channel */\n\tskills?: string[];\n\t/** If false, disable the bot for this channel */\n\tenabled?: boolean;\n\t/** Allowlist for channel senders */\n\tusers?: Array<string | number>;\n\t/** System prompt snippet for this channel */\n\tsystemPrompt?: string;\n\t/** Auto-create threads for replies */\n\tautoThread?: boolean;\n}\n\n/**\n * Guild-level configuration\n */\nexport interface DiscordGuildEntry {\n\t/** Guild slug for name-based matching */\n\tslug?: string;\n\t/** Require bot mention to respond */\n\trequireMention?: boolean;\n\t/** Reaction notification mode */\n\treactionNotifications?: \"off\" | \"own\" | \"all\" | \"allowlist\";\n\t/** Allowlist for guild users */\n\tusers?: Array<string | number>;\n\t/** Per-channel configuration */\n\tchannels?: Record<string, DiscordGuildChannelConfig>;\n}\n\n/**\n * Multi-account Discord configuration structure\n */\nexport interface DiscordMultiAccountConfig {\n\t/** Default/base configuration applied to all accounts */\n\tenabled?: boolean;\n\ttoken?: string;\n\t/** Per-account configuration overrides */\n\taccounts?: Record<string, DiscordAccountConfig>;\n}\n\n/**\n * Resolved Discord account with all configuration merged\n */\nexport interface ResolvedDiscordAccount {\n\taccountId: string;\n\tenabled: boolean;\n\tname?: string;\n\ttoken: string;\n\ttokenSource: DiscordTokenSource;\n\tconfig: DiscordAccountConfig;\n}\n\n/**\n * Normalizes an account ID, returning the default if not provided\n */\nexport function normalizeAccountId(accountId?: string | null): string {\n\tif (!accountId || typeof accountId !== \"string\") {\n\t\treturn DEFAULT_ACCOUNT_ID;\n\t}\n\tconst trimmed = accountId.trim().toLowerCase();\n\treturn trimmed || DEFAULT_ACCOUNT_ID;\n}\n\n/**\n * Normalizes a Discord token by trimming and removing \"Bot \" prefix\n */\nexport function normalizeDiscordToken(raw?: string | null): string | undefined {\n\tconst trimmed = raw?.trim();\n\treturn trimmed ? trimmed.replace(/^Bot\\s+/i, \"\") : undefined;\n}\n\n/**\n * Gets the multi-account configuration from runtime settings\n */\nexport function getMultiAccountConfig(\n\truntime: IAgentRuntime,\n): DiscordMultiAccountConfig {\n\tconst characterDiscord = runtime.character?.settings?.discord as\n\t\t| DiscordMultiAccountConfig\n\t\t| undefined;\n\n\treturn {\n\t\tenabled: characterDiscord?.enabled,\n\t\ttoken: characterDiscord?.token,\n\t\taccounts: characterDiscord?.accounts,\n\t};\n}\n\n/**\n * Lists all configured account IDs\n */\nexport function listDiscordAccountIds(runtime: IAgentRuntime): string[] {\n\tconst config = getMultiAccountConfig(runtime);\n\tconst accounts = config.accounts;\n\n\tif (!accounts || typeof accounts !== \"object\") {\n\t\treturn [DEFAULT_ACCOUNT_ID];\n\t}\n\n\tconst ids = Object.keys(accounts).filter(Boolean);\n\tif (ids.length === 0) {\n\t\treturn [DEFAULT_ACCOUNT_ID];\n\t}\n\n\treturn ids.slice().sort((a, b) => a.localeCompare(b));\n}\n\n/**\n * Resolves the default account ID to use\n */\nexport function resolveDefaultDiscordAccountId(runtime: IAgentRuntime): string {\n\tconst ids = listDiscordAccountIds(runtime);\n\tif (ids.includes(DEFAULT_ACCOUNT_ID)) {\n\t\treturn DEFAULT_ACCOUNT_ID;\n\t}\n\treturn ids[0] ?? DEFAULT_ACCOUNT_ID;\n}\n\n/**\n * Gets the account-specific configuration\n */\nfunction getAccountConfig(\n\truntime: IAgentRuntime,\n\taccountId: string,\n): DiscordAccountConfig | undefined {\n\tconst config = getMultiAccountConfig(runtime);\n\tconst accounts = config.accounts;\n\n\tif (!accounts || typeof accounts !== \"object\") {\n\t\treturn undefined;\n\t}\n\n\treturn accounts[accountId];\n}\n\n/**\n * Removes undefined values from an object to prevent them from overwriting during spread\n */\nfunction filterDefined<T extends object>(obj: T): Partial<T> {\n\treturn Object.fromEntries(\n\t\tObject.entries(obj).filter(([, v]) => v !== undefined),\n\t) as Partial<T>;\n}\n\n/**\n * Merges base configuration with account-specific overrides\n */\nfunction mergeDiscordAccountConfig(\n\truntime: IAgentRuntime,\n\taccountId: string,\n): DiscordAccountConfig {\n\tconst multiConfig = getMultiAccountConfig(runtime);\n\tconst { accounts: _ignored, ...baseConfig } = multiConfig;\n\tconst accountConfig = getAccountConfig(runtime, accountId) ?? {};\n\n\t// Get environment/runtime settings for the base config\n\tconst envChannelIds = runtime.getSetting(\"CHANNEL_IDS\") as string | undefined;\n\tconst envListenChannelIds = runtime.getSetting(\n\t\t\"DISCORD_LISTEN_CHANNEL_IDS\",\n\t) as string | undefined;\n\n\tconst envConfig: DiscordAccountConfig = {\n\t\tshouldIgnoreBotMessages:\n\t\t\t(\n\t\t\t\truntime.getSetting(\"DISCORD_SHOULD_IGNORE_BOT_MESSAGES\") as string\n\t\t\t)?.toLowerCase() === \"true\",\n\t\tshouldIgnoreDirectMessages:\n\t\t\t(\n\t\t\t\truntime.getSetting(\"DISCORD_SHOULD_IGNORE_DIRECT_MESSAGES\") as string\n\t\t\t)?.toLowerCase() === \"true\",\n\t\tshouldRespondOnlyToMentions:\n\t\t\t(\n\t\t\t\truntime.getSetting(\"DISCORD_SHOULD_RESPOND_ONLY_TO_MENTIONS\") as string\n\t\t\t)?.toLowerCase() === \"true\",\n\t\tchannelIds: envChannelIds\n\t\t\t? envChannelIds\n\t\t\t\t\t.split(\",\")\n\t\t\t\t\t.map((s) => s.trim())\n\t\t\t\t\t.filter(Boolean)\n\t\t\t: undefined,\n\t\tlistenChannelIds: envListenChannelIds\n\t\t\t? envListenChannelIds\n\t\t\t\t\t.split(\",\")\n\t\t\t\t\t.map((s) => s.trim())\n\t\t\t\t\t.filter(Boolean)\n\t\t\t: undefined,\n\t};\n\n\t// Merge order: env defaults < base config < account config\n\t// Filter undefined values to prevent them from overwriting defined values\n\treturn {\n\t\t...filterDefined(envConfig),\n\t\t...filterDefined(baseConfig),\n\t\t...filterDefined(accountConfig),\n\t};\n}\n\n/**\n * Resolves the Discord token for a specific account\n */\nexport function resolveDiscordToken(\n\truntime: IAgentRuntime,\n\topts: { accountId?: string | null } = {},\n): DiscordTokenResolution {\n\tconst accountId = normalizeAccountId(opts.accountId);\n\tconst multiConfig = getMultiAccountConfig(runtime);\n\n\t// Check account-specific token first\n\tconst accountConfig =\n\t\taccountId !== DEFAULT_ACCOUNT_ID\n\t\t\t? multiConfig.accounts?.[accountId]\n\t\t\t: multiConfig.accounts?.[DEFAULT_ACCOUNT_ID];\n\n\tconst accountToken = normalizeDiscordToken(accountConfig?.token);\n\tif (accountToken) {\n\t\treturn { token: accountToken, source: \"config\" };\n\t}\n\n\t// For default account, check base config token\n\tconst allowBase = accountId === DEFAULT_ACCOUNT_ID;\n\tconst baseToken = allowBase\n\t\t? normalizeDiscordToken(multiConfig.token)\n\t\t: undefined;\n\tif (baseToken) {\n\t\treturn { token: baseToken, source: \"character\" };\n\t}\n\n\t// For default account, check environment token\n\tconst envToken = allowBase\n\t\t? normalizeDiscordToken(runtime.getSetting(\"DISCORD_API_TOKEN\") as string)\n\t\t: undefined;\n\tif (envToken) {\n\t\treturn { token: envToken, source: \"env\" };\n\t}\n\n\treturn { token: \"\", source: \"none\" };\n}\n\n/**\n * Resolves a complete Discord account configuration\n */\nexport function resolveDiscordAccount(\n\truntime: IAgentRuntime,\n\taccountId?: string | null,\n): ResolvedDiscordAccount {\n\tconst normalizedAccountId = normalizeAccountId(accountId);\n\tconst multiConfig = getMultiAccountConfig(runtime);\n\n\tconst baseEnabled = multiConfig.enabled !== false;\n\tconst merged = mergeDiscordAccountConfig(runtime, normalizedAccountId);\n\tconst accountEnabled = merged.enabled !== false;\n\tconst enabled = baseEnabled && accountEnabled;\n\n\tconst tokenResolution = resolveDiscordToken(runtime, {\n\t\taccountId: normalizedAccountId,\n\t});\n\n\treturn {\n\t\taccountId: normalizedAccountId,\n\t\tenabled,\n\t\tname: merged.name?.trim() || undefined,\n\t\ttoken: tokenResolution.token,\n\t\ttokenSource: tokenResolution.source,\n\t\tconfig: merged,\n\t};\n}\n\n/**\n * Lists all enabled Discord accounts\n */\nexport function listEnabledDiscordAccounts(\n\truntime: IAgentRuntime,\n): ResolvedDiscordAccount[] {\n\treturn listDiscordAccountIds(runtime)\n\t\t.map((accountId) => resolveDiscordAccount(runtime, accountId))\n\t\t.filter((account) => account.enabled && account.token);\n}\n\n/**\n * Checks if multi-account mode is enabled\n */\nexport function isMultiAccountEnabled(runtime: IAgentRuntime): boolean {\n\tconst accounts = listEnabledDiscordAccounts(runtime);\n\treturn accounts.length > 1;\n}\n",
|
|
125
|
+
"import type { Guild, GuildMember, User } from \"discord.js\";\nimport type {\n\tDiscordAccountConfig,\n\tDiscordGuildChannelConfig,\n\tDiscordGuildEntry,\n} from \"./accounts\";\n\n/**\n * Normalized allowlist structure for Discord entities\n */\nexport interface DiscordAllowList {\n\tallowAll: boolean;\n\tids: Set<string>;\n\tnames: Set<string>;\n}\n\n/**\n * Match source type for allowlist matching\n */\nexport type AllowListMatchSource = \"wildcard\" | \"id\" | \"name\" | \"tag\";\n\n/**\n * Result of an allowlist match operation\n */\nexport interface DiscordAllowListMatch {\n\tallowed: boolean;\n\tmatchKey?: string;\n\tmatchSource?: AllowListMatchSource;\n}\n\n/**\n * Match source for channel configuration\n */\nexport type ChannelMatchSource = \"id\" | \"name\" | \"slug\" | \"wildcard\" | \"parent\";\n\n/**\n * Resolved channel configuration with match metadata\n */\nexport interface DiscordChannelConfigResolved {\n\tallowed: boolean;\n\trequireMention?: boolean;\n\tskills?: string[];\n\tenabled?: boolean;\n\tusers?: Array<string | number>;\n\tsystemPrompt?: string;\n\tautoThread?: boolean;\n\tmatchKey?: string;\n\tmatchSource?: ChannelMatchSource;\n}\n\n/**\n * Normalizes a Discord slug (channel name, guild name, etc.)\n * Converts to lowercase, removes special characters, replaces spaces with dashes\n */\nexport function normalizeDiscordSlug(value: string): string {\n\treturn value\n\t\t.trim()\n\t\t.toLowerCase()\n\t\t.replace(/^#/, \"\")\n\t\t.replace(/[^a-z0-9]+/g, \"-\")\n\t\t.replace(/^-+|-+$/g, \"\");\n}\n\n/**\n * Formats a Discord user tag for matching\n */\nexport function formatDiscordUserTag(user: User | GuildMember): string {\n\tif (\"user\" in user) {\n\t\treturn user.user.discriminator === \"0\"\n\t\t\t? user.user.username\n\t\t\t: `${user.user.username}#${user.user.discriminator}`;\n\t}\n\treturn user.discriminator === \"0\"\n\t\t? user.username\n\t\t: `${user.username}#${user.discriminator}`;\n}\n\n/**\n * Normalizes a raw allowlist array into a structured DiscordAllowList\n */\nexport function normalizeDiscordAllowList(\n\traw: Array<string | number> | undefined,\n\tprefixes: string[] = [\"discord:\", \"user:\", \"pk:\"],\n): DiscordAllowList | null {\n\tif (!raw || raw.length === 0) {\n\t\treturn null;\n\t}\n\n\tconst ids = new Set<string>();\n\tconst names = new Set<string>();\n\tconst allowAll = raw.some((entry) => String(entry).trim() === \"*\");\n\n\tfor (const entry of raw) {\n\t\tconst text = String(entry).trim();\n\t\tif (!text || text === \"*\") {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst normalized = normalizeDiscordSlug(text);\n\n\t\t// Check for mention format <@!123456> or <@123456>\n\t\tconst maybeId = text.replace(/^<@!?/, \"\").replace(/>$/, \"\");\n\t\tif (/^\\d+$/.test(maybeId)) {\n\t\t\tids.add(maybeId);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Check for prefixed IDs\n\t\tconst prefix = prefixes.find((p) => text.startsWith(p));\n\t\tif (prefix) {\n\t\t\tconst candidate = text.slice(prefix.length);\n\t\t\tif (candidate) {\n\t\t\t\tids.add(candidate);\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Otherwise treat as name/slug\n\t\tif (normalized) {\n\t\t\tnames.add(normalized);\n\t\t}\n\t}\n\n\treturn { allowAll, ids, names };\n}\n\n/**\n * Checks if a candidate matches the allowlist\n */\nexport function allowListMatches(\n\tlist: DiscordAllowList,\n\tcandidate: { id?: string; name?: string; tag?: string },\n): boolean {\n\tif (list.allowAll) {\n\t\treturn true;\n\t}\n\n\tif (candidate.id && list.ids.has(candidate.id)) {\n\t\treturn true;\n\t}\n\n\tconst slug = candidate.name ? normalizeDiscordSlug(candidate.name) : \"\";\n\tif (slug && list.names.has(slug)) {\n\t\treturn true;\n\t}\n\n\tif (candidate.tag && list.names.has(normalizeDiscordSlug(candidate.tag))) {\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n/**\n * Resolves an allowlist match with detailed match information\n */\nexport function resolveDiscordAllowListMatch(params: {\n\tallowList: DiscordAllowList;\n\tcandidate: { id?: string; name?: string; tag?: string };\n}): DiscordAllowListMatch {\n\tconst { allowList, candidate } = params;\n\n\tif (allowList.allowAll) {\n\t\treturn { allowed: true, matchKey: \"*\", matchSource: \"wildcard\" };\n\t}\n\n\tif (candidate.id && allowList.ids.has(candidate.id)) {\n\t\treturn { allowed: true, matchKey: candidate.id, matchSource: \"id\" };\n\t}\n\n\tconst nameSlug = candidate.name ? normalizeDiscordSlug(candidate.name) : \"\";\n\tif (nameSlug && allowList.names.has(nameSlug)) {\n\t\treturn { allowed: true, matchKey: nameSlug, matchSource: \"name\" };\n\t}\n\n\tconst tagSlug = candidate.tag ? normalizeDiscordSlug(candidate.tag) : \"\";\n\tif (tagSlug && allowList.names.has(tagSlug)) {\n\t\treturn { allowed: true, matchKey: tagSlug, matchSource: \"tag\" };\n\t}\n\n\treturn { allowed: false };\n}\n\n/**\n * Checks if a Discord user is allowed based on an allowlist\n */\nexport function resolveDiscordUserAllowed(params: {\n\tallowList?: Array<string | number>;\n\tuserId: string;\n\tuserName?: string;\n\tuserTag?: string;\n}): boolean {\n\tconst allowList = normalizeDiscordAllowList(params.allowList, [\n\t\t\"discord:\",\n\t\t\"user:\",\n\t\t\"pk:\",\n\t]);\n\tif (!allowList) {\n\t\treturn true;\n\t}\n\n\treturn allowListMatches(allowList, {\n\t\tid: params.userId,\n\t\tname: params.userName,\n\t\ttag: params.userTag,\n\t});\n}\n\n/**\n * Checks if a user is authorized for commands in DMs\n */\nexport function resolveDiscordCommandAuthorized(params: {\n\tisDirectMessage: boolean;\n\tallowFrom?: Array<string | number>;\n\tauthor: User;\n}): boolean {\n\tif (!params.isDirectMessage) {\n\t\treturn true;\n\t}\n\n\tconst allowList = normalizeDiscordAllowList(params.allowFrom, [\n\t\t\"discord:\",\n\t\t\"user:\",\n\t\t\"pk:\",\n\t]);\n\tif (!allowList) {\n\t\treturn true;\n\t}\n\n\treturn allowListMatches(allowList, {\n\t\tid: params.author.id,\n\t\tname: params.author.username,\n\t\ttag: formatDiscordUserTag(params.author),\n\t});\n}\n\n/**\n * Resolves guild entry configuration by ID or slug\n */\nexport function resolveDiscordGuildEntry(params: {\n\tguild?: Guild | null;\n\tguildEntries?: Record<string, DiscordGuildEntry>;\n}): (DiscordGuildEntry & { id?: string }) | null {\n\tconst { guild, guildEntries } = params;\n\tif (!guild || !guildEntries) {\n\t\treturn null;\n\t}\n\n\t// Check by ID first\n\tconst byId = guildEntries[guild.id];\n\tif (byId) {\n\t\treturn { ...byId, id: guild.id };\n\t}\n\n\t// Check by slug\n\tconst slug = normalizeDiscordSlug(guild.name ?? \"\");\n\tconst bySlug = guildEntries[slug];\n\tif (bySlug) {\n\t\treturn { ...bySlug, id: guild.id, slug: slug || bySlug.slug };\n\t}\n\n\t// Check for wildcard\n\tconst wildcard = guildEntries[\"*\"];\n\tif (wildcard) {\n\t\treturn { ...wildcard, id: guild.id, slug: slug || wildcard.slug };\n\t}\n\n\treturn null;\n}\n\n/**\n * Builds channel key candidates for matching\n */\nfunction buildChannelKeyCandidates(\n\tid: string,\n\tslug?: string,\n\tname?: string,\n\tallowNameMatch = true,\n): string[] {\n\tconst keys: string[] = [id];\n\n\tif (allowNameMatch) {\n\t\tif (slug) {\n\t\t\tkeys.push(slug);\n\t\t}\n\t\tif (name) {\n\t\t\tconst nameSlug = normalizeDiscordSlug(name);\n\t\t\tif (nameSlug && nameSlug !== slug) {\n\t\t\t\tkeys.push(nameSlug);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn keys;\n}\n\n/**\n * Resolves channel entry match from configuration\n */\nfunction resolveChannelEntryMatch(\n\tchannels: Record<string, DiscordGuildChannelConfig>,\n\tkeys: string[],\n\tparentKeys?: string[],\n): {\n\tentry: DiscordGuildChannelConfig;\n\tmatchKey: string;\n\tmatchSource: ChannelMatchSource;\n} | null {\n\t// Try direct keys first\n\tfor (const key of keys) {\n\t\tconst entry = channels[key];\n\t\tif (entry) {\n\t\t\tconst source: ChannelMatchSource = /^\\d+$/.test(key) ? \"id\" : \"name\";\n\t\t\treturn { entry, matchKey: key, matchSource: source };\n\t\t}\n\t}\n\n\t// Try parent keys if provided\n\tif (parentKeys) {\n\t\tfor (const parentKey of parentKeys) {\n\t\t\tconst entry = channels[parentKey];\n\t\t\tif (entry) {\n\t\t\t\treturn { entry, matchKey: parentKey, matchSource: \"parent\" };\n\t\t\t}\n\t\t}\n\t}\n\n\t// Try wildcard\n\tconst wildcard = channels[\"*\"];\n\tif (wildcard) {\n\t\treturn { entry: wildcard, matchKey: \"*\", matchSource: \"wildcard\" };\n\t}\n\n\treturn null;\n}\n\n/**\n * Resolves channel configuration from guild info\n */\nexport function resolveDiscordChannelConfig(params: {\n\tguildInfo?: (DiscordGuildEntry & { id?: string }) | null;\n\tchannelId: string;\n\tchannelName?: string;\n\tchannelSlug?: string;\n}): DiscordChannelConfigResolved | null {\n\tconst { guildInfo, channelId, channelName } = params;\n\tconst channelSlug =\n\t\tparams.channelSlug ??\n\t\t(channelName ? normalizeDiscordSlug(channelName) : \"\");\n\tconst channels = guildInfo?.channels;\n\n\tif (!channels) {\n\t\treturn null;\n\t}\n\n\tconst keys = buildChannelKeyCandidates(channelId, channelSlug, channelName);\n\tconst match = resolveChannelEntryMatch(channels, keys);\n\n\tif (!match) {\n\t\treturn { allowed: false };\n\t}\n\n\treturn {\n\t\tallowed: match.entry.allow !== false,\n\t\trequireMention: match.entry.requireMention,\n\t\tskills: match.entry.skills,\n\t\tenabled: match.entry.enabled,\n\t\tusers: match.entry.users,\n\t\tsystemPrompt: match.entry.systemPrompt,\n\t\tautoThread: match.entry.autoThread,\n\t\tmatchKey: match.matchKey,\n\t\tmatchSource: match.matchSource,\n\t};\n}\n\n/**\n * Resolves channel configuration with thread/parent fallback\n */\nexport function resolveDiscordChannelConfigWithFallback(params: {\n\tguildInfo?: (DiscordGuildEntry & { id?: string }) | null;\n\tchannelId: string;\n\tchannelName?: string;\n\tchannelSlug?: string;\n\tparentId?: string;\n\tparentName?: string;\n\tparentSlug?: string;\n\tisThread?: boolean;\n}): DiscordChannelConfigResolved | null {\n\tconst {\n\t\tguildInfo,\n\t\tchannelId,\n\t\tchannelName,\n\t\tparentId,\n\t\tparentName,\n\t\tparentSlug,\n\t\tisThread = false,\n\t} = params;\n\tconst channelSlug =\n\t\tparams.channelSlug ??\n\t\t(channelName ? normalizeDiscordSlug(channelName) : \"\");\n\tconst channels = guildInfo?.channels;\n\n\tif (!channels) {\n\t\treturn null;\n\t}\n\n\tconst resolvedParentSlug =\n\t\tparentSlug ?? (parentName ? normalizeDiscordSlug(parentName) : \"\");\n\n\t// For threads, don't match by name (thread names change)\n\tconst keys = buildChannelKeyCandidates(\n\t\tchannelId,\n\t\tchannelSlug,\n\t\tchannelName,\n\t\t!isThread,\n\t);\n\n\tconst parentKeys =\n\t\tparentId || parentName || parentSlug\n\t\t\t? buildChannelKeyCandidates(\n\t\t\t\t\tparentId ?? \"\",\n\t\t\t\t\tresolvedParentSlug,\n\t\t\t\t\tparentName,\n\t\t\t\t)\n\t\t\t: undefined;\n\n\tconst match = resolveChannelEntryMatch(channels, keys, parentKeys);\n\n\tif (!match) {\n\t\treturn { allowed: false };\n\t}\n\n\treturn {\n\t\tallowed: match.entry.allow !== false,\n\t\trequireMention: match.entry.requireMention,\n\t\tskills: match.entry.skills,\n\t\tenabled: match.entry.enabled,\n\t\tusers: match.entry.users,\n\t\tsystemPrompt: match.entry.systemPrompt,\n\t\tautoThread: match.entry.autoThread,\n\t\tmatchKey: match.matchKey,\n\t\tmatchSource: match.matchSource,\n\t};\n}\n\n/**\n * Determines if a mention is required for the bot to respond\n */\nexport function resolveDiscordShouldRequireMention(params: {\n\tisGuildMessage: boolean;\n\tisThread: boolean;\n\tbotId?: string | null;\n\tthreadOwnerId?: string | null;\n\tchannelConfig?: DiscordChannelConfigResolved | null;\n\tguildInfo?: (DiscordGuildEntry & { id?: string }) | null;\n\tisAutoThreadOwnedByBot?: boolean;\n}): boolean {\n\tif (!params.isGuildMessage) {\n\t\treturn false;\n\t}\n\n\t// Don't require mention in threads created by the bot (autoThread)\n\tconst isBotThread =\n\t\tparams.isAutoThreadOwnedByBot ?? isDiscordAutoThreadOwnedByBot(params);\n\tif (isBotThread) {\n\t\treturn false;\n\t}\n\n\treturn (\n\t\tparams.channelConfig?.requireMention ??\n\t\tparams.guildInfo?.requireMention ??\n\t\ttrue\n\t);\n}\n\n/**\n * Checks if a thread was created by the bot via autoThread feature\n */\nexport function isDiscordAutoThreadOwnedByBot(params: {\n\tisThread: boolean;\n\tchannelConfig?: DiscordChannelConfigResolved | null;\n\tbotId?: string | null;\n\tthreadOwnerId?: string | null;\n}): boolean {\n\tif (!params.isThread) {\n\t\treturn false;\n\t}\n\n\tif (!params.channelConfig?.autoThread) {\n\t\treturn false;\n\t}\n\n\tconst botId = params.botId?.trim();\n\tconst threadOwnerId = params.threadOwnerId?.trim();\n\n\treturn Boolean(botId && threadOwnerId && botId === threadOwnerId);\n}\n\n/**\n * Checks if a group (guild channel) is allowed by the policy\n */\nexport function isDiscordGroupAllowedByPolicy(params: {\n\tgroupPolicy: \"open\" | \"disabled\" | \"allowlist\";\n\tguildAllowlisted: boolean;\n\tchannelAllowlistConfigured: boolean;\n\tchannelAllowed: boolean;\n}): boolean {\n\tconst {\n\t\tgroupPolicy,\n\t\tguildAllowlisted,\n\t\tchannelAllowlistConfigured,\n\t\tchannelAllowed,\n\t} = params;\n\n\tif (groupPolicy === \"disabled\") {\n\t\treturn false;\n\t}\n\n\tif (groupPolicy === \"open\") {\n\t\treturn true;\n\t}\n\n\t// allowlist mode\n\tif (!guildAllowlisted) {\n\t\treturn false;\n\t}\n\n\tif (!channelAllowlistConfigured) {\n\t\treturn true;\n\t}\n\n\treturn channelAllowed;\n}\n\n/**\n * Resolves if a group DM is allowed\n */\nexport function resolveGroupDmAllow(params: {\n\tchannels?: Array<string | number>;\n\tchannelId: string;\n\tchannelName?: string;\n\tchannelSlug?: string;\n}): boolean {\n\tconst { channels, channelId, channelName } = params;\n\tconst channelSlug =\n\t\tparams.channelSlug ??\n\t\t(channelName ? normalizeDiscordSlug(channelName) : \"\");\n\n\tif (!channels || channels.length === 0) {\n\t\treturn true;\n\t}\n\n\tconst allowList = new Set(\n\t\tchannels.map((entry) => normalizeDiscordSlug(String(entry))),\n\t);\n\tconst candidates = [\n\t\tnormalizeDiscordSlug(channelId),\n\t\tchannelSlug,\n\t\tchannelName ? normalizeDiscordSlug(channelName) : \"\",\n\t].filter(Boolean);\n\n\treturn (\n\t\tallowList.has(\"*\") ||\n\t\tcandidates.some((candidate) => allowList.has(candidate))\n\t);\n}\n\n/**\n * Determines if a reaction notification should be emitted\n */\nexport function shouldEmitDiscordReactionNotification(params: {\n\tmode?: \"off\" | \"own\" | \"all\" | \"allowlist\";\n\tbotId?: string;\n\tmessageAuthorId?: string;\n\tuserId: string;\n\tuserName?: string;\n\tuserTag?: string;\n\tallowlist?: Array<string | number>;\n}): boolean {\n\tconst mode = params.mode ?? \"own\";\n\n\tif (mode === \"off\") {\n\t\treturn false;\n\t}\n\n\tif (mode === \"all\") {\n\t\treturn true;\n\t}\n\n\tif (mode === \"own\") {\n\t\treturn Boolean(params.botId && params.messageAuthorId === params.botId);\n\t}\n\n\tif (mode === \"allowlist\") {\n\t\tconst list = normalizeDiscordAllowList(params.allowlist, [\n\t\t\t\"discord:\",\n\t\t\t\"user:\",\n\t\t\t\"pk:\",\n\t\t]);\n\t\tif (!list) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn allowListMatches(list, {\n\t\t\tid: params.userId,\n\t\t\tname: params.userName,\n\t\t\ttag: params.userTag,\n\t\t});\n\t}\n\n\treturn false;\n}\n\n/**\n * Validates a message against all allowlist policies\n */\nexport function validateMessageAllowed(params: {\n\taccountConfig: DiscordAccountConfig;\n\tisDirectMessage: boolean;\n\tisGroupDm: boolean;\n\tguild?: Guild | null;\n\tchannelId: string;\n\tchannelName?: string;\n\tauthor: User;\n\tbotId?: string;\n}): {\n\tallowed: boolean;\n\treason?: string;\n\tchannelConfig?: DiscordChannelConfigResolved | null;\n\tguildInfo?: (DiscordGuildEntry & { id?: string }) | null;\n} {\n\tconst {\n\t\taccountConfig,\n\t\tisDirectMessage,\n\t\tisGroupDm,\n\t\tguild,\n\t\tchannelId,\n\t\tchannelName,\n\t\tauthor,\n\t} = params;\n\n\t// Handle DMs\n\tif (isDirectMessage && !isGroupDm) {\n\t\tconst dmConfig = accountConfig.dm;\n\n\t\tif (dmConfig?.enabled === false) {\n\t\t\treturn { allowed: false, reason: \"DMs disabled\" };\n\t\t}\n\n\t\tconst dmPolicy = dmConfig?.policy ?? \"open\";\n\t\tif (dmPolicy === \"disabled\") {\n\t\t\treturn { allowed: false, reason: \"DM policy disabled\" };\n\t\t}\n\n\t\tif (dmPolicy === \"allowlist\" && dmConfig?.allowFrom) {\n\t\t\tconst isAllowed = resolveDiscordUserAllowed({\n\t\t\t\tallowList: dmConfig.allowFrom,\n\t\t\t\tuserId: author.id,\n\t\t\t\tuserName: author.username,\n\t\t\t\tuserTag: formatDiscordUserTag(author),\n\t\t\t});\n\n\t\t\tif (!isAllowed) {\n\t\t\t\treturn { allowed: false, reason: \"User not in DM allowlist\" };\n\t\t\t}\n\t\t}\n\n\t\treturn { allowed: true };\n\t}\n\n\t// Handle group DMs\n\tif (isGroupDm) {\n\t\tconst dmConfig = accountConfig.dm;\n\n\t\tif (!dmConfig?.groupEnabled) {\n\t\t\treturn { allowed: false, reason: \"Group DMs disabled\" };\n\t\t}\n\n\t\tconst isAllowed = resolveGroupDmAllow({\n\t\t\tchannels: dmConfig.groupChannels,\n\t\t\tchannelId,\n\t\t\tchannelName,\n\t\t});\n\n\t\tif (!isAllowed) {\n\t\t\treturn { allowed: false, reason: \"Group DM channel not allowed\" };\n\t\t}\n\n\t\treturn { allowed: true };\n\t}\n\n\t// Handle guild messages\n\tconst groupPolicy = accountConfig.groupPolicy ?? \"open\";\n\tconst guildInfo = resolveDiscordGuildEntry({\n\t\tguild,\n\t\tguildEntries: accountConfig.guilds,\n\t});\n\n\tconst guildAllowlisted = guildInfo !== null;\n\tconst channelSlug = channelName ? normalizeDiscordSlug(channelName) : \"\";\n\n\tconst channelConfig = resolveDiscordChannelConfig({\n\t\tguildInfo,\n\t\tchannelId,\n\t\tchannelName,\n\t\tchannelSlug,\n\t});\n\n\tconst channelAllowlistConfigured = Boolean(guildInfo?.channels);\n\tconst channelAllowed = channelConfig?.allowed ?? false;\n\n\tconst isAllowed = isDiscordGroupAllowedByPolicy({\n\t\tgroupPolicy,\n\t\tguildAllowlisted,\n\t\tchannelAllowlistConfigured,\n\t\tchannelAllowed,\n\t});\n\n\tif (!isAllowed) {\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\treason: \"Channel not allowed by policy\",\n\t\t\tchannelConfig,\n\t\t\tguildInfo,\n\t\t};\n\t}\n\n\t// Check user allowlist for channel\n\tif (channelConfig?.users) {\n\t\tconst userAllowed = resolveDiscordUserAllowed({\n\t\t\tallowList: channelConfig.users,\n\t\t\tuserId: author.id,\n\t\t\tuserName: author.username,\n\t\t\tuserTag: formatDiscordUserTag(author),\n\t\t});\n\n\t\tif (!userAllowed) {\n\t\t\treturn {\n\t\t\t\tallowed: false,\n\t\t\t\treason: \"User not in channel allowlist\",\n\t\t\t\tchannelConfig,\n\t\t\t\tguildInfo,\n\t\t\t};\n\t\t}\n\t}\n\n\t// Check user allowlist for guild\n\tif (guildInfo?.users) {\n\t\tconst userAllowed = resolveDiscordUserAllowed({\n\t\t\tallowList: guildInfo.users,\n\t\t\tuserId: author.id,\n\t\t\tuserName: author.username,\n\t\t\tuserTag: formatDiscordUserTag(author),\n\t\t});\n\n\t\tif (!userAllowed) {\n\t\t\treturn {\n\t\t\t\tallowed: false,\n\t\t\t\treason: \"User not in guild allowlist\",\n\t\t\t\tchannelConfig,\n\t\t\t\tguildInfo,\n\t\t\t};\n\t\t}\n\t}\n\n\treturn { allowed: true, channelConfig, guildInfo };\n}\n",
|
|
126
|
+
"import type { Guild, MessageReaction } from \"discord.js\";\n\n/**\n * Options for chunking Discord text\n */\nexport interface ChunkDiscordTextOpts {\n\t/** Max characters per Discord message. Default: 2000. */\n\tmaxChars?: number;\n\t/**\n\t * Soft max line count per message. Default: 17.\n\t * Discord clients can clip/collapse very tall messages in the UI.\n\t */\n\tmaxLines?: number;\n\t/** Chunking mode: \"length\" (default) or \"newline\" */\n\tchunkMode?: \"length\" | \"newline\";\n}\n\ninterface OpenFence {\n\tindent: string;\n\tmarkerChar: string;\n\tmarkerLen: number;\n\topenLine: string;\n}\n\nconst DEFAULT_MAX_CHARS = 2000;\nconst DEFAULT_MAX_LINES = 17;\nconst FENCE_RE = /^( {0,3})(`{3,}|~{3,})(.*)$/;\n\nfunction countLines(text: string): number {\n\tif (!text) {\n\t\treturn 0;\n\t}\n\treturn text.split(\"\\n\").length;\n}\n\nfunction parseFenceLine(line: string): OpenFence | null {\n\tconst match = line.match(FENCE_RE);\n\tif (!match) {\n\t\treturn null;\n\t}\n\tconst indent = match[1] ?? \"\";\n\tconst marker = match[2] ?? \"\";\n\treturn {\n\t\tindent,\n\t\tmarkerChar: marker[0] ?? \"`\",\n\t\tmarkerLen: marker.length,\n\t\topenLine: line,\n\t};\n}\n\nfunction closeFenceLine(openFence: OpenFence): string {\n\treturn `${openFence.indent}${openFence.markerChar.repeat(openFence.markerLen)}`;\n}\n\nfunction closeFenceIfNeeded(text: string, openFence: OpenFence | null): string {\n\tif (!openFence) {\n\t\treturn text;\n\t}\n\tconst closeLine = closeFenceLine(openFence);\n\tif (!text) {\n\t\treturn closeLine;\n\t}\n\tif (!text.endsWith(\"\\n\")) {\n\t\treturn `${text}\\n${closeLine}`;\n\t}\n\treturn `${text}${closeLine}`;\n}\n\nfunction splitLongLine(\n\tline: string,\n\tmaxChars: number,\n\topts: { preserveWhitespace: boolean },\n): string[] {\n\tconst limit = Math.max(1, Math.floor(maxChars));\n\tif (line.length <= limit) {\n\t\treturn [line];\n\t}\n\n\tconst out: string[] = [];\n\tlet remaining = line;\n\n\twhile (remaining.length > limit) {\n\t\tif (opts.preserveWhitespace) {\n\t\t\tout.push(remaining.slice(0, limit));\n\t\t\tremaining = remaining.slice(limit);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst window = remaining.slice(0, limit);\n\t\tlet breakIdx = -1;\n\t\tfor (let i = window.length - 1; i >= 0; i--) {\n\t\t\tif (/\\s/.test(window[i])) {\n\t\t\t\tbreakIdx = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (breakIdx <= 0) {\n\t\t\tbreakIdx = limit;\n\t\t}\n\n\t\tout.push(remaining.slice(0, breakIdx));\n\t\tremaining = remaining.slice(breakIdx);\n\t}\n\n\tif (remaining.length) {\n\t\tout.push(remaining);\n\t}\n\n\treturn out;\n}\n\nfunction isReasoningItalicsPayload(source: string): boolean {\n\treturn source.startsWith(\"Reasoning:\\n_\") && source.trimEnd().endsWith(\"_\");\n}\n\n/**\n * Keep italics intact for reasoning payloads wrapped with `_…_`.\n * When Discord chunking splits the message, we close italics at the end of\n * each chunk and reopen at the start of the next so every chunk renders\n * consistently.\n */\nfunction rebalanceReasoningItalics(source: string, chunks: string[]): string[] {\n\tif (chunks.length <= 1) {\n\t\treturn chunks;\n\t}\n\n\tif (!isReasoningItalicsPayload(source)) {\n\t\treturn chunks;\n\t}\n\n\tconst adjusted = [...chunks];\n\tfor (let i = 0; i < adjusted.length; i++) {\n\t\tconst isLast = i === adjusted.length - 1;\n\t\tconst current = adjusted[i];\n\n\t\t// Ensure current chunk closes italics so Discord renders it italicized\n\t\tconst needsClosing = !current.trimEnd().endsWith(\"_\");\n\t\tif (needsClosing) {\n\t\t\tadjusted[i] = `${current}_`;\n\t\t}\n\n\t\tif (isLast) {\n\t\t\tbreak;\n\t\t}\n\n\t\t// Re-open italics on the next chunk if needed\n\t\tconst next = adjusted[i + 1];\n\t\tconst leadingWhitespaceLen = next.length - next.trimStart().length;\n\t\tconst leadingWhitespace = next.slice(0, leadingWhitespaceLen);\n\t\tconst nextBody = next.slice(leadingWhitespaceLen);\n\t\tif (!nextBody.startsWith(\"_\")) {\n\t\t\tadjusted[i + 1] = `${leadingWhitespace}_${nextBody}`;\n\t\t}\n\t}\n\n\treturn adjusted;\n}\n\n/**\n * Chunks outbound Discord text by both character count and (soft) line count,\n * while keeping fenced code blocks balanced across chunks.\n */\nexport function chunkDiscordText(\n\ttext: string,\n\topts: ChunkDiscordTextOpts = {},\n): string[] {\n\tconst requestedMaxChars = Math.max(\n\t\t1,\n\t\tMath.floor(opts.maxChars ?? DEFAULT_MAX_CHARS),\n\t);\n\tconst maxLines = Math.max(1, Math.floor(opts.maxLines ?? DEFAULT_MAX_LINES));\n\n\tconst body = text ?? \"\";\n\tif (!body) {\n\t\treturn [];\n\t}\n\n\tconst maxChars = isReasoningItalicsPayload(body)\n\t\t? Math.max(1, requestedMaxChars - 2)\n\t\t: requestedMaxChars;\n\n\tconst alreadyOk = body.length <= maxChars && countLines(body) <= maxLines;\n\tif (alreadyOk) {\n\t\treturn [body];\n\t}\n\n\tconst lines = body.split(\"\\n\");\n\tconst chunks: string[] = [];\n\n\tlet current = \"\";\n\tlet currentLines = 0;\n\tlet openFence: OpenFence | null = null;\n\n\tconst flush = () => {\n\t\tif (!current) {\n\t\t\treturn;\n\t\t}\n\t\tconst payload = closeFenceIfNeeded(current, openFence);\n\t\tif (payload.trim().length) {\n\t\t\tchunks.push(payload);\n\t\t}\n\t\tcurrent = \"\";\n\t\tcurrentLines = 0;\n\t\tif (openFence) {\n\t\t\tcurrent = openFence.openLine;\n\t\t\tcurrentLines = 1;\n\t\t}\n\t};\n\n\tfor (const originalLine of lines) {\n\t\tconst fenceInfo = parseFenceLine(originalLine);\n\t\tconst wasInsideFence = openFence !== null;\n\t\tlet nextOpenFence: OpenFence | null = openFence;\n\n\t\tif (fenceInfo) {\n\t\t\tif (!openFence) {\n\t\t\t\tnextOpenFence = fenceInfo;\n\t\t\t} else if (\n\t\t\t\topenFence.markerChar === fenceInfo.markerChar &&\n\t\t\t\tfenceInfo.markerLen >= openFence.markerLen\n\t\t\t) {\n\t\t\t\tnextOpenFence = null;\n\t\t\t}\n\t\t}\n\n\t\tconst reserveChars = nextOpenFence\n\t\t\t? closeFenceLine(nextOpenFence).length + 1\n\t\t\t: 0;\n\t\tconst reserveLines = nextOpenFence ? 1 : 0;\n\t\tconst effectiveMaxChars = maxChars - reserveChars;\n\t\tconst effectiveMaxLines = maxLines - reserveLines;\n\t\tconst charLimit = effectiveMaxChars > 0 ? effectiveMaxChars : maxChars;\n\t\tconst lineLimit = effectiveMaxLines > 0 ? effectiveMaxLines : maxLines;\n\t\tconst prefixLen = current.length > 0 ? current.length + 1 : 0;\n\t\tconst segmentLimit = Math.max(1, charLimit - prefixLen);\n\t\tconst segments = splitLongLine(originalLine, segmentLimit, {\n\t\t\tpreserveWhitespace: wasInsideFence,\n\t\t});\n\n\t\tfor (let segIndex = 0; segIndex < segments.length; segIndex++) {\n\t\t\tconst segment = segments[segIndex];\n\t\t\tconst isLineContinuation = segIndex > 0;\n\t\t\tconst delimiter = isLineContinuation\n\t\t\t\t? \"\"\n\t\t\t\t: current.length > 0\n\t\t\t\t\t? \"\\n\"\n\t\t\t\t\t: \"\";\n\t\t\tconst addition = `${delimiter}${segment}`;\n\t\t\tconst nextLen = current.length + addition.length;\n\t\t\tconst nextLines = currentLines + (isLineContinuation ? 0 : 1);\n\n\t\t\tconst wouldExceedChars = nextLen > charLimit;\n\t\t\tconst wouldExceedLines = nextLines > lineLimit;\n\n\t\t\tif ((wouldExceedChars || wouldExceedLines) && current.length > 0) {\n\t\t\t\tflush();\n\t\t\t}\n\n\t\t\tif (current.length > 0) {\n\t\t\t\tcurrent += addition;\n\t\t\t\tif (!isLineContinuation) {\n\t\t\t\t\tcurrentLines += 1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcurrent = segment;\n\t\t\t\tcurrentLines = 1;\n\t\t\t}\n\t\t}\n\n\t\topenFence = nextOpenFence;\n\t}\n\n\tif (current.length) {\n\t\tconst payload = closeFenceIfNeeded(current, openFence);\n\t\tif (payload.trim().length) {\n\t\t\tchunks.push(payload);\n\t\t}\n\t}\n\n\treturn rebalanceReasoningItalics(text, chunks);\n}\n\n/**\n * Chunks text by newlines first, then by character/line limits\n */\nfunction chunkMarkdownTextByNewline(text: string, maxChars: number): string[] {\n\tconst lines = text.split(\"\\n\");\n\tconst chunks: string[] = [];\n\tlet current = \"\";\n\n\tfor (const line of lines) {\n\t\tif (current.length + line.length + 1 > maxChars && current.length > 0) {\n\t\t\tchunks.push(current);\n\t\t\tcurrent = line;\n\t\t} else {\n\t\t\tcurrent = current.length > 0 ? `${current}\\n${line}` : line;\n\t\t}\n\t}\n\n\tif (current.length > 0) {\n\t\tchunks.push(current);\n\t}\n\n\treturn chunks;\n}\n\n/**\n * Chunks Discord text with configurable chunking mode\n */\nexport function chunkDiscordTextWithMode(\n\ttext: string,\n\topts: ChunkDiscordTextOpts = {},\n): string[] {\n\tconst chunkMode = opts.chunkMode ?? \"length\";\n\n\tif (chunkMode !== \"newline\") {\n\t\treturn chunkDiscordText(text, opts);\n\t}\n\n\tconst lineChunks = chunkMarkdownTextByNewline(\n\t\ttext,\n\t\tMath.max(1, Math.floor(opts.maxChars ?? DEFAULT_MAX_CHARS)),\n\t);\n\n\tconst chunks: string[] = [];\n\tfor (const line of lineChunks) {\n\t\tconst nested = chunkDiscordText(line, opts);\n\t\tif (!nested.length && line) {\n\t\t\tchunks.push(line);\n\t\t\tcontinue;\n\t\t}\n\t\tchunks.push(...nested);\n\t}\n\n\treturn chunks;\n}\n\n/**\n * Resolves the system location string for logging/display\n */\nexport function resolveDiscordSystemLocation(params: {\n\tisDirectMessage: boolean;\n\tisGroupDm: boolean;\n\tguild?: Guild | null;\n\tchannelName: string;\n}): string {\n\tconst { isDirectMessage, isGroupDm, guild, channelName } = params;\n\n\tif (isDirectMessage) {\n\t\treturn \"DM\";\n\t}\n\n\tif (isGroupDm) {\n\t\treturn `Group DM #${channelName}`;\n\t}\n\n\treturn guild?.name ? `${guild.name} #${channelName}` : `#${channelName}`;\n}\n\n/**\n * Formats a Discord reaction emoji for display\n */\nexport function formatDiscordReactionEmoji(emoji: {\n\tid?: string | null;\n\tname?: string | null;\n}): string {\n\tif (emoji.id && emoji.name) {\n\t\treturn `${emoji.name}:${emoji.id}`;\n\t}\n\treturn emoji.name ?? \"emoji\";\n}\n\n/**\n * Formats a Discord reaction emoji from a MessageReaction\n */\nexport function formatMessageReactionEmoji(reaction: MessageReaction): string {\n\tconst emoji = reaction.emoji;\n\tif (emoji.id && emoji.name) {\n\t\treturn `<:${emoji.name}:${emoji.id}>`;\n\t}\n\treturn emoji.name ?? \"emoji\";\n}\n\n/**\n * Formats a Discord user mention\n */\nexport function formatDiscordUserMention(userId: string): string {\n\treturn `<@${userId}>`;\n}\n\n/**\n * Formats a Discord channel mention\n */\nexport function formatDiscordChannelMention(channelId: string): string {\n\treturn `<#${channelId}>`;\n}\n\n/**\n * Formats a Discord role mention\n */\nexport function formatDiscordRoleMention(roleId: string): string {\n\treturn `<@&${roleId}>`;\n}\n\n/**\n * Extracts user ID from a mention string\n */\nexport function extractUserIdFromMention(mention: string): string | null {\n\tconst match = mention.match(/^<@!?(\\d+)>$/);\n\treturn match ? match[1] : null;\n}\n\n/**\n * Extracts channel ID from a mention string\n */\nexport function extractChannelIdFromMention(mention: string): string | null {\n\tconst match = mention.match(/^<#(\\d+)>$/);\n\treturn match ? match[1] : null;\n}\n\n/**\n * Extracts role ID from a mention string\n */\nexport function extractRoleIdFromMention(mention: string): string | null {\n\tconst match = mention.match(/^<@&(\\d+)>$/);\n\treturn match ? match[1] : null;\n}\n\n/**\n * Resolves a timestamp string to milliseconds\n */\nexport function resolveTimestampMs(\n\ttimestamp?: string | null,\n): number | undefined {\n\tif (!timestamp) {\n\t\treturn undefined;\n\t}\n\tconst parsed = Date.parse(timestamp);\n\treturn Number.isNaN(parsed) ? undefined : parsed;\n}\n\n/**\n * Formats a timestamp for Discord (Discord timestamp format)\n */\nexport function formatDiscordTimestamp(\n\ttimestamp: Date | number,\n\tformat: \"t\" | \"T\" | \"d\" | \"D\" | \"f\" | \"F\" | \"R\" = \"f\",\n): string {\n\tconst unix = Math.floor(\n\t\t(typeof timestamp === \"number\" ? timestamp : timestamp.getTime()) / 1000,\n\t);\n\treturn `<t:${unix}:${format}>`;\n}\n\n/**\n * Strips Discord formatting from text\n */\nexport function stripDiscordFormatting(text: string): string {\n\treturn text\n\t\t.replace(/\\*\\*(.+?)\\*\\*/g, \"$1\") // Bold\n\t\t.replace(/\\*(.+?)\\*/g, \"$1\") // Italic\n\t\t.replace(/__(.+?)__/g, \"$1\") // Underline\n\t\t.replace(/~~(.+?)~~/g, \"$1\") // Strikethrough\n\t\t.replace(/`{3}[\\s\\S]*?`{3}/g, \"\") // Code blocks\n\t\t.replace(/`(.+?)`/g, \"$1\") // Inline code\n\t\t.replace(/\\|\\|(.+?)\\|\\|/g, \"$1\") // Spoilers\n\t\t.replace(/<@!?\\d+>/g, \"\") // User mentions\n\t\t.replace(/<#\\d+>/g, \"\") // Channel mentions\n\t\t.replace(/<@&\\d+>/g, \"\") // Role mentions\n\t\t.replace(/<a?:\\w+:\\d+>/g, \"\") // Custom emojis\n\t\t.trim();\n}\n\n/**\n * Escapes special Discord markdown characters\n */\nexport function escapeDiscordMarkdown(text: string): string {\n\treturn text.replace(/([*_`~|\\\\])/g, \"\\\\$1\");\n}\n\n/**\n * Truncates text to a maximum length with an ellipsis\n */\nexport function truncateText(\n\ttext: string,\n\tmaxLength: number,\n\tellipsis = \"…\",\n): string {\n\tif (text.length <= maxLength) {\n\t\treturn text;\n\t}\n\treturn text.slice(0, maxLength - ellipsis.length) + ellipsis;\n}\n\n/**\n * Truncates text at a UTF-16 boundary safely\n */\nexport function truncateUtf16Safe(\n\ttext: string,\n\tmaxLength: number,\n\tellipsis = \"…\",\n): string {\n\tif (text.length <= maxLength) {\n\t\treturn text;\n\t}\n\n\tconst targetLength = maxLength - ellipsis.length;\n\tif (targetLength <= 0) {\n\t\treturn ellipsis.slice(0, maxLength);\n\t}\n\n\t// Check if we're in the middle of a surrogate pair\n\tlet truncateAt = targetLength;\n\tconst charAtTruncate = text.charCodeAt(truncateAt);\n\n\t// If we're at a low surrogate, back up one\n\tif (charAtTruncate >= 0xdc00 && charAtTruncate <= 0xdfff) {\n\t\ttruncateAt--;\n\t}\n\n\treturn text.slice(0, truncateAt) + ellipsis;\n}\n\n/**\n * Checks if a message mentions a specific user\n */\nexport function messageContainsMention(text: string, userId: string): boolean {\n\tconst mentionPattern = new RegExp(`<@!?${userId}>`);\n\treturn mentionPattern.test(text);\n}\n\n/**\n * Extracts all user mentions from a message\n */\nexport function extractAllUserMentions(text: string): string[] {\n\tconst matches = text.matchAll(/<@!?(\\d+)>/g);\n\treturn Array.from(matches, (m) => m[1]);\n}\n\n/**\n * Extracts all channel mentions from a message\n */\nexport function extractAllChannelMentions(text: string): string[] {\n\tconst matches = text.matchAll(/<#(\\d+)>/g);\n\treturn Array.from(matches, (m) => m[1]);\n}\n\n/**\n * Extracts all role mentions from a message\n */\nexport function extractAllRoleMentions(text: string): string[] {\n\tconst matches = text.matchAll(/<@&(\\d+)>/g);\n\treturn Array.from(matches, (m) => m[1]);\n}\n\n/**\n * Sanitizes a thread name for Discord (max 100 chars, no invalid chars)\n */\nexport function sanitizeThreadName(name: string): string {\n\tconst sanitized = name\n\t\t.replace(/[\\n\\r]/g, \" \")\n\t\t.replace(/\\s+/g, \" \")\n\t\t.trim();\n\n\treturn truncateUtf16Safe(sanitized, 100, \"\");\n}\n\n/**\n * Builds a message link URL\n */\nexport function buildMessageLink(\n\tguildId: string,\n\tchannelId: string,\n\tmessageId: string,\n): string {\n\treturn `https://discord.com/channels/${guildId}/${channelId}/${messageId}`;\n}\n\n/**\n * Builds a channel link URL\n */\nexport function buildChannelLink(guildId: string, channelId: string): string {\n\treturn `https://discord.com/channels/${guildId}/${channelId}`;\n}\n\n/**\n * Parses a Discord message link URL\n */\nexport function parseMessageLink(\n\turl: string,\n): { guildId: string; channelId: string; messageId: string } | null {\n\tconst match = url.match(\n\t\t/^https?:\\/\\/(?:www\\.)?discord\\.com\\/channels\\/(\\d+)\\/(\\d+)\\/(\\d+)$/,\n\t);\n\n\tif (!match) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tguildId: match[1],\n\t\tchannelId: match[2],\n\t\tmessageId: match[3],\n\t};\n}\n",
|
|
127
|
+
"import mod from \"./v10.js\";\n\nexport default mod;\nexport const APIApplicationCommandPermissionsConstant = mod.APIApplicationCommandPermissionsConstant;\nexport const APIVersion = mod.APIVersion;\nexport const ActivityFlags = mod.ActivityFlags;\nexport const ActivityPlatform = mod.ActivityPlatform;\nexport const ActivityType = mod.ActivityType;\nexport const AllowedMentionsTypes = mod.AllowedMentionsTypes;\nexport const ApplicationCommandOptionType = mod.ApplicationCommandOptionType;\nexport const ApplicationCommandPermissionType = mod.ApplicationCommandPermissionType;\nexport const ApplicationCommandType = mod.ApplicationCommandType;\nexport const ApplicationFlags = mod.ApplicationFlags;\nexport const ApplicationIntegrationType = mod.ApplicationIntegrationType;\nexport const ApplicationRoleConnectionMetadataType = mod.ApplicationRoleConnectionMetadataType;\nexport const ApplicationWebhookEventStatus = mod.ApplicationWebhookEventStatus;\nexport const ApplicationWebhookEventType = mod.ApplicationWebhookEventType;\nexport const ApplicationWebhookType = mod.ApplicationWebhookType;\nexport const AttachmentFlags = mod.AttachmentFlags;\nexport const AuditLogEvent = mod.AuditLogEvent;\nexport const AuditLogOptionsType = mod.AuditLogOptionsType;\nexport const AutoModerationActionType = mod.AutoModerationActionType;\nexport const AutoModerationRuleEventType = mod.AutoModerationRuleEventType;\nexport const AutoModerationRuleKeywordPresetType = mod.AutoModerationRuleKeywordPresetType;\nexport const AutoModerationRuleTriggerType = mod.AutoModerationRuleTriggerType;\nexport const ButtonStyle = mod.ButtonStyle;\nexport const CDNRoutes = mod.CDNRoutes;\nexport const ChannelFlags = mod.ChannelFlags;\nexport const ChannelType = mod.ChannelType;\nexport const ComponentType = mod.ComponentType;\nexport const ConnectionService = mod.ConnectionService;\nexport const ConnectionVisibility = mod.ConnectionVisibility;\nexport const EmbedType = mod.EmbedType;\nexport const EntitlementOwnerType = mod.EntitlementOwnerType;\nexport const EntitlementType = mod.EntitlementType;\nexport const EntryPointCommandHandlerType = mod.EntryPointCommandHandlerType;\nexport const FormattingPatterns = mod.FormattingPatterns;\nexport const ForumLayoutType = mod.ForumLayoutType;\nexport const GatewayCloseCodes = mod.GatewayCloseCodes;\nexport const GatewayDispatchEvents = mod.GatewayDispatchEvents;\nexport const GatewayIntentBits = mod.GatewayIntentBits;\nexport const GatewayOpcodes = mod.GatewayOpcodes;\nexport const GatewayVersion = mod.GatewayVersion;\nexport const GuildDefaultMessageNotifications = mod.GuildDefaultMessageNotifications;\nexport const GuildExplicitContentFilter = mod.GuildExplicitContentFilter;\nexport const GuildFeature = mod.GuildFeature;\nexport const GuildHubType = mod.GuildHubType;\nexport const GuildMFALevel = mod.GuildMFALevel;\nexport const GuildMemberFlags = mod.GuildMemberFlags;\nexport const GuildNSFWLevel = mod.GuildNSFWLevel;\nexport const GuildOnboardingMode = mod.GuildOnboardingMode;\nexport const GuildOnboardingPromptType = mod.GuildOnboardingPromptType;\nexport const GuildPremiumTier = mod.GuildPremiumTier;\nexport const GuildScheduledEventEntityType = mod.GuildScheduledEventEntityType;\nexport const GuildScheduledEventPrivacyLevel = mod.GuildScheduledEventPrivacyLevel;\nexport const GuildScheduledEventRecurrenceRuleFrequency = mod.GuildScheduledEventRecurrenceRuleFrequency;\nexport const GuildScheduledEventRecurrenceRuleMonth = mod.GuildScheduledEventRecurrenceRuleMonth;\nexport const GuildScheduledEventRecurrenceRuleWeekday = mod.GuildScheduledEventRecurrenceRuleWeekday;\nexport const GuildScheduledEventStatus = mod.GuildScheduledEventStatus;\nexport const GuildSystemChannelFlags = mod.GuildSystemChannelFlags;\nexport const GuildVerificationLevel = mod.GuildVerificationLevel;\nexport const GuildWidgetStyle = mod.GuildWidgetStyle;\nexport const ImageFormat = mod.ImageFormat;\nexport const IntegrationExpireBehavior = mod.IntegrationExpireBehavior;\nexport const InteractionContextType = mod.InteractionContextType;\nexport const InteractionResponseType = mod.InteractionResponseType;\nexport const InteractionType = mod.InteractionType;\nexport const InviteTargetType = mod.InviteTargetType;\nexport const InviteType = mod.InviteType;\nexport const Locale = mod.Locale;\nexport const MembershipScreeningFieldType = mod.MembershipScreeningFieldType;\nexport const MessageActivityType = mod.MessageActivityType;\nexport const MessageFlags = mod.MessageFlags;\nexport const MessageReferenceType = mod.MessageReferenceType;\nexport const MessageType = mod.MessageType;\nexport const OAuth2Routes = mod.OAuth2Routes;\nexport const OAuth2Scopes = mod.OAuth2Scopes;\nexport const OverwriteType = mod.OverwriteType;\nexport const PermissionFlagsBits = mod.PermissionFlagsBits;\nexport const PollLayoutType = mod.PollLayoutType;\nexport const PresenceUpdateStatus = mod.PresenceUpdateStatus;\nexport const RESTJSONErrorCodes = mod.RESTJSONErrorCodes;\nexport const RPCCloseEventCodes = mod.RPCCloseEventCodes;\nexport const RPCCommands = mod.RPCCommands;\nexport const RPCDeviceType = mod.RPCDeviceType;\nexport const RPCErrorCodes = mod.RPCErrorCodes;\nexport const RPCEvents = mod.RPCEvents;\nexport const RPCVersion = mod.RPCVersion;\nexport const RPCVoiceSettingsModeType = mod.RPCVoiceSettingsModeType;\nexport const RPCVoiceShortcutKeyComboKeyType = mod.RPCVoiceShortcutKeyComboKeyType;\nexport const ReactionType = mod.ReactionType;\nexport const RelationshipType = mod.RelationshipType;\nexport const RoleFlags = mod.RoleFlags;\nexport const RouteBases = mod.RouteBases;\nexport const Routes = mod.Routes;\nexport const SKUFlags = mod.SKUFlags;\nexport const SKUType = mod.SKUType;\nexport const SelectMenuDefaultValueType = mod.SelectMenuDefaultValueType;\nexport const SortOrderType = mod.SortOrderType;\nexport const StageInstancePrivacyLevel = mod.StageInstancePrivacyLevel;\nexport const StickerFormatType = mod.StickerFormatType;\nexport const StickerPackApplicationId = mod.StickerPackApplicationId;\nexport const StickerType = mod.StickerType;\nexport const SubscriptionStatus = mod.SubscriptionStatus;\nexport const TeamMemberMembershipState = mod.TeamMemberMembershipState;\nexport const TeamMemberRole = mod.TeamMemberRole;\nexport const TextInputStyle = mod.TextInputStyle;\nexport const ThreadAutoArchiveDuration = mod.ThreadAutoArchiveDuration;\nexport const ThreadMemberFlags = mod.ThreadMemberFlags;\nexport const UserFlags = mod.UserFlags;\nexport const UserPremiumType = mod.UserPremiumType;\nexport const Utils = mod.Utils;\nexport const VideoQualityMode = mod.VideoQualityMode;\nexport const VoiceChannelEffectSendAnimationType = mod.VoiceChannelEffectSendAnimationType;\nexport const VoiceConnectionStates = mod.VoiceConnectionStates;\nexport const WebhookType = mod.WebhookType;\nexport const urlSafeCharacters = mod.urlSafeCharacters;\n",
|
|
128
|
+
"import {\n\ttype APIApplicationCommandOption,\n\tApplicationCommandOptionType,\n\tButtonStyle,\n\ttype RESTPostAPIChatInputApplicationCommandsJSONBody,\n} from \"discord-api-types/v10\";\n\n/**\n * Command argument definition\n */\nexport interface CommandArgDefinition {\n\tname: string;\n\tdescription: string;\n\ttype: \"string\" | \"number\" | \"boolean\";\n\trequired?: boolean;\n\tchoices?: Array<{ label: string; value: string }>;\n}\n\n/**\n * Native command specification\n */\nexport interface NativeCommandSpec {\n\tname: string;\n\tdescription: string;\n\tacceptsArgs?: boolean;\n\targs?: CommandArgDefinition[];\n\tephemeralDefault?: boolean;\n}\n\n/**\n * Command argument values\n */\nexport type CommandArgValues = Record<string, string | number | boolean>;\n\n/**\n * Parsed command arguments\n */\nexport interface CommandArgs {\n\tvalues: CommandArgValues;\n\traw?: string;\n}\n\n/**\n * Result of building command options\n */\nexport interface BuiltCommandOption {\n\tname: string;\n\tdescription: string;\n\ttype: ApplicationCommandOptionType;\n\trequired?: boolean;\n\tchoices?: Array<{ name: string; value: string | number }>;\n}\n\n/**\n * Button specification for argument menus\n */\nexport interface CommandArgButton {\n\tlabel: string;\n\tcustomId: string;\n\tstyle: ButtonStyle;\n}\n\n/**\n * Row of buttons for argument menus\n */\nexport interface CommandArgButtonRow {\n\tbuttons: CommandArgButton[];\n}\n\n/**\n * Argument menu specification\n */\nexport interface CommandArgMenu {\n\tcontent: string;\n\trows: CommandArgButtonRow[];\n}\n\n/**\n * Key for command argument custom IDs\n */\nexport const COMMAND_ARG_CUSTOM_ID_KEY = \"cmdarg\";\n\n/**\n * Builds Discord command options from argument definitions\n */\nexport function buildDiscordCommandOptions(\n\targs?: CommandArgDefinition[],\n): BuiltCommandOption[] | undefined {\n\tif (!args || args.length === 0) {\n\t\treturn undefined;\n\t}\n\n\treturn args.map((arg) => {\n\t\tconst required = arg.required ?? false;\n\n\t\tif (arg.type === \"number\") {\n\t\t\treturn {\n\t\t\t\tname: arg.name,\n\t\t\t\tdescription: arg.description,\n\t\t\t\ttype: ApplicationCommandOptionType.Number,\n\t\t\t\trequired,\n\t\t\t};\n\t\t}\n\n\t\tif (arg.type === \"boolean\") {\n\t\t\treturn {\n\t\t\t\tname: arg.name,\n\t\t\t\tdescription: arg.description,\n\t\t\t\ttype: ApplicationCommandOptionType.Boolean,\n\t\t\t\trequired,\n\t\t\t};\n\t\t}\n\n\t\tconst choices =\n\t\t\targ.choices && arg.choices.length > 0 && arg.choices.length <= 25\n\t\t\t\t? arg.choices.map((choice) => ({\n\t\t\t\t\t\tname: choice.label,\n\t\t\t\t\t\tvalue: choice.value,\n\t\t\t\t\t}))\n\t\t\t\t: undefined;\n\n\t\treturn {\n\t\t\tname: arg.name,\n\t\t\tdescription: arg.description,\n\t\t\ttype: ApplicationCommandOptionType.String,\n\t\t\trequired,\n\t\t\tchoices,\n\t\t};\n\t});\n}\n\n/**\n * Builds a complete Discord slash command JSON body\n */\nexport function buildDiscordSlashCommand(\n\tspec: NativeCommandSpec,\n): RESTPostAPIChatInputApplicationCommandsJSONBody {\n\tconst options = buildDiscordCommandOptions(spec.args);\n\n\tconst commandOptions: APIApplicationCommandOption[] | undefined =\n\t\toptions?.map(\n\t\t\t(opt) =>\n\t\t\t\t({\n\t\t\t\t\tname: opt.name,\n\t\t\t\t\tdescription: opt.description,\n\t\t\t\t\ttype: opt.type,\n\t\t\t\t\trequired: opt.required,\n\t\t\t\t\tchoices: opt.choices,\n\t\t\t\t}) as APIApplicationCommandOption,\n\t\t) ??\n\t\t(spec.acceptsArgs\n\t\t\t? [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"input\",\n\t\t\t\t\t\tdescription: \"Command input\",\n\t\t\t\t\t\ttype: ApplicationCommandOptionType.String,\n\t\t\t\t\t\trequired: false,\n\t\t\t\t\t} as APIApplicationCommandOption,\n\t\t\t\t]\n\t\t\t: undefined);\n\n\treturn {\n\t\tname: spec.name,\n\t\tdescription: spec.description,\n\t\toptions: commandOptions,\n\t};\n}\n\n/**\n * Encodes a command argument value for use in custom IDs\n */\nexport function encodeCommandArgValue(value: string): string {\n\treturn encodeURIComponent(value);\n}\n\n/**\n * Decodes a command argument value from a custom ID\n */\nexport function decodeCommandArgValue(value: string): string {\n\ttry {\n\t\treturn decodeURIComponent(value);\n\t} catch {\n\t\treturn value;\n\t}\n}\n\n/**\n * Builds a custom ID for a command argument button\n */\nexport function buildCommandArgCustomId(params: {\n\tcommand: string;\n\targ: string;\n\tvalue: string;\n\tuserId: string;\n}): string {\n\treturn [\n\t\t`${COMMAND_ARG_CUSTOM_ID_KEY}:command=${encodeCommandArgValue(params.command)}`,\n\t\t`arg=${encodeCommandArgValue(params.arg)}`,\n\t\t`value=${encodeCommandArgValue(params.value)}`,\n\t\t`user=${encodeCommandArgValue(params.userId)}`,\n\t].join(\";\");\n}\n\n/**\n * Parses command argument data from a custom ID\n */\nexport function parseCommandArgCustomId(\n\tcustomId: string,\n): { command: string; arg: string; value: string; userId: string } | null {\n\tif (!customId.startsWith(COMMAND_ARG_CUSTOM_ID_KEY)) {\n\t\treturn null;\n\t}\n\n\tconst parts = customId.split(\";\");\n\tconst data: Record<string, string> = {};\n\n\tfor (const part of parts) {\n\t\tconst [key, value] = part.split(\"=\");\n\t\tif (key && value) {\n\t\t\t// Handle the first part which has the prefix\n\t\t\tconst cleanKey = key.replace(`${COMMAND_ARG_CUSTOM_ID_KEY}:`, \"\");\n\t\t\tdata[cleanKey] = decodeCommandArgValue(value);\n\t\t}\n\t}\n\n\tif (!data.command || !data.arg || !data.value || !data.user) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tcommand: data.command,\n\t\targ: data.arg,\n\t\tvalue: data.value,\n\t\tuserId: data.user,\n\t};\n}\n\n/**\n * Chunks an array into smaller arrays of a specified size\n */\nfunction chunkArray<T>(items: T[], size: number): T[][] {\n\tif (size <= 0) {\n\t\treturn [items];\n\t}\n\tconst rows: T[][] = [];\n\tfor (let i = 0; i < items.length; i += size) {\n\t\trows.push(items.slice(i, i + size));\n\t}\n\treturn rows;\n}\n\n/**\n * Builds an argument menu with buttons for command selection\n */\nexport function buildCommandArgMenu(params: {\n\tcommandName: string;\n\targ: CommandArgDefinition;\n\tchoices: Array<{ value: string; label: string }>;\n\tuserId: string;\n\ttitle?: string;\n\tbuttonsPerRow?: number;\n}): CommandArgMenu {\n\tconst {\n\t\tcommandName,\n\t\targ,\n\t\tchoices,\n\t\tuserId,\n\t\ttitle,\n\t\tbuttonsPerRow = 4,\n\t} = params;\n\n\tconst rows = chunkArray(choices.slice(0, 20), buttonsPerRow).map(\n\t\t(rowChoices) => ({\n\t\t\tbuttons: rowChoices.map((choice) => ({\n\t\t\t\tlabel: choice.label.slice(0, 80),\n\t\t\t\tcustomId: buildCommandArgCustomId({\n\t\t\t\t\tcommand: commandName,\n\t\t\t\t\targ: arg.name,\n\t\t\t\t\tvalue: choice.value,\n\t\t\t\t\tuserId,\n\t\t\t\t}),\n\t\t\t\tstyle: ButtonStyle.Secondary,\n\t\t\t})),\n\t\t}),\n\t);\n\n\tconst content =\n\t\ttitle ?? `Choose ${arg.description || arg.name} for /${commandName}.`;\n\n\treturn { content, rows };\n}\n\n/**\n * Checks if an error is a Discord \"Unknown Interaction\" error\n */\nexport function isUnknownInteractionError(error: unknown): boolean {\n\tif (!error || typeof error !== \"object\") {\n\t\treturn false;\n\t}\n\n\tconst err = error as {\n\t\tcode?: number;\n\t\tstatus?: number;\n\t\tmessage?: string;\n\t\trawError?: { code?: number; message?: string };\n\t};\n\n\t// Discord error code 10062 = Unknown Interaction\n\tif (err.code === 10062 || err.rawError?.code === 10062) {\n\t\treturn true;\n\t}\n\n\tif (err.status === 404 && /Unknown interaction/i.test(err.message ?? \"\")) {\n\t\treturn true;\n\t}\n\n\tif (/Unknown interaction/i.test(err.rawError?.message ?? \"\")) {\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n/**\n * Safely executes a Discord interaction call, catching expired interaction errors\n */\nexport async function safeInteractionCall<T>(\n\tfn: () => Promise<T>,\n\tonExpired?: () => void,\n): Promise<T | null> {\n\ttry {\n\t\treturn await fn();\n\t} catch (error) {\n\t\tif (isUnknownInteractionError(error)) {\n\t\t\tonExpired?.();\n\t\t\treturn null;\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/**\n * Creates command arguments from a single value\n */\nexport function createCommandArgs(\n\targName: string,\n\tvalue: string | number | boolean,\n): CommandArgs {\n\treturn {\n\t\tvalues: { [argName]: value },\n\t};\n}\n\n/**\n * Serializes command arguments to a string\n */\nexport function serializeCommandArgs(args?: CommandArgs): string {\n\tif (!args?.values) {\n\t\treturn \"\";\n\t}\n\n\treturn Object.entries(args.values)\n\t\t.map(([key, value]) => `${key}=${String(value)}`)\n\t\t.join(\" \");\n}\n\n/**\n * Builds the full command text from arguments\n */\nexport function buildCommandText(\n\tcommandName: string,\n\targs?: CommandArgs,\n): string {\n\tconst argsText = serializeCommandArgs(args);\n\treturn argsText ? `/${commandName} ${argsText}` : `/${commandName}`;\n}\n"
|
|
129
|
+
],
|
|
130
|
+
"mappings": "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",
|
|
131
|
+
"debugId": "B20F70AAC326598264756E2164756E21",
|
|
132
|
+
"names": []
|
|
133
|
+
}
|