@@ -2,13 +2,19 @@ using System; | |||
namespace Discord | |||
{ | |||
/// <summary> A class containing the strings related to various Content Delivery Networks (CDNs). </summary> | |||
/// <summary> | |||
/// A class containing the strings related to various Content Delivery Networks (CDNs). | |||
/// </summary> | |||
public static class CDN | |||
{ | |||
/// <summary> Returns the Discord developer application icon. </summary> | |||
/// <summary> | |||
/// Returns the Discord developer application icon. | |||
/// </summary> | |||
public static string GetApplicationIconUrl(ulong appId, string iconId) | |||
=> iconId != null ? $"{DiscordConfig.CDNUrl}app-icons/{appId}/{iconId}.jpg" : null; | |||
/// <summary> Returns the user avatar URL based on the size and <see cref="ImageFormat"/>. </summary> | |||
/// <summary> | |||
/// Returns the user avatar URL based on the <paramref name="size"/> and <see cref="ImageFormat" /> . | |||
/// </summary> | |||
public static string GetUserAvatarUrl(ulong userId, string avatarId, ushort size, ImageFormat format) | |||
{ | |||
if (avatarId == null) | |||
@@ -16,31 +22,47 @@ namespace Discord | |||
string extension = FormatToExtension(format, avatarId); | |||
return $"{DiscordConfig.CDNUrl}avatars/{userId}/{avatarId}.{extension}?size={size}"; | |||
} | |||
/// <summary> Returns the default user avatar URL. </summary> | |||
/// <summary> | |||
/// Returns the default user avatar URL. | |||
/// </summary> | |||
/// <param name="discriminator">The discriminator value of a user.</param> | |||
public static string GetDefaultUserAvatarUrl(ushort discriminator) | |||
{ | |||
return $"{DiscordConfig.CDNUrl}embed/avatars/{discriminator % 5}.png"; | |||
} | |||
/// <summary> | |||
/// Returns the icon URL associated with the given guild ID. | |||
/// </summary> | |||
public static string GetGuildIconUrl(ulong guildId, string iconId) | |||
=> iconId != null ? $"{DiscordConfig.CDNUrl}icons/{guildId}/{iconId}.jpg" : null; | |||
/// <summary> Returns the guild splash URL based on the guild and icon ID. </summary> | |||
/// <summary> | |||
/// Returns the guild splash URL associated with the given guild and splash ID. | |||
/// </summary> | |||
public static string GetGuildSplashUrl(ulong guildId, string splashId) | |||
=> splashId != null ? $"{DiscordConfig.CDNUrl}splashes/{guildId}/{splashId}.jpg" : null; | |||
/// <summary> Returns the channel icon URL based on the guild and icon ID. </summary> | |||
/// <summary> | |||
/// Returns the channel icon URL associated with the given guild and icon ID. | |||
/// </summary> | |||
public static string GetChannelIconUrl(ulong channelId, string iconId) | |||
=> iconId != null ? $"{DiscordConfig.CDNUrl}channel-icons/{channelId}/{iconId}.jpg" : null; | |||
/// <summary> Returns the emoji URL based on the emoji ID. </summary> | |||
/// <summary> | |||
/// Returns the emoji URL based on the emoji ID. | |||
/// </summary> | |||
public static string GetEmojiUrl(ulong emojiId, bool animated) | |||
=> $"{DiscordConfig.CDNUrl}emojis/{emojiId}.{(animated ? "gif" : "png")}"; | |||
/// <summary> Returns the rich presence asset URL based on the asset ID and <see cref="ImageFormat"/>. </summary> | |||
/// <summary> | |||
/// Returns the rich presence asset URL based on the asset ID and <see cref="ImageFormat" /> . | |||
/// </summary> | |||
public static string GetRichAssetUrl(ulong appId, string assetId, ushort size, ImageFormat format) | |||
{ | |||
string extension = FormatToExtension(format, ""); | |||
return $"{DiscordConfig.CDNUrl}app-assets/{appId}/{assetId}.{extension}?size={size}"; | |||
} | |||
/// <summary> Returns the Spotify album URL based on the album art ID. </summary> | |||
/// <summary> | |||
/// Returns the Spotify album URL based on the album art ID. | |||
/// </summary> | |||
public static string GetSpotifyAlbumArtUrl(string albumArtId) | |||
=> $"https://i.scdn.co/image/{albumArtId}"; | |||
@@ -2,43 +2,74 @@ using System.Reflection; | |||
namespace Discord | |||
{ | |||
/// <summary> | |||
/// Defines various behaviors of Discord.Net. | |||
/// </summary> | |||
public class DiscordConfig | |||
{ | |||
/// <summary> Returns the gateway version Discord.Net uses. </summary> | |||
/// <summary> | |||
/// Returns the gateway version Discord.Net uses. | |||
/// </summary> | |||
public const int APIVersion = 6; | |||
/// <summary> Returns the Discord.Net version, including the build number. </summary> | |||
/// <summary> | |||
/// Gets the Discord.Net version, including the build number. | |||
/// </summary> | |||
public static string Version { get; } = | |||
typeof(DiscordConfig).GetTypeInfo().Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion ?? | |||
typeof(DiscordConfig).GetTypeInfo().Assembly.GetName().Version.ToString(3) ?? | |||
"Unknown"; | |||
/// <summary> Returns the user agent that Discord.Net uses in its clients. </summary> | |||
/// <summary> | |||
/// Gets the user agent that Discord.Net uses in its clients. | |||
/// </summary> | |||
public static string UserAgent { get; } = $"DiscordBot (https://github.com/RogueException/Discord.Net, v{Version})"; | |||
/// <summary> Returns the base Discord API URL. </summary> | |||
/// <summary> | |||
/// Returns the base Discord API URL. | |||
/// </summary> | |||
public static readonly string APIUrl = $"https://discordapp.com/api/v{APIVersion}/"; | |||
/// <summary> Returns the base Discord CDN URL. </summary> | |||
/// <summary> | |||
/// Returns the base Discord CDN URL. | |||
/// </summary> | |||
public const string CDNUrl = "https://cdn.discordapp.com/"; | |||
/// <summary> Returns the base Discord invite URL. </summary> | |||
/// <summary> | |||
/// Returns the base Discord invite URL. | |||
/// </summary> | |||
public const string InviteUrl = "https://discord.gg/"; | |||
/// <summary> Returns the default timeout for requests. </summary> | |||
/// <summary> | |||
/// Returns the default timeout for requests. | |||
/// </summary> | |||
public const int DefaultRequestTimeout = 15000; | |||
/// <summary> Returns the max length for a Discord message. </summary> | |||
/// <summary> | |||
/// Returns the max length for a Discord message. | |||
/// </summary> | |||
public const int MaxMessageSize = 2000; | |||
/// <summary> Returns the max messages allowed to be in a request. </summary> | |||
/// <summary> | |||
/// Returns the max messages allowed to be in a request. | |||
/// </summary> | |||
public const int MaxMessagesPerBatch = 100; | |||
/// <summary> Returns the max users allowed to be in a request. </summary> | |||
/// <summary> | |||
/// Returns the max users allowed to be in a request. | |||
/// </summary> | |||
public const int MaxUsersPerBatch = 1000; | |||
/// <summary> Returns the max guilds allowed to be in a request. </summary> | |||
/// <summary> | |||
/// Returns the max guilds allowed to be in a request. | |||
/// </summary> | |||
public const int MaxGuildsPerBatch = 100; | |||
/// <summary> Gets or sets how a request should act in the case of an error, by default. </summary> | |||
/// <summary> | |||
/// Gets or sets how a request should act in the case of an error, by default. | |||
/// </summary> | |||
public RetryMode DefaultRetryMode { get; set; } = RetryMode.AlwaysRetry; | |||
/// <summary> Gets or sets the minimum log level severity that will be sent to the Log event. </summary> | |||
/// <summary> | |||
/// Gets or sets the minimum log level severity that will be sent to the Log event. | |||
/// </summary> | |||
public LogSeverity LogLevel { get; set; } = LogSeverity.Info; | |||
/// <summary> Gets or sets whether the initial log entry should be printed. </summary> | |||
/// <summary> | |||
/// Gets or sets whether the initial log entry should be printed. | |||
/// </summary> | |||
internal bool DisplayInitialLog { get; set; } = true; | |||
} | |||
} |
@@ -25,6 +25,10 @@ namespace Discord | |||
Name = unicode; | |||
} | |||
/// <summary> | |||
/// Determines whether the specified emoji is equal to the current emoji. | |||
/// </summary> | |||
/// <param name="obj">The object to compare with the current object.</param> | |||
public override bool Equals(object other) | |||
{ | |||
if (other == null) return false; | |||
@@ -36,6 +40,7 @@ namespace Discord | |||
return string.Equals(Name, otherEmoji.Name); | |||
} | |||
/// <inheritdoc /> | |||
public override int GetHashCode() => Name.GetHashCode(); | |||
} | |||
} |
@@ -5,6 +5,9 @@ using System.Threading.Tasks; | |||
namespace Discord | |||
{ | |||
/// <summary> | |||
/// Represents a generic guild object. | |||
/// </summary> | |||
public interface IGuild : IDeletable, ISnowflakeEntity | |||
{ | |||
/// <summary> | |||
@@ -17,7 +20,7 @@ namespace Discord | |||
/// </summary> | |||
int AFKTimeout { get; } | |||
/// <summary> | |||
/// Returns <see langword="true"/> if this guild is embeddable (e.g. widget) | |||
/// Returns <see langword="true"/> if this guild is embeddable (e.g. widget). | |||
/// </summary> | |||
bool IsEmbeddable { get; } | |||
/// <summary> | |||
@@ -68,7 +71,7 @@ namespace Discord | |||
/// </summary> | |||
ulong? EmbedChannelId { get; } | |||
/// <summary> | |||
/// Gets the ID of the channel where randomized welcome messages are sent, or <see langword="null"/> if not. | |||
/// Gets the ID of the channel where randomized welcome messages are sent if set, or <see langword="null"/> if not. | |||
/// </summary> | |||
ulong? SystemChannelId { get; } | |||
/// <summary> | |||
@@ -1,14 +1,22 @@ | |||
namespace Discord | |||
namespace Discord | |||
{ | |||
public interface IUserGuild : IDeletable, ISnowflakeEntity | |||
{ | |||
/// <summary> Gets the name of this guild. </summary> | |||
/// <summary> | |||
/// Gets the name of this guild. | |||
/// </summary> | |||
string Name { get; } | |||
/// <summary> Returns the url to this guild's icon, or null if one is not set. </summary> | |||
/// <summary> | |||
/// Gets the icon URL associated with this guild, or <see langword="null"/> if one is not set. | |||
/// </summary> | |||
string IconUrl { get; } | |||
/// <summary> Returns true if the current user owns this guild. </summary> | |||
/// <summary> | |||
/// Returns <see langword="true"/> if the current user owns this guild. | |||
/// </summary> | |||
bool IsOwner { get; } | |||
/// <summary> Returns the current user's permissions for this guild. </summary> | |||
/// <summary> | |||
/// Returns the current user's permissions for this guild. | |||
/// </summary> | |||
GuildPermissions Permissions { get; } | |||
} | |||
} |
@@ -1,4 +1,4 @@ | |||
using System.IO; | |||
using System.IO; | |||
namespace Discord | |||
{ | |||
/// <summary> | |||
@@ -6,6 +6,9 @@ namespace Discord | |||
/// </summary> | |||
public struct Image | |||
{ | |||
/// <summary> | |||
/// Gets the stream to be uploaded to Discord. | |||
/// </summary> | |||
public Stream Stream { get; } | |||
/// <summary> | |||
/// Create the image with a <see cref="System.IO.Stream" /> . | |||
@@ -2,6 +2,9 @@ using System.Threading.Tasks; | |||
namespace Discord | |||
{ | |||
/// <summary> | |||
/// Represents a generic invite object. | |||
/// </summary> | |||
public interface IInvite : IEntity<string>, IDeletable | |||
{ | |||
/// <summary> | |||
@@ -5,6 +5,9 @@ using System.Linq; | |||
namespace Discord | |||
{ | |||
/// <summary> | |||
/// Represents an embed object seen in an <see cref="IUserMessage" />. | |||
/// </summary> | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public class Embed : IEmbed | |||
{ | |||
@@ -70,8 +73,14 @@ namespace Discord | |||
Fields = fields; | |||
} | |||
/// <summary> | |||
/// Gets the total length of all embed properties. | |||
/// </summary> | |||
public int Length => Title?.Length + Author?.Name?.Length + Description?.Length + Footer?.Text?.Length + Fields.Sum(f => f.Name.Length + f.Value.ToString().Length) ?? 0; | |||
/// <summary> | |||
/// Gets the title of the embed. | |||
/// </summary> | |||
public override string ToString() => Title; | |||
private string DebuggerDisplay => $"{Title} ({Type})"; | |||
} | |||
@@ -3,17 +3,27 @@ using System.Diagnostics; | |||
namespace Discord | |||
{ | |||
/// <summary> An author field for an <see cref="Embed"/>. </summary> | |||
/// <summary> | |||
/// Represents a author field of an <see cref="Embed" />. | |||
/// </summary> | |||
[DebuggerDisplay("{DebuggerDisplay,nq}")] | |||
public struct EmbedAuthor | |||
{ | |||
/// <summary> Gets the name of the author field.</summary> | |||
/// <summary> | |||
/// Gets the name of the author field. | |||
/// </summary> | |||
public string Name { get; internal set; } | |||
/// <summary> Gets the URL of the author field.</summary> | |||
/// <summary> | |||
/// Gets the URL of the author field. | |||
/// </summary> | |||
public string Url { get; internal set; } | |||
/// <summary> Gets the icon URL of the author field.</summary> | |||
/// <summary> | |||
/// Gets the icon URL of the author field. | |||
/// </summary> | |||
public string IconUrl { get; internal set; } | |||
/// <summary> Gets the proxified icon URL of the author field.</summary> | |||
/// <summary> | |||
/// Gets the proxified icon URL of the author field. | |||
/// </summary> | |||
public string ProxyIconUrl { get; internal set; } | |||
internal EmbedAuthor(string name, string url, string iconUrl, string proxyIconUrl) | |||
@@ -25,6 +35,12 @@ namespace Discord | |||
} | |||
private string DebuggerDisplay => $"{Name} ({Url})"; | |||
/// <summary> | |||
/// Gets the name of the author field. | |||
/// </summary> | |||
/// <returns> | |||
/// | |||
/// </returns> | |||
public override string ToString() => Name; | |||
} | |||
} |
@@ -5,7 +5,9 @@ using System.Linq; | |||
namespace Discord | |||
{ | |||
/// <summary> A builder for creating an <see cref="Embed"/> to be sent. </summary> | |||
/// <summary> | |||
/// Represents a builder class for creating a <see cref="EmbedType.Rich"/> <see cref="Embed" />. | |||
/// </summary> | |||
public class EmbedBuilder | |||
{ | |||
private string _title; | |||
@@ -15,16 +17,24 @@ namespace Discord | |||
private EmbedThumbnail? _thumbnail; | |||
private List<EmbedFieldBuilder> _fields; | |||
/// <summary> The maximum number of fields allowed by Discord. </summary> | |||
/// <summary> | |||
/// Returns the maximum number of fields allowed by Discord. | |||
/// </summary> | |||
public const int MaxFieldCount = 25; | |||
/// <summary> The maximum length of title allowed by Discord. </summary> | |||
/// <summary> | |||
/// Returns the maximum length of title allowed by Discord. | |||
/// </summary> | |||
public const int MaxTitleLength = 256; | |||
/// <summary> The maximum length of description allowed by Discord. </summary> | |||
/// <summary> | |||
/// Returns the maximum length of description allowed by Discord. | |||
/// </summary> | |||
public const int MaxDescriptionLength = 2048; | |||
/// <summary> The maximum length of total characters allowed by Discord. </summary> | |||
/// <summary> | |||
/// Returns the maximum length of total characters allowed by Discord. | |||
/// </summary> | |||
public const int MaxEmbedLength = 6000; | |||
/// <summary> Creates a new <see cref="EmbedBuilder"/>. </summary> | |||
/// <summary> Initializes a new <see cref="EmbedBuilder"/> class. </summary> | |||
public EmbedBuilder() | |||
{ | |||
Fields = new List<EmbedFieldBuilder>(); | |||
@@ -102,6 +112,9 @@ namespace Discord | |||
/// <summary> Gets or sets the <see cref="EmbedFooterBuilder"/> of an <see cref="Embed"/>. </summary> | |||
public EmbedFooterBuilder Footer { get; set; } | |||
/// <summary> | |||
/// Gets the total length of all embed properties. | |||
/// </summary> | |||
public int Length | |||
{ | |||
get | |||
@@ -116,69 +129,91 @@ namespace Discord | |||
} | |||
} | |||
/// <summary> | |||
/// Sets the title of an <see cref="Embed" />. | |||
/// </summary> | |||
/// <param name="title">The title to be set.</param> | |||
public EmbedBuilder WithTitle(string title) | |||
{ | |||
Title = title; | |||
return this; | |||
} | |||
/// <summary> Sets the description of an <see cref="Embed"/>. </summary> | |||
/// <summary> | |||
/// Sets the description of an <see cref="Embed"/>. | |||
/// </summary> | |||
/// <param name="description"> The description to be set. </param> | |||
public EmbedBuilder WithDescription(string description) | |||
{ | |||
Description = description; | |||
return this; | |||
} | |||
/// <summary> Sets the URL of an <see cref="Embed"/>. </summary> | |||
/// <summary> | |||
/// Sets the URL of an <see cref="Embed"/>. | |||
/// </summary> | |||
/// <param name="url"> The URL to be set. </param> | |||
public EmbedBuilder WithUrl(string url) | |||
{ | |||
Url = url; | |||
return this; | |||
} | |||
/// <summary> Sets the thumbnail URL of an <see cref="Embed"/>. </summary> | |||
/// <summary> | |||
/// Sets the thumbnail URL of an <see cref="Embed"/>. | |||
/// </summary> | |||
/// <param name="thumbnailUrl"> The thumbnail URL to be set. </param> | |||
public EmbedBuilder WithThumbnailUrl(string thumbnailUrl) | |||
{ | |||
ThumbnailUrl = thumbnailUrl; | |||
return this; | |||
} | |||
/// <summary> Sets the image URL of an <see cref="Embed"/>. </summary> | |||
/// <param name="imageUrl"> The image URL to be set. </param> | |||
/// <summary> | |||
/// Sets the image URL of an <see cref="Embed" /> . | |||
/// </summary> | |||
/// <param name="imageUrl">The image URL to be set.</param> | |||
public EmbedBuilder WithImageUrl(string imageUrl) | |||
{ | |||
ImageUrl = imageUrl; | |||
return this; | |||
} | |||
/// <summary> Sets the timestamp of an <see cref="Embed"/> to the current time. </summary> | |||
/// <summary> | |||
/// Sets the timestamp of an <see cref="Embed" /> to the current time. | |||
/// </summary> | |||
public EmbedBuilder WithCurrentTimestamp() | |||
{ | |||
Timestamp = DateTimeOffset.UtcNow; | |||
return this; | |||
} | |||
/// <summary> Sets the timestamp of an <see cref="Embed"/>. </summary> | |||
/// <param name="dateTimeOffset"> The timestamp to be set. </param> | |||
/// <summary> | |||
/// Sets the timestamp of an <see cref="Embed" /> . | |||
/// </summary> | |||
/// <param name="dateTimeOffset">The timestamp to be set.</param> | |||
public EmbedBuilder WithTimestamp(DateTimeOffset dateTimeOffset) | |||
{ | |||
Timestamp = dateTimeOffset; | |||
return this; | |||
} | |||
/// <summary> Sets the sidebar color of an <see cref="Embed"/>. </summary> | |||
/// <param name="color"> The color to be set. </param> | |||
/// <summary> | |||
/// Sets the sidebar color of an <see cref="Embed" /> . | |||
/// </summary> | |||
/// <param name="color">The color to be set.</param> | |||
public EmbedBuilder WithColor(Color color) | |||
{ | |||
Color = color; | |||
return this; | |||
} | |||
/// <summary> Sets the <see cref="EmbedAuthorBuilder"/> of an <see cref="Embed"/>. </summary> | |||
/// <param name="author"> The author builder class containing the author field properties. </param> | |||
/// <summary> | |||
/// Sets the <see cref="EmbedAuthorBuilder" /> of an <see cref="Embed" /> . | |||
/// </summary> | |||
/// <param name="author">The author builder class containing the author field properties.</param> | |||
public EmbedBuilder WithAuthor(EmbedAuthorBuilder author) | |||
{ | |||
Author = author; | |||
return this; | |||
} | |||
/// <summary> Sets the author field of an <see cref="Embed"/> with the provided properties. </summary> | |||
/// <param name="action"> The delegate containing the author field properties. </param> | |||
/// <summary> | |||
/// Sets the author field of an <see cref="Embed" /> with the provided properties. | |||
/// </summary> | |||
/// <param name="action">The <see langword="delegate"/> containing the author field properties.</param> | |||
public EmbedBuilder WithAuthor(Action<EmbedAuthorBuilder> action) | |||
{ | |||
var author = new EmbedAuthorBuilder(); | |||
@@ -186,10 +221,12 @@ namespace Discord | |||
Author = author; | |||
return this; | |||
} | |||
/// <summary> Sets the author field of an <see cref="Embed"/> with the provided name, icon URL, and URL. </summary> | |||
/// <param name="name"> The title of the author field. </param> | |||
/// <param name="iconUrl"> The icon URL of the author field. </param> | |||
/// <param name="url"> The URL of the author field. </param> | |||
/// <summary> | |||
/// Sets the author field of an <see cref="Embed" /> with the provided name, icon URL, and URL. | |||
/// </summary> | |||
/// <param name="name">The title of the author field.</param> | |||
/// <param name="iconUrl">The icon URL of the author field.</param> | |||
/// <param name="url">The URL of the author field.</param> | |||
public EmbedBuilder WithAuthor(string name, string iconUrl = null, string url = null) | |||
{ | |||
var author = new EmbedAuthorBuilder | |||
@@ -201,15 +238,19 @@ namespace Discord | |||
Author = author; | |||
return this; | |||
} | |||
/// <summary> Sets the <see cref="EmbedFooterBuilder"/> of an <see cref="Embed"/>. </summary> | |||
/// <param name="footer"> The footer builder class containing the footer field properties. </param> | |||
/// <summary> | |||
/// Sets the <see cref="EmbedFooterBuilder" /> of an <see cref="Embed" /> . | |||
/// </summary> | |||
/// <param name="footer">The footer builder class containing the footer field properties.</param> | |||
public EmbedBuilder WithFooter(EmbedFooterBuilder footer) | |||
{ | |||
Footer = footer; | |||
return this; | |||
} | |||
/// <summary> Sets the footer field of an <see cref="Embed"/> with the provided properties. </summary> | |||
/// <param name="action"> The delegate containing the footer field properties. </param> | |||
/// <summary> | |||
/// Sets the footer field of an <see cref="Embed" /> with the provided properties. | |||
/// </summary> | |||
/// <param name="action">The <see langword="delegate"/> containing the footer field properties.</param> | |||
public EmbedBuilder WithFooter(Action<EmbedFooterBuilder> action) | |||
{ | |||
var footer = new EmbedFooterBuilder(); | |||
@@ -217,9 +258,11 @@ namespace Discord | |||
Footer = footer; | |||
return this; | |||
} | |||
/// <summary> Sets the footer field of an <see cref="Embed"/> with the provided name, icon URL. </summary> | |||
/// <param name="text"> The title of the footer field. </param> | |||
/// <param name="iconUrl"> The icon URL of the footer field. </param> | |||
/// <summary> | |||
/// Sets the footer field of an <see cref="Embed" /> with the provided name, icon URL. | |||
/// </summary> | |||
/// <param name="text">The title of the footer field.</param> | |||
/// <param name="iconUrl">The icon URL of the footer field.</param> | |||
public EmbedBuilder WithFooter(string text, string iconUrl = null) | |||
{ | |||
var footer = new EmbedFooterBuilder | |||
@@ -231,10 +274,12 @@ namespace Discord | |||
return this; | |||
} | |||
/// <summary> Adds an <see cref="Embed"/> field with the provided name and value. </summary> | |||
/// <param name="name"> The title of the field. </param> | |||
/// <param name="value"> The value of the field. </param> | |||
/// <param name="inline"> Indicates whether the field is in-line or not. </param> | |||
/// <summary> | |||
/// Adds an <see cref="Embed" /> field with the provided name and value. | |||
/// </summary> | |||
/// <param name="name">The title of the field.</param> | |||
/// <param name="value">The value of the field.</param> | |||
/// <param name="inline">Indicates whether the field is in-line or not.</param> | |||
public EmbedBuilder AddField(string name, object value, bool inline = false) | |||
{ | |||
var field = new EmbedFieldBuilder() | |||
@@ -244,8 +289,11 @@ namespace Discord | |||
AddField(field); | |||
return this; | |||
} | |||
/// <summary> Adds a field with the provided <see cref="EmbedFieldBuilder"/> to an <see cref="Embed"/>. </summary> | |||
/// <param name="field"> The field builder class containing the field properties. </param> | |||
/// <summary> | |||
/// Adds a field with the provided <see cref="EmbedFieldBuilder" /> to an | |||
/// <see cref="Embed" />. | |||
/// </summary> | |||
/// <param name="field">The field builder class containing the field properties.</param> | |||
public EmbedBuilder AddField(EmbedFieldBuilder field) | |||
{ | |||
if (Fields.Count >= MaxFieldCount) | |||
@@ -256,8 +304,10 @@ namespace Discord | |||
Fields.Add(field); | |||
return this; | |||
} | |||
/// <summary> Adds an <see cref="Embed"/> field with the provided properties. </summary> | |||
/// <param name="action"> The delegate containing the field properties. </param> | |||
/// <summary> | |||
/// Adds an <see cref="Embed" /> field with the provided properties. | |||
/// </summary> | |||
/// <param name="action">The <see langword="delegate"/> containing the field properties.</param> | |||
public EmbedBuilder AddField(Action<EmbedFieldBuilder> action) | |||
{ | |||
var field = new EmbedFieldBuilder(); | |||
@@ -266,8 +316,12 @@ namespace Discord | |||
return this; | |||
} | |||
/// <summary> Builds the <see cref="Embed"/> into a Rich Embed format. </summary> | |||
/// <returns> The built embed object. </returns> | |||
/// <summary> | |||
/// Builds the <see cref="Embed" /> into a Rich Embed format. | |||
/// </summary> | |||
/// <returns> | |||
/// The built embed object. | |||
/// </returns> | |||
public Embed Build() | |||
{ | |||
if (Length > MaxEmbedLength) | |||
@@ -286,9 +340,18 @@ namespace Discord | |||
private string _name; | |||
private string _value; | |||
private EmbedField _field; | |||
/// <summary> | |||
/// Gets the maximum field length for name allowed by Discord. | |||
/// </summary> | |||
public const int MaxFieldNameLength = 256; | |||
/// <summary> | |||
/// Gets the maximum field length for value allowed by Discord. | |||
/// </summary> | |||
public const int MaxFieldValueLength = 1024; | |||
/// <summary> | |||
/// Gets or sets the field name. | |||
/// </summary> | |||
public string Name | |||
{ | |||
get => _name; | |||
@@ -300,6 +363,9 @@ namespace Discord | |||
} | |||
} | |||
/// <summary> | |||
/// Gets or sets the field value. | |||
/// </summary> | |||
public object Value | |||
{ | |||
get => _value; | |||
@@ -311,24 +377,41 @@ namespace Discord | |||
_value = stringValue; | |||
} | |||
} | |||
/// <summary> | |||
/// Gets or sets whether the field should be in-line with each other. | |||
/// </summary> | |||
public bool IsInline { get; set; } | |||
/// <summary> | |||
/// Sets the field name. | |||
/// </summary> | |||
/// <param name="name">The name to set the field name to.</param> | |||
public EmbedFieldBuilder WithName(string name) | |||
{ | |||
Name = name; | |||
return this; | |||
} | |||
/// <summary> | |||
/// Sets the field value. | |||
/// </summary> | |||
/// <param name="value">The value to set the field value to.</param> | |||
public EmbedFieldBuilder WithValue(object value) | |||
{ | |||
Value = value; | |||
return this; | |||
} | |||
/// <summary> | |||
/// Sets whether the field should be in-line with each other. | |||
/// </summary> | |||
public EmbedFieldBuilder WithIsInline(bool isInline) | |||
{ | |||
IsInline = isInline; | |||
return this; | |||
} | |||
/// <summary> | |||
/// Builds the field builder into a <see cref="EmbedField"/> class. | |||
/// </summary> | |||
public EmbedField Build() | |||
=> new EmbedField(Name, Value.ToString(), IsInline); | |||
} | |||
@@ -2,15 +2,23 @@ using System.Diagnostics; | |||
namespace Discord | |||
{ | |||
/// <summary> A field for an <see cref="Embed"/>. </summary> | |||
/// <summary> | |||
/// Represents a field for an <see cref="Embed" /> . | |||
/// </summary> | |||
[DebuggerDisplay("{DebuggerDisplay,nq}")] | |||
public struct EmbedField | |||
{ | |||
/// <summary> Gets the name of the field.</summary> | |||
/// <summary> | |||
/// Gets the name of the field. | |||
/// </summary> | |||
public string Name { get; internal set; } | |||
/// <summary> Gets the value of the field.</summary> | |||
/// <summary> | |||
/// Gets the value of the field. | |||
/// </summary> | |||
public string Value { get; internal set; } | |||
/// <summary> Gets whether the field is inline inside an <see cref="Embed"/> or not.</summary> | |||
/// <summary> | |||
/// Gets whether the field should be in-line with each other. | |||
/// </summary> | |||
public bool Inline { get; internal set; } | |||
internal EmbedField(string name, string value, bool inline) | |||
@@ -21,6 +29,9 @@ namespace Discord | |||
} | |||
private string DebuggerDisplay => $"{Name} ({Value}"; | |||
/// <summary> | |||
/// Gets the name of the field. | |||
/// </summary> | |||
public override string ToString() => Name; | |||
} | |||
} |
@@ -4,7 +4,7 @@ using System.Diagnostics; | |||
namespace Discord | |||
{ | |||
/// <summary> | |||
/// A color object that Discord uses. | |||
/// Represents a Discord color. | |||
/// </summary> | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public struct Color | |||
@@ -62,10 +62,20 @@ namespace Discord | |||
/// <summary> Gets the blue component for this color. </summary> | |||
public byte B => (byte)(RawValue); | |||
/// <summary> | |||
/// Initializes a <see cref="Color" /> struct with the given raw value. | |||
/// </summary> | |||
/// <param name="rawValue">A raw value for the color (e.g. <c>0x607D8B</c>).</param> | |||
public Color(uint rawValue) | |||
{ | |||
RawValue = rawValue; | |||
} | |||
/// <summary> | |||
/// Initializes a <see cref="Color" /> struct with the given RGB bytes. | |||
/// </summary> | |||
/// <param name="r">The <see langword="byte"/> that represents the red color.</param> | |||
/// <param name="g">The <see langword="byte"/> that represents the green color.</param> | |||
/// <param name="b">The <see langword="byte"/> that represents the blue color.</param> | |||
public Color(byte r, byte g, byte b) | |||
{ | |||
RawValue = | |||
@@ -73,6 +83,12 @@ namespace Discord | |||
((uint)g << 8) | | |||
(uint)b; | |||
} | |||
/// <summary> | |||
/// Initializes a <see cref="Color"/> struct with the given RGB value. | |||
/// </summary> | |||
/// <param name="r">The value that represents the red color. Must be within 0~255.</param> | |||
/// <param name="g">The value that represents the green color. Must be within 0~255.</param> | |||
/// <param name="b">The value that represents the blue color. Must be within 0~255.</param> | |||
public Color(int r, int g, int b) | |||
{ | |||
if (r < 0 || r > 255) | |||
@@ -86,6 +102,12 @@ namespace Discord | |||
((uint)g << 8) | | |||
(uint)b; | |||
} | |||
/// <summary> | |||
/// Initializes a <see cref="Color"/> struct with the given RGB float value. | |||
/// </summary> | |||
/// <param name="r">The value that represents the red color. Must be within 0~1.</param> | |||
/// <param name="g">The value that represents the green color. Must be within 0~1.</param> | |||
/// <param name="b">The value that represents the blue color. Must be within 0~1.</param> | |||
public Color(float r, float g, float b) | |||
{ | |||
if (r < 0.0f || r > 1.0f) | |||
@@ -99,7 +121,10 @@ namespace Discord | |||
((uint)(g * 255.0f) << 8) | | |||
(uint)(b * 255.0f); | |||
} | |||
/// <summary> | |||
/// Gets the hexadecimal representation of the color (e.g. #000ccc). | |||
/// </summary> | |||
public override string ToString() => | |||
$"#{Convert.ToString(RawValue, 16)}"; | |||
private string DebuggerDisplay => | |||
@@ -14,6 +14,11 @@ namespace Discord | |||
/// </summary> | |||
public int Position { get; } | |||
/// <summary> | |||
/// Initializes a <see cref="ReorderRoleProperties" /> with the given role ID and position. | |||
/// </summary> | |||
/// <param name="id">The ID of the role to be edited.</param> | |||
/// <param name="pos">The new zero-based position of the role.</param> | |||
public ReorderRoleProperties(ulong id, int pos) | |||
{ | |||
Id = id; | |||
@@ -3,18 +3,36 @@ using System.Text; | |||
namespace Discord | |||
{ | |||
/// <summary> The message object for logging purposes. </summary> | |||
/// <summary> | |||
/// Represents a message used for logging purposes. | |||
/// </summary> | |||
public struct LogMessage | |||
{ | |||
/// <summary> The severity of the log message. </summary> | |||
/// <summary> | |||
/// Gets the severity of the log message. | |||
/// </summary> | |||
public LogSeverity Severity { get; } | |||
/// <summary> The source of the log message. </summary> | |||
/// <summary> | |||
/// Gets the source of the log message. | |||
/// </summary> | |||
public string Source { get; } | |||
/// <summary> The message of the log message. </summary> | |||
/// <summary> | |||
/// Gets the message of the log message. | |||
/// </summary> | |||
public string Message { get; } | |||
/// <summary> The exception of the log message. </summary> | |||
/// <summary> | |||
/// Gets the exception of the log message. | |||
/// </summary> | |||
public Exception Exception { get; } | |||
/// <summary> | |||
/// Initializes a new <see cref="LogMessage" /> <see langword="struct"/> with the severity, source, | |||
/// <paramref name="message"/> of the event, and optionally, an exception. | |||
/// </summary> | |||
/// <param name="severity">The severity of the event.</param> | |||
/// <param name="source">The source of the event.</param> | |||
/// <param name="message">The message of the event.</param> | |||
/// <param name="exception">The exception of the event.</param> | |||
public LogMessage(LogSeverity severity, string source, string message, Exception exception = null) | |||
{ | |||
Severity = severity; | |||
@@ -22,8 +40,8 @@ namespace Discord | |||
Message = message; | |||
Exception = exception; | |||
} | |||
public override string ToString() => ToString(null); | |||
public override string ToString() => ToString(); | |||
public string ToString(StringBuilder builder = null, bool fullException = true, bool prependTimestamp = true, DateTimeKind timestampKind = DateTimeKind.Local, int? padSource = 11) | |||
{ | |||
string sourceName = Source; | |||
@@ -1,21 +1,29 @@ | |||
using System.Threading; | |||
using System.Threading; | |||
namespace Discord | |||
{ | |||
public class RequestOptions | |||
{ | |||
/// <summary> | |||
/// Creates a new <see cref="RequestOptions" /> class with its default settings. | |||
/// </summary> | |||
public static RequestOptions Default => new RequestOptions(); | |||
/// <summary> | |||
/// The max time, in milliseconds, to wait for this request to complete. If null, a request will not time out. | |||
/// If a rate limit has been triggered for this request's bucket and will not be unpaused in time, this request will fail immediately. | |||
/// <summary> | |||
/// Gets or set the max time, in milliseconds, to wait for this request to complete. If | |||
/// <see langword="null"/>, a request will not time out. If a rate limit has been triggered for this | |||
/// request's bucket and will not be unpaused in time, this request will fail immediately. | |||
/// </summary> | |||
public int? Timeout { get; set; } | |||
public CancellationToken CancelToken { get; set; } = CancellationToken.None; | |||
/// <summary> | |||
/// Gets or sets the retry behavior when the request fails. | |||
/// </summary> | |||
public RetryMode? RetryMode { get; set; } | |||
public bool HeaderOnly { get; internal set; } | |||
/// <summary> | |||
/// The reason for this action in the guild's audit log | |||
/// Gets or sets the reason for this action in the guild's audit log. Note that this property may not apply | |||
/// to every action. | |||
/// </summary> | |||
public string AuditLogReason { get; set; } | |||
@@ -31,11 +39,15 @@ namespace Discord | |||
return options.Clone(); | |||
} | |||
/// <summary> | |||
/// Initializes a new <see cref="RequestOptions" /> class with the default request timeout set in | |||
/// <see cref="DiscordConfig" /> . | |||
/// </summary> | |||
public RequestOptions() | |||
{ | |||
Timeout = DiscordConfig.DefaultRequestTimeout; | |||
} | |||
public RequestOptions Clone() => MemberwiseClone() as RequestOptions; | |||
} | |||
} |
@@ -3,13 +3,31 @@ using System.Collections.Generic; | |||
namespace Discord | |||
{ | |||
/// <summary> | |||
/// Represents a collection of <see cref="IEqualityComparer{T}"/> for various Discord objects. | |||
/// </summary> | |||
public static class DiscordComparers | |||
{ | |||
// TODO: simplify with '??=' slated for C# 8.0 | |||
/// <summary> | |||
/// Gets an <see cref="IEqualityComparer{T}"/> to be used to compare users. | |||
/// </summary> | |||
public static IEqualityComparer<IUser> UserComparer => _userComparer ?? (_userComparer = new EntityEqualityComparer<IUser, ulong>()); | |||
/// <summary> | |||
/// Gets an <see cref="IEqualityComparer{T}"/> to be used to compare guilds. | |||
/// </summary> | |||
public static IEqualityComparer<IGuild> GuildComparer => _guildComparer ?? (_guildComparer = new EntityEqualityComparer<IGuild, ulong>()); | |||
/// <summary> | |||
/// Gets an <see cref="IEqualityComparer{T}"/> to be used to compare channels. | |||
/// </summary> | |||
public static IEqualityComparer<IChannel> ChannelComparer => _channelComparer ?? (_channelComparer = new EntityEqualityComparer<IChannel, ulong>()); | |||
/// <summary> | |||
/// Gets an <see cref="IEqualityComparer{T}"/> to be used to compare roles. | |||
/// </summary> | |||
public static IEqualityComparer<IRole> RoleComparer => _roleComparer ?? (_roleComparer = new EntityEqualityComparer<IRole, ulong>()); | |||
/// <summary> | |||
/// Gets an <see cref="IEqualityComparer{T}"/> to be used to compare messages. | |||
/// </summary> | |||
public static IEqualityComparer<IMessage> MessageComparer => _messageComparer ?? (_messageComparer = new EntityEqualityComparer<IMessage, ulong>()); | |||
private static IEqualityComparer<IUser> _userComparer; | |||
@@ -1,4 +1,4 @@ | |||
using System; | |||
using System; | |||
using System.Diagnostics; | |||
namespace Discord | |||
@@ -1,4 +1,4 @@ | |||
using System; | |||
using System; | |||
using System.Diagnostics; | |||
using System.Threading.Tasks; | |||
using Model = Discord.API.UserGuild; | |||
@@ -6,7 +6,7 @@ using Model = Discord.API.UserGuild; | |||
namespace Discord.Rest | |||
{ | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public class RestUserGuild : RestEntity<ulong>, ISnowflakeEntity, IUserGuild | |||
public class RestUserGuild : RestEntity<ulong>, IUserGuild | |||
{ | |||
private string _iconId; | |||