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..604945758 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); 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.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/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..73028362f 100644 --- a/src/Discord.Net.Rest/DiscordRestClient.cs +++ b/src/Discord.Net.Rest/DiscordRestClient.cs @@ -57,7 +57,7 @@ namespace Discord.Rest /// public Task GetInviteAsync(string inviteId, bool withCount = false, RequestOptions options = null) - => ClientHelper.GetInviteAsync(this, inviteId, withCount, options); + => ClientHelper.GetInviteAsync(this, inviteId, options); /// public Task GetGuildAsync(ulong id, RequestOptions options = null) 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..9b3143268 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); 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..be6f3795d 100644 --- a/src/Discord.Net.WebSocket/BaseSocketClient.cs +++ b/src/Discord.Net.WebSocket/BaseSocketClient.cs @@ -56,7 +56,7 @@ namespace Discord.WebSocket => 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); + => ClientHelper.GetInviteAsync(this, inviteId, options ?? RequestOptions.Default); // IDiscordClient async Task IDiscordClient.GetApplicationInfoAsync(RequestOptions options) diff --git a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs index f41f61a7c..680706713 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);