Skip to content

Commit 06a16ac

Browse files
authored
Rework Id -> Channel methods (#3343)
1 parent 5b3ea19 commit 06a16ac

File tree

4 files changed

+125
-33
lines changed

4 files changed

+125
-33
lines changed

examples/testing/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ async fn message(ctx: &Context, msg: &Message) -> Result<(), serenity::Error> {
167167
.await?;
168168
} else if msg.content == "assigntags" {
169169
let forum_id = msg.guild_channel(&ctx).await?.parent_id.unwrap();
170-
let forum = forum_id.widen().to_guild_channel(&ctx, msg.guild_id).await?;
170+
let forum = forum_id.to_guild_channel(&ctx, msg.guild_id).await?;
171171
channel_id
172172
.expect_thread()
173173
.edit(
@@ -202,7 +202,7 @@ async fn message(ctx: &Context, msg: &Message) -> Result<(), serenity::Error> {
202202
msg.author.id.dm(&ctx.http, builder).await?;
203203
} else if let Some(channel) = msg.content.strip_prefix("movetorootandback") {
204204
let mut channel = {
205-
let channel_id = channel.trim().parse::<GenericChannelId>().unwrap();
205+
let channel_id = channel.trim().parse::<ChannelId>().unwrap();
206206
channel_id.to_guild_channel(&ctx, msg.guild_id).await.unwrap()
207207
};
208208

src/model/channel/channel_id.rs

Lines changed: 51 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ use crate::builder::{
2222
};
2323
#[cfg(all(feature = "cache", feature = "model"))]
2424
use crate::cache::Cache;
25+
#[cfg(all(feature = "cache", feature = "temp_cache", feature = "model"))]
26+
use crate::cache::MaybeOwnedArc;
2527
#[cfg(feature = "model")]
2628
use crate::http::{CacheHttp, Http, Typing};
2729
use crate::model::prelude::*;
@@ -39,6 +41,55 @@ impl ChannelId {
3941

4042
#[cfg(feature = "model")]
4143
impl ChannelId {
44+
/// Fetches a channel from the cache, falling back to HTTP/temp cache.
45+
///
46+
/// It is highly recommended to pass the `guild_id` parameter as otherwise this may perform many
47+
/// HTTP requests.
48+
///
49+
/// # Errors
50+
///
51+
/// Errors if the HTTP fallback fails, or if the channel does not come from the guild passed.
52+
pub async fn to_guild_channel(
53+
self,
54+
cache_http: impl CacheHttp,
55+
guild_id: Option<GuildId>,
56+
) -> Result<GuildChannel> {
57+
#[cfg(feature = "cache")]
58+
if let Some(cache) = cache_http.cache() {
59+
if let Some(guild_id) = guild_id {
60+
if let Some(guild) = cache.guild(guild_id) {
61+
if let Some(channel) = guild.channels.get(&self) {
62+
return Ok(channel.clone());
63+
}
64+
}
65+
}
66+
67+
#[cfg(feature = "temp_cache")]
68+
if let Some(temp_channel) = cache.temp_channels.get(&self) {
69+
if guild_id.is_some_and(|id| temp_channel.base.guild_id != id) {
70+
return Err(Error::Model(ModelError::ChannelNotFound));
71+
}
72+
73+
return Ok(GuildChannel::clone(&temp_channel));
74+
}
75+
}
76+
77+
let channel = cache_http.http().get_channel(self.widen()).await?;
78+
let guild_channel = channel.guild().ok_or(ModelError::InvalidChannelType)?;
79+
80+
#[cfg(all(feature = "cache", feature = "temp_cache"))]
81+
if let Some(cache) = cache_http.cache() {
82+
let cached_channel = MaybeOwnedArc::new(guild_channel.clone());
83+
cache.temp_channels.insert(self, cached_channel);
84+
}
85+
86+
if guild_id.is_some_and(|id| guild_channel.base.guild_id != id) {
87+
return Err(Error::Model(ModelError::ChannelNotFound));
88+
}
89+
90+
Ok(guild_channel)
91+
}
92+
4293
/// Creates an invite for the given channel.
4394
///
4495
/// **Note**: Requires the [Create Instant Invite] permission.
@@ -595,8 +646,6 @@ impl GenericChannelId {
595646

596647
#[cfg(all(feature = "cache", feature = "temp_cache"))]
597648
if let Some(cache) = cache_http.cache() {
598-
use crate::cache::MaybeOwnedArc;
599-
600649
match &channel {
601650
Channel::Guild(guild_channel) => {
602651
let cached_channel = MaybeOwnedArc::new(guild_channel.clone());
@@ -614,29 +663,6 @@ impl GenericChannelId {
614663
Ok(channel)
615664
}
616665

617-
/// Fetches a channel from the cache, falling back to HTTP/temp cache.
618-
///
619-
/// It is highly recommended to pass the `guild_id` parameter as otherwise this may perform many
620-
/// HTTP requests.
621-
///
622-
/// # Errors
623-
///
624-
/// Errors if the HTTP fallback fails, or if the channel does not come from the guild passed.
625-
pub async fn to_guild_channel(
626-
self,
627-
cache_http: impl CacheHttp,
628-
guild_id: Option<GuildId>,
629-
) -> Result<GuildChannel> {
630-
let channel = self.to_channel(cache_http, guild_id).await?;
631-
let guild_channel = channel.guild().ok_or(ModelError::InvalidChannelType)?;
632-
633-
if guild_id.is_some_and(|id| guild_channel.base.guild_id != id) {
634-
return Err(Error::Model(ModelError::ChannelNotFound));
635-
}
636-
637-
Ok(guild_channel)
638-
}
639-
640666
/// Gets a message from the channel.
641667
///
642668
/// If the cache feature is enabled the cache will be checked first. If not found it will

src/model/channel/message.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,9 @@ impl Message {
169169
self.channel_id.expect_channel().crosspost(http, self.id).await
170170
}
171171

172-
/// First attempts to find a [`Channel`] by its Id in the cache, upon failure requests it via
173-
/// HTTP.
172+
/// Retrieves the [`Channel`] the message was sent in.
173+
///
174+
/// See [`GenericChannelId::to_channel`] for information about how this is retrieved.
174175
///
175176
/// # Errors
176177
///
@@ -179,14 +180,26 @@ impl Message {
179180
self.channel_id.to_channel(cache_http, self.guild_id).await
180181
}
181182

182-
/// First attempts to find the [`GuildChannel`] by it's Id in the cache, upon failure requests
183-
/// it via HTTP.
183+
/// Retrieves the [`GuildChannel`] the message was sent in.
184+
///
185+
/// See [`ChannelId::to_guild_channel`] for information on how this is retrieved.
184186
///
185187
/// # Errors
186188
///
187-
/// Can return an error if the HTTP request fails, or this is executed in a DM channel.
189+
/// Can return an error if the HTTP request fails, or this is not called in a guild channel.
188190
pub async fn guild_channel(&self, cache_http: impl CacheHttp) -> Result<GuildChannel> {
189-
self.channel_id.to_guild_channel(cache_http, self.guild_id).await
191+
self.channel_id.expect_channel().to_guild_channel(cache_http, self.guild_id).await
192+
}
193+
194+
/// Retrieves the [`GuildThread`] the message was sent in.
195+
///
196+
/// See [`ThreadId::to_thread`] for information on how this is retrieved.
197+
///
198+
/// # Errors
199+
///
200+
/// Can return an error if the HTTP request fails, or this is not called in a guild thread.
201+
pub async fn guild_thread(&self, cache_http: impl CacheHttp) -> Result<GuildThread> {
202+
self.channel_id.expect_thread().to_thread(cache_http, self.guild_id).await
190203
}
191204

192205
/// Calculates the permissions of the message author in the current channel.

src/model/channel/thread.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use super::*;
22
#[cfg(feature = "model")]
33
use crate::builder::{CreateMessage, EditThread};
4+
#[cfg(feature = "model")]
5+
use crate::http::CacheHttp;
46
use crate::internal::prelude::*;
57
use crate::model::utils::is_false;
68

@@ -42,6 +44,57 @@ impl ThreadId {
4244

4345
#[cfg(feature = "model")]
4446
impl ThreadId {
47+
/// Fetches a thread from the cache, falling back to HTTP/temp cache.
48+
///
49+
/// It is highly recommended to pass the `guild_id` parameter as otherwise this may perform many
50+
/// HTTP requests.
51+
///
52+
/// # Errors
53+
///
54+
/// Errors if the HTTP fallback fails, or if the channel does not come from the guild passed.
55+
pub async fn to_thread(
56+
self,
57+
cache_http: impl CacheHttp,
58+
guild_id: Option<GuildId>,
59+
) -> Result<GuildThread> {
60+
#[cfg(feature = "cache")]
61+
if let Some(cache) = cache_http.cache() {
62+
if let Some(guild_id) = guild_id {
63+
if let Some(guild) = cache.guild(guild_id) {
64+
if let Some(thread) = guild.threads.get(&self) {
65+
return Ok(thread.clone());
66+
}
67+
}
68+
}
69+
70+
#[cfg(feature = "temp_cache")]
71+
if let Some(temp_thread) = cache.temp_threads.get(&self) {
72+
if guild_id.is_some_and(|id| temp_thread.base.guild_id != id) {
73+
return Err(Error::Model(ModelError::ChannelNotFound));
74+
}
75+
76+
return Ok(GuildThread::clone(&temp_thread));
77+
}
78+
}
79+
80+
let channel = cache_http.http().get_channel(self.widen()).await?;
81+
let guild_thread = channel.thread().ok_or(ModelError::InvalidChannelType)?;
82+
83+
#[cfg(all(feature = "cache", feature = "temp_cache"))]
84+
if let Some(cache) = cache_http.cache() {
85+
use crate::cache::wrappers::MaybeOwnedArc;
86+
87+
let cached_thread = MaybeOwnedArc::new(guild_thread.clone());
88+
cache.temp_threads.insert(self, cached_thread);
89+
}
90+
91+
if guild_id.is_some_and(|id| guild_thread.base.guild_id != id) {
92+
return Err(Error::Model(ModelError::ChannelNotFound));
93+
}
94+
95+
Ok(guild_thread)
96+
}
97+
4598
/// Gets the thread members, if this channel is a thread.
4699
///
47100
/// # Errors

0 commit comments

Comments
 (0)