mirror of
https://github.com/discordeno/discordeno.git
synced 2026-09-17 00:37:22 +00:00
feat(rest): add guild message search support (#5233)
* feat(rest): add guild message search support * fix(types): address guild message search review feedback * Update packages/rest/src/routes.ts Co-authored-by: Awesome Stickz <38146668+AwesomeStickz@users.noreply.github.com> * Update packages/types/src/discord/message.ts Co-authored-by: Awesome Stickz <38146668+AwesomeStickz@users.noreply.github.com> * Update packages/rest/src/routes.ts Co-authored-by: Awesome Stickz <38146668+AwesomeStickz@users.noreply.github.com> * apply requested changes --------- Co-authored-by: Fleny <Fleny113@outlook.com> Co-authored-by: Awesome Stickz <38146668+AwesomeStickz@users.noreply.github.com>
This commit is contained in:
co-authored by
Awesome Stickz
Fleny
parent
4c9522f14d
commit
a6b940677e
@@ -46,6 +46,8 @@ import type {
|
||||
DiscordInvite,
|
||||
DiscordListArchivedThreads,
|
||||
DiscordPrunedCount,
|
||||
DiscordSearchGuildMessages,
|
||||
DiscordSearchGuildMessagesIndexing,
|
||||
DiscordTargetUsersJobStatus,
|
||||
DiscordTokenExchange,
|
||||
DiscordTokenRevocation,
|
||||
@@ -100,6 +102,7 @@ import type {
|
||||
ModifyLobby,
|
||||
ModifyRolePositions,
|
||||
ModifyWebhook,
|
||||
SearchGuildMessagesOptions,
|
||||
SearchMembers,
|
||||
SendLobbyMessage,
|
||||
SendSoundboardSound,
|
||||
@@ -542,6 +545,16 @@ export function createBotHelpers<TProps extends TransformersDesiredProperties, T
|
||||
publishMessage: async (channelId, messageId) => {
|
||||
return bot.transformers.message(bot, snakelize(await bot.rest.publishMessage(channelId, messageId)));
|
||||
},
|
||||
searchGuildMessages: async (guildId, options) => {
|
||||
const result = await bot.rest.searchGuildMessages(guildId, options);
|
||||
if ('code' in result) return result;
|
||||
return {
|
||||
...result,
|
||||
messages: result.messages.map((messages) => messages.map((message) => bot.transformers.message(bot, snakelize(message)))),
|
||||
threads: result.threads?.map((thread) => bot.transformers.channel(bot, snakelize(thread), { guildId })),
|
||||
members: result.members?.map((member) => bot.transformers.threadMember(bot, snakelize(member), { guildId })),
|
||||
};
|
||||
},
|
||||
sendMessage: async (channelId, options) => {
|
||||
return bot.transformers.message(bot, snakelize(await bot.rest.sendMessage(channelId, options)));
|
||||
},
|
||||
@@ -1071,6 +1084,17 @@ export type BotHelpers<TProps extends TransformersDesiredProperties, TBehavior e
|
||||
getInvites: (guildId: BigString) => Promise<SetupDesiredProps<Invite, TProps, TBehavior>[]>;
|
||||
getMessage: (channelId: BigString, messageId: BigString) => Promise<SetupDesiredProps<Message, TProps, TBehavior>>;
|
||||
getMessages: (channelId: BigString, options?: GetMessagesOptions) => Promise<SetupDesiredProps<Message, TProps, TBehavior>[]>;
|
||||
searchGuildMessages: (
|
||||
guildId: BigString,
|
||||
options?: SearchGuildMessagesOptions,
|
||||
) => Promise<
|
||||
| Camelize<DiscordSearchGuildMessagesIndexing>
|
||||
| (Omit<Camelize<DiscordSearchGuildMessages>, 'messages' | 'threads' | 'members'> & {
|
||||
messages: SetupDesiredProps<Message, TProps, TBehavior>[][];
|
||||
threads?: SetupDesiredProps<Channel, TProps, TBehavior>[];
|
||||
members?: SetupDesiredProps<ThreadMember, TProps, TBehavior>[];
|
||||
})
|
||||
>;
|
||||
getStickerPack: (stickerPackId: BigString) => Promise<SetupDesiredProps<StickerPack, TProps, TBehavior>>;
|
||||
getStickerPacks: () => Promise<SetupDesiredProps<StickerPack, TProps, TBehavior>[]>;
|
||||
getOriginalInteractionResponse: (token: string) => Promise<SetupDesiredProps<Message, TProps, TBehavior>>;
|
||||
|
||||
@@ -44,6 +44,8 @@ import type {
|
||||
DiscordPrunedCount,
|
||||
DiscordRole,
|
||||
DiscordScheduledEvent,
|
||||
DiscordSearchGuildMessages,
|
||||
DiscordSearchGuildMessagesIndexing,
|
||||
DiscordSku,
|
||||
DiscordSoundboardSound,
|
||||
DiscordStageInstance,
|
||||
@@ -1433,6 +1435,9 @@ export function createRestManager(options: CreateRestManagerOptions): RestManage
|
||||
return await rest.get<DiscordMessage[]>(rest.routes.channels.messages(channelId, options));
|
||||
},
|
||||
|
||||
async searchGuildMessages(guildId, options) {
|
||||
return await rest.get<DiscordSearchGuildMessages | DiscordSearchGuildMessagesIndexing>(rest.routes.guilds.messagesSearch(guildId, options));
|
||||
},
|
||||
async getStickerPack(stickerPackId) {
|
||||
return await rest.get<DiscordStickerPack>(rest.routes.stickerPack(stickerPackId));
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { GetMessagesOptions, GetScheduledEventUsers } from '@discordeno/types';
|
||||
import { isGetMessagesAfter, isGetMessagesAround, isGetMessagesBefore, isGetMessagesLimit } from '@discordeno/utils';
|
||||
import type { GetMessagesOptions, GetScheduledEventUsers, SearchGuildMessagesOptions } from '@discordeno/types';
|
||||
import { camelToSnakeCase, isGetMessagesAfter, isGetMessagesAround, isGetMessagesBefore, isGetMessagesLimit } from '@discordeno/utils';
|
||||
import type { RestRoutes } from './typings/routes.js';
|
||||
|
||||
/**
|
||||
@@ -447,6 +447,19 @@ export function createRoutes(disableURIEncode: boolean = false): RestRoutes {
|
||||
return url;
|
||||
},
|
||||
},
|
||||
messagesSearch: (guildId, options?: SearchGuildMessagesOptions) => {
|
||||
let url = `/guilds/${encode(guildId)}/messages/search?`;
|
||||
|
||||
if (options) {
|
||||
for (const [key, value] of Object.entries(options)) {
|
||||
if (value === undefined) continue;
|
||||
|
||||
for (const item of Array.isArray(value) ? value : [value]) url += `&${camelToSnakeCase(key)}=${encode(item)}`;
|
||||
}
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
preview: (guildId) => {
|
||||
return `/guilds/${encode(guildId)}/preview`;
|
||||
},
|
||||
|
||||
@@ -77,6 +77,8 @@ import type {
|
||||
DiscordPrunedCount,
|
||||
DiscordRole,
|
||||
DiscordScheduledEvent,
|
||||
DiscordSearchGuildMessages,
|
||||
DiscordSearchGuildMessagesIndexing,
|
||||
DiscordSku,
|
||||
DiscordSoundboardSound,
|
||||
DiscordStageInstance,
|
||||
@@ -150,6 +152,7 @@ import type {
|
||||
ModifyWebhook,
|
||||
ScheduledEventEntityType,
|
||||
ScheduledEventStatus,
|
||||
SearchGuildMessagesOptions,
|
||||
SearchMembers,
|
||||
SendLobbyMessage,
|
||||
SendSoundboardSound,
|
||||
@@ -2094,6 +2097,18 @@ export interface RestManager {
|
||||
* @see {@link https://docs.discord.com/developers/resources/channel#get-channel-messages}
|
||||
*/
|
||||
getMessages: (channelId: BigString, options?: GetMessagesOptions) => Promise<Camelize<DiscordMessage>[]>;
|
||||
/**
|
||||
* Search messages in a guild.
|
||||
*
|
||||
* @remarks
|
||||
* Requires `READ_MESSAGE_HISTORY` and is restricted by the `MESSAGE_CONTENT` intent.
|
||||
*
|
||||
* @see {@link https://docs.discord.com/developers/resources/message#search-guild-messages}
|
||||
*/
|
||||
searchGuildMessages: (
|
||||
guildId: BigString,
|
||||
options?: SearchGuildMessagesOptions,
|
||||
) => Promise<Camelize<DiscordSearchGuildMessages | DiscordSearchGuildMessagesIndexing>>;
|
||||
/**
|
||||
* Returns a sticker pack for the given ID.
|
||||
*
|
||||
|
||||
@@ -18,6 +18,7 @@ import type {
|
||||
ListGuildMembers,
|
||||
ListSkuSubscriptionsOptions,
|
||||
ListThreadMembers,
|
||||
SearchGuildMessagesOptions,
|
||||
} from '@discordeno/types';
|
||||
|
||||
export interface RestRoutes {
|
||||
@@ -166,6 +167,8 @@ export interface RestRoutes {
|
||||
invites: (guildId: BigString) => string;
|
||||
/** Route for handling a bot leaving a guild. */
|
||||
leave: (guildId: BigString) => string;
|
||||
/** Route for searching a guild's messages. */
|
||||
messagesSearch: (guildId: BigString, options?: SearchGuildMessagesOptions) => string;
|
||||
/** Route for handling a guild's preview. */
|
||||
preview: (guildId: BigString) => string;
|
||||
/** Route for handling pruning of a guild. */
|
||||
|
||||
@@ -11,6 +11,7 @@ import type {
|
||||
DiscordMessageInteraction,
|
||||
InteractionTypes,
|
||||
} from './interactions.js';
|
||||
import type { HTTPJsonErrorCodes } from './opcodes.js';
|
||||
import type { DiscordPoll } from './poll.js';
|
||||
import type { DiscordSticker, DiscordStickerItem } from './sticker.js';
|
||||
import type { DiscordUser } from './user.js';
|
||||
@@ -115,6 +116,30 @@ export interface DiscordMessage extends Partial<DiscordMessageCreateExtra> {
|
||||
shared_client_theme?: DiscordSharedClientTheme;
|
||||
}
|
||||
|
||||
/** https://docs.discord.com/developers/resources/message#search-guild-messages-response-body */
|
||||
export interface DiscordSearchGuildMessages {
|
||||
/** Whether the guild is undergoing a deep historical indexing operation */
|
||||
doing_deep_historical_index: boolean;
|
||||
/** The number of documents indexed during the current index operation, if any */
|
||||
documents_indexed?: number;
|
||||
/** The total number of results that match the query */
|
||||
total_results: number;
|
||||
/** Nested messages that match the query; surrounding context is no longer returned */
|
||||
messages: DiscordMessage[][];
|
||||
/** The threads that contain the returned messages */
|
||||
threads?: DiscordChannel[];
|
||||
/** A thread member object for each returned thread the current user has joined */
|
||||
members?: DiscordThreadMember[];
|
||||
}
|
||||
|
||||
/** https://docs.discord.com/developers/resources/message#search-guild-messages */
|
||||
export interface DiscordSearchGuildMessagesIndexing {
|
||||
message: string;
|
||||
code: HTTPJsonErrorCodes.IndexNotAvailable;
|
||||
documents_indexed: number;
|
||||
retry_after: number;
|
||||
}
|
||||
|
||||
/** https://docs.discord.com/developers/resources/message#message-object-message-types */
|
||||
export enum MessageTypes {
|
||||
Default,
|
||||
|
||||
@@ -467,6 +467,8 @@ export enum HTTPJsonErrorCodes {
|
||||
/** User cannot use burst reactions */
|
||||
NoBurstReactions = 90002,
|
||||
|
||||
/** Index not yet available. Try again later */
|
||||
IndexNotAvailable = 110000,
|
||||
/** Application not yet available. Try again later */
|
||||
AppNotAvailable = 110001,
|
||||
|
||||
|
||||
@@ -117,6 +117,136 @@ export interface GetMessagesAfter extends GetMessagesLimit {
|
||||
/** https://docs.discord.com/developers/resources/channel#get-channel-messages-query-string-params */
|
||||
export type GetMessagesOptions = GetMessagesAfter | GetMessagesBefore | GetMessagesAround | GetMessagesLimit;
|
||||
|
||||
/** https://docs.discord.com/developers/resources/message#search-guild-messages-query-string-params */
|
||||
export enum SearchGuildMessagesAuthorType {
|
||||
/** Return messages sent by user accounts */
|
||||
User = 'user',
|
||||
/** Return messages sent by bot accounts */
|
||||
Bot = 'bot',
|
||||
/** Return messages sent by webhooks */
|
||||
Webhook = 'webhook',
|
||||
/** Exclude messages sent by user accounts */
|
||||
ExcludeUser = '-user',
|
||||
/** Exclude messages sent by bot accounts */
|
||||
ExcludeBot = '-bot',
|
||||
/** Exclude messages sent by webhooks */
|
||||
ExcludeWebhook = '-webhook',
|
||||
}
|
||||
|
||||
/** https://docs.discord.com/developers/resources/message#search-guild-messages-query-string-params */
|
||||
export enum SearchGuildMessagesHas {
|
||||
/** Return messages that have an image */
|
||||
Image = 'image',
|
||||
/** Return messages that have a sound attachment */
|
||||
Sound = 'sound',
|
||||
/** Return messages that have a video */
|
||||
Video = 'video',
|
||||
/** Return messages that have an attachment */
|
||||
File = 'file',
|
||||
/** Return messages that have a sent sticker */
|
||||
Sticker = 'sticker',
|
||||
/** Return messages that have an embed */
|
||||
Embed = 'embed',
|
||||
/** Return messages that have a link */
|
||||
Link = 'link',
|
||||
/** Return messages that have a poll */
|
||||
Poll = 'poll',
|
||||
/** Return messages that have a forwarded message */
|
||||
Snapshot = 'snapshot',
|
||||
/** Exclude messages that have an image */
|
||||
ExcludeImage = '-image',
|
||||
/** Exclude messages that have a sound attachment */
|
||||
ExcludeSound = '-sound',
|
||||
/** Exclude messages that have a video */
|
||||
ExcludeVideo = '-video',
|
||||
/** Exclude messages that have an attachment */
|
||||
ExcludeFile = '-file',
|
||||
/** Exclude messages that have a sent sticker */
|
||||
ExcludeSticker = '-sticker',
|
||||
/** Exclude messages that have an embed */
|
||||
ExcludeEmbed = '-embed',
|
||||
/** Exclude messages that have a link */
|
||||
ExcludeLink = '-link',
|
||||
/** Exclude messages that have a poll */
|
||||
ExcludePoll = '-poll',
|
||||
/** Exclude messages that have a forwarded message */
|
||||
ExcludeSnapshot = '-snapshot',
|
||||
}
|
||||
|
||||
/** https://docs.discord.com/developers/resources/message#search-guild-messages-query-string-params */
|
||||
export enum SearchGuildMessagesEmbedType {
|
||||
/** Return messages that have an image embed */
|
||||
Image = 'image',
|
||||
/** Return messages that have a video embed */
|
||||
Video = 'video',
|
||||
/** Return messages that have a gifv embed */
|
||||
Gif = 'gif',
|
||||
/** Return messages that have a sound embed */
|
||||
Sound = 'sound',
|
||||
/** Return messages that have an article embed */
|
||||
Article = 'article',
|
||||
}
|
||||
|
||||
/** https://docs.discord.com/developers/resources/message#search-guild-messages-query-string-params */
|
||||
export enum SearchGuildMessagesSortBy {
|
||||
/** Sort by message creation time (default) */
|
||||
Timestamp = 'timestamp',
|
||||
/** Sort by relevance to the search query */
|
||||
Relevance = 'relevance',
|
||||
}
|
||||
|
||||
/** https://docs.discord.com/developers/resources/message#search-guild-messages-query-string-params */
|
||||
export interface SearchGuildMessagesOptions {
|
||||
/** Max number of messages to return (1-25, default 25) */
|
||||
limit?: number;
|
||||
/** Number to offset the returned messages by (max 9975) */
|
||||
offset?: number;
|
||||
/** Get messages before this message ID */
|
||||
maxId?: BigString;
|
||||
/** Get messages after this message ID */
|
||||
minId?: BigString;
|
||||
/** Max number of words to skip between matching tokens in the search content (max 100, default 2) */
|
||||
slop?: number;
|
||||
/** Filter messages by content (max 1024 characters) */
|
||||
content?: string;
|
||||
/** Filter messages by these channels (max 500) */
|
||||
channelId?: BigString[];
|
||||
/** Filter messages by author type */
|
||||
authorType?: SearchGuildMessagesAuthorType[];
|
||||
/** Filter messages by these authors (max 100) */
|
||||
authorId?: BigString[];
|
||||
/** Filter messages that mention these users (max 100) */
|
||||
mentions?: BigString[];
|
||||
/** Filter messages that mention these roles (max 100) */
|
||||
mentionsRoleId?: BigString[];
|
||||
/** Filter messages by whether they do or do not mention @everyone */
|
||||
mentionEveryone?: boolean;
|
||||
/** Filter messages that reply to these users (max 100) */
|
||||
repliedToUserId?: BigString[];
|
||||
/** Filter messages that reply to these messages (max 100) */
|
||||
repliedToMessageId?: BigString[];
|
||||
/** Filter messages by whether they are or are not pinned */
|
||||
pinned?: boolean;
|
||||
/** Filter messages by whether they have or do not have specific things */
|
||||
has?: SearchGuildMessagesHas[];
|
||||
/** Filter messages by embed type */
|
||||
embedType?: SearchGuildMessagesEmbedType[];
|
||||
/** Filter messages by embed provider (case-sensitive, max 256 characters, max 100) */
|
||||
embedProvider?: string[];
|
||||
/** Filter messages by link hostname (max 256 characters, max 100) */
|
||||
linkHostname?: string[];
|
||||
/** Filter messages by attachment filename (max 1024 characters, max 100) */
|
||||
attachmentFilename?: string[];
|
||||
/** Filter messages by attachment extension (max 256 characters, max 100) */
|
||||
attachmentExtension?: string[];
|
||||
/** The sorting algorithm to use */
|
||||
sortBy?: SearchGuildMessagesSortBy;
|
||||
/** The direction to sort (default desc); ignored when sorting by relevance */
|
||||
sortOrder?: 'asc' | 'desc';
|
||||
/** Whether to include results from age-restricted channels (default false) */
|
||||
includeNsfw?: boolean;
|
||||
}
|
||||
|
||||
/** https://docs.discord.com/developers/resources/message#create-message-json/form-params */
|
||||
export interface CreateMessageOptions {
|
||||
/** The message contents (up to 2000 characters) */
|
||||
|
||||
Reference in New Issue
Block a user