twilight_model/guild/audit_log/
change.rs

1use super::change_key::AuditLogChangeKey;
2use crate::{
3    application::command::permissions::GuildCommandPermissions,
4    channel::{
5        message::sticker::StickerFormatType, permission_overwrite::PermissionOverwrite,
6        stage_instance::PrivacyLevel, thread::AutoArchiveDuration,
7    },
8    guild::{
9        DefaultMessageNotificationLevel, ExplicitContentFilter, MfaLevel, NSFWLevel, Permissions,
10        VerificationLevel,
11    },
12    id::{
13        marker::{
14            ApplicationMarker, ChannelMarker, GenericMarker, GuildMarker, RoleMarker, UserMarker,
15        },
16        Id,
17    },
18    util::{ImageHash, Timestamp},
19};
20use serde::{Deserialize, Serialize};
21
22/// Minimal amount of information about an affected [role].
23///
24/// The following [`AuditLogChange`]s include this information:
25///
26/// - [`AuditLogChange::RoleAdded`]
27/// - [`AuditLogChange::RoleRemoved`]
28///
29/// [role]: super::super::Role
30#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
31pub struct AffectedRole {
32    /// ID of the role.
33    pub id: Id<RoleMarker>,
34    /// Name of the role.
35    pub name: String,
36}
37
38/// Value of a change which may be one of multiple types.
39#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
40#[serde(untagged)]
41pub enum AuditLogChangeTypeValue {
42    /// Value is an unsigned integer.
43    Unsigned(u64),
44    /// Value is a string.
45    String(String),
46}
47
48/// Individual change within an [`AuditLogEntry`].
49///
50/// [`AuditLogEntry`]: super::AuditLogEntry
51#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
52#[non_exhaustive]
53#[serde(rename_all = "snake_case", tag = "key")]
54pub enum AuditLogChange {
55    /// AFK channel ID was changed.
56    AfkChannelId {
57        /// New ID of the AFK channel.
58        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
59        new: Option<Id<ChannelMarker>>,
60        /// Old ID of the AFK channel.
61        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
62        old: Option<Id<ChannelMarker>>,
63    },
64    /// Timeout to cause a user to be moved to an AFK voice channel.
65    AfkTimeout {
66        /// New timeout, in seconds.
67        #[serde(rename = "new_value")]
68        new: u64,
69        /// Old timeout, in seconds.
70        #[serde(rename = "old_value")]
71        old: u64,
72    },
73    /// Allowed permissions of a permission overwrite target.
74    Allow {
75        /// New allowed permissions value.
76        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
77        new: Option<Permissions>,
78        /// Old allowed permissions value.
79        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
80        old: Option<Permissions>,
81    },
82    /// ID of an application.
83    ApplicationId {
84        /// Application's ID.
85        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
86        new: Option<Id<ApplicationMarker>>,
87        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
88        old: Option<Id<ApplicationMarker>>,
89    },
90    /// Thread is now archived/unarchived.
91    Archived {
92        /// Whether the thread is archived.
93        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
94        new: Option<bool>,
95        /// Previous state, if any.
96        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
97        old: Option<bool>,
98    },
99    /// Asset of a sticker.
100    Asset {
101        /// Empty string.
102        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
103        new: Option<String>,
104        /// Previous state, if any.
105        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
106        old: Option<String>,
107    },
108    /// Auto archive duration of a thread changed.
109    AutoArchiveDuration {
110        /// New auto archive duration.
111        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
112        new: Option<AutoArchiveDuration>,
113        /// Old auto archive duration.
114        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
115        old: Option<AutoArchiveDuration>,
116    },
117    /// Availability of a sticker.
118    Available {
119        /// New availability.
120        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
121        new: Option<bool>,
122        /// Old availability.
123        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
124        old: Option<bool>,
125    },
126    /// Hash of an avatar.
127    AvatarHash {
128        /// New hash of an avatar.
129        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
130        new: Option<ImageHash>,
131        /// Old hash of an avatar.
132        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
133        old: Option<ImageHash>,
134    },
135    /// Hash of a guild banner.
136    BannerHash {
137        /// New hash of a guild's banner.
138        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
139        new: Option<ImageHash>,
140        /// Old hash of a guild's banner.
141        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
142        old: Option<ImageHash>,
143    },
144    /// Bitrate of an audio channel.
145    Bitrate {
146        /// New bitrate.
147        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
148        new: Option<u64>,
149        /// Old bitrate.
150        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
151        old: Option<u64>,
152    },
153    /// Channel for an invite code.
154    ChannelId {
155        /// New invite's channel.
156        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
157        new: Option<Id<ChannelMarker>>,
158        /// Old invite's channel.
159        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
160        old: Option<Id<ChannelMarker>>,
161    },
162    /// Code of an invite.
163    Code {
164        /// New invite's code.
165        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
166        new: Option<String>,
167        /// Previous state, if any.
168        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
169        old: Option<String>,
170    },
171    /// Color of a role.
172    Color {
173        /// New role color.
174        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
175        new: Option<u64>,
176        /// Old role color.
177        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
178        old: Option<u64>,
179    },
180    /// Permissions for a command were updated
181    CommandId {
182        /// New command permissions.
183        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
184        new: Option<GuildCommandPermissions>,
185        /// Old command permissions.
186        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
187        old: Option<GuildCommandPermissions>,
188    },
189    /// Member timeout state changed.
190    CommunicationDisabledUntil {
191        /// New timeout timestamp.
192        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
193        new: Option<Timestamp>,
194        /// Old timeout timestamp.
195        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
196        old: Option<Timestamp>,
197    },
198    /// Whether a member is guild deafened.
199    Deaf {
200        /// Whether a member is now guild deafened.
201        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
202        new: Option<bool>,
203        /// Previous state, if any.
204        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
205        old: Option<bool>,
206    },
207    /// default auto archive duration for newly created threads changed.
208    DefaultAutoArchiveDuration {
209        /// New auto archive duration.
210        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
211        new: Option<AutoArchiveDuration>,
212        /// Old auto archive duration.
213        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
214        old: Option<AutoArchiveDuration>,
215    },
216    /// Default message notification level for a guild.
217    DefaultMessageNotifications {
218        /// New default message notification level.
219        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
220        new: Option<DefaultMessageNotificationLevel>,
221        /// Old default message notification level.
222        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
223        old: Option<DefaultMessageNotificationLevel>,
224    },
225    /// Denied permissions of a permission overwrite target.
226    Deny {
227        /// New denied permissions level.
228        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
229        new: Option<Permissions>,
230        /// Previous state, if any.
231        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
232        old: Option<Permissions>,
233    },
234    /// Description of a guild or sticker.
235    Description {
236        /// New guild description.
237        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
238        new: Option<String>,
239        /// Old guild description.
240        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
241        old: Option<String>,
242    },
243    /// Hash of a guild's discovery splash.
244    DiscoverySplashHash {
245        /// New discovery splash hash.
246        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
247        new: Option<ImageHash>,
248        /// Old discovery splash hash.
249        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
250        old: Option<ImageHash>,
251    },
252    /// Whether emoticons are enabled.
253    EnableEmoticons {
254        /// Whether emoticons are now enabled.
255        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
256        new: Option<bool>,
257        /// Whether emoticons were enabled.
258        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
259        old: Option<bool>,
260    },
261    /// Entity type of guild scheduled event was changed.
262    EntityType {
263        /// New entity type.
264        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
265        new: Option<u64>,
266        /// Previous state, if any.
267        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
268        old: Option<u64>,
269    },
270    /// Behavior of the expiration of an integration.
271    ExpireBehavior {
272        /// New expiration behavior.
273        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
274        new: Option<u64>,
275        /// Previous state, if any.
276        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
277        old: Option<u64>,
278    },
279    /// Grace period of the expiration of an integration.
280    ExpireGracePeriod {
281        /// New expiration grace period.
282        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
283        new: Option<u64>,
284        /// Previous state, if any.
285        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
286        old: Option<u64>,
287    },
288    /// Explicit content filter level of a guild.
289    ExplicitContentFilter {
290        /// New explicit content filter level.
291        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
292        new: Option<ExplicitContentFilter>,
293        /// Old explicit content filter level.
294        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
295        old: Option<ExplicitContentFilter>,
296    },
297    /// Format type of a sticker.
298    FormatType {
299        /// New format type of a sticker.
300        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
301        new: Option<StickerFormatType>,
302        /// Old format type of a sticker.
303        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
304        old: Option<StickerFormatType>,
305    },
306    /// Guild that a sticker is in.
307    GuildId {
308        /// New guild that a sticker is in.
309        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
310        new: Option<Id<GuildMarker>>,
311        /// Old guild that a sticker is in.
312        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
313        old: Option<Id<GuildMarker>>,
314    },
315    /// Whether a role is hoisted.
316    Hoist {
317        /// Whether a role is now hoisted.
318        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
319        new: Option<bool>,
320        /// Whether a role was hoisted.
321        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
322        old: Option<bool>,
323    },
324    /// Hash of a guild icon.
325    IconHash {
326        /// New hash of a guild's icon.
327        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
328        new: Option<ImageHash>,
329        /// Old hash of a guild's icon.
330        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
331        old: Option<ImageHash>,
332    },
333    /// ID of an entity.
334    Id {
335        /// New entity's ID.
336        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
337        new: Option<Id<GenericMarker>>,
338        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
339        old: Option<Id<GenericMarker>>,
340    },
341    /// Hash of a guild scheduled event cover.
342    ImageHash {
343        /// New hash of a guild's icon.
344        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
345        new: Option<ImageHash>,
346        /// Old hash of a guild's icon.
347        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
348        old: Option<ImageHash>,
349    },
350    /// Invitable state of a private thread.
351    Invitable {
352        /// New threads invitable state.
353        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
354        new: Option<bool>,
355        /// Old threads invitable state.
356        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
357        old: Option<bool>,
358    },
359    /// ID of the user who created an invite.
360    InviterId {
361        /// User ID.
362        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
363        new: Option<Id<UserMarker>>,
364        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
365        old: Option<Id<UserMarker>>,
366    },
367    /// Location for a scheduled event changed.
368    ///
369    /// Can be an [`Id<ChannelMarker>`] or a [`String`].
370    Location {
371        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
372        new: Option<String>,
373        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
374        old: Option<String>,
375    },
376    /// Thread was locked or unlocked.
377    Locked {
378        /// Whether the thread is now locked.
379        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
380        new: Option<bool>,
381        /// Previous state, if any.
382        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
383        old: Option<bool>,
384    },
385    /// Maximum age of an invite.
386    MaxAge {
387        /// New maximum age.
388        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
389        new: Option<u64>,
390        /// Previous state, if any.
391        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
392        old: Option<u64>,
393    },
394    /// Maximum uses of an invite.
395    MaxUses {
396        /// New maximum uses.
397        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
398        new: Option<u64>,
399        /// Previous state, if any.
400        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
401        old: Option<u64>,
402    },
403    /// Whether a role can be mentioned in a message.
404    Mentionable {
405        /// Whether a role is now mentionable.
406        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
407        new: Option<bool>,
408        /// Whether a role was mentionable.
409        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
410        old: Option<bool>,
411    },
412    /// Multi-Factor Authentication level required of a guild's moderators.
413    MfaLevel {
414        /// New MFA level of a guild.
415        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
416        new: Option<MfaLevel>,
417        /// Old MFA level of a guild.
418        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
419        old: Option<MfaLevel>,
420    },
421    /// Whether a user is guild muted.
422    Mute {
423        /// Whether a member is now muted.
424        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
425        new: Option<bool>,
426        /// Whether a member was muted.
427        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
428        old: Option<bool>,
429    },
430    /// Name of an entity such as a channel or role.
431    Name {
432        /// New entity name.
433        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
434        new: Option<String>,
435        /// Old entity name.
436        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
437        old: Option<String>,
438    },
439    /// Nickname of a member.
440    Nick {
441        /// New member nickname.
442        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
443        new: Option<String>,
444        /// Old member nickname.
445        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
446        old: Option<String>,
447    },
448    /// Whether a channel is NSFW.
449    Nsfw {
450        /// New state.
451        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
452        new: Option<bool>,
453        /// Previous state, if any.
454        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
455        old: Option<bool>,
456    },
457    /// NSFW level of a guild.
458    NsfwLevel {
459        /// New NSFW level.
460        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
461        new: Option<NSFWLevel>,
462        /// Old NSFW level.
463        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
464        old: Option<NSFWLevel>,
465    },
466    /// ID of the owner of a guild.
467    OwnerId {
468        /// New owner's ID.
469        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
470        new: Option<Id<UserMarker>>,
471        /// Old owner's ID.
472        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
473        old: Option<Id<UserMarker>>,
474    },
475    /// Permission overwrites on a channel changed.
476    PermissionOverwrites {
477        /// New set of overwrites.
478        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
479        new: Option<Vec<PermissionOverwrite>>,
480        /// Old set of overwrites.
481        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
482        old: Option<Vec<PermissionOverwrite>>,
483    },
484    /// Default permissions of a role.
485    Permissions {
486        /// New set of permissions.
487        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
488        new: Option<Permissions>,
489        /// Old set of permissions.
490        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
491        old: Option<Permissions>,
492    },
493    /// Position of an entity such as a channel or role.
494    Position {
495        /// New position value.
496        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
497        new: Option<u64>,
498        /// Old position value.
499        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
500        old: Option<u64>,
501    },
502    /// Preferred locale of a guild.
503    PreferredLocale {
504        /// New preferred locale.
505        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
506        new: Option<String>,
507        /// Old preferred locale.
508        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
509        old: Option<String>,
510    },
511    /// Privacy level of a stage instance.
512    PrivacyLevel {
513        /// New privacy level.
514        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
515        new: Option<PrivacyLevel>,
516        /// Old privacy level.
517        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
518        old: Option<PrivacyLevel>,
519    },
520    /// Number of days' worth of inactivity for a guild prune.
521    PruneDeleteDays {
522        /// Number of days.
523        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
524        new: Option<u64>,
525        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
526        old: Option<u64>,
527    },
528    /// ID of a guild's public updates channel.
529    PublicUpdatesChannelId {
530        /// New public updates channel ID.
531        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
532        new: Option<Id<ChannelMarker>>,
533        /// Old public updates channel ID.
534        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
535        old: Option<Id<ChannelMarker>>,
536    },
537    /// Ratelimit per user in a textual channel.
538    RateLimitPerUser {
539        /// New ratelimit, in seconds.
540        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
541        new: Option<u64>,
542        /// Old ratelimit, in seconds.
543        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
544        old: Option<u64>,
545    },
546    /// Region of a guild changed.
547    Region {
548        /// New region.
549        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
550        new: Option<String>,
551        /// Previous state, if any.
552        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
553        old: Option<String>,
554    },
555    /// Role was added to a user.
556    #[serde(rename = "$add")]
557    RoleAdded {
558        /// Minimal information about a added role.
559        #[serde(default, rename = "new_value", skip_serializing_if = "Vec::is_empty")]
560        new: Vec<AffectedRole>,
561        /// Previous state, if any.
562        #[serde(default, rename = "old_value", skip_serializing_if = "Vec::is_empty")]
563        old: Vec<AffectedRole>,
564    },
565    /// Role was removed from a user.
566    #[serde(rename = "$remove")]
567    RoleRemoved {
568        /// Minimal information about a removed role.
569        #[serde(default, rename = "new_value", skip_serializing_if = "Vec::is_empty")]
570        new: Vec<AffectedRole>,
571        /// Previous state, if any.
572        #[serde(default, rename = "old_value", skip_serializing_if = "Vec::is_empty")]
573        old: Vec<AffectedRole>,
574    },
575    /// Guild's rules channel.
576    RulesChannelId {
577        /// New rules channel.
578        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
579        new: Option<Id<ChannelMarker>>,
580        /// Old rules channel.
581        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
582        old: Option<Id<ChannelMarker>>,
583    },
584    /// Hash of a guild's splash.
585    SplashHash {
586        /// Old hash of a guild's splash.
587        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
588        new: Option<ImageHash>,
589        /// New hash of a guild's splash.
590        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
591        old: Option<ImageHash>,
592    },
593    /// Status of guild scheduled event was changed.
594    Status {
595        /// New status.
596        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
597        new: Option<u64>,
598        /// Previous state, if any.
599        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
600        old: Option<u64>,
601    },
602    /// ID of guild's system channel.
603    SystemChannelId {
604        /// New system channel ID.
605        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
606        new: Option<Id<ChannelMarker>>,
607        /// Old system channel ID.
608        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
609        old: Option<Id<ChannelMarker>>,
610    },
611    /// Related emoji of a sticker.
612    Tags {
613        /// New related emoji of a sticker.
614        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
615        new: Option<String>,
616        /// Old related emoji of a sticker.
617        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
618        old: Option<String>,
619    },
620    /// Whether an invite is temporary.
621    Temporary {
622        /// New temporary state.
623        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
624        new: Option<bool>,
625        /// Previous state, if any.
626        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
627        old: Option<bool>,
628    },
629    /// Topic of a textual channel.
630    Topic {
631        /// New topic.
632        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
633        new: Option<String>,
634        /// Old topic.
635        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
636        old: Option<String>,
637    },
638    /// Type of a created entity.
639    ///
640    /// The value of a type is dependent on the entity. For example, a channel's
641    /// type may be an integer while an integration's may be a string.
642    Type {
643        /// New target type.
644        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
645        new: Option<AuditLogChangeTypeValue>,
646        /// Old target type.
647        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
648        old: Option<AuditLogChangeTypeValue>,
649    },
650    /// Unicode emoji of a role icon changed.
651    UnicodeEmoji {
652        /// New unicode emoji.
653        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
654        new: Option<String>,
655        /// Old target type.
656        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
657        old: Option<String>,
658    },
659    /// Maximum number of users in a voice channel.
660    UserLimit {
661        /// New limit.
662        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
663        new: Option<u64>,
664        /// Old limit.
665        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
666        old: Option<u64>,
667    },
668    /// Number of uses of an invite.
669    Uses {
670        /// Number of uses.
671        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
672        new: Option<u64>,
673        /// Previous state, if any.
674        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
675        old: Option<u64>,
676    },
677    /// Code of a guild's vanity invite.
678    VanityUrlCode {
679        /// New vanity URL code.
680        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
681        new: Option<String>,
682        /// Old vanity URL code.
683        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
684        old: Option<String>,
685    },
686    /// Required verification level of new members in a guild.
687    VerificationLevel {
688        /// New verification level.
689        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
690        new: Option<VerificationLevel>,
691        /// Old verification level.
692        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
693        old: Option<VerificationLevel>,
694    },
695    /// Channel ID of a widget.
696    WidgetChannelId {
697        /// New channel ID.
698        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
699        new: Option<Id<ChannelMarker>>,
700        /// Old channel ID.
701        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
702        old: Option<Id<ChannelMarker>>,
703    },
704    /// Whether a widget is enabled.
705    WidgetEnabled {
706        /// New state of a widget being enabled.
707        #[serde(rename = "new_value", skip_serializing_if = "Option::is_none")]
708        new: Option<bool>,
709        /// Old state of a widget being enabled.
710        #[serde(rename = "old_value", skip_serializing_if = "Option::is_none")]
711        old: Option<bool>,
712    },
713    /// Other type of change not covered by other variants.
714    #[serde(other)]
715    Other,
716}
717
718impl AuditLogChange {
719    /// Key of an audit log change.
720    ///
721    /// This may return no key if the variant is [`Other`].
722    ///
723    /// # Examples
724    ///
725    /// Check the key of a [`Uses`] change:
726    ///
727    /// ```
728    /// use twilight_model::guild::audit_log::{AuditLogChange, AuditLogChangeKey};
729    ///
730    /// let change = AuditLogChange::UserLimit {
731    ///     new: Some(6),
732    ///     old: Some(3),
733    /// };
734    ///
735    /// assert_eq!(Some(AuditLogChangeKey::UserLimit), change.key());
736    /// ```
737    ///
738    /// [`Other`]: Self::Other
739    /// [`Uses`]: Self::Uses
740    pub const fn key(&self) -> Option<AuditLogChangeKey> {
741        Some(match self {
742            Self::AfkChannelId { .. } => AuditLogChangeKey::AfkChannelId,
743            Self::AfkTimeout { .. } => AuditLogChangeKey::AfkTimeout,
744            Self::Allow { .. } => AuditLogChangeKey::Allow,
745            Self::ApplicationId { .. } => AuditLogChangeKey::ApplicationId,
746            Self::Archived { .. } => AuditLogChangeKey::Archived,
747            Self::Asset { .. } => AuditLogChangeKey::Asset,
748            Self::AutoArchiveDuration { .. } => AuditLogChangeKey::AutoArchiveDuration,
749            Self::Available { .. } => AuditLogChangeKey::Available,
750            Self::AvatarHash { .. } => AuditLogChangeKey::AvatarHash,
751            Self::BannerHash { .. } => AuditLogChangeKey::BannerHash,
752            Self::Bitrate { .. } => AuditLogChangeKey::Bitrate,
753            Self::ChannelId { .. } => AuditLogChangeKey::ChannelId,
754            Self::Code { .. } => AuditLogChangeKey::Code,
755            Self::Color { .. } => AuditLogChangeKey::Color,
756            Self::CommandId { .. } => AuditLogChangeKey::CommandId,
757            Self::CommunicationDisabledUntil { .. } => {
758                AuditLogChangeKey::CommunicationDisabledUntil
759            }
760            Self::Deaf { .. } => AuditLogChangeKey::Deaf,
761            Self::DefaultAutoArchiveDuration { .. } => {
762                AuditLogChangeKey::DefaultAutoArchiveDuration
763            }
764            Self::DefaultMessageNotifications { .. } => {
765                AuditLogChangeKey::DefaultMessageNotifications
766            }
767            Self::Deny { .. } => AuditLogChangeKey::Deny,
768            Self::Description { .. } => AuditLogChangeKey::Description,
769            Self::DiscoverySplashHash { .. } => AuditLogChangeKey::DiscoverySplashHash,
770            Self::EnableEmoticons { .. } => AuditLogChangeKey::EnableEmoticons,
771            Self::EntityType { .. } => AuditLogChangeKey::EntityType,
772            Self::ExpireBehavior { .. } => AuditLogChangeKey::ExpireBehavior,
773            Self::ExpireGracePeriod { .. } => AuditLogChangeKey::ExpireGracePeriod,
774            Self::ExplicitContentFilter { .. } => AuditLogChangeKey::ExplicitContentFilter,
775            Self::FormatType { .. } => AuditLogChangeKey::FormatType,
776            Self::GuildId { .. } => AuditLogChangeKey::GuildId,
777            Self::Hoist { .. } => AuditLogChangeKey::Hoist,
778            Self::IconHash { .. } => AuditLogChangeKey::IconHash,
779            Self::Id { .. } => AuditLogChangeKey::Id,
780            Self::ImageHash { .. } => AuditLogChangeKey::ImageHash,
781            Self::Invitable { .. } => AuditLogChangeKey::Invitable,
782            Self::InviterId { .. } => AuditLogChangeKey::InviterId,
783            Self::Location { .. } => AuditLogChangeKey::Location,
784            Self::Locked { .. } => AuditLogChangeKey::Locked,
785            Self::MaxAge { .. } => AuditLogChangeKey::MaxAge,
786            Self::MaxUses { .. } => AuditLogChangeKey::MaxUses,
787            Self::Mentionable { .. } => AuditLogChangeKey::Mentionable,
788            Self::MfaLevel { .. } => AuditLogChangeKey::MfaLevel,
789            Self::Mute { .. } => AuditLogChangeKey::Mute,
790            Self::Name { .. } => AuditLogChangeKey::Name,
791            Self::Nick { .. } => AuditLogChangeKey::Nick,
792            Self::Nsfw { .. } => AuditLogChangeKey::Nsfw,
793            Self::NsfwLevel { .. } => AuditLogChangeKey::NsfwLevel,
794            Self::OwnerId { .. } => AuditLogChangeKey::OwnerId,
795            Self::PermissionOverwrites { .. } => AuditLogChangeKey::PermissionOverwrites,
796            Self::Permissions { .. } => AuditLogChangeKey::Permissions,
797            Self::Position { .. } => AuditLogChangeKey::Position,
798            Self::PreferredLocale { .. } => AuditLogChangeKey::PreferredLocale,
799            Self::PrivacyLevel { .. } => AuditLogChangeKey::PrivacyLevel,
800            Self::PruneDeleteDays { .. } => AuditLogChangeKey::PruneDeleteDays,
801            Self::PublicUpdatesChannelId { .. } => AuditLogChangeKey::PublicUpdatesChannelId,
802            Self::RateLimitPerUser { .. } => AuditLogChangeKey::RateLimitPerUser,
803            Self::Region { .. } => AuditLogChangeKey::Region,
804            Self::RoleAdded { .. } => AuditLogChangeKey::RoleAdded,
805            Self::RoleRemoved { .. } => AuditLogChangeKey::RoleRemoved,
806            Self::RulesChannelId { .. } => AuditLogChangeKey::RulesChannelId,
807            Self::SplashHash { .. } => AuditLogChangeKey::SplashHash,
808            Self::Status { .. } => AuditLogChangeKey::Status,
809            Self::SystemChannelId { .. } => AuditLogChangeKey::SystemChannelId,
810            Self::Tags { .. } => AuditLogChangeKey::Tags,
811            Self::Temporary { .. } => AuditLogChangeKey::Temporary,
812            Self::Topic { .. } => AuditLogChangeKey::Topic,
813            Self::Type { .. } => AuditLogChangeKey::Type,
814            Self::UnicodeEmoji { .. } => AuditLogChangeKey::UnicodeEmoji,
815            Self::UserLimit { .. } => AuditLogChangeKey::UserLimit,
816            Self::Uses { .. } => AuditLogChangeKey::Uses,
817            Self::VanityUrlCode { .. } => AuditLogChangeKey::VanityUrlCode,
818            Self::VerificationLevel { .. } => AuditLogChangeKey::VerificationLevel,
819            Self::WidgetChannelId { .. } => AuditLogChangeKey::WidgetChannelId,
820            Self::WidgetEnabled { .. } => AuditLogChangeKey::WidgetEnabled,
821            Self::Other => return None,
822        })
823    }
824}
825
826#[cfg(test)]
827mod tests {
828    use super::{super::AuditLogChangeKey, AffectedRole, AuditLogChange, AuditLogChangeTypeValue};
829    use crate::{channel::ChannelType, guild::Permissions, id::Id};
830    use serde::{Deserialize, Serialize};
831    use serde_test::Token;
832    use static_assertions::{assert_fields, assert_impl_all};
833    use std::{fmt::Debug, hash::Hash};
834
835    assert_fields!(AffectedRole: id, name);
836    assert_fields!(AuditLogChange::AfkChannelId: new, old);
837    assert_fields!(AuditLogChange::AfkTimeout: new, old);
838    assert_fields!(AuditLogChange::Allow: new);
839    assert_fields!(AuditLogChange::ApplicationId: new);
840    assert_fields!(AuditLogChange::AvatarHash: new, old);
841    assert_fields!(AuditLogChange::BannerHash: new, old);
842    assert_fields!(AuditLogChange::Bitrate: new, old);
843    assert_fields!(AuditLogChange::ChannelId: new);
844    assert_fields!(AuditLogChange::Code: new);
845    assert_fields!(AuditLogChange::Color: new, old);
846    assert_fields!(AuditLogChange::CommandId: new, old);
847    assert_fields!(AuditLogChange::CommunicationDisabledUntil: new, old);
848    assert_fields!(AuditLogChange::Deaf: new, old);
849    assert_fields!(AuditLogChange::DefaultMessageNotifications: new, old);
850    assert_fields!(AuditLogChange::Deny: new);
851    assert_fields!(AuditLogChange::Description: new, old);
852    assert_fields!(AuditLogChange::DiscoverySplashHash: new, old);
853    assert_fields!(AuditLogChange::EnableEmoticons: new, old);
854    assert_fields!(AuditLogChange::ExpireBehavior: new);
855    assert_fields!(AuditLogChange::ExpireGracePeriod: new);
856    assert_fields!(AuditLogChange::ExplicitContentFilter: new, old);
857    assert_fields!(AuditLogChange::Hoist: new, old);
858    assert_fields!(AuditLogChange::IconHash: new, old);
859    assert_fields!(AuditLogChange::Id: new);
860    assert_fields!(AuditLogChange::ImageHash: new, old);
861    assert_fields!(AuditLogChange::Invitable: new, old);
862    assert_fields!(AuditLogChange::InviterId: new);
863    assert_fields!(AuditLogChange::MaxAge: new);
864    assert_fields!(AuditLogChange::MaxUses: new);
865    assert_fields!(AuditLogChange::Mentionable: new, old);
866    assert_fields!(AuditLogChange::MfaLevel: new, old);
867    assert_fields!(AuditLogChange::Mute: new, old);
868    assert_fields!(AuditLogChange::Name: new, old);
869    assert_fields!(AuditLogChange::Nick: new, old);
870    assert_fields!(AuditLogChange::NsfwLevel: new, old);
871    assert_fields!(AuditLogChange::OwnerId: new, old);
872    assert_fields!(AuditLogChange::Permissions: new, old);
873    assert_fields!(AuditLogChange::PrivacyLevel: new, old);
874    assert_fields!(AuditLogChange::Position: new, old);
875    assert_fields!(AuditLogChange::PreferredLocale: new, old);
876    assert_fields!(AuditLogChange::PruneDeleteDays: new);
877    assert_fields!(AuditLogChange::PublicUpdatesChannelId: new, old);
878    assert_fields!(AuditLogChange::RateLimitPerUser: new, old);
879    assert_fields!(AuditLogChange::RoleAdded: new);
880    assert_fields!(AuditLogChange::RoleRemoved: new);
881    assert_fields!(AuditLogChange::RulesChannelId: new, old);
882    assert_fields!(AuditLogChange::SplashHash: new, old);
883    assert_fields!(AuditLogChange::SystemChannelId: new, old);
884    assert_fields!(AuditLogChange::Temporary: new);
885    assert_fields!(AuditLogChange::Topic: new);
886    assert_fields!(AuditLogChange::Type: new);
887    assert_fields!(AuditLogChange::Uses: new);
888    assert_fields!(AuditLogChange::UserLimit: new, old);
889    assert_fields!(AuditLogChange::VanityUrlCode: new, old);
890    assert_fields!(AuditLogChange::VerificationLevel: new, old);
891    assert_fields!(AuditLogChange::WidgetChannelId: new, old);
892    assert_fields!(AuditLogChange::WidgetEnabled: new, old);
893    assert_impl_all!(
894        AffectedRole: Clone,
895        Debug,
896        Deserialize<'static>,
897        Eq,
898        Hash,
899        PartialEq,
900        Send,
901        Serialize,
902        Sync
903    );
904    assert_impl_all!(
905        AuditLogChange: Clone,
906        Debug,
907        Deserialize<'static>,
908        Eq,
909        Hash,
910        PartialEq,
911        Send,
912        Serialize,
913        Sync
914    );
915    assert_impl_all!(
916        AuditLogChangeTypeValue: Clone,
917        Debug,
918        Deserialize<'static>,
919        Eq,
920        Hash,
921        PartialEq,
922        Send,
923        Serialize,
924        Sync
925    );
926
927    #[test]
928    fn afk_channel_id() {
929        let value = AuditLogChange::AfkChannelId {
930            new: Some(Id::new(1)),
931            old: None,
932        };
933
934        assert_eq!(Some(AuditLogChangeKey::AfkChannelId), value.key());
935
936        serde_test::assert_tokens(
937            &value,
938            &[
939                Token::Struct {
940                    name: "AuditLogChange",
941                    len: 2,
942                },
943                Token::String("key"),
944                Token::String("afk_channel_id"),
945                Token::String("new_value"),
946                Token::Some,
947                Token::NewtypeStruct { name: "Id" },
948                Token::String("1"),
949                Token::StructEnd,
950            ],
951        );
952    }
953
954    #[test]
955    fn permissions() {
956        let old: Permissions = Permissions::SEND_MESSAGES;
957        let new: Permissions = old | Permissions::EMBED_LINKS;
958
959        let value = AuditLogChange::Permissions {
960            new: Some(new),
961            old: Some(old),
962        };
963
964        assert_eq!(Some(AuditLogChangeKey::Permissions), value.key());
965
966        serde_test::assert_tokens(
967            &value,
968            &[
969                Token::Struct {
970                    name: "AuditLogChange",
971                    len: 3,
972                },
973                Token::String("key"),
974                Token::String("permissions"),
975                Token::String("new_value"),
976                Token::Some,
977                Token::Str("18432"),
978                Token::String("old_value"),
979                Token::Some,
980                Token::Str("2048"),
981                Token::StructEnd,
982            ],
983        );
984    }
985
986    #[test]
987    fn channel_type() {
988        let value = AuditLogChange::Type {
989            new: Some(AuditLogChangeTypeValue::Unsigned(u64::from(u8::from(
990                ChannelType::PrivateThread,
991            )))),
992            old: None,
993        };
994
995        serde_test::assert_tokens(
996            &value,
997            &[
998                Token::Struct {
999                    name: "AuditLogChange",
1000                    len: 2,
1001                },
1002                Token::String("key"),
1003                Token::Str("type"),
1004                Token::String("new_value"),
1005                Token::Some,
1006                Token::U64(u64::from(u8::from(ChannelType::PrivateThread))),
1007                Token::StructEnd,
1008            ],
1009        );
1010    }
1011
1012    #[test]
1013    fn integration_type() {
1014        let value = AuditLogChange::Type {
1015            new: Some(AuditLogChangeTypeValue::String("discord".to_owned())),
1016            old: None,
1017        };
1018
1019        serde_test::assert_tokens(
1020            &value,
1021            &[
1022                Token::Struct {
1023                    name: "AuditLogChange",
1024                    len: 2,
1025                },
1026                Token::String("key"),
1027                Token::Str("type"),
1028                Token::String("new_value"),
1029                Token::Some,
1030                Token::Str("discord"),
1031                Token::StructEnd,
1032            ],
1033        );
1034    }
1035}