diff --git a/src/Discord.Net.Rest/API/Common/AuditLog.cs b/src/Discord.Net.Rest/API/Common/AuditLog.cs index f2147cb0e..964399d92 100644 --- a/src/Discord.Net.Rest/API/Common/AuditLog.cs +++ b/src/Discord.Net.Rest/API/Common/AuditLog.cs @@ -5,8 +5,8 @@ namespace Discord.API internal class AuditLog { //TODO: figure out how this works - //[JsonProperty("webhooks")] - //public object Webhooks { get; set; } + [JsonProperty("webhooks")] + public AuditLogWebhook[] Webhooks { get; set; } [JsonProperty("users")] public User[] Users { get; set; } diff --git a/src/Discord.Net.Rest/API/Common/AuditLogWebhook.cs b/src/Discord.Net.Rest/API/Common/AuditLogWebhook.cs new file mode 100644 index 000000000..12d8bfba7 --- /dev/null +++ b/src/Discord.Net.Rest/API/Common/AuditLogWebhook.cs @@ -0,0 +1,16 @@ +using Newtonsoft.Json; + +namespace Discord.API +{ + internal class AuditLogWebhook : User + { + [JsonProperty("channel_id")] + public ulong ChannelId { get; set; } + + [JsonProperty("guild_id")] + public ulong GuildId { get; set; } + + [JsonProperty("token")] + public string Token { get; set; } + } +} diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/AuditLogHelper.cs b/src/Discord.Net.Rest/Entities/AuditLogs/AuditLogHelper.cs index 71c806a0d..541f008b0 100644 --- a/src/Discord.Net.Rest/Entities/AuditLogs/AuditLogHelper.cs +++ b/src/Discord.Net.Rest/Entities/AuditLogs/AuditLogHelper.cs @@ -1,7 +1,4 @@ -using System; -using System.Linq; - -using Model = Discord.API.AuditLog; +using Model = Discord.API.AuditLog; using EntryModel = Discord.API.AuditLogEntry; namespace Discord.Rest @@ -35,7 +32,7 @@ namespace Discord.Rest case ActionType.Ban: return BanAuditLogData.Create(discord, log, entry); case ActionType.Unban: - break; + return UnbanAuditLogData.Create(discord, log, entry); case ActionType.MemberUpdated: return MemberUpdateAuditLogData.Create(discord, log, entry); case ActionType.MemberRoleUpdated: @@ -53,14 +50,14 @@ namespace Discord.Rest case ActionType.InviteUpdated: break; case ActionType.InviteDeleted: - break; + return InviteDeleteAuditLogData.Create(discord, log, entry); case ActionType.WebhookCreated: //50 - break; + return WebhookCreateAuditLogData.Create(discord, log, entry); case ActionType.WebhookUpdated: - break; + return WebhookUpdateAuditLogData.Create(discord, log, entry); case ActionType.WebhookDeleted: - break; + return WebhookDeleteAuditLogData.Create(discord, log, entry); case ActionType.EmojiCreated: //60 return EmoteCreateAuditLogData.Create(discord, log, entry); @@ -71,7 +68,8 @@ namespace Discord.Rest case ActionType.MessageDeleted: //72 return MessageDeleteAuditLogData.Create(discord, log, entry); - default: + + default: //Unknown return null; } return null; diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/GuildUpdateAuditLogData.cs b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/GuildUpdateAuditLogData.cs index cd7603f78..5d034d9d9 100644 --- a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/GuildUpdateAuditLogData.cs +++ b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/GuildUpdateAuditLogData.cs @@ -1,23 +1,38 @@ -using Model = Discord.API.AuditLog; +using System.Linq; + +using Model = Discord.API.AuditLog; using EntryModel = Discord.API.AuditLogEntry; namespace Discord.Rest { public class GuildUpdateAuditLogData : IAuditLogData { - private GuildUpdateAuditLogData() - { } + private GuildUpdateAuditLogData(GuildInfo before, GuildInfo after) + { + Before = before; + After = after; + } internal static GuildUpdateAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry) { var changes = entry.Changes; - int? oldAfkTimeout, newAfkTimeout; - DefaultMessageNotifications? oldDefaultMessageNotifications, newDefaultMessageNotifications; - ulong? oldAfkChannelId, newAfkChannelId; - string oldName, newName; - string oldRegionId, newRegionId; - string oldIconHash, newIconHash; + int? oldAfkTimeout = null, + newAfkTimeout = null; + DefaultMessageNotifications? oldDefaultMessageNotifications = null, + newDefaultMessageNotifications = null; + ulong? oldAfkChannelId = null, + newAfkChannelId = null; + string oldName = null, + newName = null; + string oldRegionId = null, + newRegionId = null; + string oldIconHash = null, + newIconHash = null; + VerificationLevel? oldVerificationLevel = null, + newVerificationLevel = null; + ulong? oldOwnerId = null, + newOwnerId = null; foreach (var change in changes) { @@ -47,12 +62,67 @@ namespace Discord.Rest oldIconHash = change.OldValue?.ToObject(); newIconHash = change.NewValue?.ToObject(); break; - //TODO: owner, verification level + case "verification_level": + oldVerificationLevel = change.OldValue?.ToObject(); + newVerificationLevel = change.NewValue?.ToObject(); + break; + case "owner": + oldOwnerId = change.OldValue?.ToObject(); + newOwnerId = change.NewValue?.ToObject(); + break; + //TODO: 2fa auth, explicit content filter } } - //TODO: implement this - return null; + IUser oldOwner = null; + if (oldOwnerId != null) + { + var oldOwnerInfo = log.Users.FirstOrDefault(x => x.Id == oldOwnerId.Value); + oldOwner = RestUser.Create(discord, oldOwnerInfo); + } + + IUser newOwner = null; + if (newOwnerId != null) + { + var newOwnerInfo = log.Users.FirstOrDefault(x => x.Id == newOwnerId.Value); + newOwner = RestUser.Create(discord, newOwnerInfo); + } + + var before = new GuildInfo(oldAfkTimeout, oldDefaultMessageNotifications, + oldAfkChannelId, oldName, oldRegionId, oldIconHash, oldVerificationLevel, oldOwner); + var after = new GuildInfo(newAfkTimeout, newDefaultMessageNotifications, + newAfkChannelId, newName, newRegionId, newIconHash, newVerificationLevel, newOwner); + + return new GuildUpdateAuditLogData(before, after); + } + + public GuildInfo Before { get; } + public GuildInfo After { get; } + + public struct GuildInfo + { + internal GuildInfo(int? afkTimeout, DefaultMessageNotifications? defaultNotifs, + ulong? afkChannel, string name, string region, string icon, + VerificationLevel? verification, IUser owner) + { + AfkTimeout = afkTimeout; + DefaultMessageNotifications = defaultNotifs; + AfkChannelId = afkChannel; + Name = name; + RegionId = region; + IconHash = icon; + VerificationLevel = verification; + Owner = owner; + } + + public int? AfkTimeout { get; } + public DefaultMessageNotifications? DefaultMessageNotifications { get; } + public ulong? AfkChannelId { get; } + public string Name { get; } + public string RegionId { get; } + public string IconHash { get; } + public VerificationLevel? VerificationLevel { get; } + public IUser Owner { get; } } } } diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/InviteDeleteAuditLogData.cs b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/InviteDeleteAuditLogData.cs new file mode 100644 index 000000000..97c7a9b2c --- /dev/null +++ b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/InviteDeleteAuditLogData.cs @@ -0,0 +1,55 @@ +using System.Linq; + +using Model = Discord.API.AuditLog; +using EntryModel = Discord.API.AuditLogEntry; + +namespace Discord.Rest +{ + public class InviteDeleteAuditLogData : IAuditLogData + { + 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(); + var code = codeModel.OldValue.ToObject(); + var temporary = temporaryModel.OldValue.ToObject(); + var inviterId = inviterIdModel.OldValue.ToObject(); + var channelId = channelIdModel.OldValue.ToObject(); + var uses = usesModel.OldValue.ToObject(); + var maxUses = maxUsesModel.OldValue.ToObject(); + + var inviterInfo = log.Users.FirstOrDefault(x => x.Id == inviterId); + var inviter = RestUser.Create(discord, inviterInfo); + + return new InviteDeleteAuditLogData(maxAge, code, temporary, inviter, channelId, uses, maxUses); + } + + public int MaxAge { get; } + public string Code { get; } + public bool Temporary { get; } + public IUser Creator { get; } + public ulong ChannelId { get; } //TODO: IChannel-ify + public int Uses { get; } + public int MaxUses { get; } + } +} diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteCreateAuditLogData.cs b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteCreateAuditLogData.cs index 6e5658f66..d58488136 100644 --- a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteCreateAuditLogData.cs +++ b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteCreateAuditLogData.cs @@ -27,11 +27,7 @@ namespace Discord.Rest var id = entry.Options.OverwriteTargetId.Value; var type = entry.Options.OverwriteType; - PermissionTarget target; - if (type == "member") - target = PermissionTarget.User; - else - target = PermissionTarget.Role; + PermissionTarget target = type == "member" ? PermissionTarget.User : PermissionTarget.Role; return new OverwriteCreateAuditLogData(new Overwrite(id, target, permissions)); } diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteDeleteAuditLogData.cs b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteDeleteAuditLogData.cs index b1f2195b5..9c635d577 100644 --- a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteDeleteAuditLogData.cs +++ b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteDeleteAuditLogData.cs @@ -32,12 +32,7 @@ namespace Discord.Rest var id = idModel.OldValue.ToObject(); var allow = allowModel.OldValue.ToObject(); - PermissionTarget target; - - if (type == "member") - target = PermissionTarget.User; - else - target = PermissionTarget.Role; + PermissionTarget target = type == "member" ? PermissionTarget.User : PermissionTarget.Role; return new OverwriteDeleteAuditLogData(new Overwrite(id, target, new OverwritePermissions(allow, deny))); } diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteUpdateAuditLogData.cs b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteUpdateAuditLogData.cs index 923cce28f..8ed9d1415 100644 --- a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteUpdateAuditLogData.cs +++ b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteUpdateAuditLogData.cs @@ -30,11 +30,7 @@ namespace Discord.Rest var beforePermissions = new OverwritePermissions(beforeAllow ?? 0, beforeDeny ?? 0); var afterPermissions = new OverwritePermissions(afterAllow ?? 0, afterDeny ?? 0); - PermissionTarget target; - if (entry.Options.OverwriteType == "member") - target = PermissionTarget.User; - else - target = PermissionTarget.Role; + PermissionTarget target = entry.Options.OverwriteType == "member" ? PermissionTarget.User : PermissionTarget.Role; return new OverwriteUpdateAuditLogData(beforePermissions, afterPermissions, entry.Options.OverwriteTargetId.Value, target); } diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/UnbanAuditLogData.cs b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/UnbanAuditLogData.cs new file mode 100644 index 000000000..c94f18271 --- /dev/null +++ b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/UnbanAuditLogData.cs @@ -0,0 +1,23 @@ +using System.Linq; + +using Model = Discord.API.AuditLog; +using EntryModel = Discord.API.AuditLogEntry; + +namespace Discord.Rest +{ + public class UnbanAuditLogData : IAuditLogData + { + 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(RestUser.Create(discord, userInfo)); + } + + public IUser Target { get; } + } +} diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/WebhookCreateAuditLogData.cs b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/WebhookCreateAuditLogData.cs new file mode 100644 index 000000000..158ee4d4e --- /dev/null +++ b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/WebhookCreateAuditLogData.cs @@ -0,0 +1,44 @@ +using System.Linq; + +using Model = Discord.API.AuditLog; +using EntryModel = Discord.API.AuditLogEntry; + +namespace Discord.Rest +{ + public class WebhookCreateAuditLogData : IAuditLogData + { + private WebhookCreateAuditLogData(IWebhookUser user, string token, string name, ulong channelId) + { + Webhook = user; + Token = token; + Name = name; + 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(); + var type = typeModel.NewValue.ToObject(); //TODO: what on *earth* is this for + var name = nameModel.NewValue.ToObject(); + + var webhookInfo = log.Webhooks?.FirstOrDefault(x => x.Id == entry.TargetId); + var userInfo = RestWebhookUser.Create(discord, null, webhookInfo, entry.TargetId.Value); + + return new WebhookCreateAuditLogData(userInfo, webhookInfo.Token, name, channelId); + } + + //Corresponds to the *current* data + public IWebhookUser Webhook { get; } + public string Token { get; } + + //Corresponds to the *audit log* data + public string Name { get; } + public ulong ChannelId { get; } + } +} diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/WebhookDeleteAuditLogData.cs b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/WebhookDeleteAuditLogData.cs new file mode 100644 index 000000000..0121f48ad --- /dev/null +++ b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/WebhookDeleteAuditLogData.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Model = Discord.API.AuditLog; +using EntryModel = Discord.API.AuditLogEntry; + +namespace Discord.Rest +{ + public class WebhookDeleteAuditLogData : IAuditLogData + { + private WebhookDeleteAuditLogData(ulong id, ulong channel, string name, string avatar) + { + WebhookId = id; + ChannelId = channel; + Name = name; + 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(); + var type = typeModel.OldValue.ToObject(); + var name = nameModel.OldValue.ToObject(); + var avatarHash = avatarHashModel?.OldValue?.ToObject(); + + return new WebhookDeleteAuditLogData(entry.TargetId.Value, channelId, name, avatarHash); + } + + public ulong WebhookId { get; } + public ulong ChannelId { get; } + public string Name { get; } + public string Avatar { get; } + } +} diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/WebhookUpdateAuditLogData.cs b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/WebhookUpdateAuditLogData.cs new file mode 100644 index 000000000..3241832ba --- /dev/null +++ b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/WebhookUpdateAuditLogData.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Model = Discord.API.AuditLog; +using EntryModel = Discord.API.AuditLogEntry; + +namespace Discord.Rest +{ + public class WebhookUpdateAuditLogData : IAuditLogData + { + private WebhookUpdateAuditLogData(IWebhookUser user, string token, WebhookInfo before, WebhookInfo after) + { + Webhook = user; + Token = token; + 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(); + var oldChannelId = channelIdModel?.OldValue?.ToObject(); + var oldAvatar = avatarHashModel?.OldValue?.ToObject(); + var before = new WebhookInfo(oldName, oldChannelId, oldAvatar); + + var newName = nameModel?.NewValue?.ToObject(); + var newChannelId = channelIdModel?.NewValue?.ToObject(); + var newAvatar = avatarHashModel?.NewValue?.ToObject(); + var after = new WebhookInfo(newName, newChannelId, newAvatar); + + var webhookInfo = log.Webhooks?.FirstOrDefault(x => x.Id == entry.TargetId); + var userInfo = RestWebhookUser.Create(discord, null, webhookInfo, entry.TargetId.Value); + + return new WebhookUpdateAuditLogData(userInfo, webhookInfo.Token, before, after); + } + + //Again, the *current* data + public IWebhookUser Webhook { get; } + public string Token { get; } + + //And the *audit log* data + public WebhookInfo Before { get; } + public WebhookInfo After { get; } + + public struct WebhookInfo + { + internal WebhookInfo(string name, ulong? channelId, string avatar) + { + Name = name; + ChannelId = channelId; + Avatar = avatar; + } + + public string Name { get; } + public ulong? ChannelId { get; } + public string Avatar { get; } + } + } +} diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/RestAuditLogEntry.cs b/src/Discord.Net.Rest/Entities/AuditLogs/RestAuditLogEntry.cs index e30972913..9e30a5014 100644 --- a/src/Discord.Net.Rest/Entities/AuditLogs/RestAuditLogEntry.cs +++ b/src/Discord.Net.Rest/Entities/AuditLogs/RestAuditLogEntry.cs @@ -11,12 +11,8 @@ namespace Discord.Rest : base(discord, model.Id) { Action = model.Action; - - if (model.Changes != null) - Data = AuditLogHelper.CreateData(discord, fullLog, model); - + Data = AuditLogHelper.CreateData(discord, fullLog, model); User = user; - Reason = model.Reason; }