@@ -29,7 +29,8 @@ | |||||
<PackageReference Update="Microsoft.Extensions.Hosting" Version="5.0.0" /> | <PackageReference Update="Microsoft.Extensions.Hosting" Version="5.0.0" /> | ||||
<PackageReference Update="Microsoft.Extensions.Options" Version="5.0.0" /> | <PackageReference Update="Microsoft.Extensions.Options" Version="5.0.0" /> | ||||
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.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" Version="2.4.1" /> | ||||
<PackageReference Update="xunit.runner.visualstudio" Version="2.4.3" /> | <PackageReference Update="xunit.runner.visualstudio" Version="2.4.3" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
@@ -1,19 +1,21 @@ | |||||
| | ||||
Microsoft Visual Studio Solution File, Format Version 12.00 | 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 | MinimumVisualStudioVersion = 15.0.26124.0 | ||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{CD5CFA4B-143E-4495-8BFD-AF419226CBE5}" | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{CD5CFA4B-143E-4495-8BFD-AF419226CBE5}" | ||||
EndProject | 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 | EndProject | ||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{6D7B7A29-83FE-44F2-85E1-7D44B061EA27}" | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{6D7B7A29-83FE-44F2-85E1-7D44B061EA27}" | ||||
EndProject | 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 | EndProject | ||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{A47FC28E-1835-46C3-AFD5-7C048A43C157}" | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{A47FC28E-1835-46C3-AFD5-7C048A43C157}" | ||||
EndProject | 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 | EndProject | ||||
Global | Global | ||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
@@ -24,9 +26,6 @@ Global | |||||
Release|x64 = Release|x64 | Release|x64 = Release|x64 | ||||
Release|x86 = Release|x86 | Release|x86 = Release|x86 | ||||
EndGlobalSection | EndGlobalSection | ||||
GlobalSection(SolutionProperties) = preSolution | |||||
HideSolutionNode = FALSE | |||||
EndGlobalSection | |||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||||
{DAF502E3-CFE6-4243-8049-9A6157F42111}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | {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 | {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|x64.Build.0 = Release|Any CPU | ||||
{7EC53EB6-6C15-4FD7-9B83-95F96025C14D}.Release|x86.ActiveCfg = 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 | {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 | EndGlobalSection | ||||
GlobalSection(NestedProjects) = preSolution | GlobalSection(NestedProjects) = preSolution | ||||
{DAF502E3-CFE6-4243-8049-9A6157F42111} = {CD5CFA4B-143E-4495-8BFD-AF419226CBE5} | {DAF502E3-CFE6-4243-8049-9A6157F42111} = {CD5CFA4B-143E-4495-8BFD-AF419226CBE5} | ||||
{54A6E396-5186-4D79-893B-6EFD1CF658CB} = {6D7B7A29-83FE-44F2-85E1-7D44B061EA27} | {54A6E396-5186-4D79-893B-6EFD1CF658CB} = {6D7B7A29-83FE-44F2-85E1-7D44B061EA27} | ||||
{7EC53EB6-6C15-4FD7-9B83-95F96025C14D} = {A47FC28E-1835-46C3-AFD5-7C048A43C157} | {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 | EndGlobalSection | ||||
EndGlobal | EndGlobal |
@@ -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; } | |||||
} | |||||
} |
@@ -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, | |||||
} | |||||
} |
@@ -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 | |||||
} | |||||
} |
@@ -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; } | |||||
} | |||||
} |
@@ -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; } | |||||
} | |||||
} |
@@ -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, | |||||
} | |||||
} |
@@ -8,5 +8,9 @@ | |||||
Shared models between the Discord REST API and Gateway. | Shared models between the Discord REST API and Gateway. | ||||
</Description> | </Description> | ||||
</PropertyGroup> | </PropertyGroup> | ||||
<ItemGroup> | |||||
<PackageReference Include="System.Text.Json" /> | |||||
</ItemGroup> | |||||
</Project> | </Project> |
@@ -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; | |||||
} | |||||
} |
@@ -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(); | |||||
} | |||||
} |