[Feature] New ModifyCurrentApplication features (#2730)

* initial commit

* apply suggestings lol

* Update src/Discord.Net.Core/Entities/Applications/IApplication.cs

Co-authored-by: Quin Lynch <49576606+quinchs@users.noreply.github.com>

* check for null values inside the array

---------

Co-authored-by: Quin Lynch <49576606+quinchs@users.noreply.github.com>
This commit is contained in:
Misha133
2023-08-10 16:18:06 +03:00
committed by GitHub
parent 59094d2e1f
commit 166d40f1e4
9 changed files with 137 additions and 45 deletions

View File

@@ -232,5 +232,10 @@ namespace Discord
/// Returns the max length of an application description. /// Returns the max length of an application description.
/// </summary> /// </summary>
public const int MaxApplicationDescriptionLength = 400; public const int MaxApplicationDescriptionLength = 400;
/// <summary>
/// Returns the max amount of tags applied to an application.
/// </summary>
public const int MaxApplicationTagCount = 5;
} }
} }

View File

@@ -9,28 +9,62 @@ namespace Discord;
/// <summary> /// <summary>
/// Represents public flags for an application. /// Represents public flags for an application.
/// </summary> /// </summary>
[Flags]
public enum ApplicationFlags public enum ApplicationFlags
{ {
/// <summary>
/// Indicates if an app uses the Auto Moderation API.
/// </summary>
UsesAutoModApi = 1 << 6, UsesAutoModApi = 1 << 6,
/// <summary>
/// Indicates that the app has been verified to use GUILD_PRESENCES intent.
/// </summary>
GatewayPresence = 1 << 12, GatewayPresence = 1 << 12,
/// <summary>
/// Indicates that the app has enabled the GUILD_PRESENCES intent on a bot in less than 100 servers.
/// </summary>
GatewayPresenceLimited = 1 << 13, GatewayPresenceLimited = 1 << 13,
/// <summary>
/// Indicates that the app has been verified to use GUILD_MEMBERS intent.
/// </summary>
GatewayGuildMembers = 1 << 14, GatewayGuildMembers = 1 << 14,
/// <summary>
/// Indicates that the app has enabled the GUILD_MEMBERS intent on a bot in less than 100 servers.
/// </summary>
GatewayGuildMembersLimited = 1 << 15, GatewayGuildMembersLimited = 1 << 15,
/// <summary>
/// Indicates unusual growth of an app that prevents verification.
/// </summary>
VerificationPendingGuildLimit = 1 << 16, VerificationPendingGuildLimit = 1 << 16,
/// <summary>
/// Indicates if an app is embedded within the Discord client.
/// </summary>
Embedded = 1 << 17, Embedded = 1 << 17,
/// <summary>
/// Indicates that the app has been verified to use MESSAGE_CONTENT intent.
/// </summary>
GatewayMessageContent = 1 << 18, GatewayMessageContent = 1 << 18,
/// <summary>
/// Indicates that the app has enabled the MESSAGE_CONTENT intent on a bot in less than 100 servers.
/// </summary>
GatewayMessageContentLimited = 1 << 19, GatewayMessageContentLimited = 1 << 19,
/// <summary>
/// Indicates if an app has registered global application commands.
/// </summary>
ApplicationCommandBadge = 1 << 23, ApplicationCommandBadge = 1 << 23,
/// <summary>
/// Indicates if an app is considered active.
/// </summary>
ActiveApplication = 1 << 24 ActiveApplication = 1 << 24
} }

View File

@@ -1,31 +1,31 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Discord namespace Discord;
/// <summary>
/// Represents install parameters for an application.
/// </summary>
public class ApplicationInstallParams
{ {
/// <summary> /// <summary>
/// Represents install parameters for an application. /// Gets the scopes to install this application.
/// </summary> /// </summary>
public class ApplicationInstallParams public IReadOnlyCollection<string> Scopes { get; }
/// <summary>
/// Gets the default permissions to install this application.
/// </summary>
public GuildPermission Permission { get; }
public ApplicationInstallParams(string[] scopes, GuildPermission permission)
{ {
/// <summary> Preconditions.NotNull(scopes, nameof(scopes));
/// Gets the scopes to install this application.
/// </summary>
public IReadOnlyCollection<string> Scopes { get; }
/// <summary> foreach (var s in scopes)
/// Gets the default permissions to install this application Preconditions.NotNull(s, nameof(scopes));
/// </summary>
public GuildPermission? Permission { get; }
internal ApplicationInstallParams(string[] scopes, GuildPermission? permission) Scopes = scopes.ToImmutableArray();
{ Permission = permission;
Scopes = scopes.ToImmutableArray();
Permission = permission;
}
} }
} }

View File

@@ -24,7 +24,7 @@ namespace Discord
/// </summary> /// </summary>
ApplicationFlags Flags { get; } ApplicationFlags Flags { get; }
/// <summary> /// <summary>
/// Gets a collection of install parameters for this application. /// Gets a collection of install parameters for this application; <see langword="null"/> if disabled.
/// </summary> /// </summary>
ApplicationInstallParams InstallParams { get; } ApplicationInstallParams InstallParams { get; }
/// <summary> /// <summary>

View File

@@ -29,4 +29,29 @@ public class ModifyApplicationProperties
/// Gets or sets the icon of the application. /// Gets or sets the icon of the application.
/// </summary> /// </summary>
public Optional<Image?> Icon { get; set; } public Optional<Image?> Icon { get; set; }
/// <summary>
/// Gets or sets the default rich presence invite cover image of the application.
/// </summary>
public Optional<Image?> CoverImage { get; set; }
/// <summary>
/// Gets or set the default custom authorization URL for the app, if enabled.
/// </summary>
public Optional<string> CustomInstallUrl { get; set; }
/// <summary>
/// Gets or sets settings for the app's default in-app authorization link, if enabled.
/// </summary>
public Optional<ApplicationInstallParams> InstallParams { get; set; }
/// <summary>
/// Gets or sets app's public flags.
/// </summary>
/// <remarks>
/// Only <see cref="ApplicationFlags.GatewayGuildMembersLimited"/>, <see cref="ApplicationFlags.GatewayMessageContentLimited"/> and
/// <see cref="ApplicationFlags.GatewayPresenceLimited"/> flags can be updated.
/// </remarks>
public Optional<ApplicationFlags> Flags { get; set; }
} }

View File

@@ -1,17 +1,12 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Discord.API namespace Discord.API;
internal class InstallParams
{ {
internal class InstallParams [JsonProperty("scopes")]
{ public string[] Scopes { get; set; }
[JsonProperty("scopes")]
public string[] Scopes { get; set; } [JsonProperty("permissions")]
[JsonProperty("permissions")] public ulong Permission { get; set; }
public ulong Permission { get; set; }
}
} }

View File

@@ -4,18 +4,30 @@ namespace Discord.API.Rest;
internal class ModifyCurrentApplicationBotParams internal class ModifyCurrentApplicationBotParams
{ {
[JsonProperty("interactions_endpoint_url")] [JsonProperty("custom_install_url")]
public Optional<string> InteractionsEndpointUrl { get; set; } public Optional<string> CustomInstallUrl { get; set; }
[JsonProperty("role_connections_verification_url")]
public Optional<string> RoleConnectionsEndpointUrl { get; set; }
[JsonProperty("description")] [JsonProperty("description")]
public Optional<string> Description { get; set; } public Optional<string> Description { get; set; }
[JsonProperty("tags")] [JsonProperty("role_connections_verification_url")]
public Optional<string[]> Tags { get; set; } public Optional<string> RoleConnectionsEndpointUrl { get; set; }
[JsonProperty("install_params")]
public Optional<InstallParams> InstallParams { get; set; }
[JsonProperty("flags")]
public Optional<ApplicationFlags> Flags { get; set; }
[JsonProperty("icon")] [JsonProperty("icon")]
public Optional<Image?> Icon { get; set; } public Optional<Image?> Icon { get; set; }
[JsonProperty("cover_image")]
public Optional<Image?> CoverImage { get; set; }
[JsonProperty("interactions_endpoint_url")]
public Optional<string> InteractionsEndpointUrl { get; set; }
[JsonProperty("tags")]
public Optional<string[]> Tags { get; set; }
} }

View File

@@ -1,4 +1,6 @@
using Discord.API;
using Discord.API.Rest; using Discord.API.Rest;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
@@ -28,11 +30,14 @@ namespace Discord.Rest
var args = new ModifyApplicationProperties(); var args = new ModifyApplicationProperties();
func(args); func(args);
if(args.Tags.IsSpecified) if (args.Tags.IsSpecified)
{
Preconditions.AtMost(args.Tags.Value.Length, DiscordConfig.MaxApplicationTagCount, nameof(args.Tags), $"An application can have a maximum of {DiscordConfig.MaxApplicationTagCount} applied.");
foreach (var tag in args.Tags.Value) foreach (var tag in args.Tags.Value)
Preconditions.AtMost(tag.Length, DiscordConfig.MaxApplicationTagLength, nameof(args.Tags), $"An application tag must have length less or equal to {DiscordConfig.MaxApplicationTagLength}"); Preconditions.AtMost(tag.Length, DiscordConfig.MaxApplicationTagLength, nameof(args.Tags), $"An application tag must have length less or equal to {DiscordConfig.MaxApplicationTagLength}");
}
if(args.Description.IsSpecified) if (args.Description.IsSpecified)
Preconditions.AtMost(args.Description.Value.Length, DiscordConfig.MaxApplicationDescriptionLength, nameof(args.Description), $"An application description tag mus have length less or equal to {DiscordConfig.MaxApplicationDescriptionLength}"); Preconditions.AtMost(args.Description.Value.Length, DiscordConfig.MaxApplicationDescriptionLength, nameof(args.Description), $"An application description tag mus have length less or equal to {DiscordConfig.MaxApplicationDescriptionLength}");
return await client.ApiClient.ModifyCurrentBotApplicationAsync(new() return await client.ApiClient.ModifyCurrentBotApplicationAsync(new()
@@ -42,6 +47,18 @@ namespace Discord.Rest
Icon = args.Icon.IsSpecified ? args.Icon.Value?.ToModel() : Optional<API.Image?>.Unspecified, Icon = args.Icon.IsSpecified ? args.Icon.Value?.ToModel() : Optional<API.Image?>.Unspecified,
InteractionsEndpointUrl = args.InteractionsEndpointUrl, InteractionsEndpointUrl = args.InteractionsEndpointUrl,
RoleConnectionsEndpointUrl = args.RoleConnectionsEndpointUrl, RoleConnectionsEndpointUrl = args.RoleConnectionsEndpointUrl,
Flags = args.Flags,
CoverImage = args.CoverImage.IsSpecified ? args.CoverImage.Value?.ToModel() : Optional<API.Image?>.Unspecified,
CustomInstallUrl = args.CustomInstallUrl,
InstallParams = args.InstallParams.IsSpecified
? args.InstallParams.Value is null
? null
: new InstallParams
{
Permission = (ulong)args.InstallParams.Value.Permission,
Scopes = args.InstallParams.Value.Scopes.ToArray()
}
: Optional<InstallParams>.Unspecified,
}, options); }, options);
} }

View File

@@ -61,8 +61,10 @@ namespace Discord.Rest
/// <inheritdoc /> /// <inheritdoc />
public string InteractionsEndpointUrl { get; private set; } public string InteractionsEndpointUrl { get; private set; }
/// <inheritdoc />
public ApplicationInstallParams InstallParams { get; private set; } public ApplicationInstallParams InstallParams { get; private set; }
/// <inheritdoc />
public IReadOnlyCollection<string> Tags { get; private set; } public IReadOnlyCollection<string> Tags { get; private set; }
internal RestApplication(BaseDiscordClient discord, ulong id) internal RestApplication(BaseDiscordClient discord, ulong id)
@@ -86,8 +88,10 @@ namespace Discord.Rest
Tags = model.Tags.GetValueOrDefault(null)?.ToImmutableArray() ?? ImmutableArray<string>.Empty; Tags = model.Tags.GetValueOrDefault(null)?.ToImmutableArray() ?? ImmutableArray<string>.Empty;
PrivacyPolicy = model.PrivacyPolicy; PrivacyPolicy = model.PrivacyPolicy;
TermsOfService = model.TermsOfService; TermsOfService = model.TermsOfService;
var installParams = model.InstallParams.GetValueOrDefault(null);
InstallParams = new ApplicationInstallParams(installParams?.Scopes ?? Array.Empty<string>(), (GuildPermission?)installParams?.Permission); InstallParams = model.InstallParams.IsSpecified
? new ApplicationInstallParams(model.InstallParams.Value.Scopes, (GuildPermission)model.InstallParams.Value.Permission)
: null;
if (model.Flags.IsSpecified) if (model.Flags.IsSpecified)
Flags = model.Flags.Value; Flags = model.Flags.Value;