diff --git a/NadekoBot/Classes/Extensions.cs b/NadekoBot/Classes/Extensions.cs index 9d0230e7..93527acd 100644 --- a/NadekoBot/Classes/Extensions.cs +++ b/NadekoBot/Classes/Extensions.cs @@ -8,6 +8,7 @@ using System.IO; using System.Linq; using System.Net; using System.Security.Cryptography; +using System.Text; using System.Threading.Tasks; namespace NadekoBot.Extensions @@ -180,6 +181,52 @@ namespace NadekoBot.Extensions } } + public static string GetOnPage(this IEnumerable source, int pageIndex, int itemsPerPage = 5) + { + var items = source.Skip(pageIndex * itemsPerPage).Take(itemsPerPage); + if (!items.Any()) + { + return $"No items on page {pageIndex + 1}."; + } + var sb = new StringBuilder($"---page {pageIndex + 1} --\n"); + var itemsDC = items as IEnumerable>>; + var itemsDS = items as IEnumerable>; + if (itemsDC != null) + { + foreach (var item in itemsDC) + { + sb.Append($"{ Format.Code(item.Key)}\n"); + int i = 1; + var last = item.Value.Last(); + foreach (var value in item.Value) + { + if (last != value) + sb.AppendLine(" `├" + i++ + "─`" + Format.Bold(value)); + else + sb.AppendLine(" `└" + i++ + "─`" + Format.Bold(value)); + } + + } + } + else if (itemsDS != null) + { + foreach (var item in itemsDS) + { + sb.Append($"{ Format.Code(item.Key)}\n"); + sb.AppendLine(" `└─`" + Format.Bold(item.Value)); + } + + } + else + { + foreach (var item in items) + { + sb.Append($"{ Format.Code(item.ToString())} \n"); + } + } + + return sb.ToString(); + } /// /// Gets the program runtime /// diff --git a/NadekoBot/Modules/Conversations/Conversations.cs b/NadekoBot/Modules/Conversations/Conversations.cs index 458108ce..7f7d3cb0 100644 --- a/NadekoBot/Modules/Conversations/Conversations.cs +++ b/NadekoBot/Modules/Conversations/Conversations.cs @@ -1,4 +1,4 @@ -using Discord; +using Discord; using Discord.Commands; using Discord.Modules; using NadekoBot.Classes; @@ -198,11 +198,11 @@ namespace NadekoBot.Modules.Conversations var text = ""; var avatar = await GetAvatar(usr.AvatarUrl); text = usr?.Name ?? e.GetArg("user"); - await e.Channel.SendFile("ripzor_m8.png", - RipUser(text, avatar, string.IsNullOrWhiteSpace(e.GetArg("year")) + var file = RipUser(text, avatar, string.IsNullOrWhiteSpace(e.GetArg("year")) ? null - : e.GetArg("year"))) - .ConfigureAwait(false); + : e.GetArg("year")); + await e.Channel.SendFile("ripzor_m8.png", + file); }); if (!NadekoBot.Config.DontJoinServers) @@ -343,34 +343,18 @@ namespace NadekoBot.Modules.Conversations }); } - public Stream RipName(string name, string year = null) - { - var bm = Resources.rip; - - var offset = name.Length * 5; - - var fontSize = 20; - - if (name.Length > 10) - { - fontSize -= (name.Length - 10) / 2; - } - - //TODO use measure string - var g = Graphics.FromImage(bm); - g.DrawString(name, new Font("Comic Sans MS", fontSize, FontStyle.Bold), Brushes.Black, 100 - offset, 200); - g.DrawString((year ?? "?") + " - " + DateTime.Now.Year, new Font("Consolas", 12, FontStyle.Bold), Brushes.Black, 80, 235); - g.Flush(); - g.Dispose(); - - return bm.ToStream(ImageFormat.Png); - } - + /// + /// Create a RIP image of the given name and avatar, with an optional year + /// + /// + /// + /// + /// public Stream RipUser(string name, Image avatar, string year = null) { var bm = Resources.rip; var offset = name.Length * 2; - + var fontSize = 20; if (name.Length > 10) @@ -379,16 +363,16 @@ namespace NadekoBot.Modules.Conversations } //var avatar = Image.FromStream(await SearchHelper.GetResponseStreamAsync(aviLink)); - + //TODO use measure string var g = Graphics.FromImage(bm); g.DrawString(name, new Font("Comic Sans MS", fontSize, FontStyle.Bold), Brushes.Black, 100 - offset, 220); g.DrawString((year ?? "?") + " - " + DateTime.Now.Year, new Font("Consolas", 12, FontStyle.Bold), Brushes.Black, 80, 240); - - g.DrawImage(avatar, 80,135); + + g.DrawImage(avatar, 80, 135); g.DrawImage((Image)Resources.rose_overlay, 0, 0); - g.Flush(); + g.Flush(); g.Dispose(); return bm.ToStream(ImageFormat.Png); @@ -402,19 +386,19 @@ namespace NadekoBot.Modules.Conversations Bitmap bmp = new Bitmap(100, 100); using (GraphicsPath gp = new GraphicsPath()) { - gp.AddEllipse(0,0, bmp.Width, bmp.Height); + gp.AddEllipse(0, 0, bmp.Width, bmp.Height); using (Graphics gr = Graphics.FromImage(bmp)) { gr.SetClip(gp); gr.DrawImage(Image.FromStream(stream), Point.Empty); - + } } return bmp; - + } - + private static Func SayYes() => async e => await e.Channel.SendMessage("Yes. :)").ConfigureAwait(false); diff --git a/NadekoBot/Modules/Help/HelpModule.cs b/NadekoBot/Modules/Help/HelpModule.cs index 593fbd5f..dfaf1b75 100644 --- a/NadekoBot/Modules/Help/HelpModule.cs +++ b/NadekoBot/Modules/Help/HelpModule.cs @@ -4,6 +4,7 @@ using NadekoBot.Classes.Help.Commands; using NadekoBot.Extensions; using NadekoBot.Modules.Permissions.Classes; using System.Linq; +using System.Text.RegularExpressions; namespace NadekoBot.Modules.Help { @@ -16,6 +17,8 @@ namespace NadekoBot.Modules.Help } public override string Prefix { get; } = NadekoBot.Config.CommandPrefixes.Help; + + public override void Install(ModuleManager manager) { @@ -50,6 +53,37 @@ namespace NadekoBot.Modules.Help await e.Channel.SendMessage("`List of commands:` \n• " + string.Join("\n• ", cmdsArray.Select(c => c.Text))) .ConfigureAwait(false); }); + cgb.CreateCommand(Prefix + "faq") + .Description("Browse the FAQ\n**Usage**: `-faq 1` `-faq Q5`") + .Parameter("index", ParameterType.Unparsed) + .Do(async e => + { + string message = "Something went wrong"; + string indexString = e.GetArg("index")?.Trim().ToLowerInvariant(); + Regex questiona = new Regex(@"q(uestion)?\s*(?\d+)"); + var m = questiona.Match(indexString); + if (m.Success) + { + int index; + if (!int.TryParse(m.Groups["number"].Value, out index) || index < 1|| index > NadekoBot.Config.FAQ.Count) + { + message = "Valid index required"; + await e.Channel.SendMessage(message).ConfigureAwait(false); + return; + } + var question = NadekoBot.Config.FAQ.Skip(--index).FirstOrDefault(); + message = Discord.Format.Bold(question.Key) + "\n\n" + Discord.Format.Italics(question.Value); + + } + else + { + int index; + if (!int.TryParse(indexString, out index) || index < 0) index =1; + message = NadekoBot.Config.FAQ.GetOnPage(--index); + } + await e.Channel.SendMessage(message).ConfigureAwait(false); + }); + }); } } diff --git a/NadekoBot/_Models/JSONModels/Configuration.cs b/NadekoBot/_Models/JSONModels/Configuration.cs index 37312588..d48819b8 100644 --- a/NadekoBot/_Models/JSONModels/Configuration.cs +++ b/NadekoBot/_Models/JSONModels/Configuration.cs @@ -91,6 +91,11 @@ namespace NadekoBot.Classes.JSONModels } } }; + public Dictionary FAQ = new Dictionary() + { + {"Q1: Does Nadeko have music?", "A: The official Nadeko currently does not have music, which means you'll have to host a version yourself (see Q2)" } + }; + public List RotatingStatuses { get; set; } = new List(); public CommandPrefixesModel CommandPrefixes { get; set; } = new CommandPrefixesModel(); public HashSet ServerBlacklist { get; set; } = new HashSet(); diff --git a/NadekoBot/bin/Debug/data/config_example.json b/NadekoBot/bin/Debug/data/config_example.json index 87fb3c50..80c4bdfc 100644 --- a/NadekoBot/bin/Debug/data/config_example.json +++ b/NadekoBot/bin/Debug/data/config_example.json @@ -1,4 +1,7 @@ { + "FAQ": { + "Q1: Does Nadeko have music?": "A: The official Nadeko currently does not have music, which means you'll have to host a version yourself (see Q2)" + }, "DontJoinServers": false, "ForwardMessages": true, "IsRotatingStatus": false,