Skip to content

Commit

Permalink
add missing fields to guild channel
Browse files Browse the repository at this point in the history
Added `flags`, `total_messages_sent`, `available_tags`, `applied_tags`,
`default_reaction_emoji`, `default_thread_rate_limit_per_user` and
`default_sort_order` fields to `GuildChannel`.
Added `ForumTag`, `ForumTagId`, `DefaultReaction` and `SortOrder`
objects.
Box the `Channel::Guild` variant to reduce enum size.
  • Loading branch information
Chronophylos committed Nov 22, 2022
1 parent 52aabb2 commit b94b0bf
Show file tree
Hide file tree
Showing 10 changed files with 155 additions and 20 deletions.
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

0 comments on commit b94b0bf

Please sign in to comment.