Browse Source

Concrete class prototype

tags/1.0-rc
RogueException 8 years ago
parent
commit
6319933ed0
100 changed files with 670 additions and 409 deletions
  1. +29
    -7
      Discord.Net.sln
  2. +1
    -1
      src/Discord.Net.Core/API/CDN.cs
  3. +0
    -0
      src/Discord.Net.Core/API/Common/Application.cs
  4. +0
    -0
      src/Discord.Net.Core/API/Common/Attachment.cs
  5. +0
    -0
      src/Discord.Net.Core/API/Common/Ban.cs
  6. +0
    -0
      src/Discord.Net.Core/API/Common/Channel.cs
  7. +0
    -0
      src/Discord.Net.Core/API/Common/Connection.cs
  8. +0
    -0
      src/Discord.Net.Core/API/Common/Embed.cs
  9. +0
    -0
      src/Discord.Net.Core/API/Common/EmbedProvider.cs
  10. +0
    -0
      src/Discord.Net.Core/API/Common/EmbedThumbnail.cs
  11. +0
    -0
      src/Discord.Net.Core/API/Common/Emoji.cs
  12. +0
    -0
      src/Discord.Net.Core/API/Common/Game.cs
  13. +0
    -0
      src/Discord.Net.Core/API/Common/Guild.cs
  14. +0
    -0
      src/Discord.Net.Core/API/Common/GuildEmbed.cs
  15. +0
    -0
      src/Discord.Net.Core/API/Common/GuildMember.cs
  16. +0
    -0
      src/Discord.Net.Core/API/Common/Integration.cs
  17. +0
    -0
      src/Discord.Net.Core/API/Common/IntegrationAccount.cs
  18. +0
    -0
      src/Discord.Net.Core/API/Common/Invite.cs
  19. +0
    -0
      src/Discord.Net.Core/API/Common/InviteChannel.cs
  20. +0
    -0
      src/Discord.Net.Core/API/Common/InviteGuild.cs
  21. +0
    -0
      src/Discord.Net.Core/API/Common/InviteMetadata.cs
  22. +0
    -0
      src/Discord.Net.Core/API/Common/Message.cs
  23. +0
    -0
      src/Discord.Net.Core/API/Common/Overwrite.cs
  24. +0
    -0
      src/Discord.Net.Core/API/Common/Presence.cs
  25. +0
    -0
      src/Discord.Net.Core/API/Common/ReadState.cs
  26. +0
    -0
      src/Discord.Net.Core/API/Common/Relationship.cs
  27. +0
    -0
      src/Discord.Net.Core/API/Common/RelationshipType.cs
  28. +0
    -0
      src/Discord.Net.Core/API/Common/Role.cs
  29. +0
    -0
      src/Discord.Net.Core/API/Common/User.cs
  30. +0
    -0
      src/Discord.Net.Core/API/Common/UserGuild.cs
  31. +0
    -0
      src/Discord.Net.Core/API/Common/VoiceRegion.cs
  32. +0
    -0
      src/Discord.Net.Core/API/Common/VoiceState.cs
  33. +183
    -328
      src/Discord.Net.Core/API/DiscordRestApiClient.cs
  34. +1
    -1
      src/Discord.Net.Core/API/Image.cs
  35. +0
    -0
      src/Discord.Net.Core/API/Int53Attribute.cs
  36. +16
    -0
      src/Discord.Net.Core/API/Rest/CreateChannelInviteParams.cs
  37. +6
    -3
      src/Discord.Net.Core/API/Rest/CreateDMChannelParams.cs
  38. +1
    -2
      src/Discord.Net.Core/API/Rest/CreateGuildBanParams.cs
  39. +23
    -0
      src/Discord.Net.Core/API/Rest/CreateGuildChannelParams.cs
  40. +8
    -3
      src/Discord.Net.Core/API/Rest/CreateGuildIntegrationParams.cs
  41. +9
    -6
      src/Discord.Net.Core/API/Rest/CreateGuildParams.cs
  42. +22
    -0
      src/Discord.Net.Core/API/Rest/CreateMessageParams.cs
  43. +17
    -0
      src/Discord.Net.Core/API/Rest/DeleteMessagesParams.cs
  44. +10
    -0
      src/Discord.Net.Core/API/Rest/GetChannelMessagesParams.cs
  45. +0
    -0
      src/Discord.Net.Core/API/Rest/GetGatewayResponse.cs
  46. +9
    -0
      src/Discord.Net.Core/API/Rest/GetGuildMembersParams.cs
  47. +0
    -0
      src/Discord.Net.Core/API/Rest/GetGuildPruneCountResponse.cs
  48. +6
    -1
      src/Discord.Net.Core/API/Rest/GuildPruneParams.cs
  49. +10
    -3
      src/Discord.Net.Core/API/Rest/ModifyChannelPermissionsParams.cs
  50. +6
    -1
      src/Discord.Net.Core/API/Rest/ModifyCurrentUserNickParams.cs
  51. +2
    -6
      src/Discord.Net.Core/API/Rest/ModifyCurrentUserParams.cs
  52. +2
    -5
      src/Discord.Net.Core/API/Rest/ModifyGuildChannelParams.cs
  53. +8
    -3
      src/Discord.Net.Core/API/Rest/ModifyGuildChannelsParams.cs
  54. +14
    -0
      src/Discord.Net.Core/API/Rest/ModifyGuildEmbedParams.cs
  55. +16
    -0
      src/Discord.Net.Core/API/Rest/ModifyGuildIntegrationParams.cs
  56. +20
    -0
      src/Discord.Net.Core/API/Rest/ModifyGuildMemberParams.cs
  57. +30
    -0
      src/Discord.Net.Core/API/Rest/ModifyGuildParams.cs
  58. +20
    -0
      src/Discord.Net.Core/API/Rest/ModifyGuildRoleParams.cs
  59. +6
    -1
      src/Discord.Net.Core/API/Rest/ModifyGuildRolesParams.cs
  60. +1
    -2
      src/Discord.Net.Core/API/Rest/ModifyMessageParams.cs
  61. +9
    -0
      src/Discord.Net.Core/API/Rest/ModifyPresenceParams.cs
  62. +1
    -2
      src/Discord.Net.Core/API/Rest/ModifyTextChannelParams.cs
  63. +2
    -5
      src/Discord.Net.Core/API/Rest/ModifyVoiceChannelParams.cs
  64. +35
    -0
      src/Discord.Net.Core/API/Rest/UploadFileParams.cs
  65. +0
    -0
      src/Discord.Net.Core/API/WebSocketMessage.cs
  66. +4
    -4
      src/Discord.Net.Core/Audio/IAudioClient.cs
  67. +0
    -0
      src/Discord.Net.Core/Audio/Opus/OpusApplication.cs
  68. +0
    -0
      src/Discord.Net.Core/ConnectionState.cs
  69. +19
    -0
      src/Discord.Net.Core/Discord.Net.Core.xproj
  70. +0
    -0
      src/Discord.Net.Core/DiscordConfig.cs
  71. +0
    -0
      src/Discord.Net.Core/Entities/Channels/ChannelType.cs
  72. +6
    -2
      src/Discord.Net.Core/Entities/Channels/IChannel.cs
  73. +0
    -0
      src/Discord.Net.Core/Entities/Channels/IDMChannel.cs
  74. +16
    -0
      src/Discord.Net.Core/Entities/Channels/IGroupChannel.cs
  75. +5
    -3
      src/Discord.Net.Core/Entities/Channels/IGuildChannel.cs
  76. +6
    -4
      src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs
  77. +0
    -0
      src/Discord.Net.Core/Entities/Channels/IPrivateChannel.cs
  78. +0
    -0
      src/Discord.Net.Core/Entities/Channels/ITextChannel.cs
  79. +0
    -0
      src/Discord.Net.Core/Entities/Channels/IVoiceChannel.cs
  80. +0
    -0
      src/Discord.Net.Core/Entities/Guilds/DefaultMessageNotifications.cs
  81. +33
    -0
      src/Discord.Net.Core/Entities/Guilds/Emoji.cs
  82. +13
    -0
      src/Discord.Net.Core/Entities/Guilds/IBan.cs
  83. +13
    -3
      src/Discord.Net.Core/Entities/Guilds/IGuild.cs
  84. +2
    -3
      src/Discord.Net.Core/Entities/Guilds/IGuildIntegration.cs
  85. +0
    -0
      src/Discord.Net.Core/Entities/Guilds/IUserGuild.cs
  86. +0
    -0
      src/Discord.Net.Core/Entities/Guilds/IVoiceRegion.cs
  87. +0
    -0
      src/Discord.Net.Core/Entities/Guilds/IntegrationAccount.cs
  88. +0
    -0
      src/Discord.Net.Core/Entities/Guilds/MfaLevel.cs
  89. +0
    -0
      src/Discord.Net.Core/Entities/Guilds/VerificationLevel.cs
  90. +1
    -1
      src/Discord.Net.Core/Entities/IApplication.cs
  91. +0
    -0
      src/Discord.Net.Core/Entities/IDeletable.cs
  92. +15
    -0
      src/Discord.Net.Core/Entities/IEntity.cs
  93. +0
    -0
      src/Discord.Net.Core/Entities/IMentionable.cs
  94. +6
    -0
      src/Discord.Net.Core/Entities/ISnowflakeEntity.cs
  95. +0
    -0
      src/Discord.Net.Core/Entities/IUpdateable.cs
  96. +0
    -0
      src/Discord.Net.Core/Entities/Invites/IInvite.cs
  97. +0
    -0
      src/Discord.Net.Core/Entities/Invites/IInviteMetadata.cs
  98. +0
    -0
      src/Discord.Net.Core/Entities/Messages/Direction.cs
  99. +4
    -2
      src/Discord.Net.Core/Entities/Messages/EmbedProvider.cs
  100. +4
    -7
      src/Discord.Net.Core/Entities/Messages/EmbedThumbnail.cs

+ 29
- 7
Discord.Net.sln View File

@@ -1,28 +1,50 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25123.0
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net", "src\Discord.Net\Discord.Net.xproj", "{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F7F3E124-93C7-4846-AE87-9CE12BD82859}"
ProjectSection(SolutionItems) = preProject
global.json = global.json
README.md = README.md
EndProjectSection
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net.Commands", "src\Discord.Net.Commands\Discord.Net.Commands.xproj", "{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net", "src\Discord.Net\Discord.Net.xproj", "{496DB20A-A455-4D01-B6BC-90FE6D7C6B81}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net.Core", "src\Discord.Net.Core\Discord.Net.Core.xproj", "{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Impls", "Impls", "{288C363D-A636-4EAE-9AC1-4698B641B26E}"
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Discord.Net.Utils", "src\Discord.Net.Utils\Discord.Net.Utils.shproj", "{2B75119C-9893-4AAA-8D38-6176EEB09060}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net.Rest", "src\Discord.Net.Rest\Discord.Net.Rest.xproj", "{BFC6DC28-0351-4573-926A-D4124244C04F}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\Discord.Net.Utils\Discord.Net.Utils.projitems*{2b75119c-9893-4aaa-8d38-6176eeb09060}*SharedItemsImports = 13
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{496DB20A-A455-4D01-B6BC-90FE6D7C6B81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{496DB20A-A455-4D01-B6BC-90FE6D7C6B81}.Debug|Any CPU.Build.0 = Debug|Any CPU
{496DB20A-A455-4D01-B6BC-90FE6D7C6B81}.Release|Any CPU.ActiveCfg = Release|Any CPU
{496DB20A-A455-4D01-B6BC-90FE6D7C6B81}.Release|Any CPU.Build.0 = Release|Any CPU
{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}.Release|Any CPU.Build.0 = Release|Any CPU
{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Release|Any CPU.Build.0 = Release|Any CPU
{BFC6DC28-0351-4573-926A-D4124244C04F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BFC6DC28-0351-4573-926A-D4124244C04F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BFC6DC28-0351-4573-926A-D4124244C04F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BFC6DC28-0351-4573-926A-D4124244C04F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{BFC6DC28-0351-4573-926A-D4124244C04F} = {288C363D-A636-4EAE-9AC1-4698B641B26E}
EndGlobalSection
EndGlobal

src/Discord.Net/API/CDN.cs → src/Discord.Net.Core/API/CDN.cs View File

@@ -1,6 +1,6 @@
namespace Discord.API
{
internal static class CDN
public static class CDN
{
public static string GetApplicationIconUrl(ulong appId, string iconId)
=> iconId != null ? $"{DiscordConfig.CDNUrl}app-icons/{appId}/{iconId}.jpg" : null;

src/Discord.Net/API/Common/Application.cs → src/Discord.Net.Core/API/Common/Application.cs View File


src/Discord.Net/API/Common/Attachment.cs → src/Discord.Net.Core/API/Common/Attachment.cs View File


src/Discord.Net/API/Common/Ban.cs → src/Discord.Net.Core/API/Common/Ban.cs View File


src/Discord.Net/API/Common/Channel.cs → src/Discord.Net.Core/API/Common/Channel.cs View File


src/Discord.Net/API/Common/Connection.cs → src/Discord.Net.Core/API/Common/Connection.cs View File


src/Discord.Net/API/Common/Embed.cs → src/Discord.Net.Core/API/Common/Embed.cs View File


src/Discord.Net/API/Common/EmbedProvider.cs → src/Discord.Net.Core/API/Common/EmbedProvider.cs View File


src/Discord.Net/API/Common/EmbedThumbnail.cs → src/Discord.Net.Core/API/Common/EmbedThumbnail.cs View File


src/Discord.Net/API/Common/Emoji.cs → src/Discord.Net.Core/API/Common/Emoji.cs View File


src/Discord.Net/API/Common/Game.cs → src/Discord.Net.Core/API/Common/Game.cs View File


src/Discord.Net/API/Common/Guild.cs → src/Discord.Net.Core/API/Common/Guild.cs View File


src/Discord.Net/API/Common/GuildEmbed.cs → src/Discord.Net.Core/API/Common/GuildEmbed.cs View File


src/Discord.Net/API/Common/GuildMember.cs → src/Discord.Net.Core/API/Common/GuildMember.cs View File


src/Discord.Net/API/Common/Integration.cs → src/Discord.Net.Core/API/Common/Integration.cs View File


src/Discord.Net/API/Common/IntegrationAccount.cs → src/Discord.Net.Core/API/Common/IntegrationAccount.cs View File


src/Discord.Net/API/Common/Invite.cs → src/Discord.Net.Core/API/Common/Invite.cs View File


src/Discord.Net/API/Common/InviteChannel.cs → src/Discord.Net.Core/API/Common/InviteChannel.cs View File


src/Discord.Net/API/Common/InviteGuild.cs → src/Discord.Net.Core/API/Common/InviteGuild.cs View File


src/Discord.Net/API/Common/InviteMetadata.cs → src/Discord.Net.Core/API/Common/InviteMetadata.cs View File


src/Discord.Net/API/Common/Message.cs → src/Discord.Net.Core/API/Common/Message.cs View File


src/Discord.Net/API/Common/Overwrite.cs → src/Discord.Net.Core/API/Common/Overwrite.cs View File


src/Discord.Net/API/Common/Presence.cs → src/Discord.Net.Core/API/Common/Presence.cs View File


src/Discord.Net/API/Common/ReadState.cs → src/Discord.Net.Core/API/Common/ReadState.cs View File


src/Discord.Net/API/Common/Relationship.cs → src/Discord.Net.Core/API/Common/Relationship.cs View File


src/Discord.Net/API/Common/RelationshipType.cs → src/Discord.Net.Core/API/Common/RelationshipType.cs View File


src/Discord.Net/API/Common/Role.cs → src/Discord.Net.Core/API/Common/Role.cs View File


src/Discord.Net/API/Common/User.cs → src/Discord.Net.Core/API/Common/User.cs View File


src/Discord.Net/API/Common/UserGuild.cs → src/Discord.Net.Core/API/Common/UserGuild.cs View File


src/Discord.Net/API/Common/VoiceRegion.cs → src/Discord.Net.Core/API/Common/VoiceRegion.cs View File


src/Discord.Net/API/Common/VoiceState.cs → src/Discord.Net.Core/API/Common/VoiceState.cs View File


src/Discord.Net/API/DiscordRestApiClient.cs → src/Discord.Net.Core/API/DiscordRestApiClient.cs View File

@@ -4,7 +4,6 @@ using Discord.Net;
using Discord.Net.Converters;
using Discord.Net.Queue;
using Discord.Net.Rest;
using Discord.Rest;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
@@ -28,6 +27,7 @@ namespace Discord.API
protected readonly JsonSerializer _serializer;
protected readonly SemaphoreSlim _stateLock;
private readonly RestClientProvider _restClientProvider;
private readonly string _userAgent;

protected string _authToken;
protected bool _isDisposed;
@@ -36,11 +36,13 @@ namespace Discord.API

public LoginState LoginState { get; private set; }
public TokenType AuthTokenType { get; private set; }
internal RequestQueue RequestQueue { get; private set; }
public User CurrentUser { get; private set; }
public RequestQueue RequestQueue { get; private set; }

public DiscordRestApiClient(RestClientProvider restClientProvider, JsonSerializer serializer = null, RequestQueue requestQueue = null)
public DiscordRestApiClient(RestClientProvider restClientProvider, string userAgent, JsonSerializer serializer = null, RequestQueue requestQueue = null)
{
_restClientProvider = restClientProvider;
_userAgent = userAgent;
_serializer = serializer ?? new JsonSerializer { ContractResolver = new DiscordContractResolver() };
RequestQueue = requestQueue;

@@ -52,7 +54,7 @@ namespace Discord.API
{
_restClient = _restClientProvider(baseUrl);
_restClient.SetHeader("accept", "*/*");
_restClient.SetHeader("user-agent", DiscordRestConfig.UserAgent);
_restClient.SetHeader("user-agent", _userAgent);
_restClient.SetHeader("authorization", GetPrefixedToken(AuthTokenType, _authToken));
}
internal static string GetPrefixedToken(TokenType tokenType, string token)
@@ -111,6 +113,8 @@ namespace Discord.API
_authToken = token;
_restClient.SetHeader("authorization", GetPrefixedToken(AuthTokenType, _authToken));

CurrentUser = await GetMyUserAsync();

LoginState = LoginState.LoggedIn;
}
catch (Exception)
@@ -144,6 +148,7 @@ namespace Discord.API
await RequestQueue.SetCancelTokenAsync(CancellationToken.None).ConfigureAwait(false);
_restClient.SetCancelToken(CancellationToken.None);

CurrentUser = null;
LoginState = LoginState.LoggedOut;
}

@@ -268,8 +273,8 @@ namespace Discord.API
{
Preconditions.NotEqual(guildId, 0, nameof(guildId));
Preconditions.NotNull(args, nameof(args));
Preconditions.GreaterThan(args._bitrate, 0, nameof(args.Bitrate));
Preconditions.NotNullOrWhitespace(args._name, nameof(args.Name));
Preconditions.GreaterThan(args.Bitrate, 0, nameof(args.Bitrate));
Preconditions.NotNullOrWhitespace(args.Name, nameof(args.Name));

return await SendAsync<Channel>("POST", $"guilds/{guildId}/channels", args, options: options).ConfigureAwait(false);
}
@@ -283,8 +288,8 @@ namespace Discord.API
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));
Preconditions.NotNull(args, nameof(args));
Preconditions.AtLeast(args._position, 0, nameof(args.Position));
Preconditions.NotNullOrEmpty(args._name, nameof(args.Name));
Preconditions.AtLeast(args.Position, 0, nameof(args.Position));
Preconditions.NotNullOrEmpty(args.Name, nameof(args.Name));

return await SendAsync<Channel>("PATCH", $"channels/{channelId}", args, options: options).ConfigureAwait(false);
}
@@ -292,8 +297,8 @@ namespace Discord.API
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));
Preconditions.NotNull(args, nameof(args));
Preconditions.AtLeast(args._position, 0, nameof(args.Position));
Preconditions.NotNullOrEmpty(args._name, nameof(args.Name));
Preconditions.AtLeast(args.Position, 0, nameof(args.Position));
Preconditions.NotNullOrEmpty(args.Name, nameof(args.Name));

return await SendAsync<Channel>("PATCH", $"channels/{channelId}", args, options: options).ConfigureAwait(false);
}
@@ -301,10 +306,10 @@ namespace Discord.API
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));
Preconditions.NotNull(args, nameof(args));
Preconditions.GreaterThan(args._bitrate, 0, nameof(args.Bitrate));
Preconditions.AtLeast(args._userLimit, 0, nameof(args.Bitrate));
Preconditions.AtLeast(args._position, 0, nameof(args.Position));
Preconditions.NotNullOrEmpty(args._name, nameof(args.Name));
Preconditions.GreaterThan(args.Bitrate, 0, nameof(args.Bitrate));
Preconditions.AtLeast(args.UserLimit, 0, nameof(args.Bitrate));
Preconditions.AtLeast(args.Position, 0, nameof(args.Position));
Preconditions.NotNullOrEmpty(args.Name, nameof(args.Name));

return await SendAsync<Channel>("PATCH", $"channels/{channelId}", args, options: options).ConfigureAwait(false);
}
@@ -326,6 +331,132 @@ namespace Discord.API
break;
}
}
//Channel Messages
public async Task<Message> GetChannelMessageAsync(ulong channelId, ulong messageId, RequestOptions options = null)
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));
Preconditions.NotEqual(messageId, 0, nameof(messageId));

try
{
return await SendAsync<Message>("GET", $"channels/{channelId}/messages/{messageId}", options: options).ConfigureAwait(false);
}
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { return null; }
}
public async Task<IReadOnlyCollection<Message>> GetChannelMessagesAsync(ulong channelId, GetChannelMessagesParams args, RequestOptions options = null)
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));
Preconditions.NotNull(args, nameof(args));
Preconditions.AtLeast(args.Limit, 0, nameof(args.Limit));
Preconditions.AtMost(args.Limit, DiscordConfig.MaxMessagesPerBatch, nameof(args.Limit));

int limit = args.Limit.GetValueOrDefault(DiscordConfig.MaxMessagesPerBatch);
ulong? relativeId = args.RelativeMessageId.IsSpecified ? args.RelativeMessageId.Value : (ulong?)null;
string relativeDir;

switch (args.RelativeDirection.GetValueOrDefault(Direction.Before))
{
case Direction.Before:
default:
relativeDir = "before";
break;
case Direction.After:
relativeDir = "after";
break;
case Direction.Around:
relativeDir = "around";
break;
}

string endpoint;
if (relativeId != null)
endpoint = $"channels/{channelId}/messages?limit={limit}&{relativeDir}={relativeId}";
else
endpoint = $"channels/{channelId}/messages?limit={limit}";
return await SendAsync<IReadOnlyCollection<Message>>("GET", endpoint, options: options).ConfigureAwait(false);
}
public async Task<Message> CreateMessageAsync(ulong channelId, CreateMessageParams args, RequestOptions options = null)
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));
Preconditions.NotNull(args, nameof(args));
Preconditions.NotNullOrEmpty(args.Content, nameof(args.Content));
if (args.Content.Length > DiscordConfig.MaxMessageSize)
throw new ArgumentException($"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", nameof(args.Content));

return await SendAsync<Message>("POST", $"channels/{channelId}/messages", args, GlobalBucket.DirectMessage, options: options).ConfigureAwait(false);
}
public async Task<Message> UploadFileAsync(ulong channelId, UploadFileParams args, RequestOptions options = null)
{
Preconditions.NotNull(args, nameof(args));
Preconditions.NotEqual(channelId, 0, nameof(channelId));

if (args.Content.GetValueOrDefault(null) == null)
args.Content = "";
else if (args.Content.IsSpecified)
{
if (args.Content.Value == null)
args.Content = "";
if (args.Content.Value?.Length > DiscordConfig.MaxMessageSize)
throw new ArgumentOutOfRangeException($"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", nameof(args.Content));
}

return await SendMultipartAsync<Message>("POST", $"channels/{channelId}/messages", args.ToDictionary(), GlobalBucket.DirectMessage, options: options).ConfigureAwait(false);
}
public async Task DeleteMessageAsync(ulong channelId, ulong messageId, RequestOptions options = null)
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));
Preconditions.NotEqual(messageId, 0, nameof(messageId));

await SendAsync("DELETE", $"channels/{channelId}/messages/{messageId}", options: options).ConfigureAwait(false);
}
public async Task DeleteMessagesAsync(ulong channelId, DeleteMessagesParams args, RequestOptions options = null)
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));
Preconditions.NotNull(args, nameof(args));

Preconditions.NotNull(args.MessageIds, nameof(args.MessageIds));
Preconditions.AtMost(args.MessageIds.Length, 100, nameof(args.MessageIds.Length));

switch (args.MessageIds.Length)
{
case 0:
return;
case 1:
await DeleteMessageAsync(channelId, args.MessageIds[0]).ConfigureAwait(false);
break;
default:
await SendAsync("POST", $"channels/{channelId}/messages/bulk_delete", args, options: options).ConfigureAwait(false);
break;
}
}
public async Task<Message> ModifyMessageAsync(ulong channelId, ulong messageId, ModifyMessageParams args, RequestOptions options = null)
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));
Preconditions.NotEqual(messageId, 0, nameof(messageId));
Preconditions.NotNull(args, nameof(args));
if (args.Content.IsSpecified)
{
Preconditions.NotNullOrEmpty(args.Content, nameof(args.Content));
if (args.Content.Value.Length > DiscordConfig.MaxMessageSize)
throw new ArgumentOutOfRangeException($"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", nameof(args.Content));
}

return await SendAsync<Message>("PATCH", $"channels/{channelId}/messages/{messageId}", args, options: options).ConfigureAwait(false);
}
public async Task AckMessageAsync(ulong channelId, ulong messageId, RequestOptions options = null)
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));
Preconditions.NotEqual(messageId, 0, nameof(messageId));

await SendAsync("POST", $"channels/{channelId}/messages/{messageId}/ack", options: options).ConfigureAwait(false);
}
public async Task TriggerTypingIndicatorAsync(ulong channelId, RequestOptions options = null)
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));

await SendAsync("POST", $"channels/{channelId}/typing", options: options).ConfigureAwait(false);
}

//Channel Permissions
public async Task ModifyChannelPermissionsAsync(ulong channelId, ulong targetId, ModifyChannelPermissionsParams args, RequestOptions options = null)
@@ -399,7 +530,7 @@ namespace Discord.API
{
Preconditions.NotNull(args, nameof(args));
Preconditions.NotNullOrWhitespace(args.Name, nameof(args.Name));
Preconditions.NotNullOrWhitespace(args.Region, nameof(args.Region));
Preconditions.NotNullOrWhitespace(args.RegionId, nameof(args.RegionId));

return await SendAsync<Guild>("POST", "guilds", args, options: options).ConfigureAwait(false);
}
@@ -419,11 +550,11 @@ namespace Discord.API
{
Preconditions.NotEqual(guildId, 0, nameof(guildId));
Preconditions.NotNull(args, nameof(args));
Preconditions.NotEqual(args._afkChannelId, 0, nameof(args.AFKChannelId));
Preconditions.AtLeast(args._afkTimeout, 0, nameof(args.AFKTimeout));
Preconditions.NotNullOrEmpty(args._name, nameof(args.Name));
Preconditions.GreaterThan(args._ownerId, 0, nameof(args.OwnerId));
Preconditions.NotNull(args._region, nameof(args.Region));
Preconditions.NotEqual(args.AfkChannelId, 0, nameof(args.AfkChannelId));
Preconditions.AtLeast(args.AfkTimeout, 0, nameof(args.AfkTimeout));
Preconditions.NotNullOrEmpty(args.Name, nameof(args.Name));
Preconditions.GreaterThan(args.OwnerId, 0, nameof(args.OwnerId));
Preconditions.NotNull(args.RegionId, nameof(args.RegionId));

return await SendAsync<Guild>("PATCH", $"guilds/{guildId}", args, options: options).ConfigureAwait(false);
}
@@ -456,7 +587,7 @@ namespace Discord.API
Preconditions.NotEqual(guildId, 0, nameof(guildId));
Preconditions.NotEqual(userId, 0, nameof(userId));
Preconditions.NotNull(args, nameof(args));
Preconditions.AtLeast(args._deleteMessageDays, 0, nameof(args.DeleteMessageDays));
Preconditions.AtLeast(args.DeleteMessageDays, 0, nameof(args.DeleteMessageDays));

await SendAsync("PUT", $"guilds/{guildId}/bans/{userId}", args, options: options).ConfigureAwait(false);
}
@@ -514,8 +645,8 @@ namespace Discord.API
Preconditions.NotEqual(guildId, 0, nameof(guildId));
Preconditions.NotEqual(integrationId, 0, nameof(integrationId));
Preconditions.NotNull(args, nameof(args));
Preconditions.AtLeast(args._expireBehavior, 0, nameof(args.ExpireBehavior));
Preconditions.AtLeast(args._expireGracePeriod, 0, nameof(args.ExpireGracePeriod));
Preconditions.AtLeast(args.ExpireBehavior, 0, nameof(args.ExpireBehavior));
Preconditions.AtLeast(args.ExpireGracePeriod, 0, nameof(args.ExpireGracePeriod));

return await SendAsync<Integration>("PATCH", $"guilds/{guildId}/integrations/{integrationId}", args, options: options).ConfigureAwait(false);
}
@@ -552,18 +683,18 @@ namespace Discord.API

return await SendAsync<IReadOnlyCollection<InviteMetadata>>("GET", $"guilds/{guildId}/invites", options: options).ConfigureAwait(false);
}
public async Task<InviteMetadata[]> GetChannelInvitesAsync(ulong channelId, RequestOptions options = null)
public async Task<IReadOnlyCollection<InviteMetadata>> GetChannelInvitesAsync(ulong channelId, RequestOptions options = null)
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));

return await SendAsync<InviteMetadata[]>("GET", $"channels/{channelId}/invites", options: options).ConfigureAwait(false);
return await SendAsync<IReadOnlyCollection<InviteMetadata>>("GET", $"channels/{channelId}/invites", options: options).ConfigureAwait(false);
}
public async Task<InviteMetadata> CreateChannelInviteAsync(ulong channelId, CreateChannelInviteParams args, RequestOptions options = null)
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));
Preconditions.NotNull(args, nameof(args));
Preconditions.AtLeast(args._maxAge, 0, nameof(args.MaxAge));
Preconditions.AtLeast(args._maxUses, 0, nameof(args.MaxUses));
Preconditions.AtLeast(args.MaxAge, 0, nameof(args.MaxAge));
Preconditions.AtLeast(args.MaxUses, 0, nameof(args.MaxUses));

return await SendAsync<InviteMetadata>("POST", $"channels/{channelId}/invites", args, options: options).ConfigureAwait(false);
}
@@ -596,42 +727,15 @@ namespace Discord.API
{
Preconditions.NotEqual(guildId, 0, nameof(guildId));
Preconditions.NotNull(args, nameof(args));
Preconditions.GreaterThan(args._limit, 0, nameof(args.Limit));
Preconditions.GreaterThan(args._afterUserId, 0, nameof(args.AfterUserId));

int limit = args._limit.GetValueOrDefault(int.MaxValue);
ulong afterUserId = args._afterUserId.GetValueOrDefault(0);
Preconditions.GreaterThan(args.Limit, 0, nameof(args.Limit));
Preconditions.AtMost(args.Limit, DiscordConfig.MaxUsersPerBatch, nameof(args.Limit));
Preconditions.GreaterThan(args.AfterUserId, 0, nameof(args.AfterUserId));

List<GuildMember[]> result;
if (args._limit.IsSpecified)
result = new List<GuildMember[]>((limit + DiscordConfig.MaxUsersPerBatch - 1) / DiscordConfig.MaxUsersPerBatch);
else
result = new List<GuildMember[]>();

while (true)
{
int runLimit = (limit >= DiscordConfig.MaxUsersPerBatch) ? DiscordConfig.MaxUsersPerBatch : limit;
string endpoint = $"guilds/{guildId}/members?limit={runLimit}&after={afterUserId}";
var models = await SendAsync<GuildMember[]>("GET", endpoint, options: options).ConfigureAwait(false);

//Was this an empty batch?
if (models.Length == 0) break;

result.Add(models);

limit -= DiscordConfig.MaxUsersPerBatch;
afterUserId = models[models.Length - 1].User.Id;

//Was this an incomplete (the last) batch?
if (models.Length != DiscordConfig.MaxUsersPerBatch) break;
}

if (result.Count > 1)
return result.SelectMany(x => x).ToImmutableArray();
else if (result.Count == 1)
return result[0];
else
return ImmutableArray.Create<GuildMember>();
int limit = args.Limit.GetValueOrDefault(int.MaxValue);
ulong afterUserId = args.AfterUserId.GetValueOrDefault(0);
string endpoint = $"guilds/{guildId}/members?limit={limit}&after={afterUserId}";
return await SendAsync<IReadOnlyCollection<GuildMember>>("GET", endpoint, options: options).ConfigureAwait(false);
}
public async Task RemoveGuildMemberAsync(ulong guildId, ulong userId, RequestOptions options = null)
{
@@ -646,7 +750,18 @@ namespace Discord.API
Preconditions.NotEqual(userId, 0, nameof(userId));
Preconditions.NotNull(args, nameof(args));

await SendAsync("PATCH", $"guilds/{guildId}/members/{userId}", args, GuildBucket.ModifyMember, guildId, options: options).ConfigureAwait(false);
bool isCurrentUser = userId == CurrentUser.Id;

if (isCurrentUser && args.Nickname.IsSpecified)
{
var nickArgs = new ModifyCurrentUserNickParams(args.Nickname.Value ?? "");
await ModifyMyNickAsync(guildId, nickArgs).ConfigureAwait(false);
args.Nickname = Optional.Create<string>(); //Remove
}
if (!isCurrentUser || args.Deaf.IsSpecified || args.Mute.IsSpecified || args.RoleIds.IsSpecified)
{
await SendAsync("PATCH", $"guilds/{guildId}/members/{userId}", args, GuildBucket.ModifyMember, guildId, options: options).ConfigureAwait(false);
}
}

//Guild Roles
@@ -674,9 +789,9 @@ namespace Discord.API
Preconditions.NotEqual(guildId, 0, nameof(guildId));
Preconditions.NotEqual(roleId, 0, nameof(roleId));
Preconditions.NotNull(args, nameof(args));
Preconditions.AtLeast(args._color, 0, nameof(args.Color));
Preconditions.NotNullOrEmpty(args._name, nameof(args.Name));
Preconditions.AtLeast(args._position, 0, nameof(args.Position));
Preconditions.AtLeast(args.Color, 0, nameof(args.Color));
Preconditions.NotNullOrEmpty(args.Name, nameof(args.Name));
Preconditions.AtLeast(args.Position, 0, nameof(args.Position));

return await SendAsync<Role>("PATCH", $"guilds/{guildId}/roles/{roleId}", args, options: options).ConfigureAwait(false);
}
@@ -697,266 +812,6 @@ namespace Discord.API
}
}

//Messages
public async Task<Message> GetChannelMessageAsync(ulong channelId, ulong messageId, RequestOptions options = null)
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));
Preconditions.NotEqual(messageId, 0, nameof(messageId));

try
{
return await SendAsync<Message>("GET", $"channels/{channelId}/messages/{messageId}", options: options).ConfigureAwait(false);
}
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { return null; }
}
public async Task<IReadOnlyCollection<Message>> GetChannelMessagesAsync(ulong channelId, GetChannelMessagesParams args, RequestOptions options = null)
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));
Preconditions.NotNull(args, nameof(args));
Preconditions.AtLeast(args.Limit, 0, nameof(args.Limit));

int limit = args.Limit;
ulong? relativeId = args._relativeMessageId.IsSpecified ? args._relativeMessageId.Value : (ulong?)null;
string relativeDir;

switch (args.RelativeDirection)
{
case Direction.Before:
default:
relativeDir = "before";
break;
case Direction.After:
relativeDir = "after";
break;
case Direction.Around:
relativeDir = "around";
break;
}

int runs = (limit + DiscordConfig.MaxMessagesPerBatch - 1) / DiscordConfig.MaxMessagesPerBatch;
int lastRunCount = limit - (runs - 1) * DiscordConfig.MaxMessagesPerBatch;
var result = new API.Message[runs][];

int i = 0;
for (; i < runs; i++)
{
int runCount = i == (runs - 1) ? lastRunCount : DiscordConfig.MaxMessagesPerBatch;
string endpoint;
if (relativeId != null)
endpoint = $"channels/{channelId}/messages?limit={runCount}&{relativeDir}={relativeId}";
else
endpoint = $"channels/{channelId}/messages?limit={runCount}";
var models = await SendAsync<Message[]>("GET", endpoint, options: options).ConfigureAwait(false);

//Was this an empty batch?
if (models.Length == 0) break;

//We can't assume these messages to be sorted by id (fails in rare cases), lets search for the highest/lowest id ourselves
switch (args.RelativeDirection)
{
case Direction.Before:
case Direction.Around:
default:
result[i] = models;
relativeId = ulong.MaxValue;
//Lowest id *should* be the last one
for (int j = models.Length - 1; j >= 0; j--)
{
if (models[j].Id < relativeId.Value)
relativeId = models[j].Id;
}
break;
case Direction.After:
result[runs - i - 1] = models;
relativeId = ulong.MinValue;
//Highest id *should* be the first one
for (int j = 0; j < models.Length; j++)
{
if (models[j].Id > relativeId.Value)
relativeId = models[j].Id;
}
break;
}

//Was this an incomplete (the last) batch?
if (models.Length != DiscordConfig.MaxMessagesPerBatch) { i++; break; }
}

if (i > 1)
{
switch (args.RelativeDirection)
{
case Direction.Before:
case Direction.Around:
default:
return result.Take(i).SelectMany(x => x).ToImmutableArray();
case Direction.After:
return result.Skip(runs - i).Take(i).SelectMany(x => x).ToImmutableArray();
}
}
else if (i == 1)
{
switch (args.RelativeDirection)
{
case Direction.Before:
case Direction.Around:
default:
return result[0];
case Direction.After:
return result[runs - 1];
}
}
else
return ImmutableArray.Create<Message>();
}
public Task<Message> CreateMessageAsync(ulong guildId, ulong channelId, CreateMessageParams args, RequestOptions options = null)
{
Preconditions.NotEqual(guildId, 0, nameof(guildId));

return CreateMessageInternalAsync(guildId, channelId, args);
}
public Task<Message> CreateDMMessageAsync(ulong channelId, CreateMessageParams args, RequestOptions options = null)
{
return CreateMessageInternalAsync(0, channelId, args);
}
private async Task<Message> CreateMessageInternalAsync(ulong guildId, ulong channelId, CreateMessageParams args, RequestOptions options = null)
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));
Preconditions.NotNull(args, nameof(args));
Preconditions.NotNullOrEmpty(args._content, nameof(args.Content));
if (args._content.Length > DiscordConfig.MaxMessageSize)
throw new ArgumentException($"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", nameof(args.Content));

if (guildId != 0)
return await SendAsync<Message>("POST", $"channels/{channelId}/messages", args, GuildBucket.SendEditMessage, guildId, options: options).ConfigureAwait(false);
else
return await SendAsync<Message>("POST", $"channels/{channelId}/messages", args, GlobalBucket.DirectMessage, options: options).ConfigureAwait(false);
}
public Task<Message> UploadFileAsync(ulong guildId, ulong channelId, UploadFileParams args, RequestOptions options = null)
{
Preconditions.NotEqual(guildId, 0, nameof(guildId));

return UploadFileInternalAsync(guildId, channelId, args);
}
public Task<Message> UploadDMFileAsync(ulong channelId, UploadFileParams args, RequestOptions options = null)
{
return UploadFileInternalAsync(0, channelId, args);
}
private async Task<Message> UploadFileInternalAsync(ulong guildId, ulong channelId, UploadFileParams args, RequestOptions options = null)
{
Preconditions.NotNull(args, nameof(args));
Preconditions.NotEqual(channelId, 0, nameof(channelId));

if (args._content.GetValueOrDefault(null) == null)
args._content = "";
else if (args._content.IsSpecified)
{
if (args._content.Value == null)
args._content = "";
if (args._content.Value?.Length > DiscordConfig.MaxMessageSize)
throw new ArgumentOutOfRangeException($"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", nameof(args.Content));
}

if (guildId != 0)
return await SendMultipartAsync<Message>("POST", $"channels/{channelId}/messages", args.ToDictionary(), GuildBucket.SendEditMessage, guildId, options: options).ConfigureAwait(false);
else
return await SendMultipartAsync<Message>("POST", $"channels/{channelId}/messages", args.ToDictionary(), GlobalBucket.DirectMessage, options: options).ConfigureAwait(false);
}
public Task DeleteMessageAsync(ulong guildId, ulong channelId, ulong messageId, RequestOptions options = null)
{
Preconditions.NotEqual(guildId, 0, nameof(guildId));

return DeleteMessageInternalAsync(guildId, channelId, messageId);
}
public Task DeleteDMMessageAsync(ulong channelId, ulong messageId, RequestOptions options = null)
{
return DeleteMessageInternalAsync(0, channelId, messageId);
}
private async Task DeleteMessageInternalAsync(ulong guildId, ulong channelId, ulong messageId, RequestOptions options = null)
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));
Preconditions.NotEqual(messageId, 0, nameof(messageId));

if (guildId != 0)
await SendAsync("DELETE", $"channels/{channelId}/messages/{messageId}", GuildBucket.DeleteMessage, guildId, options: options).ConfigureAwait(false);
else
await SendAsync("DELETE", $"channels/{channelId}/messages/{messageId}", options: options).ConfigureAwait(false);
}
public Task DeleteMessagesAsync(ulong guildId, ulong channelId, DeleteMessagesParams args, RequestOptions options = null)
{
Preconditions.NotEqual(guildId, 0, nameof(guildId));

return DeleteMessagesInternalAsync(guildId, channelId, args);
}
public Task DeleteDMMessagesAsync(ulong channelId, DeleteMessagesParams args, RequestOptions options = null)
{
return DeleteMessagesInternalAsync(0, channelId, args);
}
private async Task DeleteMessagesInternalAsync(ulong guildId, ulong channelId, DeleteMessagesParams args, RequestOptions options = null)
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));
Preconditions.NotNull(args, nameof(args));

var messageIds = args._messages;
Preconditions.NotNull(args._messages, nameof(args.MessageIds));
Preconditions.AtMost(messageIds.Length, 100, nameof(messageIds.Length));

switch (messageIds.Length)
{
case 0:
return;
case 1:
await DeleteMessageInternalAsync(guildId, channelId, messageIds[0]).ConfigureAwait(false);
break;
default:
if (guildId != 0)
await SendAsync("POST", $"channels/{channelId}/messages/bulk_delete", args, GuildBucket.DeleteMessages, guildId, options: options).ConfigureAwait(false);
else
await SendAsync("POST", $"channels/{channelId}/messages/bulk_delete", args, options: options).ConfigureAwait(false);
break;
}
}
public Task<Message> ModifyMessageAsync(ulong guildId, ulong channelId, ulong messageId, ModifyMessageParams args, RequestOptions options = null)
{
Preconditions.NotEqual(guildId, 0, nameof(guildId));

return ModifyMessageInternalAsync(guildId, channelId, messageId, args);
}
public Task<Message> ModifyDMMessageAsync(ulong channelId, ulong messageId, ModifyMessageParams args, RequestOptions options = null)
{
return ModifyMessageInternalAsync(0, channelId, messageId, args);
}
private async Task<Message> ModifyMessageInternalAsync(ulong guildId, ulong channelId, ulong messageId, ModifyMessageParams args, RequestOptions options = null)
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));
Preconditions.NotEqual(messageId, 0, nameof(messageId));
Preconditions.NotNull(args, nameof(args));
if (args._content.IsSpecified)
{
Preconditions.NotNullOrEmpty(args._content, nameof(args.Content));
if (args._content.Value.Length > DiscordConfig.MaxMessageSize)
throw new ArgumentOutOfRangeException($"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", nameof(args.Content));
}

if (guildId != 0)
return await SendAsync<Message>("PATCH", $"channels/{channelId}/messages/{messageId}", args, GuildBucket.SendEditMessage, guildId, options: options).ConfigureAwait(false);
else
return await SendAsync<Message>("PATCH", $"channels/{channelId}/messages/{messageId}", args, options: options).ConfigureAwait(false);
}
public async Task AckMessageAsync(ulong channelId, ulong messageId, RequestOptions options = null)
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));
Preconditions.NotEqual(messageId, 0, nameof(messageId));

await SendAsync("POST", $"channels/{channelId}/messages/{messageId}/ack", options: options).ConfigureAwait(false);
}
public async Task TriggerTypingIndicatorAsync(ulong channelId, RequestOptions options = null)
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));

await SendAsync("POST", $"channels/{channelId}/typing", options: options).ConfigureAwait(false);
}

//Users
public async Task<User> GetUserAsync(ulong userId, RequestOptions options = null)
{
@@ -1012,7 +867,7 @@ namespace Discord.API
public async Task<User> ModifySelfAsync(ModifyCurrentUserParams args, RequestOptions options = null)
{
Preconditions.NotNull(args, nameof(args));
Preconditions.NotNullOrEmpty(args._username, nameof(args.Username));
Preconditions.NotNullOrEmpty(args.Username, nameof(args.Username));

return await SendAsync<User>("PATCH", "users/@me", args, options: options).ConfigureAwait(false);
}
@@ -1026,7 +881,7 @@ namespace Discord.API
public async Task<Channel> CreateDMChannelAsync(CreateDMChannelParams args, RequestOptions options = null)
{
Preconditions.NotNull(args, nameof(args));
Preconditions.GreaterThan(args._recipientId, 0, nameof(args.Recipient));
Preconditions.GreaterThan(args.RecipientId, 0, nameof(args.RecipientId));

return await SendAsync<Channel>("POST", $"users/@me/channels", args, options: options).ConfigureAwait(false);
}

src/Discord.Net/API/Image.cs → src/Discord.Net.Core/API/Image.cs View File

@@ -2,7 +2,7 @@

namespace Discord.API
{
internal struct Image
public struct Image
{
public Stream Stream { get; }
public string Hash { get; }

src/Discord.Net/API/Int53Attribute.cs → src/Discord.Net.Core/API/Int53Attribute.cs View File


+ 16
- 0
src/Discord.Net.Core/API/Rest/CreateChannelInviteParams.cs View File

@@ -0,0 +1,16 @@
#pragma warning disable CS1591
using Newtonsoft.Json;

namespace Discord.API.Rest
{
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class CreateChannelInviteParams
{
[JsonProperty("max_age")]
public Optional<int> MaxAge { get; set; }
[JsonProperty("max_uses")]
public Optional<int> MaxUses { get; set; }
[JsonProperty("temporary")]
public Optional<bool> IsTemporary { get; set; }
}
}

src/Discord.Net/API/Rest/CreateDMChannelParams.cs → src/Discord.Net.Core/API/Rest/CreateDMChannelParams.cs View File

@@ -7,8 +7,11 @@ namespace Discord.API.Rest
public class CreateDMChannelParams
{
[JsonProperty("recipient_id")]
internal ulong _recipientId { get; set; }
public ulong RecipientId { set { _recipientId = value; } }
public IUser Recipient { set { _recipientId = value.Id; } }
public ulong RecipientId { get; }

public CreateDMChannelParams(ulong recipientId)
{
RecipientId = recipientId;
}
}
}

src/Discord.Net/API/Rest/CreateGuildBanParams.cs → src/Discord.Net.Core/API/Rest/CreateGuildBanParams.cs View File

@@ -7,7 +7,6 @@ namespace Discord.API.Rest
public class CreateGuildBanParams
{
[JsonProperty("delete-message-days")]
internal Optional<int> _deleteMessageDays { get; set; }
public int DeleteMessageDays { set { _deleteMessageDays = value; } }
public Optional<int> DeleteMessageDays { get; set; }
}
}

+ 23
- 0
src/Discord.Net.Core/API/Rest/CreateGuildChannelParams.cs View File

@@ -0,0 +1,23 @@
#pragma warning disable CS1591
using Newtonsoft.Json;

namespace Discord.API.Rest
{
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class CreateGuildChannelParams
{
[JsonProperty("name")]
public string Name { get; }
[JsonProperty("type")]
public ChannelType Type { get; }

[JsonProperty("bitrate")]
public Optional<int> Bitrate { get; set; }

public CreateGuildChannelParams(string name, ChannelType type)
{
Name = name;
Type = type;
}
}
}

src/Discord.Net/API/Rest/CreateGuildIntegrationParams.cs → src/Discord.Net.Core/API/Rest/CreateGuildIntegrationParams.cs View File

@@ -7,9 +7,14 @@ namespace Discord.API.Rest
public class CreateGuildIntegrationParams
{
[JsonProperty("id")]
public ulong Id { internal get; set; }

public ulong Id { get; }
[JsonProperty("type")]
public string Type { internal get; set; }
public string Type { get; }

public CreateGuildIntegrationParams(ulong id, string type)
{
Id = id;
Type = type;
}
}
}

src/Discord.Net/API/Rest/CreateGuildParams.cs → src/Discord.Net.Core/API/Rest/CreateGuildParams.cs View File

@@ -1,6 +1,5 @@
#pragma warning disable CS1591
using Newtonsoft.Json;
using System.IO;

namespace Discord.API.Rest
{
@@ -8,13 +7,17 @@ namespace Discord.API.Rest
public class CreateGuildParams
{
[JsonProperty("name")]
public string Name { internal get; set; }

public string Name { get; }
[JsonProperty("region")]
public string Region { internal get; set; }
public string RegionId { get; }

[JsonProperty("icon")]
internal Optional<Image?> _icon { get; set; }
public Stream Icon { set { _icon = value != null ? new Image(value) : (Image?)null; } }
public Optional<Image?> Icon { get; set; }

public CreateGuildParams(string name, string regionId)
{
Name = name;
RegionId = regionId;
}
}
}

+ 22
- 0
src/Discord.Net.Core/API/Rest/CreateMessageParams.cs View File

@@ -0,0 +1,22 @@
#pragma warning disable CS1591
using Newtonsoft.Json;

namespace Discord.API.Rest
{
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class CreateMessageParams
{
[JsonProperty("content")]
public string Content { get; }

[JsonProperty("nonce")]
public Optional<string> Nonce { get; set; }
[JsonProperty("tts")]
public Optional<bool> IsTTS { get; set; }

public CreateMessageParams(string content)
{
Content = content;
}
}
}

+ 17
- 0
src/Discord.Net.Core/API/Rest/DeleteMessagesParams.cs View File

@@ -0,0 +1,17 @@
#pragma warning disable CS1591
using Newtonsoft.Json;

namespace Discord.API.Rest
{
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class DeleteMessagesParams
{
[JsonProperty("messages")]
public ulong[] MessageIds { get; }

public DeleteMessagesParams(ulong[] messageIds)
{
MessageIds = messageIds;
}
}
}

+ 10
- 0
src/Discord.Net.Core/API/Rest/GetChannelMessagesParams.cs View File

@@ -0,0 +1,10 @@
#pragma warning disable CS1591
namespace Discord.API.Rest
{
public class GetChannelMessagesParams
{
public Optional<int> Limit { get; set; }
public Optional<Direction> RelativeDirection { get; set; }
public Optional<ulong> RelativeMessageId { get; set; }
}
}

src/Discord.Net/API/Rest/GetGatewayResponse.cs → src/Discord.Net.Core/API/Rest/GetGatewayResponse.cs View File


+ 9
- 0
src/Discord.Net.Core/API/Rest/GetGuildMembersParams.cs View File

@@ -0,0 +1,9 @@
#pragma warning disable CS1591
namespace Discord.API.Rest
{
public class GetGuildMembersParams
{
public Optional<int> Limit { get; set; }
public Optional<ulong> AfterUserId { get; set; }
}
}

src/Discord.Net/API/Rest/GetGuildPruneCountResponse.cs → src/Discord.Net.Core/API/Rest/GetGuildPruneCountResponse.cs View File


src/Discord.Net/API/Rest/GuildPruneParams.cs → src/Discord.Net.Core/API/Rest/GuildPruneParams.cs View File

@@ -7,6 +7,11 @@ namespace Discord.API.Rest
public class GuildPruneParams
{
[JsonProperty("days")]
public int Days { internal get; set; }
public int Days { get; }

public GuildPruneParams(int days)
{
Days = days;
}
}
}

src/Discord.Net/API/Rest/ModifyChannelPermissionsParams.cs → src/Discord.Net.Core/API/Rest/ModifyChannelPermissionsParams.cs View File

@@ -7,10 +7,17 @@ namespace Discord.API.Rest
public class ModifyChannelPermissionsParams
{
[JsonProperty("type")]
public string Type { internal get; set; }
public string Type { get; }
[JsonProperty("allow")]
public ulong Allow { internal get; set; }
public ulong Allow { get; }
[JsonProperty("deny")]
public ulong Deny { internal get; set; }
public ulong Deny { get; }

public ModifyChannelPermissionsParams(string type, ulong allow, ulong deny)
{
Type = type;
Allow = allow;
Deny = deny;
}
}
}

src/Discord.Net/API/Rest/ModifyCurrentUserNickParams.cs → src/Discord.Net.Core/API/Rest/ModifyCurrentUserNickParams.cs View File

@@ -7,6 +7,11 @@ namespace Discord.API.Rest
public class ModifyCurrentUserNickParams
{
[JsonProperty("nick")]
public string Nickname { internal get; set; }
public string Nickname { get; }

public ModifyCurrentUserNickParams(string nickname)
{
Nickname = nickname;
}
}
}

src/Discord.Net/API/Rest/ModifyCurrentUserParams.cs → src/Discord.Net.Core/API/Rest/ModifyCurrentUserParams.cs View File

@@ -1,6 +1,5 @@
#pragma warning disable CS1591
using Newtonsoft.Json;
using System.IO;

namespace Discord.API.Rest
{
@@ -8,11 +7,8 @@ namespace Discord.API.Rest
public class ModifyCurrentUserParams
{
[JsonProperty("username")]
internal Optional<string> _username { get; set; }
public string Username { set { _username = value; } }

public Optional<string> Username { get; set; }
[JsonProperty("avatar")]
internal Optional<Image> _avatar { get; set; }
public Stream Avatar { set { _avatar = new Image(value); } }
public Optional<Image> Avatar { get; set; }
}
}

src/Discord.Net/API/Rest/ModifyGuildChannelParams.cs → src/Discord.Net.Core/API/Rest/ModifyGuildChannelParams.cs View File

@@ -7,11 +7,8 @@ namespace Discord.API.Rest
public class ModifyGuildChannelParams
{
[JsonProperty("name")]
internal Optional<string> _name { get; set; }
public string Name { set { _name = value; } }

public Optional<string> Name { get; set; }
[JsonProperty("position")]
internal Optional<int> _position { get; set; }
public int Position { set { _position = value; } }
public Optional<int> Position { get; set; }
}
}

src/Discord.Net/API/Rest/ModifyGuildChannelsParams.cs → src/Discord.Net.Core/API/Rest/ModifyGuildChannelsParams.cs View File

@@ -7,9 +7,14 @@ namespace Discord.API.Rest
public class ModifyGuildChannelsParams
{
[JsonProperty("id")]
public ulong Id { internal get; set; }

public ulong Id { get; set; }
[JsonProperty("position")]
public int Position { internal get; set; }
public int Position { get; set; }

public ModifyGuildChannelsParams(ulong id, int position)
{
Id = id;
Position = position;
}
}
}

+ 14
- 0
src/Discord.Net.Core/API/Rest/ModifyGuildEmbedParams.cs View File

@@ -0,0 +1,14 @@
#pragma warning disable CS1591
using Newtonsoft.Json;

namespace Discord.API.Rest
{
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class ModifyGuildEmbedParams
{
[JsonProperty("enabled")]
public Optional<bool> Enabled { get; set; }
[JsonProperty("channel")]
public Optional<ulong?> ChannelId { get; set; }
}
}

+ 16
- 0
src/Discord.Net.Core/API/Rest/ModifyGuildIntegrationParams.cs View File

@@ -0,0 +1,16 @@
#pragma warning disable CS1591
using Newtonsoft.Json;

namespace Discord.API.Rest
{
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class ModifyGuildIntegrationParams
{
[JsonProperty("expire_behavior")]
public Optional<int> ExpireBehavior { get; set; }
[JsonProperty("expire_grace_period")]
public Optional<int> ExpireGracePeriod { get; set; }
[JsonProperty("enable_emoticons")]
public Optional<bool> EnableEmoticons { get; set; }
}
}

+ 20
- 0
src/Discord.Net.Core/API/Rest/ModifyGuildMemberParams.cs View File

@@ -0,0 +1,20 @@
#pragma warning disable CS1591
using Newtonsoft.Json;

namespace Discord.API.Rest
{
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class ModifyGuildMemberParams
{
[JsonProperty("mute")]
public Optional<bool> Mute { get; set; }
[JsonProperty("deaf")]
public Optional<bool> Deaf { get; set; }
[JsonProperty("nick")]
public Optional<string> Nickname { get; set; }
[JsonProperty("roles")]
public Optional<ulong[]> RoleIds { get; set; }
[JsonProperty("channel_id")]
public Optional<ulong> ChannelId { get; set; }
}
}

+ 30
- 0
src/Discord.Net.Core/API/Rest/ModifyGuildParams.cs View File

@@ -0,0 +1,30 @@
#pragma warning disable CS1591
using Newtonsoft.Json;

namespace Discord.API.Rest
{
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class ModifyGuildParams
{
[JsonProperty("username")]
public Optional<string> Username { get; set; }
[JsonProperty("name")]
public Optional<string> Name { get; set; }
[JsonProperty("region")]
public Optional<string> RegionId { get; set; }
[JsonProperty("verification_level")]
public Optional<VerificationLevel> VerificationLevel { get; set; }
[JsonProperty("default_message_notifications")]
public Optional<DefaultMessageNotifications> DefaultMessageNotifications { get; set; }
[JsonProperty("afk_timeout")]
public Optional<int> AfkTimeout { get; set; }
[JsonProperty("icon")]
public Optional<Image?> Icon { get; set; }
[JsonProperty("splash")]
public Optional<Image?> Splash { get; set; }
[JsonProperty("afk_channel_id")]
public Optional<ulong?> AfkChannelId { get; set; }
[JsonProperty("owner_id")]
public Optional<ulong> OwnerId { get; set; }
}
}

+ 20
- 0
src/Discord.Net.Core/API/Rest/ModifyGuildRoleParams.cs View File

@@ -0,0 +1,20 @@
#pragma warning disable CS1591
using Newtonsoft.Json;

namespace Discord.API.Rest
{
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class ModifyGuildRoleParams
{
[JsonProperty("name")]
public Optional<string> Name { get; set; }
[JsonProperty("permissions")]
public Optional<ulong> Permissions { get; set; }
[JsonProperty("position")]
public Optional<int> Position { get; set; }
[JsonProperty("color")]
public Optional<uint> Color { get; set; }
[JsonProperty("hoist")]
public Optional<bool> Hoist { get; set; }
}
}

src/Discord.Net/API/Rest/ModifyGuildRolesParams.cs → src/Discord.Net.Core/API/Rest/ModifyGuildRolesParams.cs View File

@@ -7,6 +7,11 @@ namespace Discord.API.Rest
public class ModifyGuildRolesParams : ModifyGuildRoleParams
{
[JsonProperty("id")]
public ulong Id { internal get; set; }
public ulong Id { get; }

public ModifyGuildRolesParams(ulong id)
{
Id = id;
}
}
}

src/Discord.Net/API/Rest/ModifyMessageParams.cs → src/Discord.Net.Core/API/Rest/ModifyMessageParams.cs View File

@@ -7,7 +7,6 @@ namespace Discord.API.Rest
public class ModifyMessageParams
{
[JsonProperty("content")]
internal Optional<string> _content { get; set; }
public string Content { set { _content = value; } }
public Optional<string> Content { get; set; }
}
}

+ 9
- 0
src/Discord.Net.Core/API/Rest/ModifyPresenceParams.cs View File

@@ -0,0 +1,9 @@
#pragma warning disable CS1591
namespace Discord.API.Rest
{
public class ModifyPresenceParams
{
public Optional<UserStatus> Status { get; set; }
public Optional<Game> Game { get; set; }
}
}

src/Discord.Net/API/Rest/ModifyTextChannelParams.cs → src/Discord.Net.Core/API/Rest/ModifyTextChannelParams.cs View File

@@ -7,7 +7,6 @@ namespace Discord.API.Rest
public class ModifyTextChannelParams : ModifyGuildChannelParams
{
[JsonProperty("topic")]
internal Optional<string> _topic { get; set; }
public string Topic { set { _topic = value; } }
public Optional<string> Topic { get; set; }
}
}

src/Discord.Net/API/Rest/ModifyVoiceChannelParams.cs → src/Discord.Net.Core/API/Rest/ModifyVoiceChannelParams.cs View File

@@ -7,11 +7,8 @@ namespace Discord.API.Rest
public class ModifyVoiceChannelParams : ModifyGuildChannelParams
{
[JsonProperty("bitrate")]
internal Optional<int> _bitrate { get; set; }
public int Bitrate { set { _bitrate = value; } }

public Optional<int> Bitrate { get; set; }
[JsonProperty("user_limit")]
internal Optional<int> _userLimit { get; set; }
public int UserLimit { set { _userLimit = value; } }
public Optional<int> UserLimit { get; set; }
}
}

+ 35
- 0
src/Discord.Net.Core/API/Rest/UploadFileParams.cs View File

@@ -0,0 +1,35 @@
#pragma warning disable CS1591
using Discord.Net.Rest;
using System.Collections.Generic;
using System.IO;

namespace Discord.API.Rest
{
public class UploadFileParams
{
public Stream File { get; }

public Optional<string> Filename { get; set; }
public Optional<string> Content { get; set; }
public Optional<string> Nonce { get; set; }
public Optional<bool> IsTTS { get; set; }

public UploadFileParams(Stream file)
{
File = file;
}

public IReadOnlyDictionary<string, object> ToDictionary()
{
var d = new Dictionary<string, object>();
d["file"] = new MultipartFile(File, Filename.GetValueOrDefault("unknown.dat"));
if (Content.IsSpecified)
d["content"] = Content.Value;
if (IsTTS.IsSpecified)
d["tts"] = IsTTS.Value.ToString();
if (Nonce.IsSpecified)
d["nonce"] = Nonce.Value;
return d;
}
}
}

src/Discord.Net/API/WebSocketMessage.cs → src/Discord.Net.Core/API/WebSocketMessage.cs View File


src/Discord.Net/Audio/IAudioClient.cs → src/Discord.Net.Core/Audio/IAudioClient.cs View File

@@ -1,4 +1,5 @@
using System;
using System.IO;
using System.Threading.Tasks;

namespace Discord.Audio
@@ -8,8 +9,7 @@ namespace Discord.Audio
event Func<Task> Connected;
event Func<Exception, Task> Disconnected;
event Func<int, int, Task> LatencyUpdated;

DiscordVoiceAPIClient ApiClient { get; }
/// <summary> Gets the current connection state of this client. </summary>
ConnectionState ConnectionState { get; }
/// <summary> Gets the estimated round-trip latency, in milliseconds, to the gateway server. </summary>
@@ -17,7 +17,7 @@ namespace Discord.Audio

Task DisconnectAsync();

RTPWriteStream CreateOpusStream(int samplesPerFrame, int bufferSize = 4000);
OpusEncodeStream CreatePCMStream(int samplesPerFrame, int? bitrate = null, OpusApplication application = OpusApplication.MusicOrMixed, int bufferSize = 4000);
Stream CreateOpusStream(int samplesPerFrame, int bufferSize = 4000);
Stream CreatePCMStream(int samplesPerFrame, int? bitrate = null, OpusApplication application = OpusApplication.MusicOrMixed, int bufferSize = 4000);
}
}

src/Discord.Net/Audio/Opus/OpusApplication.cs → src/Discord.Net.Core/Audio/Opus/OpusApplication.cs View File


src/Discord.Net/ConnectionState.cs → src/Discord.Net.Core/ConnectionState.cs View File


+ 19
- 0
src/Discord.Net.Core/Discord.Net.Core.xproj View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>91e9e7bd-75c9-4e98-84aa-2c271922e5c2</ProjectGuid>
<RootNamespace>Discord</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

src/Discord.Net/DiscordConfig.cs → src/Discord.Net.Core/DiscordConfig.cs View File


src/Discord.Net/Entities/Channels/ChannelType.cs → src/Discord.Net.Core/Entities/Channels/ChannelType.cs View File


src/Discord.Net/Entities/Channels/IChannel.cs → src/Discord.Net.Core/Entities/Channels/IChannel.cs View File

@@ -3,11 +3,15 @@ using System.Threading.Tasks;

namespace Discord
{
public interface IChannel : ISnowflakeEntity, IUpdateable
public interface IChannel : ISnowflakeEntity
{
IReadOnlyCollection<IUser> CachedUsers { get; }

/// <summary> Gets a collection of all users in this channel. </summary>
Task<IReadOnlyCollection<IUser>> GetUsersAsync();
IAsyncEnumerable<IReadOnlyCollection<IUser>> GetUsersAsync();
/// <summary> Gets a user in this channel with the provided id.</summary>
Task<IUser> GetUserAsync(ulong id);
IUser GetCachedUser(ulong id);
}
}

src/Discord.Net/Entities/Channels/IDMChannel.cs → src/Discord.Net.Core/Entities/Channels/IDMChannel.cs View File


+ 16
- 0
src/Discord.Net.Core/Entities/Channels/IGroupChannel.cs View File

@@ -0,0 +1,16 @@
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Discord
{
public interface IGroupChannel : IMessageChannel, IPrivateChannel
{
///// <summary> Adds a user to this group. </summary>
//Task AddUserAsync(IUser user);

//new IReadOnlyCollection<IGroupUser> CachedUsers { get; }

/// <summary> Leaves this group. </summary>
Task LeaveAsync();
}
}

src/Discord.Net/Entities/Channels/IGuildChannel.cs → src/Discord.Net.Core/Entities/Channels/IGuildChannel.cs View File

@@ -12,8 +12,9 @@ namespace Discord
/// <summary> Gets the position of this channel in the guild's channel list, relative to others of the same type. </summary>
int Position { get; }

/// <summary> Gets the guild this channel is a member of. </summary>
IGuild Guild { get; }
/// <summary> Gets the id of the guild this channel is a member of. </summary>
ulong GuildId { get; }
new IReadOnlyCollection<IGuildUser> CachedUsers { get; }

/// <summary> Creates a new invite to this channel. </summary>
/// <param name="maxAge"> The time (in seconds) until the invite expires. Set to null to never expire. </param>
@@ -43,8 +44,9 @@ namespace Discord
Task AddPermissionOverwriteAsync(IUser user, OverwritePermissions permissions);

/// <summary> Gets a collection of all users in this channel. </summary>
new Task<IReadOnlyCollection<IGuildUser>> GetUsersAsync();
new IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> GetUsersAsync();
/// <summary> Gets a user in this channel with the provided id.</summary>
new Task<IGuildUser> GetUserAsync(ulong id);
new IGuildUser GetCachedUser(ulong id);
}
}

src/Discord.Net/Entities/Channels/IMessageChannel.cs → src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

@@ -15,20 +16,21 @@ namespace Discord
Task<IUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false);
/// <summary> Sends a file to this text channel, with an optional caption. </summary>
Task<IUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false);

/// <summary> Gets a message from this message channel with the given id, or null if not found. </summary>
Task<IMessage> GetMessageAsync(ulong id);
/// <summary> Gets the message from this channel's cache with the given id, or null if not found. </summary>
IMessage GetCachedMessage(ulong id);
/// <summary> Gets the last N messages from this message channel. </summary>
Task<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch);
IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch);
/// <summary> Gets a collection of messages in this channel. </summary>
Task<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch);
IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch);
/// <summary> Gets a collection of pinned messages in this channel. </summary>
Task<IReadOnlyCollection<IMessage>> GetPinnedMessagesAsync();
/// <summary> Bulk deletes multiple messages. </summary>
Task DeleteMessagesAsync(IEnumerable<IMessage> messages);

/// <summary> Broadcasts the "user is typing" message to all users in this channel, lasting 10 seconds.</summary>
Task TriggerTypingAsync();
IDisposable EnterTypingState();
}
}

src/Discord.Net/Entities/Channels/IPrivateChannel.cs → src/Discord.Net.Core/Entities/Channels/IPrivateChannel.cs View File


src/Discord.Net/Entities/Channels/ITextChannel.cs → src/Discord.Net.Core/Entities/Channels/ITextChannel.cs View File


src/Discord.Net/Entities/Channels/IVoiceChannel.cs → src/Discord.Net.Core/Entities/Channels/IVoiceChannel.cs View File


src/Discord.Net/Entities/Guilds/DefaultMessageNotifications.cs → src/Discord.Net.Core/Entities/Guilds/DefaultMessageNotifications.cs View File


+ 33
- 0
src/Discord.Net.Core/Entities/Guilds/Emoji.cs View File

@@ -0,0 +1,33 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using Model = Discord.API.Emoji;

namespace Discord
{
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public struct Emoji
{
public ulong Id { get; }
public string Name { get; }
public bool IsManaged { get; }
public bool RequireColons { get; }
public IReadOnlyList<ulong> RoleIds { get; }

public Emoji(ulong id, string name, bool isManaged, bool requireColons, IReadOnlyList<ulong> roleIds)
{
Id = id;
Name = name;
IsManaged = isManaged;
RequireColons = requireColons;
RoleIds = roleIds;
}
public static Emoji Create(Model model)
{
return new Emoji(model.Id, model.Name, model.Managed, model.RequireColons, ImmutableArray.Create(model.Roles));
}

public override string ToString() => Name;
private string DebuggerDisplay => $"{Name} ({Id})";
}
}

+ 13
- 0
src/Discord.Net.Core/Entities/Guilds/IBan.cs View File

@@ -0,0 +1,13 @@
//using Discord.Rest;
using System.Diagnostics;
using Model = Discord.API.Ban;

namespace Discord
{

public interface IBan
{
IUser User { get; }
string Reason { get; }
}
}

src/Discord.Net/Entities/Guilds/IGuild.cs → src/Discord.Net.Core/Entities/Guilds/IGuild.cs View File

@@ -6,7 +6,7 @@ using Discord.Audio;

namespace Discord
{
public interface IGuild : IDeletable, ISnowflakeEntity, IUpdateable
public interface IGuild : IDeletable, ISnowflakeEntity
{
/// <summary> Gets the name of this guild. </summary>
string Name { get; }
@@ -20,8 +20,12 @@ namespace Discord
MfaLevel MfaLevel { get; }
/// <summary> Gets the level of requirements a user must fulfill before being allowed to post messages in this guild. </summary>
VerificationLevel VerificationLevel { get; }
/// <summary> Returns the id of this guild's icon, or null if one is not set. </summary>
string IconId { get; }
/// <summary> Returns the url to this guild's icon, or null if one is not set. </summary>
string IconUrl { get; }
/// <summary> Returns the id of this guild's splash image, or null if one is not set. </summary>
string SplashId { get; }
/// <summary> Returns the url to this guild's splash image, or null if one is not set. </summary>
string SplashUrl { get; }
/// <summary> Returns true if this guild is currently connected and ready to be used. Only applies to the WebSocket client. </summary>
@@ -48,6 +52,7 @@ namespace Discord
IReadOnlyCollection<string> Features { get; }
/// <summary> Gets a collection of all roles in this guild. </summary>
IReadOnlyCollection<IRole> Roles { get; }
IReadOnlyCollection<IGuildUser> CachedUsers { get; }

/// <summary> Modifies this guild. </summary>
Task ModifyAsync(Action<ModifyGuildParams> func);
@@ -61,7 +66,7 @@ namespace Discord
Task LeaveAsync();

/// <summary> Gets a collection of all users banned on this guild. </summary>
Task<IReadOnlyCollection<Ban>> GetBansAsync();
Task<IReadOnlyCollection<IBan>> GetBansAsync();
/// <summary> Bans the provided user from this guild and optionally prunes their recent messages. </summary>
Task AddBanAsync(IUser user, int pruneDays = 0);
/// <summary> Bans the provided user id from this guild and optionally prunes their recent messages. </summary>
@@ -75,11 +80,15 @@ namespace Discord
Task<IReadOnlyCollection<IGuildChannel>> GetChannelsAsync();
/// <summary> Gets the channel in this guild with the provided id, or null if not found. </summary>
Task<IGuildChannel> GetChannelAsync(ulong id);
IGuildChannel GetCachedChannel(ulong id);
/// <summary> Creates a new text channel. </summary>
Task<ITextChannel> CreateTextChannelAsync(string name);
/// <summary> Creates a new voice channel. </summary>
Task<IVoiceChannel> CreateVoiceChannelAsync(string name);

Task<IReadOnlyCollection<IGuildIntegration>> GetIntegrationsAsync();
Task<IGuildIntegration> CreateIntegrationAsync(ulong id, string type);

/// <summary> Gets a collection of all invites to this guild. </summary>
Task<IReadOnlyCollection<IInviteMetadata>> GetInvitesAsync();

@@ -92,9 +101,10 @@ namespace Discord
Task<IReadOnlyCollection<IGuildUser>> GetUsersAsync();
/// <summary> Gets the user in this guild with the provided id, or null if not found. </summary>
Task<IGuildUser> GetUserAsync(ulong id);
IGuildUser GetCachedUser(ulong id);
/// <summary> Gets the current user for this guild. </summary>
Task<IGuildUser> GetCurrentUserAsync();
/// <summary> Downloads all users for this guild if the current list is incomplete. Only applies to the WebSocket client. </summary>
/// <summary> Downloads all users for this guild if the current list is incomplete. </summary>
Task DownloadUsersAsync();
/// <summary> Removes all users from this guild if they have not logged on in a provided number of days or, if simulate is true, returns the number of users that would be removed. </summary>
Task<int> PruneUsersAsync(int days = 30, bool simulate = false);

src/Discord.Net/Entities/Guilds/IGuildIntegration.cs → src/Discord.Net.Core/Entities/Guilds/IGuildIntegration.cs View File

@@ -2,7 +2,6 @@

namespace Discord
{
//TODO: Add docstrings
public interface IGuildIntegration
{
ulong Id { get; }
@@ -15,8 +14,8 @@ namespace Discord
DateTimeOffset SyncedAt { get; }
IntegrationAccount Account { get; }

IGuild Guild { get; }
ulong GuildId { get; }
ulong RoleId { get; }
IUser User { get; }
IRole Role { get; }
}
}

src/Discord.Net/Entities/Guilds/IUserGuild.cs → src/Discord.Net.Core/Entities/Guilds/IUserGuild.cs View File


src/Discord.Net/Entities/Guilds/IVoiceRegion.cs → src/Discord.Net.Core/Entities/Guilds/IVoiceRegion.cs View File


src/Discord.Net/Entities/Guilds/IntegrationAccount.cs → src/Discord.Net.Core/Entities/Guilds/IntegrationAccount.cs View File


src/Discord.Net/Entities/Guilds/MfaLevel.cs → src/Discord.Net.Core/Entities/Guilds/MfaLevel.cs View File


src/Discord.Net/Entities/Guilds/VerificationLevel.cs → src/Discord.Net.Core/Entities/Guilds/VerificationLevel.cs View File


src/Discord.Net/Entities/IApplication.cs → src/Discord.Net.Core/Entities/IApplication.cs View File

@@ -1,6 +1,6 @@
namespace Discord
{
public interface IApplication : ISnowflakeEntity, IUpdateable
public interface IApplication : ISnowflakeEntity
{
string Name { get; }
string Description { get; }

src/Discord.Net/Entities/IDeletable.cs → src/Discord.Net.Core/Entities/IDeletable.cs View File


+ 15
- 0
src/Discord.Net.Core/Entities/IEntity.cs View File

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

namespace Discord
{
public interface IEntity<TId>
where TId : IEquatable<TId>
{
/// <summary> Gets the IDiscordClient that created this object. </summary>
IDiscordClient Discord { get; }

/// <summary> Gets the unique identifier for this object. </summary>
TId Id { get; }

}
}

src/Discord.Net/Entities/IMentionable.cs → src/Discord.Net.Core/Entities/IMentionable.cs View File


+ 6
- 0
src/Discord.Net.Core/Entities/ISnowflakeEntity.cs View File

@@ -0,0 +1,6 @@
namespace Discord
{
public interface ISnowflakeEntity : IEntity<ulong>
{
}
}

src/Discord.Net/Entities/IUpdateable.cs → src/Discord.Net.Core/Entities/IUpdateable.cs View File


src/Discord.Net/Entities/Invites/IInvite.cs → src/Discord.Net.Core/Entities/Invites/IInvite.cs View File


src/Discord.Net/Entities/Invites/IInviteMetadata.cs → src/Discord.Net.Core/Entities/Invites/IInviteMetadata.cs View File


src/Discord.Net/Entities/Messages/Direction.cs → src/Discord.Net.Core/Entities/Messages/Direction.cs View File


src/Discord.Net/Entities/Messages/EmbedProvider.cs → src/Discord.Net.Core/Entities/Messages/EmbedProvider.cs View File

@@ -12,7 +12,9 @@ namespace Discord
Name = name;
Url = url;
}
internal EmbedProvider(Model model)
: this(model.Name, model.Url) { }
public static EmbedProvider Create(Model model)
{
return new EmbedProvider(model.Name, model.Url);
}
}
}

src/Discord.Net/Entities/Messages/EmbedThumbnail.cs → src/Discord.Net.Core/Entities/Messages/EmbedThumbnail.cs View File

@@ -16,14 +16,11 @@ namespace Discord
Height = height;
Width = width;
}

internal EmbedThumbnail(Model model)
: this(
model.Url,
model.ProxyUrl,
model.Height.IsSpecified ? model.Height.Value : (int?)null,
model.Width.IsSpecified ? model.Width.Value : (int?)null)
public static EmbedThumbnail Create(Model model)
{
return new EmbedThumbnail(model.Url, model.ProxyUrl,
model.Height.IsSpecified ? model.Height.Value : (int?)null,
model.Width.IsSpecified ? model.Width.Value : (int?)null);
}
}
}

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

Loading…
Cancel
Save