Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ Important notes:
### Messages and Reactions

- `discord_search_messages`: Search messages in a server
- `discord_read_messages`: Read channel messages
- `discord_read_messages`: Read channel messages (supports `before`, `after`, `around` params — accepts snowflake IDs or ISO 8601 dates like `"2025-03-01T00:00:00Z"`)
- `discord_edit_message`: Edit a bot-authored message
- `discord_add_reaction`: Add a reaction to a message
- `discord_add_multiple_reactions`: Add multiple reactions to a message
Expand Down
12 changes: 8 additions & 4 deletions src/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,14 @@ export const DeleteChannelSchema = z.object({

export const ReadMessagesSchema = z.object({
channelId: z.string({ description: "The ID of the channel to read messages from." }),
limit: z.number({ description: "How many recent messages to fetch (1-100)." }).min(1).max(100).optional().default(50)
}, {
description: "Read recent messages from a specified channel."
});
limit: z.number({ description: "How many recent messages to fetch (1-100)." }).min(1).max(100).optional().default(50),
before: z.string({ description: "Snowflake ID or ISO 8601 date (e.g. '2025-03-01T00:00:00Z'). Get messages before this point." }).optional(),
after: z.string({ description: "Snowflake ID or ISO 8601 date (e.g. '2025-03-01T00:00:00Z'). Get messages after this point." }).optional(),
around: z.string({ description: "Snowflake ID or ISO 8601 date (e.g. '2025-03-01T00:00:00Z'). Get messages around this point." }).optional(),
}).refine(
(data) => [data.before, data.after, data.around].filter(Boolean).length <= 1,
{ message: "Only one of 'before', 'after', or 'around' can be specified." }
);

export const GetServerInfoSchema = z.object({
guildId: z.string({ description: "The ID of the server (guild) to get information for." })
Expand Down
7 changes: 5 additions & 2 deletions src/toolList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ export const toolList = [
},
{
name: "discord_read_messages",
description: "Retrieves messages from a Discord text channel with a configurable limit",
description: "Retrieves messages from a Discord text channel. Supports date-based filtering via before/after/around params (accepts snowflake IDs or ISO 8601 dates).",
inputSchema: {
type: "object",
properties: {
Expand All @@ -195,7 +195,10 @@ export const toolList = [
minimum: 1,
maximum: 100,
default: 50
}
},
before: { type: "string", description: "Snowflake ID or ISO 8601 date (e.g. '2025-03-01T00:00:00Z'). Get messages before this point." },
after: { type: "string", description: "Snowflake ID or ISO 8601 date (e.g. '2025-03-01T00:00:00Z'). Get messages after this point." },
around: { type: "string", description: "Snowflake ID or ISO 8601 date (e.g. '2025-03-01T00:00:00Z'). Get messages around this point." }
},
required: ["channelId"]
}
Expand Down
11 changes: 9 additions & 2 deletions src/tools/channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
CreateVoiceChannelSchema
} from "../schemas.js";
import { handleDiscordError } from "../errorHandler.js";
import { resolveSnowflakeOrDate } from "../utils/snowflake.js";

// Category creation handler
export async function createCategoryHandler(
Expand Down Expand Up @@ -292,7 +293,7 @@ export async function readMessagesHandler(
args: unknown,
context: ToolContext
): Promise<ToolResponse> {
const { channelId, limit } = ReadMessagesSchema.parse(args);
const { channelId, limit, before, after, around } = ReadMessagesSchema.parse(args);
try {
if (!context.client.isReady()) {
return {
Expand All @@ -317,8 +318,14 @@ export async function readMessagesHandler(
};
}

// Build fetch options
const fetchOptions: { limit: number; before?: string; after?: string; around?: string } = { limit };
if (before) fetchOptions.before = resolveSnowflakeOrDate(before);
if (after) fetchOptions.after = resolveSnowflakeOrDate(after);
if (around) fetchOptions.around = resolveSnowflakeOrDate(around);

// Fetch messages
const messages = await channel.messages.fetch({ limit });
const messages = await channel.messages.fetch(fetchOptions);

if (messages.size === 0) {
return {
Expand Down
18 changes: 18 additions & 0 deletions src/utils/snowflake.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const DISCORD_EPOCH = 1420070400000n;

export function dateToSnowflake(date: Date): string {
return ((BigInt(date.getTime()) - DISCORD_EPOCH) << 22n).toString();
}

export function isSnowflake(value: string): boolean {
return /^\d{17,20}$/.test(value);
}

export function resolveSnowflakeOrDate(value: string): string {
if (isSnowflake(value)) return value;
const date = new Date(value);
if (isNaN(date.getTime())) {
throw new Error(`Invalid snowflake or date: ${value}`);
}
return dateToSnowflake(date);
}
Loading