Skip to content

Commit 06c22ba

Browse files
committed
Add GuildId param to ChannelId::to_channel (#2895)
1 parent fc576ce commit 06c22ba

File tree

7 files changed

+67
-43
lines changed

7 files changed

+67
-43
lines changed

examples/e04_message_builder/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ struct Handler;
1212
impl EventHandler for Handler {
1313
async fn message(&self, context: Context, msg: Message) {
1414
if msg.content == "!ping" {
15-
let channel = match msg.channel_id.to_channel(&context).await {
15+
let channel = match msg.channel(&context).await {
1616
Ok(channel) => channel,
1717
Err(why) => {
1818
println!("Error getting channel: {why:?}");

examples/testing/src/main.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,8 @@ async fn message(ctx: &Context, msg: Message) -> Result<(), serenity::Error> {
161161
)
162162
.await?;
163163
} else if msg.content == "assigntags" {
164-
let forum_id = channel_id.to_channel(ctx).await?.guild().unwrap().parent_id.unwrap();
165-
let forum = forum_id.to_channel(ctx).await?.guild().unwrap();
164+
let forum_id = msg.guild_channel(&ctx).await?.parent_id.unwrap();
165+
let forum = forum_id.to_guild_channel(&ctx, msg.guild_id).await?;
166166
channel_id
167167
.edit_thread(
168168
&ctx.http,
@@ -195,15 +195,18 @@ async fn message(ctx: &Context, msg: Message) -> Result<(), serenity::Error> {
195195

196196
msg.author.dm(&ctx.http, builder).await?;
197197
} else if let Some(channel) = msg.content.strip_prefix("movetorootandback") {
198-
let mut channel =
199-
channel.trim().parse::<ChannelId>().unwrap().to_channel(ctx).await?.guild().unwrap();
198+
let mut channel = {
199+
let channel_id = channel.trim().parse::<ChannelId>().unwrap();
200+
channel_id.to_guild_channel(&ctx, msg.guild_id).await.unwrap()
201+
};
202+
200203
let parent_id = channel.parent_id.unwrap();
201204
channel.edit(&ctx.http, EditChannel::new().category(None)).await?;
202205
channel.edit(&ctx.http, EditChannel::new().category(Some(parent_id))).await?;
203206
} else if msg.content == "channelperms" {
204207
let guild = guild_id.to_guild_cached(&ctx.cache).unwrap().clone();
205208
let perms = guild.user_permissions_in(
206-
&channel_id.to_channel(ctx).await?.guild().unwrap(),
209+
guild.channels.get(&channel_id).unwrap(),
207210
&*guild.member(&ctx.http, msg.author.id).await?,
208211
);
209212
channel_id.say(&ctx.http, format!("{:?}", perms)).await?;

src/model/channel/channel_id.rs

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -360,23 +360,30 @@ impl ChannelId {
360360
http.follow_news_channel(self, &map).await
361361
}
362362

363-
/// First attempts to retrieve the channel from the `temp_cache` if enabled, otherwise performs
364-
/// a HTTP request.
365-
///
366-
/// It is recommended to first check if the channel is accessible via `Cache::guild` and
367-
/// `Guild::members`, although this requires a `GuildId`.
363+
/// Attempts to retrieve the channel from the guild cache, otherwise from HTTP/temp cache.
368364
///
369365
/// # Errors
370366
///
371367
/// Returns [`Error::Http`] if the channel retrieval request failed.
372-
pub async fn to_channel(self, cache_http: impl CacheHttp) -> Result<Channel> {
373-
#[cfg(feature = "temp_cache")]
374-
{
375-
if let Some(cache) = cache_http.cache() {
376-
if let Some(channel) = cache.temp_channels.get(&self) {
377-
return Ok(Channel::Guild(GuildChannel::clone(&*channel)));
368+
pub async fn to_channel(
369+
self,
370+
cache_http: impl CacheHttp,
371+
guild_id: Option<GuildId>,
372+
) -> Result<Channel> {
373+
#[cfg(feature = "cache")]
374+
if let Some(cache) = cache_http.cache() {
375+
if let Some(guild_id) = guild_id {
376+
if let Some(guild) = cache.guild(guild_id) {
377+
if let Some(channel) = guild.channels.get(&self) {
378+
return Ok(Channel::Guild(channel.clone()));
379+
}
378380
}
379381
}
382+
383+
#[cfg(feature = "temp_cache")]
384+
if let Some(channel) = cache.temp_channels.get(&self) {
385+
return Ok(Channel::Guild(GuildChannel::clone(&*channel)));
386+
}
380387
}
381388

382389
let channel = cache_http.http().get_channel(self).await?;
@@ -396,6 +403,29 @@ impl ChannelId {
396403
Ok(channel)
397404
}
398405

406+
/// Fetches a channel from the cache, falling back to HTTP/temp cache.
407+
///
408+
/// It is highly recommended to pass the `guild_id` parameter as otherwise this may perform many
409+
/// HTTP requests.
410+
///
411+
/// # Errors
412+
///
413+
/// Errors if the HTTP fallback fails, or if the channel does not come from the guild passed.
414+
pub async fn to_guild_channel(
415+
self,
416+
cache_http: impl CacheHttp,
417+
guild_id: Option<GuildId>,
418+
) -> Result<GuildChannel> {
419+
let channel = self.to_channel(cache_http, guild_id).await?;
420+
let guild_channel = channel.guild().ok_or(ModelError::InvalidChannelType)?;
421+
422+
if guild_id.is_some_and(|id| guild_channel.guild_id != id) {
423+
return Err(Error::Model(ModelError::ChannelNotFound));
424+
}
425+
426+
Ok(guild_channel)
427+
}
428+
399429
/// Gets all of the channel's invites.
400430
///
401431
/// Requires the [Manage Channels] permission.

src/model/channel/message.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -182,16 +182,23 @@ impl Message {
182182
}
183183

184184
/// First attempts to find a [`Channel`] by its Id in the cache, upon failure requests it via
185-
/// the REST API.
186-
///
187-
/// **Note**: If the `cache`-feature is enabled permissions will be checked and upon owning the
188-
/// required permissions the HTTP-request will be issued.
185+
/// HTTP.
189186
///
190187
/// # Errors
191188
///
192189
/// Can return an error if the HTTP request fails.
193190
pub async fn channel(&self, cache_http: impl CacheHttp) -> Result<Channel> {
194-
self.channel_id.to_channel(cache_http).await
191+
self.channel_id.to_channel(cache_http, self.guild_id).await
192+
}
193+
194+
/// First attempts to find the [`GuildChannel`] by it's Id in the cache, upon failure requests
195+
/// it via HTTP.
196+
///
197+
/// # Errors
198+
///
199+
/// Can return an error if the HTTP request fails, or this is executed in a DM channel.
200+
pub async fn guild_channel(&self, cache_http: impl CacheHttp) -> Result<GuildChannel> {
201+
self.channel_id.to_guild_channel(cache_http, self.guild_id).await
195202
}
196203

197204
/// Deletes the message.
@@ -654,9 +661,10 @@ impl Message {
654661
}
655662
}
656663

657-
let channel = self.channel_id.to_channel(&cache_http).await.ok()?.guild()?;
664+
let http = cache_http.http();
665+
let channel = http.get_channel(self.channel_id).await.ok()?.guild()?;
658666
if channel.thread_metadata.is_some() {
659-
let thread_parent = channel.parent_id?.to_channel(cache_http).await.ok()?.guild()?;
667+
let thread_parent = http.get_channel(channel.parent_id?).await.ok()?.guild()?;
660668
thread_parent.parent_id
661669
} else {
662670
channel.parent_id

src/model/channel/reaction.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ impl Reaction {
104104
///
105105
/// [Read Message History]: Permissions::READ_MESSAGE_HISTORY
106106
pub async fn channel(&self, cache_http: impl CacheHttp) -> Result<Channel> {
107-
self.channel_id.to_channel(cache_http).await
107+
self.channel_id.to_channel(cache_http, self.guild_id).await
108108
}
109109

110110
/// Deletes the reaction, but only if the current user is the user who made the reaction or has

src/model/webhook.rs

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -165,23 +165,6 @@ pub struct WebhookChannel {
165165
pub name: FixedString<u16>,
166166
}
167167

168-
#[cfg(feature = "model")]
169-
impl WebhookChannel {
170-
/// First attempts to retrieve the channel from the `temp_cache` if enabled, otherwise performs
171-
/// a HTTP request.
172-
///
173-
/// It is recommended to first check if the channel is accessible via `Cache::guild` and
174-
/// `Guild::members`, although this requires a `GuildId`.
175-
///
176-
/// # Errors
177-
///
178-
/// Returns [`Error::Http`] if the channel retrieval request failed.
179-
pub async fn to_channel(self, cache_http: impl CacheHttp) -> Result<GuildChannel> {
180-
let channel = self.id.to_channel(cache_http).await?;
181-
channel.guild().ok_or(Error::Model(ModelError::InvalidChannelType))
182-
}
183-
}
184-
185168
#[cfg(feature = "model")]
186169
impl Webhook {
187170
/// Retrieves a webhook given its Id.

src/utils/argument_convert/channel.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ async fn lookup_channel_global(
4646
s: &str,
4747
) -> Result<Channel, ChannelParseError> {
4848
if let Some(channel_id) = s.parse().ok().or_else(|| crate::utils::parse_channel_mention(s)) {
49-
return channel_id.to_channel(&ctx).await.map_err(ChannelParseError::Http);
49+
return channel_id.to_channel(ctx, guild_id).await.map_err(ChannelParseError::Http);
5050
}
5151

5252
let guild_id = guild_id.ok_or(ChannelParseError::NotFoundOrMalformed)?;

0 commit comments

Comments
 (0)