use serde::{Deserialize, Serialize};
use serde_json::value::RawValue;
use serde_repr::{Deserialize_repr, Serialize_repr};
use crate::types::{Channel, Member, Snowflake, User};
#[derive(Debug, Clone, Deserialize)]
pub struct ScheduledEvent {
pub id: Snowflake,
pub guild_id: Snowflake,
pub channel_id: Option<Snowflake>,
pub creator_id: Option<Snowflake>,
pub name: String,
pub description: Option<String>,
pub scheduled_start_time: String,
pub scheduled_end_time: Option<String>,
pub privacy_level: u8,
pub status: ScheduledEventStatus,
pub entity_type: ScheduledEventEntityType,
pub entity_id: Option<Snowflake>,
pub entity_metadata: Option<EntityMetadata>,
pub creator: Option<User>,
pub user_count: Option<u32>,
pub image: Option<String>,
pub recurrence_rule: Option<Box<RawValue>>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize_repr, Serialize_repr)]
#[repr(u8)]
pub enum ScheduledEventStatus {
Scheduled = 1,
Active = 2,
Completed = 3,
Canceled = 4,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize_repr, Serialize_repr)]
#[repr(u8)]
pub enum ScheduledEventEntityType {
StageInstance = 1,
Voice = 2,
External = 3,
}
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct EntityMetadata {
#[serde(skip_serializing_if = "Option::is_none")]
pub location: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct ScheduledEventUser {
pub guild_scheduled_event_id: Snowflake,
pub user: User,
pub member: Option<Member>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct AutoModerationRule {
pub id: Snowflake,
pub guild_id: Snowflake,
pub name: String,
pub creator_id: Snowflake,
pub event_type: u8,
pub trigger_type: AutoModerationTriggerType,
pub trigger_metadata: TriggerMetadata,
pub actions: Vec<AutoModerationAction>,
pub enabled: bool,
pub exempt_roles: Vec<Snowflake>,
pub exempt_channels: Vec<Snowflake>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize_repr, Serialize_repr)]
#[repr(u8)]
pub enum AutoModerationTriggerType {
Keyword = 1,
Spam = 3,
KeywordPreset = 4,
MentionSpam = 5,
MemberProfile = 6,
}
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct TriggerMetadata {
#[serde(skip_serializing_if = "Option::is_none")]
pub keyword_filter: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub regex_patterns: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub presets: Option<Vec<u8>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub allow_list: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub mention_total_limit: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub mention_raid_protection_enabled: Option<bool>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct AutoModerationAction {
#[serde(rename = "type")]
pub kind: u8,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<ActionMetadata>,
}
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct ActionMetadata {
#[serde(skip_serializing_if = "Option::is_none")]
pub channel_id: Option<Snowflake>,
#[serde(skip_serializing_if = "Option::is_none")]
pub duration_seconds: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub custom_message: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct AuditLog {
pub audit_log_entries: Vec<AuditLogEntry>,
#[serde(default)]
pub users: Vec<User>,
#[serde(default)]
pub threads: Vec<Channel>,
#[serde(default)]
pub guild_scheduled_events: Vec<ScheduledEvent>,
#[serde(default)]
pub auto_moderation_rules: Vec<Option<AutoModerationRule>>,
#[serde(default)]
pub webhooks: Vec<Webhook>,
#[serde(default)]
pub integrations: Vec<Box<RawValue>>,
#[serde(default)]
pub application_commands: Vec<Box<RawValue>>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct AuditLogEntry {
pub id: Snowflake,
pub action_type: u16,
pub user_id: Option<Snowflake>,
pub target_id: Option<String>,
#[serde(default)]
pub changes: Vec<AuditLogChange>,
pub options: Option<AuditLogOptions>,
pub reason: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct AuditLogChange {
pub key: String,
pub new_value: Option<Box<RawValue>>,
pub old_value: Option<Box<RawValue>>,
}
#[derive(Debug, Clone, Default, Deserialize)]
pub struct AuditLogOptions {
pub application_id: Option<Snowflake>,
pub auto_moderation_rule_name: Option<String>,
pub auto_moderation_rule_trigger_type: Option<String>,
pub channel_id: Option<Snowflake>,
pub count: Option<String>,
pub delete_member_days: Option<String>,
pub id: Option<Snowflake>,
pub members_removed: Option<String>,
pub message_id: Option<Snowflake>,
pub role_name: Option<String>,
#[serde(rename = "type")]
pub kind: Option<String>,
pub integration_type: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct Webhook {
pub id: Snowflake,
#[serde(rename = "type")]
pub kind: u8,
pub guild_id: Option<Snowflake>,
pub channel_id: Option<Snowflake>,
pub user: Option<User>,
pub name: Option<String>,
pub avatar: Option<String>,
pub token: Option<String>,
pub application_id: Option<Snowflake>,
pub url: Option<String>,
pub source_guild: Option<WebhookSourceGuild>,
pub source_channel: Option<WebhookSourceChannel>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct WebhookSourceGuild {
pub id: Snowflake,
pub name: String,
pub icon: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct WebhookSourceChannel {
pub id: Snowflake,
pub name: String,
}
#[cfg(test)]
mod tests {
use serde_json::json;
use super::*;
#[test]
fn deserializes_admin_objects() {
let event: ScheduledEvent = serde_json::from_value(json!({
"id": "1", "guild_id": "2", "channel_id": null, "creator_id": "3", "name": "Meetup",
"description": null, "scheduled_start_time": "2030-01-01T00:00:00+00:00",
"scheduled_end_time": "2030-01-01T02:00:00+00:00", "privacy_level": 2, "status": 1,
"entity_type": 3, "entity_id": null, "entity_metadata": { "location": "Park" },
"image": null, "recurrence_rule": null, "guild_scheduled_event_exceptions": [],
}))
.unwrap();
assert_eq!(event.entity_type, ScheduledEventEntityType::External);
assert_eq!(
event.entity_metadata.unwrap().location.as_deref(),
Some("Park")
);
let rule: AutoModerationRule = serde_json::from_value(json!({
"id": "1", "guild_id": "2", "creator_id": "3", "name": "No spam", "event_type": 1,
"trigger_type": 1, "enabled": true, "exempt_roles": [], "exempt_channels": [],
"trigger_metadata": { "keyword_filter": ["spam"], "regex_patterns": [], "allow_list": [] },
"actions": [{ "type": 1, "metadata": { "custom_message": "no" } }],
}))
.unwrap();
assert_eq!(rule.trigger_type, AutoModerationTriggerType::Keyword);
let log: AuditLog = serde_json::from_value(json!({
"audit_log_entries": [{
"id": "9", "action_type": 22, "user_id": "3", "target_id": "4",
"changes": [{ "key": "nick", "new_value": "a" }],
"options": { "delete_member_days": "1", "members_removed": "2" },
"reason": "spam",
}],
"users": [], "integrations": [], "webhooks": [], "guild_scheduled_events": [],
"threads": [], "application_commands": [], "auto_moderation_rules": [],
}))
.unwrap();
let entry = &log.audit_log_entries[0];
assert_eq!(entry.changes[0].new_value.as_ref().unwrap().get(), "\"a\"");
assert_eq!(
entry.options.as_ref().unwrap().members_removed.as_deref(),
Some("2")
);
let follower: Webhook = serde_json::from_value(json!({
"id": "5", "type": 2, "guild_id": "6", "channel_id": "7", "name": "News",
"avatar": null, "application_id": null,
"source_guild": { "id": "8", "name": "Home", "icon": null },
"source_channel": { "id": "9", "name": "announcements" },
}))
.unwrap();
assert_eq!(follower.source_guild.unwrap().name, "Home");
assert_eq!(follower.source_channel.unwrap().id, Snowflake::from(9u64));
}
}