Discord: add fetch message action
This commit is contained in:
@@ -12,6 +12,7 @@ Use `discord` to manage messages, reactions, threads, polls, and moderation. You
|
|||||||
## Inputs to collect
|
## Inputs to collect
|
||||||
|
|
||||||
- For reactions: `channelId`, `messageId`, and an `emoji`.
|
- For reactions: `channelId`, `messageId`, and an `emoji`.
|
||||||
|
- For fetchMessage: `guildId`, `channelId`, `messageId`, or a `messageLink` like `https://discord.com/channels/<guildId>/<channelId>/<messageId>`.
|
||||||
- For stickers/polls/sendMessage: a `to` target (`channel:<id>` or `user:<id>`). Optional `content` text.
|
- For stickers/polls/sendMessage: a `to` target (`channel:<id>` or `user:<id>`). Optional `content` text.
|
||||||
- Polls also need a `question` plus 2–10 `answers`.
|
- Polls also need a `question` plus 2–10 `answers`.
|
||||||
- For media: `mediaUrl` with `file:///path` for local files or `https://...` for remote.
|
- For media: `mediaUrl` with `file:///path` for local files or `https://...` for remote.
|
||||||
@@ -21,6 +22,7 @@ Use `discord` to manage messages, reactions, threads, polls, and moderation. You
|
|||||||
Message context lines include `discord message id` and `channel` fields you can reuse directly.
|
Message context lines include `discord message id` and `channel` fields you can reuse directly.
|
||||||
|
|
||||||
**Note:** `sendMessage` uses `to: "channel:<id>"` format, not `channelId`. Other actions like `react`, `readMessages`, `editMessage` use `channelId` directly.
|
**Note:** `sendMessage` uses `to: "channel:<id>"` format, not `channelId`. Other actions like `react`, `readMessages`, `editMessage` use `channelId` directly.
|
||||||
|
**Note:** `fetchMessage` accepts message IDs or full links like `https://discord.com/channels/<guildId>/<channelId>/<messageId>`.
|
||||||
|
|
||||||
## Actions
|
## Actions
|
||||||
|
|
||||||
@@ -144,6 +146,24 @@ Use `discord.actions.*` to disable action groups:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Fetch a single message
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "fetchMessage",
|
||||||
|
"guildId": "999",
|
||||||
|
"channelId": "123",
|
||||||
|
"messageId": "456"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "fetchMessage",
|
||||||
|
"messageLink": "https://discord.com/channels/999/123/456"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Send/edit/delete a message
|
### Send/edit/delete a message
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
deleteMessageDiscord,
|
deleteMessageDiscord,
|
||||||
editMessageDiscord,
|
editMessageDiscord,
|
||||||
fetchChannelPermissionsDiscord,
|
fetchChannelPermissionsDiscord,
|
||||||
|
fetchMessageDiscord,
|
||||||
fetchReactionsDiscord,
|
fetchReactionsDiscord,
|
||||||
listPinsDiscord,
|
listPinsDiscord,
|
||||||
listThreadsDiscord,
|
listThreadsDiscord,
|
||||||
@@ -53,6 +54,23 @@ function formatDiscordTimestamp(ts?: string | null): string | undefined {
|
|||||||
return `${yyyy}-${mm}-${dd}T${hh}:${min}${sign}${offsetH}:${offsetM}${tzSuffix}`;
|
return `${yyyy}-${mm}-${dd}T${hh}:${min}${sign}${offsetH}:${offsetM}${tzSuffix}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseDiscordMessageLink(link: string) {
|
||||||
|
const normalized = link.trim();
|
||||||
|
const match = normalized.match(
|
||||||
|
/^(?:https?:\/\/)?(?:ptb\.|canary\.)?discord(?:app)?\.com\/channels\/(\d+)\/(\d+)\/(\d+)(?:\/?|\?.*)$/i,
|
||||||
|
);
|
||||||
|
if (!match) {
|
||||||
|
throw new Error(
|
||||||
|
"Invalid Discord message link. Expected https://discord.com/channels/<guildId>/<channelId>/<messageId>.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
guildId: match[1],
|
||||||
|
channelId: match[2],
|
||||||
|
messageId: match[3],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export async function handleDiscordMessagingAction(
|
export async function handleDiscordMessagingAction(
|
||||||
action: string,
|
action: string,
|
||||||
params: Record<string, unknown>,
|
params: Record<string, unknown>,
|
||||||
@@ -157,6 +175,28 @@ export async function handleDiscordMessagingAction(
|
|||||||
const permissions = await fetchChannelPermissionsDiscord(channelId);
|
const permissions = await fetchChannelPermissionsDiscord(channelId);
|
||||||
return jsonResult({ ok: true, permissions });
|
return jsonResult({ ok: true, permissions });
|
||||||
}
|
}
|
||||||
|
case "fetchMessage": {
|
||||||
|
if (!isActionEnabled("messages")) {
|
||||||
|
throw new Error("Discord message reads are disabled.");
|
||||||
|
}
|
||||||
|
const messageLink = readStringParam(params, "messageLink");
|
||||||
|
let guildId = readStringParam(params, "guildId");
|
||||||
|
let channelId = readStringParam(params, "channelId");
|
||||||
|
let messageId = readStringParam(params, "messageId");
|
||||||
|
if (messageLink) {
|
||||||
|
const parsed = parseDiscordMessageLink(messageLink);
|
||||||
|
guildId = parsed.guildId;
|
||||||
|
channelId = parsed.channelId;
|
||||||
|
messageId = parsed.messageId;
|
||||||
|
}
|
||||||
|
if (!guildId || !channelId || !messageId) {
|
||||||
|
throw new Error(
|
||||||
|
"Discord message fetch requires guildId, channelId, and messageId (or a valid messageLink).",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const message = await fetchMessageDiscord(channelId, messageId);
|
||||||
|
return jsonResult({ ok: true, message, guildId, channelId, messageId });
|
||||||
|
}
|
||||||
case "readMessages": {
|
case "readMessages": {
|
||||||
if (!isActionEnabled("messages")) {
|
if (!isActionEnabled("messages")) {
|
||||||
throw new Error("Discord message reads are disabled.");
|
throw new Error("Discord message reads are disabled.");
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ const messagingActions = new Set([
|
|||||||
"sticker",
|
"sticker",
|
||||||
"poll",
|
"poll",
|
||||||
"permissions",
|
"permissions",
|
||||||
|
"fetchMessage",
|
||||||
"readMessages",
|
"readMessages",
|
||||||
"sendMessage",
|
"sendMessage",
|
||||||
"editMessage",
|
"editMessage",
|
||||||
|
|||||||
@@ -35,6 +35,21 @@ export const DiscordToolSchema = Type.Union([
|
|||||||
action: Type.Literal("permissions"),
|
action: Type.Literal("permissions"),
|
||||||
channelId: Type.String(),
|
channelId: Type.String(),
|
||||||
}),
|
}),
|
||||||
|
Type.Union([
|
||||||
|
Type.Object({
|
||||||
|
action: Type.Literal("fetchMessage"),
|
||||||
|
messageLink: Type.String(),
|
||||||
|
guildId: Type.Optional(Type.String()),
|
||||||
|
channelId: Type.Optional(Type.String()),
|
||||||
|
messageId: Type.Optional(Type.String()),
|
||||||
|
}),
|
||||||
|
Type.Object({
|
||||||
|
action: Type.Literal("fetchMessage"),
|
||||||
|
guildId: Type.String(),
|
||||||
|
channelId: Type.String(),
|
||||||
|
messageId: Type.String(),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
Type.Object({
|
Type.Object({
|
||||||
action: Type.Literal("readMessages"),
|
action: Type.Literal("readMessages"),
|
||||||
channelId: Type.String(),
|
channelId: Type.String(),
|
||||||
|
|||||||
@@ -903,6 +903,17 @@ export async function readMessagesDiscord(
|
|||||||
)) as APIMessage[];
|
)) as APIMessage[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function fetchMessageDiscord(
|
||||||
|
channelId: string,
|
||||||
|
messageId: string,
|
||||||
|
opts: DiscordReactOpts = {},
|
||||||
|
): Promise<APIMessage> {
|
||||||
|
const rest = resolveDiscordRest(opts);
|
||||||
|
return (await rest.get(
|
||||||
|
Routes.channelMessage(channelId, messageId),
|
||||||
|
)) as APIMessage;
|
||||||
|
}
|
||||||
|
|
||||||
export async function editMessageDiscord(
|
export async function editMessageDiscord(
|
||||||
channelId: string,
|
channelId: string,
|
||||||
messageId: string,
|
messageId: string,
|
||||||
|
|||||||
Reference in New Issue
Block a user