diff --git a/src/Discord.Net.Core/Entities/Channels/INestedChannel.cs b/src/Discord.Net.Core/Entities/Channels/INestedChannel.cs index 2c9503db1..d8072f94f 100644 --- a/src/Discord.Net.Core/Entities/Channels/INestedChannel.cs +++ b/src/Discord.Net.Core/Entities/Channels/INestedChannel.cs @@ -12,7 +12,7 @@ namespace Discord /// Gets the parent (category) ID of this channel in the guild's channel list. /// /// - /// A representing the snowflake identifier of the parent of this channel; + /// A representing the snowflake identifier of the parent of this channel; /// null if none is set. /// ulong? CategoryId { get; } @@ -56,6 +56,50 @@ namespace Discord /// metadata object containing information for the created invite. /// Task CreateInviteAsync(int? maxAge = 86400, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null); + + /// + /// Creates a new invite to this channel. + /// + /// + /// The following example creates a new invite to this channel; the invite lasts for 12 hours and can only + /// be used 3 times throughout its lifespan. + /// + /// await guildChannel.CreateInviteAsync(maxAge: 43200, maxUses: 3); + /// + /// + /// The id of the embedded application to open for this invite + /// The time (in seconds) until the invite expires. Set to null to never expire. + /// The max amount of times this invite may be used. Set to null to have unlimited uses. + /// If true, the user accepting this invite will be kicked from the guild after closing their client. + /// If true, don't try to reuse a similar invite (useful for creating many unique one time use invites). + /// The options to be used when sending the request. + /// + /// A task that represents the asynchronous invite creation operation. The task result contains an invite + /// metadata object containing information for the created invite. + /// + Task CreateInviteToApplicationAsync(ulong applicationId, int? maxAge = 86400, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null); + + /// + /// Creates a new invite to this channel. + /// + /// + /// The following example creates a new invite to this channel; the invite lasts for 12 hours and can only + /// be used 3 times throughout its lifespan. + /// + /// await guildChannel.CreateInviteAsync(maxAge: 43200, maxUses: 3); + /// + /// + /// The id of the user whose stream to display for this invite + /// The time (in seconds) until the invite expires. Set to null to never expire. + /// The max amount of times this invite may be used. Set to null to have unlimited uses. + /// If true, the user accepting this invite will be kicked from the guild after closing their client. + /// If true, don't try to reuse a similar invite (useful for creating many unique one time use invites). + /// The options to be used when sending the request. + /// + /// A task that represents the asynchronous invite creation operation. The task result contains an invite + /// metadata object containing information for the created invite. + /// + Task CreateInviteToStreamAsync(IUser user, int? maxAge = 86400, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null); /// /// Gets a collection of all invites to this channel. /// B diff --git a/src/Discord.Net.Core/Entities/Invites/TargetUserType.cs b/src/Discord.Net.Core/Entities/Invites/TargetUserType.cs index 74263b888..e1818d7a9 100644 --- a/src/Discord.Net.Core/Entities/Invites/TargetUserType.cs +++ b/src/Discord.Net.Core/Entities/Invites/TargetUserType.cs @@ -9,6 +9,10 @@ namespace Discord /// /// The invite is for a Go Live stream. /// - Stream = 1 + Stream = 1, + /// + /// The invite is for embedded application. + /// + EmbeddedApplication = 2 } } diff --git a/src/Discord.Net.Rest/API/Rest/CreateChannelInviteParams.cs b/src/Discord.Net.Rest/API/Rest/CreateChannelInviteParams.cs index db79bc314..06a47f1a8 100644 --- a/src/Discord.Net.Rest/API/Rest/CreateChannelInviteParams.cs +++ b/src/Discord.Net.Rest/API/Rest/CreateChannelInviteParams.cs @@ -14,5 +14,11 @@ namespace Discord.API.Rest public Optional IsTemporary { get; set; } [JsonProperty("unique")] public Optional IsUnique { get; set; } + [JsonProperty("target_type")] + public Optional TargetType { get; set; } + [JsonProperty("target_user_id")] + public Optional TargetUserId { get; set; } + [JsonProperty("target_application_id")] + public Optional TargetApplicationId { get; set; } } } diff --git a/src/Discord.Net.Rest/DiscordRestApiClient.cs b/src/Discord.Net.Rest/DiscordRestApiClient.cs index d7978db5c..70e7f9278 100644 --- a/src/Discord.Net.Rest/DiscordRestApiClient.cs +++ b/src/Discord.Net.Rest/DiscordRestApiClient.cs @@ -1079,6 +1079,12 @@ namespace Discord.API Preconditions.AtLeast(args.MaxUses, 0, nameof(args.MaxUses)); Preconditions.AtMost(args.MaxAge, 86400, nameof(args.MaxAge), "The maximum age of an invite must be less than or equal to a day (86400 seconds)."); + if (args.TargetType.IsSpecified) + { + Preconditions.NotEqual((int)args.TargetType.Value, (int)TargetUserType.Undefined, nameof(args.TargetType)); + if (args.TargetType.Value == TargetUserType.Stream) Preconditions.GreaterThan(args.TargetUserId, 0, nameof(args.TargetUserId)); + if (args.TargetType.Value == TargetUserType.EmbeddedApplication) Preconditions.GreaterThan(args.TargetApplicationId, 0, nameof(args.TargetUserId)); + } options = RequestOptions.CreateOrClone(options); var ids = new BucketIds(channelId: channelId); diff --git a/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs b/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs index 22395ab3a..77f5e5b4c 100644 --- a/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs +++ b/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs @@ -120,6 +120,54 @@ namespace Discord.Rest return RestInviteMetadata.Create(client, null, channel, model); } + /// + /// may not be equal to zero. + /// -and- + /// and must be greater than zero. + /// -and- + /// must be lesser than 86400. + /// + public static async Task CreateInviteToStreamAsync(IGuildChannel channel, BaseDiscordClient client, + int? maxAge, int? maxUses, bool isTemporary, bool isUnique, IUser user, + RequestOptions options) + { + var args = new API.Rest.CreateChannelInviteParams + { + IsTemporary = isTemporary, + IsUnique = isUnique, + MaxAge = maxAge ?? 0, + MaxUses = maxUses ?? 0, + TargetType = TargetUserType.Stream, + TargetUserId = user.Id + }; + var model = await client.ApiClient.CreateChannelInviteAsync(channel.Id, args, options).ConfigureAwait(false); + return RestInviteMetadata.Create(client, null, channel, model); + } + + /// + /// may not be equal to zero. + /// -and- + /// and must be greater than zero. + /// -and- + /// must be lesser than 86400. + /// + public static async Task CreateInviteToApplicationAsync(IGuildChannel channel, BaseDiscordClient client, + int? maxAge, int? maxUses, bool isTemporary, bool isUnique, ulong applicationId, + RequestOptions options) + { + var args = new API.Rest.CreateChannelInviteParams + { + IsTemporary = isTemporary, + IsUnique = isUnique, + MaxAge = maxAge ?? 0, + MaxUses = maxUses ?? 0, + TargetType = TargetUserType.EmbeddedApplication, + TargetApplicationId = applicationId + }; + var model = await client.ApiClient.CreateChannelInviteAsync(channel.Id, args, options).ConfigureAwait(false); + return RestInviteMetadata.Create(client, null, channel, model); + } + //Messages public static async Task GetMessageAsync(IMessageChannel channel, BaseDiscordClient client, ulong id, RequestOptions options) diff --git a/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs index c6d0b0509..8597acd2f 100644 --- a/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs @@ -17,7 +17,7 @@ namespace Discord.Rest /// public string Topic { get; private set; } /// - public virtual int SlowModeInterval { get; private set; } + public virtual int SlowModeInterval { get; private set; } /// public ulong? CategoryId { get; private set; } @@ -78,7 +78,7 @@ namespace Discord.Rest /// /// /// A paged collection containing a collection of guild users that can access this channel. Flattening the - /// paginated response into a collection of users with + /// paginated response into a collection of users with /// is required if you wish to access the users. /// public IAsyncEnumerable> GetUsersAsync(RequestOptions options = null) @@ -215,6 +215,10 @@ namespace Discord.Rest /// public async Task CreateInviteAsync(int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) => await ChannelHelper.CreateInviteAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, options).ConfigureAwait(false); + public Task CreateInviteToApplicationAsync(ulong applicationId, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) + => throw new NotImplementedException(); + public Task CreateInviteToStreamAsync(IUser user, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) + => throw new NotImplementedException(); /// public async Task> GetInvitesAsync(RequestOptions options = null) => await ChannelHelper.GetInvitesAsync(this, Discord, options).ConfigureAwait(false); diff --git a/src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs index 3f3aa96c6..b551c7f8f 100644 --- a/src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs @@ -60,12 +60,18 @@ namespace Discord.Rest /// public Task SyncPermissionsAsync(RequestOptions options = null) => ChannelHelper.SyncPermissionsAsync(this, Discord, options); - + //Invites /// public async Task CreateInviteAsync(int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) => await ChannelHelper.CreateInviteAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, options).ConfigureAwait(false); /// + public async Task CreateInviteToApplicationAsync(ulong applicationId, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) + => await ChannelHelper.CreateInviteToApplicationAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, applicationId, options).ConfigureAwait(false); + /// + public async Task CreateInviteToStreamAsync(IUser user, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) + => await ChannelHelper.CreateInviteToStreamAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, user, options).ConfigureAwait(false); + /// public async Task> GetInvitesAsync(RequestOptions options = null) => await ChannelHelper.GetInvitesAsync(this, Discord, options).ConfigureAwait(false); diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs index 71a20c198..a9c1e8658 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs @@ -258,6 +258,12 @@ namespace Discord.WebSocket public async Task CreateInviteAsync(int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) => await ChannelHelper.CreateInviteAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, options).ConfigureAwait(false); /// + public async Task CreateInviteToApplicationAsync(ulong applicationId, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) + => await ChannelHelper.CreateInviteToApplicationAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, applicationId, options).ConfigureAwait(false); + /// + public async Task CreateInviteToStreamAsync(IUser user, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) + => await ChannelHelper.CreateInviteToStreamAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, user, options).ConfigureAwait(false); + /// public async Task> GetInvitesAsync(RequestOptions options = null) => await ChannelHelper.GetInvitesAsync(this, Discord, options).ConfigureAwait(false); diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs index bf4a63c9f..7dded5fa2 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs @@ -90,6 +90,12 @@ namespace Discord.WebSocket public async Task CreateInviteAsync(int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) => await ChannelHelper.CreateInviteAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, options).ConfigureAwait(false); /// + public async Task CreateInviteToApplicationAsync(ulong applicationId, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) + => await ChannelHelper.CreateInviteToApplicationAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, applicationId, options).ConfigureAwait(false); + /// + public async Task CreateInviteToStreamAsync(IUser user, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) + => await ChannelHelper.CreateInviteToStreamAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, user, options).ConfigureAwait(false); + /// public async Task> GetInvitesAsync(RequestOptions options = null) => await ChannelHelper.GetInvitesAsync(this, Discord, options).ConfigureAwait(false); diff --git a/test/Discord.Net.Tests.Unit/MockedEntities/MockedTextChannel.cs b/test/Discord.Net.Tests.Unit/MockedEntities/MockedTextChannel.cs index 51aece5f2..633d52e4a 100644 --- a/test/Discord.Net.Tests.Unit/MockedEntities/MockedTextChannel.cs +++ b/test/Discord.Net.Tests.Unit/MockedEntities/MockedTextChannel.cs @@ -46,6 +46,10 @@ namespace Discord { throw new NotImplementedException(); } + public Task CreateInviteToApplicationAsync(ulong applicationId, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) + => throw new NotImplementedException(); + public Task CreateInviteToStreamAsync(IUser user, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) + => throw new NotImplementedException(); public Task CreateWebhookAsync(string name, Stream avatar = null, RequestOptions options = null) { diff --git a/test/Discord.Net.Tests.Unit/MockedEntities/MockedVoiceChannel.cs b/test/Discord.Net.Tests.Unit/MockedEntities/MockedVoiceChannel.cs index eb617125d..7c3d00fdd 100644 --- a/test/Discord.Net.Tests.Unit/MockedEntities/MockedVoiceChannel.cs +++ b/test/Discord.Net.Tests.Unit/MockedEntities/MockedVoiceChannel.cs @@ -47,6 +47,10 @@ namespace Discord { throw new NotImplementedException(); } + public Task CreateInviteToApplicationAsync(ulong applicationId, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) + => throw new NotImplementedException(); + public Task CreateInviteToStreamAsync(IUser user, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) + => throw new NotImplementedException(); public Task DeleteAsync(RequestOptions options = null) {