@@ -12,26 +12,45 @@ namespace Discord | |||||
/// </summary> | /// </summary> | ||||
/// <param name="appId">The application identifier.</param> | /// <param name="appId">The application identifier.</param> | ||||
/// <param name="iconId">The icon identifier.</param> | /// <param name="iconId">The icon identifier.</param> | ||||
/// <param name="format">The format to return. Mustn't be a gif.</param> | |||||
/// <param name="size">The size of the image to return in. This can be any power of two between 16 and 2048.</param> | |||||
/// <returns> | /// <returns> | ||||
/// A URL pointing to the application's icon. | /// A URL pointing to the application's icon. | ||||
/// </returns> | /// </returns> | ||||
public static string GetApplicationIconUrl(ulong appId, string iconId) | |||||
=> iconId != null ? $"{DiscordConfig.CDNUrl}app-icons/{appId}/{iconId}.jpg" : null; | |||||
public static string GetApplicationIconUrl(ulong appId, string iconId, ImageFormat format, ushort size) | |||||
{ | |||||
if (string.IsNullOrWhiteSpace(iconId)) | |||||
return null; | |||||
if (format == ImageFormat.Gif) | |||||
throw new ArgumentException("Requested image format mustn't be a gif."); | |||||
if (!(size >= 16 && size <= 2048)) | |||||
throw new ArgumentOutOfRangeException("Size must be a power of two in a range between 16 and 2048."); | |||||
if ((size & (size - 1)) != 0) | |||||
throw new ArgumentException("Size must be a power of two."); | |||||
string extension = FormatToExtension(format, iconId); | |||||
return $"{DiscordConfig.CDNUrl}app-icons/{appId}/{iconId}.{extension}?size={size}"; | |||||
} | |||||
/// <summary> | /// <summary> | ||||
/// Returns a user avatar URL. | /// Returns a user avatar URL. | ||||
/// </summary> | /// </summary> | ||||
/// <param name="userId">The user snowflake identifier.</param> | /// <param name="userId">The user snowflake identifier.</param> | ||||
/// <param name="avatarId">The avatar identifier.</param> | /// <param name="avatarId">The avatar identifier.</param> | ||||
/// <param name="size">The size of the image to return in. This can be any power of two between 16 and 2048.</param> | |||||
/// <param name="format">The format to return.</param> | /// <param name="format">The format to return.</param> | ||||
/// <param name="size">The size of the image to return in. This can be any power of two between 16 and 2048.</param> | |||||
/// <returns> | /// <returns> | ||||
/// A URL pointing to the user's avatar in the specified size. | /// A URL pointing to the user's avatar in the specified size. | ||||
/// </returns> | /// </returns> | ||||
public static string GetUserAvatarUrl(ulong userId, string avatarId, ushort size, ImageFormat format) | |||||
public static string GetUserAvatarUrl(ulong userId, string avatarId, ImageFormat format, ushort size) | |||||
{ | { | ||||
if (avatarId == null) | |||||
if (string.IsNullOrWhiteSpace(avatarId)) | |||||
return null; | return null; | ||||
if (!(size >= 16 && size <= 2048)) | |||||
throw new ArgumentOutOfRangeException("Size must be a power of two in a range between 16 and 2048."); | |||||
if ((size & (size - 1)) != 0) | |||||
throw new ArgumentException("Size must be a power of two."); | |||||
string extension = FormatToExtension(format, avatarId); | string extension = FormatToExtension(format, avatarId); | ||||
return $"{DiscordConfig.CDNUrl}avatars/{userId}/{avatarId}.{extension}?size={size}"; | return $"{DiscordConfig.CDNUrl}avatars/{userId}/{avatarId}.{extension}?size={size}"; | ||||
} | } | ||||
@@ -51,8 +70,8 @@ namespace Discord | |||||
/// </summary> | /// </summary> | ||||
/// <param name="guildId">The guild snowflake identifier.</param> | /// <param name="guildId">The guild snowflake identifier.</param> | ||||
/// <param name="iconId">The icon identifier.</param> | /// <param name="iconId">The icon identifier.</param> | ||||
/// <param name="format">The format to return. Mustn't be a gif.</param> | |||||
/// <param name="size">The size of the image to return in. This can be any power of two between 16 and 2048.</param> | /// <param name="size">The size of the image to return in. This can be any power of two between 16 and 2048.</param> | ||||
/// <param name="format">The format to return.</param> | |||||
/// <returns> | /// <returns> | ||||
/// A URL pointing to the guild's icon in the specified size. | /// A URL pointing to the guild's icon in the specified size. | ||||
/// </returns> | /// </returns> | ||||
@@ -62,6 +81,10 @@ namespace Discord | |||||
return null; | return null; | ||||
if (format == ImageFormat.Gif) | if (format == ImageFormat.Gif) | ||||
throw new ArgumentException("Requested image format mustn't be a gif."); | throw new ArgumentException("Requested image format mustn't be a gif."); | ||||
if (!(size >= 16 && size <= 2048)) | |||||
throw new ArgumentOutOfRangeException("Size must be a power of two in a range between 16 and 2048."); | |||||
if ((size & (size - 1)) != 0) | |||||
throw new ArgumentException("Size must be a power of two."); | |||||
string extension = FormatToExtension(format, iconId); | string extension = FormatToExtension(format, iconId); | ||||
return $"{DiscordConfig.CDNUrl}icons/{guildId}/{iconId}.{extension}?size={size}"; | return $"{DiscordConfig.CDNUrl}icons/{guildId}/{iconId}.{extension}?size={size}"; | ||||
@@ -71,44 +94,63 @@ namespace Discord | |||||
/// </summary> | /// </summary> | ||||
/// <param name="guildId">The guild snowflake identifier.</param> | /// <param name="guildId">The guild snowflake identifier.</param> | ||||
/// <param name="splashId">The splash icon identifier.</param> | /// <param name="splashId">The splash icon identifier.</param> | ||||
/// <param name="format">The format to return. Mustn't be a gif.</param> | |||||
/// <param name="size">The size of the image to return in. This can be any power of two between 16 and 2048.</param> | |||||
/// <returns> | /// <returns> | ||||
/// A URL pointing to the guild's icon. | /// A URL pointing to the guild's icon. | ||||
/// </returns> | /// </returns> | ||||
public static string GetGuildSplashUrl(ulong guildId, string splashId) | |||||
=> splashId != null ? $"{DiscordConfig.CDNUrl}splashes/{guildId}/{splashId}.jpg" : null; | |||||
/// <summary> | |||||
/// Returns a channel icon URL. | |||||
/// </summary> | |||||
/// <param name="channelId">The channel snowflake identifier.</param> | |||||
/// <param name="iconId">The icon identifier.</param> | |||||
/// <returns> | |||||
/// A URL pointing to the channel's icon. | |||||
/// </returns> | |||||
public static string GetChannelIconUrl(ulong channelId, string iconId) | |||||
=> iconId != null ? $"{DiscordConfig.CDNUrl}channel-icons/{channelId}/{iconId}.jpg" : null; | |||||
public static string GetGuildSplashUrl(ulong guildId, string splashId, ImageFormat format, ushort size) | |||||
{ | |||||
if (string.IsNullOrWhiteSpace(splashId)) | |||||
return null; | |||||
if (format == ImageFormat.Gif) | |||||
throw new ArgumentException("Requested image format mustn't be a gif."); | |||||
if (!(size >= 16 && size <= 2048)) | |||||
throw new ArgumentOutOfRangeException("Size must be a power of two in a range between 16 and 2048."); | |||||
if ((size & (size - 1)) != 0) | |||||
throw new ArgumentException("Size must be a power of two."); | |||||
string extension = FormatToExtension(format, splashId); | |||||
return $"{DiscordConfig.CDNUrl}splashes/{guildId}/{splashId}.{ extension}?size={size}"; | |||||
} | |||||
/// <summary> | /// <summary> | ||||
/// Returns an emoji URL. | /// Returns an emoji URL. | ||||
/// </summary> | /// </summary> | ||||
/// <param name="emojiId">The emoji snowflake identifier.</param> | /// <param name="emojiId">The emoji snowflake identifier.</param> | ||||
/// <param name="animated">Whether this emoji is animated.</param> | /// <param name="animated">Whether this emoji is animated.</param> | ||||
/// <param name="size">The size of the image to return in. This can be any power of two between 16 and 2048.</param> | |||||
/// <returns> | /// <returns> | ||||
/// A URL pointing to the custom emote. | /// A URL pointing to the custom emote. | ||||
/// </returns> | /// </returns> | ||||
public static string GetEmojiUrl(ulong emojiId, bool animated) | |||||
=> $"{DiscordConfig.CDNUrl}emojis/{emojiId}.{(animated ? "gif" : "png")}"; | |||||
public static string GetEmojiUrl(ulong emojiId, bool animated, ushort size) | |||||
{ | |||||
if (!(size >= 16 && size <= 2048)) | |||||
throw new ArgumentOutOfRangeException("Size must be a power of two in a range between 16 and 2048."); | |||||
if ((size & (size - 1)) != 0) | |||||
throw new ArgumentException("Size must be a power of two."); | |||||
return $"{DiscordConfig.CDNUrl}emojis/{emojiId}.{(animated ? "gif" : "png")}?size={size}"; | |||||
} | |||||
/// <summary> | /// <summary> | ||||
/// Returns a Rich Presence asset URL. | /// Returns a Rich Presence asset URL. | ||||
/// </summary> | /// </summary> | ||||
/// <param name="appId">The application identifier.</param> | /// <param name="appId">The application identifier.</param> | ||||
/// <param name="assetId">The asset identifier.</param> | /// <param name="assetId">The asset identifier.</param> | ||||
/// <param name="size">The size of the image to return in. This can be any power of two between 16 and 2048.</param> | |||||
/// <param name="format">The format to return.</param> | /// <param name="format">The format to return.</param> | ||||
/// <param name="size">The size of the image to return in. This can be any power of two between 16 and 2048.</param> | |||||
/// <returns> | /// <returns> | ||||
/// A URL pointing to the asset image in the specified size. | /// A URL pointing to the asset image in the specified size. | ||||
/// </returns> | /// </returns> | ||||
public static string GetRichAssetUrl(ulong appId, string assetId, ushort size, ImageFormat format) | |||||
public static string GetRichAssetUrl(ulong appId, string assetId, ImageFormat format, ushort size) | |||||
{ | { | ||||
if (string.IsNullOrWhiteSpace(assetId)) | |||||
return null; | |||||
if (!(size >= 16 && size <= 2048)) | |||||
throw new ArgumentOutOfRangeException("Size must be a power of two in a range between 16 and 2048."); | |||||
if ((size & (size - 1)) != 0) | |||||
throw new ArgumentException("Size must be a power of two."); | |||||
string extension = FormatToExtension(format, ""); | string extension = FormatToExtension(format, ""); | ||||
return $"{DiscordConfig.CDNUrl}app-assets/{appId}/{assetId}.{extension}?size={size}"; | return $"{DiscordConfig.CDNUrl}app-assets/{appId}/{assetId}.{extension}?size={size}"; | ||||
} | } | ||||
@@ -33,6 +33,6 @@ namespace Discord | |||||
/// A string pointing to the image URL of the asset; <c>null</c> when the application ID does not exist. | /// A string pointing to the image URL of the asset; <c>null</c> when the application ID does not exist. | ||||
/// </returns> | /// </returns> | ||||
public string GetImageUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) | public string GetImageUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) | ||||
=> ApplicationId.HasValue ? CDN.GetRichAssetUrl(ApplicationId.Value, ImageId, size, format) : null; | |||||
=> ApplicationId.HasValue ? CDN.GetRichAssetUrl(ApplicationId.Value, ImageId, format, size) : null; | |||||
} | } | ||||
} | } |
@@ -26,10 +26,11 @@ namespace Discord | |||||
/// <summary> | /// <summary> | ||||
/// Gets the image URL of this emote. | /// Gets the image URL of this emote. | ||||
/// </summary> | /// </summary> | ||||
/// <param name="size">The size of the image to return in. This can be any power of two between 16 and 2048.</param> | |||||
/// <returns> | /// <returns> | ||||
/// A string that points to the URL of this emote. | /// A string that points to the URL of this emote. | ||||
/// </returns> | /// </returns> | ||||
public string Url => CDN.GetEmojiUrl(Id, Animated); | |||||
public string GetUrl(ushort size = 128) => CDN.GetEmojiUrl(Id, Animated, size); | |||||
internal Emote(ulong id, string name, bool animated) | internal Emote(ulong id, string name, bool animated) | ||||
{ | { | ||||
@@ -69,6 +69,8 @@ namespace Discord | |||||
/// <summary> | /// <summary> | ||||
/// Gets the URL of this guild's icon. | /// Gets the URL of this guild's icon. | ||||
/// </summary> | /// </summary> | ||||
/// <param name="format">The format to return. Mustn't be a gif.</param> | |||||
/// <param name="size">The size of the image to return in. This can be any power of two between 16 and 2048.</param> | |||||
/// <returns> | /// <returns> | ||||
/// A URL pointing to the guild's icon; <c>null</c> if none is set. | /// A URL pointing to the guild's icon; <c>null</c> if none is set. | ||||
/// </returns> | /// </returns> | ||||
@@ -83,10 +85,12 @@ namespace Discord | |||||
/// <summary> | /// <summary> | ||||
/// Gets the URL of this guild's splash image. | /// Gets the URL of this guild's splash image. | ||||
/// </summary> | /// </summary> | ||||
/// <param name="format">The format to return. Mustn't be a gif.</param> | |||||
/// <param name="size">The size of the image to return in. This can be any power of two between 16 and 2048.</param> | |||||
/// <returns> | /// <returns> | ||||
/// A URL pointing to the guild's splash image; <c>null</c> if none is set. | /// A URL pointing to the guild's splash image; <c>null</c> if none is set. | ||||
/// </returns> | /// </returns> | ||||
string SplashUrl { get; } | |||||
string GetSplashUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128); | |||||
/// <summary> | /// <summary> | ||||
/// Determines if this guild is currently connected and ready to be used. | /// Determines if this guild is currently connected and ready to be used. | ||||
/// </summary> | /// </summary> | ||||
@@ -21,7 +21,9 @@ namespace Discord | |||||
/// <summary> | /// <summary> | ||||
/// Gets the icon URL of the application. | /// Gets the icon URL of the application. | ||||
/// </summary> | /// </summary> | ||||
string IconUrl { get; } | |||||
/// <param name="format">The format to return. Mustn't be a gif.</param> | |||||
/// <param name="size">The size of the image to return in. This can be any power of two between 16 and 2048.</param> | |||||
string GetIconUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128); | |||||
/// <summary> | /// <summary> | ||||
/// Gets the partial user object containing info on the owner of the application. | /// Gets the partial user object containing info on the owner of the application. | ||||
@@ -62,7 +62,8 @@ namespace Discord.Rest | |||||
public string GetIconUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) | public string GetIconUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) | ||||
=> CDN.GetGuildIconUrl(Id, IconId, format, size); | => CDN.GetGuildIconUrl(Id, IconId, format, size); | ||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public string SplashUrl => CDN.GetGuildSplashUrl(Id, SplashId); | |||||
public string GetSplashUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) | |||||
=> CDN.GetGuildSplashUrl(Id, SplashId, format, size); | |||||
/// <summary> | /// <summary> | ||||
/// Gets the built-in role containing all users in this guild. | /// Gets the built-in role containing all users in this guild. | ||||
@@ -28,7 +28,8 @@ namespace Discord.Rest | |||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); | public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); | ||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public string IconUrl => CDN.GetApplicationIconUrl(Id, _iconId); | |||||
public string GetIconUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) | |||||
=> CDN.GetApplicationIconUrl(Id, _iconId, format, size); | |||||
internal RestApplication(BaseDiscordClient discord, ulong id) | internal RestApplication(BaseDiscordClient discord, ulong id) | ||||
: base(discord, id) | : base(discord, id) | ||||
@@ -80,7 +80,7 @@ namespace Discord.Rest | |||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) | public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) | ||||
=> CDN.GetUserAvatarUrl(Id, AvatarId, size, format); | |||||
=> CDN.GetUserAvatarUrl(Id, AvatarId, format, size); | |||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public string GetDefaultAvatarUrl() | public string GetDefaultAvatarUrl() | ||||
@@ -75,7 +75,7 @@ namespace Discord.Rest | |||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) | public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) | ||||
=> CDN.GetUserAvatarUrl(Id, AvatarId, size, format); | |||||
=> CDN.GetUserAvatarUrl(Id, AvatarId, format, size); | |||||
public async Task ModifyAsync(Action<WebhookProperties> func, RequestOptions options = null) | public async Task ModifyAsync(Action<WebhookProperties> func, RequestOptions options = null) | ||||
{ | { | ||||
@@ -100,7 +100,8 @@ namespace Discord.WebSocket | |||||
public string GetIconUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) | public string GetIconUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) | ||||
=> CDN.GetGuildIconUrl(Id, IconId, format, size); | => CDN.GetGuildIconUrl(Id, IconId, format, size); | ||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public string SplashUrl => CDN.GetGuildSplashUrl(Id, SplashId); | |||||
public string GetSplashUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) => | |||||
CDN.GetGuildSplashUrl(Id, SplashId, format, size); | |||||
/// <summary> Indicates whether the client has all the members downloaded to the local guild cache. </summary> | /// <summary> Indicates whether the client has all the members downloaded to the local guild cache. </summary> | ||||
public bool HasAllMembers => MemberCount == DownloadedMemberCount;// _downloaderPromise.Task.IsCompleted; | public bool HasAllMembers => MemberCount == DownloadedMemberCount;// _downloaderPromise.Task.IsCompleted; | ||||
/// <summary> Indicates whether the guild cache is synced to this guild. </summary> | /// <summary> Indicates whether the guild cache is synced to this guild. </summary> | ||||
@@ -84,7 +84,7 @@ namespace Discord.WebSocket | |||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) | public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) | ||||
=> CDN.GetUserAvatarUrl(Id, AvatarId, size, format); | |||||
=> CDN.GetUserAvatarUrl(Id, AvatarId, format, size); | |||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public string GetDefaultAvatarUrl() | public string GetDefaultAvatarUrl() | ||||
@@ -1,4 +1,4 @@ | |||||
using System; | |||||
using System; | |||||
using System.Diagnostics; | using System.Diagnostics; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
using Model = Discord.API.Webhook; | using Model = Discord.API.Webhook; | ||||
@@ -45,7 +45,7 @@ namespace Discord.Webhook | |||||
} | } | ||||
public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) | public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) | ||||
=> CDN.GetUserAvatarUrl(Id, AvatarId, size, format); | |||||
=> CDN.GetUserAvatarUrl(Id, AvatarId, format, size); | |||||
public async Task ModifyAsync(Action<WebhookProperties> func, RequestOptions options = null) | public async Task ModifyAsync(Action<WebhookProperties> func, RequestOptions options = null) | ||||
{ | { | ||||
@@ -14,7 +14,7 @@ namespace Discord | |||||
Assert.Equal(394207658351263745UL, emote.Id); | Assert.Equal(394207658351263745UL, emote.Id); | ||||
Assert.False(emote.Animated); | Assert.False(emote.Animated); | ||||
Assert.Equal(DateTimeOffset.FromUnixTimeMilliseconds(1514056829775), emote.CreatedAt); | Assert.Equal(DateTimeOffset.FromUnixTimeMilliseconds(1514056829775), emote.CreatedAt); | ||||
Assert.EndsWith("png", emote.Url); | |||||
Assert.EndsWith("png", emote.GetUrl()); | |||||
} | } | ||||
[Fact] | [Fact] | ||||
public void Test_Invalid_Emote_Parse() | public void Test_Invalid_Emote_Parse() | ||||
@@ -32,7 +32,7 @@ namespace Discord | |||||
Assert.Equal(394207658351263745UL, emote.Id); | Assert.Equal(394207658351263745UL, emote.Id); | ||||
Assert.True(emote.Animated); | Assert.True(emote.Animated); | ||||
Assert.Equal(DateTimeOffset.FromUnixTimeMilliseconds(1514056829775), emote.CreatedAt); | Assert.Equal(DateTimeOffset.FromUnixTimeMilliseconds(1514056829775), emote.CreatedAt); | ||||
Assert.EndsWith("gif", emote.Url); | |||||
Assert.EndsWith("gif", emote.GetUrl()); | |||||
} | } | ||||
[Fact] | [Fact] | ||||
public void Test_Invalid_Amimated_Emote_Parse() | public void Test_Invalid_Amimated_Emote_Parse() | ||||