pub mod sticker;
mod activity;
mod activity_type;
mod application;
mod flags;
mod kind;
mod mention;
mod reaction;
mod reference;
pub use self::{
activity::MessageActivity, activity_type::MessageActivityType, application::MessageApplication,
flags::MessageFlags, kind::MessageType, mention::Mention, reaction::MessageReaction,
reference::MessageReference, sticker::Sticker,
};
use crate::{
channel::{embed::Embed, Attachment, ChannelMention},
guild::PartialMember,
id::{ChannelId, GuildId, MessageId, RoleId, WebhookId},
user::User,
};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct Message {
#[serde(skip_serializing_if = "Option::is_none")]
pub activity: Option<MessageActivity>,
#[serde(skip_serializing_if = "Option::is_none")]
pub application: Option<MessageApplication>,
pub attachments: Vec<Attachment>,
pub author: User,
pub channel_id: ChannelId,
pub content: String,
pub edited_timestamp: Option<String>,
pub embeds: Vec<Embed>,
#[serde(skip_serializing_if = "Option::is_none")]
pub flags: Option<MessageFlags>,
#[serde(skip_serializing_if = "Option::is_none")]
pub guild_id: Option<GuildId>,
pub id: MessageId,
#[serde(rename = "type")]
pub kind: MessageType,
#[serde(skip_serializing_if = "Option::is_none")]
pub member: Option<PartialMember>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub mention_channels: Vec<ChannelMention>,
pub mention_everyone: bool,
pub mention_roles: Vec<RoleId>,
pub mentions: Vec<Mention>,
pub pinned: bool,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub reactions: Vec<MessageReaction>,
#[serde(rename = "message_reference", skip_serializing_if = "Option::is_none")]
pub reference: Option<MessageReference>,
#[serde(skip_serializing_if = "Option::is_none")]
pub referenced_message: Option<Box<Message>>,
#[serde(default)]
pub stickers: Vec<Sticker>,
pub timestamp: String,
pub tts: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub webhook_id: Option<WebhookId>,
}
#[cfg(test)]
mod tests {
use super::{
sticker::{Sticker, StickerFormatType, StickerId, StickerPackId},
ChannelMention, Message, MessageActivity, MessageActivityType, MessageApplication,
MessageFlags, MessageReaction, MessageReference, MessageType, WebhookId,
};
use crate::{
channel::{ChannelType, ReactionType},
guild::PartialMember,
id::{ApplicationId, ChannelId, GuildId, MessageId, UserId},
user::User,
};
use serde_test::Token;
#[allow(clippy::too_many_lines)]
#[test]
fn test_message_deserialization() {
let value = Message {
activity: None,
application: None,
attachments: Vec::new(),
author: User {
avatar: Some("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".to_owned()),
bot: false,
discriminator: "0001".to_owned(),
email: None,
flags: None,
id: UserId(3),
locale: None,
mfa_enabled: None,
name: "test".to_owned(),
premium_type: None,
public_flags: None,
system: None,
verified: None,
},
channel_id: ChannelId(2),
content: "ping".to_owned(),
edited_timestamp: None,
embeds: Vec::new(),
flags: Some(MessageFlags::empty()),
guild_id: Some(GuildId(1)),
id: MessageId(4),
kind: MessageType::Regular,
member: Some(PartialMember {
deaf: false,
joined_at: Some("2020-01-01T00:00:00.000000+00:00".to_owned()),
mute: false,
nick: Some("member nick".to_owned()),
premium_since: None,
roles: Vec::new(),
}),
mention_channels: Vec::new(),
mention_everyone: false,
mention_roles: Vec::new(),
mentions: Vec::new(),
pinned: false,
reactions: Vec::new(),
reference: None,
stickers: vec![Sticker {
asset: "foo1".to_owned(),
description: "foo2".to_owned(),
format_type: StickerFormatType::Png,
id: StickerId(1),
name: "sticker name".to_owned(),
pack_id: StickerPackId(2),
preview_asset: None,
tags: Some("foo,bar,baz".to_owned()),
}],
referenced_message: None,
timestamp: "2020-02-02T02:02:02.020000+00:00".to_owned(),
tts: false,
webhook_id: None,
};
serde_test::assert_tokens(
&value,
&[
Token::Struct {
name: "Message",
len: 18,
},
Token::Str("attachments"),
Token::Seq { len: Some(0) },
Token::SeqEnd,
Token::Str("author"),
Token::Struct {
name: "User",
len: 5,
},
Token::Str("avatar"),
Token::Some,
Token::Str("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
Token::Str("bot"),
Token::Bool(false),
Token::Str("discriminator"),
Token::Str("0001"),
Token::Str("id"),
Token::NewtypeStruct { name: "UserId" },
Token::Str("3"),
Token::Str("username"),
Token::Str("test"),
Token::StructEnd,
Token::Str("channel_id"),
Token::NewtypeStruct { name: "ChannelId" },
Token::Str("2"),
Token::Str("content"),
Token::Str("ping"),
Token::Str("edited_timestamp"),
Token::None,
Token::Str("embeds"),
Token::Seq { len: Some(0) },
Token::SeqEnd,
Token::Str("flags"),
Token::Some,
Token::U64(0),
Token::Str("guild_id"),
Token::Some,
Token::NewtypeStruct { name: "GuildId" },
Token::Str("1"),
Token::Str("id"),
Token::NewtypeStruct { name: "MessageId" },
Token::Str("4"),
Token::Str("type"),
Token::U8(0),
Token::Str("member"),
Token::Some,
Token::Struct {
name: "PartialMember",
len: 5,
},
Token::Str("deaf"),
Token::Bool(false),
Token::Str("joined_at"),
Token::Some,
Token::Str("2020-01-01T00:00:00.000000+00:00"),
Token::Str("mute"),
Token::Bool(false),
Token::Str("nick"),
Token::Some,
Token::Str("member nick"),
Token::Str("roles"),
Token::Seq { len: Some(0) },
Token::SeqEnd,
Token::StructEnd,
Token::Str("mention_everyone"),
Token::Bool(false),
Token::Str("mention_roles"),
Token::Seq { len: Some(0) },
Token::SeqEnd,
Token::Str("mentions"),
Token::Seq { len: Some(0) },
Token::SeqEnd,
Token::Str("pinned"),
Token::Bool(false),
Token::Str("stickers"),
Token::Seq { len: Some(1) },
Token::Struct {
name: "Sticker",
len: 8,
},
Token::Str("asset"),
Token::Str("foo1"),
Token::Str("description"),
Token::Str("foo2"),
Token::Str("format_type"),
Token::U8(1),
Token::Str("id"),
Token::NewtypeStruct { name: "StickerId" },
Token::Str("1"),
Token::Str("name"),
Token::Str("sticker name"),
Token::Str("pack_id"),
Token::NewtypeStruct {
name: "StickerPackId",
},
Token::Str("2"),
Token::Str("preview_asset"),
Token::None,
Token::Str("tags"),
Token::Some,
Token::Str("foo,bar,baz"),
Token::StructEnd,
Token::SeqEnd,
Token::Str("timestamp"),
Token::Str("2020-02-02T02:02:02.020000+00:00"),
Token::Str("tts"),
Token::Bool(false),
Token::StructEnd,
],
);
}
#[allow(clippy::too_many_lines)]
#[test]
fn test_message_deserialization_complete() {
let value = Message {
activity: Some(MessageActivity {
kind: MessageActivityType::Join,
party_id: None,
}),
application: Some(MessageApplication {
cover_image: Some("cover".to_owned()),
description: "a description".to_owned(),
icon: Some("an icon".to_owned()),
id: ApplicationId(1),
name: "application".to_owned(),
}),
attachments: Vec::new(),
author: User {
avatar: Some("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".to_owned()),
bot: false,
discriminator: "0001".to_owned(),
email: None,
flags: None,
id: UserId(3),
locale: None,
mfa_enabled: None,
name: "test".to_owned(),
premium_type: None,
public_flags: None,
system: None,
verified: None,
},
channel_id: ChannelId(2),
content: "ping".to_owned(),
edited_timestamp: Some("123".to_owned()),
embeds: Vec::new(),
flags: Some(MessageFlags::empty()),
guild_id: Some(GuildId(1)),
id: MessageId(4),
kind: MessageType::Regular,
member: Some(PartialMember {
deaf: false,
joined_at: Some("2020-01-01T00:00:00.000000+00:00".to_owned()),
mute: false,
nick: Some("member nick".to_owned()),
premium_since: None,
roles: Vec::new(),
}),
mention_channels: vec![ChannelMention {
guild_id: GuildId(1),
id: ChannelId(2),
kind: ChannelType::GuildText,
name: "channel".to_owned(),
}],
mention_everyone: false,
mention_roles: Vec::new(),
mentions: Vec::new(),
pinned: false,
reactions: vec![MessageReaction {
count: 7,
emoji: ReactionType::Unicode {
name: "a".to_owned(),
},
me: true,
}],
reference: Some(MessageReference {
channel_id: Some(ChannelId(1)),
guild_id: None,
message_id: None,
}),
stickers: vec![Sticker {
asset: "foo1".to_owned(),
description: "foo2".to_owned(),
format_type: StickerFormatType::Png,
id: StickerId(1),
name: "sticker name".to_owned(),
pack_id: StickerPackId(2),
preview_asset: None,
tags: Some("foo,bar,baz".to_owned()),
}],
referenced_message: None,
timestamp: "2020-02-02T02:02:02.020000+00:00".to_owned(),
tts: false,
webhook_id: Some(WebhookId(1)),
};
serde_test::assert_tokens(
&value,
&[
Token::Struct {
name: "Message",
len: 24,
},
Token::Str("activity"),
Token::Some,
Token::Struct {
name: "MessageActivity",
len: 1,
},
Token::Str("type"),
Token::U8(1),
Token::StructEnd,
Token::Str("application"),
Token::Some,
Token::Struct {
name: "MessageApplication",
len: 5,
},
Token::Str("cover_image"),
Token::Some,
Token::Str("cover"),
Token::Str("description"),
Token::Str("a description"),
Token::Str("icon"),
Token::Some,
Token::Str("an icon"),
Token::Str("id"),
Token::NewtypeStruct {
name: "ApplicationId",
},
Token::Str("1"),
Token::Str("name"),
Token::Str("application"),
Token::StructEnd,
Token::Str("attachments"),
Token::Seq { len: Some(0) },
Token::SeqEnd,
Token::Str("author"),
Token::Struct {
name: "User",
len: 5,
},
Token::Str("avatar"),
Token::Some,
Token::Str("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
Token::Str("bot"),
Token::Bool(false),
Token::Str("discriminator"),
Token::Str("0001"),
Token::Str("id"),
Token::NewtypeStruct { name: "UserId" },
Token::Str("3"),
Token::Str("username"),
Token::Str("test"),
Token::StructEnd,
Token::Str("channel_id"),
Token::NewtypeStruct { name: "ChannelId" },
Token::Str("2"),
Token::Str("content"),
Token::Str("ping"),
Token::Str("edited_timestamp"),
Token::Some,
Token::Str("123"),
Token::Str("embeds"),
Token::Seq { len: Some(0) },
Token::SeqEnd,
Token::Str("flags"),
Token::Some,
Token::U64(0),
Token::Str("guild_id"),
Token::Some,
Token::NewtypeStruct { name: "GuildId" },
Token::Str("1"),
Token::Str("id"),
Token::NewtypeStruct { name: "MessageId" },
Token::Str("4"),
Token::Str("type"),
Token::U8(0),
Token::Str("member"),
Token::Some,
Token::Struct {
name: "PartialMember",
len: 5,
},
Token::Str("deaf"),
Token::Bool(false),
Token::Str("joined_at"),
Token::Some,
Token::Str("2020-01-01T00:00:00.000000+00:00"),
Token::Str("mute"),
Token::Bool(false),
Token::Str("nick"),
Token::Some,
Token::Str("member nick"),
Token::Str("roles"),
Token::Seq { len: Some(0) },
Token::SeqEnd,
Token::StructEnd,
Token::Str("mention_channels"),
Token::Seq { len: Some(1) },
Token::Struct {
name: "ChannelMention",
len: 4,
},
Token::Str("guild_id"),
Token::NewtypeStruct { name: "GuildId" },
Token::Str("1"),
Token::Str("id"),
Token::NewtypeStruct { name: "ChannelId" },
Token::Str("2"),
Token::Str("type"),
Token::U8(0),
Token::Str("name"),
Token::Str("channel"),
Token::StructEnd,
Token::SeqEnd,
Token::Str("mention_everyone"),
Token::Bool(false),
Token::Str("mention_roles"),
Token::Seq { len: Some(0) },
Token::SeqEnd,
Token::Str("mentions"),
Token::Seq { len: Some(0) },
Token::SeqEnd,
Token::Str("pinned"),
Token::Bool(false),
Token::Str("reactions"),
Token::Seq { len: Some(1) },
Token::Struct {
name: "MessageReaction",
len: 3,
},
Token::Str("count"),
Token::U64(7),
Token::Str("emoji"),
Token::Struct {
name: "ReactionType",
len: 1,
},
Token::Str("name"),
Token::Str("a"),
Token::StructEnd,
Token::Str("me"),
Token::Bool(true),
Token::StructEnd,
Token::SeqEnd,
Token::Str("message_reference"),
Token::Some,
Token::Struct {
name: "MessageReference",
len: 1,
},
Token::Str("channel_id"),
Token::Some,
Token::NewtypeStruct { name: "ChannelId" },
Token::Str("1"),
Token::StructEnd,
Token::Str("stickers"),
Token::Seq { len: Some(1) },
Token::Struct {
name: "Sticker",
len: 8,
},
Token::Str("asset"),
Token::Str("foo1"),
Token::Str("description"),
Token::Str("foo2"),
Token::Str("format_type"),
Token::U8(1),
Token::Str("id"),
Token::NewtypeStruct { name: "StickerId" },
Token::Str("1"),
Token::Str("name"),
Token::Str("sticker name"),
Token::Str("pack_id"),
Token::NewtypeStruct {
name: "StickerPackId",
},
Token::Str("2"),
Token::Str("preview_asset"),
Token::None,
Token::Str("tags"),
Token::Some,
Token::Str("foo,bar,baz"),
Token::StructEnd,
Token::SeqEnd,
Token::Str("timestamp"),
Token::Str("2020-02-02T02:02:02.020000+00:00"),
Token::Str("tts"),
Token::Bool(false),
Token::Str("webhook_id"),
Token::Some,
Token::NewtypeStruct { name: "WebhookId" },
Token::Str("1"),
Token::StructEnd,
],
);
}
}