@@ -11643,5 +11643,13 @@ | |||
<exception cref="T:System.ArgumentNullException"> Thrown when the supplied token string is <c>null</c>, empty, or contains only whitespace.</exception> | |||
<exception cref="T:System.ArgumentException"> Thrown when the supplied <see cref="T:Discord.TokenType"/> or token value is invalid. </exception> | |||
</member> | |||
<member name="M:Discord.Utils.UrlValidation.Validate(System.String)"> | |||
<summary> | |||
Not full URL validation right now. Just ensures protocol is present and that it's either http or https | |||
</summary> | |||
<param name="url">url to validate before sending to Discord</param> | |||
<exception cref="T:System.InvalidOperationException">A URL must include a protocol (http or https).</exception> | |||
<returns>true if url is valid by our standard, false if null, throws an error upon invalid </returns> | |||
</member> | |||
</members> | |||
</doc> |
@@ -1,6 +1,7 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using Discord.Utils; | |||
namespace Discord | |||
{ | |||
@@ -535,12 +536,11 @@ namespace Discord | |||
if (this.Style == ButtonStyle.Link) | |||
{ | |||
if (string.IsNullOrEmpty(this.Url)) | |||
throw new InvalidOperationException("Link buttons must have a link associated with them"); | |||
else if (!Uri.IsWellFormedUriString(this.Url, UriKind.Absolute)) | |||
throw new InvalidOperationException("Urls must be well formatted and include their protocol (either HTTP or HTTPS)"); | |||
} | |||
if (string.IsNullOrEmpty(this.Url)) | |||
throw new InvalidOperationException("Link buttons must have a link associated with them"); | |||
else | |||
UrlValidation.Validate(this.Url); | |||
} | |||
else if (string.IsNullOrEmpty(this.CustomId)) | |||
throw new InvalidOperationException("Non-link buttons must have a custom id associated with them"); | |||
@@ -2,6 +2,7 @@ using System; | |||
using System.Collections.Generic; | |||
using System.Collections.Immutable; | |||
using System.Linq; | |||
using Discord.Utils; | |||
namespace Discord | |||
{ | |||
@@ -401,25 +402,29 @@ namespace Discord | |||
/// The built embed object. | |||
/// </returns> | |||
/// <exception cref="InvalidOperationException">Total embed length exceeds <see cref="MaxEmbedLength"/>.</exception> | |||
/// <exception cref="InvalidOperationException">Any Url must be well formatted include its protocols (i.e http:// or https://).</exception> | |||
/// <exception cref="InvalidOperationException">Any Url must include its protocols (i.e http:// or https://).</exception> | |||
public Embed Build() | |||
{ | |||
if (Length > MaxEmbedLength) | |||
throw new InvalidOperationException($"Total embed length must be less than or equal to {MaxEmbedLength}."); | |||
if (!string.IsNullOrEmpty(Url) && !Uri.IsWellFormedUriString(Url, UriKind.Absolute)) | |||
throw new InvalidOperationException("Url must be well formatted and include its protocol (either HTTP or HTTPS)"); | |||
if (!string.IsNullOrEmpty(ThumbnailUrl) && !Uri.IsWellFormedUriString(ThumbnailUrl, UriKind.Absolute)) | |||
throw new InvalidOperationException("Thumbnail Url must be well formatted and include its protocol (either HTTP or HTTPS)"); | |||
if (!string.IsNullOrEmpty(ImageUrl) && !Uri.IsWellFormedUriString(ImageUrl, UriKind.Absolute)) | |||
throw new InvalidOperationException("Image Url must be well formatted and include its protocol (either HTTP or HTTPS)"); | |||
if (!string.IsNullOrEmpty(Url)) | |||
UrlValidation.Validate(Url); | |||
if (!string.IsNullOrEmpty(ThumbnailUrl)) | |||
UrlValidation.Validate(ThumbnailUrl); | |||
if (!string.IsNullOrEmpty(ImageUrl)) | |||
UrlValidation.Validate(ImageUrl); | |||
if (Author != null) | |||
{ | |||
if(!string.IsNullOrEmpty(Author.Url) && !Uri.IsWellFormedUriString(Author.Url, UriKind.Absolute)) | |||
throw new InvalidOperationException("Author Url must be well formatted and include its protocol (either HTTP or HTTPS)"); | |||
if (!string.IsNullOrEmpty(Author.IconUrl) && !Uri.IsWellFormedUriString(Author.IconUrl, UriKind.Absolute)) | |||
throw new InvalidOperationException("Author Icon Url must be well formatted and include its protocol (either HTTP or HTTPS)"); | |||
if (!string.IsNullOrEmpty(Author.Url)) | |||
UrlValidation.Validate(Author.Url); | |||
if (!string.IsNullOrEmpty(Author.IconUrl)) | |||
UrlValidation.Validate(Author.IconUrl); | |||
} | |||
if(Footer != null) | |||
{ | |||
if (!string.IsNullOrEmpty(Footer.IconUrl)) | |||
UrlValidation.Validate(Footer.IconUrl); | |||
} | |||
var fields = ImmutableArray.CreateBuilder<EmbedField>(Fields.Count); | |||
for (int i = 0; i < Fields.Count; i++) | |||
fields.Add(Fields[i].Build()); | |||
@@ -0,0 +1,22 @@ | |||
using System; | |||
namespace Discord.Utils | |||
{ | |||
static class UrlValidation | |||
{ | |||
/// <summary> | |||
/// Not full URL validation right now. Just ensures protocol is present and that it's either http or https | |||
/// </summary> | |||
/// <param name="url">url to validate before sending to Discord</param> | |||
/// <exception cref="InvalidOperationException">A URL must include a protocol (http or https).</exception> | |||
/// <returns>true if url is valid by our standard, false if null, throws an error upon invalid </returns> | |||
public static bool Validate(string url) | |||
{ | |||
if (string.IsNullOrEmpty(url)) | |||
return false; | |||
if(!(url.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || (url.StartsWith("https://", StringComparison.OrdinalIgnoreCase)))) | |||
throw new InvalidOperationException($"Url {url} must be include its protocol (either HTTP or HTTPS)"); | |||
return true; | |||
} | |||
} | |||
} |