diff --git a/README.md b/README.md index bd0ef20c7..7dc8cd788 100644 --- a/README.md +++ b/README.md @@ -16,13 +16,9 @@ Our stable builds available from NuGet through the Discord.Net metapackage: The individual components may also be installed from NuGet: - [Discord.Net.Commands](https://www.nuget.org/packages/Discord.Net.Commands/) - [Discord.Net.Rest](https://www.nuget.org/packages/Discord.Net.Rest/) -- [Discord.Net.Rpc](https://www.nuget.org/packages/Discord.Net.Rpc/) - [Discord.Net.WebSocket](https://www.nuget.org/packages/Discord.Net.WebSocket/) - [Discord.Net.Webhook](https://www.nuget.org/packages/Discord.Net.Webhook/) -The following provider is available for platforms not supporting .NET Standard 1.3: -- [Discord.Net.Providers.WS4Net](https://www.nuget.org/packages/Discord.Net.Providers.WS4Net/) - ### Unstable (MyGet) Nightly builds are available through our MyGet feed (`https://www.myget.org/F/discord-net/api/v3/index.json`). @@ -41,5 +37,4 @@ The .NET Core workload must be selected during Visual Studio installation. ## Known Issues ### WebSockets (Win7 and earlier) -.NET Core 1.1 does not support WebSockets on Win7 and earlier. It's recommended to use the Discord.Net.Providers.WS4Net package until this is resolved. -Track the issue [here](https://github.com/dotnet/corefx/issues/9503). +.NET Core 1.1 does not support WebSockets on Win7 and earlier. This issue has been fixed since the release of .NET Core 2.1. It is recommended to target .NET Core 2.1 or above for your project if you wish to run your bot on legacy platforms; alternatively, you may choose to install the [Discord.Net.Providers.WS4Net](https://www.nuget.org/packages/Discord.Net.Providers.WS4Net/) package. diff --git a/src/Discord.Net.Commands/Builders/ModuleBuilder.cs b/src/Discord.Net.Commands/Builders/ModuleBuilder.cs index 0ada5a9c2..6dc50db31 100644 --- a/src/Discord.Net.Commands/Builders/ModuleBuilder.cs +++ b/src/Discord.Net.Commands/Builders/ModuleBuilder.cs @@ -120,7 +120,7 @@ namespace Discord.Commands.Builders if (Name == null) Name = _aliases[0]; - if (TypeInfo != null) + if (TypeInfo != null && !TypeInfo.IsAbstract) { var moduleInstance = ReflectionUtils.CreateObject(TypeInfo, service, services); moduleInstance.OnModuleBuilding(service, this); diff --git a/src/Discord.Net.Commands/Builders/ParameterBuilder.cs b/src/Discord.Net.Commands/Builders/ParameterBuilder.cs index d1782d7ea..8a59c247c 100644 --- a/src/Discord.Net.Commands/Builders/ParameterBuilder.cs +++ b/src/Discord.Net.Commands/Builders/ParameterBuilder.cs @@ -45,14 +45,7 @@ namespace Discord.Commands.Builders internal void SetType(Type type) { - var readers = Command.Module.Service.GetTypeReaders(type); - if (readers != null) - TypeReader = readers.FirstOrDefault().Value; - else - TypeReader = Command.Module.Service.GetDefaultTypeReader(type); - - if (TypeReader == null) - throw new InvalidOperationException($"{type} does not have a TypeReader registered for it. Parameter: {Name} in {Command.PrimaryAlias}"); + TypeReader = GetReader(type); if (type.GetTypeInfo().IsValueType) DefaultValue = Activator.CreateInstance(type); @@ -60,7 +53,16 @@ namespace Discord.Commands.Builders type = ParameterType.GetElementType(); ParameterType = type; } - + + private TypeReader GetReader(Type type) + { + var readers = Command.Module.Service.GetTypeReaders(type); + if (readers != null) + return readers.FirstOrDefault().Value; + else + return Command.Module.Service.GetDefaultTypeReader(type); + } + public ParameterBuilder WithSummary(string summary) { Summary = summary; @@ -100,10 +102,10 @@ namespace Discord.Commands.Builders internal ParameterInfo Build(CommandInfo info) { - if (TypeReader == null) + if ((TypeReader ?? (TypeReader = GetReader(ParameterType))) == null) throw new InvalidOperationException($"No type reader found for type {ParameterType.Name}, one must be specified"); return new ParameterInfo(this, info, Command.Module.Service); } } -} \ No newline at end of file +} diff --git a/src/Discord.Net.Commands/CommandService.cs b/src/Discord.Net.Commands/CommandService.cs index 8e5297e49..6fd5d38ad 100644 --- a/src/Discord.Net.Commands/CommandService.cs +++ b/src/Discord.Net.Commands/CommandService.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; @@ -262,7 +262,7 @@ namespace Discord.Commands /// If should replace the default for if one exists. public void AddTypeReader(Type type, TypeReader reader, bool replaceDefault) { - if (replaceDefault && _defaultTypeReaders.ContainsKey(type)) + if (replaceDefault && HasDefaultTypeReader(type)) { _defaultTypeReaders.AddOrUpdate(type, reader, (k, v) => reader); if (type.GetTypeInfo().IsValueType) @@ -281,6 +281,16 @@ namespace Discord.Commands AddNullableTypeReader(type, reader); } } + internal bool HasDefaultTypeReader(Type type) + { + if (_defaultTypeReaders.ContainsKey(type)) + return true; + + var typeInfo = type.GetTypeInfo(); + if (typeInfo.IsEnum) + return true; + return _entityTypeReaders.Any(x => type == x.Item1 || typeInfo.ImplementedInterfaces.Contains(x.Item2)); + } internal void AddNullableTypeReader(Type valueType, TypeReader valueTypeReader) { var readers = _typeReaders.GetOrAdd(typeof(Nullable<>).MakeGenericType(valueType), x => new ConcurrentDictionary()); diff --git a/src/Discord.Net.Commands/Extensions/MessageExtensions.cs b/src/Discord.Net.Commands/Extensions/MessageExtensions.cs index 096b03f6b..a27c5f322 100644 --- a/src/Discord.Net.Commands/Extensions/MessageExtensions.cs +++ b/src/Discord.Net.Commands/Extensions/MessageExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Discord.Commands { @@ -43,4 +43,4 @@ namespace Discord.Commands return false; } } -} \ No newline at end of file +} diff --git a/src/Discord.Net.Commands/Results/ParseResult.cs b/src/Discord.Net.Commands/Results/ParseResult.cs index d4a9af521..3a0692b2d 100644 --- a/src/Discord.Net.Commands/Results/ParseResult.cs +++ b/src/Discord.Net.Commands/Results/ParseResult.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Diagnostics; namespace Discord.Commands @@ -53,6 +54,8 @@ namespace Discord.Commands public static ParseResult FromError(CommandError error, string reason) => new ParseResult(null, null, error, reason); + public static ParseResult FromError(Exception ex) + => FromError(CommandError.Exception, ex.Message); public static ParseResult FromError(IResult result) => new ParseResult(null, null, result.Error, result.ErrorReason); diff --git a/src/Discord.Net.Commands/Results/PreconditionGroupResult.cs b/src/Discord.Net.Commands/Results/PreconditionGroupResult.cs index 1d7f29122..ee650600a 100644 --- a/src/Discord.Net.Commands/Results/PreconditionGroupResult.cs +++ b/src/Discord.Net.Commands/Results/PreconditionGroupResult.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Diagnostics; namespace Discord.Commands @@ -18,6 +19,8 @@ namespace Discord.Commands => new PreconditionGroupResult(null, null, null); public static PreconditionGroupResult FromError(string reason, ICollection preconditions) => new PreconditionGroupResult(CommandError.UnmetPrecondition, reason, preconditions); + public static new PreconditionGroupResult FromError(Exception ex) + => new PreconditionGroupResult(CommandError.Exception, ex.Message, null); public static new PreconditionGroupResult FromError(IResult result) //needed? => new PreconditionGroupResult(result.Error, result.ErrorReason, null); diff --git a/src/Discord.Net.Commands/Results/PreconditionResult.cs b/src/Discord.Net.Commands/Results/PreconditionResult.cs index ca65a373e..01fc1a3fd 100644 --- a/src/Discord.Net.Commands/Results/PreconditionResult.cs +++ b/src/Discord.Net.Commands/Results/PreconditionResult.cs @@ -1,4 +1,5 @@ -using System.Diagnostics; +using System; +using System.Diagnostics; namespace Discord.Commands { @@ -20,6 +21,8 @@ namespace Discord.Commands => new PreconditionResult(null, null); public static PreconditionResult FromError(string reason) => new PreconditionResult(CommandError.UnmetPrecondition, reason); + public static PreconditionResult FromError(Exception ex) + => new PreconditionResult(CommandError.Exception, ex.Message); public static PreconditionResult FromError(IResult result) => new PreconditionResult(result.Error, result.ErrorReason); diff --git a/src/Discord.Net.Commands/Results/SearchResult.cs b/src/Discord.Net.Commands/Results/SearchResult.cs index 87d900d4d..6a5878ea2 100644 --- a/src/Discord.Net.Commands/Results/SearchResult.cs +++ b/src/Discord.Net.Commands/Results/SearchResult.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Diagnostics; namespace Discord.Commands @@ -26,6 +27,8 @@ namespace Discord.Commands => new SearchResult(text, commands, null, null); public static SearchResult FromError(CommandError error, string reason) => new SearchResult(null, null, error, reason); + public static SearchResult FromError(Exception ex) + => FromError(CommandError.Exception, ex.Message); public static SearchResult FromError(IResult result) => new SearchResult(null, null, result.Error, result.ErrorReason); diff --git a/src/Discord.Net.Commands/Results/TypeReaderResult.cs b/src/Discord.Net.Commands/Results/TypeReaderResult.cs index 639ca3ac1..e696dbc17 100644 --- a/src/Discord.Net.Commands/Results/TypeReaderResult.cs +++ b/src/Discord.Net.Commands/Results/TypeReaderResult.cs @@ -50,6 +50,8 @@ namespace Discord.Commands => new TypeReaderResult(values, null, null); public static TypeReaderResult FromError(CommandError error, string reason) => new TypeReaderResult(null, error, reason); + public static TypeReaderResult FromError(Exception ex) + => FromError(CommandError.Exception, ex.Message); public static TypeReaderResult FromError(IResult result) => new TypeReaderResult(null, result.Error, result.ErrorReason); diff --git a/src/Discord.Net.Core/Entities/AuditLogs/IAuditLogEntry.cs b/src/Discord.Net.Core/Entities/AuditLogs/IAuditLogEntry.cs index b85730a1d..150c59a42 100644 --- a/src/Discord.Net.Core/Entities/AuditLogs/IAuditLogEntry.cs +++ b/src/Discord.Net.Core/Entities/AuditLogs/IAuditLogEntry.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -9,7 +9,7 @@ namespace Discord /// /// Represents an entry in an audit log /// - public interface IAuditLogEntry : IEntity + public interface IAuditLogEntry : ISnowflakeEntity { /// /// The action which occured to create this entry diff --git a/src/Discord.Net.Rest/Entities/Channels/ChannelType.cs b/src/Discord.Net.Core/Entities/Channels/ChannelType.cs similarity index 100% rename from src/Discord.Net.Rest/Entities/Channels/ChannelType.cs rename to src/Discord.Net.Core/Entities/Channels/ChannelType.cs diff --git a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs index 4c1c274d0..bbe7051cb 100644 --- a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs +++ b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs @@ -120,6 +120,15 @@ namespace Discord /// Gets a collection of all invites to this guild. Task> GetInvitesAsync(RequestOptions options = null); + /// + /// Gets the vanity invite URL of this guild. + /// + /// The options to be used when sending the request. + /// + /// An awaitable containing the partial metadata of the vanity invite found within + /// this guild. + /// + Task GetVanityInviteAsync(RequestOptions options = null); /// Gets the role in this guild with the provided id, or null if not found. IRole GetRole(ulong id); @@ -140,7 +149,7 @@ namespace Discord Task PruneUsersAsync(int days = 30, bool simulate = false, RequestOptions options = null); /// Gets the specified number of audit log entries for this guild. - Task> GetAuditLogAsync(int limit = DiscordConfig.MaxAuditLogEntriesPerBatch, + Task> GetAuditLogsAsync(int limit = DiscordConfig.MaxAuditLogEntriesPerBatch, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); /// Gets the webhook in this guild with the provided id, or null if not found. diff --git a/src/Discord.Net.Core/Entities/Invites/IInvite.cs b/src/Discord.Net.Core/Entities/Invites/IInvite.cs index 0ebb65679..1ab26de8f 100644 --- a/src/Discord.Net.Core/Entities/Invites/IInvite.cs +++ b/src/Discord.Net.Core/Entities/Invites/IInvite.cs @@ -1,5 +1,3 @@ -using System.Threading.Tasks; - namespace Discord { public interface IInvite : IEntity, IDeletable @@ -11,6 +9,8 @@ namespace Discord /// Gets the channel this invite is linked to. IChannel Channel { get; } + /// Gets the type of the channel this invite is linked to. + ChannelType ChannelType { get; } /// Gets the id of the channel this invite is linked to. ulong ChannelId { get; } /// Gets the name of the channel this invite is linked to. @@ -19,7 +19,7 @@ namespace Discord /// Gets the guild this invite is linked to. IGuild Guild { get; } /// Gets the id of the guild this invite is linked to. - ulong GuildId { get; } + ulong? GuildId { get; } /// Gets the name of the guild this invite is linked to. string GuildName { get; } /// Gets the approximated count of online members in the guild. diff --git a/src/Discord.Net.Core/Entities/Invites/IInviteMetadata.cs b/src/Discord.Net.Core/Entities/Invites/IInviteMetadata.cs index 1136e1678..0e026ab62 100644 --- a/src/Discord.Net.Core/Entities/Invites/IInviteMetadata.cs +++ b/src/Discord.Net.Core/Entities/Invites/IInviteMetadata.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Discord { @@ -15,8 +15,8 @@ namespace Discord /// Gets the max amount of times this invite may be used, or null if there is no limit. int? MaxUses { get; } /// Gets the amount of times this invite has been used. - int Uses { get; } + int? Uses { get; } /// Gets when this invite was created. - DateTimeOffset CreatedAt { get; } + DateTimeOffset? CreatedAt { get; } } -} \ No newline at end of file +} diff --git a/src/Discord.Net.Core/Entities/Permissions/ChannelPermission.cs b/src/Discord.Net.Core/Entities/Permissions/ChannelPermission.cs index 740b6c30b..0fbd22c4e 100644 --- a/src/Discord.Net.Core/Entities/Permissions/ChannelPermission.cs +++ b/src/Discord.Net.Core/Entities/Permissions/ChannelPermission.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Discord { @@ -30,6 +30,7 @@ namespace Discord DeafenMembers = 0x00_80_00_00, MoveMembers = 0x01_00_00_00, UseVAD = 0x02_00_00_00, + PrioritySpeaker = 0x00_00_01_00, // More General ManageRoles = 0x10_00_00_00, diff --git a/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs b/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs index fa2dfb576..61d588f8a 100644 --- a/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs +++ b/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs @@ -12,7 +12,7 @@ namespace Discord /// Gets a ChannelPermissions that grants all permissions for text channels. public static readonly ChannelPermissions Text = new ChannelPermissions(0b01100_0000000_1111111110001_010001); /// Gets a ChannelPermissions that grants all permissions for voice channels. - public static readonly ChannelPermissions Voice = new ChannelPermissions(0b00100_1111110_0000000010000_010001); + public static readonly ChannelPermissions Voice = new ChannelPermissions(0b00100_1111110_0000000010100_010001); /// Gets a ChannelPermissions that grants all permissions for category channels. public static readonly ChannelPermissions Category = new ChannelPermissions(0b01100_1111110_1111111110001_010001); /// Gets a ChannelPermissions that grants all permissions for direct message channels. @@ -78,6 +78,8 @@ namespace Discord public bool MoveMembers => Permissions.GetValue(RawValue, ChannelPermission.MoveMembers); /// If True, a user may use voice-activity-detection rather than push-to-talk. public bool UseVAD => Permissions.GetValue(RawValue, ChannelPermission.UseVAD); + /// If True, a user may use priority speaker in a voice channel. + public bool PrioritySpeaker => Permissions.GetValue(RawValue, ChannelPermission.PrioritySpeaker); /// If True, a user may adjust role permissions. This also implictly grants all other permissions. public bool ManageRoles => Permissions.GetValue(RawValue, ChannelPermission.ManageRoles); @@ -106,6 +108,7 @@ namespace Discord bool? deafenMembers = null, bool? moveMembers = null, bool? useVoiceActivation = null, + bool? prioritySpeaker = null, bool? manageRoles = null, bool? manageWebhooks = null) { @@ -129,6 +132,7 @@ namespace Discord Permissions.SetValue(ref value, deafenMembers, ChannelPermission.DeafenMembers); Permissions.SetValue(ref value, moveMembers, ChannelPermission.MoveMembers); Permissions.SetValue(ref value, useVoiceActivation, ChannelPermission.UseVAD); + Permissions.SetValue(ref value, prioritySpeaker, ChannelPermission.PrioritySpeaker); Permissions.SetValue(ref value, manageRoles, ChannelPermission.ManageRoles); Permissions.SetValue(ref value, manageWebhooks, ChannelPermission.ManageWebhooks); @@ -155,11 +159,12 @@ namespace Discord bool deafenMembers = false, bool moveMembers = false, bool useVoiceActivation = false, + bool prioritySpeaker = false, bool manageRoles = false, bool manageWebhooks = false) : this(0, createInstantInvite, manageChannel, addReactions, viewChannel, sendMessages, sendTTSMessages, manageMessages, embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect, - speak, muteMembers, deafenMembers, moveMembers, useVoiceActivation, manageRoles, manageWebhooks) + speak, muteMembers, deafenMembers, moveMembers, useVoiceActivation, prioritySpeaker, manageRoles, manageWebhooks) { } /// Creates a new ChannelPermissions from this one, changing the provided non-null permissions. @@ -182,6 +187,7 @@ namespace Discord bool? deafenMembers = null, bool? moveMembers = null, bool? useVoiceActivation = null, + bool? prioritySpeaker = null, bool? manageRoles = null, bool? manageWebhooks = null) => new ChannelPermissions(RawValue, @@ -203,6 +209,7 @@ namespace Discord deafenMembers, moveMembers, useVoiceActivation, + prioritySpeaker, manageRoles, manageWebhooks); diff --git a/src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs b/src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs index e90b4269e..13a9e32b1 100644 --- a/src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs +++ b/src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs @@ -35,6 +35,7 @@ namespace Discord DeafenMembers = 0x00_80_00_00, MoveMembers = 0x01_00_00_00, UseVAD = 0x02_00_00_00, + PrioritySpeaker = 0x00_00_01_00, // General 2 ChangeNickname = 0x04_00_00_00, diff --git a/src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs b/src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs index 7704a62d6..c9cb90ec8 100644 --- a/src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs +++ b/src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs @@ -12,7 +12,7 @@ namespace Discord /// Gets a GuildPermissions that grants all guild permissions for webhook users. public static readonly GuildPermissions Webhook = new GuildPermissions(0b00000_0000000_0001101100000_000000); /// Gets a GuildPermissions that grants all guild permissions. - public static readonly GuildPermissions All = new GuildPermissions(0b11111_1111110_1111111110011_111111); + public static readonly GuildPermissions All = new GuildPermissions(0b11111_1111110_1111111110111_111111); /// Gets a packed value representing all the permissions in this GuildPermissions. public ulong RawValue { get; } @@ -69,6 +69,8 @@ namespace Discord public bool MoveMembers => Permissions.GetValue(RawValue, GuildPermission.MoveMembers); /// If True, a user may use voice-activity-detection rather than push-to-talk. public bool UseVAD => Permissions.GetValue(RawValue, GuildPermission.UseVAD); + /// If True, a user may use priority speaker in a voice channel. + public bool PrioritySpeaker => Permissions.GetValue(RawValue, ChannelPermission.PrioritySpeaker); /// If True, a user may change their own nickname. public bool ChangeNickname => Permissions.GetValue(RawValue, GuildPermission.ChangeNickname); @@ -108,6 +110,7 @@ namespace Discord bool? deafenMembers = null, bool? moveMembers = null, bool? useVoiceActivation = null, + bool? prioritySpeaker = null, bool? changeNickname = null, bool? manageNicknames = null, bool? manageRoles = null, @@ -139,6 +142,7 @@ namespace Discord Permissions.SetValue(ref value, deafenMembers, GuildPermission.DeafenMembers); Permissions.SetValue(ref value, moveMembers, GuildPermission.MoveMembers); Permissions.SetValue(ref value, useVoiceActivation, GuildPermission.UseVAD); + Permissions.SetValue(ref value, prioritySpeaker, GuildPermission.PrioritySpeaker); Permissions.SetValue(ref value, changeNickname, GuildPermission.ChangeNickname); Permissions.SetValue(ref value, manageNicknames, GuildPermission.ManageNicknames); Permissions.SetValue(ref value, manageRoles, GuildPermission.ManageRoles); @@ -173,6 +177,7 @@ namespace Discord bool deafenMembers = false, bool moveMembers = false, bool useVoiceActivation = false, + bool prioritySpeaker = false, bool changeNickname = false, bool manageNicknames = false, bool manageRoles = false, @@ -203,6 +208,7 @@ namespace Discord deafenMembers: deafenMembers, moveMembers: moveMembers, useVoiceActivation: useVoiceActivation, + prioritySpeaker: prioritySpeaker, changeNickname: changeNickname, manageNicknames: manageNicknames, manageWebhooks: manageWebhooks, @@ -234,6 +240,7 @@ namespace Discord bool? deafenMembers = null, bool? moveMembers = null, bool? useVoiceActivation = null, + bool? prioritySpeaker = null, bool? changeNickname = null, bool? manageNicknames = null, bool? manageRoles = null, @@ -242,7 +249,7 @@ namespace Discord => new GuildPermissions(RawValue, createInstantInvite, kickMembers, banMembers, administrator, manageChannels, manageGuild, addReactions, viewAuditLog, viewChannel, sendMessages, sendTTSMessages, manageMessages, embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers, moveMembers, - useVoiceActivation, changeNickname, manageNicknames, manageRoles, manageWebhooks, manageEmojis); + useVoiceActivation, prioritySpeaker, changeNickname, manageNicknames, manageRoles, manageWebhooks, manageEmojis); public bool Has(GuildPermission permission) => Permissions.GetValue(RawValue, permission); diff --git a/src/Discord.Net.Core/Extensions/MessageExtensions.cs b/src/Discord.Net.Core/Extensions/MessageExtensions.cs new file mode 100644 index 000000000..c53ef9053 --- /dev/null +++ b/src/Discord.Net.Core/Extensions/MessageExtensions.cs @@ -0,0 +1,11 @@ +namespace Discord +{ + public static class MessageExtensions + { + public static string GetJumpUrl(this IMessage msg) + { + var channel = msg.Channel; + return $"https://discordapp.com/channels/{(channel is IDMChannel ? "@me" : $"{(channel as ITextChannel).GuildId}")}/{channel.Id}/{msg.Id}"; + } + } +} diff --git a/src/Discord.Net.Core/IDiscordClient.cs b/src/Discord.Net.Core/IDiscordClient.cs index 083c0b512..a383c37da 100644 --- a/src/Discord.Net.Core/IDiscordClient.cs +++ b/src/Discord.Net.Core/IDiscordClient.cs @@ -27,7 +27,7 @@ namespace Discord Task> GetGuildsAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); Task CreateGuildAsync(string name, IVoiceRegion region, Stream jpegIcon = null, RequestOptions options = null); - Task GetInviteAsync(string inviteId, bool withCount = false, RequestOptions options = null); + Task GetInviteAsync(string inviteId, RequestOptions options = null); Task GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); Task GetUserAsync(string username, string discriminator, RequestOptions options = null); diff --git a/src/Discord.Net.Rest/API/Common/Invite.cs b/src/Discord.Net.Rest/API/Common/Invite.cs index 1b35da870..649bc37ec 100644 --- a/src/Discord.Net.Rest/API/Common/Invite.cs +++ b/src/Discord.Net.Rest/API/Common/Invite.cs @@ -8,7 +8,7 @@ namespace Discord.API [JsonProperty("code")] public string Code { get; set; } [JsonProperty("guild")] - public InviteGuild Guild { get; set; } + public Optional Guild { get; set; } [JsonProperty("channel")] public InviteChannel Channel { get; set; } [JsonProperty("approximate_presence_count")] diff --git a/src/Discord.Net.Rest/API/Common/InviteChannel.cs b/src/Discord.Net.Rest/API/Common/InviteChannel.cs index ca9699067..f8f2a34f2 100644 --- a/src/Discord.Net.Rest/API/Common/InviteChannel.cs +++ b/src/Discord.Net.Rest/API/Common/InviteChannel.cs @@ -1,4 +1,4 @@ -#pragma warning disable CS1591 +#pragma warning disable CS1591 using Newtonsoft.Json; namespace Discord.API @@ -10,6 +10,6 @@ namespace Discord.API [JsonProperty("name")] public string Name { get; set; } [JsonProperty("type")] - public string Type { get; set; } + public int Type { get; set; } } } diff --git a/src/Discord.Net.Rest/API/Common/InviteMetadata.cs b/src/Discord.Net.Rest/API/Common/InviteMetadata.cs index 586307523..ca019b79b 100644 --- a/src/Discord.Net.Rest/API/Common/InviteMetadata.cs +++ b/src/Discord.Net.Rest/API/Common/InviteMetadata.cs @@ -1,4 +1,4 @@ -#pragma warning disable CS1591 +#pragma warning disable CS1591 using Newtonsoft.Json; using System; @@ -9,15 +9,15 @@ namespace Discord.API [JsonProperty("inviter")] public User Inviter { get; set; } [JsonProperty("uses")] - public int Uses { get; set; } + public Optional Uses { get; set; } [JsonProperty("max_uses")] - public int MaxUses { get; set; } + public Optional MaxUses { get; set; } [JsonProperty("max_age")] - public int MaxAge { get; set; } + public Optional MaxAge { get; set; } [JsonProperty("temporary")] public bool Temporary { get; set; } [JsonProperty("created_at")] - public DateTimeOffset CreatedAt { get; set; } + public Optional CreatedAt { get; set; } [JsonProperty("revoked")] public bool Revoked { get; set; } } diff --git a/src/Discord.Net.Rest/API/Rest/GetInviteParams.cs b/src/Discord.Net.Rest/API/Rest/GetInviteParams.cs deleted file mode 100644 index cb8d8f7fe..000000000 --- a/src/Discord.Net.Rest/API/Rest/GetInviteParams.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Discord.API.Rest -{ - internal class GetInviteParams - { - public Optional WithCounts { get; set; } - } -} diff --git a/src/Discord.Net.Rest/BaseDiscordClient.cs b/src/Discord.Net.Rest/BaseDiscordClient.cs index db8e2e691..f8642b96c 100644 --- a/src/Discord.Net.Rest/BaseDiscordClient.cs +++ b/src/Discord.Net.Rest/BaseDiscordClient.cs @@ -148,7 +148,7 @@ namespace Discord.Rest Task> IDiscordClient.GetConnectionsAsync(RequestOptions options) => Task.FromResult>(ImmutableArray.Create()); - Task IDiscordClient.GetInviteAsync(string inviteId, bool withCount, RequestOptions options) + Task IDiscordClient.GetInviteAsync(string inviteId, RequestOptions options) => Task.FromResult(null); Task IDiscordClient.GetGuildAsync(ulong id, CacheMode mode, RequestOptions options) diff --git a/src/Discord.Net.Rest/ClientHelper.cs b/src/Discord.Net.Rest/ClientHelper.cs index 0bba0d2c4..d8f481d15 100644 --- a/src/Discord.Net.Rest/ClientHelper.cs +++ b/src/Discord.Net.Rest/ClientHelper.cs @@ -51,13 +51,9 @@ namespace Discord.Rest } public static async Task GetInviteAsync(BaseDiscordClient client, - string inviteId, bool withCount, RequestOptions options) + string inviteId, RequestOptions options) { - var args = new GetInviteParams - { - WithCounts = withCount - }; - var model = await client.ApiClient.GetInviteAsync(inviteId, args, options).ConfigureAwait(false); + var model = await client.ApiClient.GetInviteAsync(inviteId, options).ConfigureAwait(false); if (model != null) return RestInviteMetadata.Create(client, null, null, model); return null; diff --git a/src/Discord.Net.Rest/DiscordRestApiClient.cs b/src/Discord.Net.Rest/DiscordRestApiClient.cs index 85e04f962..2236dbbf8 100644 --- a/src/Discord.Net.Rest/DiscordRestApiClient.cs +++ b/src/Discord.Net.Rest/DiscordRestApiClient.cs @@ -906,7 +906,7 @@ namespace Discord.API } //Guild Invites - public async Task GetInviteAsync(string inviteId, GetInviteParams args, RequestOptions options = null) + public async Task GetInviteAsync(string inviteId, RequestOptions options = null) { Preconditions.NotNullOrEmpty(inviteId, nameof(inviteId)); options = RequestOptions.CreateOrClone(options); @@ -919,14 +919,20 @@ namespace Discord.API if (index >= 0) inviteId = inviteId.Substring(index + 1); - var withCounts = args.WithCounts.GetValueOrDefault(false); - try { - return await SendAsync("GET", () => $"invites/{inviteId}?with_counts={withCounts}", new BucketIds(), options: options).ConfigureAwait(false); + return await SendAsync("GET", () => $"invites/{inviteId}?with_counts=true", new BucketIds(), options: options).ConfigureAwait(false); } catch (HttpException ex) when (ex.HttpCode == HttpStatusCode.NotFound) { return null; } } + public async Task GetVanityInviteAsync(ulong guildId, RequestOptions options = null) + { + Preconditions.NotEqual(guildId, 0, nameof(guildId)); + options = RequestOptions.CreateOrClone(options); + + var ids = new BucketIds(guildId: guildId); + return await SendAsync("GET", () => $"guilds/{guildId}/vanity-url", ids, options: options).ConfigureAwait(false); + } public async Task> GetGuildInvitesAsync(ulong guildId, RequestOptions options = null) { Preconditions.NotEqual(guildId, 0, nameof(guildId)); diff --git a/src/Discord.Net.Rest/DiscordRestClient.cs b/src/Discord.Net.Rest/DiscordRestClient.cs index 3a596624d..d4dee9f0a 100644 --- a/src/Discord.Net.Rest/DiscordRestClient.cs +++ b/src/Discord.Net.Rest/DiscordRestClient.cs @@ -56,8 +56,8 @@ namespace Discord.Rest => ClientHelper.GetConnectionsAsync(this, options); /// - public Task GetInviteAsync(string inviteId, bool withCount = false, RequestOptions options = null) - => ClientHelper.GetInviteAsync(this, inviteId, withCount, options); + public Task GetInviteAsync(string inviteId, RequestOptions options = null) + => ClientHelper.GetInviteAsync(this, inviteId, options); /// public Task GetGuildAsync(ulong id, RequestOptions options = null) @@ -131,8 +131,8 @@ namespace Discord.Rest async Task> IDiscordClient.GetConnectionsAsync(RequestOptions options) => await GetConnectionsAsync(options).ConfigureAwait(false); - async Task IDiscordClient.GetInviteAsync(string inviteId, bool withCount, RequestOptions options) - => await GetInviteAsync(inviteId, withCount, options).ConfigureAwait(false); + async Task IDiscordClient.GetInviteAsync(string inviteId, RequestOptions options) + => await GetInviteAsync(inviteId, options).ConfigureAwait(false); async Task IDiscordClient.GetGuildAsync(ulong id, CacheMode mode, RequestOptions options) { diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberInfo.cs b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberInfo.cs new file mode 100644 index 000000000..b0a1a8e5a --- /dev/null +++ b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberInfo.cs @@ -0,0 +1,18 @@ +namespace Discord.Rest +{ + public struct MemberInfo + { + internal MemberInfo(string nick, bool? deaf, bool? mute, string avatar_hash) + { + Nickname = nick; + Deaf = deaf; + Mute = mute; + AvatarHash = avatar_hash; + } + + public string Nickname { get; } + public bool? Deaf { get; } + public bool? Mute { get; } + public string AvatarHash { get; } + } +} diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberUpdateAuditLogData.cs b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberUpdateAuditLogData.cs index 38f078848..40a3ba681 100644 --- a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberUpdateAuditLogData.cs +++ b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberUpdateAuditLogData.cs @@ -8,28 +8,42 @@ namespace Discord.Rest { public class MemberUpdateAuditLogData : IAuditLogData { - private MemberUpdateAuditLogData(IUser target, string newNick, string oldNick) + private MemberUpdateAuditLogData(IUser target, MemberInfo before, MemberInfo after) { Target = target; - NewNick = newNick; - OldNick = oldNick; + Before = before; + After = after; } internal static MemberUpdateAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry) { - var changes = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "nick"); + var changes = entry.Changes; - var newNick = changes.NewValue?.ToObject(); - var oldNick = changes.OldValue?.ToObject(); + var nickModel = changes.FirstOrDefault(x => x.ChangedProperty == "nick"); + var deafModel = changes.FirstOrDefault(x => x.ChangedProperty == "deaf"); + var muteModel = changes.FirstOrDefault(x => x.ChangedProperty == "mute"); + var avatarModel = changes.FirstOrDefault(x => x.ChangedProperty == "avatar_hash"); + + string oldNick = nickModel?.OldValue?.ToObject(), + newNick = nickModel?.NewValue?.ToObject(); + bool? oldDeaf = deafModel?.OldValue?.ToObject(), + newDeaf = deafModel?.NewValue?.ToObject(); + bool? oldMute = muteModel?.OldValue?.ToObject(), + newMute = muteModel?.NewValue?.ToObject(); + string oldAvatar = avatarModel?.OldValue?.ToObject(), + newAvatar = avatarModel?.NewValue?.ToObject(); var targetInfo = log.Users.FirstOrDefault(x => x.Id == entry.TargetId); var user = RestUser.Create(discord, targetInfo); - return new MemberUpdateAuditLogData(user, newNick, oldNick); + var before = new MemberInfo(oldNick, oldDeaf, oldMute, oldAvatar); + var after = new MemberInfo(newNick, newDeaf, newMute, newAvatar); + + return new MemberUpdateAuditLogData(user, before, after); } public IUser Target { get; } - public string NewNick { get; } - public string OldNick { get; } + public MemberInfo Before { get; } + public MemberInfo After { get; } } } diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/RestAuditLogEntry.cs b/src/Discord.Net.Rest/Entities/AuditLogs/RestAuditLogEntry.cs index 9e30a5014..d01e964ae 100644 --- a/src/Discord.Net.Rest/Entities/AuditLogs/RestAuditLogEntry.cs +++ b/src/Discord.Net.Rest/Entities/AuditLogs/RestAuditLogEntry.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System; +using System.Linq; using Model = Discord.API.AuditLog; using EntryModel = Discord.API.AuditLogEntry; @@ -26,6 +27,8 @@ namespace Discord.Rest return new RestAuditLogEntry(discord, fullLog, model, user); } + /// + public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); /// public ActionType Action { get; } /// diff --git a/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs b/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs index c76b41a91..4bd0e9972 100644 --- a/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs +++ b/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs @@ -210,6 +210,12 @@ namespace Discord.Rest var models = await client.ApiClient.GetGuildInvitesAsync(guild.Id, options).ConfigureAwait(false); return models.Select(x => RestInviteMetadata.Create(client, guild, null, x)).ToImmutableArray(); } + public static async Task GetVanityInviteAsync(IGuild guild, BaseDiscordClient client, + RequestOptions options) + { + var model = await client.ApiClient.GetVanityInviteAsync(guild.Id, options).ConfigureAwait(false); + return RestInviteMetadata.Create(client, guild, null, model); + } //Roles public static async Task CreateRoleAsync(IGuild guild, BaseDiscordClient client, diff --git a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs index 357e22c85..9bf13fa07 100644 --- a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs +++ b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs @@ -238,6 +238,15 @@ namespace Discord.Rest //Invites public Task> GetInvitesAsync(RequestOptions options = null) => GuildHelper.GetInvitesAsync(this, Discord, options); + /// + /// Gets the vanity invite URL of this guild. + /// + /// The options to be used when sending the request. + /// + /// A partial metadata of the vanity invite found within this guild. + /// + public Task GetVanityInviteAsync(RequestOptions options = null) + => GuildHelper.GetVanityInviteAsync(this, Discord, options); //Roles public RestRole GetRole(ulong id) @@ -397,6 +406,9 @@ namespace Discord.Rest async Task> IGuild.GetInvitesAsync(RequestOptions options) => await GetInvitesAsync(options).ConfigureAwait(false); + /// + async Task IGuild.GetVanityInviteAsync(RequestOptions options) + => await GetVanityInviteAsync(options).ConfigureAwait(false); IRole IGuild.GetRole(ulong id) => GetRole(id); @@ -433,7 +445,7 @@ namespace Discord.Rest } Task IGuild.DownloadUsersAsync() { throw new NotSupportedException(); } - async Task> IGuild.GetAuditLogAsync(int limit, CacheMode cacheMode, RequestOptions options) + async Task> IGuild.GetAuditLogsAsync(int limit, CacheMode cacheMode, RequestOptions options) { if (cacheMode == CacheMode.AllowDownload) return (await GetAuditLogsAsync(limit, options).FlattenAsync().ConfigureAwait(false)).ToImmutableArray(); diff --git a/src/Discord.Net.Rest/Entities/Invites/RestInvite.cs b/src/Discord.Net.Rest/Entities/Invites/RestInvite.cs index 18698c626..050f117fb 100644 --- a/src/Discord.Net.Rest/Entities/Invites/RestInvite.cs +++ b/src/Discord.Net.Rest/Entities/Invites/RestInvite.cs @@ -1,7 +1,6 @@ using System; using System.Diagnostics; using System.Threading.Tasks; -using Discord.API.Rest; using Model = Discord.API.Invite; namespace Discord.Rest @@ -9,14 +8,15 @@ namespace Discord.Rest [DebuggerDisplay(@"{DebuggerDisplay,nq}")] public class RestInvite : RestEntity, IInvite, IUpdateable { + public ChannelType ChannelType { get; private set; } public string ChannelName { get; private set; } public string GuildName { get; private set; } public int? PresenceCount { get; private set; } public int? MemberCount { get; private set; } public ulong ChannelId { get; private set; } - public ulong GuildId { get; private set; } - internal IChannel Channel { get; private set; } - internal IGuild Guild { get; private set; } + public ulong? GuildId { get; private set; } + internal IChannel Channel { get; } + internal IGuild Guild { get; } public string Code => Id; public string Url => $"{DiscordConfig.InviteUrl}{Code}"; @@ -35,20 +35,18 @@ namespace Discord.Rest } internal void Update(Model model) { - GuildId = model.Guild.Id; + GuildId = model.Guild.IsSpecified ? model.Guild.Value.Id : default(ulong?); ChannelId = model.Channel.Id; - GuildName = model.Guild.Name; + GuildName = model.Guild.IsSpecified ? model.Guild.Value.Name : null; ChannelName = model.Channel.Name; MemberCount = model.MemberCount.IsSpecified ? model.MemberCount.Value : null; PresenceCount = model.PresenceCount.IsSpecified ? model.PresenceCount.Value : null; + ChannelType = (ChannelType)model.Channel.Type; } public async Task UpdateAsync(RequestOptions options = null) { - var args = new GetInviteParams(); - if (MemberCount != null || PresenceCount != null) - args.WithCounts = true; - var model = await Discord.ApiClient.GetInviteAsync(Code, args, options).ConfigureAwait(false); + var model = await Discord.ApiClient.GetInviteAsync(Code, options).ConfigureAwait(false); Update(model); } public Task DeleteAsync(RequestOptions options = null) diff --git a/src/Discord.Net.Rest/Entities/Invites/RestInviteMetadata.cs b/src/Discord.Net.Rest/Entities/Invites/RestInviteMetadata.cs index 42aeb40aa..c7236be58 100644 --- a/src/Discord.Net.Rest/Entities/Invites/RestInviteMetadata.cs +++ b/src/Discord.Net.Rest/Entities/Invites/RestInviteMetadata.cs @@ -1,20 +1,20 @@ -using System; +using System; using Model = Discord.API.InviteMetadata; namespace Discord.Rest { public class RestInviteMetadata : RestInvite, IInviteMetadata { - private long _createdAtTicks; + private long? _createdAtTicks; public bool IsRevoked { get; private set; } public bool IsTemporary { get; private set; } public int? MaxAge { get; private set; } public int? MaxUses { get; private set; } - public int Uses { get; private set; } + public int? Uses { get; private set; } public RestUser Inviter { get; private set; } - public DateTimeOffset CreatedAt => DateTimeUtils.FromTicks(_createdAtTicks); + public DateTimeOffset? CreatedAt => DateTimeUtils.FromTicks(_createdAtTicks); internal RestInviteMetadata(BaseDiscordClient discord, IGuild guild, IChannel channel, string id) : base(discord, guild, channel, id) @@ -32,10 +32,10 @@ namespace Discord.Rest Inviter = model.Inviter != null ? RestUser.Create(Discord, model.Inviter) : null; IsRevoked = model.Revoked; IsTemporary = model.Temporary; - MaxAge = model.MaxAge != 0 ? model.MaxAge : (int?)null; - MaxUses = model.MaxUses; - Uses = model.Uses; - _createdAtTicks = model.CreatedAt.UtcTicks; + MaxAge = model.MaxAge.IsSpecified ? model.MaxAge.Value : (int?)null; + MaxUses = model.MaxUses.IsSpecified ? model.MaxUses.Value : (int?)null; + Uses = model.Uses.IsSpecified ? model.Uses.Value : (int?)null; + _createdAtTicks = model.CreatedAt.IsSpecified ? model.CreatedAt.Value.UtcTicks : (long?)null; } IUser IInviteMetadata.Inviter => Inviter; diff --git a/src/Discord.Net.WebSocket/BaseSocketClient.cs b/src/Discord.Net.WebSocket/BaseSocketClient.cs index fb82fe14a..a7d590b42 100644 --- a/src/Discord.Net.WebSocket/BaseSocketClient.cs +++ b/src/Discord.Net.WebSocket/BaseSocketClient.cs @@ -55,8 +55,8 @@ namespace Discord.WebSocket public Task> GetConnectionsAsync(RequestOptions options = null) => ClientHelper.GetConnectionsAsync(this, options ?? RequestOptions.Default); /// - public Task GetInviteAsync(string inviteId, bool withCount = false, RequestOptions options = null) - => ClientHelper.GetInviteAsync(this, inviteId, withCount, options ?? RequestOptions.Default); + public Task GetInviteAsync(string inviteId, RequestOptions options = null) + => ClientHelper.GetInviteAsync(this, inviteId, options ?? RequestOptions.Default); // IDiscordClient async Task IDiscordClient.GetApplicationInfoAsync(RequestOptions options) @@ -70,8 +70,8 @@ namespace Discord.WebSocket async Task> IDiscordClient.GetConnectionsAsync(RequestOptions options) => await GetConnectionsAsync(options).ConfigureAwait(false); - async Task IDiscordClient.GetInviteAsync(string inviteId, bool withCount, RequestOptions options) - => await GetInviteAsync(inviteId, withCount, options).ConfigureAwait(false); + async Task IDiscordClient.GetInviteAsync(string inviteId, RequestOptions options) + => await GetInviteAsync(inviteId, options).ConfigureAwait(false); Task IDiscordClient.GetGuildAsync(ulong id, CacheMode mode, RequestOptions options) => Task.FromResult(GetGuild(id)); diff --git a/src/Discord.Net.WebSocket/DiscordShardedClient.cs b/src/Discord.Net.WebSocket/DiscordShardedClient.cs index 26d9363eb..e29cc4057 100644 --- a/src/Discord.Net.WebSocket/DiscordShardedClient.cs +++ b/src/Discord.Net.WebSocket/DiscordShardedClient.cs @@ -328,8 +328,8 @@ namespace Discord.WebSocket async Task> IDiscordClient.GetConnectionsAsync(RequestOptions options) => await GetConnectionsAsync().ConfigureAwait(false); - async Task IDiscordClient.GetInviteAsync(string inviteId, bool withCount, RequestOptions options) - => await GetInviteAsync(inviteId, withCount, options).ConfigureAwait(false); + async Task IDiscordClient.GetInviteAsync(string inviteId, RequestOptions options) + => await GetInviteAsync(inviteId, options).ConfigureAwait(false); Task IDiscordClient.GetGuildAsync(ulong id, CacheMode mode, RequestOptions options) => Task.FromResult(GetGuild(id)); diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.cs index c51ece23b..8eadc00fb 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.cs @@ -1513,6 +1513,9 @@ namespace Discord.WebSocket case "MESSAGE_ACK": await _gatewayLogger.DebugAsync("Ignored Dispatch (MESSAGE_ACK)").ConfigureAwait(false); break; + case "PRESENCES_REPLACE": + await _gatewayLogger.DebugAsync("Ignored Dispatch (PRESENCES_REPLACE)").ConfigureAwait(false); + break; case "USER_SETTINGS_UPDATE": await _gatewayLogger.DebugAsync("Ignored Dispatch (USER_SETTINGS_UPDATE)").ConfigureAwait(false); break; @@ -1819,8 +1822,8 @@ namespace Discord.WebSocket async Task> IDiscordClient.GetConnectionsAsync(RequestOptions options) => await GetConnectionsAsync().ConfigureAwait(false); - async Task IDiscordClient.GetInviteAsync(string inviteId, bool withCount, RequestOptions options) - => await GetInviteAsync(inviteId, withCount, options).ConfigureAwait(false); + async Task IDiscordClient.GetInviteAsync(string inviteId, RequestOptions options) + => await GetInviteAsync(inviteId, options).ConfigureAwait(false); Task IDiscordClient.GetGuildAsync(ulong id, CacheMode mode, RequestOptions options) => Task.FromResult(GetGuild(id)); diff --git a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs index f41f61a7c..bf33ef569 100644 --- a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs +++ b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs @@ -345,6 +345,15 @@ namespace Discord.WebSocket //Invites public Task> GetInvitesAsync(RequestOptions options = null) => GuildHelper.GetInvitesAsync(this, Discord, options); + /// + /// Gets the vanity invite URL of this guild. + /// + /// The options to be used when sending the request. + /// + /// A partial metadata of the vanity invite found within this guild. + /// + public Task GetVanityInviteAsync(RequestOptions options = null) + => GuildHelper.GetVanityInviteAsync(this, Discord, options); //Roles public SocketRole GetRole(ulong id) @@ -700,6 +709,9 @@ namespace Discord.WebSocket async Task> IGuild.GetInvitesAsync(RequestOptions options) => await GetInvitesAsync(options).ConfigureAwait(false); + /// + async Task IGuild.GetVanityInviteAsync(RequestOptions options) + => await GetVanityInviteAsync(options).ConfigureAwait(false); IRole IGuild.GetRole(ulong id) => GetRole(id); @@ -715,7 +727,7 @@ namespace Discord.WebSocket Task IGuild.GetOwnerAsync(CacheMode mode, RequestOptions options) => Task.FromResult(Owner); - async Task> IGuild.GetAuditLogAsync(int limit, CacheMode cacheMode, RequestOptions options) + async Task> IGuild.GetAuditLogsAsync(int limit, CacheMode cacheMode, RequestOptions options) { if (cacheMode == CacheMode.AllowDownload) return (await GetAuditLogsAsync(limit, options).FlattenAsync().ConfigureAwait(false)).ToImmutableArray();