Browse Source

Audit log models

pull/1868/merge
Paulo 4 years ago
parent
commit
a02d699518
11 changed files with 548 additions and 9 deletions
  1. +2
    -1
      Directory.Build.targets
  2. +26
    -8
      Discord.Net.sln
  3. +58
    -0
      src/Models/AuditLog/AuditEntryInfo.cs
  4. +17
    -0
      src/Models/AuditLog/AuditEntryInfoType.cs
  5. +34
    -0
      src/Models/AuditLog/AuditLog.cs
  6. +28
    -0
      src/Models/AuditLog/AuditLogChange.cs
  7. +52
    -0
      src/Models/AuditLog/AuditLogEntry.cs
  8. +153
    -0
      src/Models/AuditLog/AuditLogEvent.cs
  9. +4
    -0
      src/Models/Discord.Net.Models.csproj
  10. +98
    -0
      src/Models/Optional.cs
  11. +76
    -0
      src/Models/Snowflake.cs

+ 2
- 1
Directory.Build.targets View File

@@ -29,7 +29,8 @@
<PackageReference Update="Microsoft.Extensions.Hosting" Version="5.0.0" />
<PackageReference Update="Microsoft.Extensions.Options" Version="5.0.0" />
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
<PackageReference Update="System.IO.Pipelines" Version="5.0.0" />
<PackageReference Update="System.IO.Pipelines" Version="5.0.1" />
<PackageReference Update="System.Text.Json" Version="5.0.2" />
<PackageReference Update="xunit" Version="2.4.1" />
<PackageReference Update="xunit.runner.visualstudio" Version="2.4.3" />
</ItemGroup>


+ 26
- 8
Discord.Net.sln View File

@@ -1,19 +1,21 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26124.0
# Visual Studio Version 16
VisualStudioVersion = 16.0.31229.75
MinimumVisualStudioVersion = 15.0.26124.0
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{CD5CFA4B-143E-4495-8BFD-AF419226CBE5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Discord.Net.Gateway", "src\Gateway\Discord.Net.Gateway.csproj", "{DAF502E3-CFE6-4243-8049-9A6157F42111}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Gateway", "src\Gateway\Discord.Net.Gateway.csproj", "{DAF502E3-CFE6-4243-8049-9A6157F42111}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{6D7B7A29-83FE-44F2-85E1-7D44B061EA27}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PingPong", "samples\PingPong\PingPong.csproj", "{54A6E396-5186-4D79-893B-6EFD1CF658CB}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PingPong", "samples\PingPong\PingPong.csproj", "{54A6E396-5186-4D79-893B-6EFD1CF658CB}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{A47FC28E-1835-46C3-AFD5-7C048A43C157}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Discord.Net.Gateway.UnitTests", "test\Gateway\Discord.Net.Gateway.UnitTests.csproj", "{7EC53EB6-6C15-4FD7-9B83-95F96025C14D}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Gateway.UnitTests", "test\Gateway\Discord.Net.Gateway.UnitTests.csproj", "{7EC53EB6-6C15-4FD7-9B83-95F96025C14D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Models", "src\Models\Discord.Net.Models.csproj", "{564A2E82-CE92-42F6-9D4E-8CC09C5CDF17}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -24,9 +26,6 @@ Global
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DAF502E3-CFE6-4243-8049-9A6157F42111}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DAF502E3-CFE6-4243-8049-9A6157F42111}.Debug|Any CPU.Build.0 = Debug|Any CPU
@@ -64,10 +63,29 @@ Global
{7EC53EB6-6C15-4FD7-9B83-95F96025C14D}.Release|x64.Build.0 = Release|Any CPU
{7EC53EB6-6C15-4FD7-9B83-95F96025C14D}.Release|x86.ActiveCfg = Release|Any CPU
{7EC53EB6-6C15-4FD7-9B83-95F96025C14D}.Release|x86.Build.0 = Release|Any CPU
{564A2E82-CE92-42F6-9D4E-8CC09C5CDF17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{564A2E82-CE92-42F6-9D4E-8CC09C5CDF17}.Debug|Any CPU.Build.0 = Debug|Any CPU
{564A2E82-CE92-42F6-9D4E-8CC09C5CDF17}.Debug|x64.ActiveCfg = Debug|Any CPU
{564A2E82-CE92-42F6-9D4E-8CC09C5CDF17}.Debug|x64.Build.0 = Debug|Any CPU
{564A2E82-CE92-42F6-9D4E-8CC09C5CDF17}.Debug|x86.ActiveCfg = Debug|Any CPU
{564A2E82-CE92-42F6-9D4E-8CC09C5CDF17}.Debug|x86.Build.0 = Debug|Any CPU
{564A2E82-CE92-42F6-9D4E-8CC09C5CDF17}.Release|Any CPU.ActiveCfg = Release|Any CPU
{564A2E82-CE92-42F6-9D4E-8CC09C5CDF17}.Release|Any CPU.Build.0 = Release|Any CPU
{564A2E82-CE92-42F6-9D4E-8CC09C5CDF17}.Release|x64.ActiveCfg = Release|Any CPU
{564A2E82-CE92-42F6-9D4E-8CC09C5CDF17}.Release|x64.Build.0 = Release|Any CPU
{564A2E82-CE92-42F6-9D4E-8CC09C5CDF17}.Release|x86.ActiveCfg = Release|Any CPU
{564A2E82-CE92-42F6-9D4E-8CC09C5CDF17}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{DAF502E3-CFE6-4243-8049-9A6157F42111} = {CD5CFA4B-143E-4495-8BFD-AF419226CBE5}
{54A6E396-5186-4D79-893B-6EFD1CF658CB} = {6D7B7A29-83FE-44F2-85E1-7D44B061EA27}
{7EC53EB6-6C15-4FD7-9B83-95F96025C14D} = {A47FC28E-1835-46C3-AFD5-7C048A43C157}
{564A2E82-CE92-42F6-9D4E-8CC09C5CDF17} = {CD5CFA4B-143E-4495-8BFD-AF419226CBE5}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {36B0BFC9-AF79-4D25-89D4-2EE3C961612B}
EndGlobalSection
EndGlobal

+ 58
- 0
src/Models/AuditLog/AuditEntryInfo.cs View File

@@ -0,0 +1,58 @@
using System.Text.Json.Serialization;

namespace Discord.Net.Models
{
/// <summary>
/// Represents an audit entry info object.
/// </summary>
public record AuditEntryInfo
{
/// <summary>
/// Number of days after which inactive members were kicked.
/// </summary>
[JsonPropertyName("delete_member_days")]
public Optional<int> DeleteMemberDays { get; init; } // actually sent as Optional<string>
/// <summary>
/// Number of members removed by the prune.
/// </summary>
[JsonPropertyName("members_removed")]
public Optional<int> MembersRemoved { get; init; } // actually sent as Optional<string>

/// <summary>
/// Channel in which the entities were targeted.
/// </summary>
[JsonPropertyName("channel_id")]
public Optional<Snowflake> ChannelId { get; init; }

/// <summary>
/// Id of the message that was targeted.
/// </summary>
[JsonPropertyName("message_id")]
public Optional<Snowflake> MessageId { get; init; }

/// <summary>
/// Number of entities that were targeted.
/// </summary>
[JsonPropertyName("count")]
public Optional<int> Count { get; init; } // actually sent as Optional<string>

/// <summary>
/// Id of the overwritten entity.
/// </summary>
[JsonPropertyName("id")]
public Optional<Snowflake> Id { get; init; }

/// <summary>
/// Type of overwritten entity - "0" for "role" or "1" for "member".
/// </summary>
[JsonPropertyName("type")]
public Optional<AuditEntryInfo> Type { get; init; } // actually sent as Optional<string>

/// <summary>
/// Name of the role if type is "0" (not present if type is "1").
/// </summary>
[JsonPropertyName("role_name")]
public Optional<string> RoleName { get; init; }
}
}

+ 17
- 0
src/Models/AuditLog/AuditEntryInfoType.cs View File

@@ -0,0 +1,17 @@
namespace Discord.Net.Models
{
/// <summary>
/// Represents type of the overwritten entity for an audit entry info.
/// </summary>
public enum AuditEntryInfoType
{
/// <summary>
/// The type of the overwritten entity is a role.
/// </summary>
Role = 0,
/// <summary>
/// The type of the overwritten entity is a member.
/// </summary>
Member = 1,
}
}

+ 34
- 0
src/Models/AuditLog/AuditLog.cs View File

@@ -0,0 +1,34 @@
using System.Text.Json.Serialization;

namespace Discord.Net.Models
{
/// <summary>
/// Represents a discord audit log object.
/// </summary>
public record AuditLog
{
/// <summary>
/// Gets an array of <see cref="Webhook"/>s.
/// </summary>
/*[JsonPropertyName("webhooks")]
public Optional<Webhook[]> Webhooks { get; init; }*/ //TODO Add Webhook

/// <summary>
/// Gets an array of <see cref="User"/>s.
/// </summary>
/*[JsonPropertyName("users")]
public Optional<User[]> Users { get; init; }*/ //TODO Add User

/// <summary>
/// Gets an array of <see cref="AuditLogEntry"/>s.
/// </summary>
[JsonPropertyName("audit_log_entries")]
public Optional<AuditLogEntry[]> AuditLogEntries { get; init; }

/// <summary>
/// Gets an array of <see cref="Integration"/>s.
/// </summary>
/*[JsonPropertyName("integrations")]
public Optional<Integration[]> Integrations { get; init; }*/ //TODO Add Integration
}
}

+ 28
- 0
src/Models/AuditLog/AuditLogChange.cs View File

@@ -0,0 +1,28 @@
using System.Text.Json.Serialization;

namespace Discord.Net.Models
{
/// <summary>
/// Represents an audit log change object.
/// </summary>
public record AuditLogChange
{
/// <summary>
/// New value of the key.
/// </summary>
[JsonPropertyName("new_value")]
public Optional<object> NewValue { get; init; }

/// <summary>
/// Old value of the key.
/// </summary>
[JsonPropertyName("old_value")]
public Optional<object> OldValue { get; init; }

/// <summary>
/// Name of the audit log change key.
/// </summary>
[JsonPropertyName("key")]
public string? Key { get; init; }
}
}

+ 52
- 0
src/Models/AuditLog/AuditLogEntry.cs View File

@@ -0,0 +1,52 @@
using System.Text.Json.Serialization;

namespace Discord.Net.Models
{
/// <summary>
/// Represents an audit log entry object.
/// </summary>
public record AuditLogEntry
{
/// <summary>
/// Id of the affected entity (webhook, user, role, etc.).
/// </summary>
[JsonPropertyName("target_id")]
public Snowflake? TargetId { get; init; }

/// <summary>
/// Changes made to the <see cref="TargetId"/>.
/// </summary>
[JsonPropertyName("changes")]
public Optional<AuditLogChange[]> Changes { get; init; }

/// <summary>
/// The user who made the changes.
/// </summary>
[JsonPropertyName("user_id")]
public Snowflake? UserId { get; init; }

/// <summary>
/// Id of the entry.
/// </summary>
[JsonPropertyName("id")]
public Snowflake Id { get; init; }

/// <summary>
/// Type of action that occurred.
/// </summary>
[JsonPropertyName("action_type")]
public AuditLogEvent ActionType { get; init; }

/// <summary>
/// Additional info for certain action types.
/// </summary>
[JsonPropertyName("options")]
public Optional<AuditEntryInfo> Options { get; init; }

/// <summary>
/// The reason for the change (0-512 characters).
/// </summary>
[JsonPropertyName("reason")]
public Optional<string> Reason { get; init; }
}
}

+ 153
- 0
src/Models/AuditLog/AuditLogEvent.cs View File

@@ -0,0 +1,153 @@
namespace Discord.Net.Models
{
/// <summary>
/// Specifies the type of audit log event.
/// </summary>
public enum AuditLogEvent : int
{
/// <summary>
/// Default value of this type.
/// </summary>
None = 0,
/// <summary>
/// The guild was updated.
/// </summary>
GuildUpdate = 1,
/// <summary>
/// A channel was created.
/// </summary>
ChannelCreate = 10,
/// <summary>
/// A channel was updated.
/// </summary>
ChannelUpdate = 11,
/// <summary>
/// A channel was deleted.
/// </summary>
ChannelDelete = 12,
/// <summary>
/// A channel overwrite was created.
/// </summary>
ChannelOverwriteCreate = 13,
/// <summary>
/// A channel overwrite was updated.
/// </summary>
ChannelOverwriteUpdate = 14,
/// <summary>
/// A channel overwrite was deleted.
/// </summary>
ChannelOverwriteDelete = 15,
/// <summary>
/// A guild member was kicked.
/// </summary>
MemberKick = 20,
/// <summary>
/// A guild member was pruned.
/// </summary>
MemberPrune = 21,
/// <summary>
/// A guild member was banned.
/// </summary>
MemberBanAdd = 22,
/// <summary>
/// A guild member was unbanned.
/// </summary>
MemberBanRemove = 23,
/// <summary>
/// A guild member was updated.
/// </summary>
MemberUpdate = 24,
/// <summary>
/// A guild role was updated.
/// </summary>
MemberRoleUpdate = 25,
/// <summary>
/// A guild member was moved.
/// </summary>
MemberMove = 26,
/// <summary>
/// A guild member was disconnected.
/// </summary>
MemberDisconnect = 27,
/// <summary>
/// A bot was added.
/// </summary>
BotAdd = 28,
/// <summary>
/// A role was created.
/// </summary>
RoleCreate = 30,
/// <summary>
/// A role was updated.
/// </summary>
RoleUpdate = 31,
/// <summary>
/// A role was deleted.
/// </summary>
RoleDelete = 32,
/// <summary>
/// An invite was created.
/// </summary>
InviteCreate = 40,
/// <summary>
/// An invite was updated.
/// </summary>
InviteUpdate = 41,
/// <summary>
/// An invite was deleted.
/// </summary>
InviteDelete = 42,
/// <summary>
/// A webhook was created.
/// </summary>
WebhookCreate = 50,
/// <summary>
/// A webhook was updated.
/// </summary>
WebhookUpdate = 51,
/// <summary>
/// A webhook was deleted.
/// </summary>
WebhookDelete = 52,
/// <summary>
/// An emoji was created.
/// </summary>
EmojiCreate = 60,
/// <summary>
/// An emoji was updated.
/// </summary>
EmojiUpdate = 61,
/// <summary>
/// An emoji was deleted.
/// </summary>
EmojiDelete = 62,
/// <summary>
/// A message was deleted.
/// </summary>
MessageDelete = 72,
/// <summary>
/// Message were deleted in bulk.
/// </summary>
MessageBulkDelete = 73,
/// <summary>
/// A message was pinned.
/// </summary>
MessagePin = 74,
/// <summary>
/// A message was unpinned.
/// </summary>
MessageUnpin = 75,
/// <summary>
/// An integration was created.
/// </summary>
IntegrationCreate = 80,
/// <summary>
/// An integration was updated.
/// </summary>
IntegrationUpdate = 81,
/// <summary>
/// An integration was deleted.
/// </summary>
IntegrationDelete = 82,
}
}

+ 4
- 0
src/Models/Discord.Net.Models.csproj View File

@@ -8,5 +8,9 @@
Shared models between the Discord REST API and Gateway.
</Description>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Text.Json" />
</ItemGroup>

</Project>

+ 98
- 0
src/Models/Optional.cs View File

@@ -0,0 +1,98 @@
using System;

namespace Discord.Net
{
/// <summary>
/// Container to keep a type that might not be present.
/// </summary>
/// <typeparam name="T">Inner type</typeparam>
public struct Optional<T>
{
private readonly T _value;

/// <summary>
/// Gets the inner value of this <see cref="Optional{T}"/> if present.
/// </summary>
/// <returns>The value inside this <see cref="Optional{T}"/>.</returns>
/// <exception cref="InvalidOperationException">This <see cref="Optional{T}"/> has no inner value.</exception>
public T Value => !IsSpecified ? throw new InvalidOperationException("This property has no value set.") : _value;

/// <summary>
/// Gets if this <see cref="Optional{T}"/> has an inner value.
/// </summary>
/// <returns>A boolean that determines if this <see cref="Optional{T}"/> has a <see cref="Value"/>.</returns>
public bool IsSpecified { get; }

private Optional(T value)
{
_value = value;
IsSpecified = true;
}

/// <summary>
/// Creates a new unspecified <see cref="Optional{T}"/>.
/// </summary>
/// <returns>An unspecified <see cref="Optional{T}"/>.</returns>
public static Optional<T> Create()
=> default;

/// <summary>
/// Creates a new <see cref="Optional{T}"/> with the specified <paramref name="value"/>.
/// </summary>
/// <param name="value">Value that will be specified for this <see cref="Optional{T}"/>.</param>
/// <returns>A specified <see cref="Optional{T}"/> with the provided value inside.</returns>
public static Optional<T> Create(T value)
=> new(value);

/// <summary>
/// Gets the <see cref="Value"/> or their <see langword="default"/> value.
/// </summary>
/// <returns>The value inside this <see cref="Optional{T}"/> or their <see langword="default"/> value.</returns>
public T GetValueOrDefault()
=> _value;

/// <summary>
/// Gets the <see cref="Value"/> or the default value provided.
/// </summary>
/// <returns>The value inside this <see cref="Optional{T}"/> or default value provided.</returns>
public T GetValueOrDefault(T defaultValue)
=> IsSpecified ? _value : defaultValue;

/// <inheritdoc/>
public override bool Equals(object? other)
{
if (!IsSpecified)
return other == null;
if (other == null || _value == null)
return false;
return _value.Equals(other);
}

/// <inheritdoc/>
public override int GetHashCode()
=> IsSpecified ? _value?.GetHashCode() ?? default : default;

/// <summary>
/// Returns the inner value ToString value or this type fully qualified name.
/// </summary>
/// <returns>The inner value string value or this type fully qualified name.</returns>
public override string? ToString()
=> IsSpecified ? _value?.ToString() : default;

/// <summary>
/// Creates a new <see cref="Optional{T}"/> with the specified <paramref name="value"/>.
/// </summary>
/// <param name="value">Value to convert</param>
/// <returns>A new <see cref="Optional{T}"/> with the specified <paramref name="value"/></returns>
public static implicit operator Optional<T>(T value)
=> new(value);

/// <summary>
/// Gets the inner value.
/// </summary>
/// <param name="value">Value to convert</param>
/// <returns>The inner value</returns>
public static explicit operator T(Optional<T> value)
=> value.Value;
}
}

+ 76
- 0
src/Models/Snowflake.cs View File

@@ -0,0 +1,76 @@
using System;

namespace Discord.Net
{
/// <summary>
/// Represents a discord snowflake.
/// </summary>
public struct Snowflake
{
private const ulong DiscordEpoch = 1420070400000UL;

/// <summary>
/// Gets the raw value of this snowflake.
/// </summary>
/// <returns>A <see cref="ulong"/> with the rae value.</returns>
public ulong RawValue { get; }

/// <summary>
/// Creates a <see cref="Snowflake"/> based on the <paramref name="value"/> provided.
/// </summary>
/// <param name="value">Raw value of the snowflake.</param>
public Snowflake(ulong value)
{
RawValue = value;
}

/// <summary>
/// Creates a <see cref="Snowflake"/> based on the <paramref name="dateTimeOffset"/> provided.
/// </summary>
/// <param name="dateTimeOffset">DateTimeOffset of this snowflake.</param>
public Snowflake(DateTimeOffset dateTimeOffset)
{
RawValue = ((ulong)dateTimeOffset.ToUniversalTime().ToUnixTimeMilliseconds() - DiscordEpoch) << 22;
}

/// <summary>
/// Creates a <see cref="Snowflake"/> based on the <paramref name="dateTime"/> provided.
/// </summary>
/// <param name="dateTime">DateTime of this snowflake.</param>
public Snowflake(DateTime dateTime)
: this(new DateTimeOffset(dateTime)) { }

/// <summary>
/// Converts this <see cref="Snowflake"/> to a <see cref="DateTimeOffset"/>.
/// </summary>
/// <returns>A <see cref="DateTimeOffset"/> of this snowflake.</returns>
public DateTimeOffset ToDateTimeOffset() => DateTimeOffset.FromUnixTimeMilliseconds((long)((RawValue >> 22) + DiscordEpoch));

/// <summary>
/// Converts this <see cref="Snowflake"/> to a <see cref="DateTime"/>.
/// </summary>
/// <returns>A <see cref="DateTime"/> of this snowflake.</returns>
public DateTimeOffset ToDateTime() => ToDateTimeOffset().UtcDateTime;

/// <summary>
/// Converts this <see cref="Snowflake"/> to a <see cref="ulong"/>.
/// </summary>
/// <param name="snowflake">Value that will be converted</param>
/// <returns>A <see cref="ulong"/> with the raw value.</returns>
public static implicit operator ulong(Snowflake snowflake) => snowflake.RawValue;

/// <summary>
/// Converts this <see cref="ulong"/> to a <see cref="Snowflake"/>.
/// </summary>
/// <param name="value">Value that will be converted</param>
/// <returns>A <see cref="Snowflake"/> with <paramref name="value"/> as the raw value.</returns>
public static implicit operator Snowflake(ulong value) => new Snowflake(value);

/// <summary>
/// Returns the raw value as <see cref="string"/>.
/// </summary>
/// <returns>A <see cref="string"/> that is the raw value.</returns>
public override string ToString()
=> RawValue.ToString();
}
}

Loading…
Cancel
Save