twilight_model/guild/audit_log/
entry.rs

1use super::{AuditLogChange, AuditLogEventType, AuditLogOptionalEntryInfo};
2use crate::id::{
3    marker::{AuditLogEntryMarker, GenericMarker, GuildMarker, UserMarker},
4    Id,
5};
6use serde::{Deserialize, Serialize};
7
8/// Entry in an [`AuditLog`] possibly containing a number of detailed changes.
9///
10/// [`AuditLog`]: super::AuditLog
11#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
12pub struct AuditLogEntry {
13    /// Type of event to cause the entry.
14    pub action_type: AuditLogEventType,
15    /// List of changes included in the entry.
16    #[serde(default, skip_serializing_if = "Vec::is_empty")]
17    pub changes: Vec<AuditLogChange>,
18    /// ID of the server where the entry was added.
19    ///
20    /// This is **only** available when receiving the event in
21    /// [`GuildAuditLogEntryCreate`].
22    ///
23    /// [`GuildAuditLogEntryCreate`]: crate::gateway::payload::incoming::GuildAuditLogEntryCreate
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub guild_id: Option<Id<GuildMarker>>,
26    /// ID of the entire entry.
27    pub id: Id<AuditLogEntryMarker>,
28    /// Optional information about the entry.
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub options: Option<AuditLogOptionalEntryInfo>,
31    /// Optional application- or user-attached reason for the action that caused
32    /// the entry.
33    #[serde(skip_serializing_if = "Option::is_none")]
34    pub reason: Option<String>,
35    /// ID of the target entity.
36    pub target_id: Option<Id<GenericMarker>>,
37    /// ID of the [user] that performed the action.
38    ///
39    /// [user]: crate::user::User
40    pub user_id: Option<Id<UserMarker>>,
41}
42
43#[cfg(test)]
44mod tests {
45    use super::{
46        super::{AuditLogChange, AuditLogEventType},
47        AuditLogEntry,
48    };
49    use crate::{id::Id, test::image_hash};
50    use serde::{Deserialize, Serialize};
51    use serde_test::Token;
52    use static_assertions::{assert_fields, assert_impl_all};
53    use std::{fmt::Debug, hash::Hash};
54
55    assert_fields!(
56        AuditLogEntry: action_type,
57        changes,
58        id,
59        options,
60        reason,
61        target_id,
62        user_id
63    );
64    assert_impl_all!(
65        AuditLogEntry: Clone,
66        Debug,
67        Deserialize<'static>,
68        Eq,
69        Hash,
70        PartialEq,
71        Send,
72        Serialize,
73        Sync
74    );
75
76    /// Test the deserialization and serialization of an audit log entry.
77    #[test]
78    fn serde() {
79        let value = AuditLogEntry {
80            action_type: AuditLogEventType::GuildUpdate,
81            changes: Vec::from([AuditLogChange::IconHash {
82                new: None,
83                old: Some(image_hash::ICON),
84            }]),
85            guild_id: None,
86            id: Id::new(3),
87            options: None,
88            reason: Some("some reason".to_owned()),
89            target_id: Some(Id::new(2)),
90            user_id: Some(Id::new(1)),
91        };
92
93        serde_test::assert_tokens(
94            &value,
95            &[
96                Token::Struct {
97                    name: "AuditLogEntry",
98                    len: 6,
99                },
100                Token::Str("action_type"),
101                Token::U16(AuditLogEventType::GuildUpdate.into()),
102                Token::Str("changes"),
103                Token::Seq { len: Some(1) },
104                Token::Struct {
105                    name: "AuditLogChange",
106                    len: 2,
107                },
108                Token::Str("key"),
109                Token::Str("icon_hash"),
110                Token::Str("old_value"),
111                Token::Some,
112                Token::Str(image_hash::ICON_INPUT),
113                Token::StructEnd,
114                Token::SeqEnd,
115                Token::Str("id"),
116                Token::NewtypeStruct { name: "Id" },
117                Token::Str("3"),
118                Token::Str("reason"),
119                Token::Some,
120                Token::Str("some reason"),
121                Token::Str("target_id"),
122                Token::Some,
123                Token::NewtypeStruct { name: "Id" },
124                Token::Str("2"),
125                Token::Str("user_id"),
126                Token::Some,
127                Token::NewtypeStruct { name: "Id" },
128                Token::Str("1"),
129                Token::StructEnd,
130            ],
131        );
132    }
133}