titanium_model/
message.rs

1use crate::channel::{Channel, ChannelMention};
2use crate::component::Component;
3use crate::member::{Emoji, GuildMember};
4use crate::snowflake::Snowflake;
5use crate::user::User;
6use crate::TitanString;
7use serde::{Deserialize, Serialize};
8
9// ============================================================================
10// Poll Types (merged from poll.rs)
11// ============================================================================
12
13/// A poll object.
14#[derive(Debug, Clone, Deserialize, Serialize)]
15pub struct Poll<'a> {
16    /// The question of the poll.
17    pub question: PollMedia<'a>,
18
19    /// Each of the answers available in the poll.
20    pub answers: Vec<PollAnswer<'a>>,
21
22    /// The expiration date of the poll.
23    #[serde(default)]
24    pub expiry: Option<TitanString<'a>>,
25
26    /// Whether the poll allows multiple selections.
27    #[serde(default)]
28    pub allow_multiselect: bool,
29
30    /// The layout type of the poll.
31    #[serde(default)]
32    pub layout_type: Option<u8>,
33
34    /// The results of the poll.
35    #[serde(default)]
36    pub results: Option<PollResults>,
37}
38
39/// A poll media object (question text/emoji).
40#[derive(Debug, Clone, Deserialize, Serialize)]
41pub struct PollMedia<'a> {
42    /// The text of the field.
43    #[serde(default)]
44    pub text: Option<TitanString<'a>>,
45
46    /// The emoji of the field.
47    #[serde(default)]
48    pub emoji: Option<Emoji<'a>>,
49}
50
51/// A poll answer object.
52#[derive(Debug, Clone, Deserialize, Serialize)]
53pub struct PollAnswer<'a> {
54    /// The ID of the answer.
55    #[serde(default)]
56    pub answer_id: Option<u32>,
57
58    /// The data of the answer.
59    pub poll_media: PollMedia<'a>,
60}
61
62/// The results of a poll.
63#[derive(Debug, Clone, Deserialize, Serialize)]
64pub struct PollResults {
65    /// Whether the poll is finalized.
66    #[serde(default)]
67    pub is_finalized: bool,
68
69    /// The counts for each answer.
70    #[serde(default)]
71    pub answer_counts: Vec<PollAnswerCount>,
72}
73
74/// Count for a specific answer.
75#[derive(Debug, Clone, Deserialize, Serialize)]
76pub struct PollAnswerCount {
77    /// The ID of the answer.
78    pub id: u32,
79
80    /// The number of votes.
81    pub count: u32,
82
83    /// Whether the current user voted for this answer.
84    #[serde(default)]
85    pub me_voted: bool,
86}
87
88// ============================================================================
89// Message
90// ============================================================================
91
92/// Discord Message representation.
93#[derive(Debug, Clone, Deserialize, Serialize)]
94pub struct Message<'a> {
95    /// Message ID.
96    pub id: Snowflake,
97    /// Channel ID.
98    pub channel_id: Snowflake,
99    /// Author of the message.
100    pub author: User<'a>,
101    /// Message content.
102    pub content: TitanString<'a>,
103    /// When the message was sent (ISO8601 timestamp).
104    pub timestamp: TitanString<'a>,
105    /// When the message was edited (ISO8601 timestamp).
106    #[serde(default)]
107    pub edited_timestamp: Option<String>,
108    /// Whether this was a TTS message.
109    #[serde(default)]
110    pub tts: bool,
111    /// Whether this message mentions everyone.
112    #[serde(default)]
113    pub mention_everyone: bool,
114    /// Users mentioned in this message.
115    #[serde(default)]
116    pub mentions: smallvec::SmallVec<[User<'a>; 4]>,
117    /// Roles mentioned in this message.
118    #[serde(default)]
119    pub mention_roles: smallvec::SmallVec<[Snowflake; 4]>,
120    /// Channels mentioned in this message.
121    #[serde(default)]
122    pub mention_channels: smallvec::SmallVec<[ChannelMention; 2]>,
123    /// Attachments.
124    #[serde(default)]
125    pub attachments: smallvec::SmallVec<[Attachment<'a>; 4]>,
126    /// Embeds.
127    #[serde(default)]
128    pub embeds: smallvec::SmallVec<[Embed<'a>; 10]>,
129    /// Reactions.
130    #[serde(default)]
131    pub reactions: smallvec::SmallVec<[Reaction<'a>; 5]>,
132    /// Used for validating a message was sent.
133    #[serde(default)]
134    pub nonce: Option<crate::json::Value>,
135    /// Whether message is pinned.
136    #[serde(default)]
137    pub pinned: bool,
138    /// Webhook ID if sent by webhook.
139    #[serde(default)]
140    pub webhook_id: Option<Snowflake>,
141    /// Message type.
142    #[serde(rename = "type")]
143    pub message_type: u8,
144    /// Guild ID.
145    #[serde(default)]
146    pub guild_id: Option<Snowflake>,
147    /// Member properties for this message's author.
148    #[serde(default)]
149    pub member: Option<GuildMember<'a>>,
150    /// Message flags.
151    #[serde(default)]
152    pub flags: Option<u64>,
153    /// Reference data for replies/forwards.
154    #[serde(default)]
155    pub message_reference: Option<MessageReference>,
156    /// The message associated with the reference.
157    #[serde(default)]
158    pub referenced_message: Option<Box<Message<'a>>>,
159    /// Thread started from this message.
160    #[serde(default)]
161    pub thread: Option<Channel<'a>>,
162    /// Components (buttons, selects, etc.).
163    #[serde(default)]
164    pub components: smallvec::SmallVec<[Component<'a>; 5]>,
165    /// Sticker items.
166    #[serde(default)]
167    pub sticker_items: smallvec::SmallVec<[StickerItem; 3]>,
168    /// Poll object.
169    #[serde(default)]
170    pub poll: Option<Poll<'a>>,
171}
172
173/// An attachment on a message.
174#[derive(Debug, Clone, Deserialize, Serialize)]
175pub struct Attachment<'a> {
176    /// Attachment ID.
177    pub id: Snowflake,
178    /// Filename.
179    pub filename: TitanString<'a>,
180    /// Description.
181    #[serde(default)]
182    pub description: Option<TitanString<'a>>,
183    /// Media type.
184    #[serde(default)]
185    pub content_type: Option<String>,
186    /// Size in bytes.
187    pub size: u64,
188    /// Source URL.
189    pub url: TitanString<'a>,
190    /// Proxy URL.
191    pub proxy_url: TitanString<'a>,
192    /// Height (if image).
193    #[serde(default)]
194    pub height: Option<u32>,
195    /// Width (if image).
196    #[serde(default)]
197    pub width: Option<u32>,
198    /// Whether ephemeral.
199    #[serde(default)]
200    pub ephemeral: bool,
201    /// Duration in seconds (for voice messages).
202    #[serde(default)]
203    pub duration_secs: Option<f64>,
204    /// Waveform base64 (for voice messages).
205    #[serde(default)]
206    pub waveform: Option<String>,
207    /// Attachment flags.
208    #[serde(default)]
209    pub flags: Option<u64>,
210}
211
212/// An embed in a message.
213#[derive(Debug, Clone, Default, Deserialize, Serialize)]
214pub struct Embed<'a> {
215    /// Title.
216    #[serde(default)]
217    pub title: Option<TitanString<'a>>,
218    /// Type.
219    #[serde(default, rename = "type")]
220    pub embed_type: Option<TitanString<'a>>,
221    /// Description.
222    #[serde(default)]
223    pub description: Option<TitanString<'a>>,
224    /// URL.
225    #[serde(default)]
226    pub url: Option<TitanString<'a>>,
227    /// Timestamp.
228    #[serde(default)]
229    pub timestamp: Option<TitanString<'a>>,
230    /// Color.
231    #[serde(default)]
232    pub color: Option<u32>,
233    /// Footer.
234    #[serde(default)]
235    pub footer: Option<EmbedFooter<'a>>,
236    /// Image.
237    #[serde(default)]
238    pub image: Option<EmbedMedia<'a>>,
239    /// Thumbnail.
240    #[serde(default)]
241    pub thumbnail: Option<EmbedMedia<'a>>,
242    /// Video.
243    #[serde(default)]
244    pub video: Option<EmbedMedia<'a>>,
245    /// Provider.
246    #[serde(default)]
247    pub provider: Option<EmbedProvider<'a>>,
248    /// Author.
249    #[serde(default)]
250    pub author: Option<EmbedAuthor<'a>>,
251    /// Fields.
252    #[serde(default)]
253    pub fields: Vec<EmbedField<'a>>,
254}
255
256/// Embed footer.
257#[derive(Debug, Clone, Deserialize, Serialize)]
258pub struct EmbedFooter<'a> {
259    /// Footer text.
260    pub text: TitanString<'a>,
261    /// Icon URL.
262    #[serde(default)]
263    pub icon_url: Option<TitanString<'a>>,
264    /// Proxy icon URL.
265    #[serde(default)]
266    pub proxy_icon_url: Option<TitanString<'a>>,
267}
268
269/// Embed media (image, thumbnail, video).
270#[derive(Debug, Clone, Deserialize, Serialize)]
271pub struct EmbedMedia<'a> {
272    /// URL.
273    #[serde(default)]
274    pub url: Option<TitanString<'a>>,
275    /// Proxy URL.
276    #[serde(default)]
277    pub proxy_url: Option<TitanString<'a>>,
278    /// Height.
279    #[serde(default)]
280    pub height: Option<u32>,
281    /// Width.
282    #[serde(default)]
283    pub width: Option<u32>,
284}
285
286/// Embed provider.
287#[derive(Debug, Clone, Deserialize, Serialize)]
288pub struct EmbedProvider<'a> {
289    /// Provider name.
290    #[serde(default)]
291    pub name: Option<TitanString<'a>>,
292    /// Provider URL.
293    #[serde(default)]
294    pub url: Option<TitanString<'a>>,
295}
296
297/// Embed author.
298#[derive(Debug, Clone, Deserialize, Serialize)]
299pub struct EmbedAuthor<'a> {
300    /// Author name.
301    pub name: TitanString<'a>,
302    /// Author URL.
303    #[serde(default)]
304    pub url: Option<TitanString<'a>>,
305    /// Icon URL.
306    #[serde(default)]
307    pub icon_url: Option<TitanString<'a>>,
308    /// Proxy icon URL.
309    #[serde(default)]
310    pub proxy_icon_url: Option<TitanString<'a>>,
311}
312
313/// Embed field.
314#[derive(Debug, Clone, Deserialize, Serialize)]
315pub struct EmbedField<'a> {
316    /// Field name.
317    pub name: TitanString<'a>,
318    /// Field value.
319    pub value: TitanString<'a>,
320    /// Whether inline.
321    #[serde(default)]
322    pub inline: bool,
323}
324
325/// A reaction on a message.
326#[derive(Debug, Clone, Deserialize, Serialize)]
327pub struct Reaction<'a> {
328    /// Times this emoji has been used.
329    pub count: u32,
330    /// Reaction count details.
331    #[serde(default)]
332    pub count_details: Option<ReactionCountDetails>,
333    /// Whether current user reacted.
334    pub me: bool,
335    /// Whether current user super-reacted.
336    #[serde(default)]
337    pub me_burst: bool,
338    /// Emoji information.
339    pub emoji: crate::reaction::ReactionEmoji<'a>,
340    /// Colors for super-reaction.
341    #[serde(default)]
342    pub burst_colors: Vec<String>,
343}
344
345/// Reaction count details.
346#[derive(Debug, Clone, Deserialize, Serialize)]
347pub struct ReactionCountDetails {
348    /// Count of normal reactions.
349    pub burst: u32,
350    /// Count of super reactions.
351    pub normal: u32,
352}
353
354/// Message reference for replies/forwards.
355#[derive(Debug, Clone, Deserialize, Serialize)]
356pub struct MessageReference {
357    /// ID of the originating message.
358    #[serde(default)]
359    pub message_id: Option<Snowflake>,
360    /// ID of the originating channel.
361    #[serde(default)]
362    pub channel_id: Option<Snowflake>,
363    /// ID of the originating guild.
364    #[serde(default)]
365    pub guild_id: Option<Snowflake>,
366    /// Whether to fail if referenced message doesn't exist.
367    #[serde(default)]
368    pub fail_if_not_exists: Option<bool>,
369}
370
371/// A sticker item (partial sticker).
372#[derive(Debug, Clone, Deserialize, Serialize)]
373pub struct StickerItem {
374    /// Sticker ID.
375    pub id: Snowflake,
376    /// Sticker name.
377    pub name: String,
378    /// Sticker format type.
379    pub format_type: u8,
380}
381
382/// Message update event (partial message).
383#[derive(Debug, Clone, Deserialize, Serialize)]
384pub struct MessageUpdateEvent<'a> {
385    pub id: Snowflake,
386    pub channel_id: Snowflake,
387    #[serde(default)]
388    pub guild_id: Option<Snowflake>,
389    #[serde(default)]
390    pub content: Option<String>,
391    #[serde(default)]
392    pub author: Option<User<'a>>,
393    #[serde(default)]
394    pub edited_timestamp: Option<String>,
395}
396
397/// Message delete event.
398#[derive(Debug, Clone, Deserialize, Serialize)]
399pub struct MessageDeleteEvent {
400    pub id: Snowflake,
401    pub channel_id: Snowflake,
402    #[serde(default)]
403    pub guild_id: Option<Snowflake>,
404}
405
406/// Bulk message delete event.
407#[derive(Debug, Clone, Deserialize, Serialize)]
408pub struct MessageDeleteBulkEvent {
409    pub ids: Vec<Snowflake>,
410    pub channel_id: Snowflake,
411    #[serde(default)]
412    pub guild_id: Option<Snowflake>,
413}
414
415/// Typing start event.
416#[derive(Debug, Clone, Deserialize, Serialize)]
417pub struct TypingStartEvent<'a> {
418    pub channel_id: Snowflake,
419    #[serde(default)]
420    pub guild_id: Option<Snowflake>,
421    pub user_id: Snowflake,
422    pub timestamp: u64,
423    #[serde(default)]
424    pub member: Option<GuildMember<'a>>,
425}