diff --git a/src/Discord.Net.Core/Entities/Messages/Builders/CodeLanguage.cs b/src/Discord.Net.Core/Entities/Messages/Builders/CodeLanguage.cs
new file mode 100644
index 000000000..7cfddbde6
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Messages/Builders/CodeLanguage.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord
+{
+ ///
+ /// Represents a language in which codeblocks can be formatted.
+ ///
+ public struct CodeLanguage
+ {
+ ///
+ /// Gets the tag of the language.
+ ///
+ public string Tag { get; }
+
+ ///
+ /// Gets the name of the language. if this was constructed with no name provided.
+ ///
+ public string Name { get; } = string.Empty;
+
+ ///
+ /// Gets the CSharp language format.
+ ///
+ public static readonly CodeLanguage CSharp = new("cs", "csharp");
+
+ ///
+ /// Gets the Javascript language format.
+ ///
+ public static readonly CodeLanguage JavaScript = new("js", "javascript");
+
+ ///
+ /// Gets the XML language format.
+ ///
+ public static readonly CodeLanguage XML = new("xml", "xml");
+
+ ///
+ /// Gets the HTML language format.
+ ///
+ public static readonly CodeLanguage HTML = new("html", "html");
+
+ ///
+ /// Gets the CSS markdown format.
+ ///
+ public static readonly CodeLanguage CSS = new("css", "css");
+
+ ///
+ /// Gets a language format that represents none.
+ ///
+ public static readonly CodeLanguage None = new("", "none");
+
+ ///
+ /// Creates a new language format with name & tag.
+ ///
+ /// The tag with which markdown will be formatted.
+ /// The name of the language.
+ public CodeLanguage(string tag, string name)
+ {
+ Tag = tag;
+ Name = name;
+ }
+
+ ///
+ /// Creates a new language format with a tag.
+ ///
+ /// The tag with which markdown will be formatted.
+ public CodeLanguage(string tag)
+ => Tag = tag;
+
+ ///
+ /// Gets the tag of the language.
+ ///
+ ///
+ public static implicit operator string(CodeLanguage language)
+ => language.Tag;
+
+ ///
+ /// Gets a language based on the tag.
+ ///
+ ///
+ public static implicit operator CodeLanguage(string tag)
+ => new(tag);
+
+ ///
+ /// Creates markdown format for this language.
+ ///
+ /// The input string to format.
+ /// A markdown formatted code-block with this language.
+ public string ToMarkdown(string input)
+ => $"```{Tag}\n{input}\n```";
+
+ ///
+ /// Gets the tag of the language.
+ ///
+ ///
+ public override string ToString()
+ => $"{Tag}";
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Messages/Builders/HeaderFormat.cs b/src/Discord.Net.Core/Entities/Messages/Builders/HeaderFormat.cs
new file mode 100644
index 000000000..029110a1b
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Messages/Builders/HeaderFormat.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord
+{
+ ///
+ /// Represents the format in which a markdown header should be presented.
+ ///
+ public readonly struct HeaderFormat
+ {
+ public string Format { get; }
+
+ ///
+ /// The biggest header type.
+ ///
+ public static readonly HeaderFormat H1 = new("#");
+
+ ///
+ /// An above-average sized header.
+ ///
+ public static readonly HeaderFormat H2 = new("##");
+
+ ///
+ /// An average-sized header.
+ ///
+ public static readonly HeaderFormat H3 = new("###");
+
+ ///
+ /// A subheader.
+ ///
+ public static readonly HeaderFormat H4 = new("####");
+
+ ///
+ /// A smaller subheader.
+ ///
+ public static readonly HeaderFormat H5 = new("#####");
+
+ ///
+ /// Slightly bigger than regular bold markdown.
+ ///
+ public static readonly HeaderFormat H6 = new("######");
+
+ private HeaderFormat(string format)
+ => Format = format;
+
+ ///
+ /// Formats this header into markdown, appending provided string.
+ ///
+ /// The string to turn into a header.
+ /// A markdown formatted header title.
+ public string ToMarkdown(string input)
+ => $"{Format} {input}";
+
+ ///
+ /// Gets the markdown format for this header.
+ ///
+ /// The markdown format for this header.
+ public override string ToString()
+ => $"{Format}";
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Messages/MessageBuilder.cs b/src/Discord.Net.Core/Entities/Messages/Builders/MessageBuilder.cs
similarity index 84%
rename from src/Discord.Net.Core/Entities/Messages/MessageBuilder.cs
rename to src/Discord.Net.Core/Entities/Messages/Builders/MessageBuilder.cs
index c03f38029..be740fe26 100644
--- a/src/Discord.Net.Core/Entities/Messages/MessageBuilder.cs
+++ b/src/Discord.Net.Core/Entities/Messages/Builders/MessageBuilder.cs
@@ -8,35 +8,40 @@ using System.Threading.Tasks;
namespace Discord
{
///
- /// Represents a generic message builder that can build s.
+ /// Represents a generic message builder that can build 's.
///
public class MessageBuilder
{
- private string _content;
- private List _stickers = new();
- private List _embeds = new();
- private List _files = new();
+ private readonly List _files;
+
+ private List _stickers;
+ private List _embeds;
+
///
/// Gets or sets the content of this message
///
- /// The content is bigger than the .
- public string Content
- {
- get => _content;
- set
- {
- if (_content?.Length > DiscordConfig.MaxMessageSize)
- throw new ArgumentOutOfRangeException(nameof(value), $"Message size must be less than or equal to {DiscordConfig.MaxMessageSize} characters");
-
- _content = value;
- }
- }
+ public TextBuilder Content { get; set; }
///
/// Gets or sets whether or not this message is TTS.
///
public bool IsTTS { get; set; }
+ ///
+ /// Gets or sets the allowed mentions of this message.
+ ///
+ public AllowedMentions AllowedMentions { get; set; }
+
+ ///
+ /// Gets or sets the message reference (reply to) of this message.
+ ///
+ public MessageReference MessageReference { get; set; }
+
+ ///
+ /// Gets or sets the components of this message.
+ ///
+ public ComponentBuilder Components { get; set; }
+
///
/// Gets or sets the embeds of this message.
///
@@ -52,21 +57,6 @@ namespace Discord
}
}
- ///
- /// Gets or sets the allowed mentions of this message.
- ///
- public AllowedMentions AllowedMentions { get; set; }
-
- ///
- /// Gets or sets the message reference (reply to) of this message.
- ///
- public MessageReference MessageReference { get; set; }
-
- ///
- /// Gets or sets the components of this message.
- ///
- public ComponentBuilder Components { get; set; } = new();
-
///
/// Gets or sets the stickers sent with this message.
///
@@ -100,14 +90,32 @@ namespace Discord
///
public MessageFlags Flags { get; set; }
+ ///
+ /// Creates a new based on the value of .
+ ///
+ /// The message content to create this from.
+ public MessageBuilder(string content)
+ {
+ Content = new TextBuilder(content);
+ }
+
+ public MessageBuilder()
+ {
+ _embeds = new();
+ _stickers = new();
+ _files = new();
+
+ Components = new();
+ }
+
///
/// Sets the of this message.
///
/// The content of the message.
/// The current builder.
- public MessageBuilder WithContent(string content)
+ public virtual MessageBuilder WithContent(TextBuilder builder)
{
- Content = content;
+ Content = builder;
return this;
}
@@ -116,7 +124,7 @@ namespace Discord
///
/// whether or not this message is tts.
/// The current builder.
- public MessageBuilder WithTTS(bool isTTS)
+ public virtual MessageBuilder WithTTS(bool isTTS)
{
IsTTS = isTTS;
return this;
@@ -128,7 +136,7 @@ namespace Discord
/// The embeds to be put in this message.
/// The current builder.
/// A message can only contain a maximum of embeds.
- public MessageBuilder WithEmbeds(params EmbedBuilder[] embeds)
+ public virtual MessageBuilder WithEmbeds(params EmbedBuilder[] embeds)
{
Embeds = new(embeds);
return this;
@@ -140,7 +148,7 @@ namespace Discord
/// The embed builder to add
/// The current builder.
/// A message can only contain a maximum of embeds.
- public MessageBuilder AddEmbed(EmbedBuilder embed)
+ public virtual MessageBuilder AddEmbed(EmbedBuilder embed)
{
if (_embeds?.Count >= DiscordConfig.MaxEmbedsPerMessage)
throw new ArgumentOutOfRangeException(nameof(embed.Length), $"A message can only contain a maximum of {DiscordConfig.MaxEmbedsPerMessage} embeds");
@@ -157,7 +165,7 @@ namespace Discord
///
/// The allowed mentions for this message.
/// The current builder.
- public MessageBuilder WithAllowedMentions(AllowedMentions allowedMentions)
+ public virtual MessageBuilder WithAllowedMentions(AllowedMentions allowedMentions)
{
AllowedMentions = allowedMentions;
return this;
@@ -168,7 +176,7 @@ namespace Discord
///
/// The message reference (reply-to) for this message.
/// The current builder.
- public MessageBuilder WithMessageReference(MessageReference reference)
+ public virtual MessageBuilder WithMessageReference(MessageReference reference)
{
MessageReference = reference;
return this;
@@ -179,7 +187,7 @@ namespace Discord
///
/// The message to set as a reference.
/// The current builder.
- public MessageBuilder WithMessageReference(IMessage message)
+ public virtual MessageBuilder WithMessageReference(IMessage message)
{
if (message != null)
MessageReference = new MessageReference(message.Id, message.Channel?.Id, ((IGuildChannel)message.Channel)?.GuildId);
@@ -191,7 +199,7 @@ namespace Discord
///
/// The component builder to set.
/// The current builder.
- public MessageBuilder WithComponentBuilder(ComponentBuilder builder)
+ public virtual MessageBuilder WithComponentBuilder(ComponentBuilder builder)
{
Components = builder;
return this;
@@ -203,7 +211,7 @@ namespace Discord
/// The button builder to add.
/// The optional row to place the button on.
/// The current builder.
- public MessageBuilder WithButton(ButtonBuilder button, int row = 0)
+ public virtual MessageBuilder WithButton(ButtonBuilder button, int row = 0)
{
Components ??= new();
Components.WithButton(button, row);
@@ -221,7 +229,7 @@ namespace Discord
/// Whether or not the newly created button is disabled.
/// The row the button should be placed on.
/// The current builder.
- public MessageBuilder WithButton(
+ public virtual MessageBuilder WithButton(
string label = null,
string customId = null,
ButtonStyle style = ButtonStyle.Primary,
@@ -241,7 +249,7 @@ namespace Discord
/// The select menu builder to add.
/// The optional row to place the select menu on.
/// The current builder.
- public MessageBuilder WithSelectMenu(SelectMenuBuilder menu, int row = 0)
+ public virtual MessageBuilder WithSelectMenu(SelectMenuBuilder menu, int row = 0)
{
Components ??= new();
Components.WithSelectMenu(menu, row);
@@ -259,7 +267,7 @@ namespace Discord
/// Whether or not the menu is disabled.
/// The row to add the menu to.
/// The current builder.
- public MessageBuilder WithSelectMenu(string customId, List options,
+ public virtual MessageBuilder WithSelectMenu(string customId, List options,
string placeholder = null, int minValues = 1, int maxValues = 1, bool disabled = false, int row = 0)
{
Components ??= new();
@@ -272,7 +280,7 @@ namespace Discord
///
/// The file collection to set.
/// The current builder.
- public MessageBuilder WithFiles(IEnumerable files)
+ public virtual MessageBuilder WithFiles(IEnumerable files)
{
Files = new List(files);
return this;
@@ -283,7 +291,7 @@ namespace Discord
///
/// The file to add.
/// The current builder.
- public MessageBuilder AddFile(FileAttachment file)
+ public virtual MessageBuilder AddFile(FileAttachment file)
{
Files.Add(file);
return this;
@@ -300,7 +308,7 @@ namespace Discord
: ImmutableArray