Skip to content

Commit c548876

Browse files
authored
feat: add guild messages search endpoint (#1565)
1 parent b7367ee commit c548876

7 files changed

Lines changed: 375 additions & 2 deletions

File tree

include/dpp/cluster.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1983,6 +1983,17 @@ class DPP_EXPORT cluster {
19831983
*/
19841984
void messages_get(snowflake channel_id, snowflake around, snowflake before, snowflake after, uint64_t limit, command_completion_event_t callback);
19851985

1986+
/**
1987+
* @brief Search for messages in a guild
1988+
*
1989+
* @see https://discord.com/developers/docs/resources/message#search-guild-messages
1990+
* @param guild_id Guild ID to search in
1991+
* @param params Search parameters
1992+
* @param callback Function to call when the API call completes.
1993+
* On success the callback will contain a dpp::message_search_result object in confirmation_callback_t::value. On failure, the value is undefined and confirmation_callback_t::is_error() method will return true. You can obtain full error details with confirmation_callback_t::get_error().
1994+
*/
1995+
void guild_messages_search(snowflake guild_id, const message_search_params& params, command_completion_event_t callback);
1996+
19861997
/**
19871998
* @brief Send a message to a channel. The callback function is called when the message has been sent
19881999
*

include/dpp/cluster_coro_calls.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1743,6 +1743,18 @@
17431743
*/
17441744
[[nodiscard]] async<confirmation_callback_t> co_poll_end(snowflake message_id, snowflake channel_id);
17451745

1746+
/**
1747+
* @brief Search for messages in a guild
1748+
*
1749+
* @see dpp::cluster::guild_messages_search
1750+
* @see https://discord.com/developers/docs/resources/message#search-guild-messages
1751+
* @param guild_id Guild ID to search in
1752+
* @param params Search parameters
1753+
* @return message_search_result returned object on completion
1754+
* \memberof dpp::cluster
1755+
*/
1756+
[[nodiscard]] async<confirmation_callback_t> co_guild_messages_search(snowflake guild_id, const message_search_params& params);
1757+
17461758
/**
17471759
* @brief Get a channel's pins
17481760
* @see dpp::cluster::channel_pins_get

include/dpp/message.h

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3090,6 +3090,209 @@ typedef std::unordered_map<snowflake, message> message_map;
30903090
*/
30913091
typedef std::unordered_map<snowflake, message_pin> message_pin_map;
30923092

3093+
/**
3094+
* @brief Possible values for the "has" filter in message search
3095+
*/
3096+
enum message_search_has : uint8_t {
3097+
has_image,
3098+
has_sound,
3099+
has_video,
3100+
has_file,
3101+
has_sticker,
3102+
has_embed,
3103+
has_link,
3104+
has_poll,
3105+
has_snapshot,
3106+
};
3107+
3108+
/**
3109+
* @brief Sort mode for message search results
3110+
*/
3111+
enum message_search_sort : uint8_t {
3112+
sort_timestamp,
3113+
sort_relevance,
3114+
};
3115+
3116+
/**
3117+
* @brief Sort order for message search results
3118+
*/
3119+
enum message_search_order : uint8_t {
3120+
sort_desc,
3121+
sort_asc,
3122+
};
3123+
3124+
/**
3125+
* @brief Parameters for searching messages within a guild
3126+
* @see https://discord.com/developers/docs/resources/message#search-guild-messages
3127+
*/
3128+
struct DPP_EXPORT message_search_params {
3129+
/**
3130+
* @brief Filter messages by content (max 1024 characters)
3131+
*/
3132+
std::string content;
3133+
3134+
/**
3135+
* @brief Filter by author IDs (max 100)
3136+
*/
3137+
std::vector<snowflake> author_id;
3138+
3139+
/**
3140+
* @brief Filter messages that mention these users (max 100)
3141+
*/
3142+
std::vector<snowflake> mentions;
3143+
3144+
/**
3145+
* @brief Filter by channel IDs (max 500)
3146+
*/
3147+
std::vector<snowflake> channel_id;
3148+
3149+
/**
3150+
* @brief Filter messages that mention these roles (max 100)
3151+
*/
3152+
std::vector<snowflake> mentions_role_id;
3153+
3154+
/**
3155+
* @brief Filter messages that reply to these users (max 100)
3156+
*/
3157+
std::vector<snowflake> replied_to_user_id;
3158+
3159+
/**
3160+
* @brief Filter messages that reply to these messages (max 100)
3161+
*/
3162+
std::vector<snowflake> replied_to_message_id;
3163+
3164+
/**
3165+
* @brief Filter by author type (user, bot, webhook; prefix with - to negate)
3166+
*/
3167+
std::vector<std::string> author_type;
3168+
3169+
/**
3170+
* @brief Filter by presence of element types
3171+
*/
3172+
std::vector<message_search_has> has;
3173+
3174+
/**
3175+
* @brief Filter messages by embed type
3176+
*/
3177+
std::vector<std::string> embed_type;
3178+
3179+
/**
3180+
* @brief Filter messages by embed provider (case-sensitive, max 100)
3181+
*/
3182+
std::vector<std::string> embed_provider;
3183+
3184+
/**
3185+
* @brief Filter messages by link hostname (max 100)
3186+
*/
3187+
std::vector<std::string> link_hostname;
3188+
3189+
/**
3190+
* @brief Filter messages by attachment filename (max 100)
3191+
*/
3192+
std::vector<std::string> attachment_filename;
3193+
3194+
/**
3195+
* @brief Filter messages by attachment extension (max 100)
3196+
*/
3197+
std::vector<std::string> attachment_extension;
3198+
3199+
/**
3200+
* @brief Get messages before this message ID
3201+
*/
3202+
snowflake max_id;
3203+
3204+
/**
3205+
* @brief Get messages after this message ID
3206+
*/
3207+
snowflake min_id;
3208+
3209+
/**
3210+
* @brief Filter messages by whether they are pinned
3211+
*/
3212+
std::optional<bool> pinned;
3213+
3214+
/**
3215+
* @brief Filter by @everyone mention presence
3216+
*/
3217+
std::optional<bool> mention_everyone;
3218+
3219+
/**
3220+
* @brief Whether to include results from age-restricted channels (default false)
3221+
*/
3222+
std::optional<bool> include_nsfw;
3223+
3224+
/**
3225+
* @brief Max number of messages to return (1-25, default 25)
3226+
*/
3227+
std::optional<uint32_t> limit;
3228+
3229+
/**
3230+
* @brief Pagination offset (max 9975)
3231+
*/
3232+
std::optional<uint32_t> offset;
3233+
3234+
/**
3235+
* @brief Max number of words to skip between matching tokens (max 100, default 2)
3236+
*/
3237+
std::optional<uint32_t> slop;
3238+
3239+
/**
3240+
* @brief Sorting algorithm to use (default: sort_timestamp)
3241+
*/
3242+
std::optional<message_search_sort> sort_by;
3243+
3244+
/**
3245+
* @brief Direction to sort (default: sort_desc)
3246+
*/
3247+
std::optional<message_search_order> sort_order;
3248+
3249+
/**
3250+
* @brief Build the query string for the REST request
3251+
* @return URL query string starting with '?'
3252+
*/
3253+
std::string build_url_params() const;
3254+
};
3255+
3256+
/**
3257+
* @brief Represents the result of a guild message search
3258+
* @see https://discord.com/developers/docs/resources/message#search-guild-messages
3259+
*/
3260+
struct DPP_EXPORT message_search_result : public json_interface<message_search_result> {
3261+
protected:
3262+
friend struct json_interface<message_search_result>;
3263+
3264+
/**
3265+
* @brief Fill from JSON
3266+
* @param j JSON data
3267+
* @return Reference to self
3268+
*/
3269+
message_search_result& fill_from_json_impl(nlohmann::json* j);
3270+
3271+
public:
3272+
message_search_result() = default;
3273+
3274+
/**
3275+
* @brief Total number of results matching the query
3276+
*/
3277+
uint32_t total_results{0};
3278+
3279+
/**
3280+
* @brief Whether a deep historical index is being performed
3281+
*/
3282+
bool doing_deep_historical_index{false};
3283+
3284+
/**
3285+
* @brief Number of documents indexed so far (only present during deep indexing)
3286+
*/
3287+
std::optional<uint32_t> documents_indexed;
3288+
3289+
/**
3290+
* @brief Matched messages grouped by context.
3291+
* Each inner vector contains the matched message followed by context messages.
3292+
*/
3293+
std::vector<std::vector<message>> messages;
3294+
};
3295+
30933296
/**
30943297
* @brief A group of stickers
30953298
*/

include/dpp/restresults.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,8 @@ typedef std::variant<
196196
entitlement,
197197
entitlement_map,
198198
sku,
199-
sku_map
199+
sku_map,
200+
message_search_result
200201
> confirmable_t;
201202

202203
/**

src/dpp/cluster/message.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,15 @@ void cluster::poll_end(snowflake message_id, snowflake channel_id, command_compl
206206
}
207207

208208

209+
void cluster::guild_messages_search(snowflake guild_id, const message_search_params& params, command_completion_event_t callback) {
210+
this->post_rest(API_PATH "/guilds", std::to_string(guild_id), "messages/search" + params.build_url_params(), m_get, "", [this, callback](json &j, const http_request_completion_t& http) {
211+
if (callback) {
212+
callback(confirmation_callback_t(this, message_search_result().fill_from_json(&j), http));
213+
}
214+
});
215+
}
216+
217+
209218
void cluster::channel_pins_get(snowflake channel_id, command_completion_event_t callback) {
210219
channel_pins_get(channel_id, {}, {}, callback);
211220
}

src/dpp/cluster_coro_calls.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ async<confirmation_callback_t> cluster::co_get_gateway_bot() {
304304
}
305305

306306
async<confirmation_callback_t> cluster::co_guild_current_member_edit(snowflake guild_id, const std::string& nickname, const std::string& banner_blob, const image_type banner_type, const std::string& avatar_blob, const image_type avatar_type, const std::string& bio) {
307-
return async{ this, static_cast<void (cluster::*)(snowflake, const std::string &, const std::string&, const image_type, const std::string&, const image_type, const std::string&, command_completion_event_t)>(&cluster::guild_current_member_edit), guild_id, nickname, banner_blob, banner_type, avatar_blob, avatar_type, bio };
307+
return async{ this, static_cast<void (cluster::*)(snowflake, const std::string&, const std::string&, const image_type, const std::string&, const image_type, const std::string&, command_completion_event_t)>(&cluster::guild_current_member_edit), guild_id, nickname, banner_blob, banner_type, avatar_blob, avatar_type, bio };
308308
}
309309

310310
async<confirmation_callback_t> cluster::co_guild_auditlog_get(snowflake guild_id, snowflake user_id, uint32_t action_type, snowflake before, snowflake after, uint32_t limit) {
@@ -571,6 +571,10 @@ async<confirmation_callback_t> cluster::co_poll_end(snowflake message_id, snowfl
571571
return async{ this, static_cast<void (cluster::*)(snowflake, snowflake, command_completion_event_t)>(&cluster::poll_end), message_id, channel_id };
572572
}
573573

574+
async<confirmation_callback_t> cluster::co_guild_messages_search(snowflake guild_id, const message_search_params& params) {
575+
return async{ this, static_cast<void (cluster::*)(snowflake, const message_search_params&, command_completion_event_t)>(&cluster::guild_messages_search), guild_id, params };
576+
}
577+
574578
async<confirmation_callback_t> cluster::co_channel_pins_get(snowflake channel_id) {
575579
return async{ this, static_cast<void (cluster::*)(snowflake, command_completion_event_t)>(&cluster::channel_pins_get), channel_id };
576580
}

0 commit comments

Comments
 (0)