Skip to content
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

Add missing forum fields to guild channel #2298

Merged
merged 2 commits into from
Dec 4, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
6 changes: 3 additions & 3 deletions src/cache/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl CacheUpdate for ChannelCreateEvent {
.get_mut(&guild_id)
.and_then(|mut g| g.channels.insert(channel_id, self.channel.clone()));

cache.channels.insert(channel_id, channel.clone());
cache.channels.insert(channel_id, *channel.clone());

old_channel
},
Expand Down Expand Up @@ -130,7 +130,7 @@ impl CacheUpdate for ChannelUpdateEvent {
Channel::Guild(ref channel) => {
let (guild_id, channel_id) = (channel.guild_id, channel.id);

cache.channels.insert(channel_id, channel.clone());
cache.channels.insert(channel_id, *channel.clone());

cache
.guilds
Expand Down Expand Up @@ -194,7 +194,7 @@ impl CacheUpdate for GuildCreateEvent {

for pair in guild.channels.clone() {
if let Channel::Guild(channel) = pair.1 {
cache.channels.insert(pair.0, channel);
cache.channels.insert(pair.0, *channel);
}
}

Expand Down
17 changes: 12 additions & 5 deletions src/cache/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,13 +361,13 @@ impl Cache {
fn _channel(&self, id: ChannelId) -> Option<Channel> {
if let Some(channel) = self.channels.get(&id) {
let channel = channel.clone();
return Some(Channel::Guild(channel));
return Some(Channel::Guild(Box::new(channel)));
}

#[cfg(feature = "temp_cache")]
{
if let Some(channel) = self.temp_channels.get(&id) {
return Some(Channel::Guild(channel));
return Some(Channel::Guild(Box::new(channel)));
}
}

Expand Down Expand Up @@ -699,7 +699,7 @@ impl Cache {
g.channels
.iter()
.filter_map(|c| match c.1 {
Channel::Guild(channel) => Some((channel.id, channel.clone())),
Channel::Guild(channel) => Some((channel.id, *channel.clone())),
_ => None,
})
.collect()
Expand Down Expand Up @@ -1120,7 +1120,7 @@ mod test {
assert!(!channel.contains_key(&MessageId(3)));
}

let channel = Channel::Guild(GuildChannel {
let channel = Channel::Guild(Box::new(GuildChannel {
id: event.message.channel_id,
bitrate: None,
parent_id: None,
Expand All @@ -1142,7 +1142,14 @@ mod test {
thread_metadata: None,
member: None,
default_auto_archive_duration: None,
});
flags: ChannelFlags::empty(),
total_message_sent: None,
available_tags: Vec::new(),
applied_tags: Vec::new(),
default_reaction_emoji: None,
default_thread_rate_limit_per_user: None,
default_sort_order: SortOrder::Unknown,
}));

// Add a channel delete event to the cache, the cached messages for that
// channel should now be gone.
Expand Down
2 changes: 1 addition & 1 deletion src/model/channel/channel_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ impl ChannelId {
{
if let Some(cache) = cache_http.cache() {
if let Channel::Guild(guild_channel) = &channel {
cache.temp_channels.insert(guild_channel.id, guild_channel.clone());
cache.temp_channels.insert(guild_channel.id, *guild_channel.clone());
}
}
}
Expand Down
30 changes: 29 additions & 1 deletion src/model/channel/guild_channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ pub struct GuildChannel {
pub position: i64,
/// The topic of the channel.
///
/// **Note**: This is only available for text and stage channels.
/// **Note**: This is only available for text, forum and stage channels.
pub topic: Option<String>,
/// The maximum number of members allowed in the channel.
///
Expand Down Expand Up @@ -149,6 +149,34 @@ pub struct GuildChannel {
///
/// **Note**: It can currently only be set to 60, 1440, 4320, 10080.
pub default_auto_archive_duration: Option<u64>,
/// Extra information about the channel
///
/// **Note**: This is only available in forum channels.
pub flags: ChannelFlags,
/// The number of messages ever sent in a thread, it's similar to `message_count`
/// on message creation, but will not decrement the number when a message is deleted.
pub total_message_sent: Option<u64>,
/// The set of available tags.
///
/// **Note**: This is only available in forum channels.
pub available_tags: Vec<ForumTag>,
/// The set of applied tags.
///
/// **Note**: This is only available in a thread in a forum.
pub applied_tags: Vec<ForumTagId>,
/// The emoji to show in the add reaction button
///
/// **Note**: This is only available in a forum.
pub default_reaction_emoji: Option<DefaultReaction>,
/// The initial `rate_limit_per_user` to set on newly created threads in a channel.
/// This field is copied to the thread at creation time and does not live update.
///
/// **Note**: This is only available in a forum or text channel.
pub default_thread_rate_limit_per_user: Option<u64>,
/// The default sort order type used to order posts
///
/// **Note**: This is only available in a forum.
pub default_sort_order: SortOrder,
}

#[cfg(feature = "model")]
Expand Down
87 changes: 83 additions & 4 deletions src/model/channel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ pub enum Channel {
/// [voice]: ChannelType::Voice
/// [stage]: ChannelType::Stage
/// [directory]: ChannelType::Directory
Guild(GuildChannel),
Guild(Box<GuildChannel>),
/// A private channel to another [`User`]. No other users may access the
/// channel. For multi-user "private channels", use a group.
Private(PrivateChannel),
Expand Down Expand Up @@ -87,7 +87,7 @@ impl Channel {
#[must_use]
pub fn guild(self) -> Option<GuildChannel> {
match self {
Self::Guild(lock) => Some(lock),
Self::Guild(lock) => Some(*lock),
_ => None,
}
}
Expand Down Expand Up @@ -240,6 +240,7 @@ impl<'de> Deserialize<'de> for Channel {

match kind {
0 | 2 | 5 | 10 | 11 | 12 | 13 | 14 | 15 => from_value::<GuildChannel>(Value::from(v))
.map(Box::new)
.map(Channel::Guild)
.map_err(DeError::custom),
1 => from_value::<PrivateChannel>(Value::from(v))
Expand Down Expand Up @@ -449,7 +450,7 @@ pub enum VideoQualityMode {
}

enum_number!(VideoQualityMode {
Auto,
Auto
Full
});

Expand Down Expand Up @@ -539,6 +540,13 @@ mod test {
thread_metadata: None,
member: None,
default_auto_archive_duration: None,
applied_tags: Vec::new(),
flags: ChannelFlags::empty(),
total_message_sent: None,
available_tags: Vec::new(),
default_reaction_emoji: None,
default_thread_rate_limit_per_user: None,
default_sort_order: SortOrder::Unknown,
}
}

Expand Down Expand Up @@ -585,7 +593,7 @@ mod test {
channel.nsfw = false;
assert!(!channel.is_nsfw());

let channel = Channel::Guild(channel);
let channel = Channel::Guild(Box::new(channel));
assert!(!channel.is_nsfw());

let private_channel = private_channel();
Expand Down Expand Up @@ -631,3 +639,74 @@ impl FromStrAndCache for Channel {
}
}
}

/// An object that represents a tag that is able to be applied to a thread in a `GUILD_FORUM` channel.
///
/// See [Discord docs](https://discord.com/developers/docs/resources/channel#forum-tag-object)
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ForumTag {
/// The id of the tag.
pub id: ForumTagId,
/// The name of the tag (0-20 characters).
pub name: String,
/// Whether this tag can only be added to or removed from threads by a member with the MANAGE_THREADS permission.
pub moderated: bool,
/// The id of a guild's custom emoji.
///
/// **Note**: At most one of `emoji_id` and `emoji_name` may be set.
pub emoji_id: Option<EmojiId>,
/// The unicode character of the emoji.
///
/// **Note**: At most one of `emoji_id` and `emoji_name` may be set.
pub emoji_name: Option<String>,
}

/// An object that specifies the emoji to use as the default way to react to a forum post.
///
/// See [Discord docs](https://discord.com/developers/docs/resources/channel#forum-tag-object)
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct DefaultReaction {
/// The id of a guild's custom emoji.
///
/// **Note**: At most one of `emoji_id` and `emoji_name` may be set.
pub emoji_id: Option<EmojiId>,
/// The unicode character of the emoji.
///
/// **Note**: At most one of `emoji_id` and `emoji_name` may be set.
pub emoji_name: Option<String>,
}

/// The sort order for threads in a forum.
///
/// [Discord docs](https://discord.com/developers/docs/resources/channel#channel-object-sort-order-types).
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
#[non_exhaustive]
pub enum SortOrder {
/// Sort forum posts by activity.
LatestActivity = 0,
/// Sort forum posts by creation time (from most recent to oldest).
CreationDate = 2,
/// No sort order has been set.
Unknown = !0,
}

enum_number!(SortOrder {
LatestActivity
CreationDate
});

bitflags! {
/// Describes extra features of the channel.
///
/// [Discord docs](https://discord.com/developers/docs/resources/channel#channel-object-channel-flags).
#[derive(Default)]
pub struct ChannelFlags: u64 {
/// This thread is pinned to the top of its parent GUILD_FORUM channel
const PINNED = 1 << 1;
/// Whether a tag is required to be specified when creating a
/// thread in a GUILD_FORUM channel. Tags are specified in the applied_tags field.
const REQUIRE_TAG = 1 << 4;
}
}
2 changes: 1 addition & 1 deletion src/model/guild/member.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ impl Member {
for channel in guild.channels.values() {
if let Channel::Guild(channel) = channel {
if guild.user_permissions_in(channel, member).ok()?.view_channel() {
return Some(channel.clone());
return Some(*channel.clone());
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/model/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,12 @@ pub struct TargetId(#[serde(with = "snowflake")] pub u64);
)]
pub struct StageInstanceId(#[serde(with = "snowflake")] pub u64);

/// An identifier for a forum tag.
#[derive(
Copy, Clone, Default, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Deserialize, Serialize,
)]
pub struct ForumTagId(#[serde(with = "snowflake")] pub u64);

id_u64! {
AttachmentId;
ApplicationId;
Expand All @@ -249,6 +255,7 @@ id_u64! {
TargetId;
StageInstanceId;
RuleId;
ForumTagId;
}

/// Used with `#[serde(with|deserialize_with|serialize_with)]`
Expand Down
11 changes: 9 additions & 2 deletions src/model/mention.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ mod test {

#[test]
fn test_mention() {
let channel = Channel::Guild(GuildChannel {
let channel = Channel::Guild(Box::new(GuildChannel {
bitrate: None,
parent_id: None,
guild_id: GuildId(1),
Expand All @@ -231,7 +231,14 @@ mod test {
thread_metadata: None,
member: None,
default_auto_archive_duration: None,
});
flags: ChannelFlags::empty(),
total_message_sent: None,
available_tags: Vec::new(),
applied_tags: Vec::new(),
default_reaction_emoji: None,
default_thread_rate_limit_per_user: None,
default_sort_order: SortOrder::Unknown,
}));
let emoji = Emoji {
animated: false,
available: true,
Expand Down
6 changes: 3 additions & 3 deletions src/utils/argument_convert/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,15 @@ async fn lookup_channel_global(
None
}
}) {
return Ok(Channel::Guild(channel));
return Ok(Channel::Guild(Box::new(channel)));
}

if let Some(guild_id) = guild_id {
let channels = ctx.http.get_channels(guild_id.0).await.map_err(ChannelParseError::Http)?;
if let Some(channel) =
channels.into_iter().find(|channel| channel.name.eq_ignore_ascii_case(s))
{
return Ok(Channel::Guild(channel));
return Ok(Channel::Guild(Box::new(channel)));
}
}

Expand Down Expand Up @@ -155,7 +155,7 @@ impl ArgumentConvert for GuildChannel {
s: &str,
) -> Result<Self, Self::Err> {
match Channel::convert(ctx, guild_id, channel_id, s).await {
Ok(Channel::Guild(channel)) => Ok(channel),
Ok(Channel::Guild(channel)) => Ok(*channel),
Ok(_) => Err(GuildChannelParseError::NotAGuildChannel),
Err(ChannelParseError::Http(e)) => Err(GuildChannelParseError::Http(e)),
Err(ChannelParseError::NotFoundOrMalformed) => {
Expand Down
7 changes: 7 additions & 0 deletions src/utils/content_safe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,13 @@ mod tests {
thread_metadata: None,
member: None,
default_auto_archive_duration: None,
flags: ChannelFlags::empty(),
total_message_sent: None,
available_tags: Vec::new(),
applied_tags: Vec::new(),
default_reaction_emoji: None,
default_thread_rate_limit_per_user: None,
default_sort_order: SortOrder::Unknown,
};

let cache = Arc::new(Cache::default());
Expand Down