[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>
/// A thread was deleted.
/// </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>
/// Three days (4320 minutes).
/// <remarks>
/// This option is explicitly available to nitro users.
/// </remarks>
/// </summary>
ThreeDays = 4320,
/// <summary>
/// One week (10080 minutes).
/// <remarks>
/// This option is explicitly available to nitro users.
/// </remarks>
/// </summary>
OneWeek = 10080
}

View File

@@ -7,6 +7,8 @@ using System.Threading.Tasks;
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>
/// Represents a generic guild/server.
/// </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")]
public ulong ApplicationId { get; set; }
[JsonProperty("guild_id")]
public Optional<ulong> GuildId { get; set; }
[JsonProperty("name")]
public string Name { get; set; }

View File

@@ -18,5 +18,14 @@ namespace Discord.API
[JsonProperty("audit_log_entries")]
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;
namespace Discord.API
namespace Discord.API;
internal class AuditLogOptions
{
internal class AuditLogOptions
{
[JsonProperty("count")]
public int? Count { get; set; }
[JsonProperty("channel_id")]
public ulong? ChannelId { get; set; }
[JsonProperty("message_id")]
public ulong? MessageId { get; set; }
[JsonProperty("count")]
public int? Count { get; set; }
[JsonProperty("channel_id")]
public ulong? ChannelId { get; set; }
[JsonProperty("message_id")]
public ulong? MessageId { get; set; }
//Prune
[JsonProperty("delete_member_days")]
public int? PruneDeleteMemberDays { get; set; }
[JsonProperty("members_removed")]
public int? PruneMembersRemoved { get; set; }
//Prune
[JsonProperty("delete_member_days")]
public int? PruneDeleteMemberDays { get; set; }
[JsonProperty("members_removed")]
public int? PruneMembersRemoved { get; set; }
//Overwrite Update
[JsonProperty("role_name")]
public string OverwriteRoleName { get; set; }
[JsonProperty("type")]
public PermissionTarget OverwriteType { get; set; }
[JsonProperty("id")]
public ulong? OverwriteTargetId { get; set; }
}
//Overwrite Update
[JsonProperty("role_name")]
public string OverwriteRoleName { get; set; }
[JsonProperty("type")]
public PermissionTarget OverwriteType { get; set; }
[JsonProperty("id")]
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
[JsonProperty("available_tags")]
public Optional<ForumTags[]> ForumTags { get; set; }
public Optional<ForumTag[]> ForumTags { get; set; }
[JsonProperty("applied_tags")]
public Optional<ulong[]> AppliedTags { get; set; }

View File

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

View File

@@ -1,71 +1,122 @@
using System;
using System.Collections.Generic;
using System.Linq;
using AuditLogChange = Discord.API.AuditLogChange;
using EntryModel = Discord.API.AuditLogEntry;
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, 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)
private static readonly Dictionary<ActionType, Func<BaseDiscordClient, EntryModel, Model, IAuditLogData>> CreateMapping
= new ()
{
if (CreateMapping.TryGetValue(entry.Action, out var func))
return func(discord, log, entry);
[ActionType.GuildUpdated] = GuildUpdateAuditLogData.Create, // log
[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 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>
/// Contains a piece of audit log data related to a ban.
/// </summary>
public class BanAuditLogData : IAuditLogData
private BanAuditLogData(IUser user)
{
private BanAuditLogData(IUser 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; }
Target = user;
}
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 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>
/// 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)
{
private BotAddAuditLogData(IUser 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; }
Target = bot;
}
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.Immutable;
using System.Linq;
using EntryModel = Discord.API.AuditLogEntry;
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>
/// Contains a piece of audit log data related to a channel creation.
/// </summary>
public class ChannelCreateAuditLogData : IAuditLogData
private ChannelCreateAuditLogData(ChannelInfoAuditLogModel model, EntryModel entry)
{
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;
ChannelName = name;
ChannelType = type;
SlowModeInterval = rateLimit;
IsNsfw = nsfw;
Bitrate = bitrate;
Overwrites = overwrites;
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;
internal static ChannelCreateAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var changes = entry.Changes;
var overwritesModel = changes.FirstOrDefault(x => x.ChangedProperty == "permission_overwrites");
var typeModel = changes.FirstOrDefault(x => x.ChangedProperty == "type");
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; }
VideoQualityMode = model.VideoQualityMode;
RtcRegion = model.Region;
Flags = model.Flags;
UserLimit = model.UserLimit;
Overwrites = model.Overwrites?.Select(x => new Overwrite(x.TargetId, x.TargetType, new OverwritePermissions(x.Allow, x.Deny)))
.ToImmutableArray();
}
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.Immutable;
using System.Linq;
using EntryModel = Discord.API.AuditLogEntry;
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>
/// Contains a piece of audit log data related to a channel deletion.
/// </summary>
public class ChannelDeleteAuditLogData : IAuditLogData
private ChannelDeleteAuditLogData(ChannelInfoAuditLogModel model, EntryModel entry)
{
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;
ChannelName = name;
ChannelType = type;
SlowModeInterval = rateLimit;
IsNsfw = nsfw;
Bitrate = bitrate;
Overwrites = overwrites;
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;
internal static ChannelDeleteAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var changes = entry.Changes;
VideoQualityMode = model.VideoQualityMode;
RtcRegion = model.Region;
Flags = model.Flags;
UserLimit = model.UserLimit;
var overwritesModel = changes.FirstOrDefault(x => x.ChangedProperty == "permission_overwrites");
var typeModel = changes.FirstOrDefault(x => x.ChangedProperty == "type");
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.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; }
Overwrites = model.Overwrites?.Select(x
=> new Overwrite(x.TargetId,
x.TargetType,
new OverwritePermissions(x.Allow, x.Deny))).ToImmutableArray();
}
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
{
/// <summary>
@@ -5,14 +10,41 @@ namespace Discord.Rest
/// </summary>
public struct ChannelInfo
{
internal ChannelInfo(string name, string topic, int? rateLimit, bool? nsfw, int? bitrate, ChannelType? type)
internal ChannelInfo(Model model)
{
Name = name;
Topic = topic;
SlowModeInterval = rateLimit;
IsNsfw = nsfw;
Bitrate = bitrate;
ChannelType = type;
Name = model.Name;
Topic = model.Topic;
IsNsfw = model.IsNsfw;
Bitrate = model.Bitrate;
DefaultArchiveDuration = model.DefaultArchiveDuration;
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>
@@ -61,5 +93,53 @@ namespace Discord.Rest
/// The channel type of this channel; <c>null</c> if not applicable.
/// </returns>
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 EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog;
@@ -16,34 +17,13 @@ namespace Discord.Rest
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 nameModel = changes.FirstOrDefault(x => x.ChangedProperty == "name");
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");
var (before, after) = AuditLogHelper.CreateAuditLogEntityInfo<ChannelInfoAuditLogModel>(changes, discord);
string oldName = nameModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer),
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);
return new ChannelUpdateAuditLogData(entry.TargetId!.Value, new ChannelInfo(before), new ChannelInfo(after));
}
/// <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 EntryModel = Discord.API.AuditLogEntry;
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>
/// Contains a piece of audit log data related to an emoji creation.
/// </summary>
public class EmoteCreateAuditLogData : IAuditLogData
private EmoteCreateAuditLogData(ulong id, string name)
{
private EmoteCreateAuditLogData(ulong id, string 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; }
EmoteId = id;
Name = name;
}
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 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>
/// Contains a piece of audit log data related to an emoji deletion.
/// </summary>
public class EmoteDeleteAuditLogData : IAuditLogData
private EmoteDeleteAuditLogData(ulong id, string name)
{
private EmoteDeleteAuditLogData(ulong id, string 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; }
EmoteId = id;
Name = name;
}
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 EntryModel = Discord.API.AuditLogEntry;
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>
/// 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)
{
private EmoteUpdateAuditLogData(ulong id, string oldName, string newName)
{
EmoteId = id;
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; }
EmoteId = id;
OldName = oldName;
NewName = newName;
}
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
{
/// <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;
}
using Model = Discord.API.AuditLogs.GuildInfoAuditLogModel;
/// <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; }
namespace Discord.Rest;
/// <summary>
/// Represents information for a guild.
/// </summary>
public struct GuildInfo
{
internal GuildInfo(Model model, IUser owner)
{
Owner = owner;
Name = model.Name;
AfkTimeout = model.AfkTimeout.GetValueOrDefault();
IsEmbeddable = model.IsEmbeddable;
DefaultMessageNotifications = model.DefaultMessageNotifications;
MfaLevel = model.MfaLevel;
Description = model.Description;
PreferredLocale = model.PreferredLocale;
IconHash = model.IconHash;
OwnerId = model.OwnerId;
AfkChannelId = model.AfkChannelId;
ApplicationId = model.ApplicationId;
BannerId = model.Banner;
DiscoverySplashId = model.DiscoverySplash;
EmbedChannelId = model.EmbeddedChannelId;
ExplicitContentFilter = model.ExplicitContentFilterLevel;
IsBoostProgressBarEnabled = model.ProgressBarEnabled;
NsfwLevel = model.NsfwLevel;
PublicUpdatesChannelId = model.PublicUpdatesChannelId;
RegionId = model.RegionId;
RulesChannelId = model.RulesChannelId;
SplashId = model.Splash;
SystemChannelFlags = model.SystemChannelFlags;
SystemChannelId = model.SystemChannelId;
VanityURLCode = model.VanityUrl;
VerificationLevel = model.VerificationLevel;
}
/// <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 EntryModel = Discord.API.AuditLogEntry;
using Model = Discord.API.AuditLog;
@@ -15,50 +16,14 @@ namespace Discord.Rest
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 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 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),
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;
if (oldOwnerId != null)
@@ -74,14 +39,9 @@ namespace Discord.Rest
newOwner = RestUser.Create(discord, newOwnerInfo);
}
var before = new GuildInfo(oldAfkTimeout, oldDefaultMessageNotifications,
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);
var (before, after) = AuditLogHelper.CreateAuditLogEntityInfo<GuildInfoAuditLogModel>(changes, discord);
return new GuildUpdateAuditLogData(before, after);
return new GuildUpdateAuditLogData(new(before, oldOwner), new(after, newOwner));
}
/// <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 EntryModel = Discord.API.AuditLogEntry;
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>
/// Contains a piece of audit log data related to an invite creation.
/// </summary>
public class InviteCreateAuditLogData : IAuditLogData
private InviteCreateAuditLogData(InviteInfoAuditLogModel model, IUser inviter)
{
private InviteCreateAuditLogData(int maxAge, string code, bool temporary, IUser inviter, ulong channelId, int uses, int maxUses)
{
MaxAge = maxAge;
Code = code;
Temporary = temporary;
Creator = inviter;
ChannelId = channelId;
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; }
MaxAge = model.MaxAge!.Value;
Code = model.Code;
Temporary = model.Temporary!.Value;
Creator = inviter;
ChannelId = model.ChannelId!.Value;
Uses = model.Uses!.Value;
MaxUses = model.MaxUses!.Value;
}
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 EntryModel = Discord.API.AuditLogEntry;
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>
/// Contains a piece of audit log data related to an invite removal.
/// </summary>
public class InviteDeleteAuditLogData : IAuditLogData
private InviteDeleteAuditLogData(InviteInfoAuditLogModel model, IUser inviter)
{
private InviteDeleteAuditLogData(int maxAge, string code, bool temporary, IUser inviter, ulong channelId, int uses, int maxUses)
{
MaxAge = maxAge;
Code = code;
Temporary = temporary;
Creator = inviter;
ChannelId = channelId;
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; }
MaxAge = model.MaxAge!.Value;
Code = model.Code;
Temporary = model.Temporary!.Value;
Creator = inviter;
ChannelId = model.ChannelId!.Value;
Uses = model.Uses!.Value;
MaxUses = model.MaxUses!.Value;
}
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
{
/// <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;
}
using Model = Discord.API.AuditLogs.InviteInfoAuditLogModel;
/// <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; }
namespace Discord.Rest;
/// <summary>
/// Represents information for an invite.
/// </summary>
public struct InviteInfo
{
internal InviteInfo(Model model)
{
MaxAge = model.MaxAge;
Code = model.Code;
Temporary = model.Temporary;
ChannelId = model.ChannelId;
MaxUses = model.MaxUses;
CreatorId = model.InviterId;
}
/// <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 EntryModel = Discord.API.AuditLogEntry;
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>
/// Contains a piece of audit log data relating to an invite update.
/// </summary>
public class InviteUpdateAuditLogData : IAuditLogData
private InviteUpdateAuditLogData(InviteInfo before, InviteInfo after)
{
private InviteUpdateAuditLogData(InviteInfo before, InviteInfo 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; }
Before = before;
After = after;
}
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 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>
/// Contains a piece of audit log data related to a kick.
/// </summary>
public class KickAuditLogData : IAuditLogData
private KickAuditLogData(RestUser user)
{
private KickAuditLogData(RestUser 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; }
Target = user;
}
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 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>
/// Contains a piece of audit log data related to disconnecting members from voice channels.
/// </summary>
public class MemberDisconnectAuditLogData : IAuditLogData
private MemberDisconnectAuditLogData(int count)
{
private MemberDisconnectAuditLogData(int 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; }
MemberCount = count;
}
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
{
/// <summary>
/// Represents information for a member.
/// </summary>
public struct MemberInfo
{
internal MemberInfo(string nick, bool? deaf, bool? mute)
{
Nickname = nick;
Deaf = deaf;
Mute = mute;
}
using Discord.API.AuditLogs;
using System;
/// <summary>
/// Gets the nickname of the updated member.
/// </summary>
/// <returns>
/// A string representing the nickname of the updated member; <c>null</c> 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>
/// <c>true</c> if the updated member is deafened (i.e. not permitted to listen to or speak to others) by the guild;
/// otherwise <c>false</c>.
/// <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; }
namespace Discord.Rest;
/// <summary>
/// Represents information for a member.
/// </summary>
public struct MemberInfo
{
internal MemberInfo(MemberInfoAuditLogModel model)
{
Nickname = model.Nickname;
Deaf = model.IsDeafened;
Mute = model.IsMuted;
TimedOutUntil = model.TimeOutUntil;
}
/// <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 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>
/// 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)
{
private MemberMoveAuditLogData(ulong channelId, int 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; }
ChannelId = channelId;
MemberCount = count;
}
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 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>
/// 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)
{
private MemberRoleAuditLogData(IReadOnlyCollection<MemberRoleEditInfo> roles, IUser 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; }
Roles = roles;
Target = target;
}
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
{
/// <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;
}
namespace Discord.Rest;
/// <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; }
/// <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>
/// 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 EntryModel = Discord.API.AuditLogEntry;
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>
/// 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)
{
private MemberUpdateAuditLogData(IUser target, MemberInfo before, MemberInfo after)
{
Target = target;
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; }
Target = target;
Before = before;
After = after;
}
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 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>
/// Contains a piece of audit log data related to message deletion(s).
/// </summary>
public class MessageBulkDeleteAuditLogData : IAuditLogData
private MessageBulkDeleteAuditLogData(ulong channelId, int count)
{
private MessageBulkDeleteAuditLogData(ulong channelId, int 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; }
ChannelId = channelId;
MessageCount = count;
}
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 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>
/// 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)
{
private MessageDeleteAuditLogData(ulong channelId, int count, IUser user)
{
ChannelId = channelId;
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; }
ChannelId = channelId;
MessageCount = count;
Target = user;
}
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 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>
/// 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)
{
private MessagePinAuditLogData(ulong messageId, ulong channelId, IUser user)
{
MessageId = messageId;
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; }
MessageId = messageId;
ChannelId = channelId;
Target = user;
}
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 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>
/// 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)
{
private MessageUnpinAuditLogData(ulong messageId, ulong channelId, IUser user)
{
MessageId = messageId;
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; }
MessageId = messageId;
ChannelId = channelId;
Target = user;
}
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 EntryModel = Discord.API.AuditLogEntry;
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>
/// Contains a piece of audit log data for a permissions overwrite creation.
/// </summary>
public class OverwriteCreateAuditLogData : IAuditLogData
private OverwriteCreateAuditLogData(ulong channelId, Overwrite overwrite)
{
private OverwriteCreateAuditLogData(ulong 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; }
ChannelId = channelId;
Overwrite = overwrite;
}
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 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>
/// 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)
{
private OverwriteDeleteAuditLogData(ulong 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; }
ChannelId = channelId;
Overwrite = deletedOverwrite;
}
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 EntryModel = Discord.API.AuditLogEntry;
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>
/// 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)
{
private OverwriteUpdateAuditLogData(ulong channelId, OverwritePermissions before, OverwritePermissions after, ulong targetId, PermissionTarget targetType)
{
ChannelId = channelId;
OldPermissions = before;
NewPermissions = after;
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; }
ChannelId = channelId;
OldPermissions = before;
NewPermissions = after;
OverwriteTargetId = targetId;
OverwriteType = targetType;
}
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 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>
/// Contains a piece of audit log data related to a guild prune.
/// </summary>
public class PruneAuditLogData : IAuditLogData
private PruneAuditLogData(int pruneDays, int membersRemoved)
{
private PruneAuditLogData(int pruneDays, int 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; }
PruneDays = pruneDays;
MembersRemoved = membersRemoved;
}
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 EntryModel = Discord.API.AuditLogEntry;
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>
/// Contains a piece of audit log data related to a role creation.
/// </summary>
public class RoleCreateAuditLogData : IAuditLogData
private RoleCreateAuditLogData(ulong id, RoleEditInfo props)
{
private RoleCreateAuditLogData(ulong id, RoleEditInfo 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; }
RoleId = id;
Properties = props;
}
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 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>
/// Contains a piece of audit log data relating to a role deletion.
/// </summary>
public class RoleDeleteAuditLogData : IAuditLogData
private RoleDeleteAuditLogData(ulong id, RoleEditInfo props)
{
private RoleDeleteAuditLogData(ulong id, RoleEditInfo 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; }
RoleId = id;
Properties = props;
}
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
{
/// <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;
}
using Model = Discord.API.AuditLogs.RoleInfoAuditLogModel;
/// <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; }
namespace Discord.Rest;
/// <summary>
/// Represents information for a role edit.
/// </summary>
public struct RoleEditInfo
{
internal RoleEditInfo(Model model)
{
if (model.Color is not null)
Color = new Color(model.Color.Value);
else
Color = null;
Mentionable = model.IsMentionable;
Hoist = model.Hoist;
Name = model.Name;
if (model.Permissions is not null)
Permissions = new GuildPermissions(model.Permissions.Value);
else
Permissions = null;
IconId = model.IconHash;
}
/// <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 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>
/// 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)
{
private RoleUpdateAuditLogData(ulong id, RoleEditInfo oldProps, RoleEditInfo newProps)
{
RoleId = id;
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; }
RoleId = id;
Before = oldProps;
After = newProps;
}
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.Linq;
using EntryModel = Discord.API.AuditLogEntry;
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>
/// Contains a piece of audit log data related to a scheduled event creation.
/// </summary>
public class ScheduledEventCreateAuditLogData : IAuditLogData
private ScheduledEventCreateAuditLogData(ulong id, ScheduledEventInfoAuditLogModel model, IGuildScheduledEvent scheduledEvent)
{
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;
GuildId = guildId;
ChannelId = channelId;
CreatorId = creatorId;
Name = name;
Description = description;
ScheduledStartTime = scheduledStartTime;
ScheduledEndTime = scheduledEndTime;
PrivacyLevel = privacyLevel;
Status = status;
EntityType = entityType;
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; }
Id = id;
ChannelId = model.ChannelId;
Name = model.Name;
Description = model.Description;
ScheduledStartTime = model.StartTime;
ScheduledEndTime = model.EndTime;
PrivacyLevel = model.PrivacyLevel!.Value;
Status = model.EventStatus!.Value;
EntityType = model.EventType!.Value;
EntityId = model.EntityId;
Location = model.Location;
Image = model.Image;
ScheduledEvent = scheduledEvent;
}
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.Linq;
using EntryModel = Discord.API.AuditLogEntry;
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>
/// Contains a piece of audit log data related to a scheduled event deletion.
/// </summary>
public class ScheduledEventDeleteAuditLogData : IAuditLogData
private ScheduledEventDeleteAuditLogData(ulong id, ScheduledEventInfoAuditLogModel model)
{
private ScheduledEventDeleteAuditLogData(ulong id)
{
Id = id;
}
internal static ScheduledEventDeleteAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var id = entry.TargetId.Value;
return new ScheduledEventDeleteAuditLogData(id);
}
// Doc Note: Corresponds to the *current* data
/// <summary>
/// Gets the snowflake id of the event.
/// </summary>
public ulong Id { get; }
Id = id;
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;
}
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;
namespace Discord.Rest
namespace Discord.Rest;
/// <summary>
/// Represents information for a scheduled event.
/// </summary>
public class ScheduledEventInfo
{
/// <summary>
/// Represents information for a scheduled event.
/// Gets the snowflake id of the channel the event is associated with.
/// </summary>
public class ScheduledEventInfo
{
/// <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; }
public ulong? ChannelId { 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)
{
GuildId = guildId;
ChannelId = channelId;
Name = name;
Description = description;
ScheduledStartTime = scheduledStartTime;
ScheduledEndTime = scheduledEndTime;
PrivacyLevel = privacyLevel;
Status = status;
EntityType = entityType;
EntityId = entityId;
Location = location;
UserCount = userCount;
Image = image;
}
/// <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; }
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 EntryModel = Discord.API.AuditLogEntry;
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>
/// 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, IGuildScheduledEvent scheduledEvent)
{
private ScheduledEventUpdateAuditLogData(ulong id, ScheduledEventInfo before, ScheduledEventInfo after)
{
Id = id;
Before = before;
After = after;
}
Id = id;
Before = before;
After = after;
ScheduledEvent = scheduledEvent;
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 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>
/// Contains a piece of audit log data related to a stage going live.
/// Gets the topic of the stage channel.
/// </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>
/// Gets the topic of the stage channel.
/// </summary>
public string Topic { get; }
Topic = topic;
PrivacyLevel = privacyLevel;
User = user;
StageChannelId = channelId;
}
/// <summary>
/// Gets the privacy level of the stage channel.
/// </summary>
public StagePrivacyLevel PrivacyLevel { get; }
internal static StageInstanceCreateAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
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;
/// <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)
{
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);
}
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 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>
/// Contains a piece of audit log data related to a stage instance deleted.
/// Gets the topic of the stage channel.
/// </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>
/// Gets the topic of the stage channel.
/// </summary>
public string Topic { get; }
Topic = topic;
PrivacyLevel = privacyLevel;
User = user;
StageChannelId = channelId;
}
/// <summary>
/// Gets the privacy level of the stage channel.
/// </summary>
public StagePrivacyLevel PrivacyLevel { get; }
internal static StageInstanceDeleteAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
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;
/// <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)
{
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);
}
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 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>
/// Contains a piece of audit log data related to a stage instance update.
/// Gets the Id of the stage channel.
/// </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>
/// Gets the Id of the stage channel.
/// </summary>
public ulong StageChannelId { get; }
StageChannelId = channelId;
Before = before;
After = after;
}
/// <summary>
/// Gets the stage information before the changes.
/// </summary>
public StageInfo Before { get; }
internal static StageInstanceUpdatedAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log)
{
var channelId = entry.Options.ChannelId.Value;
/// <summary>
/// Gets the stage information after the changes.
/// </summary>
public StageInfo After { get; }
var topic = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "topic");
var privacy = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "privacy");
internal StageInstanceUpdatedAuditLogData(ulong channelId, StageInfo before, StageInfo after)
{
StageChannelId = channelId;
Before = before;
After = after;
}
var user = RestUser.Create(discord, log.Users.FirstOrDefault(x => x.Id == entry.UserId));
internal static StageInstanceUpdatedAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var channelId = entry.Options.ChannelId.Value;
var oldTopic = topic?.OldValue.ToObject<string>();
var newTopic = topic?.NewValue.ToObject<string>();
var oldPrivacy = privacy?.OldValue.ToObject<StagePrivacyLevel>();
var newPrivacy = privacy?.NewValue.ToObject<StagePrivacyLevel>();
var topic = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "topic");
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));
}
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 EntryModel = Discord.API.AuditLogEntry;
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>
/// Contains a piece of audit log data related to a thread creation.
/// </summary>
public class ThreadCreateAuditLogData : IAuditLogData
private ThreadCreateAuditLogData(IThreadChannel thread, ulong id, ThreadInfoAuditLogModel model)
{
private ThreadCreateAuditLogData(IThreadChannel thread, ulong id, string name, ThreadType type, bool archived,
ThreadArchiveDuration autoArchiveDuration, bool locked, int? rateLimit)
{
Thread = thread;
ThreadId = id;
ThreadName = name;
ThreadType = type;
IsArchived = archived;
AutoArchiveDuration = autoArchiveDuration;
IsLocked = locked;
SlowModeInterval = rateLimit;
}
Thread = thread;
ThreadId = id;
internal static ThreadCreateAuditLogData 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 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; }
ThreadName = model.Name;
IsArchived = model.IsArchived!.Value;
AutoArchiveDuration = model.ArchiveDuration!.Value;
IsLocked = model.IsLocked!.Value;
SlowModeInterval = model.SlowModeInterval;
AppliedTags = model.AppliedTags;
Flags = model.ChannelFlags;
ThreadType = model.Type;
}
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 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>
/// Contains a piece of audit log data related to a thread deletion.
/// </summary>
public class ThreadDeleteAuditLogData : IAuditLogData
private ThreadDeleteAuditLogData(ulong id, ThreadInfoAuditLogModel model)
{
private ThreadDeleteAuditLogData(ulong id, string name, ThreadType type, bool archived,
ThreadArchiveDuration autoArchiveDuration, bool locked, int? rateLimit)
{
ThreadId = id;
ThreadName = name;
ThreadType = type;
IsArchived = archived;
AutoArchiveDuration = autoArchiveDuration;
IsLocked = locked;
SlowModeInterval = rateLimit;
}
ThreadId = id;
internal static ThreadDeleteAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{
var changes = entry.Changes;
var id = entry.TargetId.Value;
var thread = log.Threads.FirstOrDefault(x => x.Id == id);
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 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; }
ThreadName = model.Name;
IsArchived = model.IsArchived!.Value;
AutoArchiveDuration = model.ArchiveDuration!.Value;
IsLocked = model.IsLocked!.Value;
SlowModeInterval = model.SlowModeInterval;
AppliedTags = model.AppliedTags;
Flags = model.ChannelFlags;
ThreadType = model.Type;
}
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>
/// Represents information for a thread.
/// Gets the name of the thread.
/// </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>
/// Gets the name of the thread.
/// </summary>
public string Name { get; }
/// <summary>
/// Gets the value that indicates whether the thread is archived.
/// </summary>
public bool IsArchived { get; }
/// <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;
}
Name = model.Name;
IsArchived = model.IsArchived;
AutoArchiveDuration = model.ArchiveDuration;
IsLocked = model.IsLocked;
SlowModeInterval = model.SlowModeInterval;
AppliedTags = model.AppliedTags;
Flags = model.ChannelFlags;
Type = model.Type;
}
}

View File

@@ -1,87 +1,67 @@
using Discord.API.AuditLogs;
using System.Linq;
using EntryModel = Discord.API.AuditLogEntry;
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>
/// 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)
{
private ThreadUpdateAuditLogData(IThreadChannel thread, ThreadType type, ThreadInfo before, ThreadInfo after)
{
Thread = thread;
ThreadType = type;
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; }
Thread = thread;
ThreadType = type;
Before = before;
After = after;
}
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 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>
/// Contains a piece of audit log data related to an unban.
/// </summary>
public class UnbanAuditLogData : IAuditLogData
private UnbanAuditLogData(IUser user)
{
private UnbanAuditLogData(IUser 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; }
Target = user;
}
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 EntryModel = Discord.API.AuditLogEntry;
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>
/// Contains a piece of audit log data related to a webhook creation.
/// </summary>
public class WebhookCreateAuditLogData : IAuditLogData
private WebhookCreateAuditLogData(IWebhook webhook, ulong webhookId, WebhookInfoAuditLogModel model)
{
private WebhookCreateAuditLogData(IWebhook webhook, ulong webhookId, WebhookType type, string name, ulong channelId)
{
Webhook = webhook;
WebhookId = webhookId;
Name = name;
Type = type;
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; }
Webhook = webhook;
WebhookId = webhookId;
Name = model.Name;
Type = model.Type!.Value;
ChannelId = model.ChannelId!.Value;
Avatar = model.AvatarHash;
}
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 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>
/// Contains a piece of audit log data related to a webhook deletion.
/// </summary>
public class WebhookDeleteAuditLogData : IAuditLogData
private WebhookDeleteAuditLogData(ulong id, WebhookInfoAuditLogModel model)
{
private WebhookDeleteAuditLogData(ulong id, ulong channel, WebhookType type, string name, string avatar)
{
WebhookId = id;
ChannelId = channel;
Name = name;
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; }
WebhookId = id;
ChannelId = model.ChannelId!.Value;
Name = model.Name;
Type = model.Type!.Value;
Avatar = model.AvatarHash;
}
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
{
/// <summary>
/// Represents information for a webhook.
/// </summary>
public struct WebhookInfo
{
internal WebhookInfo(string name, ulong? channelId, string avatar)
{
Name = name;
ChannelId = channelId;
Avatar = avatar;
}
using Model = Discord.API.AuditLogs.WebhookInfoAuditLogModel;
/// <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; }
namespace Discord.Rest;
/// <summary>
/// Represents information for a webhook.
/// </summary>
public struct WebhookInfo
{
internal WebhookInfo(Model model)
{
Name = model.Name;
ChannelId = model.ChannelId;
Avatar = model.AvatarHash;
}
/// <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 EntryModel = Discord.API.AuditLogEntry;
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>
/// 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)
{
private WebhookUpdateAuditLogData(IWebhook webhook, WebhookInfo before, WebhookInfo after)
{
Webhook = webhook;
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; }
Webhook = webhook;
Before = before;
After = after;
}
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)
{
Action = model.Action;
Data = AuditLogHelper.CreateData(discord, fullLog, model);
Data = AuditLogHelper.CreateData(discord, model, fullLog);
User = user;
Reason = model.Reason;
}

View File

@@ -75,7 +75,7 @@ namespace Discord.Rest
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)
).ToImmutableArray();

View File

@@ -4,7 +4,5 @@ namespace Discord.API.Gateway
{
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
#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
/// <summary>

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