| @@ -1,3 +1,4 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Collections.Immutable; | |||
| @@ -5,26 +6,58 @@ namespace Discord; | |||
| public class RoleConnectionMetadata | |||
| { | |||
| /// <summary> | |||
| /// Gets the of metadata value. | |||
| /// </summary> | |||
| public RoleConnectionMetadataType Type { get; } | |||
| /// <summary> | |||
| /// Gets the dictionary key for the metadata field. | |||
| /// </summary> | |||
| public string Key { get; } | |||
| public string Name{ get; } | |||
| public Optional<IReadOnlyDictionary<string, string>> NameLocalizations { get; } | |||
| /// <summary> | |||
| /// Gets the name of the metadata field. | |||
| /// </summary> | |||
| public string Name { get; } | |||
| /// <summary> | |||
| /// Gets the description of the metadata field. | |||
| /// </summary> | |||
| public string Description { get; } | |||
| public Optional<IReadOnlyDictionary<string, string>> DescriptionLocalizations { get; } | |||
| /// <summary> | |||
| /// Gets translations of the name. <see langword="null"/> if not set. | |||
| /// </summary> | |||
| public IReadOnlyDictionary<string, string> NameLocalizations { get; } | |||
| /// <summary> | |||
| /// Gets translations of the description. <see langword="null"/> if not set. | |||
| /// </summary> | |||
| public IReadOnlyDictionary<string, string> DescriptionLocalizations { get; } | |||
| internal RoleConnectionMetadata(RoleConnectionMetadataType type, string key, string name, string description, | |||
| Dictionary<string, string> nameLocalizations = null, Dictionary<string, string> descriptionLocalizations = null) | |||
| IDictionary<string, string> nameLocalizations = null, IDictionary<string, string> descriptionLocalizations = null) | |||
| { | |||
| Type = type; | |||
| Key = key; | |||
| Name = name; | |||
| Description = description; | |||
| NameLocalizations = nameLocalizations.ToImmutableDictionary(); | |||
| DescriptionLocalizations = descriptionLocalizations.ToImmutableDictionary(); | |||
| NameLocalizations = nameLocalizations?.ToImmutableDictionary(); | |||
| DescriptionLocalizations = descriptionLocalizations?.ToImmutableDictionary(); | |||
| } | |||
| /// <summary> | |||
| /// Initializes a new <see cref="RoleConnectionMetadataProperties"/> with the data from this object. | |||
| /// </summary> | |||
| public RoleConnectionMetadataProperties ToRoleConnectionMetadataProperties() | |||
| => new() | |||
| { | |||
| Name = Name, | |||
| Description = Description, | |||
| Type = Type, | |||
| Key = Key, | |||
| NameLocalizations = NameLocalizations, | |||
| DescriptionLocalizations = DescriptionLocalizations | |||
| }; | |||
| } | |||
| @@ -0,0 +1,121 @@ | |||
| using System.Collections.Generic; | |||
| using System; | |||
| using System.Collections.Immutable; | |||
| namespace Discord; | |||
| public class RoleConnectionMetadataProperties | |||
| { | |||
| private const int MaxKeyLength = 50; | |||
| private const int MaxNameLength = 100; | |||
| private const int MaxDescriptionLength = 200; | |||
| private string _key; | |||
| private string _name; | |||
| private string _description; | |||
| private IReadOnlyDictionary<string, string> _nameLocalizations; | |||
| private IReadOnlyDictionary<string, string> _descriptionLocalizations; | |||
| /// <summary> | |||
| /// Gets or sets the of metadata value. | |||
| /// </summary> | |||
| public RoleConnectionMetadataType Type { get; set; } | |||
| /// <summary> | |||
| /// Gets or sets the dictionary key for the metadata field. | |||
| /// </summary> | |||
| public string Key | |||
| { | |||
| get => _key; | |||
| set | |||
| { | |||
| Preconditions.AtMost(value.Length, MaxKeyLength, nameof(Key), $"Key length must be less than or equal to {MaxKeyLength}"); | |||
| _key = value; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Gets or sets the name of the metadata field. | |||
| /// </summary> | |||
| public string Name | |||
| { | |||
| get => _name; | |||
| set | |||
| { | |||
| Preconditions.AtMost(value.Length, MaxNameLength, nameof(Name), $"Name length must be less than or equal to {MaxNameLength}"); | |||
| _name = value; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Gets or sets the description of the metadata field. | |||
| /// </summary> | |||
| public string Description | |||
| { | |||
| get => _description; | |||
| set | |||
| { | |||
| Preconditions.AtMost(value.Length, MaxDescriptionLength, nameof(Description), $"Description length must be less than or equal to {MaxDescriptionLength}"); | |||
| _description = value; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Gets or sets translations of the name. <see langword="null"/> if not set. | |||
| /// </summary> | |||
| public IReadOnlyDictionary<string, string> NameLocalizations | |||
| { | |||
| get => _nameLocalizations; | |||
| set | |||
| { | |||
| if (value is not null) | |||
| foreach (var localization in value) | |||
| if (localization.Value.Length > MaxNameLength) | |||
| throw new ArgumentException($"Name localization length must be less than or equal to {MaxNameLength}. Locale '{localization}'"); | |||
| _nameLocalizations = value; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Gets or sets translations of the description. <see langword="null"/> if not set. | |||
| /// </summary> | |||
| public IReadOnlyDictionary<string, string> DescriptionLocalizations | |||
| { | |||
| get => _descriptionLocalizations; | |||
| set | |||
| { | |||
| if (value is not null) | |||
| foreach (var localization in value) | |||
| if (localization.Value.Length > MaxDescriptionLength) | |||
| throw new ArgumentException($"Description localization length must be less than or equal to {MaxDescriptionLength}. Locale '{localization}'"); | |||
| _descriptionLocalizations = value; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Initializes a new instance of <see cref="RoleConnectionMetadataProperties"/>. | |||
| /// </summary> | |||
| /// <param name="type">The type of the metadata value.</param> | |||
| /// <param name="key">The dictionary key for the metadata field. Max 50 characters.</param> | |||
| /// <param name="name">The name of the metadata visible in user profile. Max 100 characters.</param> | |||
| /// <param name="description">The description of the metadata visible in user profile. Max 200 characters.</param> | |||
| /// <param name="nameLocalizations">Translations for the name.</param> | |||
| /// <param name="descriptionLocalizations">Translations for the description.</param> | |||
| public RoleConnectionMetadataProperties(RoleConnectionMetadataType type, string key, string name, string description, | |||
| IDictionary<string, string> nameLocalizations = null, IDictionary<string, string> descriptionLocalizations = null) | |||
| { | |||
| Type = type; | |||
| Key = key; | |||
| Name = name; | |||
| Description = description; | |||
| NameLocalizations = nameLocalizations?.ToImmutableDictionary(); | |||
| DescriptionLocalizations = descriptionLocalizations?.ToImmutableDictionary(); | |||
| } | |||
| /// <summary> | |||
| /// Initializes a new instance of <see cref="RoleConnectionMetadataProperties"/>. | |||
| /// </summary> | |||
| public RoleConnectionMetadataProperties() { } | |||
| } | |||
| @@ -18,8 +18,8 @@ public class RoleConnectionMetadata | |||
| public string Description { get; set; } | |||
| [JsonProperty("name_localizations")] | |||
| public Optional<IReadOnlyCollection<KeyValuePair<string, string>>> NameLocalizations { get; set; } | |||
| public Optional<Dictionary<string, string>> NameLocalizations { get; set; } | |||
| [JsonProperty("description_localizations")] | |||
| public Optional<IReadOnlyCollection<KeyValuePair<string, string>>> DescriptionLocalizations { get; set; } | |||
| public Optional<Dictionary<string, string>> DescriptionLocalizations { get; set; } | |||
| } | |||
| @@ -264,5 +264,50 @@ namespace Discord.Rest | |||
| public static Task RemoveRoleAsync(BaseDiscordClient client, ulong guildId, ulong userId, ulong roleId, RequestOptions options = null) | |||
| => client.ApiClient.RemoveRoleAsync(guildId, userId, roleId, options); | |||
| #endregion | |||
| #region Role Subscription Metadata | |||
| public static async Task<IReadOnlyCollection<RoleConnectionMetadata>> GetRoleConnectionMetadataRecordsAsync(BaseDiscordClient client, RequestOptions options = null) | |||
| => (await client.ApiClient.GetApplicationRoleConnectionMetadataRecordsAsync(options)) | |||
| .Select(model | |||
| => new RoleConnectionMetadata( | |||
| model.Type, | |||
| model.Key, | |||
| model.Name, | |||
| model.Description, | |||
| model.NameLocalizations.IsSpecified | |||
| ? model.NameLocalizations.Value?.ToImmutableDictionary() | |||
| : null, | |||
| model.DescriptionLocalizations.IsSpecified | |||
| ? model.DescriptionLocalizations.Value?.ToImmutableDictionary() | |||
| : null)) | |||
| .ToImmutableArray(); | |||
| public static async Task<IReadOnlyCollection<RoleConnectionMetadata>> ModifyRoleConnectionMetadataRecordsAsync(ICollection<RoleConnectionMetadataProperties> metadata, BaseDiscordClient client, RequestOptions options = null) | |||
| => (await client.ApiClient.UpdateApplicationRoleConnectionMetadataRecordsAsync(metadata | |||
| .Select(x => new API.RoleConnectionMetadata | |||
| { | |||
| Name = x.Name, | |||
| Description = x.Description, | |||
| Key = x.Key, | |||
| Type = x.Type, | |||
| NameLocalizations = x.NameLocalizations?.ToDictionary(), | |||
| DescriptionLocalizations = x.DescriptionLocalizations?.ToDictionary() | |||
| }).ToArray())) | |||
| .Select(model | |||
| => new RoleConnectionMetadata( | |||
| model.Type, | |||
| model.Key, | |||
| model.Name, | |||
| model.Description, | |||
| model.NameLocalizations.IsSpecified | |||
| ? model.NameLocalizations.Value?.ToImmutableDictionary() | |||
| : null, | |||
| model.DescriptionLocalizations.IsSpecified | |||
| ? model.DescriptionLocalizations.Value?.ToImmutableDictionary() | |||
| : null)) | |||
| .ToImmutableArray(); | |||
| #endregion | |||
| } | |||
| } | |||
| @@ -4,7 +4,9 @@ using Discord.Net; | |||
| using Discord.Net.Converters; | |||
| using Discord.Net.Queue; | |||
| using Discord.Net.Rest; | |||
| using Newtonsoft.Json; | |||
| using System; | |||
| using System.Collections.Concurrent; | |||
| using System.Collections.Generic; | |||
| @@ -2480,25 +2482,17 @@ namespace Discord.API | |||
| #region Application Role Connections Metadata | |||
| public async Task<IEnumerable<RoleConnectionMetadata>> GetApplicationRoleConnectionMetadataRecordsAsync(RequestOptions options = null) | |||
| { | |||
| return await SendAsync<IEnumerable<RoleConnectionMetadata>>("GET", $"/applications/{CurrentApplicationId}/role-connections/metadata", options: options).ConfigureAwait(false); | |||
| } | |||
| public async Task<RoleConnectionMetadata[]> GetApplicationRoleConnectionMetadataRecordsAsync(RequestOptions options = null) | |||
| => await SendAsync<RoleConnectionMetadata[]>("GET", () => $"applications/{CurrentApplicationId}/role-connections/metadata", new BucketIds(), options: options).ConfigureAwait(false); | |||
| public async Task<IEnumerable<RoleConnectionMetadata>> UpdateApplicationRoleConnectionMetadataRecordsAsync(IEnumerable<RoleConnectionMetadata> roleConnections, RequestOptions options = null) | |||
| { | |||
| return await SendJsonAsync<IEnumerable<RoleConnectionMetadata>>("PUT", $"/applications/{CurrentApplicationId}/role-connections/metadata", roleConnections, options: options).ConfigureAwait(false); | |||
| } | |||
| public async Task<RoleConnectionMetadata[]> UpdateApplicationRoleConnectionMetadataRecordsAsync(RoleConnectionMetadata[] roleConnections, RequestOptions options = null) | |||
| => await SendJsonAsync <RoleConnectionMetadata[]>("PUT", () => $"applications/{CurrentApplicationId}/role-connections/metadata", roleConnections, new BucketIds(), options: options).ConfigureAwait(false); | |||
| public async Task<RoleConnection> GetUserApplicationRoleConnection(RequestOptions options = null) | |||
| { | |||
| return await SendAsync<RoleConnection>("GET", $"/users/@me/applications/{CurrentApplicationId}/role-connection", options: options); | |||
| } | |||
| => await SendAsync<RoleConnection>("GET", () => $"users/@me/applications/{CurrentApplicationId}/role-connection", new BucketIds(), options: options); | |||
| public async Task<RoleConnection> GetUserApplicationRoleConnection(RoleConnection connection, RequestOptions options = null) | |||
| { | |||
| return await SendJsonAsync<RoleConnection>("PUT", $"/users/@me/applications/{CurrentApplicationId}/role-connection", connection, options: options); | |||
| } | |||
| => await SendJsonAsync<RoleConnection>("PUT", () => $"users/@me/applications/{CurrentApplicationId}/role-connection", connection, new BucketIds(), options: options); | |||
| #endregion | |||
| } | |||
| @@ -231,7 +231,17 @@ namespace Discord.Rest | |||
| => MessageHelper.RemoveAllReactionsAsync(channelId, messageId, this, options); | |||
| public Task RemoveAllReactionsForEmoteAsync(ulong channelId, ulong messageId, IEmote emote, RequestOptions options = null) | |||
| => MessageHelper.RemoveAllReactionsForEmoteAsync(channelId, messageId, emote, this, options); | |||
| #endregion | |||
| public Task<IReadOnlyCollection<RoleConnectionMetadata>> GetRoleConnectionMetadataRecordsAsync(RequestOptions options = null) | |||
| => ClientHelper.GetRoleConnectionMetadataRecordsAsync(this, options); | |||
| public Task<IReadOnlyCollection<RoleConnectionMetadata>> ModifyRoleConnectionMetadataRecordsAsync(ICollection<RoleConnectionMetadataProperties> metadata, RequestOptions options = null) | |||
| { | |||
| Preconditions.AtMost(metadata.Count, 5, nameof(metadata), "An application can have a maximum of 5 metadata records."); | |||
| return ClientHelper.ModifyRoleConnectionMetadataRecordsAsync(metadata, this, options); | |||
| } | |||
| #endregion | |||
| #region IDiscordClient | |||
| /// <inheritdoc /> | |||