diff --git a/NadekoBot/Classes/NadekoStats.cs b/NadekoBot/Classes/NadekoStats.cs new file mode 100644 index 00000000..edf913c3 --- /dev/null +++ b/NadekoBot/Classes/NadekoStats.cs @@ -0,0 +1,102 @@ +using Discord; +using Discord.Commands; +using Parse; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Timers; +using NadekoBot.Extensions; +using System.Threading.Tasks; + +namespace NadekoBot +{ + public class NadekoStats + { + public string BotVersion = "0.8-beta3"; + + private static readonly NadekoStats _instance = new NadekoStats(); + public static NadekoStats Instance => _instance; + + private CommandService _service; + private DiscordClient _client; + + private int _commandsRan = 0; + private string _statsCache = ""; + private Stopwatch _statsSW = new Stopwatch(); + + List messages = new List(); + + static NadekoStats() { } + + private NadekoStats() { + _service = NadekoBot.client.Commands(); + _client = NadekoBot.client; + + _statsSW = new Stopwatch(); + _statsSW.Start(); + _service.CommandExecuted += StatsCollector_RanCommand; + + StartCollecting(); + Console.WriteLine("Logging enabled."); + } + + public string GetUptimeString() { + var time = (DateTime.Now - Process.GetCurrentProcess().StartTime); + return time.Days + " days, " + time.Hours + " hours, and " + time.Minutes + " minutes."; + } + + public void LoadStats() { + _statsCache = + "Author: Kwoth" + + $"\nDiscord.Net version: {DiscordConfig.LibVersion}" + + $"\nRuntime: {_client.GetRuntime()}" + + $"\nBot Version: {BotVersion}" + + $"\nLogged in as: {_client.CurrentUser.Name}" + + $"\nBot id: {_client.CurrentUser.Id}" + + $"\nUptime: {GetUptimeString()}" + + $"\nServers: {_client.Servers.Count()}" + + $"\nChannels: {_client.Servers.Sum(s => s.AllChannels.Count())}" + + $"\nUsers: {_client.Servers.SelectMany(x => x.Users.Select(y => y.Id)).Count()} (non-unique)" + + $"\nHeap: {Math.Round(GC.GetTotalMemory(true) / (1024.0 * 1024.0), 2).ToString()}MB" + + $"\nCommands Ran this session: {_commandsRan}"; + } + + public string GetStats() { + if (_statsSW.ElapsedTicks > 5) { + LoadStats(); + _statsSW.Restart(); + } + return _statsCache; + } + + private async Task StartCollecting() { + while (true) { + var obj = new ParseObject("Stats"); + obj["OnlineUsers"] = NadekoBot.client.Servers.Sum(x => x.Users.Count()); + obj["ConnectedServers"] = NadekoBot.client.Servers.Count(); + + obj.SaveAsync(); + await Task.Delay(new TimeSpan(1, 0, 0)); + } + } + //todo - batch save this + private void StatsCollector_RanCommand(object sender, CommandEventArgs e) + { + _commandsRan++; + var obj = new ParseObject("CommandsRan"); + + obj["ServerId"] = e.Server.Id; + obj["ServerName"] = e.Server.Name; + + obj["ChannelId"] = e.Channel.Id; + obj["ChannelName"] = e.Channel.Name; + + obj["UserId"] = e.User.Id; + obj["UserName"] = e.User.Name; + + obj["CommandName"] = e.Command.Text; + obj.SaveAsync(); + } + } +} diff --git a/NadekoBot/Commands/DiceRollCommand.cs b/NadekoBot/Commands/DiceRollCommand.cs index 1a57034d..98c21632 100644 --- a/NadekoBot/Commands/DiceRollCommand.cs +++ b/NadekoBot/Commands/DiceRollCommand.cs @@ -7,59 +7,46 @@ using System.Drawing; using System.Drawing.Imaging; using NadekoBot.Extensions; -namespace NadekoBot -{ - class DiceRollCommand : DiscordCommand - { +namespace NadekoBot { + class DiceRollCommand : DiscordCommand { public DiceRollCommand() : base() { } - public override Func DoFunc() - { + public override Func DoFunc() { Random r = new Random(); return async e => { - if (e.Args[0] == "") - { + if (e.Args[0] == "") { int num1 = r.Next(0, 10); int num2 = r.Next(0, 10); Image[] images; - if (num1 == 0 && num2 == 0 && r.Next(0, 2) == 1) - { + if (num1 == 0 && num2 == 0 && r.Next(0, 2) == 1) { images = new Image[3] { GetDice(1), GetDice(0), GetDice(0) }; - } - else - { + } else { images = new Image[2] { GetDice(num1), GetDice(num2) }; } Bitmap bitmap = images.Merge(); await e.Channel.SendFile("dice.png", bitmap.ToStream(ImageFormat.Png)); return; - } - else - { - try - { + } else { + try { int num = int.Parse(e.Args[0]); if (num < 1) num = 1; - if (num > 30) - { - await e.Send( "You can roll up to 30 dies at a time."); + if (num > 30) { + await e.Send("You can roll up to 30 dies at a time."); num = 30; } List dices = new List(num); List values = new List(num); - for (int i = 0; i < num; i++) - { + for (int i = 0; i < num; i++) { int randomNumber = r.Next(1, 7); int toInsert = dices.Count; - if (randomNumber == 6 || dices.Count==0) + if (randomNumber == 6 || dices.Count == 0) toInsert = 0; - else if (randomNumber!=1) + else if (randomNumber != 1) for (int j = 0; j < dices.Count; j++) { - if (values[j] < randomNumber) - { + if (values[j] < randomNumber) { toInsert = j; break; } @@ -69,12 +56,10 @@ namespace NadekoBot } Bitmap bitmap = dices.Merge(); - await e.Send( values.Count + " Dies rolled. Total: **"+values.Sum()+"** Average: **"+(values.Sum()/(1.0f*values.Count)).ToString("N2")+"**"); + await e.Send(values.Count + " Dies rolled. Total: **" + values.Sum() + "** Average: **" + (values.Sum() / (1.0f * values.Count)).ToString("N2") + "**"); await e.Channel.SendFile("dices.png", bitmap.ToStream(ImageFormat.Png)); - } - catch (Exception) - { - await e.Send( "Please enter a number of dices to roll."); + } catch (Exception) { + await e.Send("Please enter a number of dices to roll."); return; } } @@ -83,12 +68,38 @@ namespace NadekoBot private Image GetDice(int num) => Properties.Resources.ResourceManager.GetObject("_" + num) as Image; - public override void Init(CommandGroupBuilder cgb) - { + public override void Init(CommandGroupBuilder cgb) { cgb.CreateCommand("$roll") .Description("Rolls 2 dice from 0-10. If you supply a number [x] it rolls up to 30 normal dice.\n**Usage**: $roll [x]") .Parameter("num", ParameterType.Optional) .Do(DoFunc()); + cgb.CreateCommand("$nroll") + .Description("Rolls in a given range.\n**Usage**: `$nroll 5` (rolls 0-5) or `$nroll 5-15`") + .Parameter("range", ParameterType.Required) + .Do(NDoFunc()); } + + private Func NDoFunc() => + async e => { + try { + int rolled; + if (e.GetArg("range").Contains("-")) { + var arr = e.GetArg("range").Split('-') + .Take(2) + .Select(x => int.Parse(x)) + .ToArray(); + if (arr[0] > arr[1]) + throw new ArgumentException("First argument should be bigger than the second one."); + rolled = new Random().Next(arr[0],arr[1]+1); + } else { + rolled = new Random().Next(0, int.Parse(e.GetArg("range"))+1); + } + + await e.Send($"{e.User.Mention} rolled **{rolled}**."); + } catch (Exception ex) { + await e.Send($":anger: {ex.Message}"); + } + }; + } } \ No newline at end of file diff --git a/NadekoBot/Commands/RequestsCommand.cs b/NadekoBot/Commands/RequestsCommand.cs new file mode 100644 index 00000000..321260eb --- /dev/null +++ b/NadekoBot/Commands/RequestsCommand.cs @@ -0,0 +1,144 @@ +using System; +using System.Threading.Tasks; +using Discord.Commands; +using Parse; +using NadekoBot.Extensions; + +namespace NadekoBot.Commands { + class RequestsCommand : DiscordCommand { + public void SaveRequest(CommandEventArgs e, string text) { + + var obj = new ParseObject("Requests"); + + obj["ServerId"] = e.Server.Id; + obj["ServerName"] = e.Server.Name; + obj["UserId"] = e.User.Id; + obj["UserName"] = e.User.Name; + obj["Request"] = text; + + obj.SaveAsync(); + } + // todo what if it's too long? + public string GetRequests() { + var task = ParseObject.GetQuery("Requests") + .FindAsync().Result; + + string str = "Here are all current requests for NadekoBot:\n\n"; + int i = 1; + foreach (var reqObj in task) { + str += (i++) + ". by **" + reqObj["UserName"] + "** from **" + reqObj["ServerName"] + "** at " + reqObj.CreatedAt.Value.ToLocalTime() + "\n"; + str += "**" + reqObj["Request"] + "**\n----------\n"; + } + return str + "\n__Type [@NadekoBot clr] to clear all of my messages.__"; + } + + public bool DeleteRequest(int requestNumber) { + var task = ParseObject.GetQuery("Requests") + .FindAsync().Result; + int i = 1; + foreach (var reqObj in task) { + if (i == requestNumber) { + reqObj.DeleteAsync(); + return true; + } + i++; + } + return false; + } + + public class ResolveRequestObject { + public ulong Id; + public ulong ServerId; + public string Text; + } + /// + /// Resolves a request with a number and returns that users id. + /// + /// RequestObject of the request. Null if none + public ResolveRequestObject ResolveRequest(int requestNumber) { + var task = ParseObject.GetQuery("Requests") + .FindAsync().Result; + int i = 1; + foreach (var reqObj in task) { + if (i == requestNumber) { + var txt = reqObj.Get("Request"); + var id = reqObj.Get("UserId"); + var sid = reqObj.Get("ServerId"); + reqObj.DeleteAsync(); + return new ResolveRequestObject { Id = id, Text = txt, ServerId = sid }; + } + i++; + } + return null; + } + + public override Func DoFunc() { + throw new NotImplementedException(); + } + + public override void Init(CommandGroupBuilder cgb) { + + cgb.CreateCommand("req") + .Alias("request") + .Description("Requests a feature for nadeko.\n**Usage**: @NadekoBot req new_feature") + .Parameter("all", ParameterType.Unparsed) + .Do(async e => { + string str = e.Args[0]; + + try { + SaveRequest(e, str); + } catch (Exception) { + await e.Send("Something went wrong."); + return; + } + await e.Send("Thank you for your request."); + }); + + cgb.CreateCommand("lr") + .Description("PMs the user all current nadeko requests.") + .Do(async e => { + string str = GetRequests(); + if (str.Trim().Length > 110) + await e.User.Send(str); + else + await e.User.Send("No requests atm."); + }); + + cgb.CreateCommand("dr") + .Description("Deletes a request. Only owner is able to do this.") + .Parameter("reqNumber", ParameterType.Required) + .Do(async e => { + if (e.User.Id == NadekoBot.OwnerID) { + try { + if (DeleteRequest(int.Parse(e.Args[0]))) { + await e.Send(e.User.Mention + " Request deleted."); + } else { + await e.Send("No request on that number."); + } + } catch { + await e.Send("Error deleting request, probably NaN error."); + } + } else await e.Send("You don't have permission to do that."); + }); + + cgb.CreateCommand("rr") + .Description("Resolves a request. Only owner is able to do this.") + .Parameter("reqNumber", ParameterType.Required) + .Do(async e => { + if (e.User.Id == NadekoBot.OwnerID) { + try { + var sc = ResolveRequest(int.Parse(e.Args[0])); + if (sc != null) { + await e.Send(e.User.Mention + " Request resolved, notice sent."); + await client.GetServer(sc.ServerId).GetUser(sc.Id).Send("**This request of yours has been resolved:**\n" + sc.Text); + } else { + await e.Send("No request on that number."); + } + } catch { + await e.Send("Error resolving request, probably NaN error."); + } + } else await e.Send("You don't have permission to do that."); + }); + } + } +} diff --git a/NadekoBot/Modules/Administration.cs b/NadekoBot/Modules/Administration.cs index 462d1a05..72185b62 100644 --- a/NadekoBot/Modules/Administration.cs +++ b/NadekoBot/Modules/Administration.cs @@ -272,7 +272,7 @@ namespace NadekoBot.Modules { .Description("Shows some basic stats for nadeko") .Do(async e => { var t = Task.Run(() => { - return "```" + NadekoBot.GetStats() + "\n" + Music.GetMusicStats() + "```"; + return "```" + NadekoStats.Instance.GetStats() + "\n" + Music.GetMusicStats() + "```"; }); await e.Send(await t); diff --git a/NadekoBot/Modules/Conversations.cs b/NadekoBot/Modules/Conversations.cs index f8c3a175..444513ba 100644 --- a/NadekoBot/Modules/Conversations.cs +++ b/NadekoBot/Modules/Conversations.cs @@ -13,42 +13,36 @@ using System.Text; using System.Drawing.Imaging; using NadekoBot.Extensions; using NadekoBot.Properties; +using NadekoBot.Commands; -namespace NadekoBot.Modules -{ - class Conversations : DiscordModule - { +namespace NadekoBot.Modules { + class Conversations : DiscordModule { private string firestr = "🔥 ด้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็ด้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็ด้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็็้้้้ 🔥"; - public Conversations() : base() - { + public Conversations() : base() { commands.Add(new CopyCommand()); + commands.Add(new RequestsCommand()); } - public override void Install(ModuleManager manager) - { + public override void Install(ModuleManager manager) { Random rng = new Random(); - manager.CreateCommands("", cgb => - { + manager.CreateCommands("", cgb => { var client = manager.Client; cgb.CreateCommand("\\o\\") .Description("Nadeko replies with /o/") - .Do(async e => - { + .Do(async e => { await e.Send(e.User.Mention + "/o/"); }); cgb.CreateCommand("/o/") .Description("Nadeko replies with \\o\\") - .Do(async e => - { - await e.Send( e.User.Mention + "\\o\\"); + .Do(async e => { + await e.Send(e.User.Mention + "\\o\\"); }); }); - manager.CreateCommands(NadekoBot.botMention, cgb => - { + manager.CreateCommands(NadekoBot.botMention, cgb => { var client = manager.Client; commands.ForEach(cmd => cmd.Init(cgb)); @@ -63,17 +57,14 @@ namespace NadekoBot.Modules cgb.CreateCommand("die") .Description("Works only for the owner. Shuts the bot down.") - .Do(async e => - { - if (e.User.Id == NadekoBot.OwnerID) - { + .Do(async e => { + if (e.User.Id == NadekoBot.OwnerID) { Timer t = new Timer(); t.Interval = 2000; t.Elapsed += (s, ev) => { Environment.Exit(0); }; t.Start(); await e.Send(e.User.Mention + ", Yes, my love."); - } - else + } else await e.Send(e.User.Mention + ", No."); }); @@ -137,21 +128,14 @@ namespace NadekoBot.Modules cgb.CreateCommand("how are you") .Description("Replies positive only if bot owner is online.") - .Do(async e => - { - if (e.User.Id == NadekoBot.OwnerID) - { + .Do(async e => { + if (e.User.Id == NadekoBot.OwnerID) { await e.Send(e.User.Mention + " I am great as long as you are here."); - } - else - { + } else { var kw = e.Server.GetUser(NadekoBot.OwnerID); - if (kw != null && kw.Status == UserStatus.Online) - { + if (kw != null && kw.Status == UserStatus.Online) { await e.Send(e.User.Mention + " I am great as long as " + kw.Mention + " is with me."); - } - else - { + } else { await e.Send(e.User.Mention + " I am sad. My Master is not with me."); } } @@ -160,8 +144,7 @@ namespace NadekoBot.Modules cgb.CreateCommand("insult") .Parameter("mention", ParameterType.Required) .Description("Only works for owner. Insults @X person.\n**Usage**: @NadekoBot insult @X.") - .Do(async e => - { + .Do(async e => { List insults = new List { " you are a poop.", " you jerk.", " i will eat you when i get my powers back." }; Random r = new Random(); var u = e.Channel.FindUsers(e.GetArg("mention")).FirstOrDefault(); @@ -180,8 +163,7 @@ namespace NadekoBot.Modules cgb.CreateCommand("praise") .Description("Only works for owner. Praises @X person.\n**Usage**: @NadekoBot praise @X.") .Parameter("mention", ParameterType.Required) - .Do(async e => - { + .Do(async e => { List praises = new List { " You are cool.", " You are nice!", " You did a good job.", @@ -192,8 +174,7 @@ namespace NadekoBot.Modules Random r = new Random(); var u = e.Channel.FindUsers(e.GetArg("mention")).FirstOrDefault(); - if (u == null) - { + if (u == null) { await e.Send("Invalid user specified."); return; } @@ -207,8 +188,7 @@ namespace NadekoBot.Modules cgb.CreateCommand("are you real") .Description("Useless.") - .Do(async e => - { + .Do(async e => { await e.Send(e.User.Mention + " I will be soon."); }); @@ -219,15 +199,13 @@ namespace NadekoBot.Modules cgb.CreateCommand("draw") .Description("Nadeko instructs you to type $draw. Gambling functions start with $") - .Do(async e => - { + .Do(async e => { await e.Send("Sorry, I don't gamble, type $draw for that function."); }); cgb.CreateCommand("fire") .Description("Shows a unicode fire message. Optional parameter [x] tells her how many times to repeat the fire.\n**Usage**: @NadekoBot fire [x]") .Parameter("times", ParameterType.Optional) - .Do(async e => - { + .Do(async e => { int count = 0; if (e.Args?.Length > 0) int.TryParse(e.Args[0], out count); @@ -237,8 +215,7 @@ namespace NadekoBot.Modules else if (count > 12) count = 12; string str = ""; - for (int i = 0; i < count; i++) - { + for (int i = 0; i < count; i++) { str += firestr; } await e.Send(str); @@ -247,15 +224,12 @@ namespace NadekoBot.Modules cgb.CreateCommand("rip") .Description("Shows a grave image.Optional parameter [@X] instructs her to put X's name on the grave.\n**Usage**: @NadekoBot rip [@X]") .Parameter("user", ParameterType.Unparsed) - .Do(async e => - { + .Do(async e => { var usr = e.Channel.FindUsers(e.GetArg("user")).FirstOrDefault(); string text = ""; - if (usr == null) - { + if (usr == null) { text = e.GetArg("user"); - } - else { + } else { text = usr.Name; } await e.Channel.SendFile("ripzor_m8.png", RipName(text)); @@ -264,15 +238,11 @@ namespace NadekoBot.Modules cgb.CreateCommand("j") .Description("Joins a server using a code.") .Parameter("id", ParameterType.Required) - .Do(async e => - { - try - { + .Do(async e => { + try { await (await client.GetInvite(e.Args[0])).Accept(); await e.Send("I got in!"); - } - catch (Exception) - { + } catch (Exception) { await e.Send("Invalid code."); } }); @@ -280,39 +250,31 @@ namespace NadekoBot.Modules cgb.CreateCommand("save") .Description("Saves something for the owner in a file.") .Parameter("all", ParameterType.Unparsed) - .Do(async e => - { - if (e.User.Id == NadekoBot.OwnerID) - { + .Do(async e => { + if (e.User.Id == NadekoBot.OwnerID) { string m = ""; - try - { + try { FileStream f = File.OpenWrite("saves.txt"); m = e.Args[0]; byte[] b = Encoding.ASCII.GetBytes(m + "\n"); f.Seek(f.Length, SeekOrigin.Begin); f.Write(b, 0, b.Length); f.Close(); - } - catch (Exception) - { + } catch (Exception) { await e.Send("Error saving. Sorry :("); } if (m.Length > 0) await e.Send("I saved this for you: " + Environment.NewLine + "```" + m + "```"); else await e.Send("No point in saving empty message..."); - } - else await e.Send("Not for you, only my Master <3"); + } else await e.Send("Not for you, only my Master <3"); }); cgb.CreateCommand("ls") .Description("Shows all saved items.") - .Do(async e => - { + .Do(async e => { FileStream f = File.OpenRead("saves.txt"); - if (f.Length == 0) - { + if (f.Length == 0) { await e.Send("Saves are empty."); return; } @@ -351,8 +313,7 @@ namespace NadekoBot.Modules }); cgb.CreateCommand("cs") .Description("Deletes all saves") - .Do(async e => - { + .Do(async e => { File.Delete("saves.txt"); await e.Send("Cleared all saves."); }); @@ -360,159 +321,51 @@ namespace NadekoBot.Modules cgb.CreateCommand("bb") .Description("Says bye to someone. **Usage**: @NadekoBot bb @X") .Parameter("ppl", ParameterType.Unparsed) - .Do(async e => - { + .Do(async e => { string str = "Bye"; - foreach (var u in e.Message.MentionedUsers) - { + foreach (var u in e.Message.MentionedUsers) { str += " " + u.Mention; } await e.Send(str); }); - cgb.CreateCommand("req") - .Alias("request") - .Description("Requests a feature for nadeko.\n**Usage**: @NadekoBot req new_feature") - .Parameter("all", ParameterType.Unparsed) - .Do(async e => - { - string str = e.Args[0]; - - try - { - StatsCollector.SaveRequest(e, str); - } - catch (Exception) - { - await e.Send("Something went wrong."); - return; - } - await e.Send("Thank you for your request."); - }); - - cgb.CreateCommand("lr") - .Description("PMs the user all current nadeko requests.") - .Do(async e => - { - string str = StatsCollector.GetRequests(); - if (str.Trim().Length > 110) - await e.User.Send(str); - else - await e.User.Send("No requests atm."); - }); - - cgb.CreateCommand("dr") - .Description("Deletes a request. Only owner is able to do this.") - .Parameter("reqNumber", ParameterType.Required) - .Do(async e => - { - if (e.User.Id == NadekoBot.OwnerID) - { - try - { - if (StatsCollector.DeleteRequest(int.Parse(e.Args[0]))) - { - await e.Send(e.User.Mention + " Request deleted."); - } - else - { - await e.Send("No request on that number."); - } - } - catch - { - await e.Send("Error deleting request, probably NaN error."); - } - } - else await e.Send("You don't have permission to do that."); - }); - - cgb.CreateCommand("rr") - .Description("Resolves a request. Only owner is able to do this.") - .Parameter("reqNumber", ParameterType.Required) - .Do(async e => - { - if (e.User.Id == NadekoBot.OwnerID) - { - try - { - var sc = StatsCollector.ResolveRequest(int.Parse(e.Args[0])); - if (sc != null) - { - await e.Send(e.User.Mention + " Request resolved, notice sent."); - await client.GetServer(sc.ServerId).GetUser(sc.Id).Send("**This request of yours has been resolved:**\n" + sc.Text); - } - else - { - await e.Send("No request on that number."); - } - } - catch - { - await e.Send("Error resolving request, probably NaN error."); - } - } - else await e.Send("You don't have permission to do that."); - }); - cgb.CreateCommand("call") .Description("Useless. Writes calling @X to chat.\n**Usage**: @NadekoBot call @X ") .Parameter("who", ParameterType.Required) - .Do(async e => - { + .Do(async e => { await e.Send("Calling " + e.Args[0] + "..."); }); cgb.CreateCommand("hide") .Description("Hides nadeko in plain sight!11!!") - .Do(async e => - { - try - { - using (Stream ms = Resources.hidden.ToStream(ImageFormat.Png)) - { - await client.CurrentUser.Edit(NadekoBot.password, avatar: ms); - } - await e.Send("*hides*"); - } - catch (Exception ex) - { - StatsCollector.DEBUG_LOG(ex.ToString()); + .Do(async e => { + using (Stream ms = Resources.hidden.ToStream(ImageFormat.Png)) { + await client.CurrentUser.Edit(NadekoBot.password, avatar: ms); } + await e.Send("*hides*"); }); cgb.CreateCommand("unhide") .Description("Unhides nadeko in plain sight!1!!1") - .Do(async e => - { - try - { - using (Stream ms = Resources.nadeko.ToStream()) { - await client.CurrentUser.Edit(NadekoBot.password, avatar: ms,avatarType:ImageType.Jpeg); - } - await e.Send("*unhides*"); - } - catch (Exception ex) - { - StatsCollector.DEBUG_LOG(ex.ToString()); + .Do(async e => { + using (Stream ms = Resources.nadeko.ToStream()) { + await client.CurrentUser.Edit(NadekoBot.password, avatar: ms, avatarType: ImageType.Jpeg); } + await e.Send("*unhides*"); }); cgb.CreateCommand("dump") .Description("Dumps all of the invites it can to dump.txt.** Owner Only.**") - .Do(async e => - { + .Do(async e => { if (NadekoBot.OwnerID != e.User.Id) return; int i = 0; int j = 0; string invites = ""; foreach (var s in client.Servers) { - try - { + try { var invite = await s.CreateInvite(0); - invites+=invite.Url+"\n"; + invites += invite.Url + "\n"; i++; - } - catch (Exception) { + } catch (Exception) { j++; continue; } @@ -521,13 +374,12 @@ namespace NadekoBot.Modules await e.Send($"Got invites for {i} servers and failed to get invites for {j} servers"); }); - + cgb.CreateCommand("av").Alias("avatar") .Parameter("mention", ParameterType.Required) .Description("Shows a mentioned person's avatar. **Usage**: ~av @X") - .Do(async e => - { + .Do(async e => { var usr = e.Channel.FindUsers(e.GetArg("mention")).FirstOrDefault(); if (usr == null) { await e.Send("Invalid user specified."); @@ -553,16 +405,14 @@ namespace NadekoBot.Modules }); } - public Stream RipName(string name) - { + public Stream RipName(string name) { Bitmap bm = Resources.rip; int offset = name.Length * 5; int fontSize = 20; - if (name.Length > 10) - { + if (name.Length > 10) { fontSize -= (name.Length - 10) / 2; } @@ -576,7 +426,7 @@ namespace NadekoBot.Modules return bm.ToStream(ImageFormat.Png); } - private Func SayYes() + private Func SayYes() => async e => await e.Send("Yes. :)"); } } diff --git a/NadekoBot/NadekoBot.cs b/NadekoBot/NadekoBot.cs index 400bf76c..abe399f4 100644 --- a/NadekoBot/NadekoBot.cs +++ b/NadekoBot/NadekoBot.cs @@ -15,7 +15,6 @@ using System.Diagnostics; namespace NadekoBot { class NadekoBot { public static DiscordClient client; - public static StatsCollector stats_collector; public static string botMention; public static string GoogleAPIKey = null; public static ulong OwnerID; @@ -23,8 +22,6 @@ namespace NadekoBot { public static string password; public static string TrelloAppKey; public static bool ForwardMessages = false; - public static string BotVersion = "0.8-beta2"; - public static int commandsRan = 0; static void Main() { //load credentials from credentials.json @@ -75,7 +72,7 @@ namespace NadekoBot { ParseClient.Initialize(c.ParseID, c.ParseKey); //monitor commands for logging - stats_collector = new StatsCollector(commandService); + } else { Console.WriteLine("Parse key and/or ID not found. Logging disabled."); } @@ -86,9 +83,6 @@ namespace NadekoBot { //add command service var commands = client.Services.Add(commandService); - //count commands ran - client.Commands().CommandExecuted += (s, e) => commandsRan++; - //create module service var modules = client.Services.Add(new ModuleService()); @@ -110,15 +104,11 @@ namespace NadekoBot { if (loadTrello) modules.Add(new Trello(), "Trello", ModuleFilter.None); - //start the timer for stats - _statsSW.Start(); //run the bot client.ExecuteAndWait(async () => { await client.Connect(c.Username, c.Password); - - LoadStats(); Console.WriteLine("-----------------"); - Console.WriteLine(GetStats()); + Console.WriteLine(NadekoStats.Instance.GetStats()); Console.WriteLine("-----------------"); foreach (var serv in client.Servers) { @@ -129,36 +119,7 @@ namespace NadekoBot { }); Console.WriteLine("Exiting..."); Console.ReadKey(); - } - private static string _statsCache = ""; - private static Stopwatch _statsSW = new Stopwatch(); - public static string GetStats() { - if (_statsSW.ElapsedTicks > 5) { - LoadStats(); - _statsSW.Restart(); - } - return _statsCache; - } - private static void LoadStats() { - _statsCache = - "Author: Kwoth" + - $"\nDiscord.Net version: {DiscordConfig.LibVersion}" + - $"\nRuntime: {client.GetRuntime()}" + - $"\nBot Version: {BotVersion}" + - $"\nLogged in as: {client.CurrentUser.Name}" + - $"\nBot id: {client.CurrentUser.Id}" + - $"\nUptime: {GetUptimeString()}" + - $"\nServers: {client.Servers.Count()}" + - $"\nChannels: {client.Servers.Sum(s => s.AllChannels.Count())}" + - $"\nUsers: {client.Servers.SelectMany(x => x.Users.Select(y => y.Id)).Count()} (non-unique)" + - $"\nHeap: {Math.Round(GC.GetTotalMemory(true) / (1024.0 * 1024.0), 2).ToString()}MB" + - $"\nCommands Ran this session: {commandsRan}"; - } - - public static string GetUptimeString() { - var time = (DateTime.Now - Process.GetCurrentProcess().StartTime); - return time.Days + " days, " + time.Hours + " hours, and " + time.Minutes + " minutes."; - } + } static bool repliedRecently = false; private static async void Client_MessageReceived(object sender, MessageEventArgs e) { diff --git a/NadekoBot/NadekoBot.csproj b/NadekoBot/NadekoBot.csproj index 2d6ce9f5..6d07d706 100644 --- a/NadekoBot/NadekoBot.csproj +++ b/NadekoBot/NadekoBot.csproj @@ -147,6 +147,7 @@ + @@ -174,7 +175,7 @@ True Resources.resx - + diff --git a/NadekoBot/StatsCollector.cs b/NadekoBot/StatsCollector.cs deleted file mode 100644 index 466eb74a..00000000 --- a/NadekoBot/StatsCollector.cs +++ /dev/null @@ -1,195 +0,0 @@ -using Discord; -using Discord.Commands; -using Parse; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Timers; -using NadekoBot.Extensions; - -namespace NadekoBot -{ - public class StatsCollector - { - - private CommandService _service; - - string lastMention = ""; - string lastMessage = "No messages."; - int commandsRan = 0; - string dataLastSent = "Data last sent at: NEVER"; - - List messages = new List(); - - public StatsCollector(CommandService service) - { - this._service = service; - - _service.CommandExecuted += StatsCollector_RanCommand; - //NadekoBot.client.MessageReceived += Client_MessageReceived; - - StartCollecting(); - Console.WriteLine("Logging enabled."); - } - - private void FillConsole() { - Console.Clear(); - - var time = (DateTime.Now - Process.GetCurrentProcess().StartTime); - string str = "Online for " + time.Days + "d, " + time.Hours + "h, " + time.Minutes + "m, "+time.Seconds+"s."; - - Console.SetCursorPosition(0, 0); - Console.Write(str); - - Console.SetCursorPosition(0, 1); - Console.Write(dataLastSent); - - Console.SetCursorPosition(0, 2); - Console.Write("Commands ran since start: " +commandsRan); - - Console.SetCursorPosition(0, 3); - Console.Write(lastMention); - - Console.SetCursorPosition(0, 4); - Console.WriteLine(lastMessage); - } - - private void Client_MessageReceived(object sender, MessageEventArgs e) - { - - lastMessage = "[" + e.User.Name + "] on [" + e.Server.Name + "] server, channel: [" + e.Channel.Name + "] \n" + "Body: " + e.Message.Text + " "; - - if (e.Message.MentionedUsers.Where(u => u.Id == NadekoBot.OwnerID).Count() > 0) - { - lastMention = "You were last mentioned in '" + e.Server.Name + "' server, channel '" + e.Channel.Name + "', by " + e.User.Name; - } - - } - - private async void TryJoin(MessageEventArgs e, string code) { - try - { - await (await NadekoBot.client.GetInvite(code)).Accept(); - await e.Send(e.User.Mention + " I joined it, thanks :)"); - DEBUG_LOG("Successfuly joined server with code " + code); - DEBUG_LOG("Here is a link for you: discord.gg/" + code); - } - catch (Exception ex) { - DEBUG_LOG("Failed to join " + code); - DEBUG_LOG("Reason: " + ex.ToString()); - } - } - - public static void DEBUG_LOG(string text) { -#pragma warning disable CS4014 - //NadekoBot.client.GetChannel(119365591852122112).Send(text); - Console.WriteLine(text); -#pragma warning restore CS4014 - } - - private void StartCollecting() { - Timer t = new Timer(); - t.Interval = 3600000; - t.Enabled = true; - t.Elapsed += (s, e) => - { - var obj = new ParseObject("Stats"); - dataLastSent = "Data last sent at: "+DateTime.Now.Hour+":"+DateTime.Now.Minute; - obj["OnlineUsers"] = NadekoBot.client.Servers.Sum(x=>x.Users.Count()); - obj["ConnectedServers"] = NadekoBot.client.Servers.Count(); - - obj.SaveAsync(); - }; - } - - public static void SaveRequest(CommandEventArgs e, string text) { - - var obj = new ParseObject("Requests"); - - obj["ServerId"] = e.Server.Id; - obj["ServerName"] = e.Server.Name; - obj["UserId"] = e.User.Id; - obj["UserName"] = e.User.Name; - obj["Request"] = text; - - obj.SaveAsync(); - } - - public static string GetRequests() { - var task = ParseObject.GetQuery("Requests") - .FindAsync().Result; - - string str = "Here are all current requests for NadekoBot:\n\n"; - int i = 1; - foreach (var reqObj in task) - { - - str += (i++) + ". by **" + reqObj["UserName"] +"** from **" + reqObj["ServerName"] + "** at "+ reqObj.CreatedAt.Value.ToLocalTime() + "\n"; - str+= "**"+reqObj["Request"]+"**\n----------\n"; - } - return str+"\n__Type [@NadekoBot clr] to clear all of my messages.__"; - } - - public static bool DeleteRequest(int requestNumber) { - var task = ParseObject.GetQuery("Requests") - .FindAsync().Result; - int i = 1; - foreach (var reqObj in task) - { - if (i == requestNumber) - { - reqObj.DeleteAsync(); - return true; - } - i++; - } - return false; - } - /// - /// Resolves a request with a number and returns that users id. - /// - /// RequestObject of the request. Null if none - public static ResolveRequestObject ResolveRequest(int requestNumber) { - var task = ParseObject.GetQuery("Requests") - .FindAsync().Result; - int i = 1; - foreach (var reqObj in task) - { - if (i == requestNumber) { - var txt = reqObj.Get("Request"); - var id = reqObj.Get("UserId"); - var sid = reqObj.Get("ServerId"); - reqObj.DeleteAsync(); - return new ResolveRequestObject { Id = id, Text = txt, ServerId=sid }; - } - i++; - } - return null; - } - - public class ResolveRequestObject { - public ulong Id; - public ulong ServerId; - public string Text; - } - - private void StatsCollector_RanCommand(object sender, CommandEventArgs e) - { - commandsRan++; - var obj = new ParseObject("CommandsRan"); - - obj["ServerId"] = e.Server.Id; - obj["ServerName"] = e.Server.Name; - - obj["ChannelId"] = e.Channel.Id; - obj["ChannelName"] = e.Channel.Name; - - obj["UserId"] = e.User.Id; - obj["UserName"] = e.User.Name; - - obj["CommandName"] = e.Command.Text; - obj.SaveAsync(); - } - } -}