WHEW. Added placeholders in embeds and quotes, added docs about it to explained features. Wrote a placeholder system and fixed some bugs

This commit is contained in:
Master Kwoth
2017-06-28 02:44:30 +02:00
parent aa5b7f96c7
commit 942f15cf05
14 changed files with 328 additions and 210 deletions

View File

@ -0,0 +1,132 @@
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using NadekoBot.Extensions;
using NadekoBot.Services;
using NadekoBot.Services.Music;
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Text.RegularExpressions;
namespace NadekoBot.DataStructures.Replacements
{
public class ReplacementBuilder
{
private static readonly Regex rngRegex = new Regex("%rng(?:(?<from>(?:-)?\\d+)-(?<to>(?:-)?\\d+))?%", RegexOptions.Compiled);
private ConcurrentDictionary<string, Func<string>> _reps = new ConcurrentDictionary<string, Func<string>>();
private ConcurrentDictionary<Regex, Func<Match, string>> _regex = new ConcurrentDictionary<Regex, Func<Match, string>>();
public ReplacementBuilder()
{
WithRngRegex();
}
public ReplacementBuilder WithDefault(IUser usr, IMessageChannel ch, IGuild g, DiscordSocketClient client)
{
return this.WithUser(usr)
.WithChannel(ch)
.WithServer(g)
.WithClient(client);
}
public ReplacementBuilder WithDefault(ICommandContext ctx) =>
WithDefault(ctx.User, ctx.Channel, ctx.Guild, (DiscordSocketClient)ctx.Client);
public ReplacementBuilder WithClient(DiscordSocketClient client)
{
_reps.TryAdd("%mention%", () => $"<@{client.CurrentUser.Id}>");
_reps.TryAdd("%shardid%", () => client.ShardId.ToString());
_reps.TryAdd("%time%", () => DateTime.Now.ToString("HH:mm " + TimeZoneInfo.Local.StandardName.GetInitials()));
return this;
}
public ReplacementBuilder WithServer(IGuild g)
{
_reps.TryAdd("%sid%", () => g == null ? "DM" : g.Id.ToString());
_reps.TryAdd("%server%", () => g == null ? "DM" : g.Name);
return this;
}
public ReplacementBuilder WithChannel(IMessageChannel ch)
{
_reps.TryAdd("%channel%", () => (ch as ITextChannel)?.Mention ?? "#" + ch.Name);
_reps.TryAdd("%chname%", () => ch.Name);
_reps.TryAdd("%cid%", () => ch?.Id.ToString());
return this;
}
public ReplacementBuilder WithUser(IUser user)
{
_reps.TryAdd("%user%", () => user.Mention);
_reps.TryAdd("%userfull%", () => user.ToString());
_reps.TryAdd("%username%", () => user.Username);
_reps.TryAdd("%userdiscrim%", () => user.Discriminator);
_reps.TryAdd("%id%", () => user.Id.ToString());
_reps.TryAdd("%uid%", () => user.Id.ToString());
return this;
}
public ReplacementBuilder WithStats(DiscordSocketClient c)
{
_reps.TryAdd("%servers%", () => c.Guilds.Count.ToString());
_reps.TryAdd("%users%", () => c.Guilds.Sum(s => s.Users.Count).ToString());
return this;
}
public ReplacementBuilder WithMusic(MusicService ms)
{
_reps.TryAdd("%playing%", () =>
{
var cnt = ms.MusicPlayers.Count(kvp => kvp.Value.CurrentSong != null);
if (cnt != 1) return cnt.ToString();
try
{
var mp = ms.MusicPlayers.FirstOrDefault();
return mp.Value.CurrentSong.SongInfo.Title;
}
catch
{
return "No songs";
}
});
_reps.TryAdd("%queued%", () => ms.MusicPlayers.Sum(kvp => kvp.Value.Playlist.Count).ToString());
return this;
}
public ReplacementBuilder WithRngRegex()
{
var rng = new NadekoRandom();
_regex.TryAdd(rngRegex, (match) =>
{
int from = 0;
int.TryParse(match.Groups["from"].ToString(), out from);
int to = 0;
int.TryParse(match.Groups["to"].ToString(), out to);
if (from == 0 && to == 0)
{
return rng.Next(0, 11).ToString();
}
if (from >= to)
return string.Empty;
return rng.Next(from, to + 1).ToString();
});
return this;
}
public ReplacementBuilder WithOverride(string key, Func<string> output)
{
_reps.AddOrUpdate(key, output, delegate { return output; });
return this;
}
public Replacer Build()
{
return new Replacer(_reps.Select(x => (x.Key, x.Value)).ToArray(), _regex.Select(x => (x.Key, x.Value)).ToArray());
}
}
}

View File

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace NadekoBot.DataStructures.Replacements
{
public class Replacer
{
private readonly IEnumerable<(string Key, Func<string> Text)> _replacements;
private readonly IEnumerable<(Regex Regex, Func<Match, string> Replacement)> _regex;
public Replacer(IEnumerable<(string, Func<string>)> replacements, IEnumerable<(Regex, Func<Match, string>)> regex)
{
_replacements = replacements;
_regex = regex;
}
public string Replace(string input)
{
if (string.IsNullOrWhiteSpace(input))
return input;
foreach (var item in _replacements)
{
if (input.Contains(item.Key))
input = input.Replace(item.Key, item.Text());
}
foreach (var item in _regex)
{
input = item.Regex.Replace(input, (m) => item.Replacement(m));
}
return input;
}
public void Replace(CREmbed embedData)
{
embedData.PlainText = Replace(embedData.PlainText);
embedData.Description = Replace(embedData.Description);
embedData.Title = Replace(embedData.Title);
if (embedData.Fields != null)
foreach (var f in embedData.Fields)
{
f.Name = Replace(f.Name);
f.Value = Replace(f.Value);
}
if (embedData.Footer != null)
embedData.Footer.Text = Replace(embedData.Footer.Text);
}
}
}

View File

@ -33,11 +33,11 @@ namespace NadekoBot.Modules.Administration
{
var config = uow.BotConfig.GetOrCreate();
_service.RotatingStatuses = config.RotatingStatuses = !config.RotatingStatuses;
config.RotatingStatuses = !config.RotatingStatuses;
uow.Complete();
}
}
if (_service.RotatingStatuses)
if (_service.BotConfig.RotatingStatuses)
await ReplyConfirmLocalized("ropl_enabled").ConfigureAwait(false);
else
await ReplyConfirmLocalized("ropl_disabled").ConfigureAwait(false);
@ -52,7 +52,6 @@ namespace NadekoBot.Modules.Administration
var config = uow.BotConfig.GetOrCreate();
var toAdd = new PlayingStatus { Status = status };
config.RotatingStatusMessages.Add(toAdd);
_service.RotatingStatusMessages.Add(toAdd);
await uow.CompleteAsync();
}
@ -63,13 +62,13 @@ namespace NadekoBot.Modules.Administration
[OwnerOnly]
public async Task ListPlaying()
{
if (!_service.RotatingStatusMessages.Any())
if (!_service.BotConfig.RotatingStatusMessages.Any())
await ReplyErrorLocalized("ropl_not_set").ConfigureAwait(false);
else
{
var i = 1;
await ReplyConfirmLocalized("ropl_list",
string.Join("\n\t", _service.RotatingStatusMessages.Select(rs => $"`{i++}.` {rs.Status}")))
string.Join("\n\t", _service.BotConfig.RotatingStatusMessages.Select(rs => $"`{i++}.` {rs.Status}")))
.ConfigureAwait(false);
}
@ -90,7 +89,6 @@ namespace NadekoBot.Modules.Administration
return;
msg = config.RotatingStatusMessages[index].Status;
config.RotatingStatusMessages.RemoveAt(index);
_service.RotatingStatusMessages.RemoveAt(index);
await uow.CompleteAsync();
}
await ReplyConfirmLocalized("reprm", msg).ConfigureAwait(false);

View File

@ -9,6 +9,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using NadekoBot.DataStructures;
using NadekoBot.DataStructures.Replacements;
namespace NadekoBot.Modules.Utility
{
@ -66,19 +67,14 @@ namespace NadekoBot.Modules.Utility
if (quote == null)
return;
CREmbed crembed;
if (CREmbed.TryParse(quote.Text, out crembed))
if (CREmbed.TryParse(quote.Text, out var crembed))
{
try
{
await Context.Channel.EmbedAsync(crembed.ToEmbed(), crembed.PlainText ?? "")
.ConfigureAwait(false);
}
catch (Exception ex)
{
_log.Warn("Sending CREmbed failed");
_log.Warn(ex);
}
new ReplacementBuilder()
.WithDefault(Context)
.Build()
.Replace(crembed);
await Context.Channel.EmbedAsync(crembed.ToEmbed(), crembed.PlainText?.SanitizeMentions() ?? "")
.ConfigureAwait(false);
return;
}
await Context.Channel.SendMessageAsync($"`#{quote.Id}` 📣 " + quote.Text.SanitizeMentions());
@ -118,29 +114,27 @@ namespace NadekoBot.Modules.Utility
using (var uow = _db.UnitOfWork)
{
var qfromid = uow.Quotes.Get(id);
CREmbed crembed;
if (qfromid == null)
{
await Context.Channel.SendErrorAsync(GetText("quotes_notfound"));
}
else if (CREmbed.TryParse(qfromid.Text, out crembed))
else if (CREmbed.TryParse(qfromid.Text, out var crembed))
{
try
{
await Context.Channel.EmbedAsync(crembed.ToEmbed(), crembed.PlainText ?? "")
.ConfigureAwait(false);
}
catch (Exception ex)
{
_log.Warn("Sending CREmbed failed");
_log.Warn(ex);
}
return;
new ReplacementBuilder()
.WithDefault(Context)
.Build()
.Replace(crembed);
await Context.Channel.EmbedAsync(crembed.ToEmbed(), crembed.PlainText?.SanitizeMentions() ?? "")
.ConfigureAwait(false);
}
else { await Context.Channel.SendMessageAsync($"`#{qfromid.Id}` 🗯️ " + qfromid.Keyword.ToLowerInvariant().SanitizeMentions() + ": " +
qfromid.Text.SanitizeMentions()); }
else
{
await Context.Channel.SendMessageAsync($"`#{qfromid.Id}` 🗯️ " + qfromid.Keyword.ToLowerInvariant().SanitizeMentions() + ": " +
qfromid.Text.SanitizeMentions());
}
}
}

View File

@ -199,7 +199,7 @@ namespace NadekoBot
var muteService = new MuteService(Client, AllGuildConfigs, Db);
var ratelimitService = new SlowmodeService(Client, AllGuildConfigs);
var protectionService = new ProtectionService(Client, AllGuildConfigs, muteService);
var playingRotateService = new PlayingRotateService(Client, BotConfig, musicService);
var playingRotateService = new PlayingRotateService(Client, BotConfig, musicService, Db);
var gameVcService = new GameVoiceChannelService(Client, Db, AllGuildConfigs);
var autoAssignRoleService = new AutoAssignRoleService(Client, AllGuildConfigs);
var logCommandService = new LogCommandService(Client, Strings, AllGuildConfigs, Db, muteService, protectionService);

View File

@ -1377,15 +1377,6 @@
<data name="typeadd_usage" xml:space="preserve">
<value>`{0}typeadd wordswords`</value>
</data>
<data name="poll_cmd" xml:space="preserve">
<value>poll</value>
</data>
<data name="poll_desc" xml:space="preserve">
<value>Creates a poll which requires users to send the number of the voting option to the bot.</value>
</data>
<data name="poll_usage" xml:space="preserve">
<value>`{0}poll Question?;Answer1;Answ 2;A_3`</value>
</data>
<data name="pollend_cmd" xml:space="preserve">
<value>pollend</value>
</data>
@ -2583,13 +2574,13 @@
<data name="togethertube_usage" xml:space="preserve">
<value>`{0}totube`</value>
</data>
<data name="publicpoll_cmd" xml:space="preserve">
<value>publicpoll ppoll</value>
<data name="poll_cmd" xml:space="preserve">
<value>poll ppoll</value>
</data>
<data name="publicpoll_desc" xml:space="preserve">
<data name="poll_desc" xml:space="preserve">
<value>Creates a public poll which requires users to type a number of the voting option in the channel command is ran in.</value>
</data>
<data name="publicpoll_usage" xml:space="preserve">
<data name="poll_usage" xml:space="preserve">
<value>`{0}ppoll Question?;Answer1;Answ 2;A_3`</value>
</data>
<data name="autotranslang_cmd" xml:space="preserve">

View File

@ -1,59 +1,65 @@
using Discord.WebSocket;
using NadekoBot.Extensions;
using NadekoBot.DataStructures.Replacements;
using NadekoBot.Services;
using NadekoBot.Services.Database.Models;
using NadekoBot.Services.Music;
using NLog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace NadekoBot.Services.Administration
{
//todo 99 - Could make a placeholder service, which can work for any module
//and have replacements which are dependent on the types provided in the constructor
public class PlayingRotateService
{
public List<PlayingStatus> RotatingStatusMessages { get; }
public volatile bool RotatingStatuses;
private readonly Timer _t;
private readonly DiscordSocketClient _client;
private readonly BotConfig _bc;
private readonly MusicService _music;
private readonly Logger _log;
private readonly Replacer _rep;
private readonly DbService _db;
public BotConfig BotConfig { get; private set; } //todo load whole botconifg, not just for this service when you have the time
private class TimerState
{
public int Index { get; set; }
}
public PlayingRotateService(DiscordSocketClient client, BotConfig bc, MusicService music)
public PlayingRotateService(DiscordSocketClient client, BotConfig bc, MusicService music, DbService db)
{
_client = client;
_bc = bc;
BotConfig = bc;
_music = music;
_db = db;
_log = LogManager.GetCurrentClassLogger();
_rep = new ReplacementBuilder()
.WithClient(client)
.WithStats(client)
.WithMusic(music)
.Build();
RotatingStatusMessages = _bc.RotatingStatusMessages;
RotatingStatuses = _bc.RotatingStatuses;
_t = new Timer(async (objState) =>
{
try
{
using (var uow = _db.UnitOfWork)
{
BotConfig = uow.BotConfig.GetOrCreate();
}
var state = (TimerState)objState;
if (!RotatingStatuses)
if (!BotConfig.RotatingStatuses)
return;
if (state.Index >= RotatingStatusMessages.Count)
if (state.Index >= BotConfig.RotatingStatusMessages.Count)
state.Index = 0;
if (!RotatingStatusMessages.Any())
if (!BotConfig.RotatingStatusMessages.Any())
return;
var status = RotatingStatusMessages[state.Index++].Status;
var status = BotConfig.RotatingStatusMessages[state.Index++].Status;
if (string.IsNullOrWhiteSpace(status))
return;
PlayingPlaceholders.ForEach(e => status = status.Replace(e.Key, e.Value(_client, _music)));
ShardSpecificPlaceholders.ForEach(e => status = status.Replace(e.Key, e.Value(client)));
status = _rep.Replace(status);
try { await client.SetGameAsync(status).ConfigureAwait(false); }
catch (Exception ex)
{
@ -66,31 +72,5 @@ namespace NadekoBot.Services.Administration
}
}, new TimerState(), TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
}
public Dictionary<string, Func<DiscordSocketClient, MusicService, string>> PlayingPlaceholders { get; } =
new Dictionary<string, Func<DiscordSocketClient, MusicService, string>> {
{ "%servers%", (c, ms) => c.Guilds.Count.ToString()},
{ "%users%", (c, ms) => c.Guilds.Sum(s => s.Users.Count).ToString()},
{ "%playing%", (c, ms) => {
var cnt = ms.MusicPlayers.Count(kvp => kvp.Value.CurrentSong != null);
if (cnt != 1) return cnt.ToString();
try {
var mp = ms.MusicPlayers.FirstOrDefault();
return mp.Value.CurrentSong.SongInfo.Title;
}
catch {
return "No songs";
}
}
},
{ "%queued%", (c, ms) => ms.MusicPlayers.Sum(kvp => kvp.Value.Playlist.Count).ToString()},
{ "%time%", (c, ms) => DateTime.Now.ToString("HH:mm " + TimeZoneInfo.Local.StandardName.GetInitials()) },
};
public Dictionary<string, Func<DiscordSocketClient, string>> ShardSpecificPlaceholders { get; } =
new Dictionary<string, Func<DiscordSocketClient, string>> {
{ "%shardid%", (client) => client.ShardId.ToString()},
{ "%shardguilds%", (client) => client.Guilds.Count.ToString()},
};
}
}

View File

@ -3,6 +3,7 @@ using AngleSharp.Dom.Html;
using Discord;
using Discord.WebSocket;
using NadekoBot.DataStructures;
using NadekoBot.DataStructures.Replacements;
using NadekoBot.Extensions;
using NadekoBot.Services.Database.Models;
using System;
@ -15,62 +16,12 @@ namespace NadekoBot.Services.CustomReactions
{
public static class Extensions
{
public static Dictionary<string, Func<IUserMessage, string, string>> responsePlaceholders = new Dictionary<string, Func<IUserMessage, string, string>>()
{
{"%target%", (ctx, trigger) => { return ctx.Content.Substring(trigger.Length).Trim().SanitizeMentions(); } },
{"%rnduser%", (ctx, client) => {
//var ch = ctx.Channel as ITextChannel;
//if(ch == null)
// return "";
//var g = ch.Guild as SocketGuild;
//if(g == null)
// return "";
//try {
// var usr = g.Users.Skip(new NadekoRandom().Next(0, g.Users.Count)).FirstOrDefault();
// return usr.Mention;
//}
//catch {
return "[%rnduser% is temp. disabled]";
//}
//var users = g.Users.ToArray();
//return users[new NadekoRandom().Next(0, users.Length-1)].Mention;
} },
};
public static Dictionary<string, Func<IUserMessage, DiscordSocketClient, string>> placeholders = new Dictionary<string, Func<IUserMessage, DiscordSocketClient, string>>()
{
{"%mention%", (ctx, client) => { return $"<@{client.CurrentUser.Id}>"; } },
{"%user%", (ctx, client) => { return ctx.Author.Mention; } },
//{"%rng%", (ctx) => { return new NadekoRandom().Next(0,10).ToString(); } }
};
private static readonly Regex rngRegex = new Regex("%rng(?:(?<from>(?:-)?\\d+)-(?<to>(?:-)?\\d+))?%", RegexOptions.Compiled);
private static readonly Regex imgRegex = new Regex("%(img|image):(?<tag>.*?)%", RegexOptions.Compiled);
private static readonly NadekoRandom rng = new NadekoRandom();
public static Dictionary<Regex, Func<Match, Task<string>>> regexPlaceholders = new Dictionary<Regex, Func<Match, Task<string>>>()
{
{ rngRegex, (match) => {
int from = 0;
int.TryParse(match.Groups["from"].ToString(), out from);
int to = 0;
int.TryParse(match.Groups["to"].ToString(), out to);
if(from == 0 && to == 0)
{
return Task.FromResult(rng.Next(0, 11).ToString());
}
if(from >= to)
return Task.FromResult(string.Empty);
return Task.FromResult(rng.Next(from,to+1).ToString());
} },
{ imgRegex, async (match) => {
var tag = match.Groups["tag"].ToString();
if(string.IsNullOrWhiteSpace(tag))
@ -96,29 +47,24 @@ namespace NadekoBot.Services.CustomReactions
private static string ResolveTriggerString(this string str, IUserMessage ctx, DiscordSocketClient client)
{
foreach (var ph in placeholders)
{
if (str.Contains(ph.Key))
str = str.ToLowerInvariant().Replace(ph.Key, ph.Value(ctx, client));
}
var rep = new ReplacementBuilder()
.WithUser(ctx.Author)
.WithClient(client)
.Build();
str = rep.Replace(str.ToLowerInvariant());
return str;
}
private static async Task<string> ResolveResponseStringAsync(this string str, IUserMessage ctx, DiscordSocketClient client, string resolvedTrigger)
{
foreach (var ph in placeholders)
{
var lowerKey = ph.Key.ToLowerInvariant();
if (str.Contains(lowerKey))
str = str.Replace(lowerKey, ph.Value(ctx, client));
}
var rep = new ReplacementBuilder()
.WithDefault(ctx.Author, ctx.Channel, (ctx.Channel as ITextChannel)?.Guild, client)
.WithOverride("%target%", () => ctx.Content.Substring(resolvedTrigger.Length).Trim())
.Build();
foreach (var ph in responsePlaceholders)
{
var lowerKey = ph.Key.ToLowerInvariant();
if (str.Contains(lowerKey))
str = str.Replace(lowerKey, ph.Value(ctx, resolvedTrigger));
}
str = rep.Replace(str.ToLowerInvariant());
foreach (var ph in regexPlaceholders)
{
@ -133,17 +79,24 @@ namespace NadekoBot.Services.CustomReactions
public static Task<string > ResponseWithContextAsync(this CustomReaction cr, IUserMessage ctx, DiscordSocketClient client)
=> cr.Response.ResolveResponseStringAsync(ctx, client, cr.Trigger.ResolveTriggerString(ctx, client));
public static async Task<IUserMessage> Send(this CustomReaction cr, IUserMessage context, DiscordSocketClient client, CustomReactionsService crs)
public static async Task<IUserMessage> Send(this CustomReaction cr, IUserMessage ctx, DiscordSocketClient client, CustomReactionsService crs)
{
var channel = cr.DmResponse ? await context.Author.CreateDMChannelAsync() : context.Channel;
var channel = cr.DmResponse ? await ctx.Author.CreateDMChannelAsync() : ctx.Channel;
crs.ReactionStats.AddOrUpdate(cr.Trigger, 1, (k, old) => ++old);
if (CREmbed.TryParse(cr.Response, out CREmbed crembed))
{
return await channel.EmbedAsync(crembed.ToEmbed(), crembed.PlainText ?? "");
var rep = new ReplacementBuilder()
.WithDefault(ctx.Author, ctx.Channel, (ctx.Channel as ITextChannel)?.Guild, client)
.WithOverride("%target%", () => ctx.Content.Substring(cr.Trigger.ResolveTriggerString(ctx, client).Length).Trim())
.Build();
rep.Replace(crembed);
return await channel.EmbedAsync(crembed.ToEmbed(), crembed.PlainText?.SanitizeMentions() ?? "");
}
return await channel.SendMessageAsync((await cr.ResponseWithContextAsync(context, client)).SanitizeMentions());
return await channel.SendMessageAsync((await cr.ResponseWithContextAsync(ctx, client)).SanitizeMentions());
}
}
}

View File

@ -1,6 +1,7 @@
using Discord;
using Discord.WebSocket;
using NadekoBot.DataStructures;
using NadekoBot.DataStructures.Replacements;
using NadekoBot.Extensions;
using NadekoBot.Services.Database.Models;
using NLog;
@ -45,15 +46,17 @@ namespace NadekoBot.Services
if (channel == null) //maybe warn the server owner that the channel is missing
return;
CREmbed embedData;
if (CREmbed.TryParse(conf.ChannelByeMessageText, out embedData))
var rep = new ReplacementBuilder()
.WithDefault(user, channel, user.Guild, _client)
.Build();
if (CREmbed.TryParse(conf.ChannelByeMessageText, out var embedData))
{
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);
rep.Replace(embedData);
try
{
var toDelete = await channel.EmbedAsync(embedData.ToEmbed(), embedData.PlainText ?? "").ConfigureAwait(false);
var toDelete = await channel.EmbedAsync(embedData.ToEmbed(), embedData.PlainText?.SanitizeMentions() ?? "").ConfigureAwait(false);
if (conf.AutoDeleteByeMessagesTimer > 0)
{
toDelete.DeleteAfter(conf.AutoDeleteByeMessagesTimer);
@ -63,7 +66,7 @@ namespace NadekoBot.Services
}
else
{
var msg = conf.ChannelByeMessageText.Replace("%user%", user.Username).Replace("%id%", user.Id.ToString()).Replace("%server%", user.Guild.Name);
var msg = rep.Replace(conf.ChannelByeMessageText);
if (string.IsNullOrWhiteSpace(msg))
return;
try
@ -98,16 +101,16 @@ namespace NadekoBot.Services
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 rep = new ReplacementBuilder()
.WithDefault(user, channel, user.Guild, _client)
.Build();
CREmbed embedData;
if (CREmbed.TryParse(conf.ChannelGreetMessageText, out embedData))
if (CREmbed.TryParse(conf.ChannelGreetMessageText, out var embedData))
{
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);
rep.Replace(embedData);
try
{
var toDelete = await channel.EmbedAsync(embedData.ToEmbed(), embedData.PlainText ?? "").ConfigureAwait(false);
var toDelete = await channel.EmbedAsync(embedData.ToEmbed(), embedData.PlainText?.SanitizeMentions() ?? "").ConfigureAwait(false);
if (conf.AutoDeleteGreetMessagesTimer > 0)
{
toDelete.DeleteAfter(conf.AutoDeleteGreetMessagesTimer);
@ -117,7 +120,7 @@ namespace NadekoBot.Services
}
else
{
var msg = conf.ChannelGreetMessageText.Replace("%user%", user.Mention).Replace("%id%", user.Id.ToString()).Replace("%server%", user.Guild.Name);
var msg = rep.Replace(conf.ChannelGreetMessageText);
if (!string.IsNullOrWhiteSpace(msg))
{
try
@ -140,21 +143,22 @@ namespace NadekoBot.Services
if (channel != null)
{
CREmbed embedData;
if (CREmbed.TryParse(conf.DmGreetMessageText, out embedData))
var rep = new ReplacementBuilder()
.WithDefault(user, channel, user.Guild, _client)
.Build();
if (CREmbed.TryParse(conf.DmGreetMessageText, out var 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);
rep.Replace(embedData);
try
{
await channel.EmbedAsync(embedData.ToEmbed(), embedData.PlainText ?? "").ConfigureAwait(false);
await channel.EmbedAsync(embedData.ToEmbed(), embedData.PlainText?.SanitizeMentions() ?? "").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);
var msg = rep.Replace(conf.DmGreetMessageText);
if (!string.IsNullOrWhiteSpace(msg))
{
await channel.SendConfirmAsync(msg).ConfigureAwait(false);
@ -409,4 +413,4 @@ namespace NadekoBot.Services
ChannelByeMessageText = g.ChannelByeMessageText,
};
}
}
}

View File

@ -1,5 +1,6 @@
using Discord;
using Discord.WebSocket;
using NadekoBot.DataStructures.Replacements;
using NadekoBot.Extensions;
using NadekoBot.Services.Database;
using NadekoBot.Services.Database.Models;
@ -20,13 +21,6 @@ namespace NadekoBot.Services.Utility
public string RemindMessageFormat { get; }
public readonly IDictionary<string, Func<Reminder, string>> _replacements = new Dictionary<string, Func<Reminder, string>>
{
{ "%message%" , (r) => r.Message },
{ "%user%", (r) => $"<@!{r.UserId}>" },
{ "%target%", (r) => r.IsPrivate ? "Direct Message" : $"<#{r.ChannelId}>"}
};
private readonly Logger _log;
private readonly CancellationTokenSource cancelSource;
private readonly CancellationToken cancelAllToken;
@ -82,11 +76,13 @@ namespace NadekoBot.Services.Utility
if (ch == null)
return;
await ch.SendMessageAsync(
_replacements.Aggregate(RemindMessageFormat,
(cur, replace) => cur.Replace(replace.Key, replace.Value(r)))
.SanitizeMentions()
).ConfigureAwait(false); //it works trust me
var rep = new ReplacementBuilder()
.WithOverride("%user%", () => $"<@!{r.UserId}>")
.WithOverride("%message%", () => r.Message)
.WithOverride("%target%", () => r.IsPrivate ? "Direct Message" : $"<#{r.ChannelId}>")
.Build();
await ch.SendMessageAsync(rep.Replace(RemindMessageFormat).SanitizeMentions()).ConfigureAwait(false); //it works trust me
}
catch (Exception ex) { _log.Warn(ex); }
finally