Move EmbedBuilder+Extensions to Discord.Net.Core

Previously it was implemented under Discord.Net.Rest, which seems
inconsistent and unnecessary.

This also allows Commands docstrings to reference EmbedBuilder, since
Commands only has a dependency on Core.
This commit is contained in:
Christopher F
2018-03-18 15:59:45 -04:00
parent b38dca7803
commit b9be6deb4f
3 changed files with 5 additions and 2 deletions

View File

@@ -1,7 +1,10 @@
using System.Runtime.CompilerServices;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Discord.Net.Rpc")]
[assembly: InternalsVisibleTo("Discord.Net.WebSocket")]
[assembly: InternalsVisibleTo("Discord.Net.Webhook")]
[assembly: InternalsVisibleTo("Discord.Net.Commands")]
[assembly: InternalsVisibleTo("Discord.Net.Tests")]
[assembly: InternalsVisibleTo("Discord.Net.Tests")]
[assembly: TypeForwardedTo(typeof(Discord.EmbedBuilder))]
[assembly: TypeForwardedTo(typeof(Discord.EmbedBuilderExtensions))]

View File

@@ -1,379 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
namespace Discord
{
public class EmbedBuilder
{
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()
{
_embed = new Embed(EmbedType.Rich);
Fields = new List<EmbedFieldBuilder>();
}
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 string Url
{
get => _embed.Url;
set
{
if (!value.IsNullOrUri()) throw new ArgumentException("Url must be a well-formed URI", nameof(Url));
_embed.Url = value;
}
}
public string ThumbnailUrl
{
get => _embed.Thumbnail?.Url;
set
{
if (!value.IsNullOrUri()) throw new ArgumentException("Url must be a well-formed URI", nameof(ThumbnailUrl));
_embed.Thumbnail = new EmbedThumbnail(value, null, null, null);
}
}
public string ImageUrl
{
get => _embed.Image?.Url;
set
{
if (!value.IsNullOrUri()) throw new ArgumentException("Url must be a well-formed URI", nameof(ImageUrl));
_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 EmbedFooterBuilder Footer { get; set; }
private List<EmbedFieldBuilder> _fields;
public List<EmbedFieldBuilder> Fields
{
get => _fields;
set
{
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;
}
}
public EmbedBuilder WithTitle(string title)
{
Title = title;
return this;
}
public EmbedBuilder WithDescription(string description)
{
Description = description;
return this;
}
public EmbedBuilder WithUrl(string url)
{
Url = url;
return this;
}
public EmbedBuilder WithThumbnailUrl(string thumbnailUrl)
{
ThumbnailUrl = thumbnailUrl;
return this;
}
public EmbedBuilder WithImageUrl(string imageUrl)
{
ImageUrl = imageUrl;
return this;
}
public EmbedBuilder WithCurrentTimestamp()
{
Timestamp = DateTimeOffset.UtcNow;
return this;
}
public EmbedBuilder WithTimestamp(DateTimeOffset dateTimeOffset)
{
Timestamp = dateTimeOffset;
return this;
}
public EmbedBuilder WithColor(Color color)
{
Color = color;
return this;
}
public EmbedBuilder WithAuthor(EmbedAuthorBuilder author)
{
Author = author;
return this;
}
public EmbedBuilder WithAuthor(Action<EmbedAuthorBuilder> action)
{
var author = new EmbedAuthorBuilder();
action(author);
Author = author;
return this;
}
public EmbedBuilder WithAuthor(string name, string iconUrl = null, string url = null)
{
var author = new EmbedAuthorBuilder
{
Name = name,
IconUrl = iconUrl,
Url = url
};
Author = author;
return this;
}
public EmbedBuilder WithFooter(EmbedFooterBuilder footer)
{
Footer = footer;
return this;
}
public EmbedBuilder WithFooter(Action<EmbedFooterBuilder> action)
{
var footer = new EmbedFooterBuilder();
action(footer);
Footer = footer;
return this;
}
public EmbedBuilder WithFooter(string text, string iconUrl = null)
{
var footer = new EmbedFooterBuilder
{
Text = text,
IconUrl = iconUrl
};
Footer = footer;
return this;
}
public EmbedBuilder AddField(string name, object value, bool inline = false)
{
var field = new EmbedFieldBuilder()
.WithIsInline(inline)
.WithName(name)
.WithValue(value);
AddField(field);
return this;
}
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);
return this;
}
public EmbedBuilder AddField(Action<EmbedFieldBuilder> action)
{
var field = new EmbedFieldBuilder();
action(field);
this.AddField(field);
return this;
}
public Embed Build()
{
_embed.Footer = Footer?.Build();
_embed.Author = Author?.Build();
var fields = ImmutableArray.CreateBuilder<EmbedField>(Fields.Count);
for (int i = 0; i < Fields.Count; i++)
fields.Add(Fields[i].Build());
_embed.Fields = fields.ToImmutable();
if (_embed.Length > MaxEmbedLength)
{
throw new InvalidOperationException($"Total embed length must be less than or equal to {MaxEmbedLength}");
}
return _embed;
}
}
public class EmbedFieldBuilder
{
private EmbedField _field;
public const int MaxFieldNameLength = 256;
public const int MaxFieldValueLength = 1024;
public string Name
{
get => _field.Name;
set
{
if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException($"Field name must not be null, empty or entirely whitespace.", 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()
{
_field = new EmbedField();
}
public EmbedFieldBuilder WithName(string name)
{
Name = name;
return this;
}
public EmbedFieldBuilder WithValue(object value)
{
Value = value;
return this;
}
public EmbedFieldBuilder WithIsInline(bool isInline)
{
IsInline = isInline;
return this;
}
public EmbedField Build()
=> _field;
}
public class EmbedAuthorBuilder
{
private EmbedAuthor _author;
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 string Url
{
get => _author.Url;
set
{
if (!value.IsNullOrUri()) throw new ArgumentException("Url must be a well-formed URI", nameof(Url));
_author.Url = value;
}
}
public string IconUrl
{
get => _author.IconUrl;
set
{
if (!value.IsNullOrUri()) throw new ArgumentException("Url must be a well-formed URI", nameof(IconUrl));
_author.IconUrl = value;
}
}
public EmbedAuthorBuilder()
{
_author = new EmbedAuthor();
}
public EmbedAuthorBuilder WithName(string name)
{
Name = name;
return this;
}
public EmbedAuthorBuilder WithUrl(string url)
{
Url = url;
return this;
}
public EmbedAuthorBuilder WithIconUrl(string iconUrl)
{
IconUrl = iconUrl;
return this;
}
public EmbedAuthor Build()
=> _author;
}
public class EmbedFooterBuilder
{
private EmbedFooter _footer;
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 string IconUrl
{
get => _footer.IconUrl;
set
{
if (!value.IsNullOrUri()) throw new ArgumentException("Url must be a well-formed URI", nameof(IconUrl));
_footer.IconUrl = value;
}
}
public EmbedFooterBuilder()
{
_footer = new EmbedFooter();
}
public EmbedFooterBuilder WithText(string text)
{
Text = text;
return this;
}
public EmbedFooterBuilder WithIconUrl(string iconUrl)
{
IconUrl = iconUrl;
return this;
}
public EmbedFooter Build()
=> _footer;
}
}

View File

@@ -1,58 +0,0 @@
using System;
namespace Discord
{
public static class EmbedBuilderExtensions
{
public static EmbedBuilder WithColor(this EmbedBuilder builder, uint rawValue) =>
builder.WithColor(new Color(rawValue));
public static EmbedBuilder WithColor(this EmbedBuilder builder, byte r, byte g, byte b) =>
builder.WithColor(new Color(r, g, b));
public static EmbedBuilder WithColor(this EmbedBuilder builder, int r, int g, int b) =>
builder.WithColor(new Color(r, g, b));
public static EmbedBuilder WithColor(this EmbedBuilder builder, float r, float g, float b) =>
builder.WithColor(new Color(r, g, b));
public static EmbedBuilder WithAuthor(this EmbedBuilder builder, IUser user) =>
builder.WithAuthor($"{user.Username}#{user.Discriminator}", user.GetAvatarUrl());
public static EmbedBuilder WithAuthor(this EmbedBuilder builder, IGuildUser user) =>
builder.WithAuthor($"{user.Nickname ?? user.Username}#{user.Discriminator}", user.GetAvatarUrl());
public static EmbedBuilder ToEmbedBuilder(this IEmbed embed)
{
if (embed.Type != EmbedType.Rich)
throw new InvalidOperationException($"Only {nameof(EmbedType.Rich)} embeds may be built.");
var builder = new EmbedBuilder
{
Author = new EmbedAuthorBuilder
{
Name = embed.Author?.Name,
IconUrl = embed.Author?.IconUrl,
Url = embed.Author?.Url
},
Color = embed.Color ?? Color.Default,
Description = embed.Description,
Footer = new EmbedFooterBuilder
{
Text = embed.Footer?.Text,
IconUrl = embed.Footer?.IconUrl
},
ImageUrl = embed.Image?.Url,
ThumbnailUrl = embed.Thumbnail?.Url,
Timestamp = embed.Timestamp,
Title = embed.Title,
Url = embed.Url
};
foreach (var field in embed.Fields)
builder.AddField(field.Name, field.Value, field.Inline);
return builder;
}
}
}