Skip to content

Split GuildThread from GuildChannel #3026

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 12, 2025
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
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ to-arraystring = "0.2.0"
extract_map = { version = "0.2.0", features = ["serde", "iter_mut"] }
aformat = "0.1.3"
bytes = "1.5.0"
ref-cast = "1.0.23"
# Optional dependencies
foldhash = { version = "0.1.4", optional = true }
chrono = { version = "0.4.31", default-features = false, features = ["clock", "serde"], optional = true }
Expand Down
4 changes: 2 additions & 2 deletions examples/e12_parallel_loops/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use chrono::offset::Utc;
use serenity::async_trait;
use serenity::builder::{CreateEmbed, CreateMessage};
use serenity::gateway::ActivityData;
use serenity::model::id::ChannelId;
use serenity::model::id::GenericChannelId;
use serenity::prelude::*;

struct Handler {
Expand Down Expand Up @@ -93,7 +93,7 @@ async fn log_system_load(ctx: &Context) {
false,
);
let builder = CreateMessage::new().embed(embed);
let message = ChannelId::new(381926291785383946).send_message(&ctx.http, builder).await;
let message = GenericChannelId::new(381926291785383946).send_message(&ctx.http, builder).await;
if let Err(why) = message {
eprintln!("Error sending message: {why:?}");
};
Expand Down
11 changes: 7 additions & 4 deletions examples/testing/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ async fn message(ctx: &Context, msg: &Message) -> Result<(), serenity::Error> {
model_type_sizes::print_ranking();
} else if msg.content == "auditlog" {
// Test special characters in audit log reason
msg.channel_id
channel_id
.expect_channel()
.edit(
&ctx.http,
EditChannel::new().name("new-channel-name").audit_log_reason("hello\nworld\n🙂"),
Expand Down Expand Up @@ -155,6 +156,7 @@ async fn message(ctx: &Context, msg: &Message) -> Result<(), serenity::Error> {
guild_id.ban(&ctx.http, user_id, 0, None).await?;
} else if msg.content == "createtags" {
channel_id
.expect_channel()
.edit(
&ctx.http,
EditChannel::new().available_tags(vec![
Expand All @@ -165,9 +167,10 @@ async fn message(ctx: &Context, msg: &Message) -> Result<(), serenity::Error> {
.await?;
} else if msg.content == "assigntags" {
let forum_id = msg.guild_channel(&ctx).await?.parent_id.unwrap();
let forum = forum_id.to_guild_channel(&ctx, msg.guild_id).await?;
let forum = forum_id.widen().to_guild_channel(&ctx, msg.guild_id).await?;
channel_id
.edit_thread(
.expect_thread()
.edit(
&ctx.http,
EditThread::new()
.applied_tags(forum.available_tags.iter().map(|t| t.id).collect::<Vec<_>>()),
Expand Down Expand Up @@ -199,7 +202,7 @@ async fn message(ctx: &Context, msg: &Message) -> Result<(), serenity::Error> {
msg.author.id.dm(&ctx.http, builder).await?;
} else if let Some(channel) = msg.content.strip_prefix("movetorootandback") {
let mut channel = {
let channel_id = channel.trim().parse::<ChannelId>().unwrap();
let channel_id = channel.trim().parse::<GenericChannelId>().unwrap();
channel_id.to_guild_channel(&ctx, msg.guild_id).await.unwrap()
};

Expand Down
7 changes: 5 additions & 2 deletions examples/testing/src/model_type_sizes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ pub fn print_ranking() {
("GuildBanAddEvent", std::mem::size_of::<GuildBanAddEvent>()),
("GuildBanRemoveEvent", std::mem::size_of::<GuildBanRemoveEvent>()),
("GuildChannel", std::mem::size_of::<GuildChannel>()),
("GuildThread", std::mem::size_of::<GuildThread>()),
("GuildCreateEvent", std::mem::size_of::<GuildCreateEvent>()),
("GuildDeleteEvent", std::mem::size_of::<GuildDeleteEvent>()),
("GuildEmojisUpdateEvent", std::mem::size_of::<GuildEmojisUpdateEvent>()),
Expand Down Expand Up @@ -131,10 +132,12 @@ pub fn print_ranking() {
("ModalInteraction", std::mem::size_of::<ModalInteraction>()),
("ModalInteractionData", std::mem::size_of::<ModalInteractionData>()),
("AuditLogEntryOptions", std::mem::size_of::<AuditLogEntryOptions>()),
("PartialChannel", std::mem::size_of::<PartialChannel>()),
("GenericInteractionChannel", std::mem::size_of::<GenericInteractionChannel>()),
("InteractionChannel", std::mem::size_of::<InteractionChannel>()),
("InteractionGuildThread", std::mem::size_of::<InteractionGuildThread>()),
("PartialCurrentApplicationInfo", std::mem::size_of::<PartialCurrentApplicationInfo>()),
("PartialGuild", std::mem::size_of::<PartialGuild>()),
("PartialGuildChannel", std::mem::size_of::<PartialGuildChannel>()),
("PartialGuildThread", std::mem::size_of::<PartialGuildThread>()),
("PartialMember", std::mem::size_of::<PartialMember>()),
("PermissionOverwrite", std::mem::size_of::<PermissionOverwrite>()),
("Permissions", std::mem::size_of::<Permissions>()),
Expand Down
3 changes: 1 addition & 2 deletions src/builder/create_allowed_mentions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ impl ParseAction {
}
}

/// A builder to manage the allowed mentions on a message, used by the [`ChannelId::send_message`]
/// and [`ChannelId::edit_message`] methods.
/// A builder to manage the allowed mentions on a message.
///
/// # Examples
///
Expand Down
2 changes: 1 addition & 1 deletion src/builder/create_components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ pub enum CreateSelectMenuKind<'a> {
},
Channel {
channel_types: Option<Cow<'a, [ChannelType]>>,
default_channels: Option<Cow<'a, [ChannelId]>>,
default_channels: Option<Cow<'a, [GenericChannelId]>>,
},
}

Expand Down
5 changes: 2 additions & 3 deletions src/builder/create_embed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,11 @@ impl<'a> CreateEmbed<'a> {

/// Same as calling [`Self::image`] with "attachment://filename.(jpg, png)".
///
/// Note however, you have to be sure you set an attachment (with [`ChannelId::send_files`])
/// with the provided filename. Or else this won't work.
/// Remember to set an attachment with the provided filename via [`CreateAttachment`]
///
/// Refer [`Self::image`] for rules on naming local attachments.
///
/// [`ChannelId::send_files`]: crate::model::id::ChannelId::send_files
/// [`CreateAttachment`]: crate::builder::CreateAttachment
pub fn attachment(self, filename: impl Into<String>) -> Self {
let mut filename = filename.into();
filename.insert_str(0, "attachment://");
Expand Down
10 changes: 5 additions & 5 deletions src/builder/create_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::internal::prelude::*;
use crate::model::prelude::*;

/// A builder to specify the contents of an send message request, primarily meant for use
/// through [`ChannelId::send_message`].
/// through [`GenericChannelId::send_message`].
///
/// There are three situations where different field requirements are present:
///
Expand All @@ -27,21 +27,21 @@ use crate::model::prelude::*;
/// required.
///
/// Note that if you only need to send the content of a message, without specifying other fields,
/// then [`ChannelId::say`] may be a more preferable option.
/// then [`GenericChannelId::say`] may be a more preferable option.
///
/// # Examples
///
/// Sending a message with a content of `"test"` and applying text-to-speech:
///
/// ```rust,no_run
/// use serenity::builder::{CreateEmbed, CreateMessage};
/// use serenity::model::id::ChannelId;
/// use serenity::model::id::GenericChannelId;
/// # use serenity::http::Http;
/// # use std::sync::Arc;
/// #
/// # async fn run() {
/// # let http: Arc<Http> = unimplemented!();
/// # let channel_id = ChannelId::new(7);
/// # let channel_id = GenericChannelId::new(7);
/// let embed = CreateEmbed::new().title("This is an embed").description("With a description");
/// let builder = CreateMessage::new().content("test").tts(true).embed(embed);
/// let _ = channel_id.send_message(&http, builder).await;
Expand Down Expand Up @@ -290,7 +290,7 @@ impl<'a> CreateMessage<'a> {
pub async fn execute(
mut self,
http: &Http,
channel_id: ChannelId,
channel_id: GenericChannelId,
guild_id: Option<GuildId>,
) -> Result<Message> {
self.check_length()?;
Expand Down
4 changes: 2 additions & 2 deletions src/builder/create_scheduled_event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ impl<'a> CreateScheduledEvent<'a> {
///
/// [Create Events]: Permissions::CREATE_EVENTS
#[cfg(feature = "http")]
pub async fn execute(self, http: &Http, channel_id: GuildId) -> Result<ScheduledEvent> {
http.create_scheduled_event(channel_id, &self, self.audit_log_reason).await
pub async fn execute(self, http: &Http, guild_id: GuildId) -> Result<ScheduledEvent> {
http.create_scheduled_event(guild_id, &self, self.audit_log_reason).await
}
}

Expand Down
5 changes: 4 additions & 1 deletion src/builder/edit_channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,9 @@ impl<'a> EditChannel<'a> {
.await?;
}

http.edit_channel(channel_id, &self, self.audit_log_reason).await
http.edit_channel(channel_id.widen(), &self, self.audit_log_reason)
.await?
.guild()
.ok_or(Error::Model(ModelError::InvalidChannelType))
}
}
6 changes: 3 additions & 3 deletions src/builder/edit_guild_welcome_screen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,14 @@ impl<'a> EditGuildWelcomeScreen<'a> {
#[derive(Clone, Debug, Serialize)]
#[must_use]
pub struct CreateGuildWelcomeChannel<'a> {
channel_id: ChannelId,
channel_id: GenericChannelId,
emoji_name: Option<String>,
emoji_id: Option<EmojiId>,
description: Cow<'a, str>,
}

impl<'a> CreateGuildWelcomeChannel<'a> {
pub fn new(channel_id: ChannelId, description: impl Into<Cow<'a, str>>) -> Self {
pub fn new(channel_id: GenericChannelId, description: impl Into<Cow<'a, str>>) -> Self {
Self {
channel_id,
emoji_id: None,
Expand All @@ -99,7 +99,7 @@ impl<'a> CreateGuildWelcomeChannel<'a> {
}

/// The Id of the channel to show.
pub fn id(mut self, id: ChannelId) -> Self {
pub fn id(mut self, id: GenericChannelId) -> Self {
self.channel_id = id;
self
}
Expand Down
2 changes: 1 addition & 1 deletion src/builder/edit_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ impl<'a> EditMessage<'a> {
pub async fn execute(
mut self,
cache_http: impl CacheHttp,
channel_id: ChannelId,
channel_id: GenericChannelId,
message_id: MessageId,
user_id: Option<UserId>,
) -> Result<Message> {
Expand Down
8 changes: 6 additions & 2 deletions src/builder/edit_thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,12 @@ impl<'a> EditThread<'a> {
/// # Errors
///
/// Returns [`Error::Http`] if the current user lacks permission.
/// Returns [`ModelError::InvalidChannelType`] if the `ThreadId` is not identifying a thread.
#[cfg(feature = "http")]
pub async fn execute(self, http: &Http, channel_id: ChannelId) -> Result<GuildChannel> {
http.edit_thread(channel_id, &self, self.audit_log_reason).await
pub async fn execute(self, http: &Http, thread_id: ThreadId) -> Result<GuildThread> {
http.edit_channel(thread_id.widen(), &self, self.audit_log_reason)
.await?
.thread()
.ok_or(Error::Model(ModelError::InvalidChannelType))
}
}
4 changes: 2 additions & 2 deletions src/builder/edit_webhook_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub struct EditWebhookMessage<'a> {
pub(crate) attachments: Option<EditAttachments<'a>>,

#[serde(skip)]
thread_id: Option<ChannelId>,
thread_id: Option<ThreadId>,
}

impl<'a> EditWebhookMessage<'a> {
Expand All @@ -55,7 +55,7 @@ impl<'a> EditWebhookMessage<'a> {

/// Edits a message within a given thread. If the provided thread Id doesn't belong to the
/// current webhook, the API will return an error.
pub fn in_thread(mut self, thread_id: ChannelId) -> Self {
pub fn in_thread(mut self, thread_id: ThreadId) -> Self {
self.thread_id = Some(thread_id);
self
}
Expand Down
8 changes: 4 additions & 4 deletions src/builder/execute_webhook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ pub struct ExecuteWebhook<'a> {
attachments: EditAttachments<'a>,

#[serde(skip)]
thread_id: Option<ChannelId>,
thread_id: Option<ThreadId>,
#[serde(skip)]
with_components: Option<bool>,
}
Expand Down Expand Up @@ -161,19 +161,19 @@ impl<'a> ExecuteWebhook<'a> {
/// ```rust,no_run
/// # use serenity::builder::ExecuteWebhook;
/// # use serenity::http::Http;
/// # use serenity::model::{id::ChannelId, webhook::Webhook};
/// # use serenity::model::{id::ThreadId, webhook::Webhook};
/// #
/// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
/// # let http: Http = unimplemented!();
/// let url = "https://discord.com/api/webhooks/245037420704169985/ig5AO-wdVWpCBtUUMxmgsWryqgsW3DChbKYOINftJ4DCrUbnkedoYZD0VOH1QLr-S3sV";
/// let mut webhook = Webhook::from_url(&http, url).await?;
///
/// let builder = ExecuteWebhook::new().in_thread(ChannelId::new(12345678)).content("test");
/// let builder = ExecuteWebhook::new().in_thread(ThreadId::new(12345678)).content("test");
/// webhook.execute(&http, false, builder).await?;
/// # Ok(())
/// # }
/// ```
pub fn in_thread(mut self, thread_id: ChannelId) -> Self {
pub fn in_thread(mut self, thread_id: ThreadId) -> Self {
self.thread_id = Some(thread_id);
self
}
Expand Down
8 changes: 4 additions & 4 deletions src/builder/get_messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::model::prelude::*;
/// The other parameter specifies the number of messages to retrieve. This is _optional_, and
/// defaults to 50 if not specified.
///
/// See [`ChannelId::messages`] for more examples.
/// See [`GenericChannelId::messages`] for more examples.
///
/// # Examples
///
Expand All @@ -34,10 +34,10 @@ use crate::model::prelude::*;
/// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
/// # let http: Http = unimplemented!();
/// use serenity::builder::GetMessages;
/// use serenity::model::id::{ChannelId, MessageId};
/// use serenity::model::id::{GenericChannelId, MessageId};
///
/// // you can then pass it into a function which retrieves messages:
/// let channel_id = ChannelId::new(81384788765712384);
/// let channel_id = GenericChannelId::new(81384788765712384);
///
/// let builder = GetMessages::new().after(MessageId::new(158339864557912064)).limit(25);
/// let _messages = channel_id.messages(&http, builder).await?;
Expand Down Expand Up @@ -106,7 +106,7 @@ impl GetMessages {
pub async fn execute(
self,
cache_http: impl CacheHttp,
channel_id: ChannelId,
channel_id: GenericChannelId,
) -> Result<Vec<Message>> {
let http = cache_http.http();
let search_filter = self.search_filter.map(Into::into);
Expand Down
Loading
Loading