using System; using System.Collections.Concurrent; using System.Linq; using System.Text.RegularExpressions; using Discord; using Discord.Commands; using Discord.WebSocket; using NadekoBot.Extensions; namespace NadekoBot.Common.Replacements { public class ReplacementBuilder { private static readonly Regex rngRegex = new Regex("%rng(?:(?(?:-)?\\d+)-(?(?:-)?\\d+))?%", RegexOptions.Compiled); private ConcurrentDictionary> _reps = new ConcurrentDictionary>(); private ConcurrentDictionary> _regex = new ConcurrentDictionary>(); public ReplacementBuilder() { WithRngRegex(); } public ReplacementBuilder WithDefault(IUser usr, IMessageChannel ch, IGuild g, DiscordSocketClient client) { return this.WithUser(usr) .WithChannel(ch) .WithServer(client, 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(DiscordSocketClient client, IGuild g) { _reps.TryAdd("%sid%", () => g == null ? "DM" : g.Id.ToString()); _reps.TryAdd("%server%", () => g == null ? "DM" : g.Name); //_reps.TryAdd("%server_time%", () => //{ // TimeZoneInfo to = TimeZoneInfo.Local; // if (g != null) // { // if (GuildTimezoneService.AllServices.TryGetValue(client.CurrentUser.Id, out var tz)) // to = tz.GetTimeZoneOrDefault(g.Id) ?? TimeZoneInfo.Local; // } // return TimeZoneInfo.ConvertTime(DateTime.UtcNow, // TimeZoneInfo.Utc, // to).ToString("HH:mm ") + to.StandardName.GetInitials(); //}); 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.Current.Current != null); // if (cnt != 1) return cnt.ToString(); // try // { // var mp = ms.MusicPlayers.FirstOrDefault(); // var title = mp.Value?.Current.Current?.Title; // return title ?? "No songs"; // } // catch // { // return "error"; // } // }); // _reps.TryAdd("%queued%", () => ms.MusicPlayers.Sum(kvp => kvp.Value.QueueArray().Songs.Length).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 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()); } } }