@@ -1,3 +1,4 @@ | |||||
using System; | |||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Collections.Immutable; | using System.Collections.Immutable; | ||||
@@ -5,26 +6,58 @@ namespace Discord; | |||||
public class RoleConnectionMetadata | public class RoleConnectionMetadata | ||||
{ | { | ||||
/// <summary> | |||||
/// Gets the of metadata value. | |||||
/// </summary> | |||||
public RoleConnectionMetadataType Type { get; } | public RoleConnectionMetadataType Type { get; } | ||||
/// <summary> | |||||
/// Gets the dictionary key for the metadata field. | |||||
/// </summary> | |||||
public string Key { get; } | 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 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, | 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; | Type = type; | ||||
Key = key; | Key = key; | ||||
Name = name; | Name = name; | ||||
Description = description; | 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; } | public string Description { get; set; } | ||||
[JsonProperty("name_localizations")] | [JsonProperty("name_localizations")] | ||||
public Optional<IReadOnlyCollection<KeyValuePair<string, string>>> NameLocalizations { get; set; } | |||||
public Optional<Dictionary<string, string>> NameLocalizations { get; set; } | |||||
[JsonProperty("description_localizations")] | [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) | public static Task RemoveRoleAsync(BaseDiscordClient client, ulong guildId, ulong userId, ulong roleId, RequestOptions options = null) | ||||
=> client.ApiClient.RemoveRoleAsync(guildId, userId, roleId, options); | => client.ApiClient.RemoveRoleAsync(guildId, userId, roleId, options); | ||||
#endregion | #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.Converters; | ||||
using Discord.Net.Queue; | using Discord.Net.Queue; | ||||
using Discord.Net.Rest; | using Discord.Net.Rest; | ||||
using Newtonsoft.Json; | using Newtonsoft.Json; | ||||
using System; | using System; | ||||
using System.Collections.Concurrent; | using System.Collections.Concurrent; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
@@ -2480,25 +2482,17 @@ namespace Discord.API | |||||
#region Application Role Connections Metadata | #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) | 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) | 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 | #endregion | ||||
} | } | ||||
@@ -231,7 +231,17 @@ namespace Discord.Rest | |||||
=> MessageHelper.RemoveAllReactionsAsync(channelId, messageId, this, options); | => MessageHelper.RemoveAllReactionsAsync(channelId, messageId, this, options); | ||||
public Task RemoveAllReactionsForEmoteAsync(ulong channelId, ulong messageId, IEmote emote, RequestOptions options = null) | public Task RemoveAllReactionsForEmoteAsync(ulong channelId, ulong messageId, IEmote emote, RequestOptions options = null) | ||||
=> MessageHelper.RemoveAllReactionsForEmoteAsync(channelId, messageId, emote, this, options); | => 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 | #region IDiscordClient | ||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||