[Feature] Audit Log Created gateway event support (#2627)

* add event to socket client

* make `AuditLog` param optional

* Some WIP audit log changes

* api models

* moar models

* complete models

* modelsss

* forgot to push

* oh lol forgot this too

* api & rest guild method

* revert VS being VS & formatting to file scoped namespace

* socket entities

* some work eh

* moar stuff

- switched to d.net's attribute for audit log deserialization

* working socket guild updated event + reworked rest GuildInfo creation

* a bit of refactoring + new models

* +channel created

* channel updated & channel deleted

* refactor rest channel updated log + some nullable fixes

* rest channel created + deleted logs

* user banned socket log

* kick + unban

* moar log modelsssss

* fixes & 4 more log types

* overwrite logs

* role logs

* invite logs

* webhook logs

* switch to `ISocketAuditLogData` for socket log data

* emote logs

* move stuff around

* move more stuff around

* audit logs cache

* scheduled event logs

* thread logs

* command permission update audit log

* fetch scheduled event data from log

* integration audit logs

* sticker audit log data

* stage instance audit logs

* auto mod rule audit logs

* fix

* forgot couple props

* command perm updated data from options

* final automod ones

* debugging goes away :(

* merge cringe

* ...

* yup

* fix xml doc

* onboarding audit logs

* changes

---------

Co-authored-by: cat <lumitydev@gmail.com>
This commit is contained in:
Misha133
2023-04-15 02:13:02 +03:00
committed by GitHub
parent 3a8f76c4b1
commit dff6a57a92
181 changed files with 8992 additions and 2805 deletions

View File

@@ -205,6 +205,50 @@ namespace Discord
/// <summary> /// <summary>
/// A thread was deleted. /// A thread was deleted.
/// </summary> /// </summary>
ThreadDelete = 112 ThreadDelete = 112,
/// <summary>
/// Permissions were updated for a command.
/// </summary>
ApplicationCommandPermissionUpdate = 121,
/// <summary>
/// Auto Moderation rule was created.
/// </summary>
AutoModerationRuleCreate = 140,
/// <summary>
/// Auto Moderation rule was updated.
/// </summary>
AutoModerationRuleUpdate = 141,
/// <summary>
/// Auto Moderation rule was deleted.
/// </summary>
AutoModerationRuleDelete = 142,
/// <summary>
/// Message was blocked by Auto Moderation.
/// </summary>
AutoModerationBlockMessage = 143,
/// <summary>
/// Message was flagged by Auto Moderation.
/// </summary>
AutoModerationFlagToChannel = 144,
/// <summary>
/// Member was timed out by Auto Moderation.
/// </summary>
AutoModerationUserCommunicationDisabled = 145,
/// <summary>
/// Guild Onboarding Question was created.
/// </summary>
OnboardingQuestionCreated = 163,
/// <summary>
/// Guild Onboarding Question was updated.
/// </summary>
OnboardingQuestionUpdated = 164,
/// <summary>
/// Guild Onboarding was updated.
/// </summary>
OnboardingUpdated = 167
} }
} }

View File

@@ -0,0 +1,6 @@
namespace Discord;
public interface IAuditLogInfoModel
{
}

View File

@@ -17,17 +17,11 @@ namespace Discord
/// <summary> /// <summary>
/// Three days (4320 minutes). /// Three days (4320 minutes).
/// <remarks>
/// This option is explicitly available to nitro users.
/// </remarks>
/// </summary> /// </summary>
ThreeDays = 4320, ThreeDays = 4320,
/// <summary> /// <summary>
/// One week (10080 minutes). /// One week (10080 minutes).
/// <remarks>
/// This option is explicitly available to nitro users.
/// </remarks>
/// </summary> /// </summary>
OneWeek = 10080 OneWeek = 10080
} }

View File

@@ -7,6 +7,8 @@ using System.Threading.Tasks;
namespace Discord namespace Discord
{ {
// when adding properties to guilds please check if they are returned in audit log events and add them to the
// 'GuildInfo.cs' file for socket and rest audit logs.
/// <summary> /// <summary>
/// Represents a generic guild/server. /// Represents a generic guild/server.
/// </summary> /// </summary>

View File

@@ -0,0 +1,30 @@
using Discord.Rest;
namespace Discord.API.AuditLogs;
internal class AutoModRuleInfoAuditLogModel : IAuditLogInfoModel
{
[JsonField("name")]
public string Name { get; set; }
[JsonField("event_type")]
public AutoModEventType EventType { get; set; }
[JsonField("trigger_type")]
public AutoModTriggerType TriggerType { get; set; }
[JsonField("trigger_metadata")]
public TriggerMetadata TriggerMetadata { get; set; }
[JsonField("actions")]
public AutoModAction[] Actions { get; set; }
[JsonField("enabled")]
public bool Enabled { get; set; }
[JsonField("exempt_roles")]
public ulong[] ExemptRoles { get; set; }
[JsonField("exempt_channels")]
public ulong[] ExemptChannels { get; set; }
}

View File

@@ -0,0 +1,57 @@
using Discord.Rest;
namespace Discord.API.AuditLogs;
internal class ChannelInfoAuditLogModel : IAuditLogInfoModel
{
[JsonField("name")]
public string Name { get; set; }
[JsonField("type")]
public ChannelType? Type { get; set; }
[JsonField("permission_overwrites")]
public Overwrite[] Overwrites { get; set; }
[JsonField("flags")]
public ChannelFlags? Flags { get; set; }
[JsonField("default_thread_rate_limit_per_user")]
public int? DefaultThreadRateLimitPerUser { get; set; }
[JsonField("default_auto_archive_duration")]
public ThreadArchiveDuration? DefaultArchiveDuration { get; set; }
[JsonField("rate_limit_per_user")]
public int? RateLimitPerUser { get; set; }
[JsonField("auto_archive_duration")]
public ThreadArchiveDuration? AutoArchiveDuration { get; set; }
[JsonField("nsfw")]
public bool? IsNsfw { get; set; }
[JsonField("topic")]
public string Topic { get; set; }
// Forum channels
[JsonField("available_tags")]
public ForumTag[] AvailableTags { get; set; }
[JsonField("default_reaction_emoji")]
public ForumReactionEmoji DefaultEmoji { get; set; }
// Voice channels
[JsonField("user_limit")]
public int? UserLimit { get; set; }
[JsonField("rtc_region")]
public string Region { get; set; }
[JsonField("video_quality_mode")]
public VideoQualityMode? VideoQualityMode { get; set; }
[JsonField("bitrate")]
public int? Bitrate { get; set; }
}

View File

@@ -0,0 +1,82 @@
using Discord.Rest;
namespace Discord.API.AuditLogs;
public class GuildInfoAuditLogModel : IAuditLogInfoModel
{
[JsonField("name")]
public string Name { get; set; }
[JsonField("afk_timeout")]
public int? AfkTimeout { get; set; }
[JsonField("widget_enabled")]
public bool? IsEmbeddable { get; set; }
[JsonField("default_message_notifications")]
public DefaultMessageNotifications? DefaultMessageNotifications { get; set; }
[JsonField("mfa_level")]
public MfaLevel? MfaLevel { get; set; }
[JsonField("verification_level")]
public VerificationLevel? VerificationLevel { get; set; }
[JsonField("explicit_content_filter")]
public ExplicitContentFilterLevel? ExplicitContentFilterLevel { get; set; }
[JsonField("icon_hash")]
public string IconHash { get; set; }
[JsonField("discovery_splash")]
public string DiscoverySplash { get; set; }
[JsonField("splash")]
public string Splash { get; set; }
[JsonField("afk_channel_id")]
public ulong? AfkChannelId { get; set; }
[JsonField("widget_channel_id")]
public ulong? EmbeddedChannelId { get; set; }
[JsonField("system_channel_id")]
public ulong? SystemChannelId { get; set; }
[JsonField("rules_channel_id")]
public ulong? RulesChannelId { get; set; }
[JsonField("public_updates_channel_id")]
public ulong? PublicUpdatesChannelId { get; set; }
[JsonField("owner_id")]
public ulong? OwnerId { get; set; }
[JsonField("application_id")]
public ulong? ApplicationId { get; set; }
[JsonField("region")]
public string RegionId { get; set; }
[JsonField("banner")]
public string Banner { get; set; }
[JsonField("vanity_url_code")]
public string VanityUrl { get; set; }
[JsonField("system_channel_flags")]
public SystemChannelMessageDeny? SystemChannelFlags { get; set; }
[JsonField("description")]
public string Description { get; set; }
[JsonField("preferred_locale")]
public string PreferredLocale { get; set; }
[JsonField("nsfw_level")]
public NsfwLevel? NsfwLevel { get; set; }
[JsonField("premium_progress_bar_enabled")]
public bool? ProgressBarEnabled { get; set; }
}

View File

@@ -0,0 +1,33 @@
using Discord.Rest;
namespace Discord.API.AuditLogs;
internal class IntegrationInfoAuditLogModel : IAuditLogInfoModel
{
[JsonField("name")]
public string Name { get; set; }
[JsonField("type")]
public string Type { get; set; }
[JsonField("enabled")]
public bool? Enabled { get; set; }
[JsonField("syncing")]
public bool? Syncing { get; set; }
[JsonField("role_id")]
public ulong? RoleId { get; set; }
[JsonField("enable_emoticons")]
public bool? EnableEmojis { get; set; }
[JsonField("expire_behavior")]
public IntegrationExpireBehavior? ExpireBehavior { get; set; }
[JsonField("expire_grace_period")]
public int? ExpireGracePeriod { get; set; }
[JsonField("scopes")]
public string[] Scopes { get; set; }
}

View File

@@ -0,0 +1,27 @@
using Discord.Rest;
namespace Discord.API.AuditLogs;
internal class InviteInfoAuditLogModel : IAuditLogInfoModel
{
[JsonField("code")]
public string Code { get; set; }
[JsonField("channel_id")]
public ulong? ChannelId { get; set; }
[JsonField("inviter_id")]
public ulong? InviterId { get; set; }
[JsonField("uses")]
public int? Uses { get; set; }
[JsonField("max_uses")]
public int? MaxUses { get; set; }
[JsonField("max_age")]
public int? MaxAge { get; set; }
[JsonField("temporary")]
public bool? Temporary { get; set; }
}

View File

@@ -0,0 +1,19 @@
using Discord.Rest;
using System;
namespace Discord.API.AuditLogs;
internal class MemberInfoAuditLogModel : IAuditLogInfoModel
{
[JsonField("nick")]
public string Nickname { get; set; }
[JsonField("mute")]
public bool? IsMuted { get; set; }
[JsonField("deaf")]
public bool? IsDeafened { get; set; }
[JsonField("communication_disabled_until")]
public DateTimeOffset? TimeOutUntil { get; set; }
}

View File

@@ -0,0 +1,15 @@
using Discord.Rest;
namespace Discord.API.AuditLogs;
internal class OnboardingAuditLogModel : IAuditLogInfoModel
{
[JsonField("default_channel_ids")]
public ulong[] DefaultChannelIds { get; set; }
[JsonField("prompts")]
public GuildOnboardingPrompt[] Prompts { get; set; }
[JsonField("enabled")]
public bool? Enabled { get; set; }
}

View File

@@ -0,0 +1,27 @@
using Discord.Rest;
namespace Discord.API.AuditLogs;
internal class OnboardingPromptAuditLogModel : IAuditLogInfoModel
{
[JsonField("id")]
public ulong? Id { get; set; }
[JsonField("title")]
public string Title { get; set; }
[JsonField("options")]
public GuildOnboardingPromptOption[] Options { get; set; }
[JsonField("single_select")]
public bool? IsSingleSelect { get; set; }
[JsonField("required")]
public bool? IsRequired { get; set; }
[JsonField("in_onboarding")]
public bool? IsInOnboarding { get; set; }
[JsonField("type")]
public GuildOnboardingPromptType? Type { get; set; }
}

View File

@@ -0,0 +1,24 @@
using Discord.Rest;
namespace Discord.API.AuditLogs;
internal class RoleInfoAuditLogModel : IAuditLogInfoModel
{
[JsonField("name")]
public string Name { get; set; }
[JsonField("color")]
public uint? Color { get; set; }
[JsonField("hoist")]
public bool? Hoist { get; set; }
[JsonField("permissions")]
public ulong? Permissions { get; set; }
[JsonField("mentionable")]
public bool? IsMentionable { get; set; }
[JsonField("icon_hash")]
public string IconHash { get; set; }
}

View File

@@ -0,0 +1,43 @@
using Discord.Rest;
using System;
namespace Discord.API.AuditLogs;
internal class ScheduledEventInfoAuditLogModel : IAuditLogInfoModel
{
[JsonField("channel_id")]
public ulong? ChannelId { get; set; }
[JsonField("name")]
public string Name { get; set; }
[JsonField("description")]
public string Description { get; set; }
[JsonField("scheduled_start_time")]
public DateTimeOffset? StartTime { get; set; }
[JsonField("scheduled_end_time")]
public DateTimeOffset? EndTime { get; set; }
[JsonField("privacy_level")]
public GuildScheduledEventPrivacyLevel? PrivacyLevel { get; set; }
[JsonField("status")]
public GuildScheduledEventStatus? EventStatus { get; set; }
[JsonField("entity_type")]
public GuildScheduledEventType? EventType { get; set; }
[JsonField("entity_id")]
public ulong? EntityId { get; set; }
[JsonField("user_count")]
public int? UserCount { get; set; }
[JsonField("location")]
public string Location { get; set; }
[JsonField("image")]
public string Image { get; set; }
}

View File

@@ -0,0 +1,15 @@
using Discord.Rest;
namespace Discord.API.AuditLogs;
internal class StickerInfoAuditLogModel : IAuditLogInfoModel
{
[JsonField("name")]
public string Name { get; set; }
[JsonField("tags")]
public string Tags { get; set; }
[JsonField("description")]
public string Description { get; set; }
}

View File

@@ -0,0 +1,30 @@
using Discord.Rest;
namespace Discord.API.AuditLogs;
internal class ThreadInfoAuditLogModel : IAuditLogInfoModel
{
[JsonField("name")]
public string Name { get; set; }
[JsonField("type")]
public ThreadType Type { get; set; }
[JsonField("archived")]
public bool? IsArchived { get; set; }
[JsonField("locked")]
public bool? IsLocked { get; set;}
[JsonField("auto_archive_duration")]
public ThreadArchiveDuration? ArchiveDuration { get; set; }
[JsonField("rate_limit_per_user")]
public int? SlowModeInterval { get; set; }
[JsonField("flags")]
public ChannelFlags? ChannelFlags { get; set; }
[JsonField("applied_tags")]
public ulong[] AppliedTags { get; set; }
}

View File

@@ -0,0 +1,18 @@
using Discord.Rest;
namespace Discord.API.AuditLogs;
internal class WebhookInfoAuditLogModel : IAuditLogInfoModel
{
[JsonField("channel_id")]
public ulong? ChannelId { get; set; }
[JsonField("name")]
public string Name { get; set; }
[JsonField("type")]
public WebhookType? Type { get; set; }
[JsonField("avatar_hash")]
public string AvatarHash { get; set; }
}

View File

@@ -14,6 +14,9 @@ namespace Discord.API
[JsonProperty("application_id")] [JsonProperty("application_id")]
public ulong ApplicationId { get; set; } public ulong ApplicationId { get; set; }
[JsonProperty("guild_id")]
public Optional<ulong> GuildId { get; set; }
[JsonProperty("name")] [JsonProperty("name")]
public string Name { get; set; } public string Name { get; set; }

View File

@@ -18,5 +18,14 @@ namespace Discord.API
[JsonProperty("audit_log_entries")] [JsonProperty("audit_log_entries")]
public AuditLogEntry[] Entries { get; set; } public AuditLogEntry[] Entries { get; set; }
[JsonProperty("application_commands")]
public ApplicationCommand[] Commands { get; set; }
[JsonProperty("auto_moderation_rules")]
public AutoModerationRule[] AutoModerationRules { get; set;}
[JsonProperty("guild_scheduled_events")]
public GuildScheduledEvent[] GuildScheduledEvents { get; set; }
} }
} }

View File

@@ -1,28 +1,39 @@
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Discord.API namespace Discord.API;
internal class AuditLogOptions
{ {
internal class AuditLogOptions [JsonProperty("count")]
{ public int? Count { get; set; }
[JsonProperty("count")] [JsonProperty("channel_id")]
public int? Count { get; set; } public ulong? ChannelId { get; set; }
[JsonProperty("channel_id")] [JsonProperty("message_id")]
public ulong? ChannelId { get; set; } public ulong? MessageId { get; set; }
[JsonProperty("message_id")]
public ulong? MessageId { get; set; }
//Prune //Prune
[JsonProperty("delete_member_days")] [JsonProperty("delete_member_days")]
public int? PruneDeleteMemberDays { get; set; } public int? PruneDeleteMemberDays { get; set; }
[JsonProperty("members_removed")] [JsonProperty("members_removed")]
public int? PruneMembersRemoved { get; set; } public int? PruneMembersRemoved { get; set; }
//Overwrite Update //Overwrite Update
[JsonProperty("role_name")] [JsonProperty("role_name")]
public string OverwriteRoleName { get; set; } public string OverwriteRoleName { get; set; }
[JsonProperty("type")] [JsonProperty("type")]
public PermissionTarget OverwriteType { get; set; } public PermissionTarget OverwriteType { get; set; }
[JsonProperty("id")] [JsonProperty("id")]
public ulong? OverwriteTargetId { get; set; } public ulong? OverwriteTargetId { get; set; }
}
// App command perm update
[JsonProperty("application_id")]
public ulong? ApplicationId { get; set; }
// Automod
[JsonProperty("auto_moderation_rule_name")]
public string AutoModRuleName { get; set; }
[JsonProperty("auto_moderation_rule_trigger_type")]
public AutoModTriggerType? AutoModRuleTriggerType { get; set; }
} }

View File

@@ -72,7 +72,7 @@ namespace Discord.API
//ForumChannel //ForumChannel
[JsonProperty("available_tags")] [JsonProperty("available_tags")]
public Optional<ForumTags[]> ForumTags { get; set; } public Optional<ForumTag[]> ForumTags { get; set; }
[JsonProperty("applied_tags")] [JsonProperty("applied_tags")]
public Optional<ulong[]> AppliedTags { get; set; } public Optional<ulong[]> AppliedTags { get; set; }

View File

@@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace Discord.API namespace Discord.API
{ {
internal class ForumTags internal class ForumTag
{ {
[JsonProperty("id")] [JsonProperty("id")]
public ulong Id { get; set; } public ulong Id { get; set; }

View File

@@ -1,71 +1,122 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using AuditLogChange = Discord.API.AuditLogChange;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
internal static class AuditLogHelper
{ {
internal static class AuditLogHelper private static readonly Dictionary<ActionType, Func<BaseDiscordClient, EntryModel, Model, IAuditLogData>> CreateMapping
{ = new ()
private static readonly Dictionary<ActionType, Func<BaseDiscordClient, Model, EntryModel, IAuditLogData>> CreateMapping
= new Dictionary<ActionType, Func<BaseDiscordClient, Model, EntryModel, IAuditLogData>>()
{
[ActionType.GuildUpdated] = GuildUpdateAuditLogData.Create,
[ActionType.ChannelCreated] = ChannelCreateAuditLogData.Create,
[ActionType.ChannelUpdated] = ChannelUpdateAuditLogData.Create,
[ActionType.ChannelDeleted] = ChannelDeleteAuditLogData.Create,
[ActionType.OverwriteCreated] = OverwriteCreateAuditLogData.Create,
[ActionType.OverwriteUpdated] = OverwriteUpdateAuditLogData.Create,
[ActionType.OverwriteDeleted] = OverwriteDeleteAuditLogData.Create,
[ActionType.Kick] = KickAuditLogData.Create,
[ActionType.Prune] = PruneAuditLogData.Create,
[ActionType.Ban] = BanAuditLogData.Create,
[ActionType.Unban] = UnbanAuditLogData.Create,
[ActionType.MemberUpdated] = MemberUpdateAuditLogData.Create,
[ActionType.MemberRoleUpdated] = MemberRoleAuditLogData.Create,
[ActionType.MemberMoved] = MemberMoveAuditLogData.Create,
[ActionType.MemberDisconnected] = MemberDisconnectAuditLogData.Create,
[ActionType.BotAdded] = BotAddAuditLogData.Create,
[ActionType.RoleCreated] = RoleCreateAuditLogData.Create,
[ActionType.RoleUpdated] = RoleUpdateAuditLogData.Create,
[ActionType.RoleDeleted] = RoleDeleteAuditLogData.Create,
[ActionType.InviteCreated] = InviteCreateAuditLogData.Create,
[ActionType.InviteUpdated] = InviteUpdateAuditLogData.Create,
[ActionType.InviteDeleted] = InviteDeleteAuditLogData.Create,
[ActionType.WebhookCreated] = WebhookCreateAuditLogData.Create,
[ActionType.WebhookUpdated] = WebhookUpdateAuditLogData.Create,
[ActionType.WebhookDeleted] = WebhookDeleteAuditLogData.Create,
[ActionType.EmojiCreated] = EmoteCreateAuditLogData.Create,
[ActionType.EmojiUpdated] = EmoteUpdateAuditLogData.Create,
[ActionType.EmojiDeleted] = EmoteDeleteAuditLogData.Create,
[ActionType.MessageDeleted] = MessageDeleteAuditLogData.Create,
[ActionType.MessageBulkDeleted] = MessageBulkDeleteAuditLogData.Create,
[ActionType.MessagePinned] = MessagePinAuditLogData.Create,
[ActionType.MessageUnpinned] = MessageUnpinAuditLogData.Create,
[ActionType.EventCreate] = ScheduledEventCreateAuditLogData.Create,
[ActionType.EventUpdate] = ScheduledEventUpdateAuditLogData.Create,
[ActionType.EventDelete] = ScheduledEventDeleteAuditLogData.Create,
[ActionType.ThreadCreate] = ThreadCreateAuditLogData.Create,
[ActionType.ThreadUpdate] = ThreadUpdateAuditLogData.Create,
[ActionType.ThreadDelete] = ThreadDeleteAuditLogData.Create,
};
public static IAuditLogData CreateData(BaseDiscordClient discord, Model log, EntryModel entry)
{ {
if (CreateMapping.TryGetValue(entry.Action, out var func)) [ActionType.GuildUpdated] = GuildUpdateAuditLogData.Create, // log
return func(discord, log, entry); [ActionType.ChannelCreated] = ChannelCreateAuditLogData.Create,
[ActionType.ChannelUpdated] = ChannelUpdateAuditLogData.Create,
[ActionType.ChannelDeleted] = ChannelDeleteAuditLogData.Create,
return null; [ActionType.OverwriteCreated] = OverwriteCreateAuditLogData.Create,
[ActionType.OverwriteUpdated] = OverwriteUpdateAuditLogData.Create,
[ActionType.OverwriteDeleted] = OverwriteDeleteAuditLogData.Create,
[ActionType.Kick] = KickAuditLogData.Create,
[ActionType.Prune] = PruneAuditLogData.Create,
[ActionType.Ban] = BanAuditLogData.Create,
[ActionType.Unban] = UnbanAuditLogData.Create,
[ActionType.MemberUpdated] = MemberUpdateAuditLogData.Create,
[ActionType.MemberRoleUpdated] = MemberRoleAuditLogData.Create,
[ActionType.MemberMoved] = MemberMoveAuditLogData.Create,
[ActionType.MemberDisconnected] = MemberDisconnectAuditLogData.Create,
[ActionType.BotAdded] = BotAddAuditLogData.Create,
[ActionType.RoleCreated] = RoleCreateAuditLogData.Create,
[ActionType.RoleUpdated] = RoleUpdateAuditLogData.Create,
[ActionType.RoleDeleted] = RoleDeleteAuditLogData.Create,
[ActionType.InviteCreated] = InviteCreateAuditLogData.Create,
[ActionType.InviteUpdated] = InviteUpdateAuditLogData.Create,
[ActionType.InviteDeleted] = InviteDeleteAuditLogData.Create,
[ActionType.WebhookCreated] = WebhookCreateAuditLogData.Create,
[ActionType.WebhookUpdated] = WebhookUpdateAuditLogData.Create,
[ActionType.WebhookDeleted] = WebhookDeleteAuditLogData.Create,
[ActionType.EmojiCreated] = EmoteCreateAuditLogData.Create,
[ActionType.EmojiUpdated] = EmoteUpdateAuditLogData.Create,
[ActionType.EmojiDeleted] = EmoteDeleteAuditLogData.Create,
[ActionType.MessageDeleted] = MessageDeleteAuditLogData.Create,
[ActionType.MessageBulkDeleted] = MessageBulkDeleteAuditLogData.Create,
[ActionType.MessagePinned] = MessagePinAuditLogData.Create,
[ActionType.MessageUnpinned] = MessageUnpinAuditLogData.Create,
[ActionType.EventCreate] = ScheduledEventCreateAuditLogData.Create,
[ActionType.EventUpdate] = ScheduledEventUpdateAuditLogData.Create,
[ActionType.EventDelete] = ScheduledEventDeleteAuditLogData.Create,
[ActionType.ThreadCreate] = ThreadCreateAuditLogData.Create,
[ActionType.ThreadUpdate] = ThreadUpdateAuditLogData.Create,
[ActionType.ThreadDelete] = ThreadDeleteAuditLogData.Create,
[ActionType.ApplicationCommandPermissionUpdate] = CommandPermissionUpdateAuditLogData.Create,
[ActionType.IntegrationCreated] = IntegrationCreatedAuditLogData.Create,
[ActionType.IntegrationUpdated] = IntegrationUpdatedAuditLogData.Create,
[ActionType.IntegrationDeleted] = IntegrationDeletedAuditLogData.Create,
[ActionType.StageInstanceCreated] = StageInstanceCreateAuditLogData.Create,
[ActionType.StageInstanceUpdated] = StageInstanceUpdatedAuditLogData.Create,
[ActionType.StageInstanceDeleted] = StageInstanceDeleteAuditLogData.Create,
[ActionType.StickerCreated] = StickerCreatedAuditLogData.Create,
[ActionType.StickerUpdated] = StickerUpdatedAuditLogData.Create,
[ActionType.StickerDeleted] = StickerDeletedAuditLogData.Create,
[ActionType.AutoModerationRuleCreate] = AutoModRuleCreatedAuditLogData.Create,
[ActionType.AutoModerationRuleUpdate] = AutoModRuleUpdatedAuditLogData.Create,
[ActionType.AutoModerationRuleDelete] = AutoModRuleDeletedAuditLogData.Create,
[ActionType.AutoModerationBlockMessage] = AutoModBlockedMessageAuditLogData.Create,
[ActionType.AutoModerationFlagToChannel] = AutoModFlaggedMessageAuditLogData.Create,
[ActionType.AutoModerationUserCommunicationDisabled] = AutoModTimeoutUserAuditLogData.Create,
[ActionType.OnboardingQuestionCreated] = OnboardingPromptCreatedAuditLogData.Create,
[ActionType.OnboardingQuestionUpdated] = OnboardingPromptUpdatedAuditLogData.Create,
[ActionType.OnboardingUpdated] = OnboardingUpdatedAuditLogData.Create,
};
public static IAuditLogData CreateData(BaseDiscordClient discord, EntryModel entry, Model log = null)
{
if (CreateMapping.TryGetValue(entry.Action, out var func))
return func(discord, entry, log);
return null;
}
internal static (T, T) CreateAuditLogEntityInfo<T>(AuditLogChange[] changes, BaseDiscordClient discord) where T : IAuditLogInfoModel
{
var oldModel = (T)Activator.CreateInstance(typeof(T))!;
var newModel = (T)Activator.CreateInstance(typeof(T))!;
var props = typeof(T).GetProperties();
foreach (var property in props)
{
if (property.GetCustomAttributes(typeof(JsonFieldAttribute), true).FirstOrDefault() is not JsonFieldAttribute jsonAttr)
continue;
var change = changes.FirstOrDefault(x => x.ChangedProperty == jsonAttr.FieldName);
if (change is null)
continue;
property.SetValue(oldModel, change.OldValue?.ToObject(property.PropertyType, discord.ApiClient.Serializer));
property.SetValue(newModel, change.NewValue?.ToObject(property.PropertyType, discord.ApiClient.Serializer));
} }
return (oldModel, newModel);
} }
} }

View File

@@ -0,0 +1,38 @@
using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog;
namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to message getting blocked by automod.
/// </summary>
public class AutoModBlockedMessageAuditLogData : IAuditLogData
{
internal AutoModBlockedMessageAuditLogData(ulong channelId, string autoModRuleName, AutoModTriggerType autoModRuleTriggerType)
{
ChannelId = channelId;
AutoModRuleName = autoModRuleName;
AutoModRuleTriggerType = autoModRuleTriggerType;
}
internal static AutoModBlockedMessageAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
return new(entry.Options.ChannelId!.Value, entry.Options.AutoModRuleName,
entry.Options.AutoModRuleTriggerType!.Value);
}
/// <summary>
/// Gets the channel the message was sent in.
/// </summary>
public ulong ChannelId { get; set; }
/// <summary>
/// Gets the name of the auto moderation rule that got triggered.
/// </summary>
public string AutoModRuleName { get; set; }
/// <summary>
/// Gets the trigger type of the auto moderation rule that got triggered.
/// </summary>
public AutoModTriggerType AutoModRuleTriggerType { get; set; }
}

View File

@@ -0,0 +1,38 @@
using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog;
namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to message getting flagged by automod.
/// </summary>
public class AutoModFlaggedMessageAuditLogData : IAuditLogData
{
internal AutoModFlaggedMessageAuditLogData(ulong channelId, string autoModRuleName, AutoModTriggerType autoModRuleTriggerType)
{
ChannelId = channelId;
AutoModRuleName = autoModRuleName;
AutoModRuleTriggerType = autoModRuleTriggerType;
}
internal static AutoModFlaggedMessageAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
return new(entry.Options.ChannelId!.Value, entry.Options.AutoModRuleName,
entry.Options.AutoModRuleTriggerType!.Value);
}
/// <summary>
/// Gets the channel the message was sent in.
/// </summary>
public ulong ChannelId { get; set; }
/// <summary>
/// Gets the name of the auto moderation rule that got triggered.
/// </summary>
public string AutoModRuleName { get; set; }
/// <summary>
/// Gets the trigger type of the auto moderation rule that got triggered.
/// </summary>
public AutoModTriggerType AutoModRuleTriggerType { get; set; }
}

View File

@@ -0,0 +1,31 @@
using Discord.API.AuditLogs;
using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog;
namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to an auto moderation rule creation.
/// </summary>
public class AutoModRuleCreatedAuditLogData : IAuditLogData
{
private AutoModRuleCreatedAuditLogData(AutoModRuleInfo data)
{
Data = data;
}
internal static AutoModRuleCreatedAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var changes = entry.Changes;
var (_, data) = AuditLogHelper.CreateAuditLogEntityInfo<AutoModRuleInfoAuditLogModel>(changes, discord);
return new AutoModRuleCreatedAuditLogData(new (data));
}
/// <summary>
/// Gets the auto moderation rule information after the changes.
/// </summary>
public AutoModRuleInfo Data { get; }
}

View File

@@ -0,0 +1,31 @@
using Discord.API.AuditLogs;
using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog;
namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to an auto moderation rule removal.
/// </summary>
public class AutoModRuleDeletedAuditLogData : IAuditLogData
{
private AutoModRuleDeletedAuditLogData(AutoModRuleInfo data)
{
Data = data;
}
internal static AutoModRuleDeletedAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var changes = entry.Changes;
var (data, _) = AuditLogHelper.CreateAuditLogEntityInfo<AutoModRuleInfoAuditLogModel>(changes, discord);
return new AutoModRuleDeletedAuditLogData(new (data));
}
/// <summary>
/// Gets the auto moderation rule information before the changes.
/// </summary>
public AutoModRuleInfo Data { get; }
}

View File

@@ -0,0 +1,113 @@
using Discord.API.AuditLogs;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
namespace Discord.Rest;
/// <summary>
/// Represents information for an auto moderation rule.
/// </summary>
public class AutoModRuleInfo
{
internal AutoModRuleInfo(AutoModRuleInfoAuditLogModel model)
{
Actions = model.Actions?.Select(x => new AutoModRuleAction(
x.Type,
x.Metadata.GetValueOrDefault()?.ChannelId.ToNullable(),
x.Metadata.GetValueOrDefault()?.DurationSeconds.ToNullable(),
x.Metadata.IsSpecified
? x.Metadata.Value.CustomMessage.IsSpecified
? x.Metadata.Value.CustomMessage.Value
: null
: null
)).ToImmutableArray();
KeywordFilter = model.TriggerMetadata?.KeywordFilter.GetValueOrDefault(Array.Empty<string>())?.ToImmutableArray();
Presets = model.TriggerMetadata?.Presets.GetValueOrDefault(Array.Empty<KeywordPresetTypes>())?.ToImmutableArray();
RegexPatterns = model.TriggerMetadata?.RegexPatterns.GetValueOrDefault(Array.Empty<string>())?.ToImmutableArray();
AllowList = model.TriggerMetadata?.AllowList.GetValueOrDefault(Array.Empty<string>())?.ToImmutableArray();
MentionTotalLimit = model.TriggerMetadata?.MentionLimit.IsSpecified ?? false
? model.TriggerMetadata?.MentionLimit.Value
: null;
Name = model.Name;
Enabled = model.Enabled;
ExemptRoles = model.ExemptRoles?.ToImmutableArray();
ExemptChannels = model.ExemptChannels?.ToImmutableArray();
TriggerType = model.TriggerType;
EventType = model.EventType;
}
/// <inheritdoc cref="IAutoModRule.Name"/>
/// <remarks>
/// <see langword="null"/> if this property is not mentioned in this entry.
/// </remarks>
public string Name { get; set; }
/// <inheritdoc cref="IAutoModRule.EventType"/>
/// <remarks>
/// <see langword="null"/> if this property is not mentioned in this entry.
/// </remarks>
public AutoModEventType? EventType { get; set; }
/// <inheritdoc cref="IAutoModRule.TriggerType"/>
/// <remarks>
/// <see langword="null"/> if this property is not mentioned in this entry.
/// </remarks>
public AutoModTriggerType? TriggerType { get; set; }
/// <inheritdoc cref="IAutoModRule.Enabled"/>
/// <remarks>
/// <see langword="null"/> if this property is not mentioned in this entry.
/// </remarks>
public bool? Enabled { get; set; }
/// <inheritdoc cref="IAutoModRule.ExemptRoles"/>
/// <remarks>
/// <see langword="null"/> if this property is not mentioned in this entry.
/// </remarks>
public IReadOnlyCollection<ulong> ExemptRoles { get; set; }
/// <inheritdoc cref="IAutoModRule.ExemptChannels"/>
/// <remarks>
/// <see langword="null"/> if this property is not mentioned in this entry.
/// </remarks>
public IReadOnlyCollection<ulong> ExemptChannels { get; set; }
/// <inheritdoc cref="IAutoModRule.KeywordFilter"/>
/// <remarks>
/// <see langword="null"/> if this property is not mentioned in this entry.
/// </remarks>
public IReadOnlyCollection<string> KeywordFilter { get; }
/// <inheritdoc cref="IAutoModRule.RegexPatterns"/>
/// <remarks>
/// <see langword="null"/> if this property is not mentioned in this entry.
/// </remarks>
public IReadOnlyCollection<string> RegexPatterns { get; }
/// <inheritdoc cref="IAutoModRule.AllowList"/>
/// <remarks>
/// <see langword="null"/> if this property is not mentioned in this entry.
/// </remarks>
public IReadOnlyCollection<string> AllowList { get; }
/// <inheritdoc cref="IAutoModRule.Presets"/>
/// <remarks>
/// <see langword="null"/> if this property is not mentioned in this entry.
/// </remarks>
public IReadOnlyCollection<KeywordPresetTypes> Presets { get; }
/// <inheritdoc cref="IAutoModRule.MentionTotalLimit"/>
/// <remarks>
/// <see langword="null"/> if this property is not mentioned in this entry.
/// </remarks>
public int? MentionTotalLimit { get; }
/// <inheritdoc cref="IAutoModRule.Actions"/>
/// <remarks>
/// <see langword="null"/> if this property is not mentioned in this entry.
/// </remarks>
public IReadOnlyCollection<AutoModRuleAction> Actions { get; private set; }
}

View File

@@ -0,0 +1,45 @@
using Discord.API.AuditLogs;
using System.Linq;
using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog;
namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to an auto moderation rule update.
/// </summary>
public class AutoModRuleUpdatedAuditLogData : IAuditLogData
{
private AutoModRuleUpdatedAuditLogData(AutoModRuleInfo before, AutoModRuleInfo after, IAutoModRule rule)
{
Before = before;
After = after;
Rule = rule;
}
internal static AutoModRuleUpdatedAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var changes = entry.Changes;
var (before, after) = AuditLogHelper.CreateAuditLogEntityInfo<AutoModRuleInfoAuditLogModel>(changes, discord);
var rule = RestAutoModRule.Create(discord, log.AutoModerationRules.FirstOrDefault(x => x.Id == entry.TargetId));
return new AutoModRuleUpdatedAuditLogData(new (before), new(after), rule);
}
/// <summary>
/// Gets the auto moderation rule the changes correspond to.
/// </summary>
public IAutoModRule Rule { get; }
/// <summary>
/// Gets the auto moderation rule information before the changes.
/// </summary>
public AutoModRuleInfo Before { get; }
/// <summary>
/// Gets the auto moderation rule information after the changes.
/// </summary>
public AutoModRuleInfo After { get; }
}

View File

@@ -0,0 +1,38 @@
using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog;
namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to user getting in timeout by automod.
/// </summary>
public class AutoModTimeoutUserAuditLogData : IAuditLogData
{
internal AutoModTimeoutUserAuditLogData(ulong channelId, string autoModRuleName, AutoModTriggerType autoModRuleTriggerType)
{
ChannelId = channelId;
AutoModRuleName = autoModRuleName;
AutoModRuleTriggerType = autoModRuleTriggerType;
}
internal static AutoModTimeoutUserAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
return new(entry.Options.ChannelId!.Value, entry.Options.AutoModRuleName,
entry.Options.AutoModRuleTriggerType!.Value);
}
/// <summary>
/// Gets the channel the message was sent in.
/// </summary>
public ulong ChannelId { get; set; }
/// <summary>
/// Gets the name of the auto moderation rule that got triggered.
/// </summary>
public string AutoModRuleName { get; set; }
/// <summary>
/// Gets the trigger type of the auto moderation rule that got triggered.
/// </summary>
public AutoModTriggerType AutoModRuleTriggerType { get; set; }
}

View File

@@ -2,33 +2,32 @@ using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a ban.
/// </summary>
public class BanAuditLogData : IAuditLogData
{ {
/// <summary> private BanAuditLogData(IUser user)
/// Contains a piece of audit log data related to a ban.
/// </summary>
public class BanAuditLogData : IAuditLogData
{ {
private BanAuditLogData(IUser user) Target = user;
{
Target = user;
}
internal static BanAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var userInfo = log.Users.FirstOrDefault(x => x.Id == entry.TargetId);
return new BanAuditLogData((userInfo != null) ? RestUser.Create(discord, userInfo) : null);
}
/// <summary>
/// Gets the user that was banned.
/// </summary>
/// <remarks>
/// Will be <see langword="null"/> if the user is a 'Deleted User#....' because Discord does send user data for deleted users.
/// </remarks>
/// <returns>
/// A user object representing the banned user.
/// </returns>
public IUser Target { get; }
} }
internal static BanAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log = null)
{
var userInfo = log.Users.FirstOrDefault(x => x.Id == entry.TargetId);
return new BanAuditLogData((userInfo != null) ? RestUser.Create(discord, userInfo) : null);
}
/// <summary>
/// Gets the user that was banned.
/// </summary>
/// <remarks>
/// Will be <see langword="null"/> if the user is a 'Deleted User#....' because Discord does send user data for deleted users.
/// </remarks>
/// <returns>
/// A user object representing the banned user.
/// </returns>
public IUser Target { get; }
} }

View File

@@ -2,33 +2,32 @@ using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a adding a bot to a guild.
/// </summary>
public class BotAddAuditLogData : IAuditLogData
{ {
/// <summary> private BotAddAuditLogData(IUser bot)
/// Contains a piece of audit log data related to a adding a bot to a guild.
/// </summary>
public class BotAddAuditLogData : IAuditLogData
{ {
private BotAddAuditLogData(IUser bot) Target = bot;
{
Target = bot;
}
internal static BotAddAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var userInfo = log.Users.FirstOrDefault(x => x.Id == entry.TargetId);
return new BotAddAuditLogData((userInfo != null) ? RestUser.Create(discord, userInfo) : null);
}
/// <summary>
/// Gets the bot that was added.
/// </summary>
/// <remarks>
/// Will be <see langword="null"/> if the bot is a 'Deleted User#....' because Discord does send user data for deleted users.
/// </remarks>
/// <returns>
/// A user object representing the bot.
/// </returns>
public IUser Target { get; }
} }
internal static BotAddAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var userInfo = log.Users.FirstOrDefault(x => x.Id == entry.TargetId);
return new BotAddAuditLogData((userInfo != null) ? RestUser.Create(discord, userInfo) : null);
}
/// <summary>
/// Gets the bot that was added.
/// </summary>
/// <remarks>
/// Will be <see langword="null"/> if the bot is a 'Deleted User#....' because Discord does send user data for deleted users.
/// </remarks>
/// <returns>
/// A user object representing the bot.
/// </returns>
public IUser Target { get; }
} }

View File

@@ -1,104 +1,176 @@
using Discord.API.AuditLogs;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq; using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a channel creation.
/// </summary>
public class ChannelCreateAuditLogData : IAuditLogData
{ {
/// <summary> private ChannelCreateAuditLogData(ChannelInfoAuditLogModel model, EntryModel entry)
/// Contains a piece of audit log data related to a channel creation.
/// </summary>
public class ChannelCreateAuditLogData : IAuditLogData
{ {
private ChannelCreateAuditLogData(ulong id, string name, ChannelType type, int? rateLimit, bool? nsfw, int? bitrate, IReadOnlyCollection<Overwrite> overwrites) ChannelId = entry.TargetId!.Value;
ChannelName = model.Name;
ChannelType = model.Type!.Value;
SlowModeInterval = model.RateLimitPerUser;
IsNsfw = model.IsNsfw;
Bitrate = model.Bitrate;
Topic = model.Topic;
AutoArchiveDuration = model.AutoArchiveDuration;
DefaultSlowModeInterval = model.DefaultThreadRateLimitPerUser;
DefaultAutoArchiveDuration = model.DefaultArchiveDuration;
AvailableTags = model.AvailableTags?.Select(x => new ForumTag(x.Id,
x.Name,
x.EmojiId.GetValueOrDefault(null),
x.EmojiName.GetValueOrDefault(null),
x.Moderated)).ToImmutableArray();
if (model.DefaultEmoji is not null)
{ {
ChannelId = id; if (model.DefaultEmoji.EmojiId.HasValue && model.DefaultEmoji.EmojiId.Value != 0)
ChannelName = name; DefaultReactionEmoji = new Emote(model.DefaultEmoji.EmojiId.GetValueOrDefault(), null, false);
ChannelType = type; else if (model.DefaultEmoji.EmojiName.IsSpecified)
SlowModeInterval = rateLimit; DefaultReactionEmoji = new Emoji(model.DefaultEmoji.EmojiName.Value);
IsNsfw = nsfw; else
Bitrate = bitrate; DefaultReactionEmoji = null;
Overwrites = overwrites;
} }
else
DefaultReactionEmoji = null;
internal static ChannelCreateAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry) VideoQualityMode = model.VideoQualityMode;
{ RtcRegion = model.Region;
var changes = entry.Changes; Flags = model.Flags;
UserLimit = model.UserLimit;
var overwritesModel = changes.FirstOrDefault(x => x.ChangedProperty == "permission_overwrites"); Overwrites = model.Overwrites?.Select(x => new Overwrite(x.TargetId, x.TargetType, new OverwritePermissions(x.Allow, x.Deny)))
var typeModel = changes.FirstOrDefault(x => x.ChangedProperty == "type"); .ToImmutableArray();
var nameModel = changes.FirstOrDefault(x => x.ChangedProperty == "name");
var rateLimitPerUserModel = changes.FirstOrDefault(x => x.ChangedProperty == "rate_limit_per_user");
var nsfwModel = changes.FirstOrDefault(x => x.ChangedProperty == "nsfw");
var bitrateModel = changes.FirstOrDefault(x => x.ChangedProperty == "bitrate");
var overwrites = overwritesModel.NewValue.ToObject<API.Overwrite[]>(discord.ApiClient.Serializer)
.Select(x => new Overwrite(x.TargetId, x.TargetType, new OverwritePermissions(x.Allow, x.Deny)))
.ToList();
var type = typeModel.NewValue.ToObject<ChannelType>(discord.ApiClient.Serializer);
var name = nameModel.NewValue.ToObject<string>(discord.ApiClient.Serializer);
int? rateLimitPerUser = rateLimitPerUserModel?.NewValue?.ToObject<int>(discord.ApiClient.Serializer);
bool? nsfw = nsfwModel?.NewValue?.ToObject<bool>(discord.ApiClient.Serializer);
int? bitrate = bitrateModel?.NewValue?.ToObject<int>(discord.ApiClient.Serializer);
var id = entry.TargetId.Value;
return new ChannelCreateAuditLogData(id, name, type, rateLimitPerUser, nsfw, bitrate, overwrites.ToReadOnlyCollection());
}
/// <summary>
/// Gets the snowflake ID of the created channel.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the created channel.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the name of the created channel.
/// </summary>
/// <returns>
/// A string containing the name of the created channel.
/// </returns>
public string ChannelName { get; }
/// <summary>
/// Gets the type of the created channel.
/// </summary>
/// <returns>
/// The type of channel that was created.
/// </returns>
public ChannelType ChannelType { get; }
/// <summary>
/// Gets the current slow-mode delay of the created channel.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the time in seconds required before the user can send another
/// message; <c>0</c> if disabled.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public int? SlowModeInterval { get; }
/// <summary>
/// Gets the value that indicates whether the created channel is NSFW.
/// </summary>
/// <returns>
/// <c>true</c> if the created channel has the NSFW flag enabled; otherwise <c>false</c>.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public bool? IsNsfw { get; }
/// <summary>
/// Gets the bit-rate that the clients in the created voice channel are requested to use.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the bit-rate (bps) that the created voice channel defines and requests the
/// client(s) to use.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public int? Bitrate { get; }
/// <summary>
/// Gets a collection of permission overwrites that was assigned to the created channel.
/// </summary>
/// <returns>
/// A collection of permission <see cref="Overwrite"/>, containing the permission overwrites that were
/// assigned to the created channel.
/// </returns>
public IReadOnlyCollection<Overwrite> Overwrites { get; }
} }
internal static ChannelCreateAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log = null)
{
var changes = entry.Changes;
var (_, data) = AuditLogHelper.CreateAuditLogEntityInfo<ChannelInfoAuditLogModel>(changes, discord);
return new ChannelCreateAuditLogData(data, entry);
}
/// <summary>
/// Gets the snowflake ID of the created channel.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the created channel.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the name of the created channel.
/// </summary>
/// <returns>
/// A string containing the name of the created channel.
/// </returns>
public string ChannelName { get; }
/// <summary>
/// Gets the type of the created channel.
/// </summary>
/// <returns>
/// The type of channel that was created.
/// </returns>
public ChannelType ChannelType { get; }
/// <summary>
/// Gets the current slow-mode delay of the created channel.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the time in seconds required before the user can send another
/// message; <c>0</c> if disabled.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public int? SlowModeInterval { get; }
/// <summary>
/// Gets the value that indicates whether the created channel is NSFW.
/// </summary>
/// <returns>
/// <c>true</c> if the created channel has the NSFW flag enabled; otherwise <c>false</c>.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public bool? IsNsfw { get; }
/// <summary>
/// Gets the bit-rate that the clients in the created voice channel are requested to use.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the bit-rate (bps) that the created voice channel defines and requests the
/// client(s) to use.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public int? Bitrate { get; }
/// <summary>
/// Gets a collection of permission overwrites that was assigned to the created channel.
/// </summary>
/// <returns>
/// A collection of permission <see cref="Overwrite"/>, containing the permission overwrites that were
/// assigned to the created channel.
/// </returns>
public IReadOnlyCollection<Overwrite> Overwrites { get; }
/// <summary>
/// Gets the thread archive duration that was set in the created channel.
/// </summary>
public ThreadArchiveDuration? AutoArchiveDuration { get; }
/// <summary>
/// Gets the default thread archive duration that was set in the created channel.
/// </summary>
public ThreadArchiveDuration? DefaultAutoArchiveDuration { get; }
/// <summary>
/// Gets the default slow mode interval that will be set in child threads in the channel.
/// </summary>
public int? DefaultSlowModeInterval { get; }
/// <summary>
/// Gets the topic that was set in the created channel.
/// </summary>
public string Topic { get; }
/// <summary>
/// Gets tags available in the created forum channel.
/// </summary>
public IReadOnlyCollection<ForumTag> AvailableTags { get; }
/// <summary>
/// Gets the default reaction added to posts in the created forum channel.
/// </summary>
public IEmote DefaultReactionEmoji { get; }
/// <summary>
/// Gets the user limit configured in the created voice channel.
/// </summary>
public int? UserLimit { get; }
/// <summary>
/// Gets the video quality mode configured in the created voice channel.
/// </summary>
public VideoQualityMode? VideoQualityMode { get; }
/// <summary>
/// Gets the region configured in the created voice channel.
/// </summary>
public string RtcRegion { get; }
/// <summary>
/// Gets channel flags configured for the created channel.
/// </summary>
public ChannelFlags? Flags { get; }
} }

View File

@@ -1,102 +1,175 @@
using Discord.API.AuditLogs;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq; using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a channel deletion.
/// </summary>
public class ChannelDeleteAuditLogData : IAuditLogData
{ {
/// <summary> private ChannelDeleteAuditLogData(ChannelInfoAuditLogModel model, EntryModel entry)
/// Contains a piece of audit log data related to a channel deletion.
/// </summary>
public class ChannelDeleteAuditLogData : IAuditLogData
{ {
private ChannelDeleteAuditLogData(ulong id, string name, ChannelType type, int? rateLimit, bool? nsfw, int? bitrate, IReadOnlyCollection<Overwrite> overwrites) ChannelId = entry.TargetId!.Value;
ChannelType = model.Type!.Value;
ChannelName = model.Name;
Topic = model.Topic;
IsNsfw = model.IsNsfw;
Bitrate = model.Bitrate;
DefaultArchiveDuration = model.DefaultArchiveDuration;
SlowModeInterval = model.RateLimitPerUser;
ForumTags = model.AvailableTags?.Select(
x => new ForumTag(x.Id,
x.Name,
x.EmojiId.GetValueOrDefault(null),
x.EmojiName.GetValueOrDefault(null),
x.Moderated)).ToImmutableArray();
if (model.DefaultEmoji is not null)
{ {
ChannelId = id; if (model.DefaultEmoji.EmojiId.HasValue && model.DefaultEmoji.EmojiId.Value != 0)
ChannelName = name; DefaultReactionEmoji = new Emote(model.DefaultEmoji.EmojiId.GetValueOrDefault(), null, false);
ChannelType = type; else if (model.DefaultEmoji.EmojiName.IsSpecified)
SlowModeInterval = rateLimit; DefaultReactionEmoji = new Emoji(model.DefaultEmoji.EmojiName.Value);
IsNsfw = nsfw; else
Bitrate = bitrate; DefaultReactionEmoji = null;
Overwrites = overwrites;
} }
else
DefaultReactionEmoji = null;
AutoArchiveDuration = model.AutoArchiveDuration;
DefaultSlowModeInterval = model.DefaultThreadRateLimitPerUser;
internal static ChannelDeleteAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry) VideoQualityMode = model.VideoQualityMode;
{ RtcRegion = model.Region;
var changes = entry.Changes; Flags = model.Flags;
UserLimit = model.UserLimit;
var overwritesModel = changes.FirstOrDefault(x => x.ChangedProperty == "permission_overwrites"); Overwrites = model.Overwrites?.Select(x
var typeModel = changes.FirstOrDefault(x => x.ChangedProperty == "type"); => new Overwrite(x.TargetId,
var nameModel = changes.FirstOrDefault(x => x.ChangedProperty == "name"); x.TargetType,
var rateLimitPerUserModel = changes.FirstOrDefault(x => x.ChangedProperty == "rate_limit_per_user"); new OverwritePermissions(x.Allow, x.Deny))).ToImmutableArray();
var nsfwModel = changes.FirstOrDefault(x => x.ChangedProperty == "nsfw");
var bitrateModel = changes.FirstOrDefault(x => x.ChangedProperty == "bitrate");
var overwrites = overwritesModel.OldValue.ToObject<API.Overwrite[]>(discord.ApiClient.Serializer)
.Select(x => new Overwrite(x.TargetId, x.TargetType, new OverwritePermissions(x.Allow, x.Deny)))
.ToList();
var type = typeModel.OldValue.ToObject<ChannelType>(discord.ApiClient.Serializer);
var name = nameModel.OldValue.ToObject<string>(discord.ApiClient.Serializer);
int? rateLimitPerUser = rateLimitPerUserModel?.OldValue?.ToObject<int>(discord.ApiClient.Serializer);
bool? nsfw = nsfwModel?.OldValue?.ToObject<bool>(discord.ApiClient.Serializer);
int? bitrate = bitrateModel?.OldValue?.ToObject<int>(discord.ApiClient.Serializer);
var id = entry.TargetId.Value;
return new ChannelDeleteAuditLogData(id, name, type, rateLimitPerUser, nsfw, bitrate, overwrites.ToReadOnlyCollection());
}
/// <summary>
/// Gets the snowflake ID of the deleted channel.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the deleted channel.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the name of the deleted channel.
/// </summary>
/// <returns>
/// A string containing the name of the deleted channel.
/// </returns>
public string ChannelName { get; }
/// <summary>
/// Gets the type of the deleted channel.
/// </summary>
/// <returns>
/// The type of channel that was deleted.
/// </returns>
public ChannelType ChannelType { get; }
/// <summary>
/// Gets the slow-mode delay of the deleted channel.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the time in seconds required before the user can send another
/// message; <c>0</c> if disabled.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public int? SlowModeInterval { get; }
/// <summary>
/// Gets the value that indicates whether the deleted channel was NSFW.
/// </summary>
/// <returns>
/// <c>true</c> if this channel had the NSFW flag enabled; otherwise <c>false</c>.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public bool? IsNsfw { get; }
/// <summary>
/// Gets the bit-rate of this channel if applicable.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the bit-rate set of the voice channel.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public int? Bitrate { get; }
/// <summary>
/// Gets a collection of permission overwrites that was assigned to the deleted channel.
/// </summary>
/// <returns>
/// A collection of permission <see cref="Overwrite"/>.
/// </returns>
public IReadOnlyCollection<Overwrite> Overwrites { get; }
} }
internal static ChannelDeleteAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log = null)
{
var changes = entry.Changes;
var (data, _) = AuditLogHelper.CreateAuditLogEntityInfo<ChannelInfoAuditLogModel>(changes, discord);
return new ChannelDeleteAuditLogData(data, entry);
}
/// <summary>
/// Gets the snowflake ID of the deleted channel.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the deleted channel.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the name of the deleted channel.
/// </summary>
/// <returns>
/// A string containing the name of the deleted channel.
/// </returns>
public string ChannelName { get; }
/// <summary>
/// Gets the type of the deleted channel.
/// </summary>
/// <returns>
/// The type of channel that was deleted.
/// </returns>
public ChannelType ChannelType { get; }
/// <summary>
/// Gets the slow-mode delay of the deleted channel.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the time in seconds required before the user can send another
/// message; <c>0</c> if disabled.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public int? SlowModeInterval { get; }
/// <summary>
/// Gets the value that indicates whether the deleted channel was NSFW.
/// </summary>
/// <returns>
/// <c>true</c> if this channel had the NSFW flag enabled; otherwise <c>false</c>.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public bool? IsNsfw { get; }
/// <summary>
/// Gets the bit-rate of this channel if applicable.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the bit-rate set of the voice channel.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public int? Bitrate { get; }
/// <summary>
/// Gets a collection of permission overwrites that was assigned to the deleted channel.
/// </summary>
/// <returns>
/// A collection of permission <see cref="Overwrite"/>.
/// </returns>
public IReadOnlyCollection<Overwrite> Overwrites { get; }
/// <summary>
/// Gets the user limit configured in the created voice channel.
/// </summary>
public int? UserLimit { get; }
/// <summary>
/// Gets the video quality mode configured in the created voice channel.
/// </summary>
public VideoQualityMode? VideoQualityMode { get; }
/// <summary>
/// Gets the region configured in the created voice channel.
/// </summary>
public string RtcRegion { get; }
/// <summary>
/// Gets channel flags configured for the created channel.
/// </summary>
public ChannelFlags? Flags { get; }
/// <summary>
/// Gets the thread archive duration that was configured for the created channel.
/// </summary>
public ThreadArchiveDuration? AutoArchiveDuration { get; }
/// <summary>
/// Gets the default slow mode interval that was configured for the channel.
/// </summary>
public int? DefaultSlowModeInterval { get; }
/// <inheritdoc cref="ITextChannel.DefaultArchiveDuration"/>
/// <remarks>
/// <see langword="null" /> if the value was not specified in this entry..
/// </remarks>
public ThreadArchiveDuration? DefaultArchiveDuration { get; }
/// <inheritdoc cref="IForumChannel.Tags"/>
/// <remarks>
/// <see langword="null" /> if the value was not specified in this entry..
/// </remarks>
public IReadOnlyCollection<ForumTag> ForumTags { get; }
/// <inheritdoc cref="ITextChannel.Topic"/>
/// <remarks>
/// <see langword="null" /> if the value was not specified in this entry..
/// </remarks>
public string Topic { get; }
/// <inheritdoc cref="IForumChannel.DefaultReactionEmoji"/>
/// <remarks>
/// <see langword="null" /> if the value was not specified in this entry..
/// </remarks>
public IEmote DefaultReactionEmoji { get; }
} }

View File

@@ -1,3 +1,8 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Model = Discord.API.AuditLogs.ChannelInfoAuditLogModel;
namespace Discord.Rest namespace Discord.Rest
{ {
/// <summary> /// <summary>
@@ -5,14 +10,41 @@ namespace Discord.Rest
/// </summary> /// </summary>
public struct ChannelInfo public struct ChannelInfo
{ {
internal ChannelInfo(string name, string topic, int? rateLimit, bool? nsfw, int? bitrate, ChannelType? type) internal ChannelInfo(Model model)
{ {
Name = name; Name = model.Name;
Topic = topic; Topic = model.Topic;
SlowModeInterval = rateLimit; IsNsfw = model.IsNsfw;
IsNsfw = nsfw; Bitrate = model.Bitrate;
Bitrate = bitrate; DefaultArchiveDuration = model.DefaultArchiveDuration;
ChannelType = type; ChannelType = model.Type;
SlowModeInterval = model.RateLimitPerUser;
ForumTags = model.AvailableTags?.Select(
x => new ForumTag(x.Id,
x.Name,
x.EmojiId.GetValueOrDefault(null),
x.EmojiName.GetValueOrDefault(null),
x.Moderated)).ToImmutableArray();
if (model.DefaultEmoji is not null)
{
if (model.DefaultEmoji.EmojiId.HasValue && model.DefaultEmoji.EmojiId.Value != 0)
DefaultReactionEmoji = new Emote(model.DefaultEmoji.EmojiId.GetValueOrDefault(), null, false);
else if (model.DefaultEmoji.EmojiName.IsSpecified)
DefaultReactionEmoji = new Emoji(model.DefaultEmoji.EmojiName.Value);
else
DefaultReactionEmoji = null;
}
else
DefaultReactionEmoji = null;
AutoArchiveDuration = model.AutoArchiveDuration;
DefaultSlowModeInterval = model.DefaultThreadRateLimitPerUser;
VideoQualityMode = model.VideoQualityMode;
RtcRegion = model.Region;
Flags = model.Flags;
UserLimit = model.UserLimit;
} }
/// <summary> /// <summary>
@@ -61,5 +93,53 @@ namespace Discord.Rest
/// The channel type of this channel; <c>null</c> if not applicable. /// The channel type of this channel; <c>null</c> if not applicable.
/// </returns> /// </returns>
public ChannelType? ChannelType { get; } public ChannelType? ChannelType { get; }
/// <inheritdoc cref="ITextChannel.DefaultArchiveDuration"/>
/// <remarks>
/// <see langword="null" /> if the value was not updated in this entry.
/// </remarks>
public ThreadArchiveDuration? DefaultArchiveDuration { get; }
/// <inheritdoc cref="IForumChannel.Tags"/>
/// <remarks>
/// <see langword="null" /> if the value was not updated in this entry.
/// </remarks>
public IReadOnlyCollection<ForumTag> ForumTags { get; }
/// <inheritdoc cref="IForumChannel.DefaultReactionEmoji"/>
/// <remarks>
/// <see langword="null" /> if the value was not updated in this entry.
/// </remarks>
public IEmote DefaultReactionEmoji { get; }
/// <summary>
/// Gets the user limit configured in the created voice channel.
/// </summary>
public int? UserLimit { get; }
/// <summary>
/// Gets the video quality mode configured in the created voice channel.
/// </summary>
public VideoQualityMode? VideoQualityMode { get; }
/// <summary>
/// Gets the region configured in the created voice channel.
/// </summary>
public string RtcRegion { get; }
/// <summary>
/// Gets channel flags configured for the created channel.
/// </summary>
public ChannelFlags? Flags { get; }
/// <summary>
/// Gets the thread archive duration that was set in the created channel.
/// </summary>
public ThreadArchiveDuration? AutoArchiveDuration { get; }
/// <summary>
/// Gets the default slow mode interval that will be set in child threads in the channel.
/// </summary>
public int? DefaultSlowModeInterval { get; }
} }
} }

View File

@@ -1,3 +1,4 @@
using Discord.API.AuditLogs;
using System.Linq; using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
@@ -16,34 +17,13 @@ namespace Discord.Rest
After = after; After = after;
} }
internal static ChannelUpdateAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry) internal static ChannelUpdateAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log = null)
{ {
var changes = entry.Changes; var changes = entry.Changes;
var nameModel = changes.FirstOrDefault(x => x.ChangedProperty == "name"); var (before, after) = AuditLogHelper.CreateAuditLogEntityInfo<ChannelInfoAuditLogModel>(changes, discord);
var topicModel = changes.FirstOrDefault(x => x.ChangedProperty == "topic");
var rateLimitPerUserModel = changes.FirstOrDefault(x => x.ChangedProperty == "rate_limit_per_user");
var nsfwModel = changes.FirstOrDefault(x => x.ChangedProperty == "nsfw");
var bitrateModel = changes.FirstOrDefault(x => x.ChangedProperty == "bitrate");
var typeModel = changes.FirstOrDefault(x => x.ChangedProperty == "type");
string oldName = nameModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer), return new ChannelUpdateAuditLogData(entry.TargetId!.Value, new ChannelInfo(before), new ChannelInfo(after));
newName = nameModel?.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
string oldTopic = topicModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer),
newTopic = topicModel?.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
int? oldRateLimitPerUser = rateLimitPerUserModel?.OldValue?.ToObject<int>(discord.ApiClient.Serializer),
newRateLimitPerUser = rateLimitPerUserModel?.NewValue?.ToObject<int>(discord.ApiClient.Serializer);
bool? oldNsfw = nsfwModel?.OldValue?.ToObject<bool>(discord.ApiClient.Serializer),
newNsfw = nsfwModel?.NewValue?.ToObject<bool>(discord.ApiClient.Serializer);
int? oldBitrate = bitrateModel?.OldValue?.ToObject<int>(discord.ApiClient.Serializer),
newBitrate = bitrateModel?.NewValue?.ToObject<int>(discord.ApiClient.Serializer);
ChannelType? oldType = typeModel?.OldValue?.ToObject<ChannelType>(discord.ApiClient.Serializer),
newType = typeModel?.NewValue?.ToObject<ChannelType>(discord.ApiClient.Serializer);
var before = new ChannelInfo(oldName, oldTopic, oldRateLimitPerUser, oldNsfw, oldBitrate, oldType);
var after = new ChannelInfo(newName, newTopic, newRateLimitPerUser, newNsfw, newBitrate, newType);
return new ChannelUpdateAuditLogData(entry.TargetId.Value, before, after);
} }
/// <summary> /// <summary>

View File

@@ -0,0 +1,69 @@
using Discord.API;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog;
namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to an application command permission update.
/// </summary>
public class CommandPermissionUpdateAuditLogData : IAuditLogData
{
internal CommandPermissionUpdateAuditLogData(IReadOnlyCollection<ApplicationCommandPermission> before, IReadOnlyCollection<ApplicationCommandPermission> after,
IApplicationCommand command, ulong appId)
{
Before = before;
After = after;
ApplicationCommand = command;
ApplicationId = appId;
}
internal static CommandPermissionUpdateAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var changes = entry.Changes;
var before = new List<ApplicationCommandPermission>();
var after = new List<ApplicationCommandPermission>();
foreach (var change in changes)
{
var oldValue = change.OldValue?.ToObject<API.ApplicationCommandPermissions>();
var newValue = change.NewValue?.ToObject<API.ApplicationCommandPermissions>();
if (oldValue is not null)
before.Add(new ApplicationCommandPermission(oldValue.Id, oldValue.Type, oldValue.Permission));
if (newValue is not null)
after.Add(new ApplicationCommandPermission(newValue.Id, newValue.Type, newValue.Permission));
}
var command = log.Commands.FirstOrDefault(x => x.Id == entry.TargetId);
var appCommand = RestApplicationCommand.Create(discord, command, command?.GuildId.IsSpecified ?? false ? command.GuildId.Value : null);
return new(before.ToImmutableArray(), after.ToImmutableArray(), appCommand, entry.Options.ApplicationId!.Value);
}
/// <summary>
/// Gets the ID of the app whose permissions were targeted.
/// </summary>
public ulong ApplicationId { get; set; }
/// <summary>
/// Gets the application command which permissions were updated.
/// </summary>
public IApplicationCommand ApplicationCommand { get; }
/// <summary>
/// Gets values of the permissions before the change if available.
/// </summary>
public IReadOnlyCollection<ApplicationCommandPermission> Before { get; }
/// <summary>
/// Gets values of the permissions after the change if available.
/// </summary>
public IReadOnlyCollection<ApplicationCommandPermission> After { get; }
}

View File

@@ -1,41 +1,42 @@
using System.Linq; using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to an emoji creation.
/// </summary>
public class EmoteCreateAuditLogData : IAuditLogData
{ {
/// <summary> private EmoteCreateAuditLogData(ulong id, string name)
/// Contains a piece of audit log data related to an emoji creation.
/// </summary>
public class EmoteCreateAuditLogData : IAuditLogData
{ {
private EmoteCreateAuditLogData(ulong id, string name) EmoteId = id;
{ Name = name;
EmoteId = id;
Name = name;
}
internal static EmoteCreateAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var change = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "name");
var emoteName = change.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
return new EmoteCreateAuditLogData(entry.TargetId.Value, emoteName);
}
/// <summary>
/// Gets the snowflake ID of the created emoji.
/// </summary>
/// <returns>
/// A <see cref="System.UInt64"/> representing the snowflake identifier for the created emoji.
/// </returns>
public ulong EmoteId { get; }
/// <summary>
/// Gets the name of the created emoji.
/// </summary>
/// <returns>
/// A string containing the name of the created emoji.
/// </returns>
public string Name { get; }
} }
internal static EmoteCreateAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var change = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "name");
var emoteName = change.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
return new EmoteCreateAuditLogData(entry.TargetId.Value, emoteName);
}
/// <summary>
/// Gets the snowflake ID of the created emoji.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the created emoji.
/// </returns>
public ulong EmoteId { get; }
/// <summary>
/// Gets the name of the created emoji.
/// </summary>
/// <returns>
/// A string containing the name of the created emoji.
/// </returns>
public string Name { get; }
} }

View File

@@ -2,41 +2,41 @@ using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to an emoji deletion.
/// </summary>
public class EmoteDeleteAuditLogData : IAuditLogData
{ {
/// <summary> private EmoteDeleteAuditLogData(ulong id, string name)
/// Contains a piece of audit log data related to an emoji deletion.
/// </summary>
public class EmoteDeleteAuditLogData : IAuditLogData
{ {
private EmoteDeleteAuditLogData(ulong id, string name) EmoteId = id;
{ Name = name;
EmoteId = id;
Name = name;
}
internal static EmoteDeleteAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var change = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "name");
var emoteName = change.OldValue?.ToObject<string>(discord.ApiClient.Serializer);
return new EmoteDeleteAuditLogData(entry.TargetId.Value, emoteName);
}
/// <summary>
/// Gets the snowflake ID of the deleted emoji.
/// </summary>
/// <returns>
/// A <see cref="System.UInt64"/> representing the snowflake identifier for the deleted emoji.
/// </returns>
public ulong EmoteId { get; }
/// <summary>
/// Gets the name of the deleted emoji.
/// </summary>
/// <returns>
/// A string containing the name of the deleted emoji.
/// </returns>
public string Name { get; }
} }
internal static EmoteDeleteAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var change = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "name");
var emoteName = change.OldValue?.ToObject<string>(discord.ApiClient.Serializer);
return new EmoteDeleteAuditLogData(entry.TargetId.Value, emoteName);
}
/// <summary>
/// Gets the snowflake ID of the deleted emoji.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the deleted emoji.
/// </returns>
public ulong EmoteId { get; }
/// <summary>
/// Gets the name of the deleted emoji.
/// </summary>
/// <returns>
/// A string containing the name of the deleted emoji.
/// </returns>
public string Name { get; }
} }

View File

@@ -1,51 +1,53 @@
using System.Linq; using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to an emoji update.
/// </summary>
public class EmoteUpdateAuditLogData : IAuditLogData
{ {
/// <summary> private EmoteUpdateAuditLogData(ulong id, string oldName, string newName)
/// Contains a piece of audit log data related to an emoji update.
/// </summary>
public class EmoteUpdateAuditLogData : IAuditLogData
{ {
private EmoteUpdateAuditLogData(ulong id, string oldName, string newName) EmoteId = id;
{ OldName = oldName;
EmoteId = id; NewName = newName;
OldName = oldName;
NewName = newName;
}
internal static EmoteUpdateAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var change = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "name");
var newName = change.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
var oldName = change.OldValue?.ToObject<string>(discord.ApiClient.Serializer);
return new EmoteUpdateAuditLogData(entry.TargetId.Value, oldName, newName);
}
/// <summary>
/// Gets the snowflake ID of the updated emoji.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier of the updated emoji.
/// </returns>
public ulong EmoteId { get; }
/// <summary>
/// Gets the new name of the updated emoji.
/// </summary>
/// <returns>
/// A string containing the new name of the updated emoji.
/// </returns>
public string NewName { get; }
/// <summary>
/// Gets the old name of the updated emoji.
/// </summary>
/// <returns>
/// A string containing the old name of the updated emoji.
/// </returns>
public string OldName { get; }
} }
internal static EmoteUpdateAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var change = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "name");
var newName = change.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
var oldName = change.OldValue?.ToObject<string>(discord.ApiClient.Serializer);
return new EmoteUpdateAuditLogData(entry.TargetId.Value, oldName, newName);
}
/// <summary>
/// Gets the snowflake ID of the updated emoji.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier of the updated emoji.
/// </returns>
public ulong EmoteId { get; }
/// <summary>
/// Gets the new name of the updated emoji.
/// </summary>
/// <returns>
/// A string containing the new name of the updated emoji.
/// </returns>
public string NewName { get; }
/// <summary>
/// Gets the old name of the updated emoji.
/// </summary>
/// <returns>
/// A string containing the old name of the updated emoji.
/// </returns>
public string OldName { get; }
} }

View File

@@ -1,128 +1,218 @@
namespace Discord.Rest using Model = Discord.API.AuditLogs.GuildInfoAuditLogModel;
{
/// <summary>
/// Represents information for a guild.
/// </summary>
public struct GuildInfo
{
internal GuildInfo(int? afkTimeout, DefaultMessageNotifications? defaultNotifs,
ulong? afkChannel, string name, string region, string icon,
VerificationLevel? verification, IUser owner, MfaLevel? mfa, ExplicitContentFilterLevel? filter,
ulong? systemChannel, ulong? widgetChannel, bool? widget)
{
AfkTimeout = afkTimeout;
DefaultMessageNotifications = defaultNotifs;
AfkChannelId = afkChannel;
Name = name;
RegionId = region;
IconHash = icon;
VerificationLevel = verification;
Owner = owner;
MfaLevel = mfa;
ExplicitContentFilter = filter;
SystemChannelId = systemChannel;
EmbedChannelId = widgetChannel;
IsEmbeddable = widget;
}
/// <summary> namespace Discord.Rest;
/// Gets the amount of time (in seconds) a user must be inactive in a voice channel for until they are
/// automatically moved to the AFK voice channel. /// <summary>
/// </summary> /// Represents information for a guild.
/// <returns> /// </summary>
/// An <see cref="int"/> representing the amount of time in seconds for a user to be marked as inactive public struct GuildInfo
/// and moved into the AFK voice channel. {
/// <c>null</c> if this is not mentioned in this entry. internal GuildInfo(Model model, IUser owner)
/// </returns> {
public int? AfkTimeout { get; } Owner = owner;
/// <summary>
/// Gets the default message notifications for users who haven't explicitly set their notification settings. Name = model.Name;
/// </summary> AfkTimeout = model.AfkTimeout.GetValueOrDefault();
/// <returns> IsEmbeddable = model.IsEmbeddable;
/// The default message notifications setting of this guild. DefaultMessageNotifications = model.DefaultMessageNotifications;
/// <c>null</c> if this is not mentioned in this entry. MfaLevel = model.MfaLevel;
/// </returns> Description = model.Description;
public DefaultMessageNotifications? DefaultMessageNotifications { get; } PreferredLocale = model.PreferredLocale;
/// <summary> IconHash = model.IconHash;
/// Gets the ID of the AFK voice channel for this guild. OwnerId = model.OwnerId;
/// </summary> AfkChannelId = model.AfkChannelId;
/// <returns> ApplicationId = model.ApplicationId;
/// A <see cref="ulong"/> representing the snowflake identifier of the AFK voice channel; <c>null</c> if BannerId = model.Banner;
/// none is set. DiscoverySplashId = model.DiscoverySplash;
/// </returns> EmbedChannelId = model.EmbeddedChannelId;
public ulong? AfkChannelId { get; } ExplicitContentFilter = model.ExplicitContentFilterLevel;
/// <summary> IsBoostProgressBarEnabled = model.ProgressBarEnabled;
/// Gets the name of this guild. NsfwLevel = model.NsfwLevel;
/// </summary> PublicUpdatesChannelId = model.PublicUpdatesChannelId;
/// <returns> RegionId = model.RegionId;
/// A string containing the name of this guild. RulesChannelId = model.RulesChannelId;
/// </returns> SplashId = model.Splash;
public string Name { get; } SystemChannelFlags = model.SystemChannelFlags;
/// <summary> SystemChannelId = model.SystemChannelId;
/// Gets the ID of the region hosting this guild's voice channels. VanityURLCode = model.VanityUrl;
/// </summary> VerificationLevel = model.VerificationLevel;
public string RegionId { get; }
/// <summary>
/// Gets the ID of this guild's icon.
/// </summary>
/// <returns>
/// A string containing the identifier for the splash image; <c>null</c> if none is set.
/// </returns>
public string IconHash { get; }
/// <summary>
/// Gets the level of requirements a user must fulfill before being allowed to post messages in this guild.
/// </summary>
/// <returns>
/// The level of requirements.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public VerificationLevel? VerificationLevel { get; }
/// <summary>
/// Gets the owner of this guild.
/// </summary>
/// <returns>
/// A user object representing the owner of this guild.
/// </returns>
public IUser Owner { get; }
/// <summary>
/// Gets the level of Multi-Factor Authentication requirements a user must fulfill before being allowed to
/// perform administrative actions in this guild.
/// </summary>
/// <returns>
/// The level of MFA requirement.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public MfaLevel? MfaLevel { get; }
/// <summary>
/// Gets the level of content filtering applied to user's content in a Guild.
/// </summary>
/// <returns>
/// The level of explicit content filtering.
/// </returns>
public ExplicitContentFilterLevel? ExplicitContentFilter { get; }
/// <summary>
/// Gets the ID of the channel where system messages are sent.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier of the channel where system
/// messages are sent; <c>null</c> if none is set.
/// </returns>
public ulong? SystemChannelId { get; }
/// <summary>
/// Gets the ID of the widget embed channel of this guild.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier of the embedded channel found within the
/// widget settings of this guild; <c>null</c> if none is set.
/// </returns>
public ulong? EmbedChannelId { get; }
/// <summary>
/// Gets a value that indicates whether this guild is embeddable (i.e. can use widget).
/// </summary>
/// <returns>
/// <c>true</c> if this guild can be embedded via widgets; otherwise <c>false</c>.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public bool? IsEmbeddable { get; }
} }
/// <inheritdoc cref="IGuild.DiscoverySplashId"/>
/// <remarks>
/// <see langword="null" /> if the value was not updated in this entry.
/// </remarks>
public string DiscoverySplashId { get; }
/// <inheritdoc cref="IGuild.SplashId"/>
/// <remarks>
/// <see langword="null" /> if the value was not updated in this entry.
/// </remarks>
public string SplashId { get; }
/// <inheritdoc cref="IGuild.RulesChannelId"/>
/// <remarks>
/// <see langword="null" /> if the value was not updated in this entry.
/// </remarks>
public ulong? RulesChannelId { get; }
/// <inheritdoc cref="IGuild.PublicUpdatesChannelId"/>
/// <remarks>
/// <see langword="null" /> if the value was not updated in this entry.
/// </remarks>
public ulong? PublicUpdatesChannelId { get; }
/// <inheritdoc cref="IGuild.OwnerId"/>
/// <remarks>
/// <see langword="null" /> if the value was not updated in this entry.
/// </remarks>
public ulong? OwnerId { get; }
/// <inheritdoc cref="IGuild.ApplicationId"/>
/// <remarks>
/// <see langword="null" /> if the value was not updated in this entry.
/// </remarks>
public ulong? ApplicationId { get; }
/// <inheritdoc cref="IGuild.BannerId"/>
/// <remarks>
/// <see langword="null" /> if the value was not updated in this entry.
/// </remarks>
public string BannerId { get; }
/// <inheritdoc cref="IGuild.VanityURLCode"/>
/// <remarks>
/// <see langword="null" /> if the value was not updated in this entry.
/// </remarks>
public string VanityURLCode { get; }
/// <inheritdoc cref="IGuild.SystemChannelFlags"/>
/// <remarks>
/// <see langword="null" /> if the value was not updated in this entry.
/// </remarks>
public SystemChannelMessageDeny? SystemChannelFlags { get; }
/// <inheritdoc cref="IGuild.Description"/>
/// <remarks>
/// <see langword="null" /> if the value was not updated in this entry.
/// </remarks>
public string Description { get; }
/// <inheritdoc cref="IGuild.PreferredLocale"/>
/// <remarks>
/// <see langword="null" /> if the value was not updated in this entry.
/// </remarks>
public string PreferredLocale { get; }
/// <inheritdoc cref="IGuild.NsfwLevel"/>
/// <remarks>
/// <see langword="null" /> if the value was not updated in this entry.
/// </remarks>
public NsfwLevel? NsfwLevel { get; }
/// <inheritdoc cref="IGuild.IsBoostProgressBarEnabled"/>
/// <remarks>
/// <see langword="null" /> if the value was not updated in this entry.
/// </remarks>
public bool? IsBoostProgressBarEnabled { get; }
/// <summary>
/// Gets the amount of time (in seconds) a user must be inactive in a voice channel for until they are
/// automatically moved to the AFK voice channel.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the amount of time in seconds for a user to be marked as inactive
/// and moved into the AFK voice channel.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public int? AfkTimeout { get; }
/// <summary>
/// Gets the default message notifications for users who haven't explicitly set their notification settings.
/// </summary>
/// <returns>
/// The default message notifications setting of this guild.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public DefaultMessageNotifications? DefaultMessageNotifications { get; }
/// <summary>
/// Gets the ID of the AFK voice channel for this guild.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier of the AFK voice channel; <c>null</c> if
/// none is set.
/// </returns>
public ulong? AfkChannelId { get; }
/// <summary>
/// Gets the name of this guild.
/// </summary>
/// <returns>
/// A string containing the name of this guild.
/// </returns>
public string Name { get; }
/// <summary>
/// Gets the ID of the region hosting this guild's voice channels.
/// </summary>
public string RegionId { get; }
/// <summary>
/// Gets the ID of this guild's icon.
/// </summary>
/// <returns>
/// A string containing the identifier for the splash image; <c>null</c> if none is set.
/// </returns>
public string IconHash { get; }
/// <summary>
/// Gets the level of requirements a user must fulfill before being allowed to post messages in this guild.
/// </summary>
/// <returns>
/// The level of requirements.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public VerificationLevel? VerificationLevel { get; }
/// <summary>
/// Gets the owner of this guild.
/// </summary>
/// <returns>
/// A user object representing the owner of this guild.
/// </returns>
public IUser Owner { get; }
/// <summary>
/// Gets the level of Multi-Factor Authentication requirements a user must fulfill before being allowed to
/// perform administrative actions in this guild.
/// </summary>
/// <returns>
/// The level of MFA requirement.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public MfaLevel? MfaLevel { get; }
/// <summary>
/// Gets the level of content filtering applied to user's content in a Guild.
/// </summary>
/// <returns>
/// The level of explicit content filtering.
/// </returns>
public ExplicitContentFilterLevel? ExplicitContentFilter { get; }
/// <summary>
/// Gets the ID of the channel where system messages are sent.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier of the channel where system
/// messages are sent; <c>null</c> if none is set.
/// </returns>
public ulong? SystemChannelId { get; }
/// <summary>
/// Gets the ID of the widget embed channel of this guild.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier of the embedded channel found within the
/// widget settings of this guild; <c>null</c> if none is set.
/// </returns>
public ulong? EmbedChannelId { get; }
/// <summary>
/// Gets a value that indicates whether this guild is embeddable (i.e. can use widget).
/// </summary>
/// <returns>
/// <c>true</c> if this guild can be embedded via widgets; otherwise <c>false</c>.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public bool? IsEmbeddable { get; }
} }

View File

@@ -1,3 +1,4 @@
using Discord.API.AuditLogs;
using System.Linq; using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
@@ -15,50 +16,14 @@ namespace Discord.Rest
After = after; After = after;
} }
internal static GuildUpdateAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry) internal static GuildUpdateAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log = null)
{ {
var changes = entry.Changes; var changes = entry.Changes;
var afkTimeoutModel = changes.FirstOrDefault(x => x.ChangedProperty == "afk_timeout");
var defaultMessageNotificationsModel = changes.FirstOrDefault(x => x.ChangedProperty == "default_message_notifications");
var afkChannelModel = changes.FirstOrDefault(x => x.ChangedProperty == "afk_channel_id");
var nameModel = changes.FirstOrDefault(x => x.ChangedProperty == "name");
var regionIdModel = changes.FirstOrDefault(x => x.ChangedProperty == "region");
var iconHashModel = changes.FirstOrDefault(x => x.ChangedProperty == "icon_hash");
var verificationLevelModel = changes.FirstOrDefault(x => x.ChangedProperty == "verification_level");
var ownerIdModel = changes.FirstOrDefault(x => x.ChangedProperty == "owner_id"); var ownerIdModel = changes.FirstOrDefault(x => x.ChangedProperty == "owner_id");
var mfaLevelModel = changes.FirstOrDefault(x => x.ChangedProperty == "mfa_level");
var contentFilterModel = changes.FirstOrDefault(x => x.ChangedProperty == "explicit_content_filter");
var systemChannelIdModel = changes.FirstOrDefault(x => x.ChangedProperty == "system_channel_id");
var widgetChannelIdModel = changes.FirstOrDefault(x => x.ChangedProperty == "widget_channel_id");
var widgetEnabledModel = changes.FirstOrDefault(x => x.ChangedProperty == "widget_enabled");
int? oldAfkTimeout = afkTimeoutModel?.OldValue?.ToObject<int>(discord.ApiClient.Serializer),
newAfkTimeout = afkTimeoutModel?.NewValue?.ToObject<int>(discord.ApiClient.Serializer);
DefaultMessageNotifications? oldDefaultMessageNotifications = defaultMessageNotificationsModel?.OldValue?.ToObject<DefaultMessageNotifications>(discord.ApiClient.Serializer),
newDefaultMessageNotifications = defaultMessageNotificationsModel?.NewValue?.ToObject<DefaultMessageNotifications>(discord.ApiClient.Serializer);
ulong? oldAfkChannelId = afkChannelModel?.OldValue?.ToObject<ulong>(discord.ApiClient.Serializer),
newAfkChannelId = afkChannelModel?.NewValue?.ToObject<ulong>(discord.ApiClient.Serializer);
string oldName = nameModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer),
newName = nameModel?.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
string oldRegionId = regionIdModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer),
newRegionId = regionIdModel?.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
string oldIconHash = iconHashModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer),
newIconHash = iconHashModel?.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
VerificationLevel? oldVerificationLevel = verificationLevelModel?.OldValue?.ToObject<VerificationLevel>(discord.ApiClient.Serializer),
newVerificationLevel = verificationLevelModel?.NewValue?.ToObject<VerificationLevel>(discord.ApiClient.Serializer);
ulong? oldOwnerId = ownerIdModel?.OldValue?.ToObject<ulong>(discord.ApiClient.Serializer), ulong? oldOwnerId = ownerIdModel?.OldValue?.ToObject<ulong>(discord.ApiClient.Serializer),
newOwnerId = ownerIdModel?.NewValue?.ToObject<ulong>(discord.ApiClient.Serializer); newOwnerId = ownerIdModel?.NewValue?.ToObject<ulong>(discord.ApiClient.Serializer);
MfaLevel? oldMfaLevel = mfaLevelModel?.OldValue?.ToObject<MfaLevel>(discord.ApiClient.Serializer),
newMfaLevel = mfaLevelModel?.NewValue?.ToObject<MfaLevel>(discord.ApiClient.Serializer);
ExplicitContentFilterLevel? oldContentFilter = contentFilterModel?.OldValue?.ToObject<ExplicitContentFilterLevel>(discord.ApiClient.Serializer),
newContentFilter = contentFilterModel?.NewValue?.ToObject<ExplicitContentFilterLevel>(discord.ApiClient.Serializer);
ulong? oldSystemChannelId = systemChannelIdModel?.OldValue?.ToObject<ulong>(discord.ApiClient.Serializer),
newSystemChannelId = systemChannelIdModel?.NewValue?.ToObject<ulong>(discord.ApiClient.Serializer);
ulong? oldWidgetChannelId = widgetChannelIdModel?.OldValue?.ToObject<ulong>(discord.ApiClient.Serializer),
newWidgetChannelId = widgetChannelIdModel?.NewValue?.ToObject<ulong>(discord.ApiClient.Serializer);
bool? oldWidgetEnabled = widgetEnabledModel?.OldValue?.ToObject<bool>(discord.ApiClient.Serializer),
newWidgetEnabled = widgetEnabledModel?.NewValue?.ToObject<bool>(discord.ApiClient.Serializer);
IUser oldOwner = null; IUser oldOwner = null;
if (oldOwnerId != null) if (oldOwnerId != null)
@@ -74,14 +39,9 @@ namespace Discord.Rest
newOwner = RestUser.Create(discord, newOwnerInfo); newOwner = RestUser.Create(discord, newOwnerInfo);
} }
var before = new GuildInfo(oldAfkTimeout, oldDefaultMessageNotifications, var (before, after) = AuditLogHelper.CreateAuditLogEntityInfo<GuildInfoAuditLogModel>(changes, discord);
oldAfkChannelId, oldName, oldRegionId, oldIconHash, oldVerificationLevel, oldOwner,
oldMfaLevel, oldContentFilter, oldSystemChannelId, oldWidgetChannelId, oldWidgetEnabled);
var after = new GuildInfo(newAfkTimeout, newDefaultMessageNotifications,
newAfkChannelId, newName, newRegionId, newIconHash, newVerificationLevel, newOwner,
newMfaLevel, newContentFilter, newSystemChannelId, newWidgetChannelId, newWidgetEnabled);
return new GuildUpdateAuditLogData(before, after); return new GuildUpdateAuditLogData(new(before, oldOwner), new(after, newOwner));
} }
/// <summary> /// <summary>

View File

@@ -0,0 +1,39 @@
using Discord.API.AuditLogs;
using System.Linq;
using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog;
namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to an integration authorization.
/// </summary>
public class IntegrationCreatedAuditLogData : IAuditLogData
{
internal IntegrationCreatedAuditLogData(IntegrationInfo info, IIntegration integration)
{
Integration = integration;
Data = info;
}
internal static IntegrationCreatedAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var changes = entry.Changes;
var (_, data) = AuditLogHelper.CreateAuditLogEntityInfo<IntegrationInfoAuditLogModel>(changes, discord);
var integration = RestIntegration.Create(discord, null, log.Integrations.FirstOrDefault(x => x.Id == entry.TargetId));
return new(new IntegrationInfo(data), integration);
}
/// <summary>
/// Gets the partial integration the changes correspond to.
/// </summary>
public IIntegration Integration { get; }
/// <summary>
/// Gets the integration information after the changes.
/// </summary>
public IntegrationInfo Data { get; }
}

View File

@@ -0,0 +1,31 @@
using Discord.API.AuditLogs;
using System.Linq;
using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog;
namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to an integration removal.
/// </summary>
public class IntegrationDeletedAuditLogData : IAuditLogData
{
internal IntegrationDeletedAuditLogData(IntegrationInfo info)
{
Data = info;
}
internal static IntegrationDeletedAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var changes = entry.Changes;
var (data, _) = AuditLogHelper.CreateAuditLogEntityInfo<IntegrationInfoAuditLogModel>(changes, discord);
return new(new IntegrationInfo(data));
}
/// <summary>
/// Gets the integration information before the changes.
/// </summary>
public IntegrationInfo Data { get; }
}

View File

@@ -0,0 +1,69 @@
using Discord.API.AuditLogs;
using System.Collections.Generic;
using System.Collections.Immutable;
namespace Discord.Rest;
/// <summary>
/// Represents information for an integration.
/// </summary>
public class IntegrationInfo
{
internal IntegrationInfo(IntegrationInfoAuditLogModel model)
{
Name = model.Name;
Type = model.Type;
EnableEmojis = model.EnableEmojis;
Enabled = model.Enabled;
Scopes = model.Scopes?.ToImmutableArray();
ExpireBehavior = model.ExpireBehavior;
ExpireGracePeriod = model.ExpireGracePeriod;
Syncing = model.Syncing;
RoleId = model.RoleId;
}
/// <summary>
/// Gets the name of the integration. <see landword="null"/> if the property was not mentioned in this audit log.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Gets the type of the integration. <see landword="null"/> if the property was not mentioned in this audit log.
/// </summary>
public string Type { get; set; }
/// <summary>
/// Gets if the integration is enabled. <see landword="null"/> if the property was not mentioned in this audit log.
/// </summary>
public bool? Enabled { get; set; }
/// <summary>
/// Gets if syncing is enabled for this integration. <see landword="null"/> if the property was not mentioned in this audit log.
/// </summary>
public bool? Syncing { get; set; }
/// <summary>
/// Gets the id of the role that this integration uses for subscribers. <see landword="null"/> if the property was not mentioned in this audit log.
/// </summary>
public ulong? RoleId { get; set; }
/// <summary>
/// Gets whether emoticons should be synced for this integration. <see landword="null"/> if the property was not mentioned in this audit log.
/// </summary>
public bool? EnableEmojis { get; set; }
/// <summary>
/// Gets the behavior of expiring subscribers. <see landword="null"/> if the property was not mentioned in this audit log.
/// </summary>
public IntegrationExpireBehavior? ExpireBehavior { get; set; }
/// <summary>
/// Gets the grace period (in days) before expiring subscribers. <see landword="null"/> if the property was not mentioned in this audit log.
/// </summary>
public int? ExpireGracePeriod { get; set; }
/// <summary>
/// Gets the scopes the application has been authorized for. <see landword="null"/> if the property was not mentioned in this audit log.
/// </summary>
public IReadOnlyCollection<string> Scopes { get; set; }
}

View File

@@ -0,0 +1,45 @@
using Discord.API.AuditLogs;
using System.Linq;
using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog;
namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to an integration update.
/// </summary>
public class IntegrationUpdatedAuditLogData : IAuditLogData
{
internal IntegrationUpdatedAuditLogData(IntegrationInfo before, IntegrationInfo after, IIntegration integration)
{
Before = before;
After = after;
Integration = integration;
}
internal static IntegrationUpdatedAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var changes = entry.Changes;
var (before, after) = AuditLogHelper.CreateAuditLogEntityInfo<IntegrationInfoAuditLogModel>(changes, discord);
var integration = RestIntegration.Create(discord, null, log.Integrations.FirstOrDefault(x => x.Id == entry.TargetId));
return new(new IntegrationInfo(before), new IntegrationInfo(after), integration);
}
/// <summary>
/// Gets the partial integration the changes correspond to.
/// </summary>
public IIntegration Integration { get; }
/// <summary>
/// Gets the integration information before the changes.
/// </summary>
public IntegrationInfo Before { get; }
/// <summary>
/// Gets the integration information after the changes.
/// </summary>
public IntegrationInfo After { get; }
}

View File

@@ -1,108 +1,102 @@
using Discord.API.AuditLogs;
using System.Linq; using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to an invite creation.
/// </summary>
public class InviteCreateAuditLogData : IAuditLogData
{ {
/// <summary> private InviteCreateAuditLogData(InviteInfoAuditLogModel model, IUser inviter)
/// Contains a piece of audit log data related to an invite creation.
/// </summary>
public class InviteCreateAuditLogData : IAuditLogData
{ {
private InviteCreateAuditLogData(int maxAge, string code, bool temporary, IUser inviter, ulong channelId, int uses, int maxUses) MaxAge = model.MaxAge!.Value;
{ Code = model.Code;
MaxAge = maxAge; Temporary = model.Temporary!.Value;
Code = code; Creator = inviter;
Temporary = temporary; ChannelId = model.ChannelId!.Value;
Creator = inviter; Uses = model.Uses!.Value;
ChannelId = channelId; MaxUses = model.MaxUses!.Value;
Uses = uses;
MaxUses = maxUses;
}
internal static InviteCreateAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var changes = entry.Changes;
var maxAgeModel = changes.FirstOrDefault(x => x.ChangedProperty == "max_age");
var codeModel = changes.FirstOrDefault(x => x.ChangedProperty == "code");
var temporaryModel = changes.FirstOrDefault(x => x.ChangedProperty == "temporary");
var inviterIdModel = changes.FirstOrDefault(x => x.ChangedProperty == "inviter_id");
var channelIdModel = changes.FirstOrDefault(x => x.ChangedProperty == "channel_id");
var usesModel = changes.FirstOrDefault(x => x.ChangedProperty == "uses");
var maxUsesModel = changes.FirstOrDefault(x => x.ChangedProperty == "max_uses");
var maxAge = maxAgeModel.NewValue.ToObject<int>(discord.ApiClient.Serializer);
var code = codeModel.NewValue.ToObject<string>(discord.ApiClient.Serializer);
var temporary = temporaryModel.NewValue.ToObject<bool>(discord.ApiClient.Serializer);
var channelId = channelIdModel.NewValue.ToObject<ulong>(discord.ApiClient.Serializer);
var uses = usesModel.NewValue.ToObject<int>(discord.ApiClient.Serializer);
var maxUses = maxUsesModel.NewValue.ToObject<int>(discord.ApiClient.Serializer);
RestUser inviter = null;
if (inviterIdModel != null)
{
var inviterId = inviterIdModel.NewValue.ToObject<ulong>(discord.ApiClient.Serializer);
var inviterInfo = log.Users.FirstOrDefault(x => x.Id == inviterId);
inviter = (inviterInfo != null) ? RestUser.Create(discord, inviterInfo) : null;
}
return new InviteCreateAuditLogData(maxAge, code, temporary, inviter, channelId, uses, maxUses);
}
/// <summary>
/// Gets the time (in seconds) until the invite expires.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the time in seconds until this invite expires.
/// </returns>
public int MaxAge { get; }
/// <summary>
/// Gets the unique identifier for this invite.
/// </summary>
/// <returns>
/// A string containing the invite code (e.g. <c>FTqNnyS</c>).
/// </returns>
public string Code { get; }
/// <summary>
/// Gets a value that determines whether the invite is a temporary one.
/// </summary>
/// <returns>
/// <c>true</c> if users accepting this invite will be removed from the guild when they log off; otherwise
/// <c>false</c>.
/// </returns>
public bool Temporary { get; }
/// <summary>
/// Gets the user that created this invite if available.
/// </summary>
/// <remarks>
/// Will be <see langword="null"/> if the user is a 'Deleted User#....' because Discord does send user data for deleted users.
/// </remarks>
/// <returns>
/// A user that created this invite or <see langword="null"/>.
/// </returns>
public IUser Creator { get; }
/// <summary>
/// Gets the ID of the channel this invite is linked to.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the channel snowflake identifier that the invite points to.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the number of times this invite has been used.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the number of times this invite was used.
/// </returns>
public int Uses { get; }
/// <summary>
/// Gets the max number of uses this invite may have.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the number of uses this invite may be accepted until it is removed
/// from the guild; <c>null</c> if none is set.
/// </returns>
public int MaxUses { get; }
} }
internal static InviteCreateAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var changes = entry.Changes;
var (_, data) = AuditLogHelper.CreateAuditLogEntityInfo<InviteInfoAuditLogModel>(changes, discord);
RestUser inviter = null;
if (data.InviterId is not null)
{
var inviterInfo = log.Users.FirstOrDefault(x => x.Id == data.InviterId);
inviter = (inviterInfo != null) ? RestUser.Create(discord, inviterInfo) : null;
}
return new InviteCreateAuditLogData(data, inviter);
}
/// <summary>
/// Gets the time (in seconds) until the invite expires.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the time in seconds until this invite expires.
/// </returns>
public int MaxAge { get; }
/// <summary>
/// Gets the unique identifier for this invite.
/// </summary>
/// <returns>
/// A string containing the invite code (e.g. <c>FTqNnyS</c>).
/// </returns>
public string Code { get; }
/// <summary>
/// Gets a value that determines whether the invite is a temporary one.
/// </summary>
/// <returns>
/// <c>true</c> if users accepting this invite will be removed from the guild when they log off; otherwise
/// <c>false</c>.
/// </returns>
public bool Temporary { get; }
/// <summary>
/// Gets the user that created this invite if available.
/// </summary>
/// <remarks>
/// Will be <see langword="null"/> if the user is a 'Deleted User#....' because Discord does send user data for deleted users.
/// </remarks>
/// <returns>
/// A user that created this invite or <see langword="null"/>.
/// </returns>
public IUser Creator { get; }
/// <summary>
/// Gets the ID of the channel this invite is linked to.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the channel snowflake identifier that the invite points to.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the number of times this invite has been used.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the number of times this invite was used.
/// </returns>
public int Uses { get; }
/// <summary>
/// Gets the max number of uses this invite may have.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the number of uses this invite may be accepted until it is removed
/// from the guild; <c>null</c> if none is set.
/// </returns>
public int MaxUses { get; }
} }

View File

@@ -1,108 +1,102 @@
using Discord.API.AuditLogs;
using System.Linq; using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to an invite removal.
/// </summary>
public class InviteDeleteAuditLogData : IAuditLogData
{ {
/// <summary> private InviteDeleteAuditLogData(InviteInfoAuditLogModel model, IUser inviter)
/// Contains a piece of audit log data related to an invite removal.
/// </summary>
public class InviteDeleteAuditLogData : IAuditLogData
{ {
private InviteDeleteAuditLogData(int maxAge, string code, bool temporary, IUser inviter, ulong channelId, int uses, int maxUses) MaxAge = model.MaxAge!.Value;
{ Code = model.Code;
MaxAge = maxAge; Temporary = model.Temporary!.Value;
Code = code; Creator = inviter;
Temporary = temporary; ChannelId = model.ChannelId!.Value;
Creator = inviter; Uses = model.Uses!.Value;
ChannelId = channelId; MaxUses = model.MaxUses!.Value;
Uses = uses;
MaxUses = maxUses;
}
internal static InviteDeleteAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var changes = entry.Changes;
var maxAgeModel = changes.FirstOrDefault(x => x.ChangedProperty == "max_age");
var codeModel = changes.FirstOrDefault(x => x.ChangedProperty == "code");
var temporaryModel = changes.FirstOrDefault(x => x.ChangedProperty == "temporary");
var inviterIdModel = changes.FirstOrDefault(x => x.ChangedProperty == "inviter_id");
var channelIdModel = changes.FirstOrDefault(x => x.ChangedProperty == "channel_id");
var usesModel = changes.FirstOrDefault(x => x.ChangedProperty == "uses");
var maxUsesModel = changes.FirstOrDefault(x => x.ChangedProperty == "max_uses");
var maxAge = maxAgeModel.OldValue.ToObject<int>(discord.ApiClient.Serializer);
var code = codeModel.OldValue.ToObject<string>(discord.ApiClient.Serializer);
var temporary = temporaryModel.OldValue.ToObject<bool>(discord.ApiClient.Serializer);
var channelId = channelIdModel.OldValue.ToObject<ulong>(discord.ApiClient.Serializer);
var uses = usesModel.OldValue.ToObject<int>(discord.ApiClient.Serializer);
var maxUses = maxUsesModel.OldValue.ToObject<int>(discord.ApiClient.Serializer);
RestUser inviter = null;
if (inviterIdModel != null)
{
var inviterId = inviterIdModel.OldValue.ToObject<ulong>(discord.ApiClient.Serializer);
var inviterInfo = log.Users.FirstOrDefault(x => x.Id == inviterId);
inviter = (inviterInfo != null) ? RestUser.Create(discord, inviterInfo) : null;
}
return new InviteDeleteAuditLogData(maxAge, code, temporary, inviter, channelId, uses, maxUses);
}
/// <summary>
/// Gets the time (in seconds) until the invite expires.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the time in seconds until this invite expires.
/// </returns>
public int MaxAge { get; }
/// <summary>
/// Gets the unique identifier for this invite.
/// </summary>
/// <returns>
/// A string containing the invite code (e.g. <c>FTqNnyS</c>).
/// </returns>
public string Code { get; }
/// <summary>
/// Gets a value that indicates whether the invite is a temporary one.
/// </summary>
/// <returns>
/// <c>true</c> if users accepting this invite will be removed from the guild when they log off; otherwise
/// <c>false</c>.
/// </returns>
public bool Temporary { get; }
/// <summary>
/// Gets the user that created this invite if available.
/// </summary>
/// <remarks>
/// Will be <see langword="null"/> if the user is a 'Deleted User#....' because Discord does send user data for deleted users.
/// </remarks>
/// <returns>
/// A user that created this invite or <see langword="null"/>.
/// </returns>
public IUser Creator { get; }
/// <summary>
/// Gets the ID of the channel this invite is linked to.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the channel snowflake identifier that the invite points to.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the number of times this invite has been used.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the number of times this invite has been used.
/// </returns>
public int Uses { get; }
/// <summary>
/// Gets the max number of uses this invite may have.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the number of uses this invite may be accepted until it is removed
/// from the guild; <c>null</c> if none is set.
/// </returns>
public int MaxUses { get; }
} }
internal static InviteDeleteAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var changes = entry.Changes;
var (data, _) = AuditLogHelper.CreateAuditLogEntityInfo<InviteInfoAuditLogModel>(changes, discord);
RestUser inviter = null;
if (data.InviterId != null)
{
var inviterInfo = log.Users.FirstOrDefault(x => x.Id == data.InviterId);
inviter = (inviterInfo != null) ? RestUser.Create(discord, inviterInfo) : null;
}
return new InviteDeleteAuditLogData(data, inviter);
}
/// <summary>
/// Gets the time (in seconds) until the invite expires.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the time in seconds until this invite expires.
/// </returns>
public int MaxAge { get; }
/// <summary>
/// Gets the unique identifier for this invite.
/// </summary>
/// <returns>
/// A string containing the invite code (e.g. <c>FTqNnyS</c>).
/// </returns>
public string Code { get; }
/// <summary>
/// Gets a value that indicates whether the invite is a temporary one.
/// </summary>
/// <returns>
/// <c>true</c> if users accepting this invite will be removed from the guild when they log off; otherwise
/// <c>false</c>.
/// </returns>
public bool Temporary { get; }
/// <summary>
/// Gets the user that created this invite if available.
/// </summary>
/// <remarks>
/// Will be <see langword="null"/> if the user is a 'Deleted User#....' because Discord does send user data for deleted users.
/// </remarks>
/// <returns>
/// A user that created this invite or <see langword="null"/>.
/// </returns>
public IUser Creator { get; }
/// <summary>
/// Gets the ID of the channel this invite is linked to.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the channel snowflake identifier that the invite points to.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the number of times this invite has been used.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the number of times this invite has been used.
/// </returns>
public int Uses { get; }
/// <summary>
/// Gets the max number of uses this invite may have.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the number of uses this invite may be accepted until it is removed
/// from the guild; <c>null</c> if none is set.
/// </returns>
public int MaxUses { get; }
} }

View File

@@ -1,57 +1,68 @@
namespace Discord.Rest using Model = Discord.API.AuditLogs.InviteInfoAuditLogModel;
{
/// <summary>
/// Represents information for an invite.
/// </summary>
public struct InviteInfo
{
internal InviteInfo(int? maxAge, string code, bool? temporary, ulong? channelId, int? maxUses)
{
MaxAge = maxAge;
Code = code;
Temporary = temporary;
ChannelId = channelId;
MaxUses = maxUses;
}
/// <summary> namespace Discord.Rest;
/// Gets the time (in seconds) until the invite expires.
/// </summary> /// <summary>
/// <returns> /// Represents information for an invite.
/// An <see cref="int"/> representing the time in seconds until this invite expires; <c>null</c> if this /// </summary>
/// invite never expires or not specified. public struct InviteInfo
/// </returns> {
public int? MaxAge { get; } internal InviteInfo(Model model)
/// <summary> {
/// Gets the unique identifier for this invite. MaxAge = model.MaxAge;
/// </summary> Code = model.Code;
/// <returns> Temporary = model.Temporary;
/// A string containing the invite code (e.g. <c>FTqNnyS</c>). ChannelId = model.ChannelId;
/// </returns> MaxUses = model.MaxUses;
public string Code { get; } CreatorId = model.InviterId;
/// <summary>
/// Gets a value that indicates whether the invite is a temporary one.
/// </summary>
/// <returns>
/// <c>true</c> if users accepting this invite will be removed from the guild when they log off,
/// <c>false</c> if not; <c>null</c> if not specified.
/// </returns>
public bool? Temporary { get; }
/// <summary>
/// Gets the ID of the channel this invite is linked to.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the channel snowflake identifier that the invite points to;
/// <c>null</c> if not specified.
/// </returns>
public ulong? ChannelId { get; }
/// <summary>
/// Gets the max number of uses this invite may have.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the number of uses this invite may be accepted until it is removed
/// from the guild; <c>null</c> if none is specified.
/// </returns>
public int? MaxUses { get; }
} }
/// <summary>
/// Gets the time (in seconds) until the invite expires.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the time in seconds until this invite expires; <c>null</c> if this
/// invite never expires or not specified.
/// </returns>
public int? MaxAge { get; }
/// <summary>
/// Gets the unique identifier for this invite.
/// </summary>
/// <returns>
/// A string containing the invite code (e.g. <c>FTqNnyS</c>).
/// </returns>
public string Code { get; }
/// <summary>
/// Gets a value that indicates whether the invite is a temporary one.
/// </summary>
/// <returns>
/// <c>true</c> if users accepting this invite will be removed from the guild when they log off,
/// <c>false</c> if not; <c>null</c> if not specified.
/// </returns>
public bool? Temporary { get; }
/// <summary>
/// Gets the ID of the channel this invite is linked to.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the channel snowflake identifier that the invite points to;
/// <c>null</c> if not specified.
/// </returns>
public ulong? ChannelId { get; }
/// <summary>
/// Gets the max number of uses this invite may have.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the number of uses this invite may be accepted until it is removed
/// from the guild; <c>null</c> if none is specified.
/// </returns>
public int? MaxUses { get; }
/// <summary>
/// Gets the id of the user created this invite.
/// </summary>
public ulong? CreatorId { get; }
} }

View File

@@ -1,60 +1,44 @@
using Discord.API.AuditLogs;
using System.Linq; using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data relating to an invite update.
/// </summary>
public class InviteUpdateAuditLogData : IAuditLogData
{ {
/// <summary> private InviteUpdateAuditLogData(InviteInfo before, InviteInfo after)
/// Contains a piece of audit log data relating to an invite update.
/// </summary>
public class InviteUpdateAuditLogData : IAuditLogData
{ {
private InviteUpdateAuditLogData(InviteInfo before, InviteInfo after) Before = before;
{ After = after;
Before = before;
After = after;
}
internal static InviteUpdateAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var changes = entry.Changes;
var maxAgeModel = changes.FirstOrDefault(x => x.ChangedProperty == "max_age");
var codeModel = changes.FirstOrDefault(x => x.ChangedProperty == "code");
var temporaryModel = changes.FirstOrDefault(x => x.ChangedProperty == "temporary");
var channelIdModel = changes.FirstOrDefault(x => x.ChangedProperty == "channel_id");
var maxUsesModel = changes.FirstOrDefault(x => x.ChangedProperty == "max_uses");
int? oldMaxAge = maxAgeModel?.OldValue?.ToObject<int>(discord.ApiClient.Serializer),
newMaxAge = maxAgeModel?.NewValue?.ToObject<int>(discord.ApiClient.Serializer);
string oldCode = codeModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer),
newCode = codeModel?.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
bool? oldTemporary = temporaryModel?.OldValue?.ToObject<bool>(discord.ApiClient.Serializer),
newTemporary = temporaryModel?.NewValue?.ToObject<bool>(discord.ApiClient.Serializer);
ulong? oldChannelId = channelIdModel?.OldValue?.ToObject<ulong>(discord.ApiClient.Serializer),
newChannelId = channelIdModel?.NewValue?.ToObject<ulong>(discord.ApiClient.Serializer);
int? oldMaxUses = maxUsesModel?.OldValue?.ToObject<int>(discord.ApiClient.Serializer),
newMaxUses = maxUsesModel?.NewValue?.ToObject<int>(discord.ApiClient.Serializer);
var before = new InviteInfo(oldMaxAge, oldCode, oldTemporary, oldChannelId, oldMaxUses);
var after = new InviteInfo(newMaxAge, newCode, newTemporary, newChannelId, newMaxUses);
return new InviteUpdateAuditLogData(before, after);
}
/// <summary>
/// Gets the invite information before the changes.
/// </summary>
/// <returns>
/// An information object containing the original invite information before the changes were made.
/// </returns>
public InviteInfo Before { get; }
/// <summary>
/// Gets the invite information after the changes.
/// </summary>
/// <returns>
/// An information object containing the invite information after the changes were made.
/// </returns>
public InviteInfo After { get; }
} }
internal static InviteUpdateAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var changes = entry.Changes;
var (before, after) = AuditLogHelper.CreateAuditLogEntityInfo<InviteInfoAuditLogModel>(changes, discord);
return new InviteUpdateAuditLogData(new(before), new(after));
}
/// <summary>
/// Gets the invite information before the changes.
/// </summary>
/// <returns>
/// An information object containing the original invite information before the changes were made.
/// </returns>
public InviteInfo Before { get; }
/// <summary>
/// Gets the invite information after the changes.
/// </summary>
/// <returns>
/// An information object containing the invite information after the changes were made.
/// </returns>
public InviteInfo After { get; }
} }

View File

@@ -2,33 +2,32 @@ using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a kick.
/// </summary>
public class KickAuditLogData : IAuditLogData
{ {
/// <summary> private KickAuditLogData(RestUser user)
/// Contains a piece of audit log data related to a kick.
/// </summary>
public class KickAuditLogData : IAuditLogData
{ {
private KickAuditLogData(RestUser user) Target = user;
{
Target = user;
}
internal static KickAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var userInfo = log.Users.FirstOrDefault(x => x.Id == entry.TargetId);
return new KickAuditLogData((userInfo != null) ? RestUser.Create(discord, userInfo) : null);
}
/// <summary>
/// Gets the user that was kicked.
/// </summary>
/// <remarks>
/// Will be <see langword="null"/> if the user is a 'Deleted User#....' because Discord does send user data for deleted users.
/// </remarks>
/// <returns>
/// A user object representing the kicked user.
/// </returns>
public IUser Target { get; }
} }
internal static KickAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log = null)
{
var userInfo = log.Users.FirstOrDefault(x => x.Id == entry.TargetId);
return new KickAuditLogData((userInfo != null) ? RestUser.Create(discord, userInfo) : null);
}
/// <summary>
/// Gets the user that was kicked.
/// </summary>
/// <remarks>
/// Will be <see langword="null"/> if the user is a 'Deleted User#....' because Discord does send user data for deleted users.
/// </remarks>
/// <returns>
/// A user object representing the kicked user.
/// </returns>
public IUser Target { get; }
} }

View File

@@ -1,29 +1,28 @@
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to disconnecting members from voice channels.
/// </summary>
public class MemberDisconnectAuditLogData : IAuditLogData
{ {
/// <summary> private MemberDisconnectAuditLogData(int count)
/// Contains a piece of audit log data related to disconnecting members from voice channels.
/// </summary>
public class MemberDisconnectAuditLogData : IAuditLogData
{ {
private MemberDisconnectAuditLogData(int count) MemberCount = count;
{
MemberCount = count;
}
internal static MemberDisconnectAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
return new MemberDisconnectAuditLogData(entry.Options.Count.Value);
}
/// <summary>
/// Gets the number of members that were disconnected.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the number of members that were disconnected from a voice channel.
/// </returns>
public int MemberCount { get; }
} }
internal static MemberDisconnectAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
return new MemberDisconnectAuditLogData(entry.Options.Count.Value);
}
/// <summary>
/// Gets the number of members that were disconnected.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the number of members that were disconnected from a voice channel.
/// </returns>
public int MemberCount { get; }
} }

View File

@@ -1,41 +1,57 @@
namespace Discord.Rest using Discord.API.AuditLogs;
{ using System;
/// <summary>
/// Represents information for a member.
/// </summary>
public struct MemberInfo
{
internal MemberInfo(string nick, bool? deaf, bool? mute)
{
Nickname = nick;
Deaf = deaf;
Mute = mute;
}
/// <summary> namespace Discord.Rest;
/// Gets the nickname of the updated member.
/// </summary> /// <summary>
/// <returns> /// Represents information for a member.
/// A string representing the nickname of the updated member; <c>null</c> if none is set. /// </summary>
/// </returns> public struct MemberInfo
public string Nickname { get; } {
/// <summary> internal MemberInfo(MemberInfoAuditLogModel model)
/// Gets a value that indicates whether the updated member is deafened by the guild. {
/// </summary> Nickname = model.Nickname;
/// <returns> Deaf = model.IsDeafened;
/// <c>true</c> if the updated member is deafened (i.e. not permitted to listen to or speak to others) by the guild; Mute = model.IsMuted;
/// otherwise <c>false</c>. TimedOutUntil = model.TimeOutUntil;
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public bool? Deaf { get; }
/// <summary>
/// Gets a value that indicates whether the updated member is muted (i.e. not permitted to speak via voice) by the
/// guild.
/// </summary>
/// <returns>
/// <c>true</c> if the updated member is muted by the guild; otherwise <c>false</c>.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public bool? Mute { get; }
} }
/// <summary>
/// Gets the nickname of the updated member.
/// </summary>
/// <returns>
/// A string representing the nickname of the updated member; <see langword="null"/> if none is set.
/// </returns>
public string Nickname { get; }
/// <summary>
/// Gets a value that indicates whether the updated member is deafened by the guild.
/// </summary>
/// <returns>
/// <see langword="true"/> if the updated member is deafened (i.e. not permitted to listen to or speak to others) by the guild;
/// otherwise <see langword="false"/>.
/// <see langword="null"/> if this is not mentioned in this entry.
/// </returns>
public bool? Deaf { get; }
/// <summary>
/// Gets a value that indicates whether the updated member is muted (i.e. not permitted to speak via voice) by the
/// guild.
/// </summary>
/// <returns>
/// <see langword="true"/> if the updated member is muted by the guild; otherwise <see langword="false"/>.
/// <see langword="null"/> if this is not mentioned in this entry.
/// </returns>
public bool? Mute { get; }
/// <summary>
/// Gets the date and time that indicates if and for how long the updated user has been timed out.
/// </summary>
/// <remarks>
/// <see langword="null"/> or a timestamp in the past if the user is not timed out.
/// </remarks>
/// <returns>
/// A <see cref="DateTimeOffset"/> indicating how long the user will be timed out for.
/// </returns>
public DateTimeOffset? TimedOutUntil { get; }
} }

View File

@@ -1,37 +1,36 @@
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to moving members between voice channels.
/// </summary>
public class MemberMoveAuditLogData : IAuditLogData
{ {
/// <summary> private MemberMoveAuditLogData(ulong channelId, int count)
/// Contains a piece of audit log data related to moving members between voice channels.
/// </summary>
public class MemberMoveAuditLogData : IAuditLogData
{ {
private MemberMoveAuditLogData(ulong channelId, int count) ChannelId = channelId;
{ MemberCount = count;
ChannelId = channelId;
MemberCount = count;
}
internal static MemberMoveAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
return new MemberMoveAuditLogData(entry.Options.ChannelId.Value, entry.Options.Count.Value);
}
/// <summary>
/// Gets the ID of the channel that the members were moved to.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the channel that the members were moved to.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the number of members that were moved.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the number of members that were moved to another voice channel.
/// </returns>
public int MemberCount { get; }
} }
internal static MemberMoveAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log = null)
{
return new MemberMoveAuditLogData(entry.Options.ChannelId.Value, entry.Options.Count.Value);
}
/// <summary>
/// Gets the ID of the channel that the members were moved to.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the channel that the members were moved to.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the number of members that were moved.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the number of members that were moved to another voice channel.
/// </returns>
public int MemberCount { get; }
} }

View File

@@ -3,48 +3,48 @@ using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a change in a guild member's roles.
/// </summary>
public class MemberRoleAuditLogData : IAuditLogData
{ {
/// <summary> private MemberRoleAuditLogData(IReadOnlyCollection<MemberRoleEditInfo> roles, IUser target)
/// Contains a piece of audit log data related to a change in a guild member's roles.
/// </summary>
public class MemberRoleAuditLogData : IAuditLogData
{ {
private MemberRoleAuditLogData(IReadOnlyCollection<MemberRoleEditInfo> roles, IUser target) Roles = roles;
{ Target = target;
Roles = roles;
Target = target;
}
internal static MemberRoleAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var changes = entry.Changes;
var roleInfos = changes.SelectMany(x => x.NewValue.ToObject<API.Role[]>(discord.ApiClient.Serializer),
(model, role) => new { model.ChangedProperty, Role = role })
.Select(x => new MemberRoleEditInfo(x.Role.Name, x.Role.Id, x.ChangedProperty == "$add"))
.ToList();
var userInfo = log.Users.FirstOrDefault(x => x.Id == entry.TargetId);
RestUser user = (userInfo != null) ? RestUser.Create(discord, userInfo) : null;
return new MemberRoleAuditLogData(roleInfos.ToReadOnlyCollection(), user);
}
/// <summary>
/// Gets a collection of role changes that were performed on the member.
/// </summary>
/// <returns>
/// A read-only collection of <see cref="MemberRoleEditInfo"/>, containing the roles that were changed on
/// the member.
/// </returns>
public IReadOnlyCollection<MemberRoleEditInfo> Roles { get; }
/// <summary>
/// Gets the user that the roles changes were performed on.
/// </summary>
/// <returns>
/// A user object representing the user that the role changes were performed on.
/// </returns>
public IUser Target { get; }
} }
internal static MemberRoleAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log = null)
{
var changes = entry.Changes;
var roleInfos = changes.SelectMany(x => x.NewValue.ToObject<API.Role[]>(discord.ApiClient.Serializer),
(model, role) => new { model.ChangedProperty, Role = role })
.Select(x => new MemberRoleEditInfo(x.Role.Name, x.Role.Id, x.ChangedProperty == "$add"))
.ToList();
var userInfo = log.Users.FirstOrDefault(x => x.Id == entry.TargetId);
RestUser user = (userInfo != null) ? RestUser.Create(discord, userInfo) : null;
return new MemberRoleAuditLogData(roleInfos.ToReadOnlyCollection(), user);
}
/// <summary>
/// Gets a collection of role changes that were performed on the member.
/// </summary>
/// <returns>
/// A read-only collection of <see cref="MemberRoleEditInfo"/>, containing the roles that were changed on
/// the member.
/// </returns>
public IReadOnlyCollection<MemberRoleEditInfo> Roles { get; }
/// <summary>
/// Gets the user that the roles changes were performed on.
/// </summary>
/// <returns>
/// A user object representing the user that the role changes were performed on.
/// </returns>
public IUser Target { get; }
} }

View File

@@ -1,37 +1,38 @@
namespace Discord.Rest namespace Discord.Rest;
{
/// <summary>
/// An information object representing a change in one of a guild member's roles.
/// </summary>
public struct MemberRoleEditInfo
{
internal MemberRoleEditInfo(string name, ulong roleId, bool added)
{
Name = name;
RoleId = roleId;
Added = added;
}
/// <summary> /// <summary>
/// Gets the name of the role that was changed. /// An information object representing a change in one of a guild member's roles.
/// </summary> /// </summary>
/// <returns> public struct MemberRoleEditInfo
/// A string containing the name of the role that was changed. {
/// </returns> internal MemberRoleEditInfo(string name, ulong roleId, bool added)
public string Name { get; } {
/// <summary> Name = name;
/// Gets the ID of the role that was changed. RoleId = roleId;
/// </summary> Added = added;
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier of the role that was changed.
/// </returns>
public ulong RoleId { get; }
/// <summary>
/// Gets a value that indicates whether the role was added to the user.
/// </summary>
/// <returns>
/// <c>true</c> if the role was added to the user; otherwise <c>false</c>.
/// </returns>
public bool Added { get; }
} }
/// <summary>
/// Gets the name of the role that was changed.
/// </summary>
/// <returns>
/// A string containing the name of the role that was changed.
/// </returns>
public string Name { get; }
/// <summary>
/// Gets the ID of the role that was changed.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier of the role that was changed.
/// </returns>
public ulong RoleId { get; }
/// <summary>
/// Gets a value that indicates whether the role was added to the user.
/// </summary>
/// <returns>
/// <c>true</c> if the role was added to the user; otherwise <c>false</c>.
/// </returns>
public bool Added { get; }
} }

View File

@@ -1,68 +1,56 @@
using Discord.API.AuditLogs;
using System.Linq; using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a change in a guild member.
/// </summary>
public class MemberUpdateAuditLogData : IAuditLogData
{ {
/// <summary> private MemberUpdateAuditLogData(IUser target, MemberInfo before, MemberInfo after)
/// Contains a piece of audit log data related to a change in a guild member.
/// </summary>
public class MemberUpdateAuditLogData : IAuditLogData
{ {
private MemberUpdateAuditLogData(IUser target, MemberInfo before, MemberInfo after) Target = target;
{ Before = before;
Target = target; After = after;
Before = before;
After = after;
}
internal static MemberUpdateAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var changes = entry.Changes;
var nickModel = changes.FirstOrDefault(x => x.ChangedProperty == "nick");
var deafModel = changes.FirstOrDefault(x => x.ChangedProperty == "deaf");
var muteModel = changes.FirstOrDefault(x => x.ChangedProperty == "mute");
string oldNick = nickModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer),
newNick = nickModel?.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
bool? oldDeaf = deafModel?.OldValue?.ToObject<bool>(discord.ApiClient.Serializer),
newDeaf = deafModel?.NewValue?.ToObject<bool>(discord.ApiClient.Serializer);
bool? oldMute = muteModel?.OldValue?.ToObject<bool>(discord.ApiClient.Serializer),
newMute = muteModel?.NewValue?.ToObject<bool>(discord.ApiClient.Serializer);
var targetInfo = log.Users.FirstOrDefault(x => x.Id == entry.TargetId);
RestUser user = (targetInfo != null) ? RestUser.Create(discord, targetInfo) : null;
var before = new MemberInfo(oldNick, oldDeaf, oldMute);
var after = new MemberInfo(newNick, newDeaf, newMute);
return new MemberUpdateAuditLogData(user, before, after);
}
/// <summary>
/// Gets the user that the changes were performed on.
/// </summary>
/// <remarks>
/// Will be <see langword="null"/> if the user is a 'Deleted User#....' because Discord does send user data for deleted users.
/// </remarks>
/// <returns>
/// A user object representing the user who the changes were performed on.
/// </returns>
public IUser Target { get; }
/// <summary>
/// Gets the member information before the changes.
/// </summary>
/// <returns>
/// An information object containing the original member information before the changes were made.
/// </returns>
public MemberInfo Before { get; }
/// <summary>
/// Gets the member information after the changes.
/// </summary>
/// <returns>
/// An information object containing the member information after the changes were made.
/// </returns>
public MemberInfo After { get; }
} }
internal static MemberUpdateAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log = null)
{
var changes = entry.Changes;
var (before, after) = AuditLogHelper.CreateAuditLogEntityInfo<MemberInfoAuditLogModel>(changes, discord);
var targetInfo = log.Users.FirstOrDefault(x => x.Id == entry.TargetId);
RestUser user = (targetInfo != null) ? RestUser.Create(discord, targetInfo) : null;
return new MemberUpdateAuditLogData(user, new MemberInfo(before), new MemberInfo(after));
}
/// <summary>
/// Gets the user that the changes were performed on.
/// </summary>
/// <remarks>
/// Will be <see langword="null"/> if the user is a 'Deleted User#....' because Discord does send user data for deleted users.
/// </remarks>
/// <returns>
/// A user object representing the user who the changes were performed on.
/// </returns>
public IUser Target { get; }
/// <summary>
/// Gets the member information before the changes.
/// </summary>
/// <returns>
/// An information object containing the original member information before the changes were made.
/// </returns>
public MemberInfo Before { get; }
/// <summary>
/// Gets the member information after the changes.
/// </summary>
/// <returns>
/// An information object containing the member information after the changes were made.
/// </returns>
public MemberInfo After { get; }
} }

View File

@@ -1,38 +1,37 @@
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to message deletion(s).
/// </summary>
public class MessageBulkDeleteAuditLogData : IAuditLogData
{ {
/// <summary> private MessageBulkDeleteAuditLogData(ulong channelId, int count)
/// Contains a piece of audit log data related to message deletion(s).
/// </summary>
public class MessageBulkDeleteAuditLogData : IAuditLogData
{ {
private MessageBulkDeleteAuditLogData(ulong channelId, int count) ChannelId = channelId;
{ MessageCount = count;
ChannelId = channelId;
MessageCount = count;
}
internal static MessageBulkDeleteAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
return new MessageBulkDeleteAuditLogData(entry.TargetId.Value, entry.Options.Count.Value);
}
/// <summary>
/// Gets the ID of the channel that the messages were deleted from.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the channel that the messages were
/// deleted from.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the number of messages that were deleted.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the number of messages that were deleted from the channel.
/// </returns>
public int MessageCount { get; }
} }
internal static MessageBulkDeleteAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
return new MessageBulkDeleteAuditLogData(entry.TargetId.Value, entry.Options.Count.Value);
}
/// <summary>
/// Gets the ID of the channel that the messages were deleted from.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the channel that the messages were
/// deleted from.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the number of messages that were deleted.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the number of messages that were deleted from the channel.
/// </returns>
public int MessageCount { get; }
} }

View File

@@ -3,50 +3,49 @@ using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to message deletion(s).
/// </summary>
public class MessageDeleteAuditLogData : IAuditLogData
{ {
/// <summary> private MessageDeleteAuditLogData(ulong channelId, int count, IUser user)
/// Contains a piece of audit log data related to message deletion(s).
/// </summary>
public class MessageDeleteAuditLogData : IAuditLogData
{ {
private MessageDeleteAuditLogData(ulong channelId, int count, IUser user) ChannelId = channelId;
{ MessageCount = count;
ChannelId = channelId; Target = user;
MessageCount = count;
Target = user;
}
internal static MessageDeleteAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var userInfo = log.Users.FirstOrDefault(x => x.Id == entry.TargetId);
return new MessageDeleteAuditLogData(entry.Options.ChannelId.Value, entry.Options.Count.Value, userInfo != null ? RestUser.Create(discord, userInfo) : null);
}
/// <summary>
/// Gets the number of messages that were deleted.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the number of messages that were deleted from the channel.
/// </returns>
public int MessageCount { get; }
/// <summary>
/// Gets the ID of the channel that the messages were deleted from.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the channel that the messages were
/// deleted from.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the user of the messages that were deleted.
/// </summary>
/// <remarks>
/// Will be <see langword="null"/> if the user is a 'Deleted User#....' because Discord does send user data for deleted users.
/// </remarks>
/// <returns>
/// A user object representing the user that created the deleted messages.
/// </returns>
public IUser Target { get; }
} }
internal static MessageDeleteAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var userInfo = log.Users.FirstOrDefault(x => x.Id == entry.TargetId);
return new MessageDeleteAuditLogData(entry.Options.ChannelId.Value, entry.Options.Count.Value, userInfo != null ? RestUser.Create(discord, userInfo) : null);
}
/// <summary>
/// Gets the number of messages that were deleted.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the number of messages that were deleted from the channel.
/// </returns>
public int MessageCount { get; }
/// <summary>
/// Gets the ID of the channel that the messages were deleted from.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the channel that the messages were
/// deleted from.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the user of the messages that were deleted.
/// </summary>
/// <remarks>
/// Will be <see langword="null"/> if the user is a 'Deleted User#....' because Discord does send user data for deleted users.
/// </remarks>
/// <returns>
/// A user object representing the user that created the deleted messages.
/// </returns>
public IUser Target { get; }
} }

View File

@@ -2,55 +2,56 @@ using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a pinned message.
/// </summary>
public class MessagePinAuditLogData : IAuditLogData
{ {
/// <summary> private MessagePinAuditLogData(ulong messageId, ulong channelId, IUser user)
/// Contains a piece of audit log data related to a pinned message.
/// </summary>
public class MessagePinAuditLogData : IAuditLogData
{ {
private MessagePinAuditLogData(ulong messageId, ulong channelId, IUser user) MessageId = messageId;
{ ChannelId = channelId;
MessageId = messageId; Target = user;
ChannelId = channelId;
Target = user;
}
internal static MessagePinAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
RestUser user = null;
if (entry.TargetId.HasValue)
{
var userInfo = log.Users.FirstOrDefault(x => x.Id == entry.TargetId);
user = (userInfo != null) ? RestUser.Create(discord, userInfo) : null;
}
return new MessagePinAuditLogData(entry.Options.MessageId.Value, entry.Options.ChannelId.Value, user);
}
/// <summary>
/// Gets the ID of the messages that was pinned.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the messages that was pinned.
/// </returns>
public ulong MessageId { get; }
/// <summary>
/// Gets the ID of the channel that the message was pinned from.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the channel that the message was pinned from.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the user of the message that was pinned if available.
/// </summary>
/// <remarks>
/// Will be <see langword="null"/> if the user is a 'Deleted User#....' because Discord does send user data for deleted users.
/// </remarks>
/// <returns>
/// A user object representing the user that created the pinned message or <see langword="null"/>.
/// </returns>
public IUser Target { get; }
} }
internal static MessagePinAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
RestUser user = null;
if (entry.TargetId.HasValue)
{
var userInfo = log.Users.FirstOrDefault(x => x.Id == entry.TargetId);
user = (userInfo != null) ? RestUser.Create(discord, userInfo) : null;
}
return new MessagePinAuditLogData(entry.Options.MessageId!.Value, entry.Options.ChannelId!.Value, user);
}
/// <summary>
/// Gets the ID of the messages that was pinned.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the messages that was pinned.
/// </returns>
public ulong MessageId { get; }
/// <summary>
/// Gets the ID of the channel that the message was pinned from.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the channel that the message was pinned from.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the user of the message that was pinned if available.
/// </summary>
/// <remarks>
/// Will be <see langword="null"/> if the user is a 'Deleted User#....' because Discord does send user data for deleted users.
/// </remarks>
/// <returns>
/// A user object representing the user that created the pinned message or <see langword="null"/>.
/// </returns>
public IUser Target { get; }
} }

View File

@@ -2,55 +2,54 @@ using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to an unpinned message.
/// </summary>
public class MessageUnpinAuditLogData : IAuditLogData
{ {
/// <summary> private MessageUnpinAuditLogData(ulong messageId, ulong channelId, IUser user)
/// Contains a piece of audit log data related to an unpinned message.
/// </summary>
public class MessageUnpinAuditLogData : IAuditLogData
{ {
private MessageUnpinAuditLogData(ulong messageId, ulong channelId, IUser user) MessageId = messageId;
{ ChannelId = channelId;
MessageId = messageId; Target = user;
ChannelId = channelId;
Target = user;
}
internal static MessageUnpinAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
RestUser user = null;
if (entry.TargetId.HasValue)
{
var userInfo = log.Users.FirstOrDefault(x => x.Id == entry.TargetId);
user = (userInfo != null) ? RestUser.Create(discord, userInfo) : null;
}
return new MessageUnpinAuditLogData(entry.Options.MessageId.Value, entry.Options.ChannelId.Value, user);
}
/// <summary>
/// Gets the ID of the messages that was unpinned.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the messages that was unpinned.
/// </returns>
public ulong MessageId { get; }
/// <summary>
/// Gets the ID of the channel that the message was unpinned from.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the channel that the message was unpinned from.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the user of the message that was unpinned if available.
/// </summary>
/// <remarks>
/// Will be <see langword="null"/> if the user is a 'Deleted User#....' because Discord does send user data for deleted users.
/// </remarks>
/// <returns>
/// A user object representing the user that created the unpinned message or <see langword="null"/>.
/// </returns>
public IUser Target { get; }
} }
internal static MessageUnpinAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
RestUser user = null;
if (entry.TargetId.HasValue)
{
var userInfo = log.Users.FirstOrDefault(x => x.Id == entry.TargetId);
user = (userInfo != null) ? RestUser.Create(discord, userInfo) : null;
}
return new MessageUnpinAuditLogData(entry.Options.MessageId.Value, entry.Options.ChannelId.Value, user);
}
/// <summary>
/// Gets the ID of the messages that was unpinned.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the messages that was unpinned.
/// </returns>
public ulong MessageId { get; }
/// <summary>
/// Gets the ID of the channel that the message was unpinned from.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the channel that the message was unpinned from.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the user of the message that was unpinned if available.
/// </summary>
/// <remarks>
/// Will be <see langword="null"/> if the user is a 'Deleted User#....' because Discord does send user data for deleted users.
/// </remarks>
/// <returns>
/// A user object representing the user that created the unpinned message or <see langword="null"/>.
/// </returns>
public IUser Target { get; }
} }

View File

@@ -0,0 +1,34 @@
using Discord.API.AuditLogs;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
namespace Discord.Rest;
public class OnboardingInfo
{
internal OnboardingInfo(OnboardingAuditLogModel model, BaseDiscordClient discord)
{
Prompts = model.Prompts?.Select(x => new RestGuildOnboardingPrompt(discord, x.Id, x)).ToImmutableArray();
DefaultChannelIds = model.DefaultChannelIds;
IsEnabled = model.Enabled;
}
/// <inheritdoc cref="IGuildOnboarding.Prompts"/>
/// <remarks>
/// <see langword="null"/> if this property is not mentioned in this entry.
/// </remarks>
IReadOnlyCollection<IGuildOnboardingPrompt> Prompts { get; }
/// <inheritdoc cref="IGuildOnboarding.DefaultChannelIds"/>
/// <remarks>
/// <see langword="null"/> if this property is not mentioned in this entry.
/// </remarks>
IReadOnlyCollection<ulong> DefaultChannelIds { get; }
/// <inheritdoc cref="IGuildOnboarding.IsEnabled"/>
/// <remarks>
/// <see langword="null"/> if this property is not mentioned in this entry.
/// </remarks>
bool? IsEnabled { get; }
}

View File

@@ -0,0 +1,31 @@
using Discord.API.AuditLogs;
using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog;
namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to an onboarding prompt creation.
/// </summary>
public class OnboardingPromptCreatedAuditLogData : IAuditLogData
{
internal OnboardingPromptCreatedAuditLogData(OnboardingPromptInfo data)
{
Data = data;
}
internal static OnboardingPromptCreatedAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log = null)
{
var changes = entry.Changes;
var (_, data) = AuditLogHelper.CreateAuditLogEntityInfo<OnboardingPromptAuditLogModel>(changes, discord);
return new OnboardingPromptCreatedAuditLogData(new(data, discord));
}
/// <summary>
/// Gets the onboarding prompt information after the changes.
/// </summary>
OnboardingPromptInfo Data { get; set; }
}

View File

@@ -0,0 +1,56 @@
using Discord.API.AuditLogs;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
namespace Discord.Rest;
public class OnboardingPromptInfo
{
internal OnboardingPromptInfo(OnboardingPromptAuditLogModel model, BaseDiscordClient discord)
{
Title = model.Title;
IsSingleSelect = model.IsSingleSelect;
IsRequired = model.IsRequired;
IsInOnboarding = model.IsInOnboarding;
Type = model.Type;
Options = model.Options?.Select(x => new RestGuildOnboardingPromptOption(discord, x.Id, x)).ToImmutableArray();
}
/// <inheritdoc cref="IGuildOnboardingPrompt.Title"/>
/// <remarks>
/// <see langword="null"/> if this property is not mentioned in this entry.
/// </remarks>
string Title { get; }
/// <inheritdoc cref="IGuildOnboardingPrompt.IsSingleSelect"/>
/// <remarks>
/// <see langword="null"/> if this property is not mentioned in this entry.
/// </remarks>
bool? IsSingleSelect { get; }
/// <inheritdoc cref="IGuildOnboardingPrompt.IsRequired"/>
/// <remarks>
/// <see langword="null"/> if this property is not mentioned in this entry.
/// </remarks>
bool? IsRequired { get; }
/// <inheritdoc cref="IGuildOnboardingPrompt.IsInOnboarding"/>
/// <remarks>
/// <see langword="null"/> if this property is not mentioned in this entry.
/// </remarks>
bool? IsInOnboarding { get; }
/// <inheritdoc cref="IGuildOnboardingPrompt.Type"/>
/// <remarks>
/// <see langword="null"/> if this property is not mentioned in this entry.
/// </remarks>
GuildOnboardingPromptType? Type { get; }
/// <inheritdoc cref="IGuildOnboardingPrompt.Options"/>
/// <remarks>
/// <see langword="null"/> if this property is not mentioned in this entry.
/// </remarks>
IReadOnlyCollection<IGuildOnboardingPromptOption> Options { get; }
}

View File

@@ -0,0 +1,38 @@
using Discord.API.AuditLogs;
using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog;
namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to an onboarding prompt update.
/// </summary>
public class OnboardingPromptUpdatedAuditLogData : IAuditLogData
{
internal OnboardingPromptUpdatedAuditLogData(OnboardingPromptInfo before, OnboardingPromptInfo after)
{
Before = before;
After = after;
}
internal static OnboardingPromptUpdatedAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log = null)
{
var changes = entry.Changes;
var (before, after) = AuditLogHelper.CreateAuditLogEntityInfo<OnboardingPromptAuditLogModel>(changes, discord);
return new OnboardingPromptUpdatedAuditLogData(new(before, discord), new(after, discord));
}
/// <summary>
/// Gets the onboarding prompt information after the changes.
/// </summary>
OnboardingPromptInfo After { get; set; }
/// <summary>
/// Gets the onboarding prompt information before the changes.
/// </summary>
OnboardingPromptInfo Before { get; set; }
}

View File

@@ -0,0 +1,38 @@
using Discord.API.AuditLogs;
using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog;
namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a guild update.
/// </summary>
public class OnboardingUpdatedAuditLogData : IAuditLogData
{
internal OnboardingUpdatedAuditLogData(OnboardingInfo before, OnboardingInfo after)
{
Before = before;
After = after;
}
internal static OnboardingUpdatedAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log = null)
{
var changes = entry.Changes;
var (before, after) = AuditLogHelper.CreateAuditLogEntityInfo<OnboardingAuditLogModel>(changes, discord);
return new OnboardingUpdatedAuditLogData(new(before, discord), new(after, discord));
}
/// <summary>
/// Gets the onboarding information after the changes.
/// </summary>
OnboardingInfo After { get; set; }
/// <summary>
/// Gets the onboarding information before the changes.
/// </summary>
OnboardingInfo Before { get; set; }
}

View File

@@ -1,52 +1,52 @@
using System.Linq; using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data for a permissions overwrite creation.
/// </summary>
public class OverwriteCreateAuditLogData : IAuditLogData
{ {
/// <summary> private OverwriteCreateAuditLogData(ulong channelId, Overwrite overwrite)
/// Contains a piece of audit log data for a permissions overwrite creation.
/// </summary>
public class OverwriteCreateAuditLogData : IAuditLogData
{ {
private OverwriteCreateAuditLogData(ulong channelId, Overwrite overwrite) ChannelId = channelId;
{ Overwrite = overwrite;
ChannelId = channelId;
Overwrite = overwrite;
}
internal static OverwriteCreateAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var changes = entry.Changes;
var denyModel = changes.FirstOrDefault(x => x.ChangedProperty == "deny");
var allowModel = changes.FirstOrDefault(x => x.ChangedProperty == "allow");
var deny = denyModel.NewValue.ToObject<ulong>(discord.ApiClient.Serializer);
var allow = allowModel.NewValue.ToObject<ulong>(discord.ApiClient.Serializer);
var permissions = new OverwritePermissions(allow, deny);
var id = entry.Options.OverwriteTargetId.Value;
var type = entry.Options.OverwriteType;
return new OverwriteCreateAuditLogData(entry.TargetId.Value, new Overwrite(id, type, permissions));
}
/// <summary>
/// Gets the ID of the channel that the overwrite was created from.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the channel that the overwrite was
/// created from.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the permission overwrite object that was created.
/// </summary>
/// <returns>
/// An <see cref="Overwrite"/> object representing the overwrite that was created.
/// </returns>
public Overwrite Overwrite { get; }
} }
internal static OverwriteCreateAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log = null)
{
var changes = entry.Changes;
var denyModel = changes.FirstOrDefault(x => x.ChangedProperty == "deny");
var allowModel = changes.FirstOrDefault(x => x.ChangedProperty == "allow");
var deny = denyModel.NewValue.ToObject<ulong>(discord.ApiClient.Serializer);
var allow = allowModel.NewValue.ToObject<ulong>(discord.ApiClient.Serializer);
var permissions = new OverwritePermissions(allow, deny);
var id = entry.Options.OverwriteTargetId.Value;
var type = entry.Options.OverwriteType;
return new OverwriteCreateAuditLogData(entry.TargetId.Value, new Overwrite(id, type, permissions));
}
/// <summary>
/// Gets the ID of the channel that the overwrite was created from.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the channel that the overwrite was
/// created from.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the permission overwrite object that was created.
/// </summary>
/// <returns>
/// An <see cref="Overwrite"/> object representing the overwrite that was created.
/// </returns>
public Overwrite Overwrite { get; }
} }

View File

@@ -2,51 +2,50 @@ using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to the deletion of a permission overwrite.
/// </summary>
public class OverwriteDeleteAuditLogData : IAuditLogData
{ {
/// <summary> private OverwriteDeleteAuditLogData(ulong channelId, Overwrite deletedOverwrite)
/// Contains a piece of audit log data related to the deletion of a permission overwrite.
/// </summary>
public class OverwriteDeleteAuditLogData : IAuditLogData
{ {
private OverwriteDeleteAuditLogData(ulong channelId, Overwrite deletedOverwrite) ChannelId = channelId;
{ Overwrite = deletedOverwrite;
ChannelId = channelId;
Overwrite = deletedOverwrite;
}
internal static OverwriteDeleteAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var changes = entry.Changes;
var denyModel = changes.FirstOrDefault(x => x.ChangedProperty == "deny");
var allowModel = changes.FirstOrDefault(x => x.ChangedProperty == "allow");
var deny = denyModel.OldValue.ToObject<ulong>(discord.ApiClient.Serializer);
var allow = allowModel.OldValue.ToObject<ulong>(discord.ApiClient.Serializer);
var permissions = new OverwritePermissions(allow, deny);
var id = entry.Options.OverwriteTargetId.Value;
var type = entry.Options.OverwriteType;
return new OverwriteDeleteAuditLogData(entry.TargetId.Value, new Overwrite(id, type, permissions));
}
/// <summary>
/// Gets the ID of the channel that the overwrite was deleted from.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the channel that the overwrite was
/// deleted from.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the permission overwrite object that was deleted.
/// </summary>
/// <returns>
/// An <see cref="Overwrite"/> object representing the overwrite that was deleted.
/// </returns>
public Overwrite Overwrite { get; }
} }
internal static OverwriteDeleteAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log = null)
{
var changes = entry.Changes;
var denyModel = changes.FirstOrDefault(x => x.ChangedProperty == "deny");
var allowModel = changes.FirstOrDefault(x => x.ChangedProperty == "allow");
var deny = denyModel.OldValue.ToObject<ulong>(discord.ApiClient.Serializer);
var allow = allowModel.OldValue.ToObject<ulong>(discord.ApiClient.Serializer);
var permissions = new OverwritePermissions(allow, deny);
var id = entry.Options.OverwriteTargetId.Value;
var type = entry.Options.OverwriteType;
return new OverwriteDeleteAuditLogData(entry.TargetId.Value, new Overwrite(id, type, permissions));
}
/// <summary>
/// Gets the ID of the channel that the overwrite was deleted from.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the channel that the overwrite was
/// deleted from.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the permission overwrite object that was deleted.
/// </summary>
/// <returns>
/// An <see cref="Overwrite"/> object representing the overwrite that was deleted.
/// </returns>
public Overwrite Overwrite { get; }
} }

View File

@@ -1,80 +1,80 @@
using System.Linq; using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to the update of a permission overwrite.
/// </summary>
public class OverwriteUpdateAuditLogData : IAuditLogData
{ {
/// <summary> private OverwriteUpdateAuditLogData(ulong channelId, OverwritePermissions before, OverwritePermissions after, ulong targetId, PermissionTarget targetType)
/// Contains a piece of audit log data related to the update of a permission overwrite.
/// </summary>
public class OverwriteUpdateAuditLogData : IAuditLogData
{ {
private OverwriteUpdateAuditLogData(ulong channelId, OverwritePermissions before, OverwritePermissions after, ulong targetId, PermissionTarget targetType) ChannelId = channelId;
{ OldPermissions = before;
ChannelId = channelId; NewPermissions = after;
OldPermissions = before; OverwriteTargetId = targetId;
NewPermissions = after; OverwriteType = targetType;
OverwriteTargetId = targetId;
OverwriteType = targetType;
}
internal static OverwriteUpdateAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var changes = entry.Changes;
var denyModel = changes.FirstOrDefault(x => x.ChangedProperty == "deny");
var allowModel = changes.FirstOrDefault(x => x.ChangedProperty == "allow");
var beforeAllow = allowModel?.OldValue?.ToObject<ulong>(discord.ApiClient.Serializer);
var afterAllow = allowModel?.NewValue?.ToObject<ulong>(discord.ApiClient.Serializer);
var beforeDeny = denyModel?.OldValue?.ToObject<ulong>(discord.ApiClient.Serializer);
var afterDeny = denyModel?.NewValue?.ToObject<ulong>(discord.ApiClient.Serializer);
var beforePermissions = new OverwritePermissions(beforeAllow ?? 0, beforeDeny ?? 0);
var afterPermissions = new OverwritePermissions(afterAllow ?? 0, afterDeny ?? 0);
var type = entry.Options.OverwriteType;
return new OverwriteUpdateAuditLogData(entry.TargetId.Value, beforePermissions, afterPermissions, entry.Options.OverwriteTargetId.Value, type);
}
/// <summary>
/// Gets the ID of the channel that the overwrite was updated from.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the channel that the overwrite was
/// updated from.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the overwrite permissions before the changes.
/// </summary>
/// <returns>
/// An overwrite permissions object representing the overwrite permissions that the overwrite had before
/// the changes were made.
/// </returns>
public OverwritePermissions OldPermissions { get; }
/// <summary>
/// Gets the overwrite permissions after the changes.
/// </summary>
/// <returns>
/// An overwrite permissions object representing the overwrite permissions that the overwrite had after the
/// changes.
/// </returns>
public OverwritePermissions NewPermissions { get; }
/// <summary>
/// Gets the ID of the overwrite that was updated.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier of the overwrite that was updated.
/// </returns>
public ulong OverwriteTargetId { get; }
/// <summary>
/// Gets the target of the updated permission overwrite.
/// </summary>
/// <returns>
/// The target of the updated permission overwrite.
/// </returns>
public PermissionTarget OverwriteType { get; }
} }
internal static OverwriteUpdateAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log = null)
{
var changes = entry.Changes;
var denyModel = changes.FirstOrDefault(x => x.ChangedProperty == "deny");
var allowModel = changes.FirstOrDefault(x => x.ChangedProperty == "allow");
var beforeAllow = allowModel?.OldValue?.ToObject<ulong>(discord.ApiClient.Serializer);
var afterAllow = allowModel?.NewValue?.ToObject<ulong>(discord.ApiClient.Serializer);
var beforeDeny = denyModel?.OldValue?.ToObject<ulong>(discord.ApiClient.Serializer);
var afterDeny = denyModel?.NewValue?.ToObject<ulong>(discord.ApiClient.Serializer);
var beforePermissions = new OverwritePermissions(beforeAllow ?? 0, beforeDeny ?? 0);
var afterPermissions = new OverwritePermissions(afterAllow ?? 0, afterDeny ?? 0);
var type = entry.Options.OverwriteType;
return new OverwriteUpdateAuditLogData(entry.TargetId.Value, beforePermissions, afterPermissions, entry.Options.OverwriteTargetId.Value, type);
}
/// <summary>
/// Gets the ID of the channel that the overwrite was updated from.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the channel that the overwrite was
/// updated from.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the overwrite permissions before the changes.
/// </summary>
/// <returns>
/// An overwrite permissions object representing the overwrite permissions that the overwrite had before
/// the changes were made.
/// </returns>
public OverwritePermissions OldPermissions { get; }
/// <summary>
/// Gets the overwrite permissions after the changes.
/// </summary>
/// <returns>
/// An overwrite permissions object representing the overwrite permissions that the overwrite had after the
/// changes.
/// </returns>
public OverwritePermissions NewPermissions { get; }
/// <summary>
/// Gets the ID of the overwrite that was updated.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier of the overwrite that was updated.
/// </returns>
public ulong OverwriteTargetId { get; }
/// <summary>
/// Gets the target of the updated permission overwrite.
/// </summary>
/// <returns>
/// The target of the updated permission overwrite.
/// </returns>
public PermissionTarget OverwriteType { get; }
} }

View File

@@ -1,40 +1,40 @@
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a guild prune.
/// </summary>
public class PruneAuditLogData : IAuditLogData
{ {
/// <summary> private PruneAuditLogData(int pruneDays, int membersRemoved)
/// Contains a piece of audit log data related to a guild prune.
/// </summary>
public class PruneAuditLogData : IAuditLogData
{ {
private PruneAuditLogData(int pruneDays, int membersRemoved) PruneDays = pruneDays;
{ MembersRemoved = membersRemoved;
PruneDays = pruneDays;
MembersRemoved = membersRemoved;
}
internal static PruneAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
return new PruneAuditLogData(entry.Options.PruneDeleteMemberDays.Value, entry.Options.PruneMembersRemoved.Value);
}
/// <summary>
/// Gets the threshold for a guild member to not be kicked.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the amount of days that a member must have been seen in the server,
/// to avoid being kicked. (i.e. If a user has not been seen for more than <paramref cref="PruneDays"/>, they will be
/// kicked from the server)
/// </returns>
public int PruneDays { get; }
/// <summary>
/// Gets the number of members that were kicked during the purge.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the number of members that were removed from this guild for having
/// not been seen within <paramref cref="PruneDays"/>.
/// </returns>
public int MembersRemoved { get; }
} }
internal static PruneAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log = null)
{
return new PruneAuditLogData(entry.Options.PruneDeleteMemberDays.Value, entry.Options.PruneMembersRemoved.Value);
}
/// <summary>
/// Gets the threshold for a guild member to not be kicked.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the amount of days that a member must have been seen in the server,
/// to avoid being kicked. (i.e. If a user has not been seen for more than <paramref cref="PruneDays"/>, they will be
/// kicked from the server)
/// </returns>
public int PruneDays { get; }
/// <summary>
/// Gets the number of members that were kicked during the purge.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the number of members that were removed from this guild for having
/// not been seen within <paramref cref="PruneDays"/>.
/// </returns>
public int MembersRemoved { get; }
} }

View File

@@ -1,61 +1,46 @@
using Discord.API.AuditLogs;
using System.Linq; using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a role creation.
/// </summary>
public class RoleCreateAuditLogData : IAuditLogData
{ {
/// <summary> private RoleCreateAuditLogData(ulong id, RoleEditInfo props)
/// Contains a piece of audit log data related to a role creation.
/// </summary>
public class RoleCreateAuditLogData : IAuditLogData
{ {
private RoleCreateAuditLogData(ulong id, RoleEditInfo props) RoleId = id;
{ Properties = props;
RoleId = id;
Properties = props;
}
internal static RoleCreateAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var changes = entry.Changes;
var colorModel = changes.FirstOrDefault(x => x.ChangedProperty == "color");
var mentionableModel = changes.FirstOrDefault(x => x.ChangedProperty == "mentionable");
var hoistModel = changes.FirstOrDefault(x => x.ChangedProperty == "hoist");
var nameModel = changes.FirstOrDefault(x => x.ChangedProperty == "name");
var permissionsModel = changes.FirstOrDefault(x => x.ChangedProperty == "permissions");
uint? colorRaw = colorModel?.NewValue?.ToObject<uint>(discord.ApiClient.Serializer);
bool? mentionable = mentionableModel?.NewValue?.ToObject<bool>(discord.ApiClient.Serializer);
bool? hoist = hoistModel?.NewValue?.ToObject<bool>(discord.ApiClient.Serializer);
string name = nameModel?.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
ulong? permissionsRaw = permissionsModel?.NewValue?.ToObject<ulong>(discord.ApiClient.Serializer);
Color? color = null;
GuildPermissions? permissions = null;
if (colorRaw.HasValue)
color = new Color(colorRaw.Value);
if (permissionsRaw.HasValue)
permissions = new GuildPermissions(permissionsRaw.Value);
return new RoleCreateAuditLogData(entry.TargetId.Value,
new RoleEditInfo(color, mentionable, hoist, name, permissions));
}
/// <summary>
/// Gets the ID of the role that was created.
/// </summary>
/// <return>
/// A <see cref="ulong"/> representing the snowflake identifier to the role that was created.
/// </return>
public ulong RoleId { get; }
/// <summary>
/// Gets the role information that was created.
/// </summary>
/// <return>
/// An information object representing the properties of the role that was created.
/// </return>
public RoleEditInfo Properties { get; }
} }
internal static RoleCreateAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var changes = entry.Changes;
var (_, data) = AuditLogHelper.CreateAuditLogEntityInfo<RoleInfoAuditLogModel>(changes, discord);
return new RoleCreateAuditLogData(entry.TargetId!.Value,
new RoleEditInfo(data));
}
/// <summary>
/// Gets the ID of the role that was created.
/// </summary>
/// <return>
/// A <see cref="ulong"/> representing the snowflake identifier to the role that was created.
/// </return>
public ulong RoleId { get; }
/// <summary>
/// Gets the role information that was created.
/// </summary>
/// <return>
/// An information object representing the properties of the role that was created.
/// </return>
public RoleEditInfo Properties { get; }
} }

View File

@@ -1,61 +1,43 @@
using System.Linq; using Discord.API.AuditLogs;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data relating to a role deletion.
/// </summary>
public class RoleDeleteAuditLogData : IAuditLogData
{ {
/// <summary> private RoleDeleteAuditLogData(ulong id, RoleEditInfo props)
/// Contains a piece of audit log data relating to a role deletion.
/// </summary>
public class RoleDeleteAuditLogData : IAuditLogData
{ {
private RoleDeleteAuditLogData(ulong id, RoleEditInfo props) RoleId = id;
{ Properties = props;
RoleId = id;
Properties = props;
}
internal static RoleDeleteAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var changes = entry.Changes;
var colorModel = changes.FirstOrDefault(x => x.ChangedProperty == "color");
var mentionableModel = changes.FirstOrDefault(x => x.ChangedProperty == "mentionable");
var hoistModel = changes.FirstOrDefault(x => x.ChangedProperty == "hoist");
var nameModel = changes.FirstOrDefault(x => x.ChangedProperty == "name");
var permissionsModel = changes.FirstOrDefault(x => x.ChangedProperty == "permissions");
uint? colorRaw = colorModel?.OldValue?.ToObject<uint>(discord.ApiClient.Serializer);
bool? mentionable = mentionableModel?.OldValue?.ToObject<bool>(discord.ApiClient.Serializer);
bool? hoist = hoistModel?.OldValue?.ToObject<bool>(discord.ApiClient.Serializer);
string name = nameModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer);
ulong? permissionsRaw = permissionsModel?.OldValue?.ToObject<ulong>(discord.ApiClient.Serializer);
Color? color = null;
GuildPermissions? permissions = null;
if (colorRaw.HasValue)
color = new Color(colorRaw.Value);
if (permissionsRaw.HasValue)
permissions = new GuildPermissions(permissionsRaw.Value);
return new RoleDeleteAuditLogData(entry.TargetId.Value,
new RoleEditInfo(color, mentionable, hoist, name, permissions));
}
/// <summary>
/// Gets the ID of the role that was deleted.
/// </summary>
/// <return>
/// A <see cref="ulong"/> representing the snowflake identifier to the role that was deleted.
/// </return>
public ulong RoleId { get; }
/// <summary>
/// Gets the role information that was deleted.
/// </summary>
/// <return>
/// An information object representing the properties of the role that was deleted.
/// </return>
public RoleEditInfo Properties { get; }
} }
internal static RoleDeleteAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var changes = entry.Changes;
var (data, _) = AuditLogHelper.CreateAuditLogEntityInfo<RoleInfoAuditLogModel>(changes, discord);
return new RoleDeleteAuditLogData(entry.TargetId!.Value, new RoleEditInfo(data));
}
/// <summary>
/// Gets the ID of the role that was deleted.
/// </summary>
/// <return>
/// A <see cref="ulong"/> representing the snowflake identifier to the role that was deleted.
/// </return>
public ulong RoleId { get; }
/// <summary>
/// Gets the role information that was deleted.
/// </summary>
/// <return>
/// An information object representing the properties of the role that was deleted.
/// </return>
public RoleEditInfo Properties { get; }
} }

View File

@@ -1,59 +1,79 @@
namespace Discord.Rest using Model = Discord.API.AuditLogs.RoleInfoAuditLogModel;
{
/// <summary>
/// Represents information for a role edit.
/// </summary>
public struct RoleEditInfo
{
internal RoleEditInfo(Color? color, bool? mentionable, bool? hoist, string name,
GuildPermissions? permissions)
{
Color = color;
Mentionable = mentionable;
Hoist = hoist;
Name = name;
Permissions = permissions;
}
/// <summary> namespace Discord.Rest;
/// Gets the color of this role.
/// </summary> /// <summary>
/// <returns> /// Represents information for a role edit.
/// A color object representing the color assigned to this role; <c>null</c> if this role does not have a /// </summary>
/// color. public struct RoleEditInfo
/// </returns> {
public Color? Color { get; } internal RoleEditInfo(Model model)
/// <summary> {
/// Gets a value that indicates whether this role is mentionable. if (model.Color is not null)
/// </summary> Color = new Color(model.Color.Value);
/// <returns> else
/// <c>true</c> if other members can mention this role in a text channel; otherwise <c>false</c>; Color = null;
/// <c>null</c> if this is not mentioned in this entry.
/// </returns> Mentionable = model.IsMentionable;
public bool? Mentionable { get; } Hoist = model.Hoist;
/// <summary> Name = model.Name;
/// Gets a value that indicates whether this role is hoisted (i.e. its members will appear in a separate
/// section on the user list). if (model.Permissions is not null)
/// </summary> Permissions = new GuildPermissions(model.Permissions.Value);
/// <returns> else
/// <c>true</c> if this role's members will appear in a separate section in the user list; otherwise Permissions = null;
/// <c>false</c>; <c>null</c> if this is not mentioned in this entry.
/// </returns> IconId = model.IconHash;
public bool? Hoist { get; }
/// <summary>
/// Gets the name of this role.
/// </summary>
/// <returns>
/// A string containing the name of this role.
/// </returns>
public string Name { get; }
/// <summary>
/// Gets the permissions assigned to this role.
/// </summary>
/// <returns>
/// A guild permissions object representing the permissions that have been assigned to this role; <c>null</c>
/// if no permissions have been assigned.
/// </returns>
public GuildPermissions? Permissions { get; }
} }
/// <summary>
/// Gets the color of this role.
/// </summary>
/// <returns>
/// A color object representing the color assigned to this role; <c>null</c> if this role does not have a
/// color.
/// </returns>
public Color? Color { get; }
/// <summary>
/// Gets a value that indicates whether this role is mentionable.
/// </summary>
/// <returns>
/// <c>true</c> if other members can mention this role in a text channel; otherwise <c>false</c>;
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public bool? Mentionable { get; }
/// <summary>
/// Gets a value that indicates whether this role is hoisted (i.e. its members will appear in a separate
/// section on the user list).
/// </summary>
/// <returns>
/// <c>true</c> if this role's members will appear in a separate section in the user list; otherwise
/// <c>false</c>; <c>null</c> if this is not mentioned in this entry.
/// </returns>
public bool? Hoist { get; }
/// <summary>
/// Gets the name of this role.
/// </summary>
/// <returns>
/// A string containing the name of this role.
/// </returns>
public string Name { get; }
/// <summary>
/// Gets the permissions assigned to this role.
/// </summary>
/// <returns>
/// A guild permissions object representing the permissions that have been assigned to this role; <c>null</c>
/// if no permissions have been assigned.
/// </returns>
public GuildPermissions? Permissions { get; }
/// <inheritdoc cref="IRole.Icon"/>
/// <remarks>
/// <see langword="null" /> if the value was not updated in this entry.
/// </remarks>
public string IconId { get; }
} }

View File

@@ -1,82 +1,52 @@
using System.Linq; using Discord.API.AuditLogs;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a role update.
/// </summary>
public class RoleUpdateAuditLogData : IAuditLogData
{ {
/// <summary> private RoleUpdateAuditLogData(ulong id, RoleEditInfo oldProps, RoleEditInfo newProps)
/// Contains a piece of audit log data related to a role update.
/// </summary>
public class RoleUpdateAuditLogData : IAuditLogData
{ {
private RoleUpdateAuditLogData(ulong id, RoleEditInfo oldProps, RoleEditInfo newProps) RoleId = id;
{ Before = oldProps;
RoleId = id; After = newProps;
Before = oldProps;
After = newProps;
}
internal static RoleUpdateAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var changes = entry.Changes;
var colorModel = changes.FirstOrDefault(x => x.ChangedProperty == "color");
var mentionableModel = changes.FirstOrDefault(x => x.ChangedProperty == "mentionable");
var hoistModel = changes.FirstOrDefault(x => x.ChangedProperty == "hoist");
var nameModel = changes.FirstOrDefault(x => x.ChangedProperty == "name");
var permissionsModel = changes.FirstOrDefault(x => x.ChangedProperty == "permissions");
uint? oldColorRaw = colorModel?.OldValue?.ToObject<uint>(discord.ApiClient.Serializer),
newColorRaw = colorModel?.NewValue?.ToObject<uint>(discord.ApiClient.Serializer);
bool? oldMentionable = mentionableModel?.OldValue?.ToObject<bool>(discord.ApiClient.Serializer),
newMentionable = mentionableModel?.NewValue?.ToObject<bool>(discord.ApiClient.Serializer);
bool? oldHoist = hoistModel?.OldValue?.ToObject<bool>(discord.ApiClient.Serializer),
newHoist = hoistModel?.NewValue?.ToObject<bool>(discord.ApiClient.Serializer);
string oldName = nameModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer),
newName = nameModel?.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
ulong? oldPermissionsRaw = permissionsModel?.OldValue?.ToObject<ulong>(discord.ApiClient.Serializer),
newPermissionsRaw = permissionsModel?.NewValue?.ToObject<ulong>(discord.ApiClient.Serializer);
Color? oldColor = null,
newColor = null;
GuildPermissions? oldPermissions = null,
newPermissions = null;
if (oldColorRaw.HasValue)
oldColor = new Color(oldColorRaw.Value);
if (newColorRaw.HasValue)
newColor = new Color(newColorRaw.Value);
if (oldPermissionsRaw.HasValue)
oldPermissions = new GuildPermissions(oldPermissionsRaw.Value);
if (newPermissionsRaw.HasValue)
newPermissions = new GuildPermissions(newPermissionsRaw.Value);
var oldProps = new RoleEditInfo(oldColor, oldMentionable, oldHoist, oldName, oldPermissions);
var newProps = new RoleEditInfo(newColor, newMentionable, newHoist, newName, newPermissions);
return new RoleUpdateAuditLogData(entry.TargetId.Value, oldProps, newProps);
}
/// <summary>
/// Gets the ID of the role that was changed.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier of the role that was changed.
/// </returns>
public ulong RoleId { get; }
/// <summary>
/// Gets the role information before the changes.
/// </summary>
/// <returns>
/// A role information object containing the role information before the changes were made.
/// </returns>
public RoleEditInfo Before { get; }
/// <summary>
/// Gets the role information after the changes.
/// </summary>
/// <returns>
/// A role information object containing the role information after the changes were made.
/// </returns>
public RoleEditInfo After { get; }
} }
internal static RoleUpdateAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var changes = entry.Changes;
var (before, after) = AuditLogHelper.CreateAuditLogEntityInfo<RoleInfoAuditLogModel>(changes, discord);
return new RoleUpdateAuditLogData(entry.TargetId!.Value, new(before), new(after));
}
/// <summary>
/// Gets the ID of the role that was changed.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier of the role that was changed.
/// </returns>
public ulong RoleId { get; }
/// <summary>
/// Gets the role information before the changes.
/// </summary>
/// <returns>
/// A role information object containing the role information before the changes were made.
/// </returns>
public RoleEditInfo Before { get; }
/// <summary>
/// Gets the role information after the changes.
/// </summary>
/// <returns>
/// A role information object containing the role information after the changes were made.
/// </returns>
public RoleEditInfo After { get; }
} }

View File

@@ -1,148 +1,97 @@
using Discord.API; using Discord.API.AuditLogs;
using System; using System;
using System.Linq; using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a scheduled event creation.
/// </summary>
public class ScheduledEventCreateAuditLogData : IAuditLogData
{ {
/// <summary> private ScheduledEventCreateAuditLogData(ulong id, ScheduledEventInfoAuditLogModel model, IGuildScheduledEvent scheduledEvent)
/// Contains a piece of audit log data related to a scheduled event creation.
/// </summary>
public class ScheduledEventCreateAuditLogData : IAuditLogData
{ {
private ScheduledEventCreateAuditLogData(ulong id, ulong guildId, ulong? channelId, ulong? creatorId, string name, string description, DateTimeOffset scheduledStartTime, DateTimeOffset? scheduledEndTime, GuildScheduledEventPrivacyLevel privacyLevel, GuildScheduledEventStatus status, GuildScheduledEventType entityType, ulong? entityId, string location, RestUser creator, int userCount, string image) Id = id;
{ ChannelId = model.ChannelId;
Id = id; Name = model.Name;
GuildId = guildId; Description = model.Description;
ChannelId = channelId; ScheduledStartTime = model.StartTime;
CreatorId = creatorId; ScheduledEndTime = model.EndTime;
Name = name; PrivacyLevel = model.PrivacyLevel!.Value;
Description = description; Status = model.EventStatus!.Value;
ScheduledStartTime = scheduledStartTime; EntityType = model.EventType!.Value;
ScheduledEndTime = scheduledEndTime; EntityId = model.EntityId;
PrivacyLevel = privacyLevel; Location = model.Location;
Status = status; Image = model.Image;
EntityType = entityType; ScheduledEvent = scheduledEvent;
EntityId = entityId;
Location = location;
Creator = creator;
UserCount = userCount;
Image = image;
}
internal static ScheduledEventCreateAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var changes = entry.Changes;
var id = entry.TargetId.Value;
var guildId = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "guild_id")
.NewValue.ToObject<ulong>(discord.ApiClient.Serializer);
var channelId = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "channel_id")
.NewValue.ToObject<ulong?>(discord.ApiClient.Serializer);
var creatorId = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "channel_id")
.NewValue.ToObject<Optional<ulong?>>(discord.ApiClient.Serializer)
.GetValueOrDefault();
var name = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "name")
.NewValue.ToObject<string>(discord.ApiClient.Serializer);
var description = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "description")
.NewValue.ToObject<Optional<string>>(discord.ApiClient.Serializer)
.GetValueOrDefault();
var scheduledStartTime = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "scheduled_start_time")
.NewValue.ToObject<DateTimeOffset>(discord.ApiClient.Serializer);
var scheduledEndTime = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "scheduled_end_time")
.NewValue.ToObject<DateTimeOffset?>(discord.ApiClient.Serializer);
var privacyLevel = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "privacy_level")
.NewValue.ToObject<GuildScheduledEventPrivacyLevel>(discord.ApiClient.Serializer);
var status = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "status")
.NewValue.ToObject<GuildScheduledEventStatus>(discord.ApiClient.Serializer);
var entityType = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "entity_type")
.NewValue.ToObject<GuildScheduledEventType>(discord.ApiClient.Serializer);
var entityId = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "entity_id")
.NewValue.ToObject<ulong?>(discord.ApiClient.Serializer);
var entityMetadata = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "entity_metadata")
.NewValue.ToObject<GuildScheduledEventEntityMetadata>(discord.ApiClient.Serializer);
var creator = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "creator")
.NewValue.ToObject<Optional<User>>(discord.ApiClient.Serializer)
.GetValueOrDefault();
var userCount = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "user_count")
.NewValue.ToObject<Optional<int>>(discord.ApiClient.Serializer)
.GetValueOrDefault();
var image = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "image")
.NewValue.ToObject<Optional<string>>(discord.ApiClient.Serializer)
.GetValueOrDefault();
var creatorUser = creator == null ? null : RestUser.Create(discord, creator);
return new ScheduledEventCreateAuditLogData(id, guildId, channelId, creatorId, name, description, scheduledStartTime, scheduledEndTime, privacyLevel, status, entityType, entityId, entityMetadata.Location.GetValueOrDefault(), creatorUser, userCount, image);
}
// Doc Note: Corresponds to the *current* data
/// <summary>
/// Gets the snowflake id of the event.
/// </summary>
public ulong Id { get; }
/// <summary>
/// Gets the snowflake id of the guild the event is associated with.
/// </summary>
public ulong GuildId { get; }
/// <summary>
/// Gets the snowflake id of the channel the event is associated with.
/// </summary>
public ulong? ChannelId { get; }
/// <summary>
/// Gets the snowflake id of the original creator of the event.
/// </summary>
public ulong? CreatorId { get; }
/// <summary>
/// Gets name of the event.
/// </summary>
public string Name { get; }
/// <summary>
/// Gets the description of the event. null if none is set.
/// </summary>
public string Description { get; }
/// <summary>
/// Gets the time the event was scheduled for.
/// </summary>
public DateTimeOffset ScheduledStartTime { get; }
/// <summary>
/// Gets the time the event was scheduled to end.
/// </summary>
public DateTimeOffset? ScheduledEndTime { get; }
/// <summary>
/// Gets the privacy level of the event.
/// </summary>
public GuildScheduledEventPrivacyLevel PrivacyLevel { get; }
/// <summary>
/// Gets the status of the event.
/// </summary>
public GuildScheduledEventStatus Status { get; }
/// <summary>
/// Gets the type of the entity associated with the event (stage / void / external).
/// </summary>
public GuildScheduledEventType EntityType { get; }
/// <summary>
/// Gets the snowflake id of the entity associated with the event (stage / void / external).
/// </summary>
public ulong? EntityId { get; }
/// <summary>
/// Gets the metadata for the entity associated with the event.
/// </summary>
public string Location { get; }
/// <summary>
/// Gets the user that originally created the event.
/// </summary>
public RestUser Creator { get; }
/// <summary>
/// Gets the count of users interested in this event.
/// </summary>
public int UserCount { get; }
/// <summary>
/// Gets the image hash of the image that was attached to the event. Null if not set.
/// </summary>
public string Image { get; }
} }
internal static ScheduledEventCreateAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var changes = entry.Changes;
var (_, data) = AuditLogHelper.CreateAuditLogEntityInfo<ScheduledEventInfoAuditLogModel>(changes, discord);
var scheduledEvent = log.GuildScheduledEvents.FirstOrDefault(x => x.Id == entry.TargetId);
return new ScheduledEventCreateAuditLogData(entry.TargetId!.Value, data, RestGuildEvent.Create(discord, null, scheduledEvent));
}
/// <summary>
/// Gets the scheduled event this log corresponds to.
/// </summary>
public IGuildScheduledEvent ScheduledEvent { get; }
// Doc Note: Corresponds to the *current* data
/// <summary>
/// Gets the snowflake id of the event.
/// </summary>
public ulong Id { get; }
/// <summary>
/// Gets the snowflake id of the channel the event is associated with.
/// </summary>
public ulong? ChannelId { get; }
/// <summary>
/// Gets name of the event.
/// </summary>
public string Name { get; }
/// <summary>
/// Gets the description of the event. null if none is set.
/// </summary>
public string Description { get; }
/// <summary>
/// Gets the time the event was scheduled for.
/// </summary>
public DateTimeOffset? ScheduledStartTime { get; }
/// <summary>
/// Gets the time the event was scheduled to end.
/// </summary>
public DateTimeOffset? ScheduledEndTime { get; }
/// <summary>
/// Gets the privacy level of the event.
/// </summary>
public GuildScheduledEventPrivacyLevel PrivacyLevel { get; }
/// <summary>
/// Gets the status of the event.
/// </summary>
public GuildScheduledEventStatus Status { get; }
/// <summary>
/// Gets the type of the entity associated with the event (stage / void / external).
/// </summary>
public GuildScheduledEventType EntityType { get; }
/// <summary>
/// Gets the snowflake id of the entity associated with the event (stage / void / external).
/// </summary>
public ulong? EntityId { get; }
/// <summary>
/// Gets the metadata for the entity associated with the event.
/// </summary>
public string Location { get; }
/// <summary>
/// Gets the image hash of the image that was attached to the event. Null if not set.
/// </summary>
public string Image { get; }
} }

View File

@@ -1,33 +1,97 @@
using Discord.API; using Discord.API.AuditLogs;
using System; using System;
using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a scheduled event deletion.
/// </summary>
public class ScheduledEventDeleteAuditLogData : IAuditLogData
{ {
/// <summary> private ScheduledEventDeleteAuditLogData(ulong id, ScheduledEventInfoAuditLogModel model)
/// Contains a piece of audit log data related to a scheduled event deletion.
/// </summary>
public class ScheduledEventDeleteAuditLogData : IAuditLogData
{ {
private ScheduledEventDeleteAuditLogData(ulong id) Id = id;
{ ChannelId = model.ChannelId;
Id = id; Name = model.Name;
} Description = model.Description;
ScheduledStartTime = model.StartTime;
internal static ScheduledEventDeleteAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry) ScheduledEndTime = model.EndTime;
{ PrivacyLevel = model.PrivacyLevel;
var id = entry.TargetId.Value; Status = model.EventStatus;
EntityType = model.EventType;
return new ScheduledEventDeleteAuditLogData(id); EntityId = model.EntityId;
} Location = model.Location;
Image = model.Image;
// Doc Note: Corresponds to the *current* data
/// <summary>
/// Gets the snowflake id of the event.
/// </summary>
public ulong Id { get; }
} }
internal static ScheduledEventDeleteAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var changes = entry.Changes;
var (data, _) = AuditLogHelper.CreateAuditLogEntityInfo<ScheduledEventInfoAuditLogModel>(changes, discord);
return new ScheduledEventDeleteAuditLogData(entry.TargetId!.Value, data);
}
/// <summary>
/// Gets the snowflake id of the event.
/// </summary>
public ulong Id { get; }
/// <summary>
/// Gets the snowflake id of the channel the event is associated with.
/// </summary>
public ulong? ChannelId { get; }
/// <summary>
/// Gets name of the event.
/// </summary>
public string Name { get; }
/// <summary>
/// Gets the description of the event. null if none is set.
/// </summary>
public string Description { get; }
/// <summary>
/// Gets the time the event was scheduled for.
/// </summary>
public DateTimeOffset? ScheduledStartTime { get; }
/// <summary>
/// Gets the time the event was scheduled to end.
/// </summary>
public DateTimeOffset? ScheduledEndTime { get; }
/// <summary>
/// Gets the privacy level of the event.
/// </summary>
public GuildScheduledEventPrivacyLevel? PrivacyLevel { get; }
/// <summary>
/// Gets the status of the event.
/// </summary>
public GuildScheduledEventStatus? Status { get; }
/// <summary>
/// Gets the type of the entity associated with the event (stage / void / external).
/// </summary>
public GuildScheduledEventType? EntityType { get; }
/// <summary>
/// Gets the snowflake id of the entity associated with the event (stage / void / external).
/// </summary>
public ulong? EntityId { get; }
/// <summary>
/// Gets the metadata for the entity associated with the event.
/// </summary>
public string Location { get; }
/// <summary>
/// Gets the image hash of the image that was attached to the event. Null if not set.
/// </summary>
public string Image { get; }
} }

View File

@@ -1,80 +1,81 @@
using Discord.API.AuditLogs;
using System; using System;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Represents information for a scheduled event.
/// </summary>
public class ScheduledEventInfo
{ {
/// <summary> /// <summary>
/// Represents information for a scheduled event. /// Gets the snowflake id of the channel the event is associated with.
/// </summary> /// </summary>
public class ScheduledEventInfo public ulong? ChannelId { get; }
{
/// <summary>
/// Gets the snowflake id of the guild the event is associated with.
/// </summary>
public ulong? GuildId { get; }
/// <summary>
/// Gets the snowflake id of the channel the event is associated with. 0 for events with external location.
/// </summary>
public ulong? ChannelId { get; }
/// <summary>
/// Gets name of the event.
/// </summary>
public string Name { get; }
/// <summary>
/// Gets the description of the event. null if none is set.
/// </summary>
public string Description { get; }
/// <summary>
/// Gets the time the event was scheduled for.
/// </summary>
public DateTimeOffset? ScheduledStartTime { get; }
/// <summary>
/// Gets the time the event was scheduled to end.
/// </summary>
public DateTimeOffset? ScheduledEndTime { get; }
/// <summary>
/// Gets the privacy level of the event.
/// </summary>
public GuildScheduledEventPrivacyLevel? PrivacyLevel { get; }
/// <summary>
/// Gets the status of the event.
/// </summary>
public GuildScheduledEventStatus? Status { get; }
/// <summary>
/// Gets the type of the entity associated with the event (stage / void / external).
/// </summary>
public GuildScheduledEventType? EntityType { get; }
/// <summary>
/// Gets the snowflake id of the entity associated with the event (stage / void / external).
/// </summary>
public ulong? EntityId { get; }
/// <summary>
/// Gets the metadata for the entity associated with the event. <see cref="Optional{T}.Unspecified"/> if there was no change.
/// </summary>
public Optional<string> Location { get; }
/// <summary>
/// Gets the count of users interested in this event.
/// </summary>
public int? UserCount { get; }
/// <summary>
/// Gets the image hash of the image that was attached to the event. Null if not set.
/// </summary>
public string Image { get; }
internal ScheduledEventInfo(ulong? guildId, ulong? channelId, string name, string description, DateTimeOffset? scheduledStartTime, DateTimeOffset? scheduledEndTime, GuildScheduledEventPrivacyLevel? privacyLevel, GuildScheduledEventStatus? status, GuildScheduledEventType? entityType, ulong? entityId, Optional<string> location, int? userCount, string image) /// <summary>
{ /// Gets name of the event.
GuildId = guildId; /// </summary>
ChannelId = channelId; public string Name { get; }
Name = name;
Description = description; /// <summary>
ScheduledStartTime = scheduledStartTime; /// Gets the description of the event. null if none is set.
ScheduledEndTime = scheduledEndTime; /// </summary>
PrivacyLevel = privacyLevel; public string Description { get; }
Status = status;
EntityType = entityType; /// <summary>
EntityId = entityId; /// Gets the time the event was scheduled for.
Location = location; /// </summary>
UserCount = userCount; public DateTimeOffset? ScheduledStartTime { get; }
Image = image;
} /// <summary>
/// Gets the time the event was scheduled to end.
/// </summary>
public DateTimeOffset? ScheduledEndTime { get; }
/// <summary>
/// Gets the privacy level of the event.
/// </summary>
public GuildScheduledEventPrivacyLevel? PrivacyLevel { get; }
/// <summary>
/// Gets the status of the event.
/// </summary>
public GuildScheduledEventStatus? Status { get; }
/// <summary>
/// Gets the type of the entity associated with the event (stage / void / external).
/// </summary>
public GuildScheduledEventType? EntityType { get; }
/// <summary>
/// Gets the snowflake id of the entity associated with the event (stage / void / external).
/// </summary>
public ulong? EntityId { get; }
/// <summary>
/// Gets the metadata for the entity associated with the event.
/// </summary>
public string Location { get; }
/// <summary>
/// Gets the image hash of the image that was attached to the event. Null if not set.
/// </summary>
public string Image { get; }
internal ScheduledEventInfo(ScheduledEventInfoAuditLogModel model)
{
ChannelId = model.ChannelId;
Name = model.Name;
Description = model.Description;
ScheduledStartTime = model.StartTime;
ScheduledEndTime = model.EndTime;
PrivacyLevel = model.PrivacyLevel;
Status = model.EventStatus;
EntityType = model.EventType;
EntityId = model.EntityId;
Location = model.Location;
Image = model.Image;
} }
} }

View File

@@ -1,95 +1,54 @@
using System; using Discord.API.AuditLogs;
using System.Linq; using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a scheduled event updates.
/// </summary>
public class ScheduledEventUpdateAuditLogData : IAuditLogData
{ {
/// <summary> private ScheduledEventUpdateAuditLogData(ulong id, ScheduledEventInfo before, ScheduledEventInfo after, IGuildScheduledEvent scheduledEvent)
/// Contains a piece of audit log data related to a scheduled event updates.
/// </summary>
public class ScheduledEventUpdateAuditLogData : IAuditLogData
{ {
private ScheduledEventUpdateAuditLogData(ulong id, ScheduledEventInfo before, ScheduledEventInfo after) Id = id;
{ Before = before;
Id = id; After = after;
Before = before; ScheduledEvent = scheduledEvent;
After = after;
}
internal static ScheduledEventUpdateAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var changes = entry.Changes;
var id = entry.TargetId.Value;
var guildId = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "guild_id");
var channelId = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "channel_id");
var name = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "name");
var description = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "description");
var scheduledStartTime = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "scheduled_start_time");
var scheduledEndTime = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "scheduled_end_time");
var privacyLevel = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "privacy_level");
var status = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "status");
var entityType = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "entity_type");
var entityId = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "entity_id");
var location = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "location");
var userCount = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "user_count");
var image = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "image");
var before = new ScheduledEventInfo(
guildId?.OldValue.ToObject<ulong>(discord.ApiClient.Serializer),
channelId == null ? null : channelId.OldValue?.ToObject<ulong?>(discord.ApiClient.Serializer) ?? 0,
name?.OldValue.ToObject<string>(discord.ApiClient.Serializer),
description?.OldValue.ToObject<Optional<string>>(discord.ApiClient.Serializer)
.GetValueOrDefault(),
scheduledStartTime?.OldValue.ToObject<DateTimeOffset>(discord.ApiClient.Serializer),
scheduledEndTime?.OldValue.ToObject<DateTimeOffset?>(discord.ApiClient.Serializer),
privacyLevel?.OldValue.ToObject<GuildScheduledEventPrivacyLevel>(discord.ApiClient.Serializer),
status?.OldValue.ToObject<GuildScheduledEventStatus>(discord.ApiClient.Serializer),
entityType?.OldValue.ToObject<GuildScheduledEventType>(discord.ApiClient.Serializer),
entityId?.OldValue.ToObject<ulong?>(discord.ApiClient.Serializer),
location == null ? Optional<string>.Unspecified : new Optional<string>(location.OldValue?.ToObject<string>(discord.ApiClient.Serializer)),
userCount?.OldValue.ToObject<Optional<int>>(discord.ApiClient.Serializer)
.GetValueOrDefault(),
image?.OldValue.ToObject<Optional<string>>(discord.ApiClient.Serializer)
.GetValueOrDefault()
);
var after = new ScheduledEventInfo(
guildId?.NewValue.ToObject<ulong>(discord.ApiClient.Serializer),
channelId == null ? null : channelId.NewValue?.ToObject<ulong?>(discord.ApiClient.Serializer) ?? 0,
name?.NewValue.ToObject<string>(discord.ApiClient.Serializer),
description?.NewValue.ToObject<Optional<string>>(discord.ApiClient.Serializer)
.GetValueOrDefault(),
scheduledStartTime?.NewValue.ToObject<DateTimeOffset>(discord.ApiClient.Serializer),
scheduledEndTime?.NewValue.ToObject<DateTimeOffset?>(discord.ApiClient.Serializer),
privacyLevel?.NewValue.ToObject<GuildScheduledEventPrivacyLevel>(discord.ApiClient.Serializer),
status?.NewValue.ToObject<GuildScheduledEventStatus>(discord.ApiClient.Serializer),
entityType?.NewValue.ToObject<GuildScheduledEventType>(discord.ApiClient.Serializer),
entityId?.NewValue.ToObject<ulong?>(discord.ApiClient.Serializer),
location == null ? Optional<string>.Unspecified : new Optional<string>(location.NewValue?.ToObject<string>(discord.ApiClient.Serializer)),
userCount?.NewValue.ToObject<Optional<int>>(discord.ApiClient.Serializer)
.GetValueOrDefault(),
image?.NewValue.ToObject<Optional<string>>(discord.ApiClient.Serializer)
.GetValueOrDefault()
);
return new ScheduledEventUpdateAuditLogData(id, before, after);
}
// Doc Note: Corresponds to the *current* data
/// <summary>
/// Gets the snowflake id of the event.
/// </summary>
public ulong Id { get; }
/// <summary>
/// Gets the state before the change.
/// </summary>
public ScheduledEventInfo Before { get; }
/// <summary>
/// Gets the state after the change.
/// </summary>
public ScheduledEventInfo After { get; }
} }
internal static ScheduledEventUpdateAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var changes = entry.Changes;
var (before, after) = AuditLogHelper.CreateAuditLogEntityInfo<ScheduledEventInfoAuditLogModel>(changes, discord);
var scheduledEvent = log.GuildScheduledEvents.FirstOrDefault(x => x.Id == entry.TargetId);
return new ScheduledEventUpdateAuditLogData(entry.TargetId!.Value, new(before), new(after), RestGuildEvent.Create(discord, null, scheduledEvent));
}
/// <summary>
/// Gets the scheduled event this log corresponds to.
/// </summary>
public IGuildScheduledEvent ScheduledEvent { get; }
// Doc Note: Corresponds to the *current* data
/// <summary>
/// Gets the snowflake id of the event.
/// </summary>
public ulong Id { get; }
/// <summary>
/// Gets the state before the change.
/// </summary>
public ScheduledEventInfo Before { get; }
/// <summary>
/// Gets the state after the change.
/// </summary>
public ScheduledEventInfo After { get; }
} }

View File

@@ -2,49 +2,48 @@ using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a stage going live.
/// </summary>
public class StageInstanceCreateAuditLogData : IAuditLogData
{ {
/// <summary> /// <summary>
/// Contains a piece of audit log data related to a stage going live. /// Gets the topic of the stage channel.
/// </summary> /// </summary>
public class StageInstanceCreateAuditLogData : IAuditLogData public string Topic { get; }
/// <summary>
/// Gets the privacy level of the stage channel.
/// </summary>
public StagePrivacyLevel PrivacyLevel { get; }
/// <summary>
/// Gets the user who started the stage channel.
/// </summary>
public IUser User { get; }
/// <summary>
/// Gets the Id of the stage channel.
/// </summary>
public ulong StageChannelId { get; }
internal StageInstanceCreateAuditLogData(string topic, StagePrivacyLevel privacyLevel, IUser user, ulong channelId)
{ {
/// <summary> Topic = topic;
/// Gets the topic of the stage channel. PrivacyLevel = privacyLevel;
/// </summary> User = user;
public string Topic { get; } StageChannelId = channelId;
}
/// <summary> internal static StageInstanceCreateAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
/// Gets the privacy level of the stage channel. {
/// </summary> var topic = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "topic").NewValue.ToObject<string>(discord.ApiClient.Serializer);
public StagePrivacyLevel PrivacyLevel { get; } var privacyLevel = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "privacy_level").NewValue.ToObject<StagePrivacyLevel>(discord.ApiClient.Serializer);
var user = log.Users.FirstOrDefault(x => x.Id == entry.UserId);
var channelId = entry.Options.ChannelId;
/// <summary> return new StageInstanceCreateAuditLogData(topic, privacyLevel, RestUser.Create(discord, user), channelId ?? 0);
/// Gets the user who started the stage channel.
/// </summary>
public IUser User { get; }
/// <summary>
/// Gets the Id of the stage channel.
/// </summary>
public ulong StageChannelId { get; }
internal StageInstanceCreateAuditLogData(string topic, StagePrivacyLevel privacyLevel, IUser user, ulong channelId)
{
Topic = topic;
PrivacyLevel = privacyLevel;
User = user;
StageChannelId = channelId;
}
internal static StageInstanceCreateAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var topic = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "topic").NewValue.ToObject<string>(discord.ApiClient.Serializer);
var privacyLevel = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "privacy_level").NewValue.ToObject<StagePrivacyLevel>(discord.ApiClient.Serializer);
var user = log.Users.FirstOrDefault(x => x.Id == entry.UserId);
var channelId = entry.Options.ChannelId;
return new StageInstanceCreateAuditLogData(topic, privacyLevel, RestUser.Create(discord, user), channelId ?? 0);
}
} }
} }

View File

@@ -2,49 +2,48 @@ using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a stage instance deleted.
/// </summary>
public class StageInstanceDeleteAuditLogData : IAuditLogData
{ {
/// <summary> /// <summary>
/// Contains a piece of audit log data related to a stage instance deleted. /// Gets the topic of the stage channel.
/// </summary> /// </summary>
public class StageInstanceDeleteAuditLogData public string Topic { get; }
/// <summary>
/// Gets the privacy level of the stage channel.
/// </summary>
public StagePrivacyLevel PrivacyLevel { get; }
/// <summary>
/// Gets the user who started the stage channel.
/// </summary>
public IUser User { get; }
/// <summary>
/// Gets the Id of the stage channel.
/// </summary>
public ulong StageChannelId { get; }
internal StageInstanceDeleteAuditLogData(string topic, StagePrivacyLevel privacyLevel, IUser user, ulong channelId)
{ {
/// <summary> Topic = topic;
/// Gets the topic of the stage channel. PrivacyLevel = privacyLevel;
/// </summary> User = user;
public string Topic { get; } StageChannelId = channelId;
}
/// <summary> internal static StageInstanceDeleteAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
/// Gets the privacy level of the stage channel. {
/// </summary> var topic = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "topic").OldValue.ToObject<string>(discord.ApiClient.Serializer);
public StagePrivacyLevel PrivacyLevel { get; } var privacyLevel = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "privacy_level").OldValue.ToObject<StagePrivacyLevel>(discord.ApiClient.Serializer);
var user = log.Users.FirstOrDefault(x => x.Id == entry.UserId);
var channelId = entry.Options.ChannelId;
/// <summary> return new StageInstanceDeleteAuditLogData(topic, privacyLevel, RestUser.Create(discord, user), channelId ?? 0);
/// Gets the user who started the stage channel.
/// </summary>
public IUser User { get; }
/// <summary>
/// Gets the Id of the stage channel.
/// </summary>
public ulong StageChannelId { get; }
internal StageInstanceDeleteAuditLogData(string topic, StagePrivacyLevel privacyLevel, IUser user, ulong channelId)
{
Topic = topic;
PrivacyLevel = privacyLevel;
User = user;
StageChannelId = channelId;
}
internal static StageInstanceDeleteAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var topic = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "topic").OldValue.ToObject<string>(discord.ApiClient.Serializer);
var privacyLevel = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "privacy_level").OldValue.ToObject<StagePrivacyLevel>(discord.ApiClient.Serializer);
var user = log.Users.FirstOrDefault(x => x.Id == entry.UserId);
var channelId = entry.Options.ChannelId;
return new StageInstanceDeleteAuditLogData(topic, privacyLevel, RestUser.Create(discord, user), channelId ?? 0);
}
} }
} }

View File

@@ -2,50 +2,49 @@ using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a stage instance update.
/// </summary>
public class StageInstanceUpdatedAuditLogData : IAuditLogData
{ {
/// <summary> /// <summary>
/// Contains a piece of audit log data related to a stage instance update. /// Gets the Id of the stage channel.
/// </summary> /// </summary>
public class StageInstanceUpdatedAuditLogData public ulong StageChannelId { get; }
/// <summary>
/// Gets the stage information before the changes.
/// </summary>
public StageInfo Before { get; }
/// <summary>
/// Gets the stage information after the changes.
/// </summary>
public StageInfo After { get; }
internal StageInstanceUpdatedAuditLogData(ulong channelId, StageInfo before, StageInfo after)
{ {
/// <summary> StageChannelId = channelId;
/// Gets the Id of the stage channel. Before = before;
/// </summary> After = after;
public ulong StageChannelId { get; } }
/// <summary> internal static StageInstanceUpdatedAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
/// Gets the stage information before the changes. {
/// </summary> var channelId = entry.Options.ChannelId.Value;
public StageInfo Before { get; }
/// <summary> var topic = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "topic");
/// Gets the stage information after the changes. var privacy = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "privacy");
/// </summary>
public StageInfo After { get; }
internal StageInstanceUpdatedAuditLogData(ulong channelId, StageInfo before, StageInfo after) var user = RestUser.Create(discord, log.Users.FirstOrDefault(x => x.Id == entry.UserId));
{
StageChannelId = channelId;
Before = before;
After = after;
}
internal static StageInstanceUpdatedAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry) var oldTopic = topic?.OldValue.ToObject<string>();
{ var newTopic = topic?.NewValue.ToObject<string>();
var channelId = entry.Options.ChannelId.Value; var oldPrivacy = privacy?.OldValue.ToObject<StagePrivacyLevel>();
var newPrivacy = privacy?.NewValue.ToObject<StagePrivacyLevel>();
var topic = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "topic"); return new StageInstanceUpdatedAuditLogData(channelId, new StageInfo(user, oldPrivacy, oldTopic), new StageInfo(user, newPrivacy, newTopic));
var privacy = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "privacy");
var user = RestUser.Create(discord, log.Users.FirstOrDefault(x => x.Id == entry.UserId));
var oldTopic = topic?.OldValue.ToObject<string>();
var newTopic = topic?.NewValue.ToObject<string>();
var oldPrivacy = privacy?.OldValue.ToObject<StagePrivacyLevel>();
var newPrivacy = privacy?.NewValue.ToObject<StagePrivacyLevel>();
return new StageInstanceUpdatedAuditLogData(channelId, new StageInfo(user, oldPrivacy, oldTopic), new StageInfo(user, newPrivacy, newTopic));
}
} }
} }

View File

@@ -0,0 +1,29 @@
using Discord.API.AuditLogs;
using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog;
namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a sticker creation.
/// </summary>
public class StickerCreatedAuditLogData : IAuditLogData
{
internal StickerCreatedAuditLogData(StickerInfo data)
{
Data = data;
}
internal static StickerCreatedAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log = null)
{
var changes = entry.Changes;
var (_, data) = AuditLogHelper.CreateAuditLogEntityInfo<StickerInfoAuditLogModel>(changes, discord);
return new StickerCreatedAuditLogData(new(data));
}
/// <summary>
/// Gets the sticker information after the changes.
/// </summary>
public StickerInfo Data { get; }
}

View File

@@ -0,0 +1,29 @@
using Discord.API.AuditLogs;
using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog;
namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a sticker removal.
/// </summary>
public class StickerDeletedAuditLogData : IAuditLogData
{
internal StickerDeletedAuditLogData(StickerInfo data)
{
Data = data;
}
internal static StickerDeletedAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log = null)
{
var changes = entry.Changes;
var (data, _) = AuditLogHelper.CreateAuditLogEntityInfo<StickerInfoAuditLogModel>(changes, discord);
return new StickerDeletedAuditLogData(new(data));
}
/// <summary>
/// Gets the sticker information before the changes.
/// </summary>
public StickerInfo Data { get; }
}

View File

@@ -0,0 +1,31 @@
using Discord.API.AuditLogs;
namespace Discord.Rest;
/// <summary>
/// Represents information for a guild.
/// </summary>
public class StickerInfo
{
internal StickerInfo(StickerInfoAuditLogModel model)
{
Name = model.Name;
Tags = model.Tags;
Description = model.Description;
}
/// <summary>
/// Gets the name of the sticker. <see langword="null" /> if the value was not updated in this entry.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Gets tags of the sticker. <see langword="null" /> if the value was not updated in this entry.
/// </summary>
public string Tags { get; set; }
/// <summary>
/// Gets the description of the sticker. <see langword="null" /> if the value was not updated in this entry.
/// </summary>
public string Description { get; set; }
}

View File

@@ -0,0 +1,35 @@
using Discord.API.AuditLogs;
using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog;
namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a sticker update.
/// </summary>
public class StickerUpdatedAuditLogData : IAuditLogData
{
internal StickerUpdatedAuditLogData(StickerInfo before, StickerInfo after)
{
Before = before;
After = after;
}
internal static StickerUpdatedAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log = null)
{
var changes = entry.Changes;
var (before, after) = AuditLogHelper.CreateAuditLogEntityInfo<StickerInfoAuditLogModel>(changes, discord);
return new StickerUpdatedAuditLogData(new(before), new (after));
}
/// <summary>
/// Gets the sticker information before the changes.
/// </summary>
public StickerInfo Before { get; }
/// <summary>
/// Gets the sticker information after the changes.
/// </summary>
public StickerInfo After { get; }
}

View File

@@ -1,114 +1,123 @@
using Discord.API.AuditLogs;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a thread creation.
/// </summary>
public class ThreadCreateAuditLogData : IAuditLogData
{ {
/// <summary> private ThreadCreateAuditLogData(IThreadChannel thread, ulong id, ThreadInfoAuditLogModel model)
/// Contains a piece of audit log data related to a thread creation.
/// </summary>
public class ThreadCreateAuditLogData : IAuditLogData
{ {
private ThreadCreateAuditLogData(IThreadChannel thread, ulong id, string name, ThreadType type, bool archived, Thread = thread;
ThreadArchiveDuration autoArchiveDuration, bool locked, int? rateLimit) ThreadId = id;
{
Thread = thread;
ThreadId = id;
ThreadName = name;
ThreadType = type;
IsArchived = archived;
AutoArchiveDuration = autoArchiveDuration;
IsLocked = locked;
SlowModeInterval = rateLimit;
}
internal static ThreadCreateAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry) ThreadName = model.Name;
{ IsArchived = model.IsArchived!.Value;
var changes = entry.Changes; AutoArchiveDuration = model.ArchiveDuration!.Value;
IsLocked = model.IsLocked!.Value;
var id = entry.TargetId.Value; SlowModeInterval = model.SlowModeInterval;
AppliedTags = model.AppliedTags;
var nameModel = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "name"); Flags = model.ChannelFlags;
var typeModel = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "type"); ThreadType = model.Type;
var archivedModel = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "archived");
var autoArchiveDurationModel = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "auto_archive_duration");
var lockedModel = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "locked");
var rateLimitPerUserModel = changes.FirstOrDefault(x => x.ChangedProperty == "rate_limit_per_user");
var name = nameModel.NewValue.ToObject<string>(discord.ApiClient.Serializer);
var type = typeModel.NewValue.ToObject<ThreadType>(discord.ApiClient.Serializer);
var archived = archivedModel.NewValue.ToObject<bool>(discord.ApiClient.Serializer);
var autoArchiveDuration = autoArchiveDurationModel.NewValue.ToObject<ThreadArchiveDuration>(discord.ApiClient.Serializer);
var locked = lockedModel.NewValue.ToObject<bool>(discord.ApiClient.Serializer);
var rateLimit = rateLimitPerUserModel?.NewValue?.ToObject<int>(discord.ApiClient.Serializer);
var threadInfo = log.Threads.FirstOrDefault(x => x.Id == id);
var threadChannel = threadInfo == null ? null : RestThreadChannel.Create(discord, (IGuild)null, threadInfo);
return new ThreadCreateAuditLogData(threadChannel, id, name, type, archived, autoArchiveDuration, locked, rateLimit);
}
// Doc Note: Corresponds to the *current* data
/// <summary>
/// Gets the thread that was created if it still exists.
/// </summary>
/// <returns>
/// A thread object representing the thread that was created if it still exists, otherwise returns <c>null</c>.
/// </returns>
public IThreadChannel Thread { get; }
/// <summary>
/// Gets the snowflake ID of the thread.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the thread.
/// </returns>
public ulong ThreadId { get; }
/// <summary>
/// Gets the name of the thread.
/// </summary>
/// <returns>
/// A string containing the name of the thread.
/// </returns>
public string ThreadName { get; }
/// <summary>
/// Gets the type of the thread.
/// </summary>
/// <returns>
/// The type of thread.
/// </returns>
public ThreadType ThreadType { get; }
/// <summary>
/// Gets the value that indicates whether the thread is archived.
/// </summary>
/// <returns>
/// <c>true</c> if this thread has the Archived flag enabled; otherwise <c>false</c>.
/// </returns>
public bool IsArchived { get; }
/// <summary>
/// Gets the auto archive duration of the thread.
/// </summary>
/// <returns>
/// The thread auto archive duration of the thread.
/// </returns>
public ThreadArchiveDuration AutoArchiveDuration { get; }
/// <summary>
/// Gets the value that indicates whether the thread is locked.
/// </summary>
/// <returns>
/// <c>true</c> if this thread has the Locked flag enabled; otherwise <c>false</c>.
/// </returns>
public bool IsLocked { get; }
/// <summary>
/// Gets the slow-mode delay of the thread.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the time in seconds required before the user can send another
/// message; <c>0</c> if disabled.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public int? SlowModeInterval { get; }
} }
internal static ThreadCreateAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var changes = entry.Changes;
var (_, data) = AuditLogHelper.CreateAuditLogEntityInfo<ThreadInfoAuditLogModel>(changes, discord);
var threadInfo = log.Threads.FirstOrDefault(x => x.Id == entry.TargetId!.Value);
var threadChannel = threadInfo == null ? null : RestThreadChannel.Create(discord, (IGuild)null, threadInfo);
return new ThreadCreateAuditLogData(threadChannel, entry.TargetId!.Value, data);
}
/// <summary>
/// Gets the thread that was created if it still exists.
/// </summary>
/// <returns>
/// A thread object representing the thread that was created if it still exists, otherwise returns <c>null</c>.
/// </returns>
public IThreadChannel Thread { get; }
/// <summary>
/// Gets the snowflake ID of the thread.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the thread.
/// </returns>
public ulong ThreadId { get; }
/// <summary>
/// Gets the name of the thread.
/// </summary>
/// <returns>
/// A string containing the name of the thread.
/// </returns>
public string ThreadName { get; }
/// <summary>
/// Gets the type of the thread.
/// </summary>
/// <returns>
/// The type of thread.
/// </returns>
public ThreadType ThreadType { get; }
/// <summary>
/// Gets the value that indicates whether the thread is archived.
/// </summary>
/// <returns>
/// <c>true</c> if this thread has the Archived flag enabled; otherwise <c>false</c>.
/// </returns>
public bool IsArchived { get; }
/// <summary>
/// Gets the auto archive duration of the thread.
/// </summary>
/// <returns>
/// The thread auto archive duration of the thread.
/// </returns>
public ThreadArchiveDuration AutoArchiveDuration { get; }
/// <summary>
/// Gets the value that indicates whether the thread is locked.
/// </summary>
/// <returns>
/// <c>true</c> if this thread has the Locked flag enabled; otherwise <c>false</c>.
/// </returns>
public bool IsLocked { get; }
/// <summary>
/// Gets the slow-mode delay of the thread.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the time in seconds required before the user can send another
/// message; <c>0</c> if disabled.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public int? SlowModeInterval { get; }
/// <summary>
/// Gets the applied tags of this thread.
/// </summary>
/// <remarks>
/// <see langword="null"/> if the property was not updated.
/// </remarks>
public IReadOnlyCollection<ulong> AppliedTags { get; }
/// <summary>
/// Gets the flags of the thread channel.
/// </summary>
/// <remarks>
/// <see langword="null"/> if the property was not updated.
/// </remarks>
public ChannelFlags? Flags { get; }
} }

View File

@@ -1,102 +1,111 @@
using System.Linq; using Discord.API.AuditLogs;
using System.Collections.Generic;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a thread deletion.
/// </summary>
public class ThreadDeleteAuditLogData : IAuditLogData
{ {
/// <summary> private ThreadDeleteAuditLogData(ulong id, ThreadInfoAuditLogModel model)
/// Contains a piece of audit log data related to a thread deletion.
/// </summary>
public class ThreadDeleteAuditLogData : IAuditLogData
{ {
private ThreadDeleteAuditLogData(ulong id, string name, ThreadType type, bool archived, ThreadId = id;
ThreadArchiveDuration autoArchiveDuration, bool locked, int? rateLimit)
{
ThreadId = id;
ThreadName = name;
ThreadType = type;
IsArchived = archived;
AutoArchiveDuration = autoArchiveDuration;
IsLocked = locked;
SlowModeInterval = rateLimit;
}
internal static ThreadDeleteAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry) ThreadName = model.Name;
{ IsArchived = model.IsArchived!.Value;
var changes = entry.Changes; AutoArchiveDuration = model.ArchiveDuration!.Value;
IsLocked = model.IsLocked!.Value;
var id = entry.TargetId.Value; SlowModeInterval = model.SlowModeInterval;
var thread = log.Threads.FirstOrDefault(x => x.Id == id); AppliedTags = model.AppliedTags;
Flags = model.ChannelFlags;
var nameModel = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "name"); ThreadType = model.Type;
var typeModel = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "type");
var archivedModel = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "archived");
var autoArchiveDurationModel = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "auto_archive_duration");
var lockedModel = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "locked");
var rateLimitPerUserModel = changes.FirstOrDefault(x => x.ChangedProperty == "rate_limit_per_user");
var name = nameModel.OldValue.ToObject<string>(discord.ApiClient.Serializer);
var type = typeModel.OldValue.ToObject<ThreadType>(discord.ApiClient.Serializer);
var archived = archivedModel.OldValue.ToObject<bool>(discord.ApiClient.Serializer);
var autoArchiveDuration = autoArchiveDurationModel.OldValue.ToObject<ThreadArchiveDuration>(discord.ApiClient.Serializer);
var locked = lockedModel.OldValue.ToObject<bool>(discord.ApiClient.Serializer);
var rateLimit = rateLimitPerUserModel?.NewValue?.ToObject<int>(discord.ApiClient.Serializer);
return new ThreadDeleteAuditLogData(id, name, type, archived, autoArchiveDuration, locked, rateLimit);
}
/// <summary>
/// Gets the snowflake ID of the deleted thread.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the deleted thread.
/// </returns>
public ulong ThreadId { get; }
/// <summary>
/// Gets the name of the deleted thread.
/// </summary>
/// <returns>
/// A string containing the name of the deleted thread.
/// </returns>
public string ThreadName { get; }
/// <summary>
/// Gets the type of the deleted thread.
/// </summary>
/// <returns>
/// The type of thread that was deleted.
/// </returns>
public ThreadType ThreadType { get; }
/// <summary>
/// Gets the value that indicates whether the deleted thread was archived.
/// </summary>
/// <returns>
/// <c>true</c> if this thread had the Archived flag enabled; otherwise <c>false</c>.
/// </returns>
public bool IsArchived { get; }
/// <summary>
/// Gets the thread auto archive duration of the deleted thread.
/// </summary>
/// <returns>
/// The thread auto archive duration of the thread that was deleted.
/// </returns>
public ThreadArchiveDuration AutoArchiveDuration { get; }
/// <summary>
/// Gets the value that indicates whether the deleted thread was locked.
/// </summary>
/// <returns>
/// <c>true</c> if this thread had the Locked flag enabled; otherwise <c>false</c>.
/// </returns>
public bool IsLocked { get; }
/// <summary>
/// Gets the slow-mode delay of the deleted thread.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the time in seconds required before the user can send another
/// message; <c>0</c> if disabled.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public int? SlowModeInterval { get; }
} }
internal static ThreadDeleteAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var changes = entry.Changes;
var (data, _) = AuditLogHelper.CreateAuditLogEntityInfo<ThreadInfoAuditLogModel>(changes, discord);
return new ThreadDeleteAuditLogData(entry.TargetId!.Value, data);
}
/// <summary>
/// Gets the snowflake ID of the deleted thread.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier for the deleted thread.
///
/// </returns>
public ulong ThreadId { get; }
/// <summary>
/// Gets the name of the deleted thread.
/// </summary>
/// <returns>
/// A string containing the name of the deleted thread.
///
/// </returns>
public string ThreadName { get; }
/// <summary>
/// Gets the type of the deleted thread.
/// </summary>
/// <returns>
/// The type of thread that was deleted.
/// </returns>
public ThreadType ThreadType { get; }
/// <summary>
/// Gets the value that indicates whether the deleted thread was archived.
/// </summary>
/// <returns>
/// <c>true</c> if this thread had the Archived flag enabled; otherwise <c>false</c>.
/// </returns>
public bool IsArchived { get; }
/// <summary>
/// Gets the thread auto archive duration of the deleted thread.
/// </summary>
/// <returns>
/// The thread auto archive duration of the thread that was deleted.
/// </returns>
public ThreadArchiveDuration AutoArchiveDuration { get; }
/// <summary>
/// Gets the value that indicates whether the deleted thread was locked.
/// </summary>
/// <returns>
/// <c>true</c> if this thread had the Locked flag enabled; otherwise <c>false</c>.
/// </returns>
public bool IsLocked { get; }
/// <summary>
/// Gets the slow-mode delay of the deleted thread.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the time in seconds required before the user can send another
/// message; <c>0</c> if disabled.
/// <c>null</c> if this is not mentioned in this entry.
/// </returns>
public int? SlowModeInterval { get; }
/// <summary>
/// Gets the applied tags of this thread.
/// </summary>
/// <remarks>
/// <see langword="null"/> if this is not mentioned in this entry.
/// </remarks>
public IReadOnlyCollection<ulong> AppliedTags { get; }
/// <summary>
/// Gets the flags of the thread channel.
/// </summary>
/// <remarks>
/// <see langword="null"/> if this is not mentioned in this entry.
/// </remarks>
public ChannelFlags? Flags { get; }
} }

View File

@@ -1,39 +1,84 @@
namespace Discord.Rest using Discord.API.AuditLogs;
using System;
using System.Collections.Generic;
namespace Discord.Rest;
/// <summary>
/// Represents information for a thread.
/// </summary>
public class ThreadInfo
{ {
/// <summary> /// <summary>
/// Represents information for a thread. /// Gets the name of the thread.
/// </summary> /// </summary>
public class ThreadInfo public string Name { get; }
/// <summary>
/// Gets the value that indicates whether the thread is archived.
/// </summary>
/// <remarks>
/// <see langword="null"/> if the property was not updated.
/// </remarks>
public bool? IsArchived { get; }
/// <summary>
/// Gets the auto archive duration of thread.
/// </summary>
/// <remarks>
/// <see langword="null"/> if the property was not updated.
/// </remarks>
public ThreadArchiveDuration? AutoArchiveDuration { get; }
/// <summary>
/// Gets the value that indicates whether the thread is locked.
/// </summary>
/// <remarks>
/// <see langword="null"/> if the property was not updated.
/// </remarks>
public bool? IsLocked { get; }
/// <summary>
/// Gets the slow-mode delay of the thread.
/// </summary>
/// <remarks>
/// <see langword="null"/> if the property was not updated.
/// </remarks>
public int? SlowModeInterval { get; }
/// <summary>
/// Gets the applied tags of this thread.
/// </summary>
/// <remarks>
/// <see langword="null"/> if the property was not updated.
/// </remarks>
public IReadOnlyCollection<ulong> AppliedTags { get; }
/// <summary>
/// Gets the flags of the thread channel.
/// </summary>
/// <remarks>
/// <see langword="null"/> if the property was not updated.
/// </remarks>
public ChannelFlags? Flags { get; }
/// <summary>
/// Gets the type of the thread.
/// </summary>
/// <remarks>
/// <see langword="null"/> if the property was not updated.
/// </remarks>
public ThreadType Type { get; }
internal ThreadInfo(ThreadInfoAuditLogModel model)
{ {
/// <summary> Name = model.Name;
/// Gets the name of the thread. IsArchived = model.IsArchived;
/// </summary> AutoArchiveDuration = model.ArchiveDuration;
public string Name { get; } IsLocked = model.IsLocked;
/// <summary> SlowModeInterval = model.SlowModeInterval;
/// Gets the value that indicates whether the thread is archived. AppliedTags = model.AppliedTags;
/// </summary> Flags = model.ChannelFlags;
public bool IsArchived { get; } Type = model.Type;
/// <summary>
/// Gets the auto archive duration of thread.
/// </summary>
public ThreadArchiveDuration AutoArchiveDuration { get; }
/// <summary>
/// Gets the value that indicates whether the thread is locked.
/// </summary>
public bool IsLocked { get; }
/// <summary>
/// Gets the slow-mode delay of the ´thread.
/// </summary>
public int? SlowModeInterval { get; }
internal ThreadInfo(string name, bool archived, ThreadArchiveDuration autoArchiveDuration, bool locked, int? rateLimit)
{
Name = name;
IsArchived = archived;
AutoArchiveDuration = autoArchiveDuration;
IsLocked = locked;
SlowModeInterval = rateLimit;
}
} }
} }

View File

@@ -1,87 +1,67 @@
using Discord.API.AuditLogs;
using System.Linq; using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a thread update.
/// </summary>
public class ThreadUpdateAuditLogData : IAuditLogData
{ {
/// <summary> private ThreadUpdateAuditLogData(IThreadChannel thread, ThreadType type, ThreadInfo before, ThreadInfo after)
/// Contains a piece of audit log data related to a thread update.
/// </summary>
public class ThreadUpdateAuditLogData : IAuditLogData
{ {
private ThreadUpdateAuditLogData(IThreadChannel thread, ThreadType type, ThreadInfo before, ThreadInfo after) Thread = thread;
{ ThreadType = type;
Thread = thread; Before = before;
ThreadType = type; After = after;
Before = before;
After = after;
}
internal static ThreadUpdateAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var changes = entry.Changes;
var id = entry.TargetId.Value;
var nameModel = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "name");
var typeModel = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "type");
var archivedModel = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "archived");
var autoArchiveDurationModel = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "auto_archive_duration");
var lockedModel = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "locked");
var rateLimitPerUserModel = changes.FirstOrDefault(x => x.ChangedProperty == "rate_limit_per_user");
var type = typeModel.OldValue.ToObject<ThreadType>(discord.ApiClient.Serializer);
var oldName = nameModel.OldValue.ToObject<string>(discord.ApiClient.Serializer);
var oldArchived = archivedModel.OldValue.ToObject<bool>(discord.ApiClient.Serializer);
var oldAutoArchiveDuration = autoArchiveDurationModel.OldValue.ToObject<ThreadArchiveDuration>(discord.ApiClient.Serializer);
var oldLocked = lockedModel.OldValue.ToObject<bool>(discord.ApiClient.Serializer);
var oldRateLimit = rateLimitPerUserModel?.OldValue?.ToObject<int>(discord.ApiClient.Serializer);
var before = new ThreadInfo(oldName, oldArchived, oldAutoArchiveDuration, oldLocked, oldRateLimit);
var newName = nameModel.NewValue.ToObject<string>(discord.ApiClient.Serializer);
var newArchived = archivedModel.NewValue.ToObject<bool>(discord.ApiClient.Serializer);
var newAutoArchiveDuration = autoArchiveDurationModel.NewValue.ToObject<ThreadArchiveDuration>(discord.ApiClient.Serializer);
var newLocked = lockedModel.NewValue.ToObject<bool>(discord.ApiClient.Serializer);
var newRateLimit = rateLimitPerUserModel?.NewValue?.ToObject<int>(discord.ApiClient.Serializer);
var after = new ThreadInfo(newName, newArchived, newAutoArchiveDuration, newLocked, newRateLimit);
var threadInfo = log.Threads.FirstOrDefault(x => x.Id == id);
var threadChannel = threadInfo == null ? null : RestThreadChannel.Create(discord, (IGuild)null, threadInfo);
return new ThreadUpdateAuditLogData(threadChannel, type, before, after);
}
// Doc Note: Corresponds to the *current* data
/// <summary>
/// Gets the thread that was created if it still exists.
/// </summary>
/// <returns>
/// A thread object representing the thread that was created if it still exists, otherwise returns <c>null</c>.
/// </returns>
public IThreadChannel Thread { get; }
/// <summary>
/// Gets the type of the thread.
/// </summary>
/// <returns>
/// The type of thread.
/// </returns>
public ThreadType ThreadType { get; }
/// <summary>
/// Gets the thread information before the changes.
/// </summary>
/// <returns>
/// A thread information object representing the thread before the changes were made.
/// </returns>
public ThreadInfo Before { get; }
/// <summary>
/// Gets the thread information after the changes.
/// </summary>
/// <returns>
/// A thread information object representing the thread after the changes were made.
/// </returns>
public ThreadInfo After { get; }
} }
internal static ThreadUpdateAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var changes = entry.Changes;
var (before, after) = AuditLogHelper.CreateAuditLogEntityInfo<ThreadInfoAuditLogModel>(changes, discord);
var threadInfo = log.Threads.FirstOrDefault(x => x.Id == entry.TargetId!.Value);
var threadChannel = threadInfo == null ? null : RestThreadChannel.Create(discord, (IGuild)null, threadInfo);
return new ThreadUpdateAuditLogData(threadChannel, before.Type, new(before), new (after));
}
// Doc Note: Corresponds to the *current* data
/// <summary>
/// Gets the thread that was created if it still exists.
/// </summary>
/// <returns>
/// A thread object representing the thread that was created if it still exists, otherwise returns <c>null</c>.
/// </returns>
public IThreadChannel Thread { get; }
/// <summary>
/// Gets the type of the thread.
/// </summary>
/// <returns>
/// The type of thread.
/// </returns>
public ThreadType ThreadType { get; }
/// <summary>
/// Gets the thread information before the changes.
/// </summary>
/// <returns>
/// A thread information object representing the thread before the changes were made.
/// </returns>
public ThreadInfo Before { get; }
/// <summary>
/// Gets the thread information after the changes.
/// </summary>
/// <returns>
/// A thread information object representing the thread after the changes were made.
/// </returns>
public ThreadInfo After { get; }
} }

View File

@@ -2,30 +2,29 @@ using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to an unban.
/// </summary>
public class UnbanAuditLogData : IAuditLogData
{ {
/// <summary> private UnbanAuditLogData(IUser user)
/// Contains a piece of audit log data related to an unban.
/// </summary>
public class UnbanAuditLogData : IAuditLogData
{ {
private UnbanAuditLogData(IUser user) Target = user;
{
Target = user;
}
internal static UnbanAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var userInfo = log.Users.FirstOrDefault(x => x.Id == entry.TargetId);
return new UnbanAuditLogData((userInfo != null) ? RestUser.Create(discord, userInfo) : null);
}
/// <summary>
/// Gets the user that was unbanned.
/// </summary>
/// <returns>
/// A user object representing the user that was unbanned.
/// </returns>
public IUser Target { get; }
} }
internal static UnbanAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log = null)
{
var userInfo = log.Users.FirstOrDefault(x => x.Id == entry.TargetId);
return new UnbanAuditLogData((userInfo != null) ? RestUser.Create(discord, userInfo) : null);
}
/// <summary>
/// Gets the user that was unbanned.
/// </summary>
/// <returns>
/// A user object representing the user that was unbanned.
/// </returns>
public IUser Target { get; }
} }

View File

@@ -1,83 +1,87 @@
using Discord.API.AuditLogs;
using System.Linq; using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a webhook creation.
/// </summary>
public class WebhookCreateAuditLogData : IAuditLogData
{ {
/// <summary> private WebhookCreateAuditLogData(IWebhook webhook, ulong webhookId, WebhookInfoAuditLogModel model)
/// Contains a piece of audit log data related to a webhook creation.
/// </summary>
public class WebhookCreateAuditLogData : IAuditLogData
{ {
private WebhookCreateAuditLogData(IWebhook webhook, ulong webhookId, WebhookType type, string name, ulong channelId) Webhook = webhook;
{ WebhookId = webhookId;
Webhook = webhook; Name = model.Name;
WebhookId = webhookId; Type = model.Type!.Value;
Name = name; ChannelId = model.ChannelId!.Value;
Type = type; Avatar = model.AvatarHash;
ChannelId = channelId;
}
internal static WebhookCreateAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var changes = entry.Changes;
var channelIdModel = changes.FirstOrDefault(x => x.ChangedProperty == "channel_id");
var typeModel = changes.FirstOrDefault(x => x.ChangedProperty == "type");
var nameModel = changes.FirstOrDefault(x => x.ChangedProperty == "name");
var channelId = channelIdModel.NewValue.ToObject<ulong>(discord.ApiClient.Serializer);
var type = typeModel.NewValue.ToObject<WebhookType>(discord.ApiClient.Serializer);
var name = nameModel.NewValue.ToObject<string>(discord.ApiClient.Serializer);
var webhookInfo = log.Webhooks?.FirstOrDefault(x => x.Id == entry.TargetId);
var webhook = webhookInfo == null ? null : RestWebhook.Create(discord, (IGuild)null, webhookInfo);
return new WebhookCreateAuditLogData(webhook, entry.TargetId.Value, type, name, channelId);
}
// Doc Note: Corresponds to the *current* data
/// <summary>
/// Gets the webhook that was created if it still exists.
/// </summary>
/// <returns>
/// A webhook object representing the webhook that was created if it still exists, otherwise returns <c>null</c>.
/// </returns>
public IWebhook Webhook { get; }
// Doc Note: Corresponds to the *audit log* data
/// <summary>
/// Gets the webhook id.
/// </summary>
/// <returns>
/// The webhook identifier.
/// </returns>
public ulong WebhookId { get; }
/// <summary>
/// Gets the type of webhook that was created.
/// </summary>
/// <returns>
/// The type of webhook that was created.
/// </returns>
public WebhookType Type { get; }
/// <summary>
/// Gets the name of the webhook.
/// </summary>
/// <returns>
/// A string containing the name of the webhook.
/// </returns>
public string Name { get; }
/// <summary>
/// Gets the ID of the channel that the webhook could send to.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier of the channel that the webhook could send
/// to.
/// </returns>
public ulong ChannelId { get; }
} }
internal static WebhookCreateAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var changes = entry.Changes;
var (_, data) = AuditLogHelper.CreateAuditLogEntityInfo<WebhookInfoAuditLogModel>(changes, discord);
var webhookInfo = log.Webhooks?.FirstOrDefault(x => x.Id == entry.TargetId);
var webhook = webhookInfo == null ? null : RestWebhook.Create(discord, (IGuild)null, webhookInfo);
return new WebhookCreateAuditLogData(webhook, entry.TargetId!.Value, data);
}
// Doc Note: Corresponds to the *current* data
/// <summary>
/// Gets the webhook that was created if it still exists.
/// </summary>
/// <returns>
/// A webhook object representing the webhook that was created if it still exists, otherwise returns <c>null</c>.
/// </returns>
public IWebhook Webhook { get; }
// Doc Note: Corresponds to the *audit log* data
/// <summary>
/// Gets the webhook id.
/// </summary>
/// <returns>
/// The webhook identifier.
/// </returns>
public ulong WebhookId { get; }
/// <summary>
/// Gets the type of webhook that was created.
/// </summary>
/// <returns>
/// The type of webhook that was created.
/// </returns>
public WebhookType Type { get; }
/// <summary>
/// Gets the name of the webhook.
/// </summary>
/// <returns>
/// A string containing the name of the webhook.
/// </returns>
public string Name { get; }
/// <summary>
/// Gets the ID of the channel that the webhook could send to.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier of the channel that the webhook could send
/// to.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the hash value of the webhook's avatar.
/// </summary>
/// <returns>
/// A string containing the hash of the webhook's avatar.
/// </returns>
public string Avatar { get; }
} }

View File

@@ -1,75 +1,71 @@
using System.Linq; using Discord.API.AuditLogs;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a webhook deletion.
/// </summary>
public class WebhookDeleteAuditLogData : IAuditLogData
{ {
/// <summary> private WebhookDeleteAuditLogData(ulong id, WebhookInfoAuditLogModel model)
/// Contains a piece of audit log data related to a webhook deletion.
/// </summary>
public class WebhookDeleteAuditLogData : IAuditLogData
{ {
private WebhookDeleteAuditLogData(ulong id, ulong channel, WebhookType type, string name, string avatar) WebhookId = id;
{ ChannelId = model.ChannelId!.Value;
WebhookId = id; Name = model.Name;
ChannelId = channel; Type = model.Type!.Value;
Name = name; Avatar = model.AvatarHash;
Type = type;
Avatar = avatar;
}
internal static WebhookDeleteAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var changes = entry.Changes;
var channelIdModel = changes.FirstOrDefault(x => x.ChangedProperty == "channel_id");
var typeModel = changes.FirstOrDefault(x => x.ChangedProperty == "type");
var nameModel = changes.FirstOrDefault(x => x.ChangedProperty == "name");
var avatarHashModel = changes.FirstOrDefault(x => x.ChangedProperty == "avatar_hash");
var channelId = channelIdModel.OldValue.ToObject<ulong>(discord.ApiClient.Serializer);
var type = typeModel.OldValue.ToObject<WebhookType>(discord.ApiClient.Serializer);
var name = nameModel.OldValue.ToObject<string>(discord.ApiClient.Serializer);
var avatarHash = avatarHashModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer);
return new WebhookDeleteAuditLogData(entry.TargetId.Value, channelId, type, name, avatarHash);
}
/// <summary>
/// Gets the ID of the webhook that was deleted.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier of the webhook that was deleted.
/// </returns>
public ulong WebhookId { get; }
/// <summary>
/// Gets the ID of the channel that the webhook could send to.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier of the channel that the webhook could send
/// to.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the type of the webhook that was deleted.
/// </summary>
/// <returns>
/// The type of webhook that was deleted.
/// </returns>
public WebhookType Type { get; }
/// <summary>
/// Gets the name of the webhook that was deleted.
/// </summary>
/// <returns>
/// A string containing the name of the webhook that was deleted.
/// </returns>
public string Name { get; }
/// <summary>
/// Gets the hash value of the webhook's avatar.
/// </summary>
/// <returns>
/// A string containing the hash of the webhook's avatar.
/// </returns>
public string Avatar { get; }
} }
internal static WebhookDeleteAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var changes = entry.Changes;
var (data, _) = AuditLogHelper.CreateAuditLogEntityInfo<WebhookInfoAuditLogModel>(changes, discord);
return new WebhookDeleteAuditLogData(entry.TargetId!.Value, data);
}
/// <summary>
/// Gets the ID of the webhook that was deleted.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier of the webhook that was deleted.
/// </returns>
public ulong WebhookId { get; }
/// <summary>
/// Gets the ID of the channel that the webhook could send to.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier of the channel that the webhook could send
/// to.
/// </returns>
public ulong ChannelId { get; }
/// <summary>
/// Gets the type of the webhook that was deleted.
/// </summary>
/// <returns>
/// The type of webhook that was deleted.
/// </returns>
public WebhookType Type { get; }
/// <summary>
/// Gets the name of the webhook that was deleted.
/// </summary>
/// <returns>
/// A string containing the name of the webhook that was deleted.
/// </returns>
public string Name { get; }
/// <summary>
/// Gets the hash value of the webhook's avatar.
/// </summary>
/// <returns>
/// A string containing the hash of the webhook's avatar.
/// </returns>
public string Avatar { get; }
} }

View File

@@ -1,38 +1,41 @@
namespace Discord.Rest using Model = Discord.API.AuditLogs.WebhookInfoAuditLogModel;
{
/// <summary>
/// Represents information for a webhook.
/// </summary>
public struct WebhookInfo
{
internal WebhookInfo(string name, ulong? channelId, string avatar)
{
Name = name;
ChannelId = channelId;
Avatar = avatar;
}
/// <summary> namespace Discord.Rest;
/// Gets the name of this webhook.
/// </summary> /// <summary>
/// <returns> /// Represents information for a webhook.
/// A string containing the name of this webhook. /// </summary>
/// </returns> public struct WebhookInfo
public string Name { get; } {
/// <summary> internal WebhookInfo(Model model)
/// Gets the ID of the channel that this webhook sends to. {
/// </summary> Name = model.Name;
/// <returns> ChannelId = model.ChannelId;
/// A <see cref="ulong"/> representing the snowflake identifier of the channel that this webhook can send Avatar = model.AvatarHash;
/// to.
/// </returns>
public ulong? ChannelId { get; }
/// <summary>
/// Gets the hash value of this webhook's avatar.
/// </summary>
/// <returns>
/// A string containing the hash of this webhook's avatar.
/// </returns>
public string Avatar { get; }
} }
/// <summary>
/// Gets the name of this webhook.
/// </summary>
/// <returns>
/// A string containing the name of this webhook.
/// </returns>
public string Name { get; }
/// <summary>
/// Gets the ID of the channel that this webhook sends to.
/// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier of the channel that this webhook can send
/// to.
/// </returns>
public ulong? ChannelId { get; }
/// <summary>
/// Gets the hash value of this webhook's avatar.
/// </summary>
/// <returns>
/// A string containing the hash of this webhook's avatar.
/// </returns>
public string Avatar { get; }
} }

View File

@@ -1,67 +1,55 @@
using Discord.API.AuditLogs;
using System.Linq; using System.Linq;
using EntryModel = Discord.API.AuditLogEntry; using EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog; using Model = Discord.API.AuditLog;
namespace Discord.Rest namespace Discord.Rest;
/// <summary>
/// Contains a piece of audit log data related to a webhook update.
/// </summary>
public class WebhookUpdateAuditLogData : IAuditLogData
{ {
/// <summary> private WebhookUpdateAuditLogData(IWebhook webhook, WebhookInfo before, WebhookInfo after)
/// Contains a piece of audit log data related to a webhook update.
/// </summary>
public class WebhookUpdateAuditLogData : IAuditLogData
{ {
private WebhookUpdateAuditLogData(IWebhook webhook, WebhookInfo before, WebhookInfo after) Webhook = webhook;
{ Before = before;
Webhook = webhook; After = after;
Before = before;
After = after;
}
internal static WebhookUpdateAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var changes = entry.Changes;
var nameModel = changes.FirstOrDefault(x => x.ChangedProperty == "name");
var channelIdModel = changes.FirstOrDefault(x => x.ChangedProperty == "channel_id");
var avatarHashModel = changes.FirstOrDefault(x => x.ChangedProperty == "avatar_hash");
var oldName = nameModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer);
var oldChannelId = channelIdModel?.OldValue?.ToObject<ulong>(discord.ApiClient.Serializer);
var oldAvatar = avatarHashModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer);
var before = new WebhookInfo(oldName, oldChannelId, oldAvatar);
var newName = nameModel?.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
var newChannelId = channelIdModel?.NewValue?.ToObject<ulong>(discord.ApiClient.Serializer);
var newAvatar = avatarHashModel?.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
var after = new WebhookInfo(newName, newChannelId, newAvatar);
var webhookInfo = log.Webhooks?.FirstOrDefault(x => x.Id == entry.TargetId);
var webhook = webhookInfo != null ? RestWebhook.Create(discord, (IGuild)null, webhookInfo) : null;
return new WebhookUpdateAuditLogData(webhook, before, after);
}
/// <summary>
/// Gets the webhook that was updated.
/// </summary>
/// <returns>
/// A webhook object representing the webhook that was updated.
/// </returns>
public IWebhook Webhook { get; }
/// <summary>
/// Gets the webhook information before the changes.
/// </summary>
/// <returns>
/// A webhook information object representing the webhook before the changes were made.
/// </returns>
public WebhookInfo Before { get; }
/// <summary>
/// Gets the webhook information after the changes.
/// </summary>
/// <returns>
/// A webhook information object representing the webhook after the changes were made.
/// </returns>
public WebhookInfo After { get; }
} }
internal static WebhookUpdateAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var changes = entry.Changes;
var (before, after) = AuditLogHelper.CreateAuditLogEntityInfo<WebhookInfoAuditLogModel>(changes, discord);
var webhookInfo = log.Webhooks?.FirstOrDefault(x => x.Id == entry.TargetId);
var webhook = webhookInfo != null ? RestWebhook.Create(discord, (IGuild)null, webhookInfo) : null;
return new WebhookUpdateAuditLogData(webhook, new(before), new(after));
}
/// <summary>
/// Gets the webhook that was updated.
/// </summary>
/// <returns>
/// A webhook object representing the webhook that was updated.
/// </returns>
public IWebhook Webhook { get; }
/// <summary>
/// Gets the webhook information before the changes.
/// </summary>
/// <returns>
/// A webhook information object representing the webhook before the changes were made.
/// </returns>
public WebhookInfo Before { get; }
/// <summary>
/// Gets the webhook information after the changes.
/// </summary>
/// <returns>
/// A webhook information object representing the webhook after the changes were made.
/// </returns>
public WebhookInfo After { get; }
} }

View File

@@ -0,0 +1,14 @@
using System;
namespace Discord.Rest;
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
internal class JsonFieldAttribute : Attribute
{
public string FieldName { get; }
public JsonFieldAttribute(string fieldName)
{
FieldName = fieldName;
}
}

View File

@@ -14,7 +14,7 @@ namespace Discord.Rest
: base(discord, model.Id) : base(discord, model.Id)
{ {
Action = model.Action; Action = model.Action;
Data = AuditLogHelper.CreateData(discord, fullLog, model); Data = AuditLogHelper.CreateData(discord, model, fullLog);
User = user; User = user;
Reason = model.Reason; Reason = model.Reason;
} }

View File

@@ -75,7 +75,7 @@ namespace Discord.Rest
DefaultSortOrder = model.DefaultSortOrder.GetValueOrDefault(); DefaultSortOrder = model.DefaultSortOrder.GetValueOrDefault();
Tags = model.ForumTags.GetValueOrDefault(Array.Empty<API.ForumTags>()).Select( Tags = model.ForumTags.GetValueOrDefault(Array.Empty<API.ForumTag>()).Select(
x => new ForumTag(x.Id, x.Name, x.EmojiId.GetValueOrDefault(null), x.EmojiName.GetValueOrDefault(), x.Moderated) x => new ForumTag(x.Id, x.Name, x.EmojiId.GetValueOrDefault(null), x.EmojiName.GetValueOrDefault(), x.Moderated)
).ToImmutableArray(); ).ToImmutableArray();

View File

@@ -4,7 +4,5 @@ namespace Discord.API.Gateway
{ {
internal class ApplicationCommandCreatedUpdatedEvent : ApplicationCommand internal class ApplicationCommandCreatedUpdatedEvent : ApplicationCommand
{ {
[JsonProperty("guild_id")]
public Optional<ulong> GuildId { get; set; }
} }
} }

View File

@@ -0,0 +1,9 @@
using Newtonsoft.Json;
namespace Discord.API.Gateway;
internal class AuditLogCreatedEvent : AuditLogEntry
{
[JsonProperty("guild_id")]
public ulong GuildId { get; set; }
}

View File

@@ -893,6 +893,21 @@ namespace Discord.WebSocket
#endregion #endregion
#region Audit Logs
/// <summary>
/// Fired when a guild audit log entry is created.
/// </summary>
public event Func<SocketAuditLogEntry, SocketGuild, Task> AuditLogCreated
{
add { _auditLogCreated.Add(value); }
remove { _auditLogCreated.Remove(value); }
}
internal readonly AsyncEvent<Func<SocketAuditLogEntry, SocketGuild, Task>> _auditLogCreated = new();
#endregion
#region AutoModeration #region AutoModeration
/// <summary> /// <summary>

Some files were not shown because too many files have changed in this diff Show More