diff --git a/src/NadekoBot/DataStructures/CREmbed.cs b/src/NadekoBot/DataStructures/CREmbed.cs new file mode 100644 index 00000000..88e81630 --- /dev/null +++ b/src/NadekoBot/DataStructures/CREmbed.cs @@ -0,0 +1,91 @@ +using Discord; +using Newtonsoft.Json; +using NLog; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NadekoBot.DataStructures +{ + public class CREmbed + { + private static readonly Logger _log; + public string PlainText { get; set; } + public string Title { get; set; } + public string Description { get; set; } + public CREmbedFooter Footer { get; set; } + public string Thumbnail { get; set; } + public string Image { get; set; } + public CREmbedField[] Fields { get; set; } + public uint Color { get; set; } = 7458112; + + static CREmbed() + { + _log = LogManager.GetCurrentClassLogger(); + } + + public bool IsValid => + !string.IsNullOrWhiteSpace(Title) || + !string.IsNullOrWhiteSpace(Description) || + !string.IsNullOrWhiteSpace(Thumbnail) || + !string.IsNullOrWhiteSpace(Image) || + (Footer != null && (!string.IsNullOrWhiteSpace(Footer.Text) || !string.IsNullOrWhiteSpace(Footer.IconUrl))) || + (Fields != null && Fields.Length > 0); + + public EmbedBuilder ToEmbed() + { + var embed = new EmbedBuilder() + .WithTitle(Title) + .WithDescription(Description) + .WithColor(new Discord.Color(Color)); + if (Footer != null) + embed.WithFooter(efb => efb.WithIconUrl(Footer.IconUrl).WithText(Footer.Text)); + embed.WithThumbnailUrl(Thumbnail) + .WithImageUrl(Image); + + if (Fields != null) + foreach (var f in Fields) + { + embed.AddField(efb => efb.WithName(f.Name).WithValue(f.Value).WithIsInline(f.Inline)); + } + + return embed; + } + + public static bool TryParse(string input, out CREmbed embed) + { + embed = null; + if (string.IsNullOrWhiteSpace(input)) + return false; + + try + { + var crembed = JsonConvert.DeserializeObject(input); + + if (!crembed.IsValid) + return false; + + embed = crembed; + return true; + } + catch (Exception ex) + { + return false; + } + } + } + + public class CREmbedField + { + public string Name { get; set; } + public string Value { get; set; } + public bool Inline { get; set; } + } + + public class CREmbedFooter { + public string Text { get; set; } + public string IconUrl { get; set; } + } +} diff --git a/src/NadekoBot/Modules/Administration/Commands/ServerGreetCommands.cs b/src/NadekoBot/Modules/Administration/Commands/ServerGreetCommands.cs index 9183b814..6c1be19e 100644 --- a/src/NadekoBot/Modules/Administration/Commands/ServerGreetCommands.cs +++ b/src/NadekoBot/Modules/Administration/Commands/ServerGreetCommands.cs @@ -2,6 +2,7 @@ using Discord.Commands; using Discord.WebSocket; using NadekoBot.Attributes; +using NadekoBot.DataStructures; using NadekoBot.Extensions; using NadekoBot.Services; using NadekoBot.Services.Database; @@ -83,77 +84,137 @@ namespace NadekoBot.Modules.Administration return settings; } - //todo optimize ASAP - private static async Task UserLeft(IGuildUser user) + private static Task UserLeft(IGuildUser user) { - try + var _ = Task.Run(async () => { - var conf = GetOrAddSettingsForGuild(user.GuildId); - - if (!conf.SendChannelByeMessage) return; - var channel = (await user.Guild.GetTextChannelsAsync()).SingleOrDefault(c => c.Id == conf.ByeMessageChannelId); - - if (channel == null) //maybe warn the server owner that the channel is missing - return; - - var msg = conf.ChannelByeMessageText.Replace("%user%", user.Username).Replace("%id%", user.Id.ToString()).Replace("%server%", user.Guild.Name); - if (string.IsNullOrWhiteSpace(msg)) - return; try { - var toDelete = await channel.SendMessageAsync(msg.SanitizeMentions()).ConfigureAwait(false); - if (conf.AutoDeleteByeMessagesTimer > 0) + var conf = GetOrAddSettingsForGuild(user.GuildId); + + if (!conf.SendChannelByeMessage) return; + var channel = (await user.Guild.GetTextChannelsAsync()).SingleOrDefault(c => c.Id == conf.ByeMessageChannelId); + + if (channel == null) //maybe warn the server owner that the channel is missing + return; + CREmbed embedData; + if (CREmbed.TryParse(conf.ChannelByeMessageText, out embedData)) { - toDelete.DeleteAfter(conf.AutoDeleteByeMessagesTimer); + embedData.PlainText = embedData.PlainText?.Replace("%user%", user.Username).Replace("%id%", user.Id.ToString()).Replace("%server%", user.Guild.Name); + embedData.Description = embedData.Description?.Replace("%user%", user.Username).Replace("%id%", user.Id.ToString()).Replace("%server%", user.Guild.Name); + embedData.Title = embedData.Title?.Replace("%user%", user.Username).Replace("%id%", user.Id.ToString()).Replace("%server%", user.Guild.Name); + try + { + var toDelete = await channel.EmbedAsync(embedData.ToEmbed(), embedData.PlainText ?? "").ConfigureAwait(false); + if (conf.AutoDeleteByeMessagesTimer > 0) + { + toDelete.DeleteAfter(conf.AutoDeleteByeMessagesTimer); + } + } + catch (Exception ex) { _log.Warn(ex); } + } + else + { + var msg = conf.ChannelByeMessageText.Replace("%user%", user.Username).Replace("%id%", user.Id.ToString()).Replace("%server%", user.Guild.Name); + if (string.IsNullOrWhiteSpace(msg)) + return; + try + { + var toDelete = await channel.SendMessageAsync(msg.SanitizeMentions()).ConfigureAwait(false); + if (conf.AutoDeleteByeMessagesTimer > 0) + { + toDelete.DeleteAfter(conf.AutoDeleteByeMessagesTimer); + } + } + catch (Exception ex) { _log.Warn(ex); } } } - catch (Exception ex) { _log.Warn(ex); } - } - catch { } + catch { } + }); + return Task.CompletedTask; } - private static async Task UserJoined(IGuildUser user) + private static Task UserJoined(IGuildUser user) { - try + var _ = Task.Run(async () => { - var conf = GetOrAddSettingsForGuild(user.GuildId); - - if (conf.SendChannelGreetMessage) + try { - var channel = (await user.Guild.GetTextChannelsAsync()).SingleOrDefault(c => c.Id == conf.GreetMessageChannelId); - if (channel != null) //maybe warn the server owner that the channel is missing + var conf = GetOrAddSettingsForGuild(user.GuildId); + + if (conf.SendChannelGreetMessage) { - var msg = conf.ChannelGreetMessageText.Replace("%user%", user.Mention).Replace("%id%", user.Id.ToString()).Replace("%server%", user.Guild.Name); - if (!string.IsNullOrWhiteSpace(msg)) + var channel = (await user.Guild.GetTextChannelsAsync()).SingleOrDefault(c => c.Id == conf.GreetMessageChannelId); + if (channel != null) //maybe warn the server owner that the channel is missing { - try + + CREmbed embedData; + if (CREmbed.TryParse(conf.ChannelGreetMessageText, out embedData)) { - var toDelete = await channel.SendMessageAsync(msg.SanitizeMentions()).ConfigureAwait(false); - if (conf.AutoDeleteGreetMessagesTimer > 0) + embedData.PlainText = embedData.PlainText?.Replace("%user%", user.Mention).Replace("%id%", user.Id.ToString()).Replace("%server%", user.Guild.Name); + embedData.Description = embedData.Description?.Replace("%user%", user.Mention).Replace("%id%", user.Id.ToString()).Replace("%server%", user.Guild.Name); + embedData.Title = embedData.Title?.Replace("%user%", user.ToString()).Replace("%id%", user.Id.ToString()).Replace("%server%", user.Guild.Name); + try { - toDelete.DeleteAfter(conf.AutoDeleteGreetMessagesTimer); + var toDelete = await channel.EmbedAsync(embedData.ToEmbed(), embedData.PlainText ?? "").ConfigureAwait(false); + if (conf.AutoDeleteGreetMessagesTimer > 0) + { + toDelete.DeleteAfter(conf.AutoDeleteGreetMessagesTimer); + } + } + catch (Exception ex) { _log.Warn(ex); } + } + else + { + var msg = conf.ChannelGreetMessageText.Replace("%user%", user.Mention).Replace("%id%", user.Id.ToString()).Replace("%server%", user.Guild.Name); + if (!string.IsNullOrWhiteSpace(msg)) + { + try + { + var toDelete = await channel.SendMessageAsync(msg.SanitizeMentions()).ConfigureAwait(false); + if (conf.AutoDeleteGreetMessagesTimer > 0) + { + toDelete.DeleteAfter(conf.AutoDeleteGreetMessagesTimer); + } + } + catch (Exception ex) { _log.Warn(ex); } } } - catch (Exception ex) { _log.Warn(ex); } } } - } - if (conf.SendDmGreetMessage) - { - var channel = await user.CreateDMChannelAsync(); - - if (channel != null) + if (conf.SendDmGreetMessage) { - var msg = conf.DmGreetMessageText.Replace("%user%", user.Username).Replace("%server%", user.Guild.Name); - if (!string.IsNullOrWhiteSpace(msg)) + var channel = await user.CreateDMChannelAsync(); + + if (channel != null) { - await channel.SendConfirmAsync(msg).ConfigureAwait(false); + CREmbed embedData; + if (CREmbed.TryParse(conf.ChannelGreetMessageText, out embedData)) + { + embedData.PlainText = embedData.PlainText?.Replace("%user%", user.ToString()).Replace("%id%", user.Id.ToString()).Replace("%server%", user.Guild.Name); + embedData.Description = embedData.Description?.Replace("%user%", user.ToString()).Replace("%id%", user.Id.ToString()).Replace("%server%", user.Guild.Name); + embedData.Title = embedData.Title?.Replace("%user%", user.ToString()).Replace("%id%", user.Id.ToString()).Replace("%server%", user.Guild.Name); + try + { + await channel.EmbedAsync(embedData.ToEmbed(), embedData.PlainText ?? "").ConfigureAwait(false); + } + catch (Exception ex) { _log.Warn(ex); } + } + else + { + var msg = conf.DmGreetMessageText.Replace("%user%", user.ToString()).Replace("%id%", user.Id.ToString()).Replace("%server%", user.Guild.Name); + if (!string.IsNullOrWhiteSpace(msg)) + { + await channel.SendConfirmAsync(msg).ConfigureAwait(false); + } + } } } } - } - catch { } + catch { } + }); + return Task.CompletedTask; } [NadekoCommand, Usage, Description, Aliases] diff --git a/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs b/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs index 1f1cca1d..8f76f0a8 100644 --- a/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs +++ b/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs @@ -11,6 +11,8 @@ using NLog; using System.Diagnostics; using Discord.WebSocket; using System; +using Newtonsoft.Json; +using NadekoBot.DataStructures; namespace NadekoBot.Modules.CustomReactions { @@ -69,7 +71,22 @@ namespace NadekoBot.Modules.CustomReactions if (reaction != null) { if (reaction.Response != "-") - try { await channel.SendMessageAsync(reaction.ResponseWithContext(umsg)).ConfigureAwait(false); } catch { } + { + CREmbed crembed; + if (CREmbed.TryParse(reaction.Response, out crembed)) + { + try { await channel.EmbedAsync(crembed.ToEmbed(), crembed.PlainText ?? "").ConfigureAwait(false); } + catch (Exception ex) + { + _log.Warn("Sending CREmbed failed"); + _log.Warn(ex); + } + } + else + { + try { await channel.SendMessageAsync(reaction.ResponseWithContext(umsg)).ConfigureAwait(false); } catch { } + } + } ReactionStats.AddOrUpdate(reaction.Trigger, 1, (k, old) => ++old); return true; @@ -91,7 +108,20 @@ namespace NadekoBot.Modules.CustomReactions if (greaction != null) { - try { await channel.SendMessageAsync(greaction.ResponseWithContext(umsg)).ConfigureAwait(false); } catch { } + CREmbed crembed; + if (CREmbed.TryParse(greaction.Response, out crembed)) + { + try { await channel.EmbedAsync(crembed.ToEmbed(), crembed.PlainText ?? "").ConfigureAwait(false); } + catch (Exception ex) + { + _log.Warn("Sending CREmbed failed"); + _log.Warn(ex); + } + } + else + { + try { await channel.SendMessageAsync(greaction.ResponseWithContext(umsg)).ConfigureAwait(false); } catch { } + } ReactionStats.AddOrUpdate(greaction.Trigger, 1, (k, old) => ++old); return true; }