* Add various property validation in EmbedBuilder * Embed URI changes Changes property types for any URLs in Embeds to System.URI. Adding field name/value null/empty checks. * including property names in argumentexceptions * Adds overall embed length checktags/1.0
@@ -1,6 +1,7 @@ | |||||
using System; | using System; | ||||
using System.Collections.Immutable; | using System.Collections.Immutable; | ||||
using System.Diagnostics; | using System.Diagnostics; | ||||
using System.Linq; | |||||
namespace Discord | namespace Discord | ||||
{ | { | ||||
@@ -10,7 +11,7 @@ namespace Discord | |||||
public string Type { get; } | public string Type { get; } | ||||
public string Description { get; internal set; } | public string Description { get; internal set; } | ||||
public string Url { get; internal set; } | |||||
public Uri Url { get; internal set; } | |||||
public string Title { get; internal set; } | public string Title { get; internal set; } | ||||
public DateTimeOffset? Timestamp { get; internal set; } | public DateTimeOffset? Timestamp { get; internal set; } | ||||
public Color? Color { get; internal set; } | public Color? Color { get; internal set; } | ||||
@@ -30,7 +31,7 @@ namespace Discord | |||||
internal Embed(string type, | internal Embed(string type, | ||||
string title, | string title, | ||||
string description, | string description, | ||||
string url, | |||||
Uri url, | |||||
DateTimeOffset? timestamp, | DateTimeOffset? timestamp, | ||||
Color? color, | Color? color, | ||||
EmbedImage? image, | EmbedImage? image, | ||||
@@ -56,6 +57,8 @@ namespace Discord | |||||
Fields = fields; | Fields = fields; | ||||
} | } | ||||
public int Length => Title?.Length + Author?.Name?.Length + Description?.Length + Footer?.Text?.Length + Fields.Sum(f => f.Name.Length + f.Value.ToString().Length) ?? 0; | |||||
public override string ToString() => Title; | public override string ToString() => Title; | ||||
private string DebuggerDisplay => $"{Title} ({Type})"; | private string DebuggerDisplay => $"{Title} ({Type})"; | ||||
} | } | ||||
@@ -1,4 +1,5 @@ | |||||
using System.Diagnostics; | |||||
using System; | |||||
using System.Diagnostics; | |||||
namespace Discord | namespace Discord | ||||
{ | { | ||||
@@ -6,11 +7,11 @@ namespace Discord | |||||
public struct EmbedAuthor | public struct EmbedAuthor | ||||
{ | { | ||||
public string Name { get; internal set; } | public string Name { get; internal set; } | ||||
public string Url { get; internal set; } | |||||
public string IconUrl { get; internal set; } | |||||
public string ProxyIconUrl { get; internal set; } | |||||
public Uri Url { get; internal set; } | |||||
public Uri IconUrl { get; internal set; } | |||||
public Uri ProxyIconUrl { get; internal set; } | |||||
internal EmbedAuthor(string name, string url, string iconUrl, string proxyIconUrl) | |||||
internal EmbedAuthor(string name, Uri url, Uri iconUrl, Uri proxyIconUrl) | |||||
{ | { | ||||
Name = name; | Name = name; | ||||
Url = url; | Url = url; | ||||
@@ -1,4 +1,5 @@ | |||||
using System.Diagnostics; | |||||
using System; | |||||
using System.Diagnostics; | |||||
namespace Discord | namespace Discord | ||||
{ | { | ||||
@@ -6,10 +7,10 @@ namespace Discord | |||||
public struct EmbedFooter | public struct EmbedFooter | ||||
{ | { | ||||
public string Text { get; internal set; } | public string Text { get; internal set; } | ||||
public string IconUrl { get; internal set; } | |||||
public string ProxyUrl { get; internal set; } | |||||
public Uri IconUrl { get; internal set; } | |||||
public Uri ProxyUrl { get; internal set; } | |||||
internal EmbedFooter(string text, string iconUrl, string proxyUrl) | |||||
internal EmbedFooter(string text, Uri iconUrl, Uri proxyUrl) | |||||
{ | { | ||||
Text = text; | Text = text; | ||||
IconUrl = iconUrl; | IconUrl = iconUrl; | ||||
@@ -1,16 +1,17 @@ | |||||
using System.Diagnostics; | |||||
using System; | |||||
using System.Diagnostics; | |||||
namespace Discord | namespace Discord | ||||
{ | { | ||||
[DebuggerDisplay("{DebuggerDisplay,nq}")] | [DebuggerDisplay("{DebuggerDisplay,nq}")] | ||||
public struct EmbedImage | public struct EmbedImage | ||||
{ | { | ||||
public string Url { get; } | |||||
public string ProxyUrl { get; } | |||||
public Uri Url { get; } | |||||
public Uri ProxyUrl { get; } | |||||
public int? Height { get; } | public int? Height { get; } | ||||
public int? Width { get; } | public int? Width { get; } | ||||
internal EmbedImage(string url, string proxyUrl, int? height, int? width) | |||||
internal EmbedImage(Uri url, Uri proxyUrl, int? height, int? width) | |||||
{ | { | ||||
Url = url; | Url = url; | ||||
ProxyUrl = proxyUrl; | ProxyUrl = proxyUrl; | ||||
@@ -19,6 +20,6 @@ namespace Discord | |||||
} | } | ||||
private string DebuggerDisplay => $"{Url} ({(Width != null && Height != null ? $"{Width}x{Height}" : "0x0")})"; | private string DebuggerDisplay => $"{Url} ({(Width != null && Height != null ? $"{Width}x{Height}" : "0x0")})"; | ||||
public override string ToString() => Url; | |||||
public override string ToString() => Url.ToString(); | |||||
} | } | ||||
} | } |
@@ -1,4 +1,5 @@ | |||||
using System.Diagnostics; | |||||
using System; | |||||
using System.Diagnostics; | |||||
namespace Discord | namespace Discord | ||||
{ | { | ||||
@@ -6,9 +7,9 @@ namespace Discord | |||||
public struct EmbedProvider | public struct EmbedProvider | ||||
{ | { | ||||
public string Name { get; } | public string Name { get; } | ||||
public string Url { get; } | |||||
public Uri Url { get; } | |||||
internal EmbedProvider(string name, string url) | |||||
internal EmbedProvider(string name, Uri url) | |||||
{ | { | ||||
Name = name; | Name = name; | ||||
Url = url; | Url = url; | ||||
@@ -1,16 +1,17 @@ | |||||
using System.Diagnostics; | |||||
using System; | |||||
using System.Diagnostics; | |||||
namespace Discord | namespace Discord | ||||
{ | { | ||||
[DebuggerDisplay("{DebuggerDisplay,nq}")] | [DebuggerDisplay("{DebuggerDisplay,nq}")] | ||||
public struct EmbedThumbnail | public struct EmbedThumbnail | ||||
{ | { | ||||
public string Url { get; } | |||||
public string ProxyUrl { get; } | |||||
public Uri Url { get; } | |||||
public Uri ProxyUrl { get; } | |||||
public int? Height { get; } | public int? Height { get; } | ||||
public int? Width { get; } | public int? Width { get; } | ||||
internal EmbedThumbnail(string url, string proxyUrl, int? height, int? width) | |||||
internal EmbedThumbnail(Uri url, Uri proxyUrl, int? height, int? width) | |||||
{ | { | ||||
Url = url; | Url = url; | ||||
ProxyUrl = proxyUrl; | ProxyUrl = proxyUrl; | ||||
@@ -19,6 +20,6 @@ namespace Discord | |||||
} | } | ||||
private string DebuggerDisplay => $"{Url} ({(Width != null && Height != null ? $"{Width}x{Height}" : "0x0")})"; | private string DebuggerDisplay => $"{Url} ({(Width != null && Height != null ? $"{Width}x{Height}" : "0x0")})"; | ||||
public override string ToString() => Url; | |||||
public override string ToString() => Url.ToString(); | |||||
} | } | ||||
} | } |
@@ -1,15 +1,16 @@ | |||||
using System.Diagnostics; | |||||
using System; | |||||
using System.Diagnostics; | |||||
namespace Discord | namespace Discord | ||||
{ | { | ||||
[DebuggerDisplay("{DebuggerDisplay,nq}")] | [DebuggerDisplay("{DebuggerDisplay,nq}")] | ||||
public struct EmbedVideo | public struct EmbedVideo | ||||
{ | { | ||||
public string Url { get; } | |||||
public Uri Url { get; } | |||||
public int? Height { get; } | public int? Height { get; } | ||||
public int? Width { get; } | public int? Width { get; } | ||||
internal EmbedVideo(string url, int? height, int? width) | |||||
internal EmbedVideo(Uri url, int? height, int? width) | |||||
{ | { | ||||
Url = url; | Url = url; | ||||
Height = height; | Height = height; | ||||
@@ -17,6 +18,6 @@ namespace Discord | |||||
} | } | ||||
private string DebuggerDisplay => $"{Url} ({(Width != null && Height != null ? $"{Width}x{Height}" : "0x0")})"; | private string DebuggerDisplay => $"{Url} ({(Width != null && Height != null ? $"{Width}x{Height}" : "0x0")})"; | ||||
public override string ToString() => Url; | |||||
public override string ToString() => Url.ToString(); | |||||
} | } | ||||
} | } |
@@ -5,7 +5,7 @@ namespace Discord | |||||
{ | { | ||||
public interface IEmbed | public interface IEmbed | ||||
{ | { | ||||
string Url { get; } | |||||
Uri Url { get; } | |||||
string Type { get; } | string Type { get; } | ||||
string Title { get; } | string Title { get; } | ||||
string Description { get; } | string Description { get; } | ||||
@@ -13,7 +13,7 @@ namespace Discord.API | |||||
[JsonProperty("description")] | [JsonProperty("description")] | ||||
public string Description { get; set; } | public string Description { get; set; } | ||||
[JsonProperty("url")] | [JsonProperty("url")] | ||||
public string Url { get; set; } | |||||
public Uri Url { get; set; } | |||||
[JsonProperty("color")] | [JsonProperty("color")] | ||||
public uint? Color { get; set; } | public uint? Color { get; set; } | ||||
[JsonProperty("timestamp")] | [JsonProperty("timestamp")] | ||||
@@ -1,4 +1,5 @@ | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
@@ -7,10 +8,10 @@ namespace Discord.API | |||||
[JsonProperty("name")] | [JsonProperty("name")] | ||||
public string Name { get; set; } | public string Name { get; set; } | ||||
[JsonProperty("url")] | [JsonProperty("url")] | ||||
public string Url { get; set; } | |||||
public Uri Url { get; set; } | |||||
[JsonProperty("icon_url")] | [JsonProperty("icon_url")] | ||||
public string IconUrl { get; set; } | |||||
public Uri IconUrl { get; set; } | |||||
[JsonProperty("proxy_icon_url")] | [JsonProperty("proxy_icon_url")] | ||||
public string ProxyIconUrl { get; set; } | |||||
public Uri ProxyIconUrl { get; set; } | |||||
} | } | ||||
} | } |
@@ -1,4 +1,5 @@ | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
@@ -7,8 +8,8 @@ namespace Discord.API | |||||
[JsonProperty("text")] | [JsonProperty("text")] | ||||
public string Text { get; set; } | public string Text { get; set; } | ||||
[JsonProperty("icon_url")] | [JsonProperty("icon_url")] | ||||
public string IconUrl { get; set; } | |||||
public Uri IconUrl { get; set; } | |||||
[JsonProperty("proxy_icon_url")] | [JsonProperty("proxy_icon_url")] | ||||
public string ProxyIconUrl { get; set; } | |||||
public Uri ProxyIconUrl { get; set; } | |||||
} | } | ||||
} | } |
@@ -1,4 +1,5 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using System; | |||||
using Newtonsoft.Json; | using Newtonsoft.Json; | ||||
namespace Discord.API | namespace Discord.API | ||||
@@ -6,9 +7,9 @@ namespace Discord.API | |||||
internal class EmbedImage | internal class EmbedImage | ||||
{ | { | ||||
[JsonProperty("url")] | [JsonProperty("url")] | ||||
public string Url { get; set; } | |||||
public Uri Url { get; set; } | |||||
[JsonProperty("proxy_url")] | [JsonProperty("proxy_url")] | ||||
public string ProxyUrl { get; set; } | |||||
public Uri ProxyUrl { get; set; } | |||||
[JsonProperty("height")] | [JsonProperty("height")] | ||||
public Optional<int> Height { get; set; } | public Optional<int> Height { get; set; } | ||||
[JsonProperty("width")] | [JsonProperty("width")] | ||||
@@ -1,4 +1,5 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using System; | |||||
using Newtonsoft.Json; | using Newtonsoft.Json; | ||||
namespace Discord.API | namespace Discord.API | ||||
@@ -8,6 +9,6 @@ namespace Discord.API | |||||
[JsonProperty("name")] | [JsonProperty("name")] | ||||
public string Name { get; set; } | public string Name { get; set; } | ||||
[JsonProperty("url")] | [JsonProperty("url")] | ||||
public string Url { get; set; } | |||||
public Uri Url { get; set; } | |||||
} | } | ||||
} | } |
@@ -1,4 +1,5 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using System; | |||||
using Newtonsoft.Json; | using Newtonsoft.Json; | ||||
namespace Discord.API | namespace Discord.API | ||||
@@ -6,9 +7,9 @@ namespace Discord.API | |||||
internal class EmbedThumbnail | internal class EmbedThumbnail | ||||
{ | { | ||||
[JsonProperty("url")] | [JsonProperty("url")] | ||||
public string Url { get; set; } | |||||
public Uri Url { get; set; } | |||||
[JsonProperty("proxy_url")] | [JsonProperty("proxy_url")] | ||||
public string ProxyUrl { get; set; } | |||||
public Uri ProxyUrl { get; set; } | |||||
[JsonProperty("height")] | [JsonProperty("height")] | ||||
public Optional<int> Height { get; set; } | public Optional<int> Height { get; set; } | ||||
[JsonProperty("width")] | [JsonProperty("width")] | ||||
@@ -1,4 +1,5 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using System; | |||||
using Newtonsoft.Json; | using Newtonsoft.Json; | ||||
namespace Discord.API | namespace Discord.API | ||||
@@ -6,7 +7,7 @@ namespace Discord.API | |||||
internal class EmbedVideo | internal class EmbedVideo | ||||
{ | { | ||||
[JsonProperty("url")] | [JsonProperty("url")] | ||||
public string Url { get; set; } | |||||
public Uri Url { get; set; } | |||||
[JsonProperty("height")] | [JsonProperty("height")] | ||||
public Optional<int> Height { get; set; } | public Optional<int> Height { get; set; } | ||||
[JsonProperty("width")] | [JsonProperty("width")] | ||||
@@ -8,19 +8,42 @@ namespace Discord | |||||
{ | { | ||||
private readonly Embed _embed; | private readonly Embed _embed; | ||||
public const int MaxFieldCount = 25; | |||||
public const int MaxTitleLength = 256; | |||||
public const int MaxDescriptionLength = 2048; | |||||
public const int MaxEmbedLength = 6000; // user bot limit is 2000, but we don't validate that here. | |||||
public EmbedBuilder() | public EmbedBuilder() | ||||
{ | { | ||||
_embed = new Embed("rich"); | _embed = new Embed("rich"); | ||||
Fields = new List<EmbedFieldBuilder>(); | Fields = new List<EmbedFieldBuilder>(); | ||||
} | } | ||||
public string Title { get { return _embed.Title; } set { _embed.Title = value; } } | |||||
public string Description { get { return _embed.Description; } set { _embed.Description = value; } } | |||||
public string Url { get { return _embed.Url; } set { _embed.Url = value; } } | |||||
public string ThumbnailUrl { get { return _embed.Thumbnail?.Url; } set { _embed.Thumbnail = new EmbedThumbnail(value, null, null, null); } } | |||||
public string ImageUrl { get { return _embed.Image?.Url; } set { _embed.Image = new EmbedImage(value, null, null, null); } } | |||||
public DateTimeOffset? Timestamp { get { return _embed.Timestamp; } set { _embed.Timestamp = value; } } | |||||
public Color? Color { get { return _embed.Color; } set { _embed.Color = value; } } | |||||
public string Title | |||||
{ | |||||
get => _embed.Title; | |||||
set | |||||
{ | |||||
if (value?.Length > MaxTitleLength) throw new ArgumentException($"Title length must be less than or equal to {MaxTitleLength}.", nameof(Title)); | |||||
_embed.Title = value; | |||||
} | |||||
} | |||||
public string Description | |||||
{ | |||||
get => _embed.Description; | |||||
set | |||||
{ | |||||
if (value?.Length > MaxDescriptionLength) throw new ArgumentException($"Description length must be less than or equal to {MaxDescriptionLength}.", nameof(Description)); | |||||
_embed.Description = value; | |||||
} | |||||
} | |||||
public Uri Url { get => _embed.Url; set { _embed.Url = value; } } | |||||
public Uri ThumbnailUrl { get => _embed.Thumbnail?.Url; set { _embed.Thumbnail = new EmbedThumbnail(value, null, null, null); } } | |||||
public Uri ImageUrl { get => _embed.Image?.Url; set { _embed.Image = new EmbedImage(value, null, null, null); } } | |||||
public DateTimeOffset? Timestamp { get => _embed.Timestamp; set { _embed.Timestamp = value; } } | |||||
public Color? Color { get => _embed.Color; set { _embed.Color = value; } } | |||||
public EmbedAuthorBuilder Author { get; set; } | public EmbedAuthorBuilder Author { get; set; } | ||||
public EmbedFooterBuilder Footer { get; set; } | public EmbedFooterBuilder Footer { get; set; } | ||||
@@ -30,8 +53,10 @@ namespace Discord | |||||
get => _fields; | get => _fields; | ||||
set | set | ||||
{ | { | ||||
if (value != null) _fields = value; | |||||
else throw new ArgumentNullException("Cannot set an embed builder's fields collection to null", nameof(value)); | |||||
if (value == null) throw new ArgumentNullException("Cannot set an embed builder's fields collection to null", nameof(Fields)); | |||||
if (value.Count > MaxFieldCount) throw new ArgumentException($"Field count must be less than or equal to {MaxFieldCount}.", nameof(Fields)); | |||||
_fields = value; | |||||
} | } | ||||
} | } | ||||
@@ -45,17 +70,17 @@ namespace Discord | |||||
Description = description; | Description = description; | ||||
return this; | return this; | ||||
} | } | ||||
public EmbedBuilder WithUrl(string url) | |||||
public EmbedBuilder WithUrl(Uri url) | |||||
{ | { | ||||
Url = url; | Url = url; | ||||
return this; | return this; | ||||
} | } | ||||
public EmbedBuilder WithThumbnailUrl(string thumbnailUrl) | |||||
public EmbedBuilder WithThumbnailUrl(Uri thumbnailUrl) | |||||
{ | { | ||||
ThumbnailUrl = thumbnailUrl; | ThumbnailUrl = thumbnailUrl; | ||||
return this; | return this; | ||||
} | } | ||||
public EmbedBuilder WithImageUrl(string imageUrl) | |||||
public EmbedBuilder WithImageUrl(Uri imageUrl) | |||||
{ | { | ||||
ImageUrl = imageUrl; | ImageUrl = imageUrl; | ||||
return this; | return this; | ||||
@@ -107,7 +132,7 @@ namespace Discord | |||||
.WithIsInline(false) | .WithIsInline(false) | ||||
.WithName(name) | .WithName(name) | ||||
.WithValue(value); | .WithValue(value); | ||||
Fields.Add(field); | |||||
AddField(field); | |||||
return this; | return this; | ||||
} | } | ||||
public EmbedBuilder AddInlineField(string name, object value) | public EmbedBuilder AddInlineField(string name, object value) | ||||
@@ -116,11 +141,16 @@ namespace Discord | |||||
.WithIsInline(true) | .WithIsInline(true) | ||||
.WithName(name) | .WithName(name) | ||||
.WithValue(value); | .WithValue(value); | ||||
Fields.Add(field); | |||||
AddField(field); | |||||
return this; | return this; | ||||
} | } | ||||
public EmbedBuilder AddField(EmbedFieldBuilder field) | public EmbedBuilder AddField(EmbedFieldBuilder field) | ||||
{ | { | ||||
if (Fields.Count >= MaxFieldCount) | |||||
{ | |||||
throw new ArgumentException($"Field count must be less than or equal to {MaxFieldCount}.", nameof(field)); | |||||
} | |||||
Fields.Add(field); | Fields.Add(field); | ||||
return this; | return this; | ||||
} | } | ||||
@@ -128,7 +158,7 @@ namespace Discord | |||||
{ | { | ||||
var field = new EmbedFieldBuilder(); | var field = new EmbedFieldBuilder(); | ||||
action(field); | action(field); | ||||
Fields.Add(field); | |||||
this.AddField(field); | |||||
return this; | return this; | ||||
} | } | ||||
@@ -140,6 +170,12 @@ namespace Discord | |||||
for (int i = 0; i < Fields.Count; i++) | for (int i = 0; i < Fields.Count; i++) | ||||
fields.Add(Fields[i].Build()); | fields.Add(Fields[i].Build()); | ||||
_embed.Fields = fields.ToImmutable(); | _embed.Fields = fields.ToImmutable(); | ||||
if (_embed.Length > MaxEmbedLength) | |||||
{ | |||||
throw new InvalidOperationException($"Total embed length must be less than or equal to {MaxEmbedLength}"); | |||||
} | |||||
return _embed; | return _embed; | ||||
} | } | ||||
public static implicit operator Embed(EmbedBuilder builder) => builder?.Build(); | public static implicit operator Embed(EmbedBuilder builder) => builder?.Build(); | ||||
@@ -149,9 +185,32 @@ namespace Discord | |||||
{ | { | ||||
private EmbedField _field; | private EmbedField _field; | ||||
public string Name { get { return _field.Name; } set { _field.Name = value; } } | |||||
public object Value { get { return _field.Value; } set { _field.Value = value.ToString(); } } | |||||
public bool IsInline { get { return _field.Inline; } set { _field.Inline = value; } } | |||||
public const int MaxFieldNameLength = 256; | |||||
public const int MaxFieldValueLength = 1024; | |||||
public string Name | |||||
{ | |||||
get => _field.Name; | |||||
set | |||||
{ | |||||
if (string.IsNullOrEmpty(value)) throw new ArgumentException($"Field name must not be null or empty.", nameof(Name)); | |||||
if (value.Length > MaxFieldNameLength) throw new ArgumentException($"Field name length must be less than or equal to {MaxFieldNameLength}.", nameof(Name)); | |||||
_field.Name = value; | |||||
} | |||||
} | |||||
public object Value | |||||
{ | |||||
get => _field.Value; | |||||
set | |||||
{ | |||||
var stringValue = value.ToString(); | |||||
if (string.IsNullOrEmpty(stringValue)) throw new ArgumentException($"Field value must not be null or empty.", nameof(Value)); | |||||
if (stringValue.Length > MaxFieldValueLength) throw new ArgumentException($"Field value length must be less than or equal to {MaxFieldValueLength}.", nameof(Value)); | |||||
_field.Value = stringValue; | |||||
} | |||||
} | |||||
public bool IsInline { get => _field.Inline; set { _field.Inline = value; } } | |||||
public EmbedFieldBuilder() | public EmbedFieldBuilder() | ||||
{ | { | ||||
@@ -182,9 +241,19 @@ namespace Discord | |||||
{ | { | ||||
private EmbedAuthor _author; | private EmbedAuthor _author; | ||||
public string Name { get { return _author.Name; } set { _author.Name = value; } } | |||||
public string Url { get { return _author.Url; } set { _author.Url = value; } } | |||||
public string IconUrl { get { return _author.IconUrl; } set { _author.IconUrl = value; } } | |||||
public const int MaxAuthorNameLength = 256; | |||||
public string Name | |||||
{ | |||||
get => _author.Name; | |||||
set | |||||
{ | |||||
if (value?.Length > MaxAuthorNameLength) throw new ArgumentException($"Author name length must be less than or equal to {MaxAuthorNameLength}.", nameof(Name)); | |||||
_author.Name = value; | |||||
} | |||||
} | |||||
public Uri Url { get => _author.Url; set { _author.Url = value; } } | |||||
public Uri IconUrl { get => _author.IconUrl; set { _author.IconUrl = value; } } | |||||
public EmbedAuthorBuilder() | public EmbedAuthorBuilder() | ||||
{ | { | ||||
@@ -196,12 +265,12 @@ namespace Discord | |||||
Name = name; | Name = name; | ||||
return this; | return this; | ||||
} | } | ||||
public EmbedAuthorBuilder WithUrl(string url) | |||||
public EmbedAuthorBuilder WithUrl(Uri url) | |||||
{ | { | ||||
Url = url; | Url = url; | ||||
return this; | return this; | ||||
} | } | ||||
public EmbedAuthorBuilder WithIconUrl(string iconUrl) | |||||
public EmbedAuthorBuilder WithIconUrl(Uri iconUrl) | |||||
{ | { | ||||
IconUrl = iconUrl; | IconUrl = iconUrl; | ||||
return this; | return this; | ||||
@@ -215,8 +284,18 @@ namespace Discord | |||||
{ | { | ||||
private EmbedFooter _footer; | private EmbedFooter _footer; | ||||
public string Text { get { return _footer.Text; } set { _footer.Text = value; } } | |||||
public string IconUrl { get { return _footer.IconUrl; } set { _footer.IconUrl = value; } } | |||||
public const int MaxFooterTextLength = 2048; | |||||
public string Text | |||||
{ | |||||
get => _footer.Text; | |||||
set | |||||
{ | |||||
if (value?.Length > MaxFooterTextLength) throw new ArgumentException($"Footer text length must be less than or equal to {MaxFooterTextLength}.", nameof(Text)); | |||||
_footer.Text = value; | |||||
} | |||||
} | |||||
public Uri IconUrl { get => _footer.IconUrl; set { _footer.IconUrl = value; } } | |||||
public EmbedFooterBuilder() | public EmbedFooterBuilder() | ||||
{ | { | ||||
@@ -228,7 +307,7 @@ namespace Discord | |||||
Text = text; | Text = text; | ||||
return this; | return this; | ||||
} | } | ||||
public EmbedFooterBuilder WithIconUrl(string iconUrl) | |||||
public EmbedFooterBuilder WithIconUrl(Uri iconUrl) | |||||
{ | { | ||||
IconUrl = iconUrl; | IconUrl = iconUrl; | ||||
return this; | return this; | ||||