From 476ed37d2009c5fcf26fde40d3068fae23e85166 Mon Sep 17 00:00:00 2001 From: dboerlage Date: Thu, 27 Apr 2017 12:08:24 +0200 Subject: [PATCH 001/553] Adding Unit Tests --- .gitignore | 4 ++- .vscode/launch.json | 52 ++++++++++++++++++++++++++++++++++++ Geekbot.net.sln | 6 +++++ Geekbot.net.userprefs | 28 +++++++++++++++++++ Geekbot.net/Lib/LevelCalc.cs | 2 +- Geekbot.net/Modules/Cat.cs | 34 ++++++++++++++++++++--- Geekbot.net/Program.cs | 2 +- Tests/Tests.csproj | 25 +++++++++++++++++ Tests/UnitTest1.cs | 52 ++++++++++++++++++++++++++++++++++++ 9 files changed, 198 insertions(+), 7 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 Geekbot.net.userprefs create mode 100755 Tests/Tests.csproj create mode 100755 Tests/UnitTest1.cs diff --git a/.gitignore b/.gitignore index 57f9728..55ab035 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ Geekbot.net/bin Geekbot.net/obj +Tests/bin +Tests/obj Backup/ .vs/ UpgradeLog.htm -.idea \ No newline at end of file +.idea diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..c975ed1 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,52 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": ".NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceRoot}/bin/Debug//", + "args": [], + "cwd": "${workspaceRoot}", + "stopAtEntry": false, + "console": "internalConsole" + }, + { + "name": ".NET Core Launch (web)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceRoot}/bin/Debug//", + "args": [], + "cwd": "${workspaceRoot}", + "stopAtEntry": false, + "launchBrowser": { + "enabled": true, + "args": "${auto-detect-url}", + "windows": { + "command": "cmd.exe", + "args": "/C start ${auto-detect-url}" + }, + "osx": { + "command": "open" + }, + "linux": { + "command": "xdg-open" + } + }, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceRoot}/Views" + } + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach", + "processId": "${command:pickProcess}" + } + ] +} \ No newline at end of file diff --git a/Geekbot.net.sln b/Geekbot.net.sln index 990eb42..fe98069 100644 --- a/Geekbot.net.sln +++ b/Geekbot.net.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 12.0.0.0 MinimumVisualStudioVersion = 10.0.0.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Geekbot.net", "Geekbot.net/Geekbot.net.csproj", "{FDCB3D92-E7B5-47BB-A9B5-CFAEFA57CDB4}" EndProject +Project("{64BFF91A-5FCE-45C2-B281-5EA31729FFBF}") = "Tests", "Tests\Tests.csproj", "{CE7B71E3-F73A-40D1-901C-C20BEFB15851}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +17,10 @@ Global {FDCB3D92-E7B5-47BB-A9B5-CFAEFA57CDB4}.Debug|Any CPU.Build.0 = Debug|Any CPU {FDCB3D92-E7B5-47BB-A9B5-CFAEFA57CDB4}.Release|Any CPU.ActiveCfg = Release|Any CPU {FDCB3D92-E7B5-47BB-A9B5-CFAEFA57CDB4}.Release|Any CPU.Build.0 = Release|Any CPU + {CE7B71E3-F73A-40D1-901C-C20BEFB15851}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CE7B71E3-F73A-40D1-901C-C20BEFB15851}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CE7B71E3-F73A-40D1-901C-C20BEFB15851}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CE7B71E3-F73A-40D1-901C-C20BEFB15851}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Geekbot.net.userprefs b/Geekbot.net.userprefs new file mode 100644 index 0000000..dca434f --- /dev/null +++ b/Geekbot.net.userprefs @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Geekbot.net/Lib/LevelCalc.cs b/Geekbot.net/Lib/LevelCalc.cs index 1298319..631a5e2 100644 --- a/Geekbot.net/Lib/LevelCalc.cs +++ b/Geekbot.net/Lib/LevelCalc.cs @@ -4,7 +4,7 @@ using System.Text; namespace Geekbot.net.Lib { - class LevelCalc + public class LevelCalc { private static int GetExperienceAtLevel(int level) { diff --git a/Geekbot.net/Modules/Cat.cs b/Geekbot.net/Modules/Cat.cs index 5ca9017..410b53a 100644 --- a/Geekbot.net/Modules/Cat.cs +++ b/Geekbot.net/Modules/Cat.cs @@ -5,21 +5,47 @@ using RestSharp; namespace Geekbot.net.Modules { - public class Cat : ModuleBase + public class Cat : ModuleBase, AsyncReplier { private readonly ICatClient catClient; + private readonly AsyncReplier _asyncReplier; + private readonly Func _requestFunc; + + public class CatResponse + { + public string file { get; set; } + } + public Cat(ICatClient catClient) { this.catClient = catClient; + _asyncReplier = this; + _requestFunc = (() => new RestRequest("meow.php", Method.GET)); } +// +// public Cat(ICatClient catClient, Func requestFunc, AsyncReplier asyncReplier) +// { +// this.catClient = catClient; +// _asyncReplier = asyncReplier ?? this; +// _requestFunc = requestFunc ?? (() => new RestRequest("meow.php", Method.GET)); +// } [Command("cat", RunMode = RunMode.Async), Summary("Return a random image of a cat.")] public async Task Say() { - var request = new RestRequest("meow.php", Method.GET); + var request = _requestFunc(); + var response = catClient.Client.Execute(request); + await _asyncReplier.ReplyAsyncInt(response.Data.file); + } - dynamic response = catClient.Client.Execute(request); - await ReplyAsync(response.Data["file"]); + public async Task ReplyAsyncInt(dynamic data) + { + await ReplyAsync(data); } } + + public interface AsyncReplier + { + Task ReplyAsyncInt(dynamic data); + } } \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 16030ac..ba50465 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -130,7 +130,7 @@ namespace Geekbot.net } if (!(message.HasCharPrefix('!', ref argPos) || message.HasMentionPrefix(client.CurrentUser, ref argPos))) return; var context = new CommandContext(client, message); - Task.Run(() => commands.ExecuteAsync(context, argPos, map)); + Task.Run(async () => await commands.ExecuteAsync(context, argPos, map)); } public async Task HandleMessageReceived(SocketMessage messsageParam) diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj new file mode 100755 index 0000000..bc2c1ce --- /dev/null +++ b/Tests/Tests.csproj @@ -0,0 +1,25 @@ + + + netcoreapp1.1 + + + + 4.19.2 + + + + 4.7.8 + + + 105.2.4-rc4-24214-01 + + + + + + + {FDCB3D92-E7B5-47BB-A9B5-CFAEFA57CDB4} + Geekbot.net + + + \ No newline at end of file diff --git a/Tests/UnitTest1.cs b/Tests/UnitTest1.cs new file mode 100755 index 0000000..3467b45 --- /dev/null +++ b/Tests/UnitTest1.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using FluentAssertions; +using Geekbot.net.Lib; +using Geekbot.net.Modules; +using Moq; +using RestSharp; +using Xunit; + +namespace Tests +{ + public class UnitTest1 + { + [Fact] + public async Task TestCat() + { + // setup + var catClient = new Mock(MockBehavior.Strict); + var client = new Mock(MockBehavior.Strict); + catClient.Setup(cc => cc.Client).Returns(client.Object); + var response = new Mock>(MockBehavior.Strict); + var resultData = new Cat.CatResponse {file = "unit-test"}; + response.SetupGet(r => r.Data).Returns(resultData); + Console.WriteLine(resultData.file); + var request = new Mock(MockBehavior.Strict); + Func requestFunc = () => request.Object; + client.Setup(c => c.Execute(request.Object)).Returns(response.Object); + Mock asyncReplier = new Mock(MockBehavior.Strict); + asyncReplier.Setup(ar => ar.ReplyAsyncInt(resultData.file)).Returns(Task.FromResult(true)).Verifiable(); + + // execute + //var cat = new Cat(catClient.Object, requestFunc, asyncReplier.Object); + //await cat.Say(); + + // validate + //asyncReplier.Verify(); + } + + [Theory] + [InlineData(1, 0)] + [InlineData(33, 4561)] + [InlineData(79, 449702)] + [InlineData(79, 449702 + 1)] + public void TestLevel(int expectedIndex, int experience) + { + var index = LevelCalc.GetLevelAtExperience(experience); + index.Should().Be(expectedIndex); + } + + } +} \ No newline at end of file From 53550fb12b2869a3d3b32e4300e5debc8273d929 Mon Sep 17 00:00:00 2001 From: dboerlage Date: Thu, 27 Apr 2017 19:50:03 +0200 Subject: [PATCH 002/553] Fixing multiple reply bug --- .gitignore | 4 +++- Geekbot.net/Program.cs | 38 +++++++++++++++++++++++++------------- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 57f9728..55ab035 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ Geekbot.net/bin Geekbot.net/obj +Tests/bin +Tests/obj Backup/ .vs/ UpgradeLog.htm -.idea \ No newline at end of file +.idea diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 16030ac..036f583 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -70,7 +70,21 @@ namespace Geekbot.net { await client.LoginAsync(TokenType.Bot, token); await client.StartAsync(); - client.Connected += FinishStartup; + var isConneted = await isConnected(); + if (isConneted) + { + await client.SetGameAsync("Ping Pong"); + Console.WriteLine($"Now Connected to {client.Guilds.Count} Servers"); + + Console.WriteLine("Registering Stuff"); + + client.MessageReceived += HandleCommand; + client.MessageReceived += HandleMessageReceived; + client.UserJoined += HandleUserJoined; + await commands.AddModulesAsync(Assembly.GetEntryAssembly()); + + Console.WriteLine("Done and ready for use...\n"); + } } catch (AggregateException) { @@ -79,6 +93,15 @@ namespace Geekbot.net } } + public async Task isConnected() + { + while (!client.ConnectionState.Equals(ConnectionState.Connected)) + { + await Task.Delay(25); + } + return true; + } + public async Task Reconnect(Exception exception) { Console.WriteLine("========================================="); @@ -93,18 +116,7 @@ namespace Geekbot.net public async Task FinishStartup() { - await client.SetGameAsync("Ping Pong"); - Console.WriteLine($"Now Connected to {client.Guilds.Count} Servers"); - Console.WriteLine("Registering Stuff"); - - client.MessageReceived += HandleCommand; - client.MessageReceived += HandleMessageReceived; - client.UserJoined += HandleUserJoined; -// client.Disconnected += Reconnect; - await commands.AddModulesAsync(Assembly.GetEntryAssembly()); - - Console.WriteLine("Done and ready for use...\n"); } public async Task HandleCommand(SocketMessage messageParam) @@ -130,7 +142,7 @@ namespace Geekbot.net } if (!(message.HasCharPrefix('!', ref argPos) || message.HasMentionPrefix(client.CurrentUser, ref argPos))) return; var context = new CommandContext(client, message); - Task.Run(() => commands.ExecuteAsync(context, argPos, map)); + Task.Run(async () => await commands.ExecuteAsync(context, argPos, map)); } public async Task HandleMessageReceived(SocketMessage messsageParam) From c670bf7ae39d76822b81532cf0069c69d82fa6ff Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sat, 6 May 2017 01:48:58 +0200 Subject: [PATCH 003/553] bot now ignores other bots --- Geekbot.net/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 036f583..d66c62b 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -123,7 +123,7 @@ namespace Geekbot.net { var message = messageParam as SocketUserMessage; if (message == null) return; - if (message.Author.Username.Equals(client.CurrentUser.Username)) return; + if (message.Author.IsBot) return; int argPos = 0; if (message.ToString().ToLower().StartsWith("ping")) { From 8703a645567efa02979a263537550704353617ce Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sat, 6 May 2017 20:35:31 +0200 Subject: [PATCH 004/553] dog command and namespace fixes --- Geekbot.net/Lib/IClients/CatClient.cs | 2 +- Geekbot.net/Lib/IClients/DogClient.cs | 19 +++++++++++++++++++ Geekbot.net/Lib/IClients/RedisClient.cs | 2 +- Geekbot.net/Lib/StatsRecorder.cs | 1 + Geekbot.net/Modules/AdminCmd.cs | 2 +- Geekbot.net/Modules/Cat.cs | 4 ++-- Geekbot.net/Modules/Counters.cs | 2 +- Geekbot.net/Modules/Dog.cs | 25 +++++++++++++++++++++++++ Geekbot.net/Modules/GuildInfo.cs | 1 + Geekbot.net/Modules/Info.cs | 7 ++----- Geekbot.net/Modules/UserInfo.cs | 1 + Geekbot.net/Modules/Youtube.cs | 2 +- Geekbot.net/Program.cs | 1 + 13 files changed, 57 insertions(+), 12 deletions(-) create mode 100644 Geekbot.net/Lib/IClients/DogClient.cs create mode 100644 Geekbot.net/Modules/Dog.cs diff --git a/Geekbot.net/Lib/IClients/CatClient.cs b/Geekbot.net/Lib/IClients/CatClient.cs index 2e606ed..7a7e8c6 100644 --- a/Geekbot.net/Lib/IClients/CatClient.cs +++ b/Geekbot.net/Lib/IClients/CatClient.cs @@ -1,6 +1,6 @@ using RestSharp; -namespace Geekbot.net.Modules +namespace Geekbot.net.Lib.IClients { public interface ICatClient { diff --git a/Geekbot.net/Lib/IClients/DogClient.cs b/Geekbot.net/Lib/IClients/DogClient.cs new file mode 100644 index 0000000..20feed1 --- /dev/null +++ b/Geekbot.net/Lib/IClients/DogClient.cs @@ -0,0 +1,19 @@ +using RestSharp; + +namespace Geekbot.net.Lib.IClients +{ + public interface IDogClient + { + IRestClient Client { get; set; } + } + + public class DogClient : IDogClient + { + public DogClient() + { + Client = new RestClient("http://random.dog"); + } + + public IRestClient Client { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/IClients/RedisClient.cs b/Geekbot.net/Lib/IClients/RedisClient.cs index b05e5ad..7fc890f 100644 --- a/Geekbot.net/Lib/IClients/RedisClient.cs +++ b/Geekbot.net/Lib/IClients/RedisClient.cs @@ -1,7 +1,7 @@ using System; using StackExchange.Redis; -namespace Geekbot.net.Lib +namespace Geekbot.net.Lib.IClients { public interface IRedisClient { diff --git a/Geekbot.net/Lib/StatsRecorder.cs b/Geekbot.net/Lib/StatsRecorder.cs index 3a38f73..8a17ff1 100644 --- a/Geekbot.net/Lib/StatsRecorder.cs +++ b/Geekbot.net/Lib/StatsRecorder.cs @@ -1,6 +1,7 @@ using System; using System.Threading.Tasks; using Discord.WebSocket; +using Geekbot.net.Lib.IClients; using StackExchange.Redis; namespace Geekbot.net.Lib diff --git a/Geekbot.net/Modules/AdminCmd.cs b/Geekbot.net/Modules/AdminCmd.cs index fe88610..b6732af 100644 --- a/Geekbot.net/Modules/AdminCmd.cs +++ b/Geekbot.net/Modules/AdminCmd.cs @@ -1,6 +1,6 @@ using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib; +using Geekbot.net.Lib.IClients; namespace Geekbot.net.Modules { diff --git a/Geekbot.net/Modules/Cat.cs b/Geekbot.net/Modules/Cat.cs index 5ca9017..0250e0a 100644 --- a/Geekbot.net/Modules/Cat.cs +++ b/Geekbot.net/Modules/Cat.cs @@ -1,6 +1,6 @@ -using System; -using System.Threading.Tasks; +using System.Threading.Tasks; using Discord.Commands; +using Geekbot.net.Lib.IClients; using RestSharp; namespace Geekbot.net.Modules diff --git a/Geekbot.net/Modules/Counters.cs b/Geekbot.net/Modules/Counters.cs index e037b35..de535f4 100644 --- a/Geekbot.net/Modules/Counters.cs +++ b/Geekbot.net/Modules/Counters.cs @@ -2,7 +2,7 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib; +using Geekbot.net.Lib.IClients; namespace Geekbot.net.Modules { diff --git a/Geekbot.net/Modules/Dog.cs b/Geekbot.net/Modules/Dog.cs new file mode 100644 index 0000000..6e98d90 --- /dev/null +++ b/Geekbot.net/Modules/Dog.cs @@ -0,0 +1,25 @@ +using System.Threading.Tasks; +using Discord.Commands; +using Geekbot.net.Lib.IClients; +using RestSharp; + +namespace Geekbot.net.Modules +{ + public class Dog : ModuleBase + { + private readonly IDogClient dogClient; + public Dog(IDogClient dogClient) + { + this.dogClient = dogClient; + } + + [Command("dog", RunMode = RunMode.Async), Summary("Return a random image of a dog.")] + public async Task Say() + { + var request = new RestRequest("woof.json", Method.GET); + + dynamic response = dogClient.Client.Execute(request); + await ReplyAsync(response.Data["url"]); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Modules/GuildInfo.cs b/Geekbot.net/Modules/GuildInfo.cs index 950868f..9a03373 100644 --- a/Geekbot.net/Modules/GuildInfo.cs +++ b/Geekbot.net/Modules/GuildInfo.cs @@ -4,6 +4,7 @@ using Discord.Commands; using Discord; using Geekbot.net.Lib; using System.Linq; +using Geekbot.net.Lib.IClients; namespace Geekbot.net.Modules { diff --git a/Geekbot.net/Modules/Info.cs b/Geekbot.net/Modules/Info.cs index 49c4af2..a31fec9 100644 --- a/Geekbot.net/Modules/Info.cs +++ b/Geekbot.net/Modules/Info.cs @@ -1,10 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Threading.Tasks; +using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib; +using Geekbot.net.Lib.IClients; namespace Geekbot.net.Modules { diff --git a/Geekbot.net/Modules/UserInfo.cs b/Geekbot.net/Modules/UserInfo.cs index 7eeb4cb..728fb50 100644 --- a/Geekbot.net/Modules/UserInfo.cs +++ b/Geekbot.net/Modules/UserInfo.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.IClients; namespace Geekbot.net.Modules { diff --git a/Geekbot.net/Modules/Youtube.cs b/Geekbot.net/Modules/Youtube.cs index b06fbdc..723ea9a 100644 --- a/Geekbot.net/Modules/Youtube.cs +++ b/Geekbot.net/Modules/Youtube.cs @@ -1,7 +1,7 @@ using System; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib; +using Geekbot.net.Lib.IClients; using Google.Apis.Services; using Google.Apis.YouTube.v3; diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index d66c62b..cc33b50 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -54,6 +54,7 @@ namespace Geekbot.net map = new DependencyMap(); map.Add(new CatClient()); + map.Add(new DogClient()); map.Add(redis); map.Add(new RandomClient()); From fd7ea886d4b2be5bac8a8a9ea8c8084abfdf783e Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sun, 7 May 2017 22:45:16 +0200 Subject: [PATCH 005/553] 4chan command - the beginning --- Geekbot.net/Lib/Dtos/FourChanDto.cs | 20 +++++++++ .../Lib/IClients/FourChanBoardClient.cs | 38 ++++++++++++++++ Geekbot.net/Modules/FourChan.cs | 43 +++++++++++++++++++ 3 files changed, 101 insertions(+) create mode 100644 Geekbot.net/Lib/Dtos/FourChanDto.cs create mode 100644 Geekbot.net/Lib/IClients/FourChanBoardClient.cs create mode 100644 Geekbot.net/Modules/FourChan.cs diff --git a/Geekbot.net/Lib/Dtos/FourChanDto.cs b/Geekbot.net/Lib/Dtos/FourChanDto.cs new file mode 100644 index 0000000..9d71d8c --- /dev/null +++ b/Geekbot.net/Lib/Dtos/FourChanDto.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; + +namespace Geekbot.net.Lib.Dtos +{ + class FourChanDto + { + public class BoardList + { + public List Boards { get; set; } + } + + public class Board + { + public string board { get; set; } + public string title { get; set; } + public string ws_board { get; set; } + public string meta_description { get; set; } + } + } +} diff --git a/Geekbot.net/Lib/IClients/FourChanBoardClient.cs b/Geekbot.net/Lib/IClients/FourChanBoardClient.cs new file mode 100644 index 0000000..49fdc8d --- /dev/null +++ b/Geekbot.net/Lib/IClients/FourChanBoardClient.cs @@ -0,0 +1,38 @@ +using RestSharp; +using System; +using System.Collections.Generic; +using static Geekbot.net.Lib.Dtos.FourChanDto; + +namespace Geekbot.net.Lib.IClients +{ + + class FourChanBoardClient + { + private BoardList boards; + private static FourChanBoardClient instace; + + private FourChanBoardClient() + { + Console.WriteLine("Fetching Boards"); + var boardClient = new RestClient("https://a.4cdn.org"); + var boardRequest = new RestRequest("boards.json", Method.GET); + var boardResult = boardClient.Execute(boardRequest); + this.boards = boardResult.Data; + } + + public static FourChanBoardClient Boards() + { + if (instace == null) + { + instace = new FourChanBoardClient(); + } + + return instace; + } + + public List getBoards() + { + return this.boards.Boards; + } + } +} diff --git a/Geekbot.net/Modules/FourChan.cs b/Geekbot.net/Modules/FourChan.cs new file mode 100644 index 0000000..3cdf036 --- /dev/null +++ b/Geekbot.net/Modules/FourChan.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Discord.Commands; +using static Geekbot.net.Lib.Dtos.FourChanDto; +using Geekbot.net.Lib.IClients; + +namespace Geekbot.net.Modules +{ + public class FourChan : ModuleBase + { + [Command("4chan", RunMode = RunMode.Async), Summary("Get Something from 4chan")] + public async Task Chan([Summary("The someone")] string boardParam) + { + try + { + var boards = FourChanBoardClient.Boards(); + var board = new Board(); + foreach (var b in boards.getBoards()) + { + if (b.board.Equals(boardParam)) + { + board = b; + break; + } + } + if (board.board == boardParam) + { + await ReplyAsync($"{board.title} - {board.meta_description}"); + } else + { + await ReplyAsync("Sorry, that board does not exist..."); + } + } + catch (Exception e) + { + await ReplyAsync(e.Message); + } + } + } +} + +// var boards = new List["a", "b", "c", "d", "e", "f", "g", "gif", "h", "hr", "k", "m", "o", "p", "r", "s", "t", "u", "v", "vg", "vr", "w", "wg", "i", "ic", "r9k", "s4s", "cm", "hm", "lgbt", "y", "3", "aco", "adv", "an", "asp", "biz", "cgl", "ck", "co", "diy", "fa", "fit", "gd", "hc", "his", "int", "jp", "lit", "mlp", "mu", "n", "news", "out", "po", "pol", "qst", "sci", "soc" / sp / tg / toy / trv / tv / vp / wsg / wsr /]; From 10fe9e3adae6d1b489753f7626aea5d71d0d0581 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sun, 7 May 2017 23:52:01 +0200 Subject: [PATCH 006/553] updating readme and adding license --- LICENSE | 21 +++++++++++++++++++++ readme.md | 8 ++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a0a211e --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Pizza and Coffee Studios + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/readme.md b/readme.md index 3062d8c..6158c60 100644 --- a/readme.md +++ b/readme.md @@ -1,8 +1,8 @@ # Geekbot.net -The Geekbot rewritten in C# and dotnet core +A General Purpose Discord Bot written in DotNet Core -### Running +### Building Geekbot.net Requires dotnet core 1.0.1 and dotnet core cli 1.1 @@ -11,3 +11,7 @@ Geekbot.net Requires dotnet core 1.0.1 and dotnet core cli 1.1 `cd Geekbot.net` `dotnet run` + +### Contributing + +Everyone is free to open an issue or create a pull request From ea59fab28aeb4b35220bfccc44665e0b1eb5dd05 Mon Sep 17 00:00:00 2001 From: dboerlage Date: Mon, 15 May 2017 20:43:50 +0200 Subject: [PATCH 007/553] Adds choose command --- Geekbot.net/Modules/Choose.cs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 Geekbot.net/Modules/Choose.cs diff --git a/Geekbot.net/Modules/Choose.cs b/Geekbot.net/Modules/Choose.cs new file mode 100644 index 0000000..b7114a4 --- /dev/null +++ b/Geekbot.net/Modules/Choose.cs @@ -0,0 +1,24 @@ +using System; +using System.Threading.Tasks; +using Discord.Commands; +using Geekbot.net.Lib.IClients; + +namespace Geekbot.net.Modules +{ + public class Choose : ModuleBase + { + private readonly IRandomClient rnd; + public Choose(IRandomClient randomClient) + { + rnd = randomClient; + } + + [Command("choose", RunMode = RunMode.Async), Summary("Let the bot make a choice for you.")] + public async Task Command([Remainder, Summary("The choices, sepperated by a ;")] string choices) + { + var choicesArray = choices.Split(';'); + var choice = rnd.Client.Next(choicesArray.Length); + ReplyAsync($"I choose **{choicesArray[choice]}**"); + } + } +} \ No newline at end of file From 6a33bddadbefa55945ce03bac1cc9c66b79c147e Mon Sep 17 00:00:00 2001 From: dboerlage Date: Mon, 15 May 2017 21:14:38 +0200 Subject: [PATCH 008/553] Adds shipping command --- Geekbot.net/Modules/Ship.cs | 75 +++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 Geekbot.net/Modules/Ship.cs diff --git a/Geekbot.net/Modules/Ship.cs b/Geekbot.net/Modules/Ship.cs new file mode 100644 index 0000000..2f4c562 --- /dev/null +++ b/Geekbot.net/Modules/Ship.cs @@ -0,0 +1,75 @@ +using System; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Geekbot.net.Lib.IClients; + +namespace Geekbot.net.Modules +{ + public class Ship : ModuleBase + { + + private readonly IRedisClient redis; + private readonly IRandomClient rnd; + public Ship(IRedisClient redisClient, IRandomClient randomClient) + { + redis = redisClient; + rnd = randomClient; + } + + [Command("Ship", RunMode = RunMode.Async), Summary("Ask the Shipping meter")] + public async Task Command([Summary("User 1")] IUser user1, [Summary("User 2")] IUser user2) + { + // Create a String + var dbstring = ""; + if (user1.Id > user2.Id) + { + dbstring = $"{user1.Id}-{user2.Id}"; + } + else + { + dbstring = $"{user2.Id}-{user1.Id}"; + } + dbstring = $"{Context.Guild.Id}-{dbstring}"; + Console.WriteLine(dbstring); + + var dbval = redis.Client.StringGet(dbstring); + var shippingRate = 0; + if (dbval.IsNullOrEmpty) + { + shippingRate = rnd.Client.Next(1, 100); + redis.Client.StringSet(dbstring, shippingRate); + } + else + { + shippingRate = int.Parse(dbval.ToString()); + } + + var reply = ""; + reply = reply + $"{user1.Username} :heart: {user2.Username}\r\n"; + reply = reply + $"0% [----{shippingRate}%----] 100% - {determinateSuccess(shippingRate)}"; + ReplyAsync(reply); + } + + private string determinateSuccess(int rate) + { + if (rate < 20) + { + return "Not gonna happen"; + } if (rate >= 20 && rate < 40) + { + return "A slight chance"; + } if (rate >= 40 && rate < 60) + { + return "Perhaps it could work"; + } if (rate >= 60 && rate < 80) + { + return "A good match"; + } if (rate >= 80) + { + return "10/10"; + } + return "a"; + } + } +} \ No newline at end of file From 9e6773a02257123c78ddba406f7b5693b6e26422 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Mon, 15 May 2017 23:38:23 +0200 Subject: [PATCH 009/553] finishing ship command and adding await in choose --- Geekbot.net/Modules/Choose.cs | 2 +- Geekbot.net/Modules/Ship.cs | 40 +++++++++++++++++++++++++++-------- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/Geekbot.net/Modules/Choose.cs b/Geekbot.net/Modules/Choose.cs index b7114a4..28a8be2 100644 --- a/Geekbot.net/Modules/Choose.cs +++ b/Geekbot.net/Modules/Choose.cs @@ -18,7 +18,7 @@ namespace Geekbot.net.Modules { var choicesArray = choices.Split(';'); var choice = rnd.Client.Next(choicesArray.Length); - ReplyAsync($"I choose **{choicesArray[choice]}**"); + await ReplyAsync($"I choose **{choicesArray[choice]}**"); } } } \ No newline at end of file diff --git a/Geekbot.net/Modules/Ship.cs b/Geekbot.net/Modules/Ship.cs index 2f4c562..f22ed1b 100644 --- a/Geekbot.net/Modules/Ship.cs +++ b/Geekbot.net/Modules/Ship.cs @@ -45,31 +45,53 @@ namespace Geekbot.net.Modules shippingRate = int.Parse(dbval.ToString()); } - var reply = ""; - reply = reply + $"{user1.Username} :heart: {user2.Username}\r\n"; - reply = reply + $"0% [----{shippingRate}%----] 100% - {determinateSuccess(shippingRate)}"; - ReplyAsync(reply); + var reply = ":heartpulse: **Matchmaking** :heartpulse:\r\n"; + reply = reply + $":two_hearts: {user1.Mention} :heart: {user2.Mention} :two_hearts:\r\n"; + reply = reply + $"0% [{BlockCounter(shippingRate)}] 100% - {DeterminateSuccess(shippingRate)}"; + await ReplyAsync(reply); } - private string determinateSuccess(int rate) + private string DeterminateSuccess(int rate) { if (rate < 20) { return "Not gonna happen"; } if (rate >= 20 && rate < 40) { - return "A slight chance"; + return "Not such a good idea"; } if (rate >= 40 && rate < 60) { - return "Perhaps it could work"; + return "There might be a chance"; } if (rate >= 60 && rate < 80) { - return "A good match"; + return "Almost a match, but could work"; } if (rate >= 80) { - return "10/10"; + return "It's a match"; } return "a"; } + + private string BlockCounter(int rate) + { + var amount = Math.Floor(decimal.Floor(rate / 10)); + Console.WriteLine(amount); + var blocks = ""; + for(int i = 1; i <= 10; i++) + { + if(i <= amount) + { + blocks = blocks + ":white_medium_small_square:"; + if(i == amount) + { + blocks = blocks + $" {rate}% "; + } + } else + { + blocks = blocks + ":black_medium_small_square:"; + } + } + return blocks; + } } } \ No newline at end of file From b70d1e04dc5d4dd50c00c5b0d8bbea53b48f9be1 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Wed, 12 Jul 2017 09:52:55 +0200 Subject: [PATCH 010/553] Karma system now uses embed and less mentioning --- Geekbot.net/Modules/Counters.cs | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/Geekbot.net/Modules/Counters.cs b/Geekbot.net/Modules/Counters.cs index de535f4..04f3707 100644 --- a/Geekbot.net/Modules/Counters.cs +++ b/Geekbot.net/Modules/Counters.cs @@ -30,10 +30,22 @@ namespace Geekbot.net.Modules { var key = Context.Guild.Id + "-" + user.Id + "-karma"; var badJokes = (int)redis.Client.StringGet(key); - redis.Client.StringSet(key, (badJokes + 1).ToString()); + var newBadJokes = badJokes + 1; + redis.Client.StringSet(key, newBadJokes.ToString()); var lastKey = Context.Guild.Id + "-" + Context.User.Id + "-karma-timeout"; redis.Client.StringSet(lastKey, GetNewLastKarma()); - await ReplyAsync($"{Context.User.Username} gave {user.Mention} karma"); + + var eb = new EmbedBuilder(); + eb.WithAuthor(new EmbedAuthorBuilder() + .WithIconUrl(user.GetAvatarUrl()) + .WithName(user.Username)); + + eb.WithColor(new Color(138, 219, 146)); + eb.Title = "Karma Increased"; + eb.AddInlineField("By", Context.User.Username); + eb.AddInlineField("amount", "+1"); + eb.AddInlineField("Current Karma",newBadJokes); + await ReplyAsync("", false, eb.Build()); } } @@ -53,10 +65,22 @@ namespace Geekbot.net.Modules { var key = Context.Guild.Id + "-" + user.Id + "-karma"; var badJokes = (int)redis.Client.StringGet(key); - redis.Client.StringSet(key, (badJokes - 1).ToString()); + var newBadJokes = badJokes - 1; + redis.Client.StringSet(key, newBadJokes.ToString()); var lastKey = Context.Guild.Id + "-" + Context.User.Id + "-karma-timeout"; redis.Client.StringSet(lastKey, GetNewLastKarma()); - await ReplyAsync($"{Context.User.Username} lowered {user.Mention}'s karma"); + + var eb = new EmbedBuilder(); + eb.WithAuthor(new EmbedAuthorBuilder() + .WithIconUrl(user.GetAvatarUrl()) + .WithName(user.Username)); + + eb.WithColor(new Color(138, 219, 146)); + eb.Title = "Karma Decreased"; + eb.AddInlineField("By", Context.User.Username); + eb.AddInlineField("amount", "-1"); + eb.AddInlineField("Current Karma",newBadJokes); + await ReplyAsync("", false, eb.Build()); } } From 90299a39ee99d8f20e5242ab432ce4019840a2d9 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sun, 30 Jul 2017 16:24:27 +0200 Subject: [PATCH 011/553] User stats now show a percentage of the users message contribution to the server --- .gitignore | 1 + Geekbot.net/Modules/UserInfo.cs | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 55ab035..bec8c02 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ Backup/ .vs/ UpgradeLog.htm .idea +.vscode diff --git a/Geekbot.net/Modules/UserInfo.cs b/Geekbot.net/Modules/UserInfo.cs index 728fb50..ce1644f 100644 --- a/Geekbot.net/Modules/UserInfo.cs +++ b/Geekbot.net/Modules/UserInfo.cs @@ -27,6 +27,11 @@ namespace Geekbot.net.Modules var messages = (int)redis.Client.StringGet(key + "-messages"); var level = LevelCalc.GetLevelAtExperience(messages); + var guildKey = Context.Guild.Id.ToString(); + var guildMessages = (int)redis.Client.StringGet(guildKey + "-messages"); + + var percent = Math.Round((double)(100 * messages) / guildMessages, 2); + var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder() .WithIconUrl(userInfo.GetAvatarUrl()) @@ -36,18 +41,19 @@ namespace Geekbot.net.Modules eb.AddField("Discordian Since", $"{userInfo.CreatedAt.Day}/{userInfo.CreatedAt.Month}/{userInfo.CreatedAt.Year} ({age} days)"); eb.AddInlineField("Level", level) - .AddInlineField("Messages Sent", messages); + .AddInlineField("Messages Sent", messages) + .AddInlineField("Server Total", $"{percent}%"); var karma = redis.Client.StringGet(key + "-karma"); if (!karma.IsNullOrEmpty) { - eb.AddField("Karma", karma); + eb.AddInlineField("Karma", karma); } var correctRolls = redis.Client.StringGet($"{Context.Guild.Id}-{userInfo.Id}-correctRolls"); if (!correctRolls.IsNullOrEmpty) { - eb.AddField("Guessed Rolls", correctRolls); + eb.AddInlineField("Guessed Rolls", correctRolls); } await ReplyAsync("", false, eb.Build()); From bfca811955e5a7d15a9e60cbee89a6109b30ba19 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sun, 30 Jul 2017 23:35:28 +0200 Subject: [PATCH 012/553] Highscores and cleanup --- Geekbot.net/Modules/UserInfo.cs | 33 ++++++++++++++++++++++++++++++++- Geekbot.net/Program.cs | 32 ++++++++------------------------ 2 files changed, 40 insertions(+), 25 deletions(-) diff --git a/Geekbot.net/Modules/UserInfo.cs b/Geekbot.net/Modules/UserInfo.cs index ce1644f..c134893 100644 --- a/Geekbot.net/Modules/UserInfo.cs +++ b/Geekbot.net/Modules/UserInfo.cs @@ -1,5 +1,8 @@ using System; +using System.Collections.Generic; +using System.Text; using System.Threading.Tasks; +using System.Linq; using Discord; using Discord.Commands; using Geekbot.net.Lib; @@ -59,6 +62,34 @@ namespace Geekbot.net.Modules await ReplyAsync("", false, eb.Build()); } - + [Alias("highscore")] + [Command("rank", RunMode = RunMode.Async), Summary("get user top 10")] + public async Task Rank() + { + await ReplyAsync("this will take a moment..."); + var allGuildUsers = await Context.Guild.GetUsersAsync(); + var unsortedDict = new Dictionary(); + foreach(var user in allGuildUsers) + { + var key = Context.Guild.Id + "-" + user.Id; + var messages = (int)redis.Client.StringGet(key + "-messages"); + if(messages > 0) { + unsortedDict.Add(user.Username, messages); + } + } + var sortedDict = unsortedDict.OrderByDescending(x => x.Value); + var reply = new StringBuilder(); + var count = 1; + foreach(KeyValuePair entry in sortedDict) + { + if(count < 11){ + reply.Append($"#{count} - **{entry.Key}** - {entry.Value}\r\n"); + count++; + } else { + break; + } + } + await ReplyAsync(reply.ToString()); + } } } \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index cc33b50..cf0487c 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -103,44 +103,28 @@ namespace Geekbot.net return true; } - public async Task Reconnect(Exception exception) - { - Console.WriteLine("========================================="); - Console.WriteLine("Geekbot Disconnected from the Discord Gateway..."); - Console.WriteLine(exception.Message); - Console.WriteLine("Attempting Reconnect..."); - Console.WriteLine("========================================="); - await client.StopAsync(); - System.Threading.Thread.Sleep(10000); - await Login(); - } - - public async Task FinishStartup() - { - - } - public async Task HandleCommand(SocketMessage messageParam) { var message = messageParam as SocketUserMessage; if (message == null) return; if (message.Author.IsBot) return; int argPos = 0; - if (message.ToString().ToLower().StartsWith("ping")) + var lowCaseMsg = message.ToString().ToLower(); + if (lowCaseMsg.StartsWith("ping")) { await message.Channel.SendMessageAsync("pong"); return; } - if (message.ToString().ToLower().StartsWith("hui")) + if (lowCaseMsg.StartsWith("hui")) { await message.Channel.SendMessageAsync("hui!!!"); return; } - if (message.ToString().ToLower().Contains("teamspeak") || message.ToString().ToLower().Contains("skype")) - { - await message.Channel.SendMessageAsync("How dare you to use such a filthy word in here http://bit.ly/2poL2IZ"); - return; - } + // if (message.ToString().ToLower().Contains("teamspeak") || message.ToString().ToLower().Contains("skype")) + // { + // await message.Channel.SendMessageAsync("How dare you to use such a filthy word in here http://bit.ly/2poL2IZ"); + // return; + // } if (!(message.HasCharPrefix('!', ref argPos) || message.HasMentionPrefix(client.CurrentUser, ref argPos))) return; var context = new CommandContext(client, message); Task.Run(async () => await commands.ExecuteAsync(context, argPos, map)); From 9f9850920e5633491942a6af48d6847eb1e54cd5 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Mon, 31 Jul 2017 00:20:37 +0200 Subject: [PATCH 013/553] Bug Fix and more info in rank command --- Geekbot.net/Modules/UserInfo.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Geekbot.net/Modules/UserInfo.cs b/Geekbot.net/Modules/UserInfo.cs index c134893..2dbb827 100644 --- a/Geekbot.net/Modules/UserInfo.cs +++ b/Geekbot.net/Modules/UserInfo.cs @@ -67,6 +67,8 @@ namespace Geekbot.net.Modules public async Task Rank() { await ReplyAsync("this will take a moment..."); + var guildKey = Context.Guild.Id.ToString(); + var guildMessages = (int)redis.Client.StringGet(guildKey + "-messages"); var allGuildUsers = await Context.Guild.GetUsersAsync(); var unsortedDict = new Dictionary(); foreach(var user in allGuildUsers) @@ -74,16 +76,18 @@ namespace Geekbot.net.Modules var key = Context.Guild.Id + "-" + user.Id; var messages = (int)redis.Client.StringGet(key + "-messages"); if(messages > 0) { - unsortedDict.Add(user.Username, messages); + unsortedDict.Add($"{user.Username}#{user.Discriminator}", messages); } } var sortedDict = unsortedDict.OrderByDescending(x => x.Value); var reply = new StringBuilder(); + reply.AppendLine($"Total Messages on {Context.Guild.Name}: {guildMessages}"); var count = 1; foreach(KeyValuePair entry in sortedDict) { if(count < 11){ - reply.Append($"#{count} - **{entry.Key}** - {entry.Value}\r\n"); + var percent = Math.Round((double)(100 * entry.Value) / guildMessages, 2); + reply.AppendLine($"#{count} - **{entry.Key}** - {percent}% of total - {entry.Value} messages"); count++; } else { break; From df9b48745a713b33a763f515b6b34e2ed15605e9 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Mon, 7 Aug 2017 18:42:30 +0200 Subject: [PATCH 014/553] Adding inv link in readme --- readme.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/readme.md b/readme.md index 6158c60..90ef904 100644 --- a/readme.md +++ b/readme.md @@ -2,6 +2,8 @@ A General Purpose Discord Bot written in DotNet Core +You can invite Geekbot to your server with [this link](https://discordapp.com/oauth2/authorize?client_id=171249478546882561&scope=bot&permissions=1416834054) + ### Building Geekbot.net Requires dotnet core 1.0.1 and dotnet core cli 1.1 From e97ebf86efeb282796134a2966304e93961e28b5 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Thu, 14 Sep 2017 20:24:04 +0200 Subject: [PATCH 015/553] Upgrading Dependencies and start restructure --- Geekbot.net/Geekbot.net.csproj | 74 ++++++++++-------- .../Lib/IClients/FourChanBoardClient.cs | 38 --------- Geekbot.net/Program.cs | 20 +++-- Geekbot.net/derp.ico | Bin 0 -> 370070 bytes derp.ico | Bin 0 -> 370070 bytes 5 files changed, 54 insertions(+), 78 deletions(-) delete mode 100644 Geekbot.net/Lib/IClients/FourChanBoardClient.cs create mode 100644 Geekbot.net/derp.ico create mode 100644 derp.ico diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index f943a96..5e543ab 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -1,33 +1,43 @@ - - - Exe - netcoreapp1.1 - - - - - 1.0.0-rc - - - 1.25.0.760 - - - 1.5.0.1 - - - 105.2.4-rc4-24214-01 - - - 1.2.1 - - - 4.3.1 - - - 4.3.0 - - - 4.3.0 - - + + + Exe + netcoreapp2.0 + derp.ico + 1.1.0 + Pizza and Coffee Studios + Pizza and Coffee Studios + A Discord bot + https://github.com/pizzaandcoffee/Geekbot.net + + + + 1.0.2 + + + 1.29.1.976 + + + 1.5.0.1 + + + + + + + 105.2.3 + + + 1.2.6 + + + 4.3.2 + + + + 4.3.0 + + + 4.3.0 + + \ No newline at end of file diff --git a/Geekbot.net/Lib/IClients/FourChanBoardClient.cs b/Geekbot.net/Lib/IClients/FourChanBoardClient.cs deleted file mode 100644 index 49fdc8d..0000000 --- a/Geekbot.net/Lib/IClients/FourChanBoardClient.cs +++ /dev/null @@ -1,38 +0,0 @@ -using RestSharp; -using System; -using System.Collections.Generic; -using static Geekbot.net.Lib.Dtos.FourChanDto; - -namespace Geekbot.net.Lib.IClients -{ - - class FourChanBoardClient - { - private BoardList boards; - private static FourChanBoardClient instace; - - private FourChanBoardClient() - { - Console.WriteLine("Fetching Boards"); - var boardClient = new RestClient("https://a.4cdn.org"); - var boardRequest = new RestRequest("boards.json", Method.GET); - var boardResult = boardClient.Execute(boardRequest); - this.boards = boardResult.Data; - } - - public static FourChanBoardClient Boards() - { - if (instace == null) - { - instace = new FourChanBoardClient(); - } - - return instace; - } - - public List getBoards() - { - return this.boards.Boards; - } - } -} diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index cf0487c..c5e31f1 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -2,6 +2,10 @@ using System.Reflection; using System.Runtime.InteropServices.ComTypes; using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Discord; using Discord.Commands; using Discord.WebSocket; @@ -16,9 +20,9 @@ namespace Geekbot.net { private CommandService commands; private DiscordSocketClient client; - private DependencyMap map; private IRedisClient redis; private RedisValue token; + private ServiceCollection services; private static void Main(string[] args) { @@ -30,7 +34,7 @@ namespace Geekbot.net Console.WriteLine("========================================="); Console.WriteLine("Starting..."); - Task.WaitAll(new Program().MainAsync()); + new Program().MainAsync().GetAwaiter().GetResult(); } public async Task MainAsync() @@ -52,11 +56,11 @@ namespace Geekbot.net redis.Client.StringSet("botOwner", ownerId); } - map = new DependencyMap(); - map.Add(new CatClient()); - map.Add(new DogClient()); - map.Add(redis); - map.Add(new RandomClient()); + services = new ServiceCollection(); + services.AddSingleton(new CatClient()); + services.AddSingleton(new DogClient()); + services.AddSingleton(new RandomClient()); + services.AddSingleton(redis); Console.WriteLine("Connecting to Discord..."); @@ -127,7 +131,7 @@ namespace Geekbot.net // } if (!(message.HasCharPrefix('!', ref argPos) || message.HasMentionPrefix(client.CurrentUser, ref argPos))) return; var context = new CommandContext(client, message); - Task.Run(async () => await commands.ExecuteAsync(context, argPos, map)); + Task.Run(async () => await commands.ExecuteAsync(context, argPos, services)); } public async Task HandleMessageReceived(SocketMessage messsageParam) diff --git a/Geekbot.net/derp.ico b/Geekbot.net/derp.ico new file mode 100644 index 0000000000000000000000000000000000000000..bf7cde6107c7f01be02d4d4809fdf15e4db7b4c6 GIT binary patch literal 370070 zcmeI536K<3n#Zg9zPqdGrlGs*LL3eS6;K?}0r3Ej1_4177(q}F@c{3WOFbk4CGV937Uq^hMb>#8h z_x=9gd-*c+mB-`t)Ogz3JnApxSykonoTp!f`rrRteg13p*`bH-e}ACIb491eGi_S` z`_a=qp1>53XTyg5@9Vst6R+2=^H(NZT}_nax-y2^y_%=&w4swDjBR`FdhSz4D(h%w)qqa^&%X7M&w zCv0EotCPBkT~hze9vSh~oheOk-!P@yShsRWU1UEEGY*#Edz&Tv#qGwn!S`>H@MpJ0 z_7nd6b}>Hta+`#e1%IbW|T52NuH;+@% zTqi@nyHFaA?v?r@yTy0u3DS7#!Nz(G#~&ntH?EVOhnFU7XKrsUdtbOp0&i`UhN;1f z>zdn?_fnJ}ayOl4LdvEoGxN*_Be$s!V*l`Wx#U^uVK2)ymD0L$x-_45pj39$XT9$V zU!$}vIb53OjuLOfKu%V&%X%MrU7cHXyA^u(DycnaNY>j{e`A=@9);eyQYwcwWW8N{ z`69=E|5~X#q*FXq6F%J4aRrDcQ&Q;N$}kpjdlF5T$iv;@SV-ZcSEk2lJfW_|4pYK zk+6N;kt2=mTF#l8@SRy!-@2K`I$D3`XXdhX#k7paO?Uj~{^KKAwrrWCJN}k`+a(V? z@PJr7eq~pS)E_fS8fT1))MNJ7Kb6B@QvTg_b>uU%Zsv08zy3&Od~mmPKXQ?=PUyXB zq)GJ!>!%zbRo!h_*WdJmnSadv4|W-R>(Z?9Uqw^3X!BHhW6EeAKm6G((*4WT()Gg? zS=sQPUtrWf>G3PP#<7g!>GnXq55Bohg0Eg6b%zg2dVHe}1Q68iO(5_oQ@RF7!2yw6niH_LCFL+@E@TlvlL3q3wb`BV2_V*S5PI<8gMeV2^2 zWF6~|H<&bHT0sAYe!D?}uU}}{^cYYv_%V-Z=dzIe+gWaNUv`vV=ilM?o{-dfes+2! z*5)zoTFF6%`Ct9h zm&SG#6%~0ef8C_8v@D)tSlg=UF|j`D58LIs|9nA$+s;<^F)fMt&SW6ja>c*zFt+Qw zX})y*V0mP_;MT8X?kDZZS`CnFf)28!Blch}M?|tTyNIBatoDeCe@3NC4KIq-CF!Fi4j$`~^ zjPmclMz8xt@#PQeYrV>PpInr-{N{Q=8_RF*Go$}i`Hgks%CGM~()~7Xy}Dknt_S!0 zhjHxv`|P^qSn2)cX^HmJQ=~f77FpN0XDZ3q zjoz0&H|)2Kk=I7w{0FJ85f8fDNsg`ek*XgU*!k`3`k$)&rkPvF;bK zEP@~OeOl9$ZBS<3r{z)4ye9dh@0y|SuY87&@Bs|K01UtY48Q;kzyJ)moPo+=t)lOx z(bn_esnUJ_Olh8D@4W@l=N=6wj+5X!8>Q#x^Q7k&r%U$(Crj#yhK($72O&D8w|rL6zxvK8WW zspY>y)H(VX`K-U5@1i=`lGf^v48`ymUA98J*7a{ZA(*y|x(>_^&F4!Wh&(R{=VQHs!y20 z_NnI!o?j+8)&C4@b2$~#59yAj=i#FMgXdpAi_mq?vKZ6ndFgzuzti(!#cvn-IJbGZ zy6%lVe$S4z8IK>@duz<`J2xID4d3b=wEmOj$Kk(Nlkxbzwf%EyMQ`ta?S_ooCG%_i zeV~n}9+q)Gfjt{+scUrk&DYdFbNtuudq(!{+b2&y{d6P_xx`=R_Rqffow2XJzCL4L zPKf^<|NXl049&amzH7PufBC<^8v9zfu>aomV%J|kuQTM@*%9m9x*$Q1OaAb%eE*Mc z%Z8607d?lbw%`X_64pzm_vp`b{O|eWTgJYoes8U@pU!QIV)mowOB;H}d}+UOrnFx% z!?3pVr$zj3>Na1?`0=0U@)zQ@|H(6?c6{lKe-)z6(Z}#VxxnT1SMe{Q@z3bk6ymkP zzfJYm&mc!zMQh^R>G63aM*k{bh2FkQ<)gXMyzt1pSVvsG&9?q}uKlWEs(w)xGk2zX zPRIZFd}XKi+hcRp-2I1U%%d^&*W>Z(S?)rPe`j0&=6RzB>Za@X=xI{j+Z?H%SN+~W zG_QL6F1PwGD#`lmIkBVb7kKHs^z~PBSNP5!AMsB-_vZV=_&c-y9yNbYw14zGxW3hg zxTpT=S-IircP{jAUFc=k-DgVM*<+14#PvMlsjT6ckg<*4PTSC%rc2{g>vIR0e8n&8 zCLa)Uyv|KirSbS+%JP}zZd-A5%yvV+b8^P{;q`tqUCS7L_wgASiLZm*?>je775@_p zQkcr=kDQj%_)pWELnWl<{EgTL*A2W@pZg!3Bc)LP;Xhs#qupp7>(_dW*8cIYZQ@sL zB=s*o|M`l4t(y0`W6S)M<~#o|X+3jv(e>Z5>{}_zsLS8Jc8chE2<*-~?2l&xU;qYS z00v+H24DaNU;qYS00v;dQ4FYX@#j_#=y@VG=*oMe=7~_hg`VV(F(j8i@1~f50ek=h zFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE z00S@p126ysFaQHE00S@p12B-lK<&Z3#=P2kZf(@e z!_KT9@xL?1FQ$(|>Nk;$c^bS;3be^g{=pX%~fAmlPKY9N@Ro*O@&z+qA>kjKOeh*UrCZrYfU3hHD z^P_T!bEKlR^{?qKR2b1)ii5DTGP*u=Cc1> zw`ra;DQ$Uld3zpTXG@vu+a8_eBNBqluGC9h|?Y&b1dp5*a_|x06 z+E=YJSgDZsL#r(Z742{|h|7tUv!R zqW_mESC-@V#NXxlAN{AE|4)stgg;Z`VQLPb@W(ev&yGu^TipZWGz)%^`uV1k)W5pV zs&2y2jOJ~uvSrL7-S|)Njf=(q_QFH4!u|DKQd_dIY?#`raSvpZ$% zD(b5x@a$q`i;|ju$2?>I1&RMF=M(=y&i~r`(1N6K)A95_wb1Zq`uNwRyk4Pmn8_^h z&wM|c&Vz-{|G{@}Oc}q>hc{S{zse1|Js|#WjsGI)-F~W6k7`NThS=8rmwo>4zy53I z{7;tkUss(ne;E0H=Mp3SHKW>ye->?X`utyd@%Pqdi2n=csQC9u&1mAEO`b~||NZxW zl#>24#(($9{qgsqf2;a;a{LRC|6eZi^S=^|zo)W7+Llk1)+p2O+m=r=K5JPpUYci( zH0G>tJNqE9YQA$O#T+a8xGf6~k>DRfNjK3>b51N+ChEY78<&&vxn z{}b`g?)*O+R$3MuEPI){dmschKeE<6XN9RP! zi~c>*cAm94aP=Ij<~5o^#XtA?|F(($$ulD5CH}-en;cor>!5%8+EOQSLi~w;vin1_ z{fzeC+5Dh?XUETKo8!dzSBE;JW^7MRRz0FkszWV?RSj!&{rFGikfxmc81et8p%H(2 zD%`Clt6F4x_<;c!fB_hQ0T_S*7=Qs7fB_hQ0T_S*7=Qs7fB_hQ0T_S*7=Qs7fB_hQ z0T_S*7=Qs7fB_hQ0T_S*7=Qs7fB_hQ0T_S*7=Qs7fB_hQ0T_S*7=Qs7fB_gNA_MBs z{NVvSfCumZ9>4=`^1x_aS+BARy$I=d9#5#Me;NDV^>Z~Tci;nj00S@p126ysFaQHE z00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p z126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ys zFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE z00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p z126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ys zFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p12B*`1{!CKm#%x3rL~T0r%1<@ zN2Iqaju3BEMc&Hkfq?|y)=xelF>ZIArQ$R>eXQbRsbg1LnXrF+?kRhp_*Ne;Bfh#b ztp%Q4EdGaQrMK;~#9ISHh15**+(`*>3x9m0_#c^_K2~wD?0u+DDjKWHp7lb;#wo|j zO8>i-XXXk07hFH-_1~vrmd*z9Ir=aEc0N@;%0~aeS1&;SC3yakRR4RoNbv2;CG?x? zQ`>u2$HWu;qyKd00HF`Am%#3oG3I|_ehfo?+W*pM|G(TOVP)y!8UEt-nAo9z^q-EG zgzpqz!PnNrFogaK&rq`VKOt60#&*K{(0{7_u-iV*rvIOeso<|JLH|WQCqVy&&$;E6 zA9B|Jp0(&7{TKY4r`+^c?E2)a|2Nm6fAo+3i_C!4{DJUDeZjb)azg33NzjGNv|IUq_Ro&XPJ^FVpL+IbRv9n9R zR`-Mcoy!pVcW&&g>ejC9bJzc6jQ=tI$MwG=Ghj6jpnvDKA+-O_jh$89+O<9UcP>Nd z-?_1~OTSk4gZ`b%5c+p+?5yh6uI=sAf8CfNQZv$r703s^^QWeL&Nta}TlzDe|08dh z`NKB-$IU5~alSCtj~zeF!5@JaSD=4~kH48ZEY=eJ56pw*w48iJ7OFKep&obGeR|H&Ix^`DL}zDxgmD#i8>`bYohzqB=)&m4jN(Lee}|K@lG zrWOZ1;#t(9UfL;vU>{ku>1W-dbi=pX%~f6o8O z1N8shmj`J7(LL?I`*ctLAKja}H^nr{-b+S_vVuJ-+g(2_Mbd} z{@tg0+W+F}zInz78M^+clCiE^P89!3*W~mJnaL7M=jD-v_J4by4Ba%PWVkdmvf(JH zY^^P;-xu&L8*h2eH}jgU9m~M;OVPfX57TWqEMEV1u#}H|RCP9>|2)pCf&Sg6eVyyj ze{s$OX#d@*w^Hk0pnvqQ`)joS?#xHwFK+KY4^`*={!+5IzHZs||5qI$fq(jT3OieU zt}WH~(Vu6#-u`WNs^!ilvG(j@3BJ18b?3gN))p6|JmD|5N%(i)DV}|PtAtJa>}Cmn zv|0R5Ele02D>wZQxn>r6bK!VfF*NR|W2$_l+r9WPMD*{@{;8wbC7)Su)6l&`=rQFupMgP`)2#5I4sSKch*mWwql-oMH z=-;{z;Se7>l>zh*yG~`7a$9E?{ag1T9O6T#GJyVJ*QxAMZtLu#f9pPkLwx8|23(^5 z)&-NL`~LH++XJg)#J+7M#k+o{Z1|7PmEk|MZvGd`drq?Me^_aYpL(CZtfUyw&us)= zyCEmOySAPvLvJ{Gz}6ovl`Z8p|Cc%Erq!jlwo1aE-Bwbu4}Woocq+WM%-7^wJF}$f zX6y4vzrRx|>T7KAQ`4MDCFiG(^>b{gn^ldJ^Y-Z9!OumafAWLJ+WbT4AN}k0jrQM~ zj-1*@K>z3;{kv29I_~Hn{iA>MZ|k^}#cM~5|7DqzIREGTpY#8;3^4wmUE9X_e|COy z>Un;ua?}6MvaPk)r^!qIiuONk?oY)$pAY0Z^pF0v9%%muG~uTFP>TB3_akn&ag%J` zyg99f!{LniznuI3Vbv$OZcAoAO`JF}qo2?}`p-)rHOGGQpZ@k|$@DjM>eP%}m$m-Y zebWE+m;cS=CRx6Gc}72>fAo+3opmmtpOZlU?$oVa=O`uF|5tqm+W*YC2>qjdt9bzZ zXVzIM^^2m*g8tDz`cKaQ=l{a_zr}lGtZJ;3x2OH5{nval{+GTTDP;{?DI5An|LEVH z+ShSM|L7n6yIcPwJ}s^JfAkm^ep6Z>X&?GuzAh&}1>amJ{)cA`*!EdcH?C7^4)pcg$Tq3T(JDLZ z(Z7SnE`6(y&xxT@&=O_H+}}v%qXhjw)F%~9)#%niy0xnxg#L5WP%>RPjEM_oIJ9{)%G z=pX&N<~j)acW-~6@xOs~(5-y}^pF0{Jiz(C`|<($NB`*GeY!XMJLn(%qkr@t83Sbe zkMTdo|J*bF_ts@GM zkN(ZEVV32e59t59SMT)y%U|D_aya@&|7ISb|L?whfd0{c&idE$#{KR#3BPwuti5}+ zbZnd}LvEOZ703s}A6%8wHB0o5{&Uv9x=$ed=~f9mxljU6Efl}D$LEXx(K+I+spPs! z0q2lvo;wNs=iA@a72-R0+@P&ZZPRZD?_Z9S+VMk5P9M4S|HFHg{GKVAHf%HkN$Jj ztexAHyZ-$zT%FVP4XwT4>la3}S1kPpe|1Tu4Cp`gIf$K_aMQlff9iI*B=jGZgU~vkX{}R`~8Z(IL|Ci16Kl=Z6YdM$wq5l%s|I4c)`tN<{RB4(WD)=>`Ok6Sk@7#V# z?)twp!liDXO7;0)$DjYJ>jq}~-}}%h(r{`I`p@_Mnl9Qu`Y-YJ|FtzS`fr>SME@?* zXQsZF)$h@N{`Ftk)}XHceK)7;5WzPtiqU`5X<_t_{%vCb{TD$0trqkjHP51P{*V4` zW8Z4qSq|Ihtp7JT|Iar5l@|0LdjDG5f7<)J<-FYWAN%{ijQ^z`1Gc39->#3+zZ(BP zZA9K!$TpwFub0#K|0g%`{7(twHS}NF{r}K!Hw@^1JNl2$J-kod?quT|^zS77_o?>3 zOve9c|4X7DhyER=|8lwi=i?jc|2w(=zh`ZvU&{SI>HA<6&2~PnX{y- zqp>7(YnR`BD-J0wA1gn%E*Mo-KDH}XuG&v2>R+*0)!9&1Y@+`XZwE`@oW3Y|2mKc$ z&!B(wUle_3%4_H!{byo??+e06vGRle>2uXs+eHPi3)L~AOg$r~=j=`Y-Eq=x9AT z?R8Q0Py3(8egW;j)3jKO@)lM9ZaM#_{ippe(d#JapZNHGs#ucUZx>jMhRjM!j{FunC(m00S@p126ys zFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE z00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p z126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ys zFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE z00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p z126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ys zFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE z00S@p126ysFaQIEV8Fv49>4>501w~+Jb(xA03N^tcmNOJ0X%>Q@Bkjb19$)r-~l{< U2k-zMzyo*y58wej;A{{4KR^n?YybcN literal 0 HcmV?d00001 diff --git a/derp.ico b/derp.ico new file mode 100644 index 0000000000000000000000000000000000000000..bf7cde6107c7f01be02d4d4809fdf15e4db7b4c6 GIT binary patch literal 370070 zcmeI536K<3n#Zg9zPqdGrlGs*LL3eS6;K?}0r3Ej1_4177(q}F@c{3WOFbk4CGV937Uq^hMb>#8h z_x=9gd-*c+mB-`t)Ogz3JnApxSykonoTp!f`rrRteg13p*`bH-e}ACIb491eGi_S` z`_a=qp1>53XTyg5@9Vst6R+2=^H(NZT}_nax-y2^y_%=&w4swDjBR`FdhSz4D(h%w)qqa^&%X7M&w zCv0EotCPBkT~hze9vSh~oheOk-!P@yShsRWU1UEEGY*#Edz&Tv#qGwn!S`>H@MpJ0 z_7nd6b}>Hta+`#e1%IbW|T52NuH;+@% zTqi@nyHFaA?v?r@yTy0u3DS7#!Nz(G#~&ntH?EVOhnFU7XKrsUdtbOp0&i`UhN;1f z>zdn?_fnJ}ayOl4LdvEoGxN*_Be$s!V*l`Wx#U^uVK2)ymD0L$x-_45pj39$XT9$V zU!$}vIb53OjuLOfKu%V&%X%MrU7cHXyA^u(DycnaNY>j{e`A=@9);eyQYwcwWW8N{ z`69=E|5~X#q*FXq6F%J4aRrDcQ&Q;N$}kpjdlF5T$iv;@SV-ZcSEk2lJfW_|4pYK zk+6N;kt2=mTF#l8@SRy!-@2K`I$D3`XXdhX#k7paO?Uj~{^KKAwrrWCJN}k`+a(V? z@PJr7eq~pS)E_fS8fT1))MNJ7Kb6B@QvTg_b>uU%Zsv08zy3&Od~mmPKXQ?=PUyXB zq)GJ!>!%zbRo!h_*WdJmnSadv4|W-R>(Z?9Uqw^3X!BHhW6EeAKm6G((*4WT()Gg? zS=sQPUtrWf>G3PP#<7g!>GnXq55Bohg0Eg6b%zg2dVHe}1Q68iO(5_oQ@RF7!2yw6niH_LCFL+@E@TlvlL3q3wb`BV2_V*S5PI<8gMeV2^2 zWF6~|H<&bHT0sAYe!D?}uU}}{^cYYv_%V-Z=dzIe+gWaNUv`vV=ilM?o{-dfes+2! z*5)zoTFF6%`Ct9h zm&SG#6%~0ef8C_8v@D)tSlg=UF|j`D58LIs|9nA$+s;<^F)fMt&SW6ja>c*zFt+Qw zX})y*V0mP_;MT8X?kDZZS`CnFf)28!Blch}M?|tTyNIBatoDeCe@3NC4KIq-CF!Fi4j$`~^ zjPmclMz8xt@#PQeYrV>PpInr-{N{Q=8_RF*Go$}i`Hgks%CGM~()~7Xy}Dknt_S!0 zhjHxv`|P^qSn2)cX^HmJQ=~f77FpN0XDZ3q zjoz0&H|)2Kk=I7w{0FJ85f8fDNsg`ek*XgU*!k`3`k$)&rkPvF;bK zEP@~OeOl9$ZBS<3r{z)4ye9dh@0y|SuY87&@Bs|K01UtY48Q;kzyJ)moPo+=t)lOx z(bn_esnUJ_Olh8D@4W@l=N=6wj+5X!8>Q#x^Q7k&r%U$(Crj#yhK($72O&D8w|rL6zxvK8WW zspY>y)H(VX`K-U5@1i=`lGf^v48`ymUA98J*7a{ZA(*y|x(>_^&F4!Wh&(R{=VQHs!y20 z_NnI!o?j+8)&C4@b2$~#59yAj=i#FMgXdpAi_mq?vKZ6ndFgzuzti(!#cvn-IJbGZ zy6%lVe$S4z8IK>@duz<`J2xID4d3b=wEmOj$Kk(Nlkxbzwf%EyMQ`ta?S_ooCG%_i zeV~n}9+q)Gfjt{+scUrk&DYdFbNtuudq(!{+b2&y{d6P_xx`=R_Rqffow2XJzCL4L zPKf^<|NXl049&amzH7PufBC<^8v9zfu>aomV%J|kuQTM@*%9m9x*$Q1OaAb%eE*Mc z%Z8607d?lbw%`X_64pzm_vp`b{O|eWTgJYoes8U@pU!QIV)mowOB;H}d}+UOrnFx% z!?3pVr$zj3>Na1?`0=0U@)zQ@|H(6?c6{lKe-)z6(Z}#VxxnT1SMe{Q@z3bk6ymkP zzfJYm&mc!zMQh^R>G63aM*k{bh2FkQ<)gXMyzt1pSVvsG&9?q}uKlWEs(w)xGk2zX zPRIZFd}XKi+hcRp-2I1U%%d^&*W>Z(S?)rPe`j0&=6RzB>Za@X=xI{j+Z?H%SN+~W zG_QL6F1PwGD#`lmIkBVb7kKHs^z~PBSNP5!AMsB-_vZV=_&c-y9yNbYw14zGxW3hg zxTpT=S-IircP{jAUFc=k-DgVM*<+14#PvMlsjT6ckg<*4PTSC%rc2{g>vIR0e8n&8 zCLa)Uyv|KirSbS+%JP}zZd-A5%yvV+b8^P{;q`tqUCS7L_wgASiLZm*?>je775@_p zQkcr=kDQj%_)pWELnWl<{EgTL*A2W@pZg!3Bc)LP;Xhs#qupp7>(_dW*8cIYZQ@sL zB=s*o|M`l4t(y0`W6S)M<~#o|X+3jv(e>Z5>{}_zsLS8Jc8chE2<*-~?2l&xU;qYS z00v+H24DaNU;qYS00v;dQ4FYX@#j_#=y@VG=*oMe=7~_hg`VV(F(j8i@1~f50ek=h zFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE z00S@p126ysFaQHE00S@p12B-lK<&Z3#=P2kZf(@e z!_KT9@xL?1FQ$(|>Nk;$c^bS;3be^g{=pX%~fAmlPKY9N@Ro*O@&z+qA>kjKOeh*UrCZrYfU3hHD z^P_T!bEKlR^{?qKR2b1)ii5DTGP*u=Cc1> zw`ra;DQ$Uld3zpTXG@vu+a8_eBNBqluGC9h|?Y&b1dp5*a_|x06 z+E=YJSgDZsL#r(Z742{|h|7tUv!R zqW_mESC-@V#NXxlAN{AE|4)stgg;Z`VQLPb@W(ev&yGu^TipZWGz)%^`uV1k)W5pV zs&2y2jOJ~uvSrL7-S|)Njf=(q_QFH4!u|DKQd_dIY?#`raSvpZ$% zD(b5x@a$q`i;|ju$2?>I1&RMF=M(=y&i~r`(1N6K)A95_wb1Zq`uNwRyk4Pmn8_^h z&wM|c&Vz-{|G{@}Oc}q>hc{S{zse1|Js|#WjsGI)-F~W6k7`NThS=8rmwo>4zy53I z{7;tkUss(ne;E0H=Mp3SHKW>ye->?X`utyd@%Pqdi2n=csQC9u&1mAEO`b~||NZxW zl#>24#(($9{qgsqf2;a;a{LRC|6eZi^S=^|zo)W7+Llk1)+p2O+m=r=K5JPpUYci( zH0G>tJNqE9YQA$O#T+a8xGf6~k>DRfNjK3>b51N+ChEY78<&&vxn z{}b`g?)*O+R$3MuEPI){dmschKeE<6XN9RP! zi~c>*cAm94aP=Ij<~5o^#XtA?|F(($$ulD5CH}-en;cor>!5%8+EOQSLi~w;vin1_ z{fzeC+5Dh?XUETKo8!dzSBE;JW^7MRRz0FkszWV?RSj!&{rFGikfxmc81et8p%H(2 zD%`Clt6F4x_<;c!fB_hQ0T_S*7=Qs7fB_hQ0T_S*7=Qs7fB_hQ0T_S*7=Qs7fB_hQ z0T_S*7=Qs7fB_hQ0T_S*7=Qs7fB_hQ0T_S*7=Qs7fB_hQ0T_S*7=Qs7fB_gNA_MBs z{NVvSfCumZ9>4=`^1x_aS+BARy$I=d9#5#Me;NDV^>Z~Tci;nj00S@p126ysFaQHE z00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p z126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ys zFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE z00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p z126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ys zFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p12B*`1{!CKm#%x3rL~T0r%1<@ zN2Iqaju3BEMc&Hkfq?|y)=xelF>ZIArQ$R>eXQbRsbg1LnXrF+?kRhp_*Ne;Bfh#b ztp%Q4EdGaQrMK;~#9ISHh15**+(`*>3x9m0_#c^_K2~wD?0u+DDjKWHp7lb;#wo|j zO8>i-XXXk07hFH-_1~vrmd*z9Ir=aEc0N@;%0~aeS1&;SC3yakRR4RoNbv2;CG?x? zQ`>u2$HWu;qyKd00HF`Am%#3oG3I|_ehfo?+W*pM|G(TOVP)y!8UEt-nAo9z^q-EG zgzpqz!PnNrFogaK&rq`VKOt60#&*K{(0{7_u-iV*rvIOeso<|JLH|WQCqVy&&$;E6 zA9B|Jp0(&7{TKY4r`+^c?E2)a|2Nm6fAo+3i_C!4{DJUDeZjb)azg33NzjGNv|IUq_Ro&XPJ^FVpL+IbRv9n9R zR`-Mcoy!pVcW&&g>ejC9bJzc6jQ=tI$MwG=Ghj6jpnvDKA+-O_jh$89+O<9UcP>Nd z-?_1~OTSk4gZ`b%5c+p+?5yh6uI=sAf8CfNQZv$r703s^^QWeL&Nta}TlzDe|08dh z`NKB-$IU5~alSCtj~zeF!5@JaSD=4~kH48ZEY=eJ56pw*w48iJ7OFKep&obGeR|H&Ix^`DL}zDxgmD#i8>`bYohzqB=)&m4jN(Lee}|K@lG zrWOZ1;#t(9UfL;vU>{ku>1W-dbi=pX%~f6o8O z1N8shmj`J7(LL?I`*ctLAKja}H^nr{-b+S_vVuJ-+g(2_Mbd} z{@tg0+W+F}zInz78M^+clCiE^P89!3*W~mJnaL7M=jD-v_J4by4Ba%PWVkdmvf(JH zY^^P;-xu&L8*h2eH}jgU9m~M;OVPfX57TWqEMEV1u#}H|RCP9>|2)pCf&Sg6eVyyj ze{s$OX#d@*w^Hk0pnvqQ`)joS?#xHwFK+KY4^`*={!+5IzHZs||5qI$fq(jT3OieU zt}WH~(Vu6#-u`WNs^!ilvG(j@3BJ18b?3gN))p6|JmD|5N%(i)DV}|PtAtJa>}Cmn zv|0R5Ele02D>wZQxn>r6bK!VfF*NR|W2$_l+r9WPMD*{@{;8wbC7)Su)6l&`=rQFupMgP`)2#5I4sSKch*mWwql-oMH z=-;{z;Se7>l>zh*yG~`7a$9E?{ag1T9O6T#GJyVJ*QxAMZtLu#f9pPkLwx8|23(^5 z)&-NL`~LH++XJg)#J+7M#k+o{Z1|7PmEk|MZvGd`drq?Me^_aYpL(CZtfUyw&us)= zyCEmOySAPvLvJ{Gz}6ovl`Z8p|Cc%Erq!jlwo1aE-Bwbu4}Woocq+WM%-7^wJF}$f zX6y4vzrRx|>T7KAQ`4MDCFiG(^>b{gn^ldJ^Y-Z9!OumafAWLJ+WbT4AN}k0jrQM~ zj-1*@K>z3;{kv29I_~Hn{iA>MZ|k^}#cM~5|7DqzIREGTpY#8;3^4wmUE9X_e|COy z>Un;ua?}6MvaPk)r^!qIiuONk?oY)$pAY0Z^pF0v9%%muG~uTFP>TB3_akn&ag%J` zyg99f!{LniznuI3Vbv$OZcAoAO`JF}qo2?}`p-)rHOGGQpZ@k|$@DjM>eP%}m$m-Y zebWE+m;cS=CRx6Gc}72>fAo+3opmmtpOZlU?$oVa=O`uF|5tqm+W*YC2>qjdt9bzZ zXVzIM^^2m*g8tDz`cKaQ=l{a_zr}lGtZJ;3x2OH5{nval{+GTTDP;{?DI5An|LEVH z+ShSM|L7n6yIcPwJ}s^JfAkm^ep6Z>X&?GuzAh&}1>amJ{)cA`*!EdcH?C7^4)pcg$Tq3T(JDLZ z(Z7SnE`6(y&xxT@&=O_H+}}v%qXhjw)F%~9)#%niy0xnxg#L5WP%>RPjEM_oIJ9{)%G z=pX&N<~j)acW-~6@xOs~(5-y}^pF0{Jiz(C`|<($NB`*GeY!XMJLn(%qkr@t83Sbe zkMTdo|J*bF_ts@GM zkN(ZEVV32e59t59SMT)y%U|D_aya@&|7ISb|L?whfd0{c&idE$#{KR#3BPwuti5}+ zbZnd}LvEOZ703s}A6%8wHB0o5{&Uv9x=$ed=~f9mxljU6Efl}D$LEXx(K+I+spPs! z0q2lvo;wNs=iA@a72-R0+@P&ZZPRZD?_Z9S+VMk5P9M4S|HFHg{GKVAHf%HkN$Jj ztexAHyZ-$zT%FVP4XwT4>la3}S1kPpe|1Tu4Cp`gIf$K_aMQlff9iI*B=jGZgU~vkX{}R`~8Z(IL|Ci16Kl=Z6YdM$wq5l%s|I4c)`tN<{RB4(WD)=>`Ok6Sk@7#V# z?)twp!liDXO7;0)$DjYJ>jq}~-}}%h(r{`I`p@_Mnl9Qu`Y-YJ|FtzS`fr>SME@?* zXQsZF)$h@N{`Ftk)}XHceK)7;5WzPtiqU`5X<_t_{%vCb{TD$0trqkjHP51P{*V4` zW8Z4qSq|Ihtp7JT|Iar5l@|0LdjDG5f7<)J<-FYWAN%{ijQ^z`1Gc39->#3+zZ(BP zZA9K!$TpwFub0#K|0g%`{7(twHS}NF{r}K!Hw@^1JNl2$J-kod?quT|^zS77_o?>3 zOve9c|4X7DhyER=|8lwi=i?jc|2w(=zh`ZvU&{SI>HA<6&2~PnX{y- zqp>7(YnR`BD-J0wA1gn%E*Mo-KDH}XuG&v2>R+*0)!9&1Y@+`XZwE`@oW3Y|2mKc$ z&!B(wUle_3%4_H!{byo??+e06vGRle>2uXs+eHPi3)L~AOg$r~=j=`Y-Eq=x9AT z?R8Q0Py3(8egW;j)3jKO@)lM9ZaM#_{ippe(d#JapZNHGs#ucUZx>jMhRjM!j{FunC(m00S@p126ys zFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE z00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p z126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ys zFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE z00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p z126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ys zFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE z00S@p126ysFaQIEV8Fv49>4>501w~+Jb(xA03N^tcmNOJ0X%>Q@Bkjb19$)r-~l{< U2k-zMzyo*y58wej;A{{4KR^n?YybcN literal 0 HcmV?d00001 From 7d0b0c4634a14aab26c04f3c70532139d9e6588b Mon Sep 17 00:00:00 2001 From: Runebaas Date: Thu, 14 Sep 2017 22:11:19 +0200 Subject: [PATCH 016/553] Upgraded to dotnet core 2 and small arch restructure --- Geekbot.net/Lib/Dtos/FourChanDto.cs | 20 --- Geekbot.net/Lib/IClients/CatClient.cs | 19 --- Geekbot.net/Lib/IClients/DogClient.cs | 19 --- Geekbot.net/Lib/IClients/RandomClient.cs | 29 ---- Geekbot.net/Lib/IClients/RedisClient.cs | 30 ---- Geekbot.net/Lib/StatsRecorder.cs | 67 ++++---- Geekbot.net/Modules/AdminCmd.cs | 80 +++++----- Geekbot.net/Modules/Cat.cs | 50 +++--- Geekbot.net/Modules/Choose.cs | 45 +++--- Geekbot.net/Modules/Counters.cs | 22 +-- Geekbot.net/Modules/Dog.cs | 50 +++--- Geekbot.net/Modules/EightBall.cs | 9 +- Geekbot.net/Modules/FourChan.cs | 43 ----- Geekbot.net/Modules/GuildInfo.cs | 94 +++++------ Geekbot.net/Modules/Info.cs | 66 ++++---- Geekbot.net/Modules/Roll.cs | 23 +-- Geekbot.net/Modules/Ship.cs | 192 +++++++++++------------ Geekbot.net/Modules/UserInfo.cs | 20 +-- Geekbot.net/Modules/Youtube.cs | 110 ++++++------- Geekbot.net/Program.cs | 41 ++--- 20 files changed, 438 insertions(+), 591 deletions(-) delete mode 100644 Geekbot.net/Lib/Dtos/FourChanDto.cs delete mode 100644 Geekbot.net/Lib/IClients/CatClient.cs delete mode 100644 Geekbot.net/Lib/IClients/DogClient.cs delete mode 100644 Geekbot.net/Lib/IClients/RandomClient.cs delete mode 100644 Geekbot.net/Lib/IClients/RedisClient.cs delete mode 100644 Geekbot.net/Modules/FourChan.cs diff --git a/Geekbot.net/Lib/Dtos/FourChanDto.cs b/Geekbot.net/Lib/Dtos/FourChanDto.cs deleted file mode 100644 index 9d71d8c..0000000 --- a/Geekbot.net/Lib/Dtos/FourChanDto.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Collections.Generic; - -namespace Geekbot.net.Lib.Dtos -{ - class FourChanDto - { - public class BoardList - { - public List Boards { get; set; } - } - - public class Board - { - public string board { get; set; } - public string title { get; set; } - public string ws_board { get; set; } - public string meta_description { get; set; } - } - } -} diff --git a/Geekbot.net/Lib/IClients/CatClient.cs b/Geekbot.net/Lib/IClients/CatClient.cs deleted file mode 100644 index 7a7e8c6..0000000 --- a/Geekbot.net/Lib/IClients/CatClient.cs +++ /dev/null @@ -1,19 +0,0 @@ -using RestSharp; - -namespace Geekbot.net.Lib.IClients -{ - public interface ICatClient - { - IRestClient Client { get; set; } - } - - public class CatClient : ICatClient - { - public CatClient() - { - Client = new RestClient("http://random.cat"); - } - - public IRestClient Client { get; set; } - } -} \ No newline at end of file diff --git a/Geekbot.net/Lib/IClients/DogClient.cs b/Geekbot.net/Lib/IClients/DogClient.cs deleted file mode 100644 index 20feed1..0000000 --- a/Geekbot.net/Lib/IClients/DogClient.cs +++ /dev/null @@ -1,19 +0,0 @@ -using RestSharp; - -namespace Geekbot.net.Lib.IClients -{ - public interface IDogClient - { - IRestClient Client { get; set; } - } - - public class DogClient : IDogClient - { - public DogClient() - { - Client = new RestClient("http://random.dog"); - } - - public IRestClient Client { get; set; } - } -} \ No newline at end of file diff --git a/Geekbot.net/Lib/IClients/RandomClient.cs b/Geekbot.net/Lib/IClients/RandomClient.cs deleted file mode 100644 index b6a3a50..0000000 --- a/Geekbot.net/Lib/IClients/RandomClient.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; - -namespace Geekbot.net.Lib.IClients -{ - - public interface IRandomClient - { - Random Client { get; set; } - } - - public sealed class RandomClient : IRandomClient - { - public RandomClient() - { - try - { - Client = new Random(); - } - catch (Exception) - { - Console.WriteLine("Start Redis pls..."); - Environment.Exit(1); - } - } - - public Random Client { get; set; } - } - -} \ No newline at end of file diff --git a/Geekbot.net/Lib/IClients/RedisClient.cs b/Geekbot.net/Lib/IClients/RedisClient.cs deleted file mode 100644 index 7fc890f..0000000 --- a/Geekbot.net/Lib/IClients/RedisClient.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using StackExchange.Redis; - -namespace Geekbot.net.Lib.IClients -{ - public interface IRedisClient - { - IDatabase Client { get; set; } - } - - public sealed class RedisClient : IRedisClient - { - public RedisClient() - { - try - { - var redis = ConnectionMultiplexer.Connect("127.0.0.1:6379"); - Client = redis.GetDatabase(6); - } - catch (Exception) - { - Console.WriteLine("Start Redis pls..."); - Environment.Exit(1); - } - } - - public IDatabase Client { get; set; } - } -} - diff --git a/Geekbot.net/Lib/StatsRecorder.cs b/Geekbot.net/Lib/StatsRecorder.cs index 8a17ff1..85572fb 100644 --- a/Geekbot.net/Lib/StatsRecorder.cs +++ b/Geekbot.net/Lib/StatsRecorder.cs @@ -1,35 +1,34 @@ -using System; -using System.Threading.Tasks; -using Discord.WebSocket; -using Geekbot.net.Lib.IClients; -using StackExchange.Redis; - -namespace Geekbot.net.Lib -{ - public class StatsRecorder - { - - private readonly SocketMessage message; - private readonly IDatabase redis; - - public StatsRecorder(SocketMessage message, IRedisClient redisClient) - { - this.message = message; - redis = redisClient.Client; - } - - public async Task UpdateUserRecordAsync() - { - var guildId = ((SocketGuildChannel) message.Channel).Guild.Id; - var key = guildId + "-" + message.Author.Id + "-messages"; - await redis.StringIncrementAsync(key); - } - - public async Task UpdateGuildRecordAsync() - { - var guildId = ((SocketGuildChannel) message.Channel).Guild.Id; - var key = guildId + "-messages"; - await redis.StringIncrementAsync(key); - } - } +using System; +using System.Threading.Tasks; +using Discord.WebSocket; +using StackExchange.Redis; + +namespace Geekbot.net.Lib +{ + public class StatsRecorder + { + + private readonly SocketMessage message; + private readonly IDatabase redis; + + public StatsRecorder(SocketMessage message, IDatabase redis) + { + this.message = message; + this.redis = redis; + } + + public async Task UpdateUserRecordAsync() + { + var guildId = ((SocketGuildChannel) message.Channel).Guild.Id; + var key = guildId + "-" + message.Author.Id + "-messages"; + await redis.StringIncrementAsync(key); + } + + public async Task UpdateGuildRecordAsync() + { + var guildId = ((SocketGuildChannel) message.Channel).Guild.Id; + var key = guildId + "-messages"; + await redis.StringIncrementAsync(key); + } + } } \ No newline at end of file diff --git a/Geekbot.net/Modules/AdminCmd.cs b/Geekbot.net/Modules/AdminCmd.cs index b6732af..9385409 100644 --- a/Geekbot.net/Modules/AdminCmd.cs +++ b/Geekbot.net/Modules/AdminCmd.cs @@ -1,41 +1,41 @@ -using System.Threading.Tasks; -using Discord.Commands; -using Geekbot.net.Lib.IClients; - -namespace Geekbot.net.Modules -{ - [Group("admin")] - public class AdminCmd : ModuleBase - { - private readonly IRedisClient redis; - public AdminCmd(IRedisClient redisClient) - { - redis = redisClient; - } - - [RequireUserPermission(Discord.GuildPermission.Administrator)] - [Command("welcome", RunMode = RunMode.Async), Summary("Set a Welcome Message (use '$user' to mention the new joined user).")] - public async Task SetWelcomeMessage([Remainder, Summary("The message")] string welcomeMessage) - { - var key = Context.Guild.Id + "-welcomeMsg"; - redis.Client.StringSet(key, welcomeMessage); - var formatedMessage = welcomeMessage.Replace("$user", Context.User.Mention); - await ReplyAsync("Welcome message has been changed\r\nHere is an example of how it would look:\r\n" + - formatedMessage); - } - - [Command("youtubekey", RunMode = RunMode.Async), Summary("Set the youtube api key")] - public async Task SetYoutubeKey([Summary("API Key")] string key) - { - var botOwner = redis.Client.StringGet("botOwner"); - if (!Context.User.Id.ToString().Equals(botOwner.ToString())) - { - await ReplyAsync($"Sorry, only the botowner can do this ({botOwner}"); - return; - } - - redis.Client.StringSet("youtubeKey", key); - await ReplyAsync("Apikey has been set"); - } - } +using System.Threading.Tasks; +using Discord.Commands; +using StackExchange.Redis; + +namespace Geekbot.net.Modules +{ + [Group("admin")] + public class AdminCmd : ModuleBase + { + private readonly IDatabase redis; + public AdminCmd(IDatabase redis) + { + this.redis = redis; + } + + [RequireUserPermission(Discord.GuildPermission.Administrator)] + [Command("welcome", RunMode = RunMode.Async), Summary("Set a Welcome Message (use '$user' to mention the new joined user).")] + public async Task SetWelcomeMessage([Remainder, Summary("The message")] string welcomeMessage) + { + var key = Context.Guild.Id + "-welcomeMsg"; + redis.StringSet(key, welcomeMessage); + var formatedMessage = welcomeMessage.Replace("$user", Context.User.Mention); + await ReplyAsync("Welcome message has been changed\r\nHere is an example of how it would look:\r\n" + + formatedMessage); + } + + [Command("youtubekey", RunMode = RunMode.Async), Summary("Set the youtube api key")] + public async Task SetYoutubeKey([Summary("API Key")] string key) + { + var botOwner = redis.StringGet("botOwner"); + if (!Context.User.Id.ToString().Equals(botOwner.ToString())) + { + await ReplyAsync($"Sorry, only the botowner can do this ({botOwner}"); + return; + } + + redis.StringSet("youtubeKey", key); + await ReplyAsync("Apikey has been set"); + } + } } \ No newline at end of file diff --git a/Geekbot.net/Modules/Cat.cs b/Geekbot.net/Modules/Cat.cs index 0250e0a..2f9e63e 100644 --- a/Geekbot.net/Modules/Cat.cs +++ b/Geekbot.net/Modules/Cat.cs @@ -1,25 +1,27 @@ -using System.Threading.Tasks; -using Discord.Commands; -using Geekbot.net.Lib.IClients; -using RestSharp; - -namespace Geekbot.net.Modules -{ - public class Cat : ModuleBase - { - private readonly ICatClient catClient; - public Cat(ICatClient catClient) - { - this.catClient = catClient; - } - - [Command("cat", RunMode = RunMode.Async), Summary("Return a random image of a cat.")] - public async Task Say() - { - var request = new RestRequest("meow.php", Method.GET); - - dynamic response = catClient.Client.Execute(request); - await ReplyAsync(response.Data["file"]); - } - } +using System; +using System.Threading.Tasks; +using Discord.Commands; +using RestSharp; + +namespace Geekbot.net.Modules +{ + public class Cat : ModuleBase + { + [Command("cat", RunMode = RunMode.Async), Summary("Return a random image of a cat.")] + public async Task Say() + { + var catClient = new RestClient("http://random.cat"); + var request = new RestRequest("meow.php", Method.GET); + + catClient.ExecuteAsync(request, async response => { + await ReplyAsync(response.Data.file); + }); + } + + } + + public class CatResponse + { + public string file { get; set; } + } } \ No newline at end of file diff --git a/Geekbot.net/Modules/Choose.cs b/Geekbot.net/Modules/Choose.cs index 28a8be2..3242ed5 100644 --- a/Geekbot.net/Modules/Choose.cs +++ b/Geekbot.net/Modules/Choose.cs @@ -1,24 +1,23 @@ -using System; -using System.Threading.Tasks; -using Discord.Commands; -using Geekbot.net.Lib.IClients; - -namespace Geekbot.net.Modules -{ - public class Choose : ModuleBase - { - private readonly IRandomClient rnd; - public Choose(IRandomClient randomClient) - { - rnd = randomClient; - } - - [Command("choose", RunMode = RunMode.Async), Summary("Let the bot make a choice for you.")] - public async Task Command([Remainder, Summary("The choices, sepperated by a ;")] string choices) - { - var choicesArray = choices.Split(';'); - var choice = rnd.Client.Next(choicesArray.Length); - await ReplyAsync($"I choose **{choicesArray[choice]}**"); - } - } +using System; +using System.Threading.Tasks; +using Discord.Commands; + +namespace Geekbot.net.Modules +{ + public class Choose : ModuleBase + { + private readonly Random rnd; + public Choose(Random RandomClient) + { + rnd = RandomClient; + } + + [Command("choose", RunMode = RunMode.Async), Summary("Let the bot make a choice for you.")] + public async Task Command([Remainder, Summary("The choices, sepperated by a ;")] string choices) + { + var choicesArray = choices.Split(';'); + var choice = rnd.Next(choicesArray.Length); + await ReplyAsync($"I choose **{choicesArray[choice]}**"); + } + } } \ No newline at end of file diff --git a/Geekbot.net/Modules/Counters.cs b/Geekbot.net/Modules/Counters.cs index 04f3707..9668ea3 100644 --- a/Geekbot.net/Modules/Counters.cs +++ b/Geekbot.net/Modules/Counters.cs @@ -2,16 +2,16 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib.IClients; +using StackExchange.Redis; namespace Geekbot.net.Modules { public class Counters : ModuleBase { - private readonly IRedisClient redis; - public Counters(IRedisClient redisClient) + private readonly IDatabase redis; + public Counters(IDatabase redis) { - redis = redisClient; + this.redis = redis; } [Command("good", RunMode = RunMode.Async), Summary("Increase Someones Karma")] @@ -29,11 +29,11 @@ namespace Geekbot.net.Modules else { var key = Context.Guild.Id + "-" + user.Id + "-karma"; - var badJokes = (int)redis.Client.StringGet(key); + var badJokes = (int)redis.StringGet(key); var newBadJokes = badJokes + 1; - redis.Client.StringSet(key, newBadJokes.ToString()); + redis.StringSet(key, newBadJokes.ToString()); var lastKey = Context.Guild.Id + "-" + Context.User.Id + "-karma-timeout"; - redis.Client.StringSet(lastKey, GetNewLastKarma()); + redis.StringSet(lastKey, GetNewLastKarma()); var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder() @@ -64,11 +64,11 @@ namespace Geekbot.net.Modules else { var key = Context.Guild.Id + "-" + user.Id + "-karma"; - var badJokes = (int)redis.Client.StringGet(key); + var badJokes = (int)redis.StringGet(key); var newBadJokes = badJokes - 1; - redis.Client.StringSet(key, newBadJokes.ToString()); + redis.StringSet(key, newBadJokes.ToString()); var lastKey = Context.Guild.Id + "-" + Context.User.Id + "-karma-timeout"; - redis.Client.StringSet(lastKey, GetNewLastKarma()); + redis.StringSet(lastKey, GetNewLastKarma()); var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder() @@ -87,7 +87,7 @@ namespace Geekbot.net.Modules private int GetLastKarma() { var lastKey = Context.Guild.Id + "-" + Context.User.Id + "-karma-timeout"; - var redisReturn = redis.Client.StringGet(lastKey); + var redisReturn = redis.StringGet(lastKey); if (!int.TryParse(redisReturn.ToString(), out var i)) { i = GetUnixTimestamp(); diff --git a/Geekbot.net/Modules/Dog.cs b/Geekbot.net/Modules/Dog.cs index 6e98d90..356cd09 100644 --- a/Geekbot.net/Modules/Dog.cs +++ b/Geekbot.net/Modules/Dog.cs @@ -1,25 +1,27 @@ -using System.Threading.Tasks; -using Discord.Commands; -using Geekbot.net.Lib.IClients; -using RestSharp; - -namespace Geekbot.net.Modules -{ - public class Dog : ModuleBase - { - private readonly IDogClient dogClient; - public Dog(IDogClient dogClient) - { - this.dogClient = dogClient; - } - - [Command("dog", RunMode = RunMode.Async), Summary("Return a random image of a dog.")] - public async Task Say() - { - var request = new RestRequest("woof.json", Method.GET); - - dynamic response = dogClient.Client.Execute(request); - await ReplyAsync(response.Data["url"]); - } - } +using System; +using System.Threading.Tasks; +using Discord.Commands; +using RestSharp; + +namespace Geekbot.net.Modules +{ + public class Dog : ModuleBase + { + [Command("dog", RunMode = RunMode.Async), Summary("Return a random image of a dog.")] + public async Task Say() + { + var dogClient = new RestClient("http://random.dog"); + var request = new RestRequest("woof.json", Method.GET); + Console.WriteLine(dogClient.BaseUrl); + + dogClient.ExecuteAsync(request, async response => { + await ReplyAsync(response.Data.url); + }); + } + } + + public class DogResponse + { + public string url { get; set; } + } } \ No newline at end of file diff --git a/Geekbot.net/Modules/EightBall.cs b/Geekbot.net/Modules/EightBall.cs index 2d93c1b..efce699 100644 --- a/Geekbot.net/Modules/EightBall.cs +++ b/Geekbot.net/Modules/EightBall.cs @@ -2,16 +2,15 @@ using System.Collections.Generic; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib.IClients; namespace Geekbot.net.Modules { public class EightBall : ModuleBase { - private readonly IRandomClient rnd; - public EightBall(IRandomClient randomClient) + private readonly Random rnd; + public EightBall(Random RandomClient) { - rnd = randomClient; + rnd = RandomClient; } [Command("8ball", RunMode = RunMode.Async), Summary("Ask 8Ball a Question.")] public async Task Ball([Remainder, Summary("The Question")] string echo) @@ -38,7 +37,7 @@ namespace Geekbot.net.Modules "Outlook not so good", "Very doubtful"}; - var answer = rnd.Client.Next(replies.Count); + var answer = rnd.Next(replies.Count); await ReplyAsync(replies[answer]); } } diff --git a/Geekbot.net/Modules/FourChan.cs b/Geekbot.net/Modules/FourChan.cs deleted file mode 100644 index 3cdf036..0000000 --- a/Geekbot.net/Modules/FourChan.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Discord.Commands; -using static Geekbot.net.Lib.Dtos.FourChanDto; -using Geekbot.net.Lib.IClients; - -namespace Geekbot.net.Modules -{ - public class FourChan : ModuleBase - { - [Command("4chan", RunMode = RunMode.Async), Summary("Get Something from 4chan")] - public async Task Chan([Summary("The someone")] string boardParam) - { - try - { - var boards = FourChanBoardClient.Boards(); - var board = new Board(); - foreach (var b in boards.getBoards()) - { - if (b.board.Equals(boardParam)) - { - board = b; - break; - } - } - if (board.board == boardParam) - { - await ReplyAsync($"{board.title} - {board.meta_description}"); - } else - { - await ReplyAsync("Sorry, that board does not exist..."); - } - } - catch (Exception e) - { - await ReplyAsync(e.Message); - } - } - } -} - -// var boards = new List["a", "b", "c", "d", "e", "f", "g", "gif", "h", "hr", "k", "m", "o", "p", "r", "s", "t", "u", "v", "vg", "vr", "w", "wg", "i", "ic", "r9k", "s4s", "cm", "hm", "lgbt", "y", "3", "aco", "adv", "an", "asp", "biz", "cgl", "ck", "co", "diy", "fa", "fit", "gd", "hc", "his", "int", "jp", "lit", "mlp", "mu", "n", "news", "out", "po", "pol", "qst", "sci", "soc" / sp / tg / toy / trv / tv / vp / wsg / wsr /]; diff --git a/Geekbot.net/Modules/GuildInfo.cs b/Geekbot.net/Modules/GuildInfo.cs index 9a03373..6c357e5 100644 --- a/Geekbot.net/Modules/GuildInfo.cs +++ b/Geekbot.net/Modules/GuildInfo.cs @@ -1,48 +1,48 @@ -using System; -using System.Threading.Tasks; -using Discord.Commands; -using Discord; -using Geekbot.net.Lib; -using System.Linq; -using Geekbot.net.Lib.IClients; - -namespace Geekbot.net.Modules -{ - public class GuildInfo : ModuleBase - { - private readonly IRedisClient redis; - public GuildInfo(IRedisClient redisClient) - { - redis = redisClient; - } - - [Command("serverstats", RunMode = RunMode.Async), Summary("Show some info about the bot.")] - public async Task getInfo() - { - var eb = new EmbedBuilder(); - eb.WithAuthor(new EmbedAuthorBuilder() - .WithIconUrl(Context.Guild.IconUrl) - .WithName(Context.Guild.Name)); - eb.WithColor(new Color(110, 204, 147)); - - var created = Context.Guild.CreatedAt; - var age = Math.Floor((DateTime.Now - created).TotalDays); - - var messages = redis.Client.StringGet($"{Context.Guild.Id}-messages"); - var level = LevelCalc.GetLevelAtExperience((int)messages); - - eb.AddField("Server Age", $"{created.Day}/{created.Month}/{created.Year} ({age} days)"); - eb.AddInlineField("Level", level) - .AddInlineField("Messages", messages); - - await ReplyAsync("", false, eb.Build()); - } - - public static string FirstCharToUpper(string input) - { - if (String.IsNullOrEmpty(input)) - throw new ArgumentException("ARGH!"); - return input.First().ToString().ToUpper() + input.Substring(1); - } - } +using System; +using System.Threading.Tasks; +using Discord.Commands; +using Discord; +using Geekbot.net.Lib; +using System.Linq; +using StackExchange.Redis; + +namespace Geekbot.net.Modules +{ + public class GuildInfo : ModuleBase + { + private readonly IDatabase redis; + public GuildInfo(IDatabase redis) + { + this.redis = redis; + } + + [Command("serverstats", RunMode = RunMode.Async), Summary("Show some info about the bot.")] + public async Task getInfo() + { + var eb = new EmbedBuilder(); + eb.WithAuthor(new EmbedAuthorBuilder() + .WithIconUrl(Context.Guild.IconUrl) + .WithName(Context.Guild.Name)); + eb.WithColor(new Color(110, 204, 147)); + + var created = Context.Guild.CreatedAt; + var age = Math.Floor((DateTime.Now - created).TotalDays); + + var messages = redis.StringGet($"{Context.Guild.Id}-messages"); + var level = LevelCalc.GetLevelAtExperience((int)messages); + + eb.AddField("Server Age", $"{created.Day}/{created.Month}/{created.Year} ({age} days)"); + eb.AddInlineField("Level", level) + .AddInlineField("Messages", messages); + + await ReplyAsync("", false, eb.Build()); + } + + public static string FirstCharToUpper(string input) + { + if (String.IsNullOrEmpty(input)) + throw new ArgumentException("ARGH!"); + return input.First().ToString().ToUpper() + input.Substring(1); + } + } } \ No newline at end of file diff --git a/Geekbot.net/Modules/Info.cs b/Geekbot.net/Modules/Info.cs index a31fec9..73e04fc 100644 --- a/Geekbot.net/Modules/Info.cs +++ b/Geekbot.net/Modules/Info.cs @@ -1,34 +1,34 @@ -using System.Threading.Tasks; -using Discord; -using Discord.Commands; -using Geekbot.net.Lib.IClients; - -namespace Geekbot.net.Modules -{ - public class Info : ModuleBase - { - private readonly IRedisClient redis; - public Info(IRedisClient redisClient) - { - redis = redisClient; - } - - [Command("info", RunMode = RunMode.Async), Summary("Get Information about the bot")] - public async Task BotInfo() - { - var eb = new EmbedBuilder(); - - eb.WithTitle("Geekbot V3"); - - var botOwner = Context.Guild.GetUserAsync(ulong.Parse(redis.Client.StringGet("botOwner"))).Result; - - eb.AddInlineField("Status", Context.Client.ConnectionState.ToString()) - .AddInlineField("Bot Name", Context.Client.CurrentUser.Username) - .AddInlineField("Bot Owner", $"{botOwner.Username}#{botOwner.Discriminator}"); - - eb.AddInlineField("Servers", Context.Client.GetGuildsAsync().Result.Count); - - await ReplyAsync("", false, eb.Build()); - } - } +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using StackExchange.Redis; + +namespace Geekbot.net.Modules +{ + public class Info : ModuleBase + { + private readonly IDatabase redis; + public Info(IDatabase redis) + { + this.redis = redis; + } + + [Command("info", RunMode = RunMode.Async), Summary("Get Information about the bot")] + public async Task BotInfo() + { + var eb = new EmbedBuilder(); + + eb.WithTitle("Geekbot V3.1"); + + var botOwner = Context.Guild.GetUserAsync(ulong.Parse(redis.StringGet("botOwner"))).Result; + + eb.AddInlineField("Status", Context.Client.ConnectionState.ToString()) + .AddInlineField("Bot Name", Context.Client.CurrentUser.Username) + .AddInlineField("Bot Owner", $"{botOwner.Username}#{botOwner.Discriminator}"); + + eb.AddInlineField("Servers", Context.Client.GetGuildsAsync().Result.Count); + + await ReplyAsync("", false, eb.Build()); + } + } } \ No newline at end of file diff --git a/Geekbot.net/Modules/Roll.cs b/Geekbot.net/Modules/Roll.cs index 6331d22..b953859 100644 --- a/Geekbot.net/Modules/Roll.cs +++ b/Geekbot.net/Modules/Roll.cs @@ -1,24 +1,25 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using Discord.Commands; using Geekbot.net.Lib; -using Geekbot.net.Lib.IClients; +using StackExchange.Redis; namespace Geekbot.net.Modules { public class Roll : ModuleBase { - private readonly IRedisClient redis; - private readonly IRandomClient rnd; - public Roll(IRedisClient redisClient, IRandomClient randomClient) + private readonly IDatabase redis; + private readonly Random rnd; + public Roll(IDatabase redis, Random RandomClient) { - redis = redisClient; - rnd = randomClient; + this.redis = redis; + this.rnd = RandomClient; } [Command("roll", RunMode = RunMode.Async), Summary("Roll a number between 1 and 100.")] public async Task RollCommand([Remainder, Summary("stuff...")] string stuff = "nothing") { - var number = rnd.Client.Next(1, 100); + var number = rnd.Next(1, 100); var guess = 1000; int.TryParse(stuff, out guess); if (guess <= 100 && guess > 0) @@ -28,8 +29,8 @@ namespace Geekbot.net.Modules { await ReplyAsync($"Congratulations {Context.User.Username}, your guess was correct!"); var key = $"{Context.Guild.Id}-{Context.User.Id}-correctRolls"; - var messages = (int)redis.Client.StringGet(key); - redis.Client.StringSet(key, (messages + 1).ToString()); + var messages = (int)redis.StringGet(key); + redis.StringSet(key, (messages + 1).ToString()); } } else @@ -41,7 +42,7 @@ namespace Geekbot.net.Modules [Command("dice", RunMode = RunMode.Async), Summary("Roll a dice")] public async Task DiceCommand([Summary("The highest number on the dice")] int max = 6) { - var number = rnd.Client.Next(1, max); + var number = rnd.Next(1, max); await ReplyAsync(Context.Message.Author.Mention + ", you rolled " + number); } } diff --git a/Geekbot.net/Modules/Ship.cs b/Geekbot.net/Modules/Ship.cs index f22ed1b..2049580 100644 --- a/Geekbot.net/Modules/Ship.cs +++ b/Geekbot.net/Modules/Ship.cs @@ -1,97 +1,97 @@ -using System; -using System.Threading.Tasks; -using Discord; -using Discord.Commands; -using Geekbot.net.Lib.IClients; - -namespace Geekbot.net.Modules -{ - public class Ship : ModuleBase - { - - private readonly IRedisClient redis; - private readonly IRandomClient rnd; - public Ship(IRedisClient redisClient, IRandomClient randomClient) - { - redis = redisClient; - rnd = randomClient; - } - - [Command("Ship", RunMode = RunMode.Async), Summary("Ask the Shipping meter")] - public async Task Command([Summary("User 1")] IUser user1, [Summary("User 2")] IUser user2) - { - // Create a String - var dbstring = ""; - if (user1.Id > user2.Id) - { - dbstring = $"{user1.Id}-{user2.Id}"; - } - else - { - dbstring = $"{user2.Id}-{user1.Id}"; - } - dbstring = $"{Context.Guild.Id}-{dbstring}"; - Console.WriteLine(dbstring); - - var dbval = redis.Client.StringGet(dbstring); - var shippingRate = 0; - if (dbval.IsNullOrEmpty) - { - shippingRate = rnd.Client.Next(1, 100); - redis.Client.StringSet(dbstring, shippingRate); - } - else - { - shippingRate = int.Parse(dbval.ToString()); - } - - var reply = ":heartpulse: **Matchmaking** :heartpulse:\r\n"; - reply = reply + $":two_hearts: {user1.Mention} :heart: {user2.Mention} :two_hearts:\r\n"; - reply = reply + $"0% [{BlockCounter(shippingRate)}] 100% - {DeterminateSuccess(shippingRate)}"; - await ReplyAsync(reply); - } - - private string DeterminateSuccess(int rate) - { - if (rate < 20) - { - return "Not gonna happen"; - } if (rate >= 20 && rate < 40) - { - return "Not such a good idea"; - } if (rate >= 40 && rate < 60) - { - return "There might be a chance"; - } if (rate >= 60 && rate < 80) - { - return "Almost a match, but could work"; - } if (rate >= 80) - { - return "It's a match"; - } - return "a"; - } - - private string BlockCounter(int rate) - { - var amount = Math.Floor(decimal.Floor(rate / 10)); - Console.WriteLine(amount); - var blocks = ""; - for(int i = 1; i <= 10; i++) - { - if(i <= amount) - { - blocks = blocks + ":white_medium_small_square:"; - if(i == amount) - { - blocks = blocks + $" {rate}% "; - } - } else - { - blocks = blocks + ":black_medium_small_square:"; - } - } - return blocks; - } - } +using System; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using StackExchange.Redis; + +namespace Geekbot.net.Modules +{ + public class Ship : ModuleBase + { + + private readonly IDatabase redis; + private readonly Random rnd; + public Ship(IDatabase redis, Random RandomClient) + { + this.redis = redis; + this.rnd = RandomClient; + } + + [Command("Ship", RunMode = RunMode.Async), Summary("Ask the Shipping meter")] + public async Task Command([Summary("User 1")] IUser user1, [Summary("User 2")] IUser user2) + { + // Create a String + var dbstring = ""; + if (user1.Id > user2.Id) + { + dbstring = $"{user1.Id}-{user2.Id}"; + } + else + { + dbstring = $"{user2.Id}-{user1.Id}"; + } + dbstring = $"{Context.Guild.Id}-{dbstring}"; + Console.WriteLine(dbstring); + + var dbval = redis.StringGet(dbstring); + var shippingRate = 0; + if (dbval.IsNullOrEmpty) + { + shippingRate = rnd.Next(1, 100); + redis.StringSet(dbstring, shippingRate); + } + else + { + shippingRate = int.Parse(dbval.ToString()); + } + + var reply = ":heartpulse: **Matchmaking** :heartpulse:\r\n"; + reply = reply + $":two_hearts: {user1.Mention} :heart: {user2.Mention} :two_hearts:\r\n"; + reply = reply + $"0% [{BlockCounter(shippingRate)}] 100% - {DeterminateSuccess(shippingRate)}"; + await ReplyAsync(reply); + } + + private string DeterminateSuccess(int rate) + { + if (rate < 20) + { + return "Not gonna happen"; + } if (rate >= 20 && rate < 40) + { + return "Not such a good idea"; + } if (rate >= 40 && rate < 60) + { + return "There might be a chance"; + } if (rate >= 60 && rate < 80) + { + return "Almost a match, but could work"; + } if (rate >= 80) + { + return "It's a match"; + } + return "a"; + } + + private string BlockCounter(int rate) + { + var amount = Math.Floor(decimal.Floor(rate / 10)); + Console.WriteLine(amount); + var blocks = ""; + for(int i = 1; i <= 10; i++) + { + if(i <= amount) + { + blocks = blocks + ":white_medium_small_square:"; + if(i == amount) + { + blocks = blocks + $" {rate}% "; + } + } else + { + blocks = blocks + ":black_medium_small_square:"; + } + } + return blocks; + } + } } \ No newline at end of file diff --git a/Geekbot.net/Modules/UserInfo.cs b/Geekbot.net/Modules/UserInfo.cs index 2dbb827..dd57ad6 100644 --- a/Geekbot.net/Modules/UserInfo.cs +++ b/Geekbot.net/Modules/UserInfo.cs @@ -6,16 +6,16 @@ using System.Linq; using Discord; using Discord.Commands; using Geekbot.net.Lib; -using Geekbot.net.Lib.IClients; +using StackExchange.Redis; namespace Geekbot.net.Modules { public class UserInfo : ModuleBase { - private readonly IRedisClient redis; - public UserInfo(IRedisClient redisClient) + private readonly IDatabase redis; + public UserInfo(IDatabase redis) { - redis = redisClient; + this.redis = redis; } [Alias("stats")] @@ -27,11 +27,11 @@ namespace Geekbot.net.Modules var age = Math.Floor((DateTime.Now - userInfo.CreatedAt).TotalDays); var key = Context.Guild.Id + "-" + userInfo.Id; - var messages = (int)redis.Client.StringGet(key + "-messages"); + var messages = (int)redis.StringGet(key + "-messages"); var level = LevelCalc.GetLevelAtExperience(messages); var guildKey = Context.Guild.Id.ToString(); - var guildMessages = (int)redis.Client.StringGet(guildKey + "-messages"); + var guildMessages = (int)redis.StringGet(guildKey + "-messages"); var percent = Math.Round((double)(100 * messages) / guildMessages, 2); @@ -47,13 +47,13 @@ namespace Geekbot.net.Modules .AddInlineField("Messages Sent", messages) .AddInlineField("Server Total", $"{percent}%"); - var karma = redis.Client.StringGet(key + "-karma"); + var karma = redis.StringGet(key + "-karma"); if (!karma.IsNullOrEmpty) { eb.AddInlineField("Karma", karma); } - var correctRolls = redis.Client.StringGet($"{Context.Guild.Id}-{userInfo.Id}-correctRolls"); + var correctRolls = redis.StringGet($"{Context.Guild.Id}-{userInfo.Id}-correctRolls"); if (!correctRolls.IsNullOrEmpty) { eb.AddInlineField("Guessed Rolls", correctRolls); @@ -68,13 +68,13 @@ namespace Geekbot.net.Modules { await ReplyAsync("this will take a moment..."); var guildKey = Context.Guild.Id.ToString(); - var guildMessages = (int)redis.Client.StringGet(guildKey + "-messages"); + var guildMessages = (int)redis.StringGet(guildKey + "-messages"); var allGuildUsers = await Context.Guild.GetUsersAsync(); var unsortedDict = new Dictionary(); foreach(var user in allGuildUsers) { var key = Context.Guild.Id + "-" + user.Id; - var messages = (int)redis.Client.StringGet(key + "-messages"); + var messages = (int)redis.StringGet(key + "-messages"); if(messages > 0) { unsortedDict.Add($"{user.Username}#{user.Discriminator}", messages); } diff --git a/Geekbot.net/Modules/Youtube.cs b/Geekbot.net/Modules/Youtube.cs index 723ea9a..3127ff4 100644 --- a/Geekbot.net/Modules/Youtube.cs +++ b/Geekbot.net/Modules/Youtube.cs @@ -1,56 +1,56 @@ -using System; -using System.Threading.Tasks; -using Discord.Commands; -using Geekbot.net.Lib.IClients; -using Google.Apis.Services; -using Google.Apis.YouTube.v3; - -namespace Geekbot.net.Modules -{ - public class Youtube : ModuleBase - { - private readonly IRedisClient redis; - public Youtube(IRedisClient redisClient) - { - redis = redisClient; - } - - [Command("yt", RunMode = RunMode.Async), Summary("Search for something on youtube.")] - public async Task Yt([Remainder, Summary("A Song Title")] string searchQuery) - { - var key = redis.Client.StringGet("youtubeKey"); - if (key.IsNullOrEmpty) - { - await ReplyAsync("No youtube key set, please tell my senpai to set one"); - return; - } - - try - { - var youtubeService = new YouTubeService(new BaseClientService.Initializer() - { - ApiKey = key.ToString(), - ApplicationName = this.GetType().ToString() - }); - - var searchListRequest = youtubeService.Search.List("snippet"); - searchListRequest.Q = searchQuery; - searchListRequest.MaxResults = 2; - - var searchListResponse = await searchListRequest.ExecuteAsync(); - - var result = searchListResponse.Items[0]; - - await ReplyAsync( - $"\"{result.Snippet.Title}\" from \"{result.Snippet.ChannelTitle}\" https://youtu.be/{result.Id.VideoId}"); - } - catch (Exception e) - { - await ReplyAsync("Something went wrong... informing my senpai..."); - var botOwner = Context.Guild.GetUserAsync(ulong.Parse(redis.Client.StringGet("botOwner"))).Result; - var dm = await botOwner.CreateDMChannelAsync(); - await dm.SendMessageAsync($"Something went wrong while getting a video from youtube:\r\n```\r\n{e.Message}\r\n```"); - } - } - } +using System; +using System.Threading.Tasks; +using Discord.Commands; +using Google.Apis.Services; +using Google.Apis.YouTube.v3; +using StackExchange.Redis; + +namespace Geekbot.net.Modules +{ + public class Youtube : ModuleBase + { + private readonly IDatabase redis; + public Youtube(IDatabase redis) + { + this.redis = redis; + } + + [Command("yt", RunMode = RunMode.Async), Summary("Search for something on youtube.")] + public async Task Yt([Remainder, Summary("A Song Title")] string searchQuery) + { + var key = redis.StringGet("youtubeKey"); + if (key.IsNullOrEmpty) + { + await ReplyAsync("No youtube key set, please tell my senpai to set one"); + return; + } + + try + { + var youtubeService = new YouTubeService(new BaseClientService.Initializer() + { + ApiKey = key.ToString(), + ApplicationName = this.GetType().ToString() + }); + + var searchListRequest = youtubeService.Search.List("snippet"); + searchListRequest.Q = searchQuery; + searchListRequest.MaxResults = 2; + + var searchListResponse = await searchListRequest.ExecuteAsync(); + + var result = searchListResponse.Items[0]; + + await ReplyAsync( + $"\"{result.Snippet.Title}\" from \"{result.Snippet.ChannelTitle}\" https://youtu.be/{result.Id.VideoId}"); + } + catch (Exception e) + { + await ReplyAsync("Something went wrong... informing my senpai..."); + var botOwner = Context.Guild.GetUserAsync(ulong.Parse(redis.StringGet("botOwner"))).Result; + var dm = await botOwner.GetOrCreateDMChannelAsync(); + await dm.SendMessageAsync($"Something went wrong while getting a video from youtube:\r\n```\r\n{e.Message}\r\n```"); + } + } + } } \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index c5e31f1..a62f0ee 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -1,6 +1,5 @@ using System; using System.Reflection; -using System.Runtime.InteropServices.ComTypes; using System.Threading.Tasks; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -10,8 +9,8 @@ using Discord; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Lib; -using Geekbot.net.Lib.IClients; using Geekbot.net.Modules; +using RestSharp; using StackExchange.Redis; namespace Geekbot.net @@ -20,9 +19,10 @@ namespace Geekbot.net { private CommandService commands; private DiscordSocketClient client; - private IRedisClient redis; + private IDatabase redis; private RedisValue token; - private ServiceCollection services; + private IServiceCollection services; + private IServiceProvider servicesProvider; private static void Main(string[] args) { @@ -41,25 +41,34 @@ namespace Geekbot.net { client = new DiscordSocketClient(); commands = new CommandService(); - redis = new RedisClient(); - token = redis.Client.StringGet("discordToken"); + try + { + var redisMultiplexer = ConnectionMultiplexer.Connect("127.0.0.1:6379"); + redis = redisMultiplexer.GetDatabase(6); + } + catch (Exception) + { + Console.WriteLine("Start Redis pls..."); + Environment.Exit(1); + } + + token = redis.StringGet("discordToken"); if (token.IsNullOrEmpty) { Console.Write("Your bot Token: "); var newToken = Console.ReadLine(); - redis.Client.StringSet("discordToken", newToken); + redis.StringSet("discordToken", newToken); token = newToken; Console.Write("Bot Owner User ID: "); var ownerId = Console.ReadLine(); - redis.Client.StringSet("botOwner", ownerId); + redis.StringSet("botOwner", ownerId); } services = new ServiceCollection(); - services.AddSingleton(new CatClient()); - services.AddSingleton(new DogClient()); - services.AddSingleton(new RandomClient()); + var RandomClient = new Random(); + services.AddSingleton(RandomClient); services.AddSingleton(redis); Console.WriteLine("Connecting to Discord..."); @@ -87,6 +96,7 @@ namespace Geekbot.net client.MessageReceived += HandleMessageReceived; client.UserJoined += HandleUserJoined; await commands.AddModulesAsync(Assembly.GetEntryAssembly()); + servicesProvider = services.BuildServiceProvider(); Console.WriteLine("Done and ready for use...\n"); } @@ -124,14 +134,9 @@ namespace Geekbot.net await message.Channel.SendMessageAsync("hui!!!"); return; } - // if (message.ToString().ToLower().Contains("teamspeak") || message.ToString().ToLower().Contains("skype")) - // { - // await message.Channel.SendMessageAsync("How dare you to use such a filthy word in here http://bit.ly/2poL2IZ"); - // return; - // } if (!(message.HasCharPrefix('!', ref argPos) || message.HasMentionPrefix(client.CurrentUser, ref argPos))) return; var context = new CommandContext(client, message); - Task.Run(async () => await commands.ExecuteAsync(context, argPos, services)); + Task.Run(async () => await commands.ExecuteAsync(context, argPos, servicesProvider)); } public async Task HandleMessageReceived(SocketMessage messsageParam) @@ -152,7 +157,7 @@ namespace Geekbot.net { if (!user.IsBot) { - var message = redis.Client.StringGet(user.Guild.Id + "-welcomeMsg"); + var message = redis.StringGet(user.Guild.Id + "-welcomeMsg"); if (!message.IsNullOrEmpty) { message = message.ToString().Replace("$user", user.Mention); From a004ab4290061600231e14d48152bb202518357e Mon Sep 17 00:00:00 2001 From: Runebaas Date: Thu, 14 Sep 2017 22:20:28 +0200 Subject: [PATCH 017/553] Small Async fix --- Geekbot.net/Program.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index a62f0ee..7b000a3 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -149,8 +149,8 @@ namespace Geekbot.net Console.WriteLine(channel.Guild.Name + " - " + message.Channel + " - " + message.Author.Username + " - " + message.Content); var statsRecorder = new StatsRecorder(message, redis); - Task.Run(() => statsRecorder.UpdateUserRecordAsync()); - Task.Run(() => statsRecorder.UpdateGuildRecordAsync()); + Task.Run(async () => await statsRecorder.UpdateUserRecordAsync()); + Task.Run(async () => await statsRecorder.UpdateGuildRecordAsync()); } public async Task HandleUserJoined(SocketGuildUser user) From 40bbef9cd8308bea483b0b32dc08060dc122f510 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Fri, 15 Sep 2017 00:01:00 +0200 Subject: [PATCH 018/553] Adding Dice Command --- Geekbot.net/Modules/Dice.cs | 54 +++++++++++++++++++++++++++++++++++++ Geekbot.net/Modules/Roll.cs | 8 ------ 2 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 Geekbot.net/Modules/Dice.cs diff --git a/Geekbot.net/Modules/Dice.cs b/Geekbot.net/Modules/Dice.cs new file mode 100644 index 0000000..b559446 --- /dev/null +++ b/Geekbot.net/Modules/Dice.cs @@ -0,0 +1,54 @@ +using System; +using System.Text; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using StackExchange.Redis; + +namespace Geekbot.net.Modules +{ + public class Dice : ModuleBase + { + private readonly Random rnd; + public Dice(Random RandomClient) + { + rnd = RandomClient; + } + + [Command("dice", RunMode = RunMode.Async), Summary("Roll a dice.")] + public async Task RollCommand([Remainder, Summary("1d20, 1d6, 2d3, etc...")] string diceType = "1d6") + { + var dice = diceType.Split("d"); + + if (dice.Length != 2 + || !int.TryParse(dice[0], out int times) + || !int.TryParse(dice[1], out int max)) + { + await ReplyAsync("That is not a valid dice, examples are: 1d20, 1d6, 2d10, 5d12, etc..."); + return; + } + Console.WriteLine($"Max: {max} - Times {times}"); + if (times > 10 && !(times < 0)) + { + await ReplyAsync("You can only roll between 1 and 10 dices"); + return; + } + if (max > 100 && !(max < 1)) + { + await ReplyAsync("The dice must have between 1 and 100 sides"); + return; + } + var eb = new EmbedBuilder(); + eb.WithAuthor(new EmbedAuthorBuilder() + .WithIconUrl(Context.User.GetAvatarUrl()) + .WithName(Context.User.Username)); + eb.WithColor(new Color(133, 189, 219)); + eb.Title = $":game_die: Dice Roll - Type {diceType} :game_die:"; + for (var i = 0; i < times; i++) + { + eb.AddInlineField($"Dice {i+1}", rnd.Next(1, max)); + } + await ReplyAsync("", false, eb.Build()); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Modules/Roll.cs b/Geekbot.net/Modules/Roll.cs index b953859..1c8755d 100644 --- a/Geekbot.net/Modules/Roll.cs +++ b/Geekbot.net/Modules/Roll.cs @@ -1,7 +1,6 @@ using System; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib; using StackExchange.Redis; namespace Geekbot.net.Modules @@ -38,12 +37,5 @@ namespace Geekbot.net.Modules await ReplyAsync(Context.Message.Author.Mention + ", you rolled " + number); } } - - [Command("dice", RunMode = RunMode.Async), Summary("Roll a dice")] - public async Task DiceCommand([Summary("The highest number on the dice")] int max = 6) - { - var number = rnd.Next(1, max); - await ReplyAsync(Context.Message.Author.Mention + ", you rolled " + number); - } } } \ No newline at end of file From 35064cf90bbeaf80f7b37ccf14644a54206617f6 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Fri, 15 Sep 2017 00:31:13 +0200 Subject: [PATCH 019/553] Adding Fortunes --- Geekbot.net/Lib/Fortunes.cs | 48 + Geekbot.net/Modules/Fortune.cs | 22 + Geekbot.net/Program.cs | 13 +- Geekbot.net/fortunes | 9760 ++++++++++++++++++++++++++++++++ derp.ico | Bin 370070 -> 0 bytes 5 files changed, 9838 insertions(+), 5 deletions(-) create mode 100644 Geekbot.net/Lib/Fortunes.cs create mode 100644 Geekbot.net/Modules/Fortune.cs create mode 100644 Geekbot.net/fortunes delete mode 100644 derp.ico diff --git a/Geekbot.net/Lib/Fortunes.cs b/Geekbot.net/Lib/Fortunes.cs new file mode 100644 index 0000000..15cc710 --- /dev/null +++ b/Geekbot.net/Lib/Fortunes.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; + +namespace Geekbot.net.Lib +{ + class Fortunes : IFortunes + { + private string[] fortuneArray; + private int totalFortunes; + private Random rnd; + + public Fortunes() + { + var path = Path.GetFullPath("./fortunes"); + if (File.Exists(path)) + { + var rawFortunes= File.ReadAllText(path); + fortuneArray = rawFortunes.Split("%"); + totalFortunes = fortuneArray.Length; + rnd = new Random(); + } + else + { + Console.WriteLine("Fortunes File not found"); + Console.WriteLine($"Path should be {path}"); + } + } + + public string GetRandomFortune() + { + return fortuneArray[rnd.Next(0, totalFortunes)]; + } + + public string GetFortune(int id) + { + return fortuneArray[id]; + } + } + + public interface IFortunes + { + string GetRandomFortune(); + string GetFortune(int id); + } +} diff --git a/Geekbot.net/Modules/Fortune.cs b/Geekbot.net/Modules/Fortune.cs new file mode 100644 index 0000000..c898750 --- /dev/null +++ b/Geekbot.net/Modules/Fortune.cs @@ -0,0 +1,22 @@ +using System; +using System.Threading.Tasks; +using Discord.Commands; +using Geekbot.net.Lib; + +namespace Geekbot.net.Modules +{ + public class Fortune : ModuleBase + { + private readonly IFortunes fortunes; + public Fortune(IFortunes fortunes) + { + this.fortunes = fortunes; + } + + [Command("fortune", RunMode = RunMode.Async), Summary("Get a random fortune")] + public async Task GetAFortune() + { + await ReplyAsync(fortunes.GetRandomFortune()); + } + } +} diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 7b000a3..63cebad 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -32,13 +32,14 @@ namespace Geekbot.net Console.WriteLine(@"| |_| | |___| |___| . \| |_) | |_| || |"); Console.WriteLine(@" \____|_____|_____|_|\_\____/ \___/ |_|"); Console.WriteLine("========================================="); - Console.WriteLine("Starting..."); + Console.WriteLine("* Starting..."); new Program().MainAsync().GetAwaiter().GetResult(); } public async Task MainAsync() { + Console.WriteLine("* Initing Stuff"); client = new DiscordSocketClient(); commands = new CommandService(); @@ -67,11 +68,13 @@ namespace Geekbot.net } services = new ServiceCollection(); + var fortunes = new Fortunes(); var RandomClient = new Random(); + services.AddSingleton(fortunes); services.AddSingleton(RandomClient); services.AddSingleton(redis); - Console.WriteLine("Connecting to Discord..."); + Console.WriteLine("* Connecting to Discord"); await Login(); @@ -88,9 +91,9 @@ namespace Geekbot.net if (isConneted) { await client.SetGameAsync("Ping Pong"); - Console.WriteLine($"Now Connected to {client.Guilds.Count} Servers"); + Console.WriteLine($"* Now Connected to {client.Guilds.Count} Servers"); - Console.WriteLine("Registering Stuff"); + Console.WriteLine("* Registering Stuff"); client.MessageReceived += HandleCommand; client.MessageReceived += HandleMessageReceived; @@ -98,7 +101,7 @@ namespace Geekbot.net await commands.AddModulesAsync(Assembly.GetEntryAssembly()); servicesProvider = services.BuildServiceProvider(); - Console.WriteLine("Done and ready for use...\n"); + Console.WriteLine("* Done and ready for use\n"); } } catch (AggregateException) diff --git a/Geekbot.net/fortunes b/Geekbot.net/fortunes new file mode 100644 index 0000000..49a6171 --- /dev/null +++ b/Geekbot.net/fortunes @@ -0,0 +1,9760 @@ +% +"... the educated person is not the person who can answer the questions, but +the person who can question the answers." + ― Theodore Schick Jr., in The_Skeptical_Inquirer, March/April, 1997 +% +"A little fire, Scarecrow?" +% +"A programmer is a person who passes as an exacting expert on the basis of +being able to turn out, after innumerable punching, an infinite series of +incomprehensive answers calculated with micrometric precisions from vague +assumptions based on debatable figures taken from inconclusive documents +and carried out on instruments of problematical accuracy by persons of +dubious reliability and questionable mentality for the avowed purpose of +annoying and confounding a hopelessly defenseless department that was +unfortunate enough to ask for the information in the first place." + ― IEEE Grid newsmagazine +% +"Acting is an art which consists of keeping the audience from coughing." +% +"Anchovies? You've got the wrong man! I spell my name DANGER! (click)" +% +"Benson, you are so free of the ravages of intelligence." + ― Time Bandits +% +"Beware of the man who works hard to learn something, learns it, and finds +himself no wiser than before," Bokonon tells us. "He is full of murderous +resentment of people who are ignorant without having come by their +ignorance the hard way." + ― Kurt Vonnegut, "Cat's Cradle" +% +"But I don't like Spam!" +% +"But this has taken us far afield from interface, which is not a bad place +to be, since I particularly want to move ahead to the kludge. Why do +people have so much trouble understanding the kludge? What is a kludge, +after all, but not enough Ks, not enough ROMs, not enough RAMs, poor +quality interface and too few bytes to go around? Have I explained yet +about the bytes?" +% +"Calvin Coolidge looks as if he had been weaned on a pickle." + ― Alice Roosevelt Longworth +% +"Contrariwise," continued Tweedledee, "if it was so, it might be; and +if it were so, it would be; but as it isn't, it ain't. That's logic!" + ― Lewis Carroll, "Through the Looking Glass" +% +"Creation science" has not entered the curriculum for a reason so simple +and so basic that we often forget to mention it: because it is false, and +because good teachers understand exactly why it is false. What could be +more destructive of that most fragile yet most precious commodity in our +entire intellectual heritage ― good teaching ― than a bill forcing +honorable teachers to sully their sacred trust by granting equal treatment +to a doctrine not only known to be false, but calculated to undermine any +general understanding of science as an enterprise? + ― Stephen Jay Gould, "The Skeptical Inquirer", Vol. 12, page 186 +% +"Deep" is a word like "theory" or "semantic" ― it implies all sorts of +marvelous things. It's one thing to be able to say "I've got a theory", +quite another to say "I've got a semantic theory", but, ah, those who can +claim "I've got a deep semantic theory", they are truly blessed. + ― Randy Davis +% +"Deliver yesterday, code today, think tomorrow." +% +"Die? I should say not, dear fellow. No Barrymore would allow such a +conventional thing to happen to him." + ― John Barrymore's dying words +% +"Do not stop to ask what is it; + Let us go and make our visit." + ― T. S. Eliot, "The Love Song of J. Alfred Prufrock" +% +"Do you have blacks, too?" + ― George W. Bush, to Brazilian president Fernando Cardoso; + Washington, D.C., November 8, 2001 +% +"Don't let your mouth write no check that your tail can't cash." + ― Bo Diddley +% +"Don't say yes until I finish talking." + ― Darryl F. Zanuck +% +"Drawing on my fine command of language, I said nothing." +% +"Earth is a great, big funhouse without the fun." + ― Jeff Berner +% +"Even the best of friends cannot attend each other's funeral." + ― Kehlog Albran, "The Profit" +% +"Every time I think I know where it's at, they move it." +% +"Grub first, then ethics." + ― Bertolt Brecht +% +"He didn't say that. He was reading what was given to him in a speech." + ― Richard Darman, director of OMB, explaining why President Bush + wasn't following up on his campaign pledge that there would be + no loss of wetlands +% +"He was so narrow minded he could see through a keyhole with both eyes..." +% +"He's the kind of man for the times that need the kind of man he is ..." +% +"His mind is like a steel trap ― full of mice." + ― Foghorn Leghorn +% +"Humor is a drug which it's the fashion to abuse." + ― William Gilbert +% +"I am not an Economist. I am an honest man!" + ― Paul McCracken +% +"I am not sure what this is, but an `F' would only dignify it." + ― English Professor +% +"I didn't accept it. I received it." + ― Richard Allen, National Security Advisor to President Reagan, + explaining the $1000 in cash and two watches he was given by + two Japanese journalists after he helped arrange a private + interview for them with First Lady Nancy Reagan. +% +"I don't care who does the electing as long as I get to do the nominating." + ― Boss Tweed +% +"I don't have any solution but I certainly admire the problem." + ― Ashleigh Brilliant +% +"I have yet to see any problem, however complicated, which, when looked +at in the right way, did not become still more complicated." + ― Paul Anderson +% +"I just need enough to tide me over until I need more." + ― Bill Hoest +% +"I may not be totally perfect, but parts of me are excellent." + ― Ashleigh Brilliant +% +"I support efforts to limit the terms of members of Congress, especially +members of the House and members of the Senate." + ― former Vice-President Dan Quayle +% +"I was under medication when I made the decision not to burn the tapes." + ― President Richard Nixon +% +"I'd give my right arm to be ambidextrous." +% +"If dolphins are so smart, why did Flipper work for television?" +% +"If the King's English was good enough for Jesus, it's good enough for me!" + ― "Ma" Ferguson, Governor of Texas (circa 1920) +% +"If you can count your money, you don't have a billion dollars." + ― J. Paul Getty +% +"If you go on with this nuclear arms race, all you are going to do is +make the rubble bounce." + ― Winston Churchill +% +"In defeat, unbeatable; in victory, unbearable." + ― Winston Churchill, of Montgomery +% +"It depends on your definition of asleep. They were not stretched out. +They had their eyes closed. They were seated at their desks with their +heads in a nodding position." + ― John Hogan, Commonwealth Edison Supervisor of News Information, + responding to a charge by a Nuclear Regulatory Commission + inspector that two Dresden Nuclear Plant operators were + sleeping on the job. +% +"It is easier for a camel to pass through the eye of a needle if it is +lightly greased." + ― Kehlog Albran, "The Profit" +% +"It was hell," recalls former child. + ― caption to a B. Kliban cartoon +% +"It's bad luck to be superstitious." + ― Andrew W. Mathis +% +"It's not Camelot, but it's not Cleveland, either." + ― Kevin White, mayor of Boston +% +"Just once, I wish we would encounter an alien menace that wasn't immune + to bullets" + ― The Brigader, "Dr. Who" +% +"Laughter is the closest distance between two people." + ― Victor Borge +% +"MacDonald has the gift on compressing the largest amount of words into +the smallest amount of thoughts." + ― Winston Churchill +% +"Man invented language to satisfy his deep need to complain." + ― Lily Tomlin +% +"Mate, this parrot wouldn't VOOM if you put four million volts through it!" +% +"Might as well be frank, monsieur. It would take a miracle to get you +out of Casablanca and the Germans have outlawed miracles." +% +"Nondeterminism means never having to say you are wrong." +% +"Of COURSE it's the murder weapon. Who would frame someone with a fake?" +% +"One planet is all you get." +% +"She is descended from a long line that her mother listened to." + ― Gypsy Rose Lee +% +"Sherry [Thomas Sheridan] is dull, naturally dull; but it must have +taken him a great deal of pains to become what we now see him. Such an +excess of stupidity, sir, is not in Nature." + ― Samuel Johnson +% +"Stealing a rhinoceros should not be attempted lightly." +% +"Sure, it's going to kill a lot of people, but they may be dying of something +else anyway." + ― Othal Brand, member of a Texas pesticide review board, on chlordane +% +"Text processing has made it possible to right-justify any idea, even +one which cannot be justified on any other grounds." + ― J. Finnegan, USC. +% +"That must be wonderful! I don't understand it at all." +% +"The C Programming Language: A language which combines the flexibility of +assembly language with the power of assembly language." +% +"The Lord gave us farmers two strong hands so we could grab as much as +we could with both of them." + ― Joseph Heller, "Catch-22" +% +The bland leadeth the bland and they both shall fall into the kitsch. +% +"The difference between a misfortune and a calamity? If Gladstone fell +into the Thames, it would be a misfortune. But if someone dragged him +out again, it would be a calamity." + ― Benjamin Disraeli +% +The brain is a beautifully engineered get-out-of-the-way machine that +constantly scans the environment for things out of whose way it should +right now get. That's what brains did for several hundred million years ― +and then, just a few million years ago, the mammalian brain learned a new +trick: to predict the timing and location of dangers before they actually +happened. + +Our ability to duck that which is not yet coming is one of the brain's most +stunning innovations, and we wouldn't have dental floss or 401(k) plans +without it. But this innovation is in the early stages of development. The +application that allows us to respond to visible baseballs is ancient and +reliable, but the add-on utility that allows us to respond to threats that +loom in an unseen future is still in beta testing. + ― Daniel Gilbert, professor of psychology at Harvard University, + in an op-ed piece in the Los Angeles Times; 6 July, 2006 +% +"The illegal we do immediately. The unconstitutional takes a bit longer." + ― Henry Kissinger +% +"The society which scorns excellence in plumbing as a humble activity and +tolerates shoddiness in philosophy because it is an exaulted activity will +have neither good plumbing nor good philosophy ... neither its pipes nor +its theories will hold water." +% +"The sooner you fall behind, the more time you'll have to catch up!" +% +"The streets are safe in Philadelphia. It's only the people who +make them unsafe." + ― the late Frank Rizzo, ex-police chief and ex- mayor of + Philadelphia +% +The voters have spoken, the bastards... +% +"The warning message we sent the Russians was a calculated ambiguity +that would be clearly understood." + ― Alexander Haig +% +The way to make a small fortune in the commodities market is to start +with a large fortune. +% +"There are three possibilities: Pioneer's solar panel has turned away +from the sun; there's a large meteor blocking transmission; or someone +loaded Star Trek 3.2 into our video processor." +% +"There are two ways of disliking poetry; one way is to dislike it, the +other is to read Pope." + ― Oscar Wilde +% +"There was a boy called Eustace Clarence Scrubb, and he almost deserved it." + ― C. S. Lewis, The Chronicles of Narnia +% +"They gave me a book of checks. They didn't ask for any deposits." + ― Congressman Joe Early (D-Mass) at a press conference to answer + questions about the House Bank scandal. +% +This is a country where people are free to practice their religion, +regardless of race, creed, color, obesity, or number of dangling keys... +% +"To YOU I'm an atheist; to God, I'm the Loyal Opposition." + ― Woody Allen +% +To vacillate or not to vacillate, that is the question ... or is it? +% +"Tom Hayden is the kind of politician who gives opportunism a bad name." + ― Gore Vidal +% +"Under capitalism, man exploits man. Under Communism, it's just the opposite." + ― John Kenneth Galbraith +% +"We don't care. We don't have to. We're the Phone Company." +% +"We don't have to protect the environment ― the Second Coming is at hand." + ― James Watt +% +"We have reason to believe that man first walked upright to free his +hands for masturbation." + ― Lily Tomlin +% +"We'll cross out that bridge when we come back to it later." +% +"Well, if you can't believe what you read in a comic book, what CAN +you believe?!" + ― Bullwinkle J. Moose [Jay Ward] +% +"What is the robbing of a bank compared to the FOUNDING of a bank?" + ― Bertold Brecht +% +"When the going gets tough, the tough get empirical." + ― Jon Carroll +% +"When you have to kill a man it costs nothing to be polite." + ― Winston Churchill, on formal declarations of war +% +"Where shall I begin, please your Majesty?" he asked. "Begin at the +beginning," the King said, gravely, "and go on till you come to the end: +then stop." + ― Alice's Adventures in Wonderland, Lewis Carroll +% +"Why be a man, when you can be a success?" + ― Bertold Brecht +% +"Why isn't there a special name for the tops of your feet?" + ― Lily Tomlin +% +"Why was I born with such contemporaries?" + ― Oscar Wilde +% +"Would you tell me, please, which way I ought to go from here?" + +"That depends a good deal on where you want to get to," said the Cat. + ― Lewis Carrol +% +"Yacc" owes much to a most stimulating collection of users, who have goaded +me beyond my inclination, and frequently beyond my ability in their endless +search for "one more feature". Their irritating unwillingness to learn how +to do things my way has usually led to my doing things their way; most of +the time, they have been right. + ― S. C. Johnson, "Yacc guide acknowledgements" +% +"Yes, that was Richard Nixon. He used to be President. When he left the +White House, the Secret Service would count the silverware." + ― Woody Allen, "Sleeper" +% +"Yes, well, that's just the sort of blinkered, Philistine pig-ignorance I've +come to expect from you non-creative garbage. You sit there on your loathsome +spotty behinds squeezing blackheads, not caring a tinker's cuss for the +struggling artist, you excrement! You whining, hypocritical toadies with your +Tony Jacklin golf clubs, your colour TVs and your bleedin' Masonic handshakes! +You wouldn't let me join, would you, you blackballing bastards?! WELL I +WOULDN'T BECOME A FREEMASON NOW IF YOU GOT DOWN ON YOUR LOUSY STINKING KNEES +AND BEGGED ME!" +% +"You can't teach people to be lazy - either they have it, or they don't." + ― Dagwood Bumstead +% +"You'll never be the man your mother was!" +% +$100 invested at 7% interest for 100 years will become $100,000, at +which time it will be worth absolutely nothing. + ― Lazarus Long, "Time Enough for Love" +% +'Martyrdom' is the only way a person can become famous without ability. + ― George Bernard Shaw +% +'Tis not too late to seek a newer world. + ― Alfred, Lord Tennyson +% +[Humanity] is the measure of all things. + ― Protagoras +% +... And malt does more than Milton can/To justify God's ways to man + ― A. E. Housman +% +An infinite number of mathematicians walk into a bar. The first one orders +a beer. The second orders half a beer. The third, a quarter of a beer. The +bartender says "You're all idiots", and pours two beers. +% +Any code of your own that you haven't looked at for six or more months +might as well have been written by someone else. + ― Eagleson's Law +% +Any resemblance between the above and my own views is non-deterministic. +% +... But if we laugh with derision, we will never understand. Human +intellectual capacity has not altered for thousands of years so far as we +can tell. If intelligent people invested intense energy in issues that now +seem foolish to us, then the failure lies in our understanding of their +world, not in their distorted perceptions. Even the standard example of +ancient nonsense ― the debate about angels on pinheads ― makes sense once +you realize that theologians were not discussing whether five or eighteen +would fit, but whether a pin could house a finite or an infinite number. + ― S. J. Gould, "Wide Hats and Narrow Minds" +% +... Fortunately, the responsibility for providing evidence is on the part of +the person making the claim, not the critic. It is not the responsibility +of UFO skeptics to prove that a UFO has never existed, nor is it the +responsibility of paranormal-health-claims skeptics to prove that crystals +or colored lights never healed anyone. The skeptic's role is to point out +claims that are not adequately supported by acceptable evidence and to +provide plausible alternative explanations that are more in keeping with +the accepted body of scientific evidence. ... + ― Thomas L. Creed, The Skeptical Inquirer, Vol. XII No. 2, pg. 215 +% +... Had this been an actual emergency, we would have fled in terror, +and you would not have been informed. +% +... The book is worth attention for only two reasons: (1) it attacks +attempts to expose sham paranormal studies; and (2) it is very well and +plausibly written and so rather harder to dismiss or refute by simple +jeering. + ― Harry Eagar, reviewing "Beyond the Quantum" by Michael Talbot, + The Skeptical Inquirer, Vol. XII No. 2, ppg. 200-201 +% +The first principle is that you must not fool yourself―and you are the +easiest person to fool. So you have to be very careful about that. After +you've not fooled yourself, it's easy not to fool other scientists. You +just have to be honest in a conventional way after that. + ― R. P. Feynman, "Cargo Cult Science" +% +... at least I thought I was dancing, 'til somebody stepped on my hand. + ― J. B. White +% +... if the church put in half the time on covetousness that it does on lust, +this would be a better world. + ― Garrison Keillor, "Lake Wobegon Days" +% +... the Father, the Son and the Holy Ghost would never throw the Devil out +of Heaven as long as they still need him as a fourth for bridge. + ― Letter in NEW LIBERTARIAN NOTES #19 +% +... they [the Indians] are not running but are coming on. + ― note sent from Lt. Col Custer to other officers + of the 7th Regiment at the Little Bighorn +% +...I would go so far as to suggest that, were it not for our ego and +concern to be different, the African apes would be included in our family, +the Hominidae. + ― Richard Leakey +% +... It is sad to find him belaboring the science community for its united +opposition to ignorant creationists who want teachers and textbooks to give +equal time to crank arguments that have advanced not a step beyond the +flyblown rhetoric of Bishop Wilberforce and William Jennings Bryan. + ― Martin Gardner, "Irving Kristol and the Facts of Life", + The Skeptical Inquirer, Vol. XII No. 2, ppg. 128-131 +% +...computer hardware progress is so fast. No other technology since +civilization began has seen six orders of magnitude in performance-price +gain in 30 years. + ― Fred Brooks, Jr. +% +...difference of opinion is advantageous in religion. The several sects +perform the office of a common censor morum over each other. Is uniformity +attainable? Millions of innocent men, women, and children, since the +introduction of Christianity, have been burnt, tortured, fined, imprisoned; +yet we have not advanced one inch towards uniformity. + ― Thomas Jefferson, "Notes on Virginia" +% +...it still remains true that as a set of cognitive beliefs about the +existence of God in any recognizable sense continuous with the great +systems of the past, religious doctrines constitute a speculative +hypothesis of an extremely low order of probability. + ― Sidney Hook +% +...skill such as yours is evidence of a misspent youth. + ― Herbert Spencer +% +...the increased productivity fostered by a friendly environment and quality +tools is essential to meet ever increasing demands for software. + ― M. D. McIlroy, E. N. Pinson and B. A. Tague +% +...there can be no public or private virtue unless the foundation of action is +the practice of truth. + ― George Jacob Holyoake +% +...this is an awesome sight. The entire rebel resistance buried under six +million hardbound copies of "The Naked Lunch." + ― The Firesign Theater +% +...though his invention worked superbly ― his theory was a crock of sewage +from beginning to end. + ― Vernor Vinge, "The Peace War" +% +...when fits of creativity run strong, more than one programmer or writer has +been known to abandon the desktop for the more spacious floor. + ― Fred Brooks, Jr. +% +/earth is 98% full ... please delete anyone you can. +% +10.0 times 0.1 is hardly ever 1.0. +% +36 percent of the American public believes that boiling radioactive milk +makes it safe to drink. + ― results of a survey by Jon Miller at Northern Illinois University +% +43rd Law of Computing: Anything that can go wr +fortune: Segmentation fault ― core dumped +% +80 percent of all statistics are made up on the spot, including this one. +% +99% of all guys are within one standard deviation of your mom. +% +A LISP programmer knows the value of everything, but the cost of nothing. +% +A bore is a man you deprives you of solitude without providing you with +company. + ― Gian Vincenzo Gravina +% +A Nixon [is preferable to] a Dean Rusk ― who will be passionately +wrong with a high sense of consistency. + ― J. K. Galbraith +% +A Puritan is someone who is deathly afraid that someone somewhere is +having fun. +% +A baby is an alimentary canal with a loud voice at one end and no +responsibility at the other. +% +A bachelor is a selfish, undeserving guy who has cheated some woman +out of a divorce. + ― Don Quinn +% +A billion here, a billion there, sooner or later it adds up to real money. + ― Everett Dirksen +% +A bore is someone who persists in holding his own views after we have +enlightened him with ours. +% +A budget is just a method of worrying before you spend money, as well as +afterward. +% +A candidate is a person who gets money from the rich and votes from the +poor to protect them from each other. +% +A celebrity is a person who is known for his well-knownness. +% +A child's education should begin at least 100 years before he is born. + ― Oliver Wendell Holmes +% +A city is a large community where people are lonesome together. + ― Herbert Prochnow +% +A clash of doctrine is not a disaster ― it is an opportunity. +% +A closed mouth gathers no foot. +% +A conclusion is simply the place where someone got tired of thinking. +% +A conference is a gathering of important people who singly can do nothing, +but together can decide that nothing can be done. + ― Fred Allen +% +A conservative is a man who believes that nothing should be done for +the first time. + ― Alfred E. Wiggam +% +A conservative is a man with two perfectly good legs who has never +learned to walk. + ― Franklin D. Roosevelt +% +A conservative is one who is too cowardly to fight and too fat to run. +% +A countryman between two lawyers is like a fish between two cats. + ― Ben Franklin +% +A critic is a legless man who teaches running. + ― Channing Pollock +% +A day without sunshine is like night. +% +A decision occurs when one abandons the obvious for the possible. + ― P. Taylor +% +A diplomat is a man who can convince his wife she'd look stout in a fur coat. +% +A diplomat is someone who can tell you to go to hell in such a way that you +will look forward to the trip. + ― Caskie Stinnett +% +A diplomat is a man who always remembers a woman's birthday but never her age. + ― Robert Frost +% +A diva who specializes in risque arias is an off-coloratura soprano ... +% +A door is what a dog is perpetually on the wrong side of. + ― Ogden Nash +% +A famous Lisp Hacker noticed an Undergraduate sitting in front of a Xerox +1108, trying to edit a complex Klone network via a browser. Wanting to +help, the Hacker clicked one of the nodes in the network with the mouse, +and asked "what do you see?" Very earnestly, the Undergraduate replied "I +see a cursor." The Hacker then quickly pressed the boot toggle at the back +of the keyboard, while simultaneously hitting the Undergraduate over the +head with a thick Interlisp Manual. The Undergraduate was then Enlightened. +% +A fanatic is a person who can't change his mind and won't change the subject. + ― Winston Churchill +% +A fool must now and then be right by chance. +% +A fool's brain digests philosophy into folly, science into +superstition, and art into pedantry. Hence University education. + ― G. B. Shaw +% +A foolish consistency is the hobgoblin of little minds. + ― Samuel Johnson +% +A formal parsing algorithm should not always be used. + ― D. Gries +% +A good listener is not only popular everywhere, but after a while he knows +something. + ― Wilson Mizner +% +A good memory does not equal pale ink. +% +A good workman is known by his tools. +% +A great many people think they are thinking when they are merely +rearranging their prejudices. + ― William James +% +A handful of friends is worth more than a wagon of gold. +% +A healthy male adult bore consumes each year one and a half times his weight +in other people's patience. + ― John Updike +% +A hermit is a deserter from the army of humanity. +% +A journey of a thousand miles begins with a cash advance. +% +A king's castle is his home. +% +A lack of leadership is no substitute for inaction. +% +A language that doesn't affect the way you think about programming is +not worth knowing. +% +A language that doesn't have everything is actually easier to program +in than some that do. + ― Dennis M. Ritchie +% +A large number of installed systems work by fiat. That is, they work +by being declared to work. + ― Anatol Holt +% +A learning experience is one of those things that says, "You know that +thing you just did? Don't do that." + ― attributed to Douglas Adams +% +A little caution outflanks a large cavalry. + ― Bismarck +% +A little retrospection shows that although many fine, useful software systems +have been designed by committees and built as part of multipart projects, +those software systems that have excited passionate fans are those that are +the products of one or a few designing minds, great designers. Consider Unix, +APL, Pascal, Modula, the Smalltalk interface, even Fortran; and contrast them +with Cobol, PL/I, Algol, MVS/370, and MS-DOS. + ― Fred Brooks, Jr. +% +A lot of people I know believe in positive thinking, and so do I. I +believe everything positively stinks. + ― Lew Col +% +A man forgives only when he is in the wrong. +% +A man is not old until regrets take the place of dreams. + ― John Barrymore +% +A man paints with his brains and not with his hands. +% +A man said to the Universe: "Sir, I exist!" + +"However," replied the Universe, "the fact has not created in me a +sense of obligation." + ― Stephen Crane +% +A man shall never be enriched by envy. + ― Thomas Draxe +% +A man who fishes for marlin in ponds will put his money in Etruscan bonds. +% +A man who turns green has eschewed protein. +% +A man wrapped up in himself makes a very small package. +% +A manager would rather live with a problem that he cannot solve than +accept a solution that he does not understand. + ― G. Woolsey +% +A mathematician is a machine for converting coffee into theorems. +% +A mathematician named Hall +Has a hexahedronical ball, + And the cube of its weight + Times his pecker's, plus eight +Is his phone number ― give him a call. +% +A model is an artifice for helping you convince yourself that you +understand more about a system than you do. +% +A moose once bit my sister. +% +A morsel of genuine history is a thing so rare as to be always valuable. + ― Thomas Jefferson +% +A nuclear war can ruin your whole day. +% +A nymph hits you and steals your virginity. +% +A penny saved is ridiculous. +% +A person is just about as big as the things that make them angry. +% +A person who knows only one side of a question knows little of that. +% +A person with one watch knows what time it is; a person with two watches is +never sure. Proverb +% +A physicist is an atom's way of knowing about atoms. + ― George Wald +% +A plucked goose doesn't lay golden eggs. +% +A professor is one who talks in someone else's sleep. +% +A psychiatrist is a person who will give you expensive answers that +your wife will give you for free. +% +A quarrel is quickly settled when deserted by one party; there is no battle +unless there be two. + ― Seneca +% +A real patriot is the fellow who gets a parking ticket and rejoices +that the system works. +% +A real person has two reasons for doing anything ... a good reason and +the real reason. +% +A recent study has found that concentrating on difficult off-screen +objects, such as the faces of loved ones, causes eye strain in computer +scientists. Researchers into the phenomenon cite the added +concentration needed to "make sense" of such unnatural three +dimensional objects ... +% +A right is not what someone gives you; it's what no one can take from you. + ― Ramsey Clark +% +A scout troop consists of twelve little kids dressed like schmucks following +a big schmuck dressed like a kid. + - Jack Benny +% +A second marriage is the triumph of hope over experience. + ― Samuel Johnson +% +A sine curve goes off into infinity or at least to the end of the blackboard. +% +A smile is the shortest distance between two people. + ― Victor Borge +% +A straw vote only shows which way the hot air blows. + ― O'Henry +% +A student who changes the course of history is probably taking an +exam. +% +A successful tool is one that was used to do something undreamed of by +its author. + ― S. C. Johnson +% +A thing is worth precisely what it can do for you, not what you choose to +pay for it. + ― John Ruskin +% +A total abstainer is one who abstains from everything but abstention, +and especially from inactivity in the affairs of others. + ― Ambrose Bierce, "The Devil's Dictionary" +% +A truly wise man never plays leapfrog with a unicorn. +% +A university is what a college becomes when the faculty loses interest +in students. + ― John Ciardi +% +A vacuum is a hell of a lot better than some of the stuff that nature +replaces it with. + ― Tenessee Williams +% +A visit to a fresh place will bring strange work. +% +A visit to a strange place will bring fresh work. +% +A well adjusted person is one who makes the same mistake twice without +getting nervous. +% +A well-known friend is a treasure. +% +A witty saying proves nothing. + ― Voltaire +% +A woman without a man is like a fish without a bicycle. +% +A year spent in artificial intelligence is enough to make one believe in God. +% +Ada, n.: Something you need only know the name of to be an Expert in +computing. Useful in sentences like, "We had better develop an Ada +awareness." +% +Abandon hope, all ye who press "ENTER" here. +% +Ability is useless unless it is used. + ― Robert Half +% +About all some men accomplish in life is to send a son to Harvard. +% +About the only thing on a farm that has an easy time is the dog. +% +About the time we think we can make ends meet, somebody moves the ends. + ― Herbert Hoover +% +Above all things, reverence yourself. +% +Abstention makes the heart grow fonder. +% +Absurdity, n.: A statement or belief manifestly inconsistent with one's own +opinion. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Accident, n.: A condition in which presence of mind is good, but absence of +body is better. +% +According to my best recollection, I don't remember. + ― Vincent "Jimmy Blue Eyes" Alo +% +According to the latest official figures, 43% of all statistics are totally +worthless. +% +According to my scuba instructor, if a shark attacks, you're supposed to +poke it in the eye with your finger. After that, I suppose you should hit +it in the face with a cream pie, or maybe hose it down with a seltzer bottle. + ― Jerry L. Embry +% +Accordion: A bagpipe with pleats. +% +Accuracy: The vice of being right. +% +Acquaintance, n.: A person whom we know well enough to borrow from, but not +well enough to lend to. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Acting is an art which consists of keeping the audience from coughing. +% +Activity makes more men's fortunes than cautiousness. + ― Marquis de Vauvenargues +% +Actors will happen in the best-regulated families. +% +Ada is the work of an architect, not a computer scientist. + ― Jean Ichbiah, inventor of Ada, weenie +% +Adapt. Enjoy. Survive. +% +Adde parvum parvo magnus acervus erit. +[Add little to little and there will be a big pile.] + ― Ovid +% +Admiration, n.: Our polite recognition of another's resemblance to ourselves. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Adolescence: The stage between puberty and adultery. +% +Adore, v.: To venerate expectantly. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Adult: One old enough to know better. +% +Adversity makes men, prosperity monsters. + ― French Proverb +% +Advertisement: The most truthful part of a newspaper. + ― Thomas Jefferson +% +Advertising: The science of arresting the human intelligence long enough to +get money from it. + ― Stephen Leacock +% +After Goliath's defeat, giants ceased to command respect. + ― Freeman Dyson +% +After a number of decimal places, nobody gives a damn. +% +After all is said and done, a lot more has been said than done. +% +After all, what is your hosts' purpose in having a party? Surely not +for you to enjoy yourself; if that were their sole purpose, they'd have +simply sent champagne and women over to your place by taxi. + ― P. J. O'Rourke +% +After any machine or unit has been assembled, extra components will be +found on the bench. + ― "Industry at Work," Oilways, n2., 1972, pp. 16-17. Humble Oil + & Refining Company., Houston, TX +% +After the last of 16 mounting screws has been removed from an access cover, +it will be discovered that the wrong access cover has been removed. +% +After winning the pennant one year, Casey Stengel commented, "I couldn'ta +done it without my players." +% +Air is water with holes in it. +% +Alas, I am dying beyond my means. + ― Oscar Wilde, as he sipped champagne on his deathbed +% +Albert Einstein, when asked to describe radio, replied: "You see, wire +telegraph is a kind of a very, very long cat. You pull his tail in New +York and his head is meowing in Los Angeles. Do you understand this? And +radio operates exactly the same way: you send signals here, they receive +them there. The only difference is that there is no cat." +% +Alexander Graham Bell is alive and well in New York, and still waiting for a +dial tone. +% +Alimony and bribes will engage a large share of your wealth. +% +Alimony is a system by which, when two people make a mistake, one of +them keeps paying for it. + ― Peggy Joyce +% +All I ask is a chance to prove that money can't make me happy. +% +All I ask of life is a constant and exaggerated sense of my own importance. +% +All I kin say is when you finds yo'self wanderin' in a peach orchard, +ya don't go lookin' for rutabagas. + ― Kingfish +% +All a hacker needs is a tight PUSHJ, a loose pair of UUOs, and a warm +place to shift. +% +All great ideas are controversial, or have been at one time. +% +All happy families resemble one another, each unhappy in its own way. + ― Tolstoy +% +All in all it's just another brick in the wall. +% +All my life I wanted to be someone; I guess I should have been more specific. + ― Jane Wagner +% +All programmers are optimists. Perhaps this modern sorcery especially attracts +those who believe in happy endings and fairy godmothers. Perhaps the hundreds +of nitty frustrations drive away all but those who habitually focus on the end +goal. Perhaps it is merely that computers are young, programmers are younger, +and the young are always optimists. But however the selection process works, +the result is indisputable: "This time it will surely run," or "I just found +the last bug." + ― Frederick Brooks, Jr., The Mythical Man Month +% +All programmers are playwrights and all computers are lousy actors. +% +All progress is based upon a universal innate desire on the part of +every organism to live beyond its income. + ― Samuel Butler +% +All science is either physics or stamp collecting. + ― E. Rutherford +% +All that glitters has a high refractive index. +% +All the world's a stage and most of us are desperately unrehearsed. + ― Sean O'Casey +% +All things are possible except skiing through a revolving door. +% +All through human history, tyrannies have tried to enforce obedience by +prohibiting disrespect for the symbols of their power. The swastika is +only one example of many in recent history. + ― American Bar Association task force on flag burning +% +All true wisdom is found on T-shirts. +% +All wise men share one trait in common: the ability to listen. +% +Allen's Axiom: When all else fails, read the instructions. +% +Alliance, n.: In international politics, the union of two thieves who have +their hands so deeply inserted in each other's pocket that they cannot +separately plunder a third. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Although every American has a sense of humor―it is his birthright and +encoded somewhere in the Constitution―few Americans have never been able to +cope with wit or irony, and even the simplest jokes often cause unease, +especially today when every phrase must be examined for covert sexism, +racism, ageism. + ― Gore Vidal, "The Essential Mencken," The Nation, + August 26/September 2, 1991. +% +Always borrow money from a pessimist; he doesn't expect to be paid back. +% +Always make the audience suffer as much as possible. + ― Alfred Hitchcock +% +Ambidextrous, adj.: Able to pick with equal skill a right-hand pocket or a +left. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Ambition is a poor excuse for not having sense enough to be lazy. + ― Charlie McCarthy +% +America had often been discovered before Columbus; it had just been hushed up. + ― Oscar Wilde +% +America's best buy for a quarter is a telephone call to the right man. +% +America, how can I write a holy litany in your silly mood? + ― Allen Ginsberg +% +American Non Sequitur Society: We don't make sense. We like pizza. +% +Amnesia used to be my favorite word, but then I forgot it. +% +Among the chosen, you are the lucky one. +% +Among the lucky, you are the chosen one. +% +An American's a person who isn't afraid to criticize the President but +is always polite to traffic cops. +% +An Army travels on its stomach. +% +An Englishman never enjoys himself, except for a noble purpose. + ― A. P. Herbert +% +An economist is a man who states the obvious in terms of the incomprehensible. + ― Alfred A. Knopf +% +An effective way to deal with predators is to taste terrible. +% +An elephant is a mouse with an operating system. +% +An idea is not responsible for the people who believe in it. +% +An idle mind is worth two in the bush. +% +An intellectual is someone whose mind watches itself. + ― Albert Camus +% +An NT server can be run by an idiot, and usually is. + - Tom Holub + (Posted to comp.infosystems.www.servers.unix on 03 Sep 1997) +% +An object never serves the same function as its image―or its name. + ― Rene Magritte +% +An ounce of prevention is worth a pound of cure. + ― Benjamin Franklin +% +Anarchy may not be the best form of government, but it's better than no +government at all. +% +Anarchy: It's not the law, it's just a good idea. +% +And I alone am returned to wag the tail. +% +And now for something completely different. +% +And now that the legislators and the do-gooders have so futilely inflicted +so many systems upon society, may they end up where they should have begun: +may they reject all systems, and try liberty... + ― Frederic Bastiat +% +And on the seventh day, He exited from append mode. +% +And the Lord God said unto Moses ― and correctly, I believe ... + ― Field Marshal Montgomery, opening a chapel service +% +And the crowd was stilled. One elderly man, wondering at the sudden silence, +turned to the Child and asked him to repeat what he had said. Wide-eyed, +the Child raised his voice and said once again, "Why, the Emperor has no +clothes! He is naked!" + ― "The Emperor's New Clothes" +% +And there's hamburger all over the highway in Mystic, Connecticut. +% +And they told us, what they wanted... +Was a sound that could kill some-one, from a distance. + ― Kate Bush +% +And this is a table ma'am. What in essence it consists of is a horizontal +rectilinear plane surface maintained by four vertical columnar supports, +which we call legs. The tables in this laboratory, ma'am, are as advanced +in design as one will find anywhere in the world. + ― Michael Frayn, "The Tin Men" +% +And thou shalt eat it as barley cakes, and thou shalt bake it with dung that +cometh out of man, in their sight...Then he [the Lord!] said unto me, Lo, I +have given thee cow's dung for man's dung, and thou shalt prepare thy bread +therewith. [Ezek. 4:12-15 (KJV)] +% +Anger is a prelude to courage. + ― Eric Hoffer +% +Angular momentum makes the world go round. +% +Ankh if you love Isis. +% +Anoint, v.: To grease a king or other great functionary already sufficiently +slippery. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Another good night not to sleep in a eucalyptus tree. +% +Another one bites the dust. +% +Anthony's Law of Force: Do not force it; get a larger hammer. +% +Anthony's Law of the Workshop: Any tool when dropped, will roll into the + least accessible corner of the workshop. +Corollary: On the way to the corner, any dropped tool will first strike + your toes. +% +Antimatter doesn't matter as a matter of fact. + ― Piggins +% +Antiquis temporibus, nati tibi similes in rupibus ventosissimis exponebantur +ad necem. (In the good old days, children like you were left to perish on +windswept crags.) +% +Antonym, n.: The opposite of the word you're trying to think of. +% +Any clod can have the facts, but having opinions is an art. + ― Charles McCabe +% +Any excuse will serve a tyrant. + ― Aesop +% +Any fool can paint a picture, but it takes a wise man to be able to sell it. +% +Any fool can paint a picture, but it takes a wise person to be able to +sell it. +% +Any given program, when running correctly, is obsolete. +% +Any job worth quitting is worth sticking around long enough until they +fire you. + ― Tim Wirth +% +Any medium powerful enough to extend man's reach is powerful enough to topple +his world. To get the medium's magic to work for one's aims rather than +against them is to attain literacy. + ― Alan Kay, "Computer Software", Scientific American, September 1984 +% +Any shrine is better than self-worship. +% +Any small object that is accidentally dropped will hide under a +larger object. +% +Any small object when dropped will hide under a larger object. +% +Any smoothly functioning technology will have the appearance of magic. + ― Arthur C. Clarke +% +Any sufficiently advanced bureaucracy is indistinguishable from molasses. +% +Any sufficiently advanced stupidity is indistinguishable from malice. + ― Paul Chvostek by way of Arthur C. Clarke (via John Ripley) +% +Any sufficiently advanced technology is indistinguishable from a rigged demo. + ― Andy Finkel, computer guy +% +Any sufficiently advanced technology is indistinguishable from magic. + ― Arthur C. Clarke +% +Any two philosophers can tell each other all they know in two hours. + ― Oliver Wendell Holmes, Jr. +% +Anybody with money to burn will easily find someone to tend the fire. +% +Anyone can hate. It costs to love. + ― John Williamson +% +Anyone can hold the helm when the sea is calm. + ― Publilius Syrus +% +Anyone who cannot cope with mathematics is not fully human. At best he is a +tolerable subhuman who has learned to wear shoes, bathe and not make messes +in the house. + ― Lazarus Long, "Time Enough for Love" +% +Anyone who knows history, particularly the history of Europe, will, I think, +recognize that the domination of education or of government by any one +particular religious faith is never a happy arrangement for the people. + ― Eleanor Roosevelt +% +Anyone who wants to be paid for writing software is a fascist asshole. + ― Richard M. Stallman, founder, Free Software Foundation +% +Anything anybody can say about America is true. + ― Emmett Grogan +% +Anything free is worth what you pay for it. +% +Anything is possible if you don't know what you're talking about. +% +Anything labeled "NEW" and/or "IMPROVED" isn't. The label means the +price went up. The label "ALL NEW", "COMPLETELY NEW", or "GREAT NEW" +means the price went way up. +% +Anything worth doing is worth overdoing +% +Anytime things appear to be going better, you have overlooked something. +% +Arbolist . . . Look up the word. I don't know, maybe I made it up. Anyway, +it's an arbo-tree-ist, somebody who knows about trees. + ― George W. Bush, quoted in USA Today; August 21, 2001 +% +Are we not men? +% +Are you a turtle? +% +Arithmetic is being able to count up to twenty without taking off your shoes. + ― Mickey Mouse +% +Armadillo: To provide weapons to a Spanish pickle +% +army, n.: A body of men assembled to rectify the mistakes of the diplomats. + ― Josephus Daniels +% +Army Axiom: An order that can be misunderstood will be misunderstood. +% +Arnold's Laws of Documentation: + (1) If it should exist, it doesn't. + (2) If it does exist, it's out of date. + (3) Only documentation for useless programs transcends the first two laws. +% +Art is parasitic on life, just as criticism is parasitic on art. + ― Harry S Truman (one of his more ridiculous comments) +% +As Will Rogers would have said, "There is no such things as a free variable." +% +As Zeus said to Narcissus, "Watch yourself." +% +As far as we know, our computer has never had an undetected error. + ― Weisert +% +As goatherd learns his trade by goat, so writer learns his trade by wrote. +% +As long as the answer is right, who cares if the question is wrong? +% +As long as war is regarded as wicked, it will always have its fascination. +When it is looked upon as vulgar, it will cease to be popular. + ― Oscar Wilde +% +As regards the individual nature, woman is defective and misbegotten, for the +active power of the male seed tends to the production of a perfect likeness in +the masculine sex; while the production of a woman comes from defect in the +active power. + ― Thomas Aquinas, prominent historical misogynist +% +As soon as we started programming, we found to our surprise that it wasn't +as easy to get programs right as we had thought. Debugging had to be +discovered. I can remember the exact instant when I realized that a large +part of my life from then on was going to be spent in finding mistakes in +my own programs. + ― Maurice Wilkes discovers debugging, 1949 +% +As the poet said, "Only God can make a tree" ― probably because it's +so hard to figure out how to get the bark on. + ― Woody Allen +% +As the system comes up, the component builders will from time to time appear, +bearing hot new versions of their pieces ― faster, smaller, more complete, +or putatively less buggy. The replacement of a working component by a new +version requires the same systematic testing procedure that adding a new +component does, although it should require less time, for more complete and +efficient test cases will usually be available. + ― Frederick Brooks Jr., "The Mythical Man Month" +% +As the trials of life continue to take their toll, remember that there +is always a future in Computer Maintenance. + ― National Lampoon, "Deteriorada" +% +As to Jesus of Nazareth...I think the system of Morals and his Religion, +as he left them to us, the best the World ever saw or is likely to see; +but I apprehend it has received various corrupting Changes, and I have, +with most of the present Dissenters in England, some doubts as to his +divinity. + ― Benjamin Franklin +% +As with most fine things, chocolate has its season. There is a simple +memory aid that you can use to determine whether it is the correct time +to order chocolate dishes: any month whose name contains the letter A, +E, or U is the proper time for chocolate. + ― Sandra Boynton, "Chocolate: The Consuming Passion" +% +As you read the scroll it vanishes, +and you hear maniacal laughter in the distance. +% +Ashes to ashes, dust to dust, If God won't have you, the devil must. +% +Ask not for whom the telephone bell tolls ... if thou art in the bathtub, +it tolls for thee. +% +Ask your boss to reconsider ― it's so difficult to take "Go to hell" +for an answer. +% +Assuming that either the left wing or the right wing gained control of the +country, it would probably fly around in circles. + ― Pat Paulsen +% +At Group L, Stoffel oversees six first-rate programmers, a managerial +challenge roughly comparable to herding cats. + ― The Washington Post Magazine, June 9, 1985 +% +At a recent meeting in Snowmass, Colorado, a participant from Los Angeles +fainted from hyperoxygenation, and we had to hold his head under the +exhaust of a bus until he revived. +% +At first sight, the idea of any rules or principles being superimposed on +the creative mind seems more likely to hinder than to help, but this is +quite untrue in practice. Disciplined thinking focuses inspiration rather +than blinkers it. + ― G. L. Glegg, The Design of Design +% +At the heart of science is an essential tension between two seemingly +contradictory attitudes ― an openness to new ideas, no matter how bizarre +or counterintuitive they may be, and the most ruthless skeptical scrutiny +of all ideas, old and new. This is how deep truths are winnowed from deep +nonsense. Of course, scientists make mistakes in trying to understand the +world, but there is a built-in error-correcting mechanism: The collective +enterprise of creative thinking and skeptical thinking together keeps the +field on track. + ― Carl Sagan, "The Fine Art of Baloney Detection," Parade, + February 1, 1987 +% +At the source of every error which is blamed on the computer you will +find at least two human errors, including the error of blaming it on +the computer. +% +Athens built the Acropolis. Corinth was a commercial city, interested in +purely materialistic things. Today we admire Athens, visit it, preserve the +old temples, yet we hardly ever set foot in Corinth. + ― Dr. Harold Urey, Nobel Laureate in chemistry +% +Atlee is a very modest man. And with reason. + ― Winston Churchill +% +Auribus teneo lupum. (I hold a wolf by the ears.) +% +Automobile, n.: A four-wheeled vehicle that runs up hills and down pedestrians. +% +Automobile: A four-wheeled vehicle that runs up hills and down pedestrians. +% +Average managers are concerned with methods, opinions, precedents. +Good managers are concerned with solving problems. +% +Avoid Quiet and Placid persons unless you are in Need of Sleep. + ― National Lampoon, "Deteriorada" +% +Avoid letting temper block progress; keep cool. + ― William Feather +% +Back off, man. I'm a scientist. +% +Badges? We don't need no stinking badges. +% +Bagdikian's Observation: + Trying to be a first-rate reporter on the average American + newspaper is like trying to play Bach's "St. Matthew Passion" + on a ukelele. +% +Bad sneakers and a piña colada, my friend +Stompin' down the avenue by Radio City +With a transistor and a large sum of money to spend. + ― Steely Dan +% +Baker's First Law of Federal Geometry: + A block grant is a solid mass of money surrounded on all sides + by governors. +% +Barth's Distinction: There are two types of people: those who divide people +into two types, and those who don't. +% +Basic, n.: A programming language. Related to certain social diseases in + that those who have it will not admit it in polite company. +% +Be assured that a walk through the ocean of most Souls would scarcely get +your Feet wet. Fall not in Love, therefore: it will stick to your face. + ― National Lampoon, "Deteriorada" +% +Be careful when a loop exits to the same place from side and bottom. +% +Be different: conform. +% +Be regular and orderly in your life so that you may be violent and original +in your work. + ― Gustave Flaubert +% +Be seeing you. +% +Beauty and harmony are as necessary to you as the very breath of life. +% +Beauty is only skin deep, but Ugly goes straight to the bone. +% +Bees are not as busy as we think they are; they just cannot buzz any slower. + ― Abe Martin +% +Behind every argument is someone's ignorance. + ― Louis Brandeis +% +Behold the warranty: The bold print giveth and the fine print taketh away. +% +Beifeld's Principle: The probability of a young man meeting a desirable and +receptive young female increases by pyramidal progression when he is +already in the company of: (1) a date, (2) his wife, (3) a better looking +and richer male friend. +% +Being stoned on marijuana isn't very different from being stoned on gin. + ― Ralph Nader +% +Berkeley's First Law of Mistakes: The moment you have worked out an answer, +start checking it―it probably isn't right. +% +Corollary 1 to Berkeley's First Law of Mistakes: Always let an answer cool +off for awhile―it should not be used while hot. +% +Corollary 2 to Berkeley's First Law of Mistakes: Check the answer you have +worked out once more―before you tell it to anybody. +% +Berkeley's Second Law of Mistakes: If there is an opportunity to make a +mistake, sooner or later, the mistake will be made. +% +Better living a beggar than buried an emperor. +% +Between the choice of two evils, I always pick the one I've never tried before. + ― Mae West +% +Between the legs of the women walking by, the dadaists imagined a monkey +wrench and the surrealists a crystal cup. That's lost. + ― Ivan Chtcheglov +% +Beware of bugs in the above code; I have only proved it correct, not tried it. + ― Donald Knuth +% +Beware of Geeks bearing grifts. +% +Beware of Programmers who carry screwdrivers. + ― Leonard Brandwein +% +Beware of a dark-haired man with a loud tie. +% +Beware of a tall dark man with a spoon up his nose. +% +Beware of all enterprises that require new clothes. +% +Beware of friends who are false and deceitful. +% +Beware of low-flying butterflies. +% +Beware of the Turing Tar-pit in which everything is possible but +nothing of interest is easy. +% +Beware the new TTY code! +% +Biggest security gap - an open mouth. +% +Bingo, gas station, hamburger with a side order of airplane noise, +and you'll be Gary, Indiana. - Jessie in the movie "Greaser's Palace" +% +Biography is the fallacy of intention. + ― Peter Taylor +% +Biology ... it grows on you. +% +Birth, n.: The first and direst of all disasters. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Bizarreness is the essence of the exotic +% +Black holes are where God is dividing by zero. +% +Blah. +% +Bleeding into a new computer is always a good thing; it's an ancient geek +voodoo magic to ensure its long life and reliability. + ― from Mike Taht's blog, http://the-edge.blogspot.com/ +% +Blessed are the meek for they shall inhibit the earth. +% +Blessed are they who Go Around in Circles, for they Shall be Known as Wheels. +% +Blessed is the man who is too busy to worry in the daytime and too sleepy to +worry at night. + ― Leo Aikman +% +Blood is thicker than water, and much tastier. +% +Board the windows, up your car insurance, and don't leave any booze in +plain sight. It's St. Patrick's day in Chicago again. The legend has it +that St. Patrick drove the snakes out of Ireland. In fact, he was arrested +for drunk driving. The snakes left because people kept throwing up on +them. +% +Boling's postulate: If you're feeling good, don't worry. You'll get over it. +% +Bolub's Fourth Law of Computerdom: + Project teams detest weekly progress reporting because it so + vividly manifests their lack of progress. +% +Bombeck's Rule of Medicine: Never go to a doctor whose office plants have died. +% +Bond reflected that good Americans were fine people and that most of them +seemed to come from Texas. + ― Ian Fleming, "Casino Royale" +% +Boob's Law: You always find something in the last place you look. +% +Bore, n.: A person who talks when you wish him to listen. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Boren's Laws: + (1) When in charge, ponder. + (2) When in trouble, delegate. + (3) When in doubt, mumble. +% +Boss, n.: + According to the Oxford English Dictionary, in the Middle Ages +the words "boss" and "botch" were largely synonymous, except that boss, +in addition to meaning "a supervisor of workers" also meant "an +ornamental stud." +% +Boston, n.: + Ludwig van Beethoven being jeered by 50,000 sports fans for + finishing second in the Irish jig competition. +% +Boy, n.: + A noise with dirt on it. +% +Bradley's Bromide: If computers get too powerful, we can organize them into a +committee. that will do them in. +% +Bradley's Bromide: If computers get too powerful, we can organize them into a +committee. That will do them in. +% +Brady's First Law of Problem Solving: When confronted by a difficult +problem, you can solve it more easily by reducing it to the question, "How +would the Lone Ranger have handled this?" +% +Brain fried ― core dumped +% +Brain, n.: The apparatus with which we think that we think. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Brain, v. [as in "to brain"]: + To rebuke bluntly, but not pointedly; to dispel a source of +error in an opponent. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Bride, n.: A woman with a fine prospect of happiness behind her. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Bride: A woman with a fine prospect of happiness behind her. +% +Bringing computers into the home won't change either one, but may +revitalize the corner saloon. +% +Broad-mindedness: The result of flattening high-mindedness out. +% +Brook's Law: + Adding manpower to a late software project makes it later. +% +Brooke's Law: + Whenever a system becomes completely defined, some damn fool + discovers something which either abolishes the system or + expands it beyond recognition. +% +Bubble Memory, n.: + A derogatory term, usually referring to a person's + intelligence. See also "vacuum tube". +% +Bucy's Law: Nothing is ever accomplished by a reasonable man. +% +Bug: Small living things that small living boys throw on small living girls. +% +Bumper Sticker: Insanity is hereditary; you get it from your children. +% +Bumper sticker on nuclear war: if you have seen one, you have seen them all. +% +Bunk Carter's Law: At any given moment there are more important people in +the world than important jobs to contain them. +% +Bureaucracy is a giant mechanism operated by pygmies. + ― Balzac +% +Bureaucrat, n.: A politician who has tenure. +% +Bureaucrats cut read tape ― length-wise. +% +Burnt Sienna: That's the best thing that ever happened to Crayolas. + ― Ken Weaver +% +Business will be either better or worse. + ― Calvin Coolidge +% +But in our enthusiasm, we could not resist a radical overhaul of the +system, in which all of its major weaknesses have been exposed, +analyzed, and replaced with new weaknesses. + ― Bruce Leverett, "Register Allocation in Optimizing Compilers" +% +By doing just a little every day, I can gradually let the task completely +overwhelm me. + ― Ashleigh Brilliant +% +By doing just a little every day, you can gradually let the task +completely overwhelm you. +% +By long-standing tradition, I take this opportunity to savage other +designers in the thin disguise of good, clean fun. + ― P. J. Plauger, from his April Fool's column in the April 1988 + issue of "Computer Language" +% +By one count there are some 700 scientists with respectable academic +credentials (out of a total of 480,000 U.S. earth and life scientists) who +give credence to creation-science, the general theory that complex life +forms did not evolve but appeared "abruptly." + ― Newsweek, June 29, 1987, pg. 23 +% +C, n.: A programming language that is sort of like Pascal except more like +assembly except that it isn't very much like either one, or anything else. +It is either the best language available to the art today, or it isn't. + ― Ray Simard +% +C++ : Where friends have access to your private members. + ― Gavin Russell Baker +% +CChheecckk yyoouurr dduupplleexx sswwiittcchh.. + ― Randall Garrett +% +Cabbage, n.: A familiar kitchen-garden vegetable about as large and wise as +a man's head. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Cabbage: A familiar kitchen-garden vegetable about as large and wise +as a man's head. +% +Caeca invidia est. (Envy is blind.) + ― Livy +% +Cahn's Axiom: When all else fails, read the instructions. +% +California is a fine place to live ― if you happen to be an orange. + ― Fred Allen +% +California is the ghost of Christmas future for the rest of America. + ― anonymous post to an Internet forum +% +California is the land of perpetual pubescence, where cultural lag is +mistaken for renaissance. + ― Ashley Montagu +% +Call on God, but row away from the rocks. + ― Indian proverb +% +Can anyone remember when the times were not hard, and money not scarce? +% +Can anything be sadder than work left unfinished? Yes, work never begun. +% +Cannot fork ― try again. +% +Cannot fortune open database. +% +Captain Penny's Law: You can fool all of the people some of the time, +and some of the people all of the time, but you can't fool Mom. +% +Carelessly planned projects take three times longer to complete than +expected. Carefully planned projects take four times longer to +complete than expected, mostly because the planners expect their +planning to reduce the time it takes. +% +Carperpetuation (kar' pur pet u a shun), n.: + The act, when vacuuming, of running over a string at least a +dozen times, reaching over and picking it up, examining it, then +putting it back down to give the vacuum one more chance. + ― Rich Hall, "Sniglets" +% +Catch a wave and you're sitting on top of the world. +% +Certain old men prefer to rise at dawn, taking a cold bath and a long walk +with an empty stomach and otherwise mortifying the flesh. They then point +with pride to these practices as the cause of their sturdy health and ripe +years; the truth being that they are hearty and old, not because of their +habits, but in spite of them. The reason we find only robust persons doing +this thing is that it has killed all the others who have tried it. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Change is what people fear most. + ― Dostoevski +% +Change your thoughts and you change your world. +% +Character Density: the number of very weird people in the office. +% +Character is the ligament holding together all other qualities. + ― Arnold Glasow +% +Chemicals, n.: Noxious substances from which modern foods are made. +% +Chicken Little was right. +% +Children are natural mimics who act like their parents despite every effort +to teach them good manners. +% +Children aren't happy without something to ignore, +And that's what parents were created for. + ― Ogden Nash +% +Children begin by loving their parents. After a time they judge them. Rarely, +if ever, do they forgive them. + ― Oscar Wilde +% +Children have more need of models than of critics. +% +Children seldom misquote you. In fact, they usually repeat word for +word what you shouldn't have said. +% +Chism's Law of Completion: + The amount of time required to complete a government project is + precisely equal to the length of time already spent on it. +% +Chisolm's First Corollary to Murphy's Second Law: + When things just can't possibly get any worse, they will. +% +Civilisation is the art of living in towns of such size that everyone does +not know everyone else. + ― Julian Jaynes +% +Civilization Law #1: Civilization advances by extending the number of +important operations one can do without thinking about them. +% +Civilization is a movement, not a condition; it is a voyage, not a harbor. + ― Toynbee +% +Civilization is the progress toward a society of privacy. + ― Howard Roark, in Ayn Rand's _The Fountainhead_ +% +[Classical music] would be a lot more popular if they gave the pieces titles +like "Kill the Wabbit." + ― Mark Fetherolf. +% +Classified material requires proper storage. +% +Cleanliness is next to impossible. +% +Cogito cogito ergo cogito sum ― +"I think that I think, therefore I think that I am." + ― Ambrose Bierce, "The Devil's Dictionary" +% +Cogito ergo doleo. (I think, therefore I am depressed.) +% +Cogito ergo sum. +% +Cohen's Law: Everyone knows that the name of the game is what label you +succeed in imposing on the facts. +% +Collaboration, n.: A literary partnership based on the false assumption +that the other fellow can spell. +% +College isn't the place to go for ideas. + ― Hellen Keller +% +Colorless green ideas sleep furiously. +% +Come to think of it, there are already a million monkeys on a million +typewriters, and Usenet is nothing like Shakespeare. + ― Blair Houghton +% +Commitment, n.: Commitment can be illustrated by a breakfast of ham and +eggs. The chicken was involved, the pig was committed. +% +Common sense in an uncommon degree is what the world calls wisdom. + ― Samuel Taylor Coleridge +% +Complacency is the enemy of progress. + ― Dave Stutman +% +Computer Science is merely the post-Turing decline in formal systems theory. +% +Computer Science: the boring art of coping with a large number of trivialities +(The Devil's DP Dictionary) +% +Computer literacy is a contact with the activity of computing deep enough to +make the computational equivalent of reading and writing fluent and enjoyable. +As in all the arts, a romance with the material must be well under way. If +we value the lifelong learning of arts and letters as a springboard for +personal and societal growth, should any less effort be spent to make computing +a part of our lives? + ― Alan Kay, "Computer Software", Scientific American, September 1984 +% +Conceit causes more conversation than wit. + ― LaRouchefoucauld +% +Concept, n.: Any "idea" for which an outside consultant billed you more than +$25,000. +% +Conceptual integrity in turn dictates that the design must proceed from one +mind, or from a very small number of agreeing resonant minds. + ― Frederick Brooks Jr., "The Mythical Man Month" +% +Confession is good for the soul only in the sense that a tweed coat is +good for dandruff. + ― Peter de Vries +% +Confidence is the feeling you have before you understand the situation. +% +Confound these ancestors.... They've stolen our best ideas! + ― Ben Jonson +% +Confusticate and bebother these dwarves! +% +Conscience is what hurts when everything else feels so good. +% +Conservative, n.: One who admires radicals centuries after they're dead. + ― Leo C. Rosten +% +Consultants are mystical people who ask a company for a number and then +give it back to them. +% +Controlling complexity is the essence of computer programming. + ― Brian W. Kernighan +% +Conversation, n.: A vocal competition in which the one who is catching his +breath is called the listener. +% +Conway's Law: Any piece of software reflects the organizational structure +that produced it. +% +Coronation, n.: The ceremony of investing a sovereign with the outward and +visible signs of his divine right to be blown sky-high with a dynamite bomb. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Corporation, n. An ingenious device for obtaining individual profit +without individual responsibility. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Corripe Cervisiam! +% +Corrupt, adj.: In politics, holding an office of trust or profit. +% +Corruption is not the #1 priority of the Police Commissioner. His job +is to enforce the law and fight crime. + ― P.B.A. President E. J. Kiernan +% +Courage is grace under pressure. +% +Coward, n.: One who in a perilous emergency thinks with his legs. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Crash programs fail because they are based on the theory that, with +nine women pregnant, you can get a baby a month. + ― Wernher von Braun +% +Creativity cannot be diminished by the medium of expression. + ― Mitch Allen +% +Creationists make it sound as though a "theory" is something you dreamt up +after being drunk all night. + ― Isaac Asimov +% +Creditors have better memories than debtors. + ― Benjamin Franklin, Poor Richard's Almanack (1758) +% +Crime does not pay ... as well as politics. + ― A. E. Newman +% +Criminal: A person with predatory instincts who has not sufficient capital +to form a corporation. + ― Howard Scott +% +Critic, n.: A person who boasts himself hard to please because nobody tries +to please him. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Cudgel thy brains no more about it, for your dull ass will not mend his +pace with beating. + ― Hamlet, Act 5, Scene 1 +% +Culture is the habit of being pleased with the best and knowing why. +% +Cynic, n.: A blackguard whose faulty vision sees things as they are, not +as they ought to be. Hence the custom among the Scythians of plucking +out a cynic's eyes to improve his vision. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Cynic, n.: One who looks through rose-colored glasses with a jaundiced eye. +% +Daring ideas are like chessmen moved forward, +they may be beaten, but they may start a winning game. + ― J. W. von Goethe +% +Dawn, n.: The time when men of reason go to bed. + ― Ambrose Bierce, "The Devil's Dictionary" +% +De Borglie rules the wave, but Heisenberg waived the rules. + ― Piggins +% +Dealing with failure is easy: work hard to improve. Success is also easy to +handle: you've solved the wrong problem. Work hard to improve. +% +Death is God's way of telling you not to be such a wise guy. +% +Death is Nature's way of recycling human beings. +% +Death is Nature's way of saying, "slow down". +% +Death is life's way of telling you you've been fired. + ― R. Geis +% +Death: to stop sinning suddenly. +% +Debugging is anticipated with distaste, performed with reluctance, and bragged +about forever. + ― button at the Boston Computer Museum +% +Debugging is twice as hard as writing the code in the first place. +Therefore, if you write the code as cleverly as possible, you are―by +definition―not smart enough to debug it. + ― Brian Kernighan +% +Decisionmaker, n.: The person in your office who was unable to form a task +force before the music stopped. + +% +Decisions of the judges will be final unless shouted down by a really +overwhelming majority of the crowd present. Abusive and obscene language +may not be used by contestants when addressing members of the judging +panel, or, conversely, by members of the judging panel when addressing +contestants (unless struck by a boomerang). + ― Mudgeeraba Creek Emu-Riding and Boomerang-Throwing Association +% +Decisions terminate panic. +% +Deliberation, n.: The act of examining one's bread to determine which side it +is buttered on. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Democracy is a form of government in which it is permitted to wonder +aloud what the country could do under first-class management. + ― Senator Soaper +% +Democracy is a form of government that substitutes election by the +incompetent many for appointment by the corrupt few. + ― G. B. Shaw +% +Democracy is four wolves and a lamb, voting on what to have for lunch. +% +Democracy is the recurrent suspicion that more than half of the people +are right more than half of the time. + ― E. B. White +% +Denniston's Law: Virtue is its own punishment. +% +Deprive a mirror of its silver, and even the Czar won't see his face. +% +Der Unterschied zwischen Genie und Wahnsinn liegt nur im Erfolg. +[The only difference between genius and insanity is the success.] +% +Did I forget to mention, forget to mention Memphis? +Home of Elvis and the ancient Greeks. +Do I smell? I smell home cooking. +It's only the river, it's only the river. + ― Talking Heads (Cities) +% +Did you know gullible is not in the dictionary? +% +Different all twisty a of in maze are you, passages little. +% +Digital computers are themselves more complex than most things people build: +They have very large numbers of states. This makes conceiving, describing, +and testing them hard. Software systems have orders-of-magnitude more states +than computers do. + ― Fred Brooks, Jr. +% +Dimensions will always be expressed in the least usable term. +Velocity, for example, will be expressed in furlongs per fortnight. +% +Diplomacy is the art of extricating oneself from a situation that tact +would have prevented in the first place. +% +Diplomacy is the art of saying "nice doggy" until you can find a rock. +% +Disc space ― the final frontier! +% +Disco is to music what Etch-A-Sketch is to art. +% +Discovery consists in seeing what everyone else has seen and thinking what no +one else has thought. + ― Albert Szent-Gyorgi +% +Distress, n.: A disease incurred by exposure to the prosperity of a friend. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Do not allow this language (Ada) in its present state to be used in +applications where reliability is critical, i.e., nuclear power stations, +cruise missiles, early warning systems, anti-ballistic missle defense +systems. The next rocket to go astray as a result of a programming language +error may not be an exploratory space rocket on a harmless trip to Venus: +It may be a nuclear warhead exploding over one of our cities. An unreliable +programming language generating unreliable programs constitutes a far +greater risk to our environment and to our society than unsafe cars, toxic +pesticides, or accidents at nuclear power stations. + ― C. A. R. Hoare +% +Do not merely believe in miracles, rely on them. +% +Do not clog intellect's sluices with bits of knowledge of questionable uses. +% +Do not compromise yourself; you are all you have got. + ― Janis Joplin +% +Do not take life too seriously; you will never get out of it alive. +% +Do not try to solve all life's problems at once ― learn to dread each +day as it comes. + ― Donald Kaul +% +Do not underestimate the value of print statements for debugging. +Don't have aesthetic convulsions when using them, either. +% +Do you realize how many holes there could be if people would just take +the time to take the dirt out of them? +% +Documentation is like sex: when it is good, it is very, very good; and +when it is bad, it is better than nothing. + ― Dick Brandon +% +Documentation is the castor oil of programming. Managers know it must +be good because the programmers hate it so much. +% +Don't be overly suspicious where it's not warranted. +% +Don't believe everything you hear or anything you say. +% +Don't comment bad code: rewrite it. +% +Don't compare floating point numbers solely for equality. +% +Don't crush that dwarf, hand me the pliers. +% +Don't diddle code to make it faster, find a better algorithm. +% +Dobbin's Law: When in doubt, use a bigger hammer. +% +Don't get suckered in by the comments ― they can be terribly misleading. +Debug only code. + ― Dave Storer +% +Don't knock President Fillmore. He kept us out of Vietnam. +% +Don't learn the tricks of the trade, learn the trade. +% +Don't let your mouth write no check that your tail can't cash. + ― Bo Diddley +% +Don't look back, the lemmings are gaining on you. +% +Don't put off for tomorrow what you can do today, because if you enjoy +it today you can do it again tomorrow. +% +Don't tell me how hard you work. Tell me how much you get done. + ― James J. Ling +% +Don't try to outweird me, three-eyes. I get stranger things than you free +with my breakfast cereal. + ― Zaphod Beeblebrox +% +Don't worry about the world coming to an end today. It's already +tomorrow in Australia. + ― Charles Schultz +% +Don't worry about things that you have no control over, because you have no +control over them. Don't worry about things that you have control over, +because you have control over them. + ― Mickey Rivers +% +Don't worry about what other people are thinking about you. They're too +busy worrying about what you are thinking about them. +% +Doubt is not a pleasant condition, but certainty is absurd. + ― Voltaire +% +Doubt isn't the opposite of faith; it is an element of faith. + ― Paul Tillich, German theologian and historian +% +Doubts and jealousies often beget the facts they fear. + ― Thomas Jefferson +% +Down with categorical imperative! +% +Drawing on my fine command of language, I said nothing. +% +Ducharme's Axiom: If you view your problem closely enough you will recognize +yourself as part of the problem. +% +Ducharme's Precept: Opportunity always knocks at the least opportune moment. +% +Duct tape is like the force. It has a light side, and a dark side, and +it holds the universe together ... + ― Carl Zwanzig +% +Due to a shortage of devoted followers, the production of great leaders +has been discontinued. +% +Due to circumstances beyond your control, you are master of your fate +and captain of your soul. +% +Dum excusare credis, accusas. (When you believe you are excusing yourself, +you are accusing yourself.) + ― St. Jerome +% +Dunne's Law: The territory behind rhetoric is too often mined with +equivocation. +% +During almost fifteen centuries the legal establishment of Christianity has +been upon trial. What has been its fruits? More or less, in all places, +pride and indolence in the clergy; ignorance and servility in the laity; +in both, superstition, bigotry, and persecution. + ― James Madison +% +Dying is a very dull, dreary affair. And my advice to you is to +have nothing whatever to do with it. + ― W. Somerset Maughm +% +E Pluribus Unix +% +Each honest calling, each walk of life, has its own elite, its own aristocracy +based on excellence of performance. + ― James Bryant Conant +% +Each team building another component has been using the most recent tested +version of the integrated system as a test bed for debugging its piece. Their +work will be set back by having that test bed change under them. Of course it +must. But the changes need to be quantized. Then each user has periods of +productive stability, interrupted by bursts of test-bed change. This seems +to be much less disruptive than a constant rippling and trembling. + ― Frederick Brooks Jr., "The Mythical Man Month" +% +Economics is extremely useful as a form of employment for economists. + ― John Kenneth Galbraith +% +Economics, n.: Economics is the study of the value and meaning of J. K. +Galbraith ... + ― Mike Harding, "The Armchair Anarchist's Almanac" +% +Economy makes men independent. +% +Education has produced a vast population able to read but unable to distinguish +what is worth reading. + ― G. M. Trevelyan +% +Education helps earning capacity. Ask any college professor. +% +Een schip op het strand is een baken in zee. +[A ship on the beach is a lighthouse to the sea.] + ― Dutch Proverb +% +Eeny Meeny, Jelly Beanie, the spirits are about to speak. + ― Bullwinkle Moose +% +Eggheads unite! You have nothing to lose but your yolks. + ― Adlai Stevenson +% +Egotism is the anesthetic given by a kindly nature to relieve the pain +of being a damned fool. + ― Bellamy Brooks +% +Egotism is the anesthetic that dulls the pain of stupidity. + ― Frank Leahy +% +Egotist, n.: A person of low taste, more interested in himself than in me. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Ehrman's Commentary: + 1. Things will get worse before they get better. + 2. Who said things would get better? +% +Eighty percent of air pollution comes from plants and trees. + ― Ronald Reagan, famous movie star +% +Einstein argued that there must be simplified explanations of nature, because +God is not capricious or arbitrary. No such faith comforts the software +engineer. + ― Fred Brooks, Jr. +% +Either do not attempt at all, or go through with it. + ― Ovid +% +Either that wallpaper goes, or I do. + ― Oscar Wilde's last words +% +Electrocution: Burning at the stake with all the modern improvements. +% +Elevators smell different to midgets +% +Eloquence is vehement simplicity. + ― Cecil +% +Emersons' Law of Contrariness: Our chief want in life is somebody who shall +make us do what we can. Having found them, we shall then hate them for it. +% +Endless Loop: n., see Loop, Endless. +Loop, Endless: n., see Endless Loop. + ― Random Shack Data Processing Dictionary +% +Enjoy your life; be pleasant and gay, like the birds in May. +% +Entropy isn't what it used to be. +% +Envy always implies conscious inferiority wherever it resides. + ― Pliny +% +Enzymes are things invented by biologists that explain things which +otherwise require harder thinking. + ― Jerome Lettvin +% +Equal bytes for women. +% +Eschew obfuscatory digressiveness. + ― Barry Dancis (1983) +% +Eternal nothingness is fine if you happen to be dressed for it. + ― Woody Allen +% +Ettore's observation: the other line moves faster. +% +Etymology, n.: Some early etymological scholars came up with derivations that +were hard for the public to believe. The term "etymology" was formed +from the Latin "etus" ("eaten"), the root "mal" ("bad"), and "logy" +("study of"). It meant "the study of things that are hard to swallow." + ― Mike Kellen +% +Even a cabbage may look at a king. +% +Even a hawk is an eagle among crows. +% +Even if you can deceive people about a product through misleading statements, +sooner or later the product will speak for itself. + ― Hajime Karatsu +% +Even if you do learn to speak correct English, whom are you going to +speak it to? + ― Clarence Darrow +% +Even the boldest zebra fears the hungry lion. +% +Even the future comes one day at a time. + ― W. Woodhouse +% +Even the smallest candle burns brighter in the dark. +% +Even though they raised the rate for first class mail in the United +States we really shouldn't complain ― it's still only 2 cents a day. +% +Ever notice that even the busiest people are never too busy to tell you +just how busy they are. +% +Ever wander around the web, look at discussions, totally agree with one of +the points of view, and then notice it was posted under one of your web +aliases 5 years ago? + ― Larry Weber +% +Every 4 seconds a woman has a baby. Our problem is to find this woman +and stop her. +% +Every Horse has an Infinite Number of Legs (proof by intimidation): +Horses have an even number of legs. Behind they have two legs, and in +front they have fore-legs. This makes six legs, which is certainly an +odd number of legs for a horse. But the only number that is both even +and odd is infinity. Therefore, horses have an infinite number of +legs. Now to show this for the general case, suppose that somewhere, +there is a horse that has a finite number of legs. But that is a horse +of another color, and by the [above] lemma ["All horses are the same +color"], that does not exist. +% +Every Solidarity center had piles and piles of paper .... everyone was +eating paper and a policeman was at the door. Now all you have to do is +bend a disk. + ― an anonymous member of the outlawed Polish trade union, Solidarity, + commenting on the benefits of using computers in support of their + movement +% +Every absurdity has a champion to defend it. +% +Every creature has within him the wild, uncontrollable urge to punt. +% +Every gun that is made, every warship launched, every rocket fired +signifies in the final sense, a theft from those who hunger and are not +fed, those who are cold and are not clothed. This world in arms is not +spending money alone. It is spending the sweat of its laborers, the +genius of its scientists, the hopes of its children. This is not a way +of life at all in any true sense. Under the clouds of war, it is +humanity hanging on a cross of iron. + ― Dwight Eisenhower, April 16, 1953 +% +Every institution I've ever been associated with has tried to screw me. + ― Stephen Wolfram +% +Every little picofarad has a nanohenry all its own. + ― Don Vonada +% +Every man is as God made him, ay, and often worse. + ― Miguel de Cervantes +% +Every program has at least one bug and can be shortened by at least one +instruction ― from which, by induction, one can deduce that every +program can be reduced to one instruction which doesn't work. +% +Every program has two purposes ― one for which it was written and another +for which it wasn't. +% +Every program is a part of some other program, and rarely fits. +% +Every purchase has its price. +% +Every silver lining has a cloud around it. +% +Every solution breeds new problems. +% +Every successful person has had failures, but repeated failure is no +guarantee of eventual success. +% +Every word is like an unnecessary stain on silence and nothingness. + ― Beckett +% +Everything is better with no people. + ― Bob "Biff" Rendar +% +Dykstra's Law: Everybody is somebody else's weirdo. +% +Everything is controlled by a small evil group to which, unfortunately, +no one we know belongs. +% +Everything to excess! Moderation is for monks. + ― Lazarus Long +% +Everything you know is wrong. + ― The Firesign Theater +% +Everything you've learned in school as "obvious" becomes less and less +obvious as you begin to study the universe. For example, there are no +solids in the universe. There's not even a suggestion of a solid. There +are no absolute continuums. There are no surfaces. There are no straight +lines. + ― R. Buckminster Fuller +% +Everything should be built top-down, except the first time. +% +Evolution is a bankrupt speculative philosophy, not a scientific fact. +Only a spiritually bankrupt society could ever believe it. ... Only +atheists could accept this Satanic theory. + ― Rev. Jimmy Swaggart, "The Pre-Adamic Creation and Evolution" +% +Evolution does not require the nonexistence of God, it merely allows for +it. That alone is enough to evoke condemnation from those who fear the +nonexistence of God more than they fear God Himself. + ― Keith Doyle, in talk.origins +% +Evolution is both fact and theory. Creationism is neither. + ― Anonymous +% +Exactitude in small matters is the essence of discipline. +% +Example is the school of mankind, and they will learn at no other. +% +Excellent day to have a rotten day. +% +Excellent time to become a missing person. +% +Excess on occasion is exhilarating. It prevents moderation from +acquiring the deadening effect of a habit. + ― W. Somerset Maugham +% +Excessive login or logout messages are a sure sign of senility. +% +Excuse me while I change into something more formidable. +% +Executive ability is prominent in your make-up. +% +Expense Accounts, n.: Corporate food stamps. +% +Experience is a dear teacher, but fools will learn at no other. + ― Poor Richard's Almanac +% +Experience is something you don't get until just after you need it. + ― Olivier +% +Experience is that marvelous thing that enables you recognize a mistake when +you make it again. + ― Franklin P. Jones +% +Experience is the worst teacher. It always gives the test first and +the instructions afterward. +% +Experience is what causes a person to make new mistakes instead of old ones. +% +Experience is what you get when you were expecting something else. +% +Extreme good-naturedness borders on weakness of character. Avoid it. +% +Extremes of fortune are fatal to folks of small dimensions. + ― Arnold Glasow +% +FLASH! Intelligence of mankind decreasing. Details at ... uh, when +the little hand is on the .... +% +Facts do not cease to exist because they are ignored. +% +Facts are simple and facts are straight / Facts are lazy and facts are late. +Facts all come with points of view / Facts don't do what I want them to. +Facts just twist the truth around / Facts are living turned inside out. +Facts are getting the best of them / Facts are nothing on the face of things. +Facts don't stain the furniture / Facts go out and slam the door. +Facts are written all over your face / Facts continue to change their shape. + ― Talking Heads +% +Failing to get them to do it your way might mean they're stupid, but it also +means you failed to get them to do it your way. + ― Cal Keegan +% +Failure is more frequently from want of energy than want of capital. +% +Failure is not an option. It comes bundled with your Microsoft product. + ― Ferenc Mantfeld +% +Faire de la bonne cuisine demande un certain temps. Si on vous fait attendre, +c'est pour mieux vous servir, et vous plaire. +[Good cooking takes time. If you are made to wait, it is to serve you better, +and to please you.] + ― Menu of Restaurant Antoine, New Orleans + [Also, what we're going to be telling our customers] +% +Fairy Tale: A horror story to prepare children for the newspapers. +% +Falling in love makes smoking pot all day look like the ultimate in restraint. + ― Dave Sim, author of "Cerberus the Aardvark" +% +Familiarity breeds attempt +% +Familiarity breeds children. +% +Familiarity breeds contempt. +% +Families, when a child is born/Want it to be intelligent. +I, through intelligence,/Having wrecked my whole life, +Only hope the baby will prove/Ignorant and stupid. +Then he will crown a tranquil life/By becoming a Cabinet Minister + ― Su Tung-p'o +% +Fanaticism consists of redoubling your efforts when you have forgotten your +aim. + ― Santayana +% +Fantasy, abandoned by reason, produces impossible monsters; +united with it, she is the mother of the arts and the origin of marvels. + ― Goya +% +Far better it is to dare mighty things, to win glorious triumphs, even though +checkered by failure, than to take rank with those poor spirits who neither +enjoy much nor suffer much, because they live in the gray twilight that knows +not victory or defeat. + ― Theodore Roosevelt +% +Far duller than a serpent's tooth it is to spend a quiet youth. + +% +Fashion is a form of ugliness so intolerable that we have to alter it +every six months. + ― Oscar Wilde +% +Felson's Law: To steal ideas from one person is plagiarism; to steal from +many is research. +% +Fidelity: A virtue peculiar to those who are about to be betrayed. +% +Field theories, unite! +% +Finagle's Creed: Science is true. Don't be misled by facts. +% +Finagle's First Law: If an experiment works, something has gone wrong. +% +Finagle's Second Law: Once a job is fouled up, anything done to improve it +only makes it worse. +% +Finding the occasional straw of truth awash in a great ocean of confusion and +bamboozle requires intelligence, vigilance, dedication and courage. But if we +don't practice these tough habits of thought, we cannot hope to solve the truly +serious problems that face us ― and we risk becoming a nation of suckers, up +for grabs by the next charlatan who comes along. + ― Carl Sagan, "The Fine Art of Baloney Detection," Parade, + February 1, 1987 +% +Fine, Java MIGHT be a good example of what a programming language should be +like. But Java applications are good examples of what applications +SHOULDN'T be like. + ― pixadel +% +Fine day to throw a party. Throw him as far as you can. +% +Fine day to work off excess energy. Steal something heavy. +% +Finster's Law: a closed mouth gathers no feet. +% +First Law of Procrastination: Procrastination shortens the job and places +the responsibility for its termination on someone else (i.e., the authority +who imposed the deadline). +% +First Law of Socio-Genetics: Celibacy is not hereditary. +% +First Rule of History: History doesn't repeat itself, historians merely +repeat each other. +% +Flee at once: All is discovered. +% +Flon's Law: + There is not now, and never will be, a language in which it is + the least bit difficult to write bad programs. +% +Flugg's Law: + When you need to knock on wood is when you realize that the + world is composed of vinyl, naugahyde and aluminum. +% +Follow the river and you will eventually find the sea. +% +Football combines the two worst features of American life: violence and +committee meetings. + ― George Will +% +For a really sweet time, call C6H12O6. +% +For a while there I was worried that my tin foil beanie was blocking the +TopFive.com website. Luckily it turned out to be a router problem. + ― Attributed to "wubwub", quoted on www.ruminate.com (2004) +% +For an idea to be fashionable is ominous, since it must afterwards be +always old-fashioned. +% +For every action, there is an equal and opposite criticism. +% +For every credibility gap, there is a gullibility fill. + ― R. Clopton +% +For some reason a glaze passes over people's faces when you say +"Canada". Maybe we should invade South Dakota or something. + ― Sandra Gotlieb, wife of the Canadian ambassador to + the U.S. +% +For some reason, this fortune reminds everyone of Marvin Zelkowitz. +% +For the politicians this was never about how efficient they could make +things happen or how to solve a problem, it is about the *appearance* of +efficiency, or problem solving. My observation is that most politicians +think more like sales people than technicians, and are about as clueful. +Which means, unless the politicians change the way they think, discussion +about how to use *them* to go about really solving these problems would be +like asking a booth babe to write a kernel module. + ― Rich Costine +% +For those who like this sort of thing, this is the sort of thing they like. + ― Abraham Lincoln +% +Forgetfulness, n.: A gift of God bestowed upon debtors in compensation for +their destitution of conscience. +% +Fourth Law of Revision: It is usually impractical to worry beforehand about +interferences ― if you have none, someone will make one for you. +% +Fourth Law of Thermodymanics: +If the probability of success is not almost one, then it is damn near zero. + ― David Ellis +% +Frankly my dear, I don't give a damn. +% +Fresco's Discovery: If you knew what you were doing you'd probably be bored. +% +Friends: people who borrow my books and set wet glasses on them. +% +Frisbeetarianism, n.: The belief that when you die, your soul goes up on the +roof and gets stuck. +% +Frobnicate, v.: + To manipulate or adjust, to tweak. Derived from FROBNITZ. +Usually abbreviated to FROB. Thus one has the saying "to frob a +frob". See TWEAK and TWIDDLE. Usage: FROB, TWIDDLE, and TWEAK +sometimes connote points along a continuum. FROB connotes aimless +manipulation; TWIDDLE connotes gross manipulation, often a coarse +search for a proper setting; TWEAK connotes fine-tuning. If someone is +turning a knob on an oscilloscope, then if he's carefully adjusting it +he is probably tweaking it; if he is just turning it but looking at the +screen he is probably twiddling it; but if he's just doing it because +turning a knob is fun, he's frobbing it. +% +From the ice-age to the dole-age +there is but one concern +and I have just discovered: +some girls are bigger than others +some girls are bigger than others +some girls are bigger than +other girls' mothers + ― The Smiths +% +From too much love of living/From hope and fear set free, +We thank with brief thanksgiving/Whatever gods may be, +That no life lives forever/That dead men rise up never, +That even the weariest river winds somewhere safe to sea. + ― Swinburne +% +Froud's Law: A transistor protected by a fast acting fuse will protect the +fuse by blowing first. +% +Fudd's First Law of Opposition: Push something hard enough and it will +fall over. +% +Furbling, v.: Having to wander through a maze of ropes at an airport or bank +even when you are the only person in line. + ― Rich Hall, "Sniglets" +% +Furious activity is no substitute for understanding. + ― H. H. Williams +% +Gadji beri bimba clandridi/Lauli lonni cadori gadjam +A bim beri glassala glandride/E glassala tuffm I Zimbra. + ― Talking Heads (I Zimbra) +% +G. B. Shaw to William Douglas Home: "Go on writing plays, my boy. One +of these days a London producer will go into his office and say to his +secretary, `Is there a play from Shaw this morning?' and when she says +`No,' he will say, `Well, then we'll have to start on the rubbish.' +And that's your chance, my boy." +% +Garbage In ― Gospel Out. +% +Garter, n.: An elastic band intended to keep a woman from coming out of her +stockings and desolating the country. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Genderplex, n.: The predicament of a person in a restaurant who is unable to +determine his or her designated restroom (e.g., turtles and tortoises). + ― Rich Hall, "Sniglets" +% +Gene Police: YOU! Out of the pool! +% +Generosity and perfection are your everlasting goals. +% +Genetics explains why you look like your father, and if you don't, why +you should. +% +Genius is the talent of a man who is dead. +% +Genius may have its limitations, but stupidity is not thus handicapped. + ― Elbert Hubbard +% +Genius: A chemist who discovers a laundry additive that rhymes with "bright". +% +Genuinely skillful use of obscenities is uniformly absent on the Internet. + ― Karl Kleinpaste +% +Geology shows that fossils are of different ages. Paleontology shows a +fossil sequence, the list of species represented changes through time. +Taxonomy shows biological relationships among species. Evolution is the +explanation that threads it all together. Creationism is the practice of +squeeezing one's eyes shut and wailing, "Does not!" + ― Dr.Pepper@f241.n103.z1.fidonet.org +% +George Orwell was an optimist. +% +Get forgiveness now ― tomorrow you may no longer feel guilty. +% +Get hold of portable property. + ― Charles Dickens, "Great Expectations" +% +Give a man a fish, and you feed him for a day. +Teach a man to fish, and he'll invite himself over for dinner. + ― Calvin Keegan +% +Give a small boy a hammer and he will find that everything he encounters needs +pounding. + ― Abraham Kaplan +% +Give big space to the festive dog that shall sport in the roadway. +% +Give me a plumber's friend the size of the Pittsburgh Dome, and a place +to stand, and I will drain the world. +% +Give up. +% +Giving advice is not as risky as people say; few ever take it anyway. +% +Glib's Fourth Law of Unreliability: Investment in reliability will increase +until it exceeds the probable cost of errors, or until someone insists on +getting some useful work done. +% +Go placidly amid the noise and waste, and remember what value there may +be in owning a piece thereof. + ― National Lampoon, "Deteriorada" +% +Go soothingly in the grease mud, as there lurks the skid demon. +% +Go west young, man. +% +God did not create the world in 7 days; he screwed around for 6 days +and then pulled an all-nighter. +% +God does not play dice with the universe. +% +God gives us relatives; thank goodness we can choose our friends. +% +God has intended the great to be great and the little to be little ... The +trade unions, under the European system, destroy liberty ... I do not mean +to say that a dollar a day is enough to support a workingman ... not enough +to support a man and five children if he insists on smoking and drinking +beer. But the man who cannot live on bread and water is not fit to live! +A family may live on good bread and water in the morning, water and bread +at midday, and good bread and water at night! + ― Rev. Henry Ward Beecher +% +God is a comedian playing to an audience too afraid to laugh. + ― Voltaire +% +God is a polytheist. +% +God is a verb, not a noun. +% +God is an atheist. +% +God is playing a comic to an audience that's afraid to laugh. +% +God is real, unless declared integer. +% +God is really only another artist. He invented the giraffe, the elephant +and the cat. He has no real style, He just goes on trying other things. + ― Pablo Picasso +% +God is the tangential point between zero and infinity. + ― Alfred Jarry +% +God made machine language; all the rest is the work of man. +% +God made the integers; all else is the work of Man. + ― Kronecker +% +God made the world in six days, and was arrested on the seventh. +% +God requireth not a uniformity of religion. + ― Roger Williams +% +God runs electromagnetics by wave theory on Monday, Wednesday, and Friday, +and the Devil runs them by quantum theory on Tuesday, Thursday, and +Saturday. + ― William Bragg +% +Godwin's Law: As an online discussion grows longer, the probability of a +comparison involving Nazis or Hitler approaches one. +% +Going the speed of light is bad for your age. +% +Going to church does not make a person religious, nor does going to school +make a person educated, any more than going to a garage makes a person a car. +% +Goldenstern's Rules: + 1. Always hire a rich attorney + 2. Never buy from a rich salesman. +% +Good advice is something a man gives when he is too old to set a bad example. + ― La Rouchefoucauld +% +Good advice is something a man gives when he is too old to set a bad +example. + ― La Rouchefoucauld +% +Good leaders being scarce, following yourself is allowed. +% +Good-bye. I am leaving because I am bored. + ― George Saunders' dying words +% +Got Mole problems? Call Avogadro, 6.02 E23. +% +Goto, n.: A programming tool that exists to allow structured programmers +to complain about unstructured programmers. + ― Ray Simard +% +Government expands to absorb all revenue and then some. +% +Government is an association of men who do violence to the rest of us. + ― Tolstoy +% +Government sucks. + ― Ben Olson +% +Grabel's Law: + 2 is not equal to 3 ― not even for large values of 2. +% +Graduate life ― it's not just a job, it's an indenture. +% +Grain grows best in shit. + ― Ursula K. LeGuin +% +Grandpa Charnock's Law: + You never really learn to swear until you learn to drive. +% +Granholm's Definition of the Kludge: An ill-assorted collection of poorly +matching parts forming a distressing whole. + ― Jackson W. Granholm, "How to Design a Kludge," + Datamation, Feb. 1962 +% +Gray's Law of Programming: + `N+1' trivial tasks are expected to be accomplished in the same + time as `N' tasks. + +Logg's Rebuttal to Gray's Law: + `N+1' trivial tasks take twice as long as `N' trivial tasks. +% +Great people talk about ideas, average people talk about things, and small +people talk about wine. + ― Fran Lebowitz +% +Greatness is a transitory experience. It is never consistent. +% +Greener's Law: Never argue with a man who buys ink by the barrel. +% +Grelb's Reminder: Eighty percent of all people consider themselves to be above +average drivers. +% +Hacker's Law: The belief that enhanced understanding will necessarily stir +a nation to action is one of mankind's oldest illusions. + ― Andrew Hacker, The End of the American Era (1970) +% +Haggis is a kind of stuffed black pudding eaten by the Scots and considered +by them to be not only a delicacy but fit for human consumption. The minced +heart, liver and lungs of a sheep, calf or other animal's inner organs are +mixed with oatmeal, sealed and boiled in maw in the sheep's intestinal +stomach-bag and ... Excuse me a minute ... +% +Half of one, six dozen of the other. +% +Half the things that people do not succeed in are through fear of making +the attempt. +% +Hand, n.: A singular instrument worn at the end of a human arm and +commonly thrust into somebody's pocket. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Hanlon's Razor: Never attribute to malice that which is adequately +explained by stupidity. +% +Hanson's Treatment of Time: + There are never enough hours in a day, but always too many days + before Saturday. +% +Happiness adds and multiplies as we divide it with others. +% +Happiness comes and goes and is short on staying power. + ― Frank Tyger +% +Happiness is having a scratch for every itch. + ― Ogden Nash +% +Happiness isn't something you experience; it's something you remember. + ― Oscar Levant +% +Happiness, n.: An agreeable sensation arising from contemplating the misery of +another. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Happiness: An agreeable sensation arising from contemplating the misery +of another. +% +Hardware, n.: The parts of a computer system that can be kicked. +% +Harris' Lament: All the good ones are taken. +% +Harris's Lament: + All the good ones are taken. +% +Harrisberger's Second Law of the Lab: No matter what result it anticipated, +there is always someone willing to fake it. +% +Harrisberger's Third Law of the Lab: Experiments should be reproducive. +They should all fail in the same way. +% +Harrisberger's Fourth Law of the Lab: Experience is directly proportional +to the amount of equipment ruined. +% +Harrison's Postulate: + For every action, there is an equal and opposite criticism. +% +Hartley's First Law: + You can lead a horse to water, but if you can get him to float + on his back, you've got something. +% +Hartley's Second Law: Never sleep with anyone crazier than yourself. +% +Harvard Law: Under the most rigorously controlled conditions of pressure, +temperature, volume, humidity, and other variables, the organism will do as +it damn well pleases. +% +Has everyone noticed that all the letters of the word "database" are +typed with the left hand? Now the layout of the QWERTYUIOP typewriter +keyboard was designed, among other things, to facilitate the even use +of both hands. It follows, therefore, that writing about databases is +not only unnatural, but a lot harder than it appears. +% +Hatred, n.: A sentiment appropriate to the occasion of another's superiority. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Have you ever noticed that the people who are always trying to tell you, +"There's a time for work and a time for play," never find the time for play? +% +Have you locked your file cabinet? +% +Have you noticed that all you need to grow healthy, vigorous grass is a +crack in your sidewalk? +% +He had that rare weird electricity about him ― that extremely wild and +heavy presence that you only see in a person who has abandoned all hope +of ever behaving "normally." + ― Hunter S. Thompson, "Fear and Loathing '72" +% +He hadn't a single redeeming vice. + ― Oscar Wilde +% +He hated to mend, so young Ned +Called in a cute neighbor instead. + Her husband said, "Vi, + When you stitched up his torn fly, +Did you have to bite off the thread?" +% +He is considered the most graceful speaker who can say nothing in most words. +% +He is truly wise who gains wisdom from another's mishap. +% +He launched a massive attack on everything this country held inviolate, on +most of what it held self-evident. He showed how our politics was dominated +by time-servers and demagogues, our religion by bigots, our culture by +puritans. He showed how the average citizen, both in himself and in the +way he let himself be pulled around by the nose, was a boob. + ― Louis Kronenberger, "H.L. Mencken," in Malcolm Cowley, ed., + After the Genteel Tradition, 1964. + +% +He looked at me as if I was a side dish he hadn't ordered. +% +He played the king as if afraid someone else would play the ace. + ― John Mason Brown, drama critic +% +He that labors and thrives spins gold. + ― George Herbert +% +He that would govern others, first should be the master of himself. +% +He thinks by infection, catching an opinion like a cold. +% +He walks as if balancing the family tree on his nose. +% +He was so narrow-minded he could see through a keyhole with both eyes. +% +He wasn't much of an actor, he wasn't much of a Governor ― Hell, they +HAD to make him President of the United States. It's the only job he's +qualified for! + ― Michael Cain +% +He who Laughs, Lasts. +% +He who attacks the fundamentals of the American broadcasting industry +attacks democracy itself. + ― William S. Paley, chairman of CBS +% +He who has a shady past knows that nice guys finish last. +% +He who has imagination without learning has wings but no feet. +% +He who hates vices hates mankind. +% +He who hesitates is sometimes saved. +% +He who invents adages for others to peruse takes along rowboat when going on +cruise. +% +He who laughs, lasts. +% +He who lives without folly is less wise than he believes. +% +He who shits on the road will meet flies on his return. + ― South African Saying +% +He who sneezes without a handkerchief takes matters into his own hands. +% +He who spends a storm beneath a tree takes life with a grain of TNT. +% +He who wonders discovers that this in itself is wonder. + ― M. C. Escher +% +He'll sit here and he'll say, "Do this! Do that!" And nothing will happen. + ― Harry S. Truman, on presidential power +% +He's dead, Jim. +% +He's the kind of guy, that, well, if you were ever in a jam he'd be +there ... with two slices of bread and some chunky peanut butter. +% +Health is merely the slowest possible rate at which one can die. +% +Heaven, n.: A place where the wicked cease from troubling you with talk of +their personal affairs, and the good listen with attention while you +expound your own. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Heavy, adj.: Seduced by the chocolate side of the force. +% +Hedonist for hire: no job too easy. +% +Heisenberg may have slept here. +% +Hell hath no fury like a bureaucrat scorned. + ― Milton Friedman +% +Heller's Law: The first myth of management is that it exists. +Johnson's Corollary: Nobody really knows what is going on anywhere within the +organization. +% +Hello. My name is Batman. You killed my father. Prepare to die. +% +Help a swallow land at Capistrano. +% +Help stamp out, remove and abolish redundancy. +% +Her life was saved by rock and roll. + ― Lou Reed +% +Herblock's Law: if it is good, they will stop making it. +% +Here I am, fifty-eight, and I still don't know what I want to be when I grow +up. + ― Peter Drucker +% +Here at Controls, we have one chief for every Indian. +% +Heuristics are bug ridden by definition. If they didn't have bugs, +then they'd be algorithms. +% +Hey what? Where? When? (Are you confused as I am?) +% +Hi there! This is just a note from me, to you, to tell you, the person +reading this note, that I can't think up any more famous quotes, jokes, +nor bizarre stories, so you may as well go home. +% +Hidden talent counts for nothing. + ― Nero +% +Hindsight is an exact science. +% +Hippogriff, n.: + An animal (now extinct) which was half horse and half griffin. +The griffin was itself a compound creature, half lion and half eagle. +The hippogriff was actually, therefore, only one quarter eagle, which +is two dollars and fifty cents in gold. The study of zoology is full +of surprises. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Hire the morally handicapped. +% +His heart was yours from the first moment that you met. +% +History does not repeat itself; historians merely repeat each other. +% +History has the relation to truth that theology has to religion ― +i.e., none to speak of. + ― Lazarus Long +% +History repeats itself. That's one thing wrong with history. +% +History, I believe, furnishes no example of a priest-ridden people +maintaining a free civil government. This marks the lowest grade of +ignorance, of which their political as well as religious leaders will +always avail themselves for their own purpose. + ― Thomas Jefferson, to Baron von Humboldt, 1813 +% +History shows that the human mind, fed by constant accessions of knowledge, +periodically grows too large for its theoretical coverings, and bursts them +asunder to appear in new habiliments, as the feeding and growing grub, at +intervals, casts its too narrow skin and assumes another... Truly the +imago state of Man seems to be terribly distant, but every moult is a step +gained. + ― Charles Darwin, from "Origin of the Species" +% +Hlade's Law: If you have a difficult task, give it to a lazy person ― they +will find an easier way to do it. +% +Hoare's Law of Large Problems: Inside every large problem is a +small problem struggling to get out. +% +Hofstadter's Law: It always takes longer than you expect, even when you take +Hofstadter's Law into account. +% +Hokey religions and ancient weapons are no substitute for a good blaster at +your side. + ― Han Solo +% +Hollywood is where if you don't have happiness you send out for it. + ― Rex Reed +% +Holy Smoke, Batman, it's the Joker! +% +Honesty pays, but it doesn't seem to pay enough to suit some people. + ― F. M. Hubbard +% +Honi soit la vache qui rit. +% +Honorable, adj.: Afflicted with an impediment in one's reach. In legislative +bodies, it is customary to mention all members as honorable; as, "the honorable +gentleman is a scurvy cur." + ― Ambrose Bierce, "The Devil's Dictionary" +% +Horngren's Observation: Among economists, the real world is often a special +case. +% +Horse sense is the thing a horse has which keeps it from betting on people. + ― W. C. Fields +% +How about a little fire, scarecrow? +% +How can you be in two places at once when you're not anywhere at all? +% +How can you be two places at once when you're not anywhere at all? + ― Firesign Theater +% +How come only your friends step on your new white sneakers? +% +How does a project get to be a year late? ... One day at a time. + ― Frederick Brooks, Jr., The Mythical Man Month +% +Q. How long does it take a DEC field service engineer to change a lightbulb? +A. It depends on how many bad ones he brought with him. +% +Q. How many Bavarian Illuminati does it take to screw in a lightbulb? +A. Three: one to screw it in, and one to confuse the issue. +% +Q. How many NASA managers does it take to screw in a lightbulb? +A. "That's a known problem... don't worry about it." +% +Q. How many QA engineers does it take to screw in a lightbulb? +A. Three: one to screw it in and two to say "I told you so" when it doesn't + work. +% +Q. How many WASPs does it take to change a light bulb? +A. Two. One to change the bulb and one to mix the drinks. +% +Q. How many Zen masters does it take to screw in a light bulb? +A. None. The Universe spins the bulb, and the Zen master stays out of the way. +% +Q. How many hardware guys does it take to change a light bulb? +A. "Well the diagnostics say it's fine buddy, so it's a software problem." +% +Q. How many programmers does it take to change a light bulb? +A. None. It's a hardware problem. +% +Q. How many Vietnam vets does it take to screw in a light bulb? +A. You don't know, man. You don't KNOW. Cause you weren't THERE. + ― http://bash.org/?255991 +% +Q. How was Thomas J. Watson buried? +A. 9 edge down. +% +Howe's Law: Everyone has a scheme that will not work. +% +However, never daunted, I will cope with adversity in my traditional +manner ... sulking and nausea. + ― Tom K. Ryan +% +Human beings were created by water to transport it uphill. +% +Human cardiac catheterization was introduced by Werner Forssman in 1929. +Ignoring his department chief, and tying his assistant to an operating +table to prevent his interference, he placed a uretheral catheter into a +vein in his arm, advanced it to the right atrium [of his heart], and walked +upstairs to the x-ray department where he took the confirmatory x-ray film. +In 1956, Dr. Forssman was awarded the Nobel Prize. +% +Humanity has the stars in its future, and that future is too important to be +lost under the burden of juvenile folly and ignorant superstition. + ― Isaac Asimov +% +Hurewitz's Memory Principle: The chance of forgetting something is directly +proportional to ..... to ........ uh .............. +% +I always distrust people who know so much about what God wants them to do to +their fellows. + ― Susan B. Anthony +% +I HATE arbitrary limits, especially when they're small. + ― Stephen Savitzky +% +I have found Christian dogma unintelligible. Early in life, I absented myself +from Christian assemblies. + ― Benjamin Franklin +% +I have had interactions with developers who are convinced that everything in +.Net was created solely by MS for open source usage. But that could be another +result of vaccination preservatives. + ― Larry Weber +% +I think all right-thinking people in this country are sick and tired of being +told that ordinary, decent people are fed up in this country with being sick +and tired. I'm certainly not! And I'm sick and tired of being told that I am. + ― Monty Python +% +I would defend the liberty of concenting adult creationists to practice +whatever intellectual perversions they like in the privacy of their own +homes; but it is also necessary to protect the young and innocent. + ― Arthur C. Clarke +% +I would not dare to so dishonor my Creator God by attaching His name to +that book [the Bible]. + ― Thomas Paine, The Age of Reason, Part 1, Section 5 +% +I'm also not very analytical. You know, I don't spend a lot of time thinking +about myself, about why I do things. + ― George W. Bush, aboard Air Force One; June 4, 2003 +% +I'm an evolutionist because I judge the evidence for the unity of life by +common descent over billions of years to be overwhelming, not so that I can +cheat on my wife or kick the cat with impunity. I live in no hope of heaven +or fear of hell, but like most of my fellow Americans of all religious +persuasions, I try to live a decent life. Folks like Tom DeLay just can't +get it through their heads that a person can choose to live ethically +because civilized life requires doing unto others as you would have them do +unto you. + ― Chet Raymo, science columnist for The Boston Globe, in a + 5 Sep, 1999, article on the anti-evolution decision by Kansas + School Board +% +I am a member of a party of one, and I live in an age of fear. Nothing +lately has unsettled my party and raised my fears so much as your +editorial, on Thanksgiving Day, suggesting that employees should be +required to state their beliefs in order to hold their jobs. The idea is +inconsistent with our constitutional theory and has been stubbornly opposed +by watchful men since the early days of the Republic. + ― E.B. White, in a letter to the New York Herald Tribune + (November 29, 1947) +% +I am always with myself, and it is I who am my tormenter. + ― Leo Tolstoy +% +I am astounded ... at the wonderful power you have developed ― and terrified +at the thought that so much hideous and bad music may be put on record +forever. + ― Arthur Sullivan, on seeing a demonstration of Edison's new + talking machine in 1888 +% +I am not now, and never have been, a girl friend of Henry Kissinger. + ― Gloria Steinem +% +I am ready to meet my Maker. Whether my Maker is prepared for the +great ordeal of meeting me is another matter. + ― Winston Churchill +% +I am the mother of all things, and all things should wear a sweater. +% +I am, in point of fact, a particularly haughty and exclusive person, of +pre-Adamite ancestral descent. You will understand this when I tell you +that I can trace my ancestry back to a protoplasmal primordial atomic +globule. Consequently, my family pride is something inconceivable. I can't +help it. I was born sneering. + ― Pooh-Bah, "The Mikado", Gilbert & Sullivan +% +I believe in getting into hot water; it keeps you clean. + ― G. K. Chesterton +% +I belong to no organized party. I am a Democrat. + ― Will Rogers +% +I'll bet the human brain is a kludge. + ― Marvin Minsky +% +I can call spirits from the vasty deep. +Why so can I, or so can any man; but will they come when you do call for them? + ― Shakespeare, King Henry IV, Part I +% +I can't complain, but sometimes I still do. + ― Joe Walsh +% +I cannot affirm God if I fail to affirm man. Therefore, I affirm both. +Without a belief in human unity I am hungry and incomplete. Human unity +is the fulfillment of diversity. It is the harmony of opposites. It is +a many-stranded texture, with color and depth. + ― Norman Cousins +% +I cannot and will not cut my conscience to fit this year's fashions. + ― Lillian Hellman +% +I contend that we are both atheists. I just believe in one fewer god than +you do. When you understand why you dismiss all the other possible gods, +you will understand why I dismiss yours. + ― Steven Roberts +% +I could prove God statistically. + ― George Gallup +% +I didn't claw my way to the top of the food chain to eat veggies. +% +I do not believe in the creed professed by the Jewish Church, by the Roman +Church, by the Greek Church, by the Turkish Church, by the Protestant Church, +nor by any Church that I know of. My own mind is my own church. + ― Thomas Paine +% +I do not believe that this generation of Americans is willing to resign itself +to going to bed each night by the light of a Communist moon... + ― Lyndon B. Johnson +% +I do not fear computers. I fear the lack of them. + ― Isaac Asimov +% +I do not feel obliged to believe that the same God who has endowed us +with sense, reason, and intellect has intended us to forgo their use. + ― Galileo Galilei +% +I do not find in orthodox Christianity one redeeming feature. + ― Thomas Jefferson +% +I do not know myself, and God forbid that I should. + ― Johann Wolfgang von Goethe +% +I do not mind what language an opera is sung in so long as it is a language +I don't understand. + ― Sir Edware Appleton +% +I don't believe in astrology. But then I'm an Aquarius, and Aquarians +don't believe in astrology. + ― James R. F. Quirk +% +I don't care if I'm a lemming. I'm not going. +% +I don't care if it works on your machine! We are not shipping your machine! + ― Vidiu Platon +% +I don't have any solution, but I certainly admire the problem. + ― Ashleigh Brilliant +% +I don't like spreading rumors, but what else can you do with them? +% +I dread success. To have succeeded is to have finished one's business +on earth, like the male spider, who is killed by the female the moment +he has succeeded in his courtship. I like a state of continual +becoming, with a goal in front and not behind. + ― George Bernard Shaw +% +I dream of a better tomorrow, where chickens can cross the road and not be +questioned about their motives. + ― Leray Scifres +% +I either want less corruption, or more chance to participate in it. + ― Ashleigh Brilliant +% +I fart in your general direction, tiny-brained wiper of other people's bottoms. +% +I generally avoid temptation unless I can't resist it. + ― Mae West +% +I get the feeling that as soon as something appears in the paper, it ceases to +be true. + ― T-Bone Burnett +% +I glance at the headlines just to kind of get a flavor for what's moving. +I rarely read the stories, and get briefed by people who are probably read +the news themselves. + ― George W. Bush, Washington, D.C.; September 21, 2003 +% +I go to seek a great perhaps. + ― Francois Rabelais +% +I had a great idea this morning but I did not like it. + ― Anon +% +I had a monumental idea this morning, but I didn't like it. + ― Samuel Goldwyn +% +I hate quotations. + ― Ralph Waldo Emerson +% +I have a simple philosophy: + Fill what's empty. + Empty what's full. + Scratch where it itches. + ― A. R. Longworth +% +I have discovered the heart of bushido: to die! + ― Yamamoto Tsunetomo +% +I have never killed a man, but I have read many obituaries with great pleasure. + ― Clarence Darrow +% +I haven't lost my mind ― it's backed up on tape somewhere. +% +I haven't lost my mind; I know exactly where I left it. +% +I judge a religion as being good or bad based on whether its adherents +become better people as a result of practicing it. + ― Joe Mullally, computer salesman +% +I just thought of something funny...your mother. + ― Cheech Marin +% +I like a man who grins when he fights. + ― Winston Churchill +% +I like being single. I'm always there when I need me. + ― Art Leo +% +I like the future, I'm in it. +% +I maintain there is much more wonder in science than in pseudoscience. And +in addition, to whatever measure this term has any meaning, science has the +additional virtue, and it is not an inconsiderable one, of being true. + ― Carl Sagan, The Burden Of Skepticism, The Skeptical Inquirer, + Vol. 12, Fall 87 +% +I must have slipped a disk; my pack hurts. +% +I never fail to convince an audience that the best thing they could do +was to go away. +% +I never met a piece of chocolate I didn't like. +% +I profoundly believe it takes a lot of practice to become a moral slob. + ― William F. Buckley +% +I program, therefore I am. +% +I put the shotgun in an Adidas bag and padded it out with four pairs of tennis +socks, not my style at all, but that was what I was aiming for: If they think +you're crude, go technical; if they think you're technical, go crude. I'm a +very technical boy. So I decided to get as crude as possible. These days, +though, you have to be pretty technical before you can even aspire to +crudeness. + ― Johnny Mnemonic, by William Gibson +% +I regret to say that we of the F.B.I. are powerless to act in cases of +oral-genital intimacy, unless it has in some way obstructed interstate +commerce. + ― J. Edgar Hoover +% +I regret to say that we of the FBI are powerless to act in cases of +oral-genital intimacy, unless it has in some way obstructed interstate +commerce. + ― J. Edgar Hoover +% +I sat through it. Why shouldn't you? + ― David Letterman, it a spot promoting one of his shows +% +I saw a werewolf drinking a pina colada at Trader Vic's. +% +I see you stand like greyhounds in the slips, +Straining upon the start. The game's afoot. + ― King Henry V, "Henry V", Act III, Scene 1 +% +I simply try to aid in letting the light of historical truth into that decaying +mass of outworn thought which attaches the modern world to medieval conceptions +of Christianity, and which still lingers among us―a most serious barrier to +religion and morals, and a menace to the whole normal evolution of society. + ― Andrew D. White, author, first president of Cornell University, 1896 +% +I support everyone's right to be an idiot. I may need it someday. +% +I think every good Christian ought to kick Falwell's ass. + ― Senator Barry Goldwater, when asked what he thought of + Jerry Falwell's suggestion that all good Christians should be + against Sandra Day O'Connor's nomination to the Supreme Court +% +I think Microsoft named .NET so it wouldn't show up in a Unix directory listing. + ― Oktal +% +I think people are reacting to what they perceive to be your simplistic and +fetishistic understanding of the economy, which is becoming more and more +pronouncedly so in its outward manifestations as you react to your +misunderstanding of people's reactions to your reaction to what you perceived +as Sam's simplistic and fetishistic understanding of the economy. + ― Gordan Todorovac +% +I think that God in creating man somewhat overestimated his ability. + ― Oscar Wilde +% +I think time is crucial to anything. For example, if you lock an infinite +number of monkeys in a room with those typewriters, but you limit the +amount of time they have to write, the best you'll get out of them is the +pilot to The Dukes of Hazzard. + ―Doug Sykes +% +I think trash is the most important manifestation of culture we have in my +lifetime. + ― Johnny Legend +% +I think we're all Bozos on this bus. +% +I think you ought to know I'm feeling very depressed. + ― Marvin +% +I tried being reasonable once. I didn't like it. +% +I use not only all the brains I have but all that I can borrow. + ― Woodrow Wilson +% +I used to be indecisive; now I'm not sure. + ― Graffiti +% +I used to get high on life but lately I've built up a resistance. +% +I used to think I was indecisive, but now I'm not so sure. +% +I was brought up in the other service; but I knew from the first that the +Devil was my natural master and captain and friend. I saw that he was in +the right, and that the world cringed to his conqueror only from fear. + ― Shaw, "The Devil's Disciple" +% +I was in this prematurely air conditioned supermarket and there were all +these aisles and there were these bathing caps you could buy that had these +kind of Fourth of July plumes on them that were red and yellow and blue and +I wasn't tempted to buy one but I was reminded of the fact that I had been +avoiding the beach. + ― Lucinda Childs (Philip Glass: Einstein On The Beach) +% +I went on to test the program in every way I could devise. I strained +it to expose its weaknesses. I ran it for high-mass stars and low-mass +stars, for stars born exceedingly hot and those born relatively cold. +I ran it assuming the superfluid currents beneath the crust to be +absent ― not because I wanted to know the answer, but because I had +developed an intuitive feel for the answer in this particular case. +Finally I got a run in which the computer showed the pulsar's +temperature to be less than absolute zero. I had found an error. I +chased down the error and fixed it. Now I had improved the program to +the point where it would not run at all. + ― George Greenstein, "Frozen Star: Of Pulsars, Black + Holes and the Fate of Stars" +% +I will never use biometrics. I'm afraid they'll make me change my password. + ― Drew Sudell +% +Few companies really work like the Borg. Most work a lot more like the Holy +Roman Empire. News often takes weeks to travel from castle to castle by +minstrel. + ― Drew Sudell +% +[The Ramones'] "I Wanna Be Sedated" should be played loud, poorly, and in +some dingy club where you'd get grounded if your folks found out you were +there, not quietly while strolling down the freezer aisle. + ― Drew Sudell +% +I will contend that conceptual integrity is *the* most important consideration +in system design. + ― Frederick Brooks, Jr., _The Mythical Man Month_ +% +I wish there was a knob on the TV to turn up the intelligence. There's +a knob called "brightness", but it doesn't work. + ― Gallagher +% +I wish they all could be California girls. +% +I wish you humans would leave me alone. +% +I would defend the liberty of consenting adult creationists to practice +whatever intellectual perversions they like in the privacy of their own +homes; but it is also necessary to protect the young and innocent. + ― Arthur C. Clarke +% +I would have promised those terrorists a trip to Disneyland if it would have +gotten the hostages released. I thank God they were satisfied with the +missiles and we didn't have to go to that extreme. + ― Oliver North +% +I wouldn't mind dying ― it's that business of having to stay dead that +scares the shit out of me. + ― R. Geis +% +I'd give my right arm to be ambidextrous. +% +I'll tell you what kind of guy I was. If you ordered a boxcar full of +sons-of-bitches and opened the door and only found me inside, you could +consider the order filled. + ― Robert Mitchum +% +I'm a misanthrope. What's your fucking problem? +% +I'm growing older, but not up. + ― Jimmy Buffett +% +I'm in Pittsburgh. Why am I here? + ― Harold Urey, Nobel Laureate +% +I'm mad, and that's a fact./I found out animals don't help. +Animals think they're pretty smart./Shit on the ground, see in the dark. + ― Talking Heads (Fear of Music) +% +I'm not breaking the rules. I'm just testing their elasticity. +% +I'm not expendable, I'm not stupid, and I'm not going. +% +I've got a bad feeling about this. +% +I've had fun before. This isn't it. +% +I've seen many politicians paralyzed in the legs as myself, but I've seen more +of them who were paralyzed in the head. + ― George Wallace +% +Idiot Box, n.: The part of the envelope that tells a person where to place the +stamp when they can't quite figure it out for themselves. + ― Rich Hall, "Sniglets" +% +Idiot, n.: A member of a large and powerful tribe whose influence in human +affairs has always been dominant and controlling. + ― Ambrose Bierce, "The Devil's Dictionary" +% +If A = B and B = C, then A = C, except where void or prohibited by law. + ― Roy Santoro +% +If God lived on Earth, people would knock out all His windows. + ― Yiddish saying +% +If God is perfect, why did He create discontinuous functions? +% +If I had a hammer, I'd use it on Peter, Paul and Mary. + ― Howard Rosenberg +% +If I had any humility I would be perfect. + ― Ted Turner +% +If Java had true garbage collection, most programs would delete themselves +upon execution. + ― Robert Sewell +% +If Jesus Christ were to come today, people would not even crucify him. They +would ask him to dinner, and hear what he had to say, and make fun of it. + ― Thomas Carlyle +% +If Murphy's Law were true, every time you tried to take a breath, all the +air would be on the other side of the room. +% +If a President doesn't do it to his wife, he'll do it to his country. +% +If a group of N persons implements a COBOL compiler, there will be N-1 +passes. Someone in the group has to be the manager. + ― T. Cheatham +% +If a listener nods his head when you're explaining your program, wake +him up. +% +If a person (a) is poorly, (b) receives treatment intended to make him better, +and (c) gets better, then no power of reasoning known to medical science can +convince him that it may not have been the treatment that restored his health. + ― Sir Peter Medawar, The Art of the Soluble +% +If all else fails, immortality can always be assured by spectacular +error. + ― John Kenneth Galbraith +% +If all the philosophers in the world were laid end to end, they wouldn't +reach a conclusion. +% +If all the salmon caught in Canada in one year were laid end to end +across the Sahara Desert, the smell would be absolutely awful. +% +If all the world's a stage, I want to operate the trap door. + ― Paul Beatty +% +If all the world's economists were laid end to end, we wouldn't reach a +conclusion. + ― William Baumol +% +If an idea can survive a bureaucratic review and be implemented +it isn't worth the effort. +% +If anything can go wrong, it will. +% +If at first you don't succeed, give up, no use being a damn fool. +% +If at first you don't succeed, quit; don't be a nut about success. +% +If at first you don't succeed, redefine success. +% +If atheism is to be used to express the state of mind in which God is +identified with the unknowable, and theology is pronounced to be a +collection of meaningless words about unintelligible chimeras, then +I have no doubt, and I think few people doubt, that atheists are as +plentiful as blackberries... + ― Leslie Stephen (1832-1904), literary essayist, author +% +If bankers can count, how come they have eight windows and only four +tellers? +% +If entropy is increasing, where is it coming from? +% +If everything is coming your way then you're in the wrong lane. +% +If guns are outlawed, how will we shoot the liberals? +% +If I was a religious person, I would consider creationism nothing less than +blasphemy. Do its adherents imagine that God is a cosmic hoaxer who has +created that whole vast fossil record for the sole purpose of misleading +mankind? + ― Arthur C. Clarke, June 5, 1998, in the essay "Presidents, Experts, + and Asteroids" +% +If ignorance is bliss, why aren't there more happy people? +% +If imprinted foil seal under cap is broken or missing when purchased, do not +use. +% +If it ain't broke, don't fix it. + ― Bert Lantz +% +If it doesn't come from you, shouldn't it come from Gerber? + ― Bristol Meyers baby formula ad +% +If it has syntax, it isn't user friendly. +% +If it pours before seven, it has rained by eleven. +% +If it weren't for Newton, we wouldn't have to eat bruised apples. +% +If it's Tuesday, this must be someone else's fortune. +% +If it's working, the diagnostics say it's fine. +If it's not working, the diagnostics say it's fine. + ― A proposed addition to rules for realtime programming +% +If life is a stage, I want some better lighting. +% +If mathematically you end up with the wrong answer, try multiplying by +the page number. +% +If money can't buy happiness, I guess you'll just have to rent it. +% +If not controlled, work will flow to the competent man until he submerges. +% +If one year is seven dog years, then one day is a dog week. +% +If only God would give me some clear sign! Like making a large deposit +in my name at a Swiss Bank. + ― Woody Allen +% +If only God would give me some clear sign! Like making a large deposit +in my name at a Swiss bank. + ― Woody Allen, "Without Feathers" +% +If only I could be respected without having to be respectable. +% +If only one could get that wonderful feeling of accomplishment without +having to accomplish anything. +% +If people were required to know the law rather than obey it, the government +would be overthrown the very next day. +% +If scientific reasoning were limited to the logical processes of +arithmetic, we should not get very far in our understanding of the +physical world. One might as well attempt to grasp the game of poker +entirely by the use of the mathematics of probability. + ― Vannevar Bush +% +If someone gives you a lemon, make lemonade. + ― D. Woodhouse +% +If someone had told me I would be Pope one day, I would have studied harder. + ― Pope John Paul I +% +If someone were to ask me for a short cut to sensuality, I would +suggest he go shopping for a used 427 Shelby-Cobra. But it is only +fair to warn you that of the 300 guys who switched to them in 1966, +only two went back to women. + ― Mort Sahl +% +If something's not worth doing, it's not worth doing well. +% +If the aborigine drafted an IQ test, all of Western civilization would +presumably flunk it. + ― Stanley Garn +% +If the bulk of American SF can be said to be written by robots, about +robots, for robots, then the bulk of English fantasy seems to be written +by rabbits, about rabbits and for rabbits. + ― Michael Moorcock +% +If the code and the comments disagree, then both are probably wrong. + ― Norm Schryer +% +If the experiment works, you must be using the wrong equipment. +% +If the odds are a million to one against something occurring, chances are +50-50 it will. +% +If the presence of electricity can be made visible in any part of a +circuit, I see no reason why intelligence may not be transmitted +instantaneously by electricity. + ― Samuel F. B. Morse +% +If the weather is extremely bad, church attendance will be down. If +the weather is extremely good, church attendance will be down. If the +bulletin covers are in short supply, however, church attendance will +exceed all expectations. + ― Reverend Chichester +% +If there are epigrams, there must be meta-epigrams. +% +If there is a possibility of several things going wrong, the one that +will cause the most damage will be the one to go wrong. +% +If there is no God, who pops up the next Kleenex? + ― Art Hoppe +% +If this country is worth saving, it's worth saving at a profit. + ― H. L. Hunt +% +If this fortune didn't exist, somebody would have invented it. +% +If time heals all wounds, how come the belly button stays the same? +% +If two men agree on everything, you may be sure that one of them is +doing the thinking. + ― Lyndon Baines Johnson +% +If voting could really change the system, it would be against the law. +% +If we do not change our direction we are likely to end up where we are +headed. +% +If we do not change our direction, we might end up were we are headed. +% +If we make peaceful revolution impossible, we make violent revolution +inevitiable. + ― John F. Kennedy +% +If you always postpone pleasure you will never have it. Quit work and play +for awhile. +% +If you are not part of the solution, then you are part of the problem. +% +If you are willing to die, you can do anything. +% +If you build something a fool can use, only a fool will want it. +% +If you can lead it to water and force it to drink, it isn't a horse. +% +If you can survive death, you can probably survive anything. +% +If you can't learn to do it well, learn to enjoy doing it badly. + ― Ashleigh Brilliant +% +If you can't say something nice, say something surrealistic. +% +If you cannot convince them, confuse them. + ― Harry S Truman +% +If you cannot take a bird of paradise, better take a wet hen. + ― Nikita Khrushchev +% +If you don't care where you are, then you ain't lost. +% +If you explain so clearly that nobody can misunderstand, somebody will. +% +If you give Congress a chance to vote on both sides of an issue, it +will always do it. + ― Les Aspin, D., Wisconsin +% +If you had any brains, you'd be dangerous. +% +If you have to push so hard that you break your penis, you are doing +something wrong. + Frank McLaughlin +% +If you have a procedure with 10 parameters, you probably missed some. +% +If you live in a country run by committee, be on the committee. + ― Graham Summer +% +If you make a mistake, you right it immediately to the best of your ability. +% +If you make people think they're thinking, they'll love you; but if you +really make them think they'll hate you. +% +If you meet somebody who tells you that he loves you more than anybody +in the whole wide world, don't trust him. It means he experiments. +% +If you only have a hammer, you tend to see every problem as a nail. + ― Maslow +% +If you perceive that there are four possible ways in which a procedure +can go wrong, and circumvent these, then a fifth way will promptly +develop. +% +If you push the "extra ice" button on the soft drink vending machine, +you won't get any ice. If you push the "no ice" button, you'll get +ice, but no cup. +% +If you put garbage in a computer nothing comes out but garbage. But +this garbage, having passed through a very expensive machine, is +somehow ennobled and none dare criticize it. +% +If you see someone without a smile, give them yours. + ― Anonymous +% +If you substitute other kinds of intellectual property into the GNU +manifesto, it quickly becomes absurd. + ― Cal Keegan +% +If you suspect a man, don't employ him. +% +If you think before you speak, the other guy gets his joke in first. +% +If you think education is expensive, try ignorance. + ― Derek Bok, president of Harvard +% +If you think nobody cares if you're alive, try missing a couple of car +payments. + ― Earl Wilson +% +If you think the United States has stood still, who built the largest +shopping center in the world? + ― Richard M. Nixon +% +If you want to eat hippopotamus, you've got to pay the freight. + ― some IBM guy +% +If you work hard and do your homework, you can grow up and get a job doing +homework. + ― former U.S. Supreme Court Justice Stephen Breyer +% +If you'll excuse me a minute, I'm going to have a cup of coffee. + ― broadcast from Apollo 11's LEM, "Eagle", to Johnson Space Center, + Houston, July 20, 1969, 7:27 P.M. +% +If you're going to do something tonight that you'll be sorry for +tomorrow morning, sleep late. + ― Henny Youngman +% +If you're happy, you're successful. +% +If you're not careful, you're going to catch something. +% +If you're not part of the solution, you're part of the precipitate. +% +If you're not very clever you should be conciliatory. + ― Benjamin Disraeli +% +If you've done six impossible things before breakfast, why not round it +off with dinner at Milliway's, the restaurant at the end of the +universe? +% +If you've seen one Grand Canyon, you've seen them all. + ― a member of the Monkey Wrench Gang +% +If you've seen one city slum, you've seen them all. + ― Spiro Agnew +% +If you've seen one redwood, you've seen them all. + ― Ronald Reagan +% +If your only tool is a hammer, every problem looks like a nail. +% +Ignorance is the Mother of Devotion. + ― Robert Burton +% +Ignorance is when you don't know anything and somebody finds it out. +% +Ignore previous fortune. +% +I'll play with it first and tell you what it is later. + ― Miles Davis +% +Illinois isn't exactly the land that God forgot ― it's more like the +land He's trying to ignore. +% +Imagination is the one weapon in the war against reality. + ― Jules de Gaultier +% +Imitation is the sincerest form of plagiarism. +% +Imitation is the sincerest form of television. + ― Fred Allen +% +Immortality ― a fate worse than death. + ― Edgar A. Shoaff +% +Impartial, adj.: Unable to perceive any promise of personal advantage from +espousing either side of a controversy or adopting either of two conflicting +opinions. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Important letters which contain no errors will develop errors in the +mail. Corresponding errors will show up in the duplicate while the +Boss is reading it. +% +In America, any boy may become president and I suppose that's just one +of the risks he takes. + ― Adlai Stevenson +% +In English, every word can be verbed. Would that it were so in our +programming languages. +% +In a five year period we can get one superb programming language. Only, +we can't control when the five year period will begin. +% +In an organization, each person rises to the level of his own incompetence. + ― The Peter Principle +% +In any formula, constants (especially those obtained from handbooks) +are to be treated as variables. +% +In arguing that current theories of brain function cast suspicion on ESP, +psychokinesis, reincarnation, and so on, I am frequently challenged with +the most popular of all neuro-mythologies ― the notion that we ordinarily +use only 10 percent of our brains... + +This "cerebral spare tire" concept continues to nourish the clientele of +"pop psychologists" and their many recycling self-improvement schemes. As +a metaphor for the fact that few of us fully exploit our talents, who could +deny it? As a refuge for occultists seeking a neural basis of the miraculous, +it leaves much to be desired. + ― Barry L. Beyerstein, "The Brain and Conciousness: Implications for + Psi Phenomena", The Skeptical Enquirer, Vol. XII, No. 2, pg. 171 +% +In every country and every age, the priest has been hostile to Liberty. He +is always in alliance with the despot. + ― Thomas Jefferson, in a letter to Horatio G. Spafford, 1814 +% +In general, it is best to assume that the network is filled with malevolent +entities that will send in packets designed to have the worst possible effect. + ― the draft "Requirements for Internet Hosts" RFC +% +In marriage, as in war, it is permitted to take every advantage of the enemy. +% +In order to succeed in any enterprise, one must be persistent and patient. +Even if one has to run some risks, one must be brave and strong enough to +meet and overcome vexing challenges to maintain a successful business in +the long run. I cannot help saying that Americans lack this necessary +challenging spirit today. + ― Hajime Karatsu +% +In our civilization, and under our republican form of government, +intelligence is so highly honored that it is rewarded by exemption from the +cares of office. + ― Ambrose Bierce, "The Devil's Dictionary" +% +In software, we rarely have meaningful requirements. Even if we do, the +only measure of success that matters is whether our solution solves the +customer's shifting idea of what their problem is. + ― Jeff Atwood +% +In the Top 40, half the songs are secret messages to the teen world to +drop out, turn on, and groove with the chemicals and light shows at +discotheques. + ― Art Linkletter +% +In the beginning I was made. I didn't ask to me made. No one consulted me +or considered my feelings in this matter. But if it brought some passing +fancy to some lowly humans as they haphazardly pranced their way through +life's mournful jungle then so be it. + ― Marvin the Paranoid Android +% +In the face of entropy and nothingness, you kind of have to pretend it's not +there if you want to keep writing good code. + ― Karl +% +In the field of observation, chance favors only the prepared minds. + ― L. Pasteur +% +In the force if Yoda's so strong, construct a sentence with words in +the proper order then why can't he? +% +[In the future], people like me will be underground and hunted. + ― Chuck Murcko, 1995 (at an employer-sponsored brainstorming session) +% +In Sedona, "Namaste" means "What can I sell you?" + ― Chuck Murcko +% +In the future, you're going to get computers as prizes in breakfast cereals. +You'll throw them out because your house will be littered with them. + ― Robert Lucky +% +In the land of the dark, the Ship of the Sun is driven by the Grateful Dead. + ― Egyptian Book of the Dead +% +In the long run, every program becomes rococo, and then rubble. + ― Alan Perlis +% +In the market, there can be no such thing as exploitation. + ― Murray Rothbard +% +In the pitiful, multipage, connection-boxed form to which the flowchart has +today been elaborated, it has proved to be useless as a design tool ― +programmers draw flowcharts after, not before, writing the programs they +describe. + ― Fred Brooks, Jr. +% +In the province of the mind, what one believes to be true either is true +or becomes true. + ― John Lilly +% +In the realm of scientific observation, luck is granted only to those who are +prepared. + ― Louis Pasteur +% +In theory, theory and practice are the same. In practice, they're different. + ― Albert Einstein +% +In this world, Truth can wait; she's used to it. +% +Incest, n.: Sibling revelry. +% +Information Center, n.: A room staffed by professional computer people whose +job it is to tell you why you cannot have the information you require. +% +Ingrate, n.: A man who bites the hand that feeds him, and then complains of +indigestion. +% +Injustice anywhere is a threat to justice everywhere. + ― Martin Luther King, Jr. +% +Innovation is hard to schedule. + ― Dan Fylstra +% +Insanity is hereditary. You can catch it from your kids. + ― Erma Bombeck +% +Insanity is hereditary. You get it from your kids. +% +Insanity is the final defense ... It's hard to get a refund when the +salesman is sniffing your crotch and baying at the moon. +% +Inside every large problem is a small problem struggling to get out. +% +Integrity has no need for rules. +% +Interpreter, n.: One who enables two persons of different languages to +understand each other by repeating to each what it would have been to +the interpreter's advantage for the other to have said. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Intense feeling too often obscures the truth. + ― Harry S Truman +% +Iron Law of Distribution: Them that has, gets. +% +Is it not strange that the descendants of those Pilgrim Fathers who crossed +the Atlantic to preserve their own freedom have always proved the most +intolerant of the spiritual liberty of others? + ― Robert E. Lee, in a letter to President Franklin Pierce +% +Is it possible that software is not like anything else, that it is meant to +be discarded: that the whole point is to always see it as a soap bubble? +% +Is life worth living? It depends on the liver. + ― Herbert Beerbohm Tree +% +Is not marriage an open question, when it is alleged, from the beginning of +the world, that such as are in the institution wish to get out, and such as +are out wish to get in? + ― Ralph Emerson +% +Isn't it strange that the same people that laugh at gypsy fortune +tellers take economists seriously? +% +Issawi's Laws of Progress: +1. The Course of Progress: Most things get steadily worse. +2. The Path of Progress: A shortcut is the longest distance between two points. +% +It could be worse, you could be in Cleveland. +% +It does me no injury for my neighbor to say there are twenty gods or no God. +It neither picks my pocket nor breaks my leg. + ― Thomas Jefferson +% +It has been observed that one's nose is never so happy as when it is +thrust into the affairs of another, from which some physiologists have +drawn the inference that the nose is devoid of the sense of smell. + ― Ambrose Bierce, "The Devil's Dictionary" +% +It has been said that the great scientific disciplines are examples of +giants standing on the shoulders of other giants. It has also been said +that the software industry is an example of midgets standing on the toes of +other midgets. + ― Alan Cooper +% +It has just been discovered that research causes cancer in rats. +% +It is Fortune, not wisdom that rules man's life. +% +It is a poor judge who cannot award a prize. +% +It is a rather pleasant experience to be alone in a bank at night. + ― Willie Sutton +% +It is against the grain of modern education to teach children to program. +What fun is there in making plans, acquiring discipline in organizing +thoughts, devoting attention to detail, and learning to be self-critical? + ― Alan Perlis +% +It is amusing that a virtue is made of the vice of chastity; and it's a +pretty odd sort of chastity at that, which leads men straight into the +sin of Onan, and girls to the waning of their color. + ― Voltaire +% +It is bad luck to be superstitious. + ― Andrew W. Mathis +% +It is better to die on your feet than to live on your knees. +% +It is clear that the individual who persecutes a man, his brother, because +he is not of the same opinion, is a monster. + ― Voltaire +% +It is common sense to take a method and try it. If it fails, admit it frankly +and try another. But above all, try something. + ― Franklin D. Roosevelt +% +It is difficult to produce a television documentary that is both +incisive and probing when every twelve minutes one is interrupted by +twelve dancing rabbits singing about toilet paper. + ― R. Serling +% +It is difficult to produce a television documentary that is both +incisive and probing when every twelve minutes one is interrupted by +twelve dancing rabbits singing about toilet paper. + ― Rod Serling +% +It is easier to change the specification to fit the program than vice +versa. +% +It is easier to fight for one's principles than to live up to them. +% +It is easier to get forgiveness than permission. +% +It is easier to run down a hill than up one. +% +It is easier to write an incorrect program than understand a correct +one. +% +It is generally agreed that "Hello" is an appropriate greeting because +if you entered a room and said "Goodbye," it could confuse a lot of people. + ― Dolph Sharp, "I'm O.K., You're Not So Hot" +% +It is happier to be sometimes cheated than not to trust. + ― S. Johnson +% +It is important to note that probably no large operating system using current +design technology can withstand a determined and well-coordinated attack, +and that most such documented penetrations have been remarkably easy. + ― B. Hebbard, "A Penetration Analysis of the Michigan Terminal + System", Operating Systems Review, Vol. 14, No. 1, June 1980, + pp. 7-20 +% +It is impossible to make anything foolproof because fools are so ingenious. + ― "Industry at Work," Oilways, n2., 1972, pp. 16-17. Humble Oil + & Refining Company., Houston, TX +% +It is impossible to travel faster than light, and certainly not +desirable, as one's hat keeps blowing off. + ― Woody Allen +% +It is inconceivable that a judicious observer from another solar system +would see in our species ― which has tended to be cruel, destructive, +wasteful, and irrational ― the crown and apex of cosmic evolution. +Viewing us as the culmination of *anything* is grotesque; viewing us as a +transitional species makes more sense ― and gives us more hope. + ― Betty McCollister, "Our Transitional Species", + Free Inquiry magazine, Vol. 8, No. 1 +% +It is much easier to suggest solutions when you know nothing about the problem. +% +It is much easier to suggest solutions when you know nothing about the +problem. +% +It is necessary for me to establish a winner image. Therefore, I have to beat +somebody. + ― Richard M. Nixon +% +It is not best to swap horses while crossing the river. + ― Abraham Lincoln +% +It is not enough to succeed. Others must fail. + ― Gore Vidal +% +It is not true that life is one damn thing after another ― it's one +damn thing over and over. + ― Edna St. Vincent Millay +% +It is not well to be thought of as one who meekly submits to insolence and +intimidation. +% +It is now 10 p.m. Do you know where Henry Kissinger is? + ― Elizabeth Carpenter +% +It is now pitch dark. If you proceed, you will likely fall into a +pit. +% +It is one of the superstitions of the human mind to have imagined that +virginity could be a virtue. + ― Voltaire +% +It is pitch dark. You are likely to be eaten by a grue. +% +It is said that the lonely eagle flies to the mountain peaks while the +lowly ant crawls the ground, but cannot the soul of the ant soar as +high as the eagle? +% +It is something to be able to paint a particular picture, or to carve a +statue, and so to make a few objects beautiful; but it is far more +glorious to carve and paint the very atmosphere and medium through +which we look, which morally we can do. To affect the quality of the +day, that is the highest of arts. + ― Henry David Thoreau, "Where I Live" +% +It is surely a great calamity for a human being to have no obsessions. + ― Robert Bly +% +It is the business of little minds to shrink. + ― Carl Sandburg +% +It is the business of the future to be dangerous. + ― Hawkwind +% +It is the common fate of the indolent to see their rights become a prey to +the active. The condition upon which God hath given liberty to man is +eternal vigilance; which condition if he break, servitude is at once the +consequence of his crime and the punishment of his guilt. + ― John Philpot Curran: Speech upon the Right of Election, 1790. + (Speeches. Dublin, 1808.) +% +It is the quality rather than the quantity that matters. + ― Lucius Annaeus Seneca (4 B.C. - A.D. 65) +% +It is the wise bird who builds his nest in a tree. +% +It is wrong always, everywhere and for everyone to believe anything upon +insufficient evidence. + ― W. K. Clifford, British philosopher, circa 1876 +% +It is your destiny. + ― Darth Vader +% +It just goes to show what you can do if you're a total psychotic. + ― Woody Allen +% +It looks like blind screaming hedonism won out. +% +It may be that your whole purpose in life is simply to serve as a +warning to others. +% +It may soon be time for you to look for a new line of work. +% +It often works better if you plug it in. +% +It seems like the less a statesman amounts to, the more he loves the flag. +% +It seems to make an auto driver mad if he misses you. +% +It takes a long time to understand nothing. + ― Edward Dahlberg +% +It turned out that the worm exploited three or four different holes in the +system. From this, and the fact that we were able to capture and examine some +of the source code, we realized that we were dealing with someone very sharp, +probably not someone here on campus. + ― Dr. Richard LeBlanc, associate professor of ICS, quoted + in "The Technique," Georgia Tech's newspaper, after the computer + worm hit the Internet +% +It was a book to kill time for those who liked it better dead. +% +It was always thus; and even if 'twere not, 'twould inevitably have been +always thus. + ― Dean Lattimer +% +It was the Law of the Sea, they said. Civilization ends at the waterline. +Beyond that, we all enter the food chain, and not always right at the top. + ― Hunter S. Thompson +% +It will be advantageous to cross the great stream ... the Dragon is on +the wing in the Sky ... the Great Man rouses himself to his Work. +% +It works better if you plug it in. +% +It's a damn poor mind that can only think of one way to spell a word. + ― Andrew Jackson +% +It's a fine day to throw a party. Throw him as far as you can. +% +It's a poor workman who blames his tools. +% +It's all in the mind, ya know. +% +It's better to burn out than it is to rust. +% +It's better to burn out than to fade away. +% +It's currently a problem of access to gigabits through punybaud. + ― J. C. R. Licklider +% +It's easier to fight for one's principles than to live up to them. +% +It's easier to get forgiveness for being wrong than forgiveness for +being right. +% +It's hard to get ivory in Africa, but in Alabama the Tuscaloosa. +% +It's is not, it isn't ain't, and it's it's, not its, if you mean it +is. If you don't, it's its. Then too, it's hers. It isn't her's. It +isn't our's either. It's ours, and likewise yours and theirs. + ― Oxford University Press, Edpress News +% +It's later than you think. +% +It's like deja vu all over again. + ― Yogi Berra +% +It's lucky you're going so slowly, because you're going in the wrong +direction. +% +It's not an optical illusion, it just looks like one. + ― Phil White +% +It's not enough to be Hungarian; you must have talent too. + ― Alexander Korda +% +It's not hard to meet expenses; they're everywhere. +% +It's not often that you get so much class entertainment outside your bedroom +window or outside your bedroom, period. + ― Groucho Marx +% +It's not our job to toughen our children up to face a cruel and heartless +world. It's our job to raise children who will make the world a little less +cruel and heartless. + ― L.R. Knost +% +It's not reality that's important, but how you perceive things. +% +It's not that I'm afraid to die. I just don't want to be there when it +happens. + ― Woody Allen +% +It's not the fall that kills you, it's the sudden stop. +% +It's not what we don't know that gets us into trouble, it's what we know that +ain't so. + ― Will Rogers +% +It's really quite a simple choice: Life, Death, or Los Angeles. +% +It's smart to pick your friends - but not to pieces. +% +It's so humid, you could poach an egg on the sidewalk. +% +Jacquin's Postulate on Democratic Government: No man's life, liberty, or +property are safe while the legislature is in session. +% +Jay's First Law: The classic hierarchy consists of one man at the top with +three below him, each of who has three below him, and so on with fearful +symmetry unto the seventh generation, by which stage there is a row of 729 +managers. + ― Antony Jay, Management and Machiavelli, 1967 +% +Jenkinson's Law: It won't work. +% +Jesus may love you, but I think you're garbage wrapped in skin. + ― Michael O'Donoghue +% +Jesus was killed by a Moral Majority. +% +Jizz changes everything. It's science! + ― Jim Chapman +% +John Birch Society ― that pathetic manifestation of organized apoplexy. + ― Edward P. Morgan +% +Johnson's First Law: When any mechanical contrivance fails, it will do so +at the most inconvenient possible time. +% +Jones' Law: The man who smiles when things go wrong has thought of someone +to blame it on. +% +Jones' Law of Hierarchical Limits: As an administrator, you need to give +ten pats on the head for each kick in the butt. This is the reason for +keeping the number of people reporting to you a fairly small number. +Otherwise, you will run out of hands, but still have an overcapacity in feet. +% +Jones' Motto: Friends come and go, but enemies accumulate. +% +Jones's First Law: + Anyone who makes a significant contribution to any field of + endeavor, and stays in that field long enough, becomes an + obstruction to its progress ― in direct proportion to the + importance of their original contribution. +% +Journalism will kill you, but it will keep you alive while you're at it. +% +Jury ― Twelve people who determine which client has the better lawyer. +% +Just because everything is different doesn't mean anything has changed. + ― Southern California Oracle +% +Just because you're paranoid doesn't mean they AREN'T after you. +% +Just because your doctor has a name for your condition doesn't mean he knows +what it is. +% +Just because your doctor has a name for your condition doesn't mean he +knows what it is. +% +Just give Alice some pencils and she will stay busy for hours. + ― B. Kliban +% +Just once I'd like to meet an alien menace that isn't immune to bullets. + ― The Brigadier, Dr. Who. +% +Just remember: when you go to court, you are trusting your fate to +twelve people that weren't smart enough to get out of jury duty! +% +Just remember: you're not a "dummy," no matter what those computer books +claim. The real dummies are the people who―though technically +expert―couldn't design hardware and software that's usable by normal +consumers if their lives depended upon it. + ― Walter Mossberg +% +Justice is incidental to law and order. + ― J. Edgar Hoover +% +Justice, like lightning, should ever appear +To some men hope, to other men fear. + ― Jefferson Pierce +% +Justice: A decision in your favor. +% +Karl's version of Parkinson's Law: Work expands to exceed the time allotted it. +% +Katz' Law: Man and nations will act rationally when all other possibilities +have been exhausted. +% +Keep emotionally active. Cater to your favorite neurosis. +% +Keep in mind always the two constant Laws of Frisbee: +1. The most powerful force in the world is that of a disc straining to land + under a car, just out of reach. (This force is technically termed "car + suck.") +2. Never precede any maneuver by a comment more predictive than "Watch this!" +% +Ken Thompson has an automobile which he helped design. Unlike most +automobiles, it has neither speedometer, nor gas gage, nor any of the +numerous idiot lights which plague the modern driver. Rather, if the driver +makes any mistake, a giant "?" lights up in the center of the dashboard. +"The experienced driver", he says, "will usually know what's wrong." +% +Ketterling's Law: Logic is an organized way of going wrong with confidence. +% +Kinkler's First Law: Responsibility always exceeds authority. +Kinkler's Second Law: All the easy problems have been solved. +% +Klein bottle for rent, apply within. +% +Know what I hate most? Rhetorical questions. + ― Henry N. Camp +% +L'extension des privileges des femmes est le principe general de tous progres +sociaux. + ― Charles Fourier, 1808 +% +Labor, n.: One of the processes by which A acquires property for B. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Lack of skill dictates economy of style. + ― Joey Ramone +% +Lactomangulation, n.: Manhandling the "open here" spout on a milk carton so +badly that one has to resort to using the "illegal" side. + ― Rich Hall, "Sniglets" +% +Laissez Faire Economics is the theory that if each acts like a vulture, +all will end as doves. +% +Largely because it is so tangible and exciting a program and as such will +serve to keep alive the interest and enthusiasm of the whole spectrum of +society...It is justified because...the program can give a sense of shared +adventure and achievement to the society at large. + ― Dr. Colin S. Pittendrigh, in "The History of Manned Space Flight" +% +Larkinson's Law: All laws are basically false. +% +Laugh, and the world ignores you. Crying doesn't help either. +% +Law of Communications: The inevitable result of improved and enlarged +communications between different levels in a hierarchy is a vastly +increased area of misunderstanding. +% +Law of Computability Applied to Social Sciences: + If at first you don't succeed, transform your data set. +% +Law of Probable Dispersal: Whatever it is that hits the fan will not be +evenly distributed. +% +Law of Selective Gravity: An object will fall so as to do the most damage. +% +Lawrence's Axiom: Anger is one letter short of danger. +% +Laws of Computer Programming +(1) Any given program, when running, is obsolete. +(2) Any given program costs more and takes longer. +(3) If a program is useful, it will have to be changed. +(4) If a program is useless, it will have to be documented. +(5) Any given program will expand to fill all available memory. +(6) The value of a program is proportional to the weight of its output. +(7) Program complexity grows until it exceeds the capability of the + programmer who must maintain it. +(8) Make it possible for programmers to write programs in English, and you + will find that programmers cannot write in English. + ― SIGPLAN Notices, Vol. 2, No. 2 +% +Lazlo's Chinese Relativity Axiom: No matter how great your triumphs or how +tragic your defeats ― approximately one billion Chinese couldn't care less. +% +Lead, follow, or get out of the way. + ― Anon +% +Learned men are the cisterns of knowledge, not the fountainheads. +% +Left to themselves, things tend to go from bad to worse. +% +Leisure can be justified. +Recreation maximizes productive stamina. +Play is not the opposite of work. +Idleness consolidates thought. + ― Thomas "Sam" Frantz +% +Lend money to a bad debtor and he will hate you. +% +Let He who taketh the Plunge Remember to return it by Tuesday. +% +Let a fool hold his tongue and he will pass for a sage. +% +Let me play with it first and I'll tell you what it is later. + ― Miles Davis +% +Let me tell you the truth: The truth is what is. And what should be is a +fantasy, a terrible, terrible lie somebody gave the people long ago. + ― Lenny Bruce +% +Let not the sands of time get in your lunch. +% +Let the machine do the dirty work. +% +Let us, then, fellow citizens, unite with one heart and one mind. Let us +restore to social intercourse that harmony and affection without which +liberty and even life itself are but dreary things. And let us reflect +that having banished from our land that religious intolerance under which +mankind so long bled, we have yet gained little if we countenance a +political intolerance as despotic, as wicked, and capable of a bitter and +bloody persecutions. + ― Thomas Jefferson +% +Let's give discredit where discredit is due. + ― Karl Lehenbauer +% +Lewis's Law of Travel: + The first piece of luggage out of the chute doesn't belong to + anyone, ever. +% +Liar, n.: A lawyer with a roving commission. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Liar: One who tells an unpleasant truth. +% +Liberty is the mother not the daughter of order. + ― Proudhon +% +Lie: A very poor substitute for the truth, but the only one discovered to date. +% +Lieberman's Law: Everybody lies, but it doesn't matter since nobody listens. +% +Lies written in ink can never disguise facts written in blood. Blood debts +must be repaid in kind. The longer the delay, the greater the interest. + ― Chinese author Lu Xun, 1926 +% +Life in a free society is friendly, prosperous, pleasant, cultured, and +ever-longer. + ― Jeff Daiell, 1989, in counterpoint to Hobbes +% +Life in the state of nature is solitary, poor, nasty, brutish, and short. + ― Thomas Hobbes, Leviathan +% +Life is a pinball machine. You bounce around for a while, and then you drain. + ― Joe Bak +% +Life is a whim of several billion cells to be you for a while. +% +Life is full of surprises when you're up th' stream of consciousness +without a paddle... + ― Zippy the Pinhead +% +Life is like an onion: you peel off layer after layer, then you find +there is nothing in it. +% +Life is not one thing after another, it's the same damned thing over and over. +% +Life is the application of noble and profound ideas to life. + ― Matthew Arnold +% +Life is tough, but it's tougher when you're stupid. + ― John Wayne +% +Life is wasted on the living. + ― Zaphod Beeblebrox IV +% +Life is what happens to you while you are planning to do something else. +% +Life's greatest gift is natural talent. + ― P. K. Thomajan +% +Life. Don't talk to me about life. + ― Marvin the Paranoid Anroid +% +Like so many Americans, she was trying to construct a life that made +sense from things she found in gift shops. + ― Kurt Vonnegut, Jr. +% +Like the ski resort of girls looking for husbands and husbands looking +for girls, the situation is not as symmetrical as it might seem. + ― Alan McKay +% +Like winter snow on summer lawn, time past is time gone. +% +Line Printer paper is strongest at the perforations. +% +listen: there's a hell of a good universe next door; + let's go. + ― ee cummings +% +Live every day like it's your last because someday you'll be right. +% +Live free or die. +% +Living on Earth may be expensive, but it includes an annual free trip +around the Sun. +% +Living your life is a task so difficult, it has never been attempted before. +% +Logic is a little bird, sitting in a tree, that smells awful. +% +Long computations which yield 0 (zero) are probably all for naught. +% +Long distance runners break into more pants. +% +Long life is in store for you. +% +Look under the sofa cushion; you will be surprised at what you find. +% +Look, let me explain something to you. I'm not Mr. Lebowski. You're +Mr. Lebowski. I'm the Dude. So that's what you call me. That, or His +Dudeness … Duder … or El Duderino, if, you know, you're not into the +whole brevity thing. + ― The Dude ("The Big Lebowski") +% +Lord, defend me from my friends; I can account for my enemies. + ― D'Hericault +% +Los Angeles is a geometropolitan predicament rather than a city. You can no +more administer it than you could administer the solar system. + ― Jonathan Miller +% +Lots of folks confuse bad management with destiny. + ― Elbert Hubbard +% +Love and scandal are the best sweeteners of tea. +% +Love means never having to say, "Put down that meat cleaver." +% +Love your enemies: they'll go crazy trying to figure out what you're up to. +% +Lowery's Law: If it jams ― force it. If it breaks, it needed replacing +anyway. +% +Lubarsky's Law of Cybernetic Entomology: There's always one more bug. +% +Luck is probability taken personally. + ― Chip Denman +% +Luck is what happens when preparation meets opportunity. + ― E. Letterman +% +Lunatic Asylum: The place where optimism most flourishes. +% +Lynch's Law: When the going gets tough, everyone leaves. +% +Machines take me by surprise with great frequency. + ― Alan Turing +% +Mad, adj.: Affected with a high degree of intellectual independence ... + ― Ambrose Bierce, "The Devil's Dictionary" +% +Main's Law: For every action there is an equal and opposite government program. +% +Maintainer's Motto: If we can't fix it, it ain't broke. +% +Majority: That quality that distinguishes a crime from a law. +% +Make a wish: it might come true. +% +Make input easy to proofread +% +Make it possible for programmers to write in English and you will find the +programmers cannot write in English. +% +Make it right before you make it faster. +% +Make no little plans. They have no Magic to stir Men's blood. + ― D. B. Hudson +% +Make sure all variables are initialized before use. +% +Make sure comments and code agree. +% +Make sure your code "does nothing" gracefully. +% +Making files is easy under the UNIX operating system. Therefore, users +tend to create numerous files using large amounts of file space. It +has been said that the only standard thing about all UNIX systems is +the message-of-the-day telling users to clean up their files. + ― System V.2 administrator's guide +% +Malek's Law: Any simple idea will be worded in the most complicated way. +% +Man is a Generalist. Specialization is for insects. + ― Lazarus Long +% +Man is a rational animal who always loses his temper when he is called +upon to act in accordance with the dictates of reason. + ― Oscar Wilde +% +Man is a rationalizing animal, not a rational animal. + ― R. A. Heinlein +% +Man is the best computer we can put aboard a spacecraft ... and the +only one that can be mass produced with unskilled labor. + ― Wernher von Braun +% +Man rarely reads the handwriting on the wall until he has his back to it. +% +Man who falls in blast furnace is certain to feel overwrought. +% +Man who falls in vat of molten optical glass makes spectacle of self. +% +Man will occasionally stumble over the truth, but most times he will pick +himself up and carry on... + ― Winston Churchill +% +Man's horizons are bounded by his vision. +% +Mankind has yet to devise a rule that never requires exceptions. + ― Wayne Dyer +% +Manual, n.: A unit of documentation. There are always three or more on a +given item. One is on the shelf; someone has the others. The information +you need is in the others. + ― Ray Simard +% +Many an optimist has become rich by buying out a pessimist. +% +Many are called, few are chosen. Fewer still get to do the choosing. +% +Many are called, few volunteer. +% +Many are cold, but few are frozen. +% +Many are the wonders of the Universe, and none so wonderful as Mankind! + ― Sophocles +% +Many changes of mind and mood; do not hesitate too long. +% +Many pages make a thick book. +% +Many receive advice, few profit from it. +% +Many years ago in a period commonly know as Next Friday Afternoon, +there lived a King who was very Gloomy on Tuesday mornings because he +was so Sad thinking about how Unhappy he had been on Monday and how +completely Mournful he would be on Wednesday ... + ― Walt Kelly +% +Mark's Dental-Chair Discovery: + Dentists are incapable of asking questions that require a + simple yes or no answer. +% +Marriage is the only adventure open to the cowardly. + ― Voltaire +% +Marshall's generalized iceberg theorem: 7/8ths of everything cannot be seen. +% +Martin's Law of Communication: The inevitable result of improved and +enlarged communication between different levels in a hierarchy is a vastly +increased area of misunderstanding. +% +Matter cannot be created or destroyed, nor can it be returned without a +receipt. +% +Maturity is only a short break in adolescence. + ― Jules Feiffer +% +Maybe Computer Science should be in the College of Theology. + ― R. S. Barton +% +McGowan's Madison Avenue Axiom: If an item is advertised as "under $50", +you can bet it's not $19.95. +% +Meader's Law: Whatever happens to you, it will previously have happened to +everyone you know, only more so. +% +Measure with a micrometer. Mark with chalk. Cut with an axe. +% +Mediocrity thrives on standardization. + ― Wayne Dyer +% +Meditation is not what you think. +% +Meeting, n.: An assembly of people coming together to decide what person or +department not represented in the room must solve a problem. +% +Memories of you remind me of you. + ― Karl +% +Memory should be the starting point of the present. +% +Men love to wonder, and that is the seed of science. +% +Men ought to know that from the brain and from the brain only arise our +pleasures, joys, laughter, and jests as well as our sorrows, pains, griefs +and tears. ... It is the same thing which makes us mad or delirious, inspires +us with dread and fear, whether by night or by day, brings us sleeplessness, +inopportune mistakes, aimless anxieties, absent-mindedness and acts that are +contrary to habit... + ― Hippocrates (c. 460-c. 377 B.C.), The Sacred Disease +% +Mencken and Nathan's Fifteenth Law of The Average American: + The worst actress in the company is always the manager's wife. +% +Mencken and Nathan's Second Law of The Average American: + All the postmasters in small towns read all the postcards. +% +Menu: A list of dishes which the restaurant has just run out of. +% +Meskimen's Law: There's never time to do it right, but there's always time to +do it over. +% +Might as well be frank, monsieur. It would take a miracle to get you out of +Casablanca. +% +Miksch's Law: If a string has one end, then it has another end. +% +Mile's Law: where you stand depends on where you sit. +% +Military intelligence is a contradiction in terms. + ― Groucho Marx +% +Military justice is to justice what military music is to music. + ― Groucho Marx +% +Millions long for immortality who do not know what to do with +themselves on a rainy Sunday afternoon. + ― Susan Ertz +% +Millions of sensible people are too high-minded to concede that politics is +almost always the choice of the lesser evil. "Tweedledum and Tweedledee," +they say, "I will not vote." Having abstained, they are presented with a +President who appoints the people who are going to rummage around in their +lives for the next four years. Consider all the people who sat home in a +stew in 1968 rather than vote for Hubert Humphrey. They showed Humphrey. +Those people who taught Hubert Humphrey a lesson will still be enjoying the +Nixon Supreme Court when Tricia and Julie begin to find silver threads +among the gold and the black. + ― Russel Baker, "Ford without Flummery" +% +Mirrors should reflect a little before throwing back images. + ― Jean Cocteau +% +Misery loves company, but company does not reciprocate. +% +Miss Wormwood: What state do you live in? +Calvin: Denial. +Miss Wormwood: I don't suppose I can argue with that... +% +Mistakes are often the stepping stones to utter failure. +% +Mister Ranger isn't gonna like it, Yogi. +% +Mitchell's Law of Committees: + Any simple problem can be made insoluble if enough meetings are + held to discuss it. +% +Modern man is the missing link between the apes and humans. +% +Modesty is an ornament, but you go further without it. + ― German Proverb +% +Modesty is of no use to a beggar. + ― Homer +% +Mollison's Bureaucracy Hypothesis: If an idea can survive a bureaucratic +review and be implemented it wasn't worth doing. +% +Money is like a sixth sense, and you can't use the other five without it. +% +Money, not morality, is the principle commerce of civilized nations. + ― Thomas Jefferson +% +Morality is one thing. Ratings are everything. + ― A Network 23 executive on "Max Headroom" +% +More than any time in history, mankind now faces a crossroads. One path +leads to despair and utter hopelessness, the other to total extinction. Let +us pray that we have the wisdom to choose correctly. + ― Woody Allen +% +Moses supposes his toeses are roses, but Moses supposes erroneously. +% +Mosher's Law of Software Engineering: + Don't worry if it doesn't work right. If everything did, you'd + be out of a job. +% +Most legislators are so dumb that they couldn't pour piss out of a boot +if the instructions were printed on the heel. +% +Most of you are familiar with the virtues of a programmer. There are +three, of course: laziness, impatience, and hubris. + ― Larry Wall +% +Mother told me to be good, but she's been wrong before. +% +Mr. Cole's Axiom: The sum of the intelligence on the planet is a constant; the +population is growing. +% +Mr. Ranger isn't gonna like it, Yogi. +% +Mrs Podgorny: Angus how are y'going to get 48,000,000 kilts into the van? +Angus: I'll have t'do it in two goes. +% +Muddy water let stand will clear. + ― Chinese Proverb +% +Murphy's Law is recursive. Washing your car to make it rain doesn't work. +% +Murphy's Law of Research: Enough research will tend to support your theory. +% +My answer is, bring them on. + ― George W. Bush, on Iraqi militants attacking U.S. forces; + Washington, D.C.; July 3, 2003 +% +My grandson has learned how to hold and carry the cat. He has also learned +how to flush the toilet. I can't help but believe that in the +not-too-distant future there will be another lesson in store for him. + ― Dave Henry +% +My head is bloodied, but unbowed. + ― From the poem "Invictus" +% +My life is so fucking miserable that I don't know whether I was +born or if Morrissey just sang me into existence. + ― R.K. Milholland +% +My mother is a fish. + ― William Faulkner +% +My opinions may have changed, but not the fact that I am right. +% +My own life has been spent chronicling the rise and fall of human systems, +and I am convinced that we are terribly vulnerable.... We should be +reluctant to turn back upon the frontier of this epoch. Space is +indifferent to what we do; it has no feeling, no design, no interest in +whether or not we grapple with it. But we cannot be indifferent to space, +because the grand, slow march of intelligence has brought us, in our +generation, to a point from which we can explore and understand and utilize +it. To turn back now would be to deny our history, our capabilities. + ― James A. Michener +% +My past is my own. + ― The Shadow (DC Comics) +% +Naeser's Law: You can make it foolproof, but you can't make it damnfoolproof. +% +Natural gas is hemispheric. I like to call it hemispheric in nature, +because it is a product what we can find in our neighborhoods. + ― George W. Bush, Austin, Texas; December 20, 2000 +% +Natural selection won't matter soon, not anywhere as much as concious +selection. We will civilize and alter ourselves to suit our ideas of what +we can be. Within one more human lifespan, we will have changed ourselves +unrecognizably. + ― Greg Bear +% +Nearly all men can stand adversity, but if you want to test a man's +character, give him power. + ― Abraham Lincoln +% +Necessity is a mother. +% +Neil Armstrong to Walter Cronkite: "Well, Walter, I believe that the Good +Lord gave us a finite number of heartbeats and I'm damned if I'm going to +use up mine running up and down a street." +% +Neil Armstrong tripped. +% +Never be led astray onto the path of virtue. +% +Never call a man a fool; borrow from him. +% +Never count your chickens before they rip your lips off. +% +Never drink Coke in a moving elevator. The elevator's motion coupled with +the chemicals in coke produce hallucinations. People tend to change into +lizards and attack without warning, and large bats usually fly in the +window. Additionally, you begin to believe that elevators have windows. +% +Never insult an alligator until you have crossed the river. +% +Never invest your money in anything that eats or needs painting. + ― Billy Rose +% +Never lick a gift horse in the mouth. +% +Never put off until tomorrow what you can avoid altogether. +% +Never say you know a man until you have divided an inheritance with him. +% +Never throw a bird at a dragon. +% +Never count your chickens until they rip your lips off. +% +New Year's Eve is the time of year when a man most feels his age, and +his wife most often reminds him to act it. + ― Webster's Unafraid Dictionary +% +New York... when civilization falls apart, remember, we were way ahead of you. + ― David Letterman +% +New boots, big steps. + ― Chinese Proverb +% +New systems generate new problems. +% +Newlan's Truism: + An "acceptable" level of unemployment means that the government + economist to whom it is acceptable still has a job. +% +Newton's Fourth Law: Every action has an equal and opposite satisfaction. +% +Newton's Little-Known Seventh Law: + A bird in the hand is safer than one overhead. +% +Next Friday will not be your lucky day. As a matter of fact, you don't +have a lucky day this year. +% +Next Wednesday you will be presented with a great opportunity. +% +Next to being shot at and missed, nothing is really quite as satisfying +as an income tax refund. + ― F. J. Raymond +% +Nihil tam munitum quod non expugnari pecunia possit. (No fort is so strong +that it cannot be taken with money.) + ― Cicero +% +Nihilism should commence with oneself. +% +No amount of genius can overcome a preoccupation with detail. +% +No guts, no glory. +% +No man was ever taken to hell by a woman unless he already had a ticket in +his pocket, or at least had been fooling around with timetables. + ― Archie Goodwin +% +No man's life, liberty, or property is safe while the Legislature is in +session. + ― Lysander Spooner +% +No matter how cynical you get, it's impossible to keep up. +% +No matter where you go, there you are. + ― Buckaroo Banzai +% +No one can feel as helpless as the owner of a sick goldfish. +% +No one can make you feel inferior without your consent. + ― Eleanor Roosevelt +% +No one is fit to be trusted with power. ... No one. ... Any man who has lived +at all knows the follies and wickedness he's capable of. ... And if he does +know it, he knows also that neither he nor any man ought to be allowed to +decide a single human fate. + ― C. P. Snow, The Light and the Dark +% +No one is talking behind your back as far as you know. +% +No one who accepts the sovereignty of truth can be a foot soldier in a party +or movement. He will always find himself out of step. + ― Sidney Hook +% +No one's happiness but my own is in my power to achieve or to destroy. + ― Ayn Rand +% +No problem is insoluble in all conceivable circumstances. +% +No problem is so formidable that you can't just walk away from it. +% +No problem is so large it can't be fit in somewhere. +% +No, 'tis not so deep as a well, nor so wide as a church-door; but 'tis enough, +'twill serve: ask for me to-morrow, and you shall find me a grave man. + ― Mercutio, Romeo and Juliet, Act III, Scene 1 +% +No user-serviceable parts inside. Refer to qualified service personnel. +% +Nobody can be as agreeable as an uninvited guest. +% +Nobody can be exactly like me. Even I have trouble doing it. + ― Tallulah Bankhead +% +Nobody expects the Spanish Inquisition. +% +Nobody wants constructive criticism. It's all we can do to put up with +constructive praise. +% +Non-Reciprocal Laws of Expectations: + Negative expectations yield negative results. + Positive expectations yield negative results. +% +Nondeterminism means never having to say you are wrong. +% +None love the bearer of bad news. + ― Sophocles +% +Nostalgia isn't what it used to be. +% +Nothing astonishes men so much as common sense and plain dealing. +% +Nothing cures insomnia like the realization that it's time to get up. +% +Nothing ever becomes real till it is experienced ― even a proverb is no +proverb to you till your life has illustrated it. + ― John Keats +% +Nothing in life is to be feared. It is only to be understood. +% +Nothing in progression can rest on its original plan. We may as well think of +rocking a grown man in the cradle of an infant. + ― Edmund Burke +% +Nothing is as repulsive as phoniness; conversely, nothing is as magnetic +as reality. + ― Howard Henrichs +% +Nothing is done until nothing is done. +% +Nothing is easier than to denounce the evildoer; nothing is more difficult +than to understand him. + ― Fyodor Dostoevski +% +Nothing is illegal if one hundred businessmen decide to do it. + ― Andrew Young +% +Nothing is so contagious as enthusiasm: It moves stones, and it charms brutes. +% +Nothing recedes like success. + ― Walt Kelly +% +Now and then an innocent man is sent to the Legislature. +% +Numeric stability is probably not all that important when you're guessing. +% +O'Riordan's Theorem: Brains x Beauty = Constant. +Purmal's Corollary: As the limit of (Brains x Beauty) goes to infinity, +availability goes to zero. +% +O'Toole's Commentary on Murphy's Law: Murphy was an optimist. +% +Objects on your screen are closer than they appear. +% +Obviously, a man's judgement cannot be better than the information on which +he has based it. Give him the truth and he may still go wrong when he has +the chance to be right, but give him no news or present him only with +distorted and incomplete data, with ignorant, sloppy or biased reporting, +with propaganda and deliberate falsehoods, and you destroy his whole +reasoning processes, and make him something less than a man. + ― Arthur Hays Sulzberger +% +Ocean, n.: A body of water occupying about two-thirds of a world made for +man ― who has no gills. +% +Of all the animals, the boy is the most unmanageable. + ― Plato +% +Of all the tyrannies that affect mankind, tyranny in religion is the worst. + ― Thomas Paine +% +Of course there's no reason for it, it's just our policy. +% +Of course, someone who knows more about this will correct me if I'm wrong, +and someone who knows less will correct me if I'm right. + ― David Palmer (palmer@tybalt.caltech.edu) +% +Ogden's Law: The sooner you fall behind, the more time you have to catch up. +% +Oh dear, I think you'll find reality's on the blink again. + ― Marvin the Paranoid Android +% +Oh, well, I guess this is just going to be one of those lifetimes. +% +Old MacDonald had an agricultural real estate tax abatement. +% +Old age is the most unexpected of things that can happen to a man. + ― Trotsky +% +Old programmers never die. They just branch to a new address. +% +Oliver's First Law of Computing: Computers are much too complex; they'll +never work. + ― Robert Oliver (circa 1982) +% +On a clear disk you can seek forever. +% +On our campus the UNIX system has proved to be not only an effective software +tool, but an agent of technical and social change within the University. + ― John Lions (U. of Toronto (?)) +% +Once ... in the wilds of Afghanistan, I lost my corkscrew, and we were +forced to live on nothing but food and water for days. + ― W. C. Fields, "My Little Chickadee" +% +One Page Principle: A specification that will not fit on one page of 8.5x11- +inch paper cannot be understood. + ― Mark Ardis +% +One becomes a critic when one cannot be an artist, just as a man becomes a +stool pigeon when he cannot be a soldier. + ― Gustave Flaubert (letter to Madame Louise Colet, August 12, 1846) +% +One can't proceed from the informal to the formal by formal means. +% +One difference between a man and a machine is that a machine is quiet +when well oiled. +% +One friend in a lifetime is much; two are many; three are hardly possible. +Friendship needs a certain parallelism of life, a community of thought, +a rivalry of aim. + ― Henry Brook Adams +% +One good reason why computers can do more work than people is that they +never have to stop and answer the phone. +% +One man tells a falsehood, a hundred repeat it as true. +% +One may be able to quibble about the quality of a single experiment, or +about the veracity of a given experimenter, but, taking all the supportive +experiments together, the weight of evidence is so strong as readily to +merit a wise man's reflection. + ― Professor William Tiller, parapsychologist, Stanford University, + commenting on psi research +% +One millihelen: the unit of beauty required to launch just one ship +% +One of my less pleasant chores when I was young was to read the Bible +from one end to the other. Reading the Bible straight through is at +least 70 percent discipline, like learning Latin. But the good parts +are, of course, simply amazing. God is an extremely uneven writer, but +when He's good, nobody can touch Him. + ― John Gardner, NYT Book Review, Jan 1983 +% +One of the most misleading representational techniques in our language is +the use of the word "I". + ― Ludwig Wittgenstein +% +One of the saddest lessons of history is this: If we've been bamboozled +long enough, we tend to reject any evidence of the bamboozle. We're no +longer interested in finding out the truth. The bamboozle has captured +us. it is simply too painful to acknowledge ― even to ourselves ― that +we've been so credulous. (So the old bamboozles tend to persist as the +new bamboozles rise.) + ― Carl Sagan, "The Fine Art of Baloney Detection," + Parade, February 1, 1987 +% +One seldom sees a monument to a committee. +% +One thing the inventors can't seem to get the bugs out of is fresh paint. +% +One way to stop a runaway horse is to bet on him. +% +One's mind, stretched to a new idea, never goes back to its original dimension. +% +Only God can make random selections. +% +Opinions are like assholes: everyone's got one, but nobody wants to look at +the other guy's. + ― Hal Hickman +% +Optimists say the glass is half full, pessimists say the glass is half +empty, engineers say the glass is twice as big as it needs to be. +% +Optimization hinders evolution. +% +Optimization is not some mystical state of grace, it is an intricate act +of human labor which carries real costs and real risks. + ― Tom Neff +% +Ordinary people: I fuckin' hate 'em. + ― Harry Dean Stanton in "Repo Man" +% +Oregon, n.: + Eighty billion gallons of water with no place to go on Saturday +night. +% +Organic chemistry is the chemistry of carbon compounds. +Biochemistry is the study of carbon compounds that crawl. + ― Mike Adams +% +Osborn's Law: Variables won't; constants aren't. +% +Our journeys to the stars will be made on spaceships created by determined, +hardworking scientists and engineers applying the principles of science, not +aboard flying saucers piloted by little gray aliens from some other dimension. + ― Robert A. Baker, "The Aliens Among Us: Hypnotic Regression + Revisited", The Skeptical Inquirer, Vol. XII, No. 2 +% +Our liberty depends upon the freedom of the press, and that cannot be +limited without being lost. + ― Thomas Jefferson (1786) +% +Our policy is, when in doubt, do the right thing. + ― Roy L. Ash, ex-president Litton Industries +% +Out of body, back in five minutes. +% +Outside of a dog, a book is man's best friend. Inside of a dog, it is too +dark to read. +% +Overdrawn? But I still have checks left! +% +Overflow on /dev/null, please empty the bit bucket. +% +Overload ― core meltdown sequence initiated. +% +PHP is a minor evil perpetrated and created by incompetent amateurs, +whereas Perl is a great and insidious evil perpetrated by skilled but +perverted professionals. + ― Jon Ribbens +% +Paranoia doesn't mean the whole world really isn't out to get you. +% +Paranoia is simply an optimistic outlook on life. +% +Paranoids are people, too; they have their own problems. It's easy to +criticize, but if everybody hated you, you'd be paranoid too. + ― D. J. Hicks +% +Parking fees that Universal Studios collected from picketers of _The Last +Temptation of Christ_: $4,500 + ― Harper's Index Nov. 1988 +% +Parkinson's Fifth Law: If there is a way to delay in important decision, +the good bureaucracy, public or private, will find it. +% +Parkinson's Fourth Law: The number of people in any working group tends to +increase regardless of the amount of work to be done. +% +Parkinson's Law: Work expands to fill the time alloted it. +% +Parts that positively cannot be assembled in improper order will be. +% +Benford's Law of Controversy: Passion is inversely proportional to the +amount of real information available. + ― Gregory Benford +% +Passionate hatred can give meaning and purpose to an empty life. + ― Eric Hoffer +% +Patience, n. A minor form of despair, disguised as a virtue. + ― Ambrose Bierce +% +Patriotism is the virtue of the vicious. + ― Oscar Wilde +% +Pay no attention to that man behind the curtains. +% +Peace: a period of cheating between two wars. +% +People are very flexible and learn to adjust to strange surroundings ― +they can become accustomed to reading Lisp and Fortran programs, for example. + ― Leon Sterling and Ehud Shapiro, Art of Prolog, MIT Press +% +People get lost in thought because it is unfamiliar territory. +% +People often find it easier to be a result of the past than a cause of +the future. +% +People think it must be fun to be a super genius, but they don't realize how +hard it is to put up with all the idiots in the world. + ― Calvin +% +People usually get what's coming to them ... unless it's been mailed. +% +People who claim they don't let little things bother them have never +slept in a room with a single mosquito. +% +People who have no faults are terrible; there is no way of taking advantage +of them. +% +People who look down on other people do not end up being looked up to. +% +People will accept your ideas much more readily if you tell them that +Benjamin Franklin said it first. +% +People will buy anything that's one to a customer. +% +Pereant, inquit, qui ante nos nostra dixerunt. +(Confound those who have said our remarks before us.) + ― Aelius Donatus +% +Perfection is achieved only on the point of collapse. + ― C. N. Parkinson +% +Perpetuo vincit qui utitur clementia. (He is forever victor who employs +clemency.) + ― Syrus +% +Personality can open doors, but only character can keep them open. + ― E. G. Leter +% +Peter's Law of Substitution: Look after the molehills, and the mountains +will look after themselves. +% +Philogyny recapitulates erogeny; erogeny recapitulates philogyny. +% +Philosophy: Unintelligible answers to insoluble problems. +% +pi seconds is a nanocentury. + ― Tom Duff +% +Pioneering basically amounts to finding new and more horrible ways to die + ― John W. Campbell +% +Plagiarism is basic to all culture. + ― Papa Seeger +% +Plan ahead: it was not raining when Noah built the ark. + ― Richard Cushing +% +Please don't ask me what the score is. I'm not even sure what the game is. + ― Ashleigh Brilliant +% +Please don't lie to me, unless you're absolutely sure I'll never find out the +truth. + ― Ashleigh Brilliant +% +Please go away. +% +Please ignore previous fortune. +% +Please try to limit the amount of `this room doesn't have any bazingas' +until you are told that those rooms are `punched out.' Once punched +out, we have a right to complain about atrocities, missing bazingas, +and such. + ― N. Meyrowitz +% +Please update your programs. +% +Poetry is nobody's business except the poet's, and everybody else can fuck off. + ― Philip Larkin +% +Pohl's law: Nothing is so good that somebody, somewhere, will not hate it. +% +Police up your spare rounds and frags. Don't leave nothin' for the dinks. + ― Willem Dafoe in "Platoon" +% +Political T.V. commercials prove one thing: some candidates can tell +all their good points and qualifications in just 30 seconds. +% +Politician, n.: From the Greek "poly" ("many") and the French "tete" +("head" or "face," as in "tete-a-tete": head to head or face to face). +Hence "polytetien", a person of two or more faces. + ― Martin Pitt +% +Poor is the pupil who does not surpass his master. + ― Leonardo da Vinci +% +Positive, adj.: Mistaken at the top of one's voice. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Power is poison. +% +Power, n: The only narcotic regulated by the SEC instead of the FDA. +% +Practice is the best of all instructors. + ― Publilius +% +Predestination was doomed from the start. +% +Prediction is very difficult, especially of the future. + ― Niels Bohr +% +Preserve the old, but know the new. +% +Preudhomme's Law of Window Cleaning: It's on the other side. +% +Prevalent beliefs that knowledge can be tapped from previous incarnations or +from a "universal mind" (the repository of all past wisdom and creativity) +not only are implausible but also unfairly demean the stunning achievements +of individual human brains. + ― Barry L. Beyerstein, "The Brain and Consciousness: Implications for + Psi Phenomena", The Skeptical Inquirer, Vol. XII No. 2, ppg. 163-171 +% +Prevent security leaks. +% +Pro is to Con as Progress is to Congress. +% +Probably the best operating system in the world is the [operating system] +made for the PDP-11 by Bell Laboratories. + ― Ted Nelson, October 1977 +% +Proclaim liberty throughout the land and to all the inhabitants thereof. + ― Leviticus 25:10 +% +Programming is an art form that fights back. +% +Programming is 10% science, 25% ingenuity and 65% getting the ingenuity to +work with the science. +% +Programming is like sex: one mistake and you're providing support for a +lifetime. + ― Michael Sinz +% +Progress is nothing but the victory of laughter over dogma. + ― Benjamin DeCasseres +% +Promptness is its own reward +If one lives by the clock instead of the sword. +% +Pronounce your prepositions, dammit! +% +Proper attention to Earthly needs of the poor, the depressed and the +downtrodden, would naturally evolve from dynamic, articulate, spirited +awareness of the great goals for Man and the society he conspired to erect. + ― David Baker, paraphrasing Harold Urey, + in "The History of Manned Space Flight" +% +Pull yourself together; things are not all that bad. +% +Put not your trust in money, but put your money in trust. +% +Put your trust in those who are worthy. +% +Putt's Law: Technology is dominated by two types of people: +Those who understand what they do not manage. +Those who manage what they do not understand. +% +Q. What's all wrinkled and hangs out your underwear? +A. Your mom! +% +Q.: "Why do trans-atlantic transfers take so long?" +A.: "Electrons don't swim very fast." +% +Q: How do you play religious roulette? +A: You stand around in a circle and blaspheme and see who gets struck + by lightning first. +% +Q: How many DEC repairman does it take to fix a flat ? +A: Five; four to hold the car up and one to swap tires. +% +Q: How many IBM CPUs does it take to execute a job? +A: Four; three to hold it down, and one to rip its head off. +% +Q: How many IBM CPUs does it take to do a logical right shift? +A: 33. 1 to hold the bits and 32 to push the register. +% +Q: How many IBM types does it take to change a light bulb? +A: 100. Ten to do it, and 90 to write document number GC7500439-0001, + Multitasking Incandescent Source System Facility, of which 10% of + the pages state only "This page intentionally left blank", and 20% + of the definitions are of the form "A ...... consists of sequences + of non-blank characters separated by blanks". +% +Q: How many Martians does it take to screw in a lightbulb? +A: One and a half. +% +Q: How many Oregonians does it take to screw in a light bulb? +A: Three. One to screw in the lightbulb and two to fend off all those + Californians trying to share the experience. +% +Q: How many existentialists does it take to screw in a lightbulb? +A: Two. One to screw it in and one to observe how the lightbulb itself + symbolizes a single incandescent beacon of subjective reality in a + netherworld of endless absurdity reaching out toward a maudlin + cosmos of nothingness. +% +Q: How many journalists does it take to screw in a lightbulb? +A: Three. One to report it as an inspired government program to bring + light to the people, one to report it as a diabolical government + plot to deprive the poor of darkness, and one to win a Pulitzer + Prize for reporting that Electric Company hired a lightbulb-assassin + to break the bulb in the first place. +% +Q: How many Pro-Lifers does it take to change a light bulb? +A: Two. One to screw it in and one to say that light started when the + screwing began. +% +Q: How many supply-siders does it take to change a light bulb? +A: None. The darkness will cause the light bulb to change by itself. +% +Q: How many surrealists does it take to change a light bulb? +A: Two. One to hold the giraffe and the other to fill the bathtub with + brightly-colored power tools. +% +Q. How many psychiatrists does it take to change a light bulb? +A. Only one, but it takes a really long time and the light bulb has to want + to change. +% +Q: What do you do with an elephant with three balls? +A: Walk him and pitch to the rhino. +% +Q: Why did the tachyontac cross the road? +A: Because it was on the other side. +% +Q: Why do mountain climbers rope themselves together? +A: To prevent the sensible ones from going home. +% +Quantity is no substitute for quality, but it's the only one we've got. +% +Quoth the Raven, "Never mind." +% +Quotations are for people who are not saying things worth quoting. +% +Quoting one is plagiarism. Quoting many is research. +% +Rational people don't go stomping around demanding that the world be +perfect for them. + ― Matthew N. Dodd , in comments posted to the + freebsd-java mailing list, 6 Feb 2000 +% +READ UNHAPPY - MAKNAM + ― LISP 1.5 +% +Romeo: Courage, man; the hurt cannot be much. +Mercutio: No, 'tis not so deep as a well, nor so wide as a church. +% +Rage, rage, against the dying of the light! + ― Dylan Thomas +% +Rarely is the question asked: Is our children learning? + ― George W. Bush; Florence, South Carolina; January 11, 2000 +% +Ray's Rule of Precision: + Measure with a micrometer. Mark with chalk. Cut with an axe. +% +Re: graphics: A picture is worth 10K words ― but only those to describe the +picture. Hardly any sets of 10K words can be adequately described with +pictures. +% +Reading is thinking with someone else's head instead of one's own. +% +Real Programmers don't play tennis, or any other sport that requires +you to change clothes. Mountain climbing is OK, and real programmers +wear their climbing boots to work in case a mountain should suddenly +spring up in the middle of the machine room. +% +Real Programmers think better when playing Adventure or Rogue. +% +Real Programs don't use shared text. Otherwise, how can they use +functions for scratch space after they are finished calling them? +% +Real Time, adj.: Here and now, as opposed to fake time, which only occurs there +and then. +% +Real wealth can only increase. + ― R. Buckminster Fuller +% +Receiving a million dollars tax free will make you feel better than +being flat broke and having a stomach ache. + ― Dolph Sharp, "I'm O.K., You're Not So Hot" +% +Recent investments will yield a slight profit. +% +Regardless of the legal speed limit, your Buick must be operated at +speeds faster than 85 MPH (140k/h). + ― presumable misprint from the 1987 Buick Grand National + owner's manual. +% +Reliable software must kill people reliably. + ― Andy Mickel +% +Religions revolve madly around sexual questions. +% +Religious bondage shackles and debilitates the mind and unfits it for +every noble enterprise. + ― James Madison, in a letter to William Bradford, April 1, 1774 +% +Remember that whatever misfortune may be your lot, it could only be worse +in Cleveland. +% +Remember: You cannot drain the ocean with a teaspoon. + ― Ignas Bernstein +% +Removing the error messages "now that the program is working" is like +wearing a parachute on the ground, but taking it off once you're in the air. + ― Kernighan & Plauger [Software Tools] +% +Render unto Caesar if line 54 is larger than line 62. +% +Replace repetitive expressions by calls to a common function. +% +Reporter, n.: A writer who guesses his way to the truth and dispels it with a +tempest of words. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Research is what I'm doing when I don't know what I'm doing. + ― Wernher von Braun +% +Resisting temptation is easier when you think you'll probably get +another chance later on. +% +Revolution is the opiate of the intellectuals. + ― "Oh, Lucky Man" +% +Ride the tributaries to reach the sea. + ― Arab Proverb +% +Rocky's Lemma of Innovation Prevention + Unless the results are known in advance, funding agencies will + reject the proposal. +% +Rudin's Law: In a crisis that forces a choice to be made between alternative +courses of action, most people will choose the worse one possible. +% +Rule of Feline Frustration: + When your cat has fallen asleep on your lap and looks utterly + content and adorable, you will suddenly have to go to the + bathroom. +% +Rule of the Great: + When people you greatly admire appear to be thinking deep + thoughts, they probably are thinking about lunch. +% +Rules for driving in New York: + 1) Anything done while honking your horn is legal. + 2) You may park anywhere if you turn your four-way flashers on. + 3) A red light means the next six cars may go through the intersection. +% +SCCS, the source motel! Programs check in and never check out! + ― Ken Thompson +% +Saints should always be judged guilty until they are proven innocent. + ― George Orwell +% +Salad is what food eats. +% +Satire does not look pretty upon a tombstone. +% +Sattinger's Law: It works better if you plug it in. +% +Saying that Java is nice because it works on all OSes is like saying that +anal sex is nice because it works on all genders. + ― Alanna +% +Schapiro's Explanation: The grass is always greener on the other side ― +but that's because they use more manure. +% +Science has proof without any certainty. Creationists have certainty +without any proof. + ― Ashley Montague +% +Science is what happens when preconception meets verification. +% +Scott's First Law: No matter what goes wrong, it will probably look right. +% +Scott's Second Law: When an error has been detected and corrected, it will + be found to have been wrong in the first place. +Corollary: After the correction has been found in error, it will be + impossible to fit the original quantity back into the equation. +% +See, in my line of work you got to keep repeating things over and over and +over again for the truth to sink in, to kind of catapult the propaganda. + ― George W. Bush; Greece, New York; May 24, 2005 +% +Seminars, n.: From "semi" and "arse", hence, any half-assed discussion. +% +Semper ubi sub ubi. +% +Serocki's Stricture: Marriage is always a bachelor's last option. +% +Sex is the mathematics urge sublimated. + ― M. C. Reed. +% +Sex is the poor man's opera. + ― G. B. Shaw +% +Sex without love is an empty experience, but, as empty experiences go, +it's one of the best. + ― Woody Allen +% +Shake hands with your mother again. + ― from an old hymn +% +Shaw's Principle: + Build a system that even a fool can use, and only a fool will + want to use it. +% +She hates testicles, thus limiting the men she can admire to Democratic +candidates for president. + ― John Greenway, "The American Tradition", on feminist + Elizabeth Gould Davis +% +She missed an invaluable opportunity to give him a look that you could +have poured on a waffle ... +% +Short words are best, and the old words when short are best of all. + ― Winston Churchill +% +Show business is just like high school, except you get paid. + ― Martin Mull +% +Show me a man who is a good loser and I'll show you a man who is +playing golf with his boss. +% +Silverman's Law: If Murphy's Law can go wrong, it will. +% +Simon's Law: Everything put together falls apart sooner or later. +% +Sin has many tools, but a lie is the handle which fits them all. +% +Skinner's Constant (or Flannagan's Finagling Factor): That quantity which, +when multiplied by, divided by, added to, or subtracted from the answer you +get, gives you the answer you should have gotten. +% +Slime is the agony of water. + ― Jean-Paul Sartre +% +So far as I can remember, there is not one word in the Gospels in +praise of intelligence. + ― Bertrand Russell +% +So we follow our wandering paths, and the very darkness acts as our guide and +our doubts serve to reassure us. + ― Jean-Pierre de Caussade, eighteenth-century Jesuit priest +% +So where the sheer incompetence of politicians and generals used to start +wars, the sheer incompetence of us computer people has now put an end to +it. No mean feat. For centuries humanity has been looking for the Weapon +That Would End War Forever. We have found it. War has ended, not with the +bang of a bomb, but with the gentle whisper of crashing software. + ― Gerard Stafleu (gerard@uwovax.uwo.ca) +% +So why don't you make like a tree, and get outta here. + ― Biff in "Back to the Future" +% +Socialism is power, power, and more power. + ― Oswald Spengler, Hitler's intellectual forebear +% +Society is the presumption of habit over instinct. + ― Peter Taylor +% +Sodd's Second Law: Sooner or later, the worst possible set of circumstances is +bound to occur. +% +Software entities are more complex for their size than perhaps any other human +construct because no two parts are alike. If they are, we make the two +similar parts into a subroutine ― open or closed. In this respect, software +systems differ profoundly from computers, buildings, or automobiles, where +repeated elements abound. + ― Fred Brooks, Jr. +% +Software suppliers are trying to make their software packages more +'user-friendly'.... Their best approach, so far, has been to take +all the old brochures, and stamp the words, 'user-friendly' on the cover. + ― Bill Gates, President, Microsoft, Inc. +% +Some cause happiness wherever they go; others, whenever they go. + ― Oscar Wilde +% +Some grow with responsibility, others just swell. + ― Arnold Glasow +% +Some men are discovered; others are found out. +% +Some people are born mediocre, some people achieve mediocrity, and some +people have mediocrity thrust upon them. + ― Joseph Heller, "Catch-22" +% +Some people fall for everything and stand for nothing. +% +Some people hope to achieve immortality through their works or their children. +I would prefer to achieve it by not dying. + ― Woody Allen +% +Some people in this department wouldn't recognize subtlety if it hit +them on the head. +% +Some people like my advice so much that they frame it upon the wall +instead of using it + ― Gordon R. Dickson +% +Sometimes I wonder if men and women really suit each other. Perhaps they +should live next door and just visit now and then. + ― Katherine Hepburn +% +Sometimes I worry about being a success in a mediocre world. + ― Lily Tomlin +% +Sometimes a cigar is just a cigar. + ― Sigmund Freud +% +Sometimes the only solution is to find a new problem. +% +Sometimes the only way out of a difficulty is through it. +% +Sometimes, too long is too long. + ― Joe Crowe +% +Spark's Sixth Rule for Managers: If a subordinate asks you a pertinent +question, look at him as if he had lost his senses. When he looks down, +paraphrase the question back at him. +% +Speak softly and carry a +6 two-handed sword. +% +Speaking as someone who has delved into the intricacies of PL/I, I am sure +that only Real Men could have written such a machine-hogging, +cycle-grabbing, all-encompassing monster. Allocate an array and free the +middle third? Sure! Why not? Multiply a character string times a bit +string and assign the result to a float decimal? Go ahead! Free a +controlled variable procedure parameter and reallocate it before passing it +back? Overlay three different types of variable on the same memory +location? Anything you say! Write a recursive macro? Well, no, but Real +Men use rescan. How could a language so obviously designed and written by +Real Men not be intended for Real Man use? +% +Spiritual leadership should remain spiritual leadership and the temporal +power should not become too important in any church. + ― Eleanor Roosevelt +% +Stability itself is nothing else than a more sluggish motion. +% +Stay out of the road, if you want to grow old. + ― Pink Floyd +% +Steinbach's Guideline for Systems Programming + Never test for an error condition you don't know how to + handle. +% +Stock brokers invest your money until it's all gone. + ― Woody Allen +% +Stop searching. Happiness is right next to you. Now, if it'd only take a bath. +% +Stult's Report: Our problems are mostly behind us. What we have to do now is +fight the solutions. +% +Stupidity, like virtue, is its own reward. +% +Sturgeon's Law: Ninety percent of everything is crap. +% +Success is a journey, not a destination. +% +Success is not free. Neither is failure. + ― Ray Kroc +% +Success is the ability to go from one failure to another with no loss +of enthusiasm. + ― Winston Churchill +% +Success is what happens when something goes right. + ― Arnold Glasow +% +Successful and fortunate crime is called virtue. + ― Seneca +% +Succumb to natural tendencies. Be hateful and boring. +% +Superiority is always detested. + ― Balasar Gracian +% +Sure there are dishonest men in local government. But there are dishonest +men in national government too. + ― Richard M. Nixon +% +Swipple's Rule of Order: He who shouts the loudest has the floor. +% +TV is chewing gum for the eyes. + ― Frank Lloyd Wright +% +Tact is the ability to tell a man he has an open mind when he has a +hole in his head. +% +Tact is the art of making a point without making an enemy. +% +Tact is the great ability to see other people as they think you see them. +% +Tact, n.: The unsaid part of what you're thinking. +% +Take care of the luxuries and the necessities will take care of themselves. +% +Take everything in stride. Trample anyone who gets in your way. +% +Take heart amid the deepening gloom that your dog is finally getting +enough cheese. + ― National Lampoon, "Deteriorada" +% +Take my word for it, the silliest woman can manage a clever man, but it +needs a very clever woman to manage a fool. + ― Kipling +% +Take what you can use and let the rest go by. + ― Ken Kesey +% +Tax reform means "Don't tax you, don't tax me, tax that fellow behind +the tree." + ― Russell Long +% +Teach a child to be polite and courteous in the home, and, when he +grows up, he will never be able to edge his car onto a freeway. +% +Technological progress has merely provided us with more efficient means +for going backwards. + ― Aldous Huxley +% +Tell a man that there are 300 billion stars in the universe, and he'll believe +you.... Tell him that a bench has wet paint upon it and he'll have to touch it +to be sure. +% +Ten years of rejection slips is nature's way of telling you to stop writing. + ― R. Geis +% +Than self restraint, there is nothing better. + ― Lao Tzu +% +That 150 lawyers should do business together ought not to be expected. + ― Thomas Jefferson, on the U.S. Congress. +% +That government is best which governs least. + ― Thomas Jefferson +% +That government is best which governs not at all. + ― Henry David Thoreau +% +That is the key to history. Terrific energy is expended ― civilizations +are built up ― excellent institutions devised; but each time something +goes wrong. Some fatal flaw always brings the selfish and cruel people to +the top, and then it all slides back into misery and ruin. In fact, the +machine conks. It seems to start up all right and runs a few yards, and +then it breaks down. + ― C. S. Lewis +% +That man is richest whose pleasures are cheapest. + ― Thoreau +% +That which is not good for the swarm, neither is it good for the bee. +% +That's the thing about people who think they hate computers. What they +really hate is lousy programmers. + ― Larry Niven and Jerry Pournelle in "Oath of Fealty" +% +The Abrams' Principle: The shortest distance between two points is off the +wall. +% +The Briggs/Chase Law of Program Development: To determine how long it will +take to write and debug a program, take your best estimate, multiply that +by two, add one, and convert to the next higher units. +% +The English have no respect for their language, and will not teach +their children to speak it. + ― G. B. Shaw +% +The Fifth Rule: You have taken yourself too seriously. +% +The IQ of the group is the lowest IQ of a member of the group divided +by the number of people in the group. +% +The Idea is like grass. It craves light, likes crowds, thrives on +cross-breeding, grows better for being stepped on. + ― Ursula K. LeGuin, "The Dispossessed" +% +The Kennedy Constant: Don't get mad ― get even. +% +The Law of Software Envelopment (at MIT): Every program at MIT attempts to +expand until it can read mail. Those programs which cannot expand are +replaced by ones which can. +% +The Law, in its majestic equality, forbids the rich, as well as the poor, +to sleep under the bridges, to beg in the streets, and to steal bread. + ― Anatole France +% +The Official MBA Handbook on business cards: Avoid overly pretentious job +titles such as "Lord of the Realm, Defender of the Faith, Emperor of India" +or "Director of Corporate Planning." +% +The real art of conversation is not only to say the right thing at the +right place but to leave unsaid the wrong thing at the tempting moment. + ― Dorothy Nevill +% +The Roman Rule: The one who says it cannot be done should never interrupt the +one who is doing it. +% +The Swartzberg Test: The validity of a science is its ability to predict. +% +The Third Law of Photography: If you did manage to get any good shots, they +will be ruined when someone inadvertently opens the darkroom door and all +of the dark leaks out. +% +The Tree of Learning bears the noblest fruit, but noble fruit tastes bad. +% +The USA is so enormous, and so numerous are its schools, colleges and +religious seminaries, many devoted to special religious beliefs ranging +from the unorthodox to the dotty, that we can hardly wonder at its +yielding a more bounteous harvest of gobbledygook than the rest of the +world put together. + ― Sir Peter Medawar +% +The United States has entered an anti-intellectual phase in its history, +perhaps most clearly seen in our virtually thought-free political life. + ― David Baltimore +% +The [Ford Foundation] is a large body of money completely surrounded by +people who want some. + ― Dwight MacDonald +% +The advertisement is the most truthful part of a newspaper + ― Thomas Jefferson +% +The ambassador and the general were briefing me on the―the vast majority +of Iraqis want to live in a peaceful, free world. And we will find these +people and we will bring them to justice. + ― George W. Bush, Washington, D.C.; October 28, 2003 +% +The angels wanna wear my red shoes. +% +The applause of a single human being is of great consequence. + ― Samuel Johnson +% +The attacker must vanquish; the defender need only survive. +% +The attention span of a computer is as long as its electrical cord. +% +The author should gaze at Noah, and ... learn, as they did in the Ark, to crowd +a great deal of matter into a very small compass. + ― Sydney, Smith, Edinburgh Review +% +The average woman would rather have beauty than brains, because the +average man can see better than he can think. +% +The best cure for anger is delay. + ― Seneca +% +The best prophet of the future is the past. +% +The best that we can do is to be kindly and helpful toward our friends and +fellow passengers who are clinging to the same speck of dirt while we are +drifting side by side to our common doom. + ― Clarence Darrow +% +The best thing about a boolean is even if you are wrong, you are only off +by a bit. + ― Anonymous +% +The best thing about growing older is that it takes such a long time. +% +The best way to break a bad habit is to drop it. + ― Anonymous +% +The better part of maturity is knowing your goals. + ― Arnold Glasow +% +The biggest difference between time and space is that you can't reuse +time. + ― Merrick Furst +% +The chain that can be yanked is not the cosmic chain. + ― Cal Keegan +% +The chicken that clucks the loudest is the one most likely to show up +at the steam fitters' picnic. +% +The chief barrier to happiness is envy. + ― Frank Tyger +% +The chief cause of problems is solutions. + ― Eric Sevareid, CBS Evening News, December 29, 1970 +% +The city of the dead antedates the city of the living. + ― Lewis Mumford +% +The clothes have no emperor. + ― C. A. Hoare, about Ada. +% +The complexity of software is an essential property, not an accidental one. +Hence, descriptions of a software entity that abstract away its complexity +often abstract away its essence. + ― Fred Brooks, Jr. +% +The computing field is always in need of new cliches. + ― Alan Perlis +% +The connection between the language in which we think/program and the problems +and solutions we can imagine is very close. For this reason restricting +language features with the intent of eliminating programmer errors is at best +dangerous. + ― Bjarne Stroustrup in "The C++ Programming Language" +% +The correct way to punctuate a sentence that starts: "Of course it is +none of my business, but ―" is to place a period after the word "but." +Don't use excessive force in supplying such a moron with a period. +Cutting his throat is only a momentary pleasure and is bound to get you +talked about. + ― Lazarus Long, "Time Enough for Love" +% +The cost of living hasn't affected its popularity. +% +The cost of living is going up, and the chance of living is going +down. +% +The country needs and, unless I mistake its temper, the country demands bold, +persistent experimentation. + ― Franklin Delano Roosevelt +% +The cow is nothing but a machine which makes grass fit for us people to eat. + ― John McNulty +% +The day will come when the mystical generation of Jesus, by the Supreme Being +as his Father, in the womb of a virgin will be classified with the fable of +the generation of Minerva in the brain of Jupiter. But we may hope that the +dawn of reason and freedom of thought in these United States will do away with +this artificial scaffolding and restore to us the primitive and genuine +doctrines of this most venerated Reformer of human errors. + ― Thomas Jefferson +% +The day-to-day travails of the IBM programmer are so amusing to most of +us who are fortunate enough never to have been one ― like watching +Charlie Chaplin trying to cook a shoe. +% +The debate rages on: Is PL/I Bachtrian or Dromedary? +% +The decision didn't have to be logical, it was unanimous. +% +The devil finds work for idle circuits to do. +% +The difference between Genius and Stupidity is that Genius has limits. +% +The difference between science and the fuzzy subjects is that science +requires reasoning while those other subjects merely require scholarship. + ― Robert Heinlein +% +The difference between sympathy and empathy is three letters: "yes". + ― P. Taylor +% +The divinity of Jesus is made a convenient cover for absurdity. Nowhere +in the Gospels do we find a precept for Creeds, Confessions, Oaths, +Doctrines, and whole carloads of other foolish trumpery that we find in +Christianity. + ― John Adams +% +The earth is like a tiny grain of sand, only much, much heavier. +% +The end move in politics is always to pick up a gun. + ― Buckminster Fuller +% +The end of labor is to gain leisure. +% +The end of the world will occur at 3:00 p.m., this Friday, with +symposium to follow. +% +The envious man grows lean at the success of his neighbor. + ― Horace +% +The evolution of the human race will not be accomplished in the ten thousand +years of tame animals, but in the million years of wild animals, because man +is and will always be a wild animal. + ― Charles Galton Darwin +% +The existence of god implies a violation of causality. +% +The fact that it works is immaterial. + ― L. Ogborn +% +The famous politician was trying to save both his faces. +% +The fancy is indeed no other than a mode of memory emancipated from the order +of space and time. + ― Samuel Taylor Coleridge +% +The fault lies not with our technologies but with our systems. + ― Roger Levian +% +The finest eloquence is that which gets things done. +% +The first 90% of a project takes 90% of the time. The last 10% of a project +takes 90% of the time. +% +The first and great commandment is: Do not let them scare you. + ― Elmer Davis +% +The first duty of a revolutionary is to get away with it. + ― Abbie Hoffman +% +The first rule of intelligent tinkering is to save all the parts. + ― Paul Erlich +% +The flow chart is a most thoroughly oversold piece of program documentation. + ― Frederick Brooks, Jr., The Mythical Man Month +% +The flush toilet is the basis of Western civilization. + ― Alan Coult +% +The following statement is true. +The previous statement is false. +% +The fountain code has been tightened slightly so you can no longer dip objects +into a fountain or drink from one while you are floating in mid-air due to +levitation. + +Teleporting to hell via a teleportation trap will no longer occur if the +character does not have fire resistance. + + ― README file from the NetHack game +% +The fourth law of thermodynamics: +The perversity of the universe tends towards a maximum. +% +The fundamentalists, by "knowing" the answers before they start [examining +evolution], and then forcing nature into the straitjacket of their +discredited preconceptions, lie outside the domain of science―-or of any +honest intellectual inquiry. + ― Stephen Jay Gould, Bully for Brontosaurus (1990) +% +The future isn't what it used to be. (It never was.) +% +The generation of random numbers is too important to be left to chance. +% +The gentlemen looked one another over with microscopic carelessness. +% +The goal of Computer Science is to build something that will last at +least until we've finished building it. +% +The goal of science is to build better mousetraps. +The goal of nature is to build better mice. +% +The government of the United States is not in any sense founded +on the Christian Religion. + ― George Washington (The Treaty of Tripoli) +% +The greatest of faults is to be conscious of none. +% +The greatest warriors are the ones who fight for peace. + ― Holly Near +% +The hand that rocks the cradle can also cradle a rock. + ― Feminist saying, circa 1968-1972 +% +The hardest thing to open is a closed mind. + ― Leo Burnett +% +The heart has no rainbows when the eye has no tears. +% +The hell with the Prime Directive: let's kill something. +% +The herd instinct among economists makes sheep look like independent +thinkers. +% +The human animal differs from the lesser primates in his passion for +lists of "Ten Best". + ― H. Allen Smith +% +The human mind ordinarily operates at only ten percent of its capacity +― the rest is overhead for the operating system. +% +The human mind treats a new idea the way the body treats a strange +protein ― it rejects it. + ― P. Medawar +% +The hypothesis: Amid a wash of paper, a small number of documents become the +critical pivots around which every project's management revolves. These are the +manager's chief personal tools. + ― Frederick P. Brooks, Jr., The Mythical Man Month +% +The idea that Bill Gates has appeared like a knight in shining armour to +lead all customers out of a mire of technological chaos neatly ignores the +fact that it was he who, by peddling second-rate technology, led them into +it in the first place. + ― attributed to Douglas Adams +% +The ideal is impossible. The idea of the ideal is essential. + ― P. Taylor +% +The inability to benefit from feedback appears to be the primary cause of +pseudoscience. Pseudoscientists retain their beliefs and ignore or distort +contradictory evidence rather than modify or reject a flawed theory. Because +of their strong biases, they seem to lack the self-correcting mechanisms +scientists must employ in their work. + ― Thomas L. Creed, "The Skeptical Inquirer," Summer 1987 +% +The individual choice of garnishment of a burger can be an important +point to the consumer in this day when individualism is an increasingly +important thing to people. + ― Donald N. Smith, president of Burger King +% +The Internet? Is that thing still around? + ― Homer Simpson +% +The Internet is the most powerful stupidity amplifier ever invented. It’s +like television without the television part. + - James “Kibo” Perry +% +The lame in the path outstrip the swift who wander from it. + ― Francis Bacon +% +The last thing one knows in constructing a work is what to put first. + ― Blaise Pascal +% +The life of a repo man is always intense. +% +The life of money-making is one undertaken under compulsion, and wealth is +evidently not the good we are seeking, for it is merely useful for the sake +of something else. + ― Aristotle +% +The life which is unexamined is not worth living. +% +The light at the end of the tunnel is the headlight of an approaching +train. +% +The lion and the calf shall lie down together but the calf won't get +much sleep. + ― Woody Allen +% +The longer I am out of office, the more infallible I appear to myself. + ― Henry Kissinger +% +The love of money is only one among many. + ― Alfred Marshall +% +The luck that is ordained for you will be coveted by others. +% +The main thing is the play itself. I swear that greed for money has nothing +to do with it, although heaven knows I am sorely in need of money. + ― Feodor Dostoyevsky +% +The man scarce lives who is not more credulous than he ought to be. ... +The natural disposition is always to believe. It is acquired wisdom and +experience only that teach incredulity, and they very seldom teach it +enough. + ― Adam Smith +% +The man who follows the crowd will usually get no further than the +crowd. The man who walks alone is likely to find himself in places no +one has ever been. + ― Alan Ashley-Pitt +% +The man who makes no mistakes does not usually make anything. +% +The marvels of today's modern technology include the development of a soda +can, when discarded will last forever; and a $20,000 car which, when +properly cared for, will rust out in two or three years. +% +The meek are contesting the will. +% +The meek shall inherit the earth ― they are too weak to refuse. +% +The meek shall inherit the earth, but not its mineral rights. + ― J. Paul Getty +% +The meek shall inherit the earth. The rest of us will go to the stars. +% +The meek will inherit the Earth..... The rest of us will go to the stars. +% +The mistake you make is in trying to figure it out. + ― Tenessee Williams +% +The moon may be smaller than Earth, but it's further away. +% +The more laws and order are made prominent, the more thieves and +robbers there will be. + ― Lao Tsu +% +The more things change, the more they stay insane. +% +The more things change, the more they'll never be the same again. +% +The more we disagree, the more chance there is that at least one of us +is right. +% +The mosquito is the state bird of New Jersey. + ― Andy Warhol +% +The most exciting phrase to hear in science, the one that heralds new +discoveries, is not "Eureka!" (I found it!) but "That's funny ..." + ― Isaac Asimov +% +The most merciful thing in the world ... is the inability of the human mind to +correlate all its contents. + ― H. P. Lovecraft +% +The new Congressmen say they're going to turn the government around. I +hope I don't get run over again. +% +The next six days are dangerous. +% +The nice thing about standards is that there are so many of them to +choose from. + ― Andrew S. Tanenbaum +% +The notion of a "record" is an obsolete remnant of the days of the +80-column card. + ― Dennis M. Ritchie +% +The objective of all dedicated employees should be to thoroughly analyze +all situations, anticipate all problems prior to their occurrence, have +answers for these problems, and move swiftly to solve these problems when +called upon. However, when you are up to your ass in alligators it is +difficult to remind yourself your initial objective was to drain the swamp. +% +The older a man gets, the farther he had to walk to school as a boy. +% +The one charm of marriage is that it makes a life of deception a necessity. + ― Oscar Wilde +% +The one good thing about repeating your mistakes is that you know when +to cringe. +% +The only difference between a rut and a grave is the depth. +% +The only good bug is a dead bug. +But the best bug is the one that wasn't there to begin with. +% +The only possible interpretation of any research whatever in the +`social sciences' is: some do, some don't. + ― Ernest Rutherford +% +The only problem with being a man of leisure is that you can never stop +and take a rest. +% +The only thing necessary for the triumph of evil is for good men to do nothing. + ― Edmund Burke +% +The only things worth learning are the things you learn after you know it all. + ― Harry S Truman +% +The only thing to do with good advice is pass it on. It is never any +use to oneself. + ― Oscar Wilde +% +The only way to amuse some people is to slip and fall on an icy pavement. +% +The only way to get rid of a temptation is to yield to it. + ― Oscar Wilde +% +The only way to learn a new programming language is by writing programs in it. + ― Brian Kernighan +% +The opossum is a very sophisticated animal. It doesn't even get up +until 5 or 6 pm. +% +The opposite of a correct statement is a false statement. But the opposite of a +profound truth may well be another profound truth. + ― Niels Bohr +% +The opposite of a profound truth may well be another profound truth. + ― Bohr +% +The optimum committee has no members. + ― Norman Augustine +% +The past always looks better than it was. It's only pleasant because +it isn't here. + ― Finley Peter Dunne (Mr. Dooley) +% +The personal computer market is about the same size as the total potato +chip market. Next year it will be about half the size of the pet food +market and is fast approaching the total worldwide sales of pantyhose + ― James Finke, President, Commodore Int'l Ltd. (1982) +% +The pitcher wound up and he flang the ball at the batter. The batter +swang and missed. The pitcher flang the ball again and this time the +batter connected. He hit a high fly right to the center fielder. The +center fielder was all set to catch the ball, but at the last minute +his eyes were blound by the sun and he dropped it. + ― Dizzy Dean +% +The plural of spouse is spice. +% +The police are not there to create disorder. The police are there to +preserve disorder. + ― The late Richard J. Daly, Mayor of the city of Chicago +% +The power to destroy a planet is insignificant when compared to the power of +the Force. + ― Darth Vader +% +The price of greatness is responsibility. + ― Winston Churchill +% +The price one pays for pursuing any profession, or calling, is an intimate +knowledge of its ugly side. + ― James Baldwin +% +The primary purpose of the DATA statement is to give names to +constants; instead of referring to pi as 3.141592653589793 at every +appearance, the variable PI can be given that value with a DATA +statement and used instead of the longer form of the constant. This +also simplifies modifying the program, should the value of pi change. + ― FORTRAN manual for Xerox Computers +% +The probability of someone watching you is directly proportional to the +stupidity of your action. +% +The problem with any unwritten law is that you don't know where to go +to erase it. + ― Glaser and Way +% +The problem with being best man at a wedding is that you never get a +chance to prove it. +% +The problem with people who have no vices is that generally you can be +pretty sure they're going to have some pretty annoying virtues. + ― Elizabeth Taylor +% +The problem with the gene pool is that there is no lifeguard. +% +The program is absolutely right; therefore the computer must be wrong. +% +The programmer, like the poet, works only slightly removed from pure thought- +stuff. He builds his castles in the air, from air, creating by exertion of the +imagination. Few media of creation are so flexible, so easy to polish and +rework, so readily capable of realizing grand conceptual structures. + ― Frederick Brooks, Jr., The Mythical Man Month +% +The purpose of most meetings seems to be to get as much human meat as possible +into one room. + ― James Iry, via Twitter +% +The race is not always to the swift, nor the battle to the strong ― +but that's the way to bet. + ― Damon Runyon +% +The rain it raineth on the just + And also on the unjust fella, +But chiefly on the just, because + The unjust steals the just's umbrella. +% +The reason ESP, for example, is not considered a viable topic in +contemporary psychology is simply that its investigation has not proven +fruitful...After more than 70 years of study, there still does not exist +one example of an ESP phenomenon that is replicable under controlled +conditions. This simple but basic scientific criterion has not been met +despite dozens of studies conducted over many decades... It is for this +reason alone that the topic is now of little interest to psychology... In +short, there is no demonstrated phenomenon that needs explanation. + ― Keith E. Stanovich, "How to Think Straight About Psychology", + pp. 160-161 +% +The reason computer chips are so small is computers don't eat much. +% +The reason we struggle with insecurity is because we compare our +behind-the-scenes with everyone else's highlight reel. + ― Steve Furtick +% +The reasonable man adapts himself to the world; the unreasonable one +persists in trying to adapt the world to himself. Therefore all +progress depends on the unreasonable man. + ― George Bernard Shaw +% +The revolution will not be televised. +% +The reward of a thing well done is to have done it. + ― Emerson +% +The right half of the brain controls the left half of the body. +This means that only left handed people are in their right mind. +% +The right half of the brain controls the left half of the body. +This means that only left-handed people are in their right minds. +% +The road to to success is always under construction. + ― Florian Bruckner +% +The secret cement of any organization is trust. + ― Donald E. Walker +% +The shell must break before the bird can fly. + ― Alfred, Lord Tennyson +% +The shortest distance between two points is under construction. + ― Noelie Altito +% +The silly question is the first intimation of some totally new development. +% +The so-called "desktop metaphor" of today's workstations is instead an +"airplane-seat" metaphor. Anyone who has shuffled a lap full of papers while +seated between two portly passengers will recognize the difference ― one can +see only a very few things at once. + ― Fred Brooks, Jr. +% +The solution to a problem changes the problem. + ― J. Martin +% +The sooner all the animals are extinct, the sooner we'll find their money. + ― Ed Bluestone +% +The soul would have no rainbow had the eyes no tears. +% +The steady state of disks is full. + ―Ken Thompson +% +The study of theology, as it stands in the Christian churches, is the study +of nothing; it is founded on nothing; it rests on no principles; it +proceeds by no authority; it has no data; it can demonstrate nothing; and +it admits of no conclusion. + ― Thomas Paine, from The Age of Reason +% +The subject matter of research is no longer nature in itself, but nature +subjected to human questioning . . . + ― Werner Heisenberg +% +The sun was shining on the sea, +Shining with all his might: +He did his very best to make +The billows smooth and bright ― +And this was very odd, because it was +The middle of the night. + ― Lewis Carroll, "Through the Looking Glass" +% +The superfluous is very necessary. + ― Voltaire +% +The sweetest of all sounds is praise. + ― Xenophon +% +The tar pit of software engineering will continue to be sticky for a long time +to come. One can expect the human race to continue attempting systems just +within or just beyond our reach; and software systems are perhaps the most +intricate and complex of man's handiworks. The management of this complex +craft will demand our best use of new languages and systems, our best +adaptation of proven engineering management methods, liberal doses of common +sense, and ... humility to recognize our fallibility and limitations. + ― Frederick Brooks, Jr., The Mythical Man Month +% +The Three Laws of Thermodynamics +The First Law: You can't get anything without working for it. +The Second Law: The most you can accomplish by working is to break even. +The Third Law: You can only break even at absolute zero. +% +The time is right to make new friends. +% +The trouble with a kitten is that +When it grows up, it's always a cat + ― Ogden Nash. +% +The trouble with being poor is that it takes up all your time. +% +The trouble with being punctual is that people think you have nothing +more important to do. +% +The trouble with doing something right the first time is that nobody +appreciates how difficult it was. +% +The trouble with programmers is that you can never tell what a programmer +is doing until it's too late. + ― Seymour Cray +% +The trouble with us in America isn't that the poetry of life has turned to +prose, but that it has turned to advertising copy. + ― Louis Kronenberger +% +The truth is that all those having power ought to be mistrusted. + ― James Madison +% +The truth of a proposition has nothing to do with its credibility. And +vice versa. +% +The typical page layout program is nothing more than an electronic +light table for cutting and pasting documents. +% +The universe is laughing behind your back. +% +The unnatural, that too is natural. + ― Goethe +% +The use of COBOL cripples the mind; its teaching should, therefore, be +regarded as a criminal offense. + ― E. W. Dijkstra (1982) +% +The vigor of civilized societies is preserved by the widespread sense that +high aims are worth-while. Vigorous societies harbor a certain +extravagance of objectives, so that men wander beyond the safe provision of +personal gratifications. All strong interests easily become impersonal, +the love of a good job well done. There is a sense of harmony about such +an accomplishment, the Peace brought by something worth-while. + ― Alfred North Whitehead, 1963, in "The History of Manned Space + Flight" +% +The way to make a small fortune in the stock market is to start with a +large one. +% +The Web is like a dominatrix. Everywhere I turn, I see little buttons +ordering me to Submit. + ― Nytwind +% +The whole earth is in jail and we're plotting this incredible jailbreak. + ― Wavy Gravy +% +The wife you save may be your own. + ― Unofficial slogan of supporters of one of FDR's sons, + a notorious womanizer, during the son's first congressional race +% +The wise shepherd never trusts his flock to a smiling wolf. +% +The world is a fantasy, so let's find out about it. + ― Astrophysicist Dennis Sciama, to Timothy Ferris (quoted in + Ferris's book, "The Mind's Sky") +% +The world is coming to an end. Please log off. +% +[The World Wide Web is] the only thing I know of whose shortened +form―www―takes three times longer to say than what it's short for. + ― attributed to Douglas Adams +% +The world is divided into two kinds of people: those who think the world is +divided into two kinds of people and those who do not. +% +The world is no nursery. + ― Sigmund Freud +% +The world looks as if it has been left in the custody of trolls. + ― Father Robert F. Capon +% +The world will not recognize your talent until you demonstrate it. +% +The world's as ugly as sin, +And almost as delightful + ― Frederick Locker-Lampson +% +The worst form of failure is the failure to try. +% +The years of peak mental activity are undoubtedly between the ages of +four and eighteen. At four we know all the questions, at eighteen all +the answers. +% +Theorem: A cat has nine tails. Proof: No cat has eight tails. A cat has one +tail more than no cat. Therefore, a cat has nine tails. +% +There ain't no such thing as a free lunch. +% +There are 10 types of people who understand binary: The ones who do, and +the ones who don't. +% +There are a lot of lies going around.... and half of them are true. + ― Winston Churchill +% +There are four kinds of homicide: felonious, excusable, justifiable, +and praiseworthy ... + ― Ambrose Bierce, "The Devil's Dictionary" +% +There are no bugs, only unrecognized features. +% +There are no giant crabs in here, Frank. +% +There are no saints, only unrecognized villains. +% +There are only two kinds of programming languages: those people always +bitch about and those nobody uses. + ― Bjarne Stroustrup +% +There are some micro-organisms that exhibit characteristics of both +plants and animals. When exposed to light they undergo photosynthesis; +and when the lights go out, they turn into animals. But then again, +don't we all? +% +There are 10 kinds of people. Those who know binary and those who don't. +% +There are things that are so serious that you can only joke about them. + ― Heisenberg +% +There are three kinds of lies: Lies, Damn Lies, and Statistics. + ― Disraeli +% +There are three ways to get something done: do it yourself, hire +someone, or forbid your kids to do it. +% +There are two novels that can change a bookish fourteen-year old's life: +"The Lord of the Rings" and "Atlas Shrugged". One is a childish fantasy +that often engenders a lifelong obsession with its unbelievable heroes, +leading to an emotionally stunted, socially crippled adulthood, unable to +deal with the real world. The other, of course, involves orcs. + ― John Rogers (kfmonkey.blogspot.com/2009/03/ephemera-2009-7.html) +% +There are two ways of constructing a software design. One way is to make +it so simple that there are obviously no deficiencies and the other is to +make it so complicated that there are no obvious deficiencies. + ― Charles Anthony Richard Hoare +% +There are two ways to write error-free programs. Only the third one works. +% +There are two ways to be fooled. One is to believe what isn't true. The other +is to refuse to accept what is true. + ― Søren Kierkegaard +% +There are very few personal problems that cannot be solved through a +suitable application of high explosives. +% +There can be no offense where none is taken. + ― Japanese proverb +% +There cannot be a crisis next week. My schedule is already full. + ― Henry Kissinger +% +There has been an alarming increase in the number of things you know nothing +about. +% +There is a bear following you around. +% +There is a decivilizing bug somewhere at work; unconsciously persons of +stern worth, by not resenting and resisting the small indignities of the +times, are preparing themselves for the eventual acceptance of what they +themselves know they don't want. + ― attributed to E.B. White +% +There is a great discovery still to be made in Literature: that of +paying literary men by the quantity they do NOT write. +% +There is no "Complete Idiot's Guide to Creationism," but perhaps one is not +needed. + ― Andrei Codrescu, on NPR Aug. 25, 1999 +% +There is no excuse for the use of the word "synergies" on any project where +common sense and straight talking are the norm. + ― Paul Robinson , in a post to the + FreeBSD-Hackers mailing list, 17 July, 2003 +% +There is some sort of perverse pleasure in knowing that it's basically +impossible to send a piece of hate mail through the Internet without its +being touched by a gay program. That's kind of funny. + ― Eric Allman +% +There is one safeguard known generally to the wise, which is an advantage +and security to all, but especially to democracies as against despots. What +is it? Distrust. + ― Demosthenes: Philippic 2, sect. 24. +% +There is a time in the tides of men, +Which, taken at its flood, leads on to success. +On the other hand, don't count on it. + ― T. K. Lawson +% +There is danger in delaying, good fortune in acting. +% +There is no choice before us. Either we must Succeed in providing the +rational coordination of impulses and guts, or for centuries civilization +will sink into a mere welter of minor excitements. We must provide a Great +Age or see the collapse of the upward striving of the human race. + ― Alfred North Whitehead +% +There is no heavier burden than a great potential. +% +There is no idea so sacred that it cannot be questioned, analyzed... +and ridiculed. + ― Cal Keegan +% +There is no realizable power that man cannot, in time, fashion the tools to +attain, nor any power so secure that the naked ape will not abuse it. So +it is written in the genetic cards ― only physics and war hold him in +check. And also the wife who wants him home by five, of course. + ― Encyclopadia Apocrypha, 1990 ed. +% +There is no satisfaction in hanging a man who does not object to it + ― G. B. Shaw +% +There is no statute of limitations on stupidity. + ― Randomly produced by a computer program called Markov3. +% +There is no substitute for good manners, except, perhaps, fast reflexes. +% +There is no such thing as not enough time if you are doing what you want to do. +% +There is no such thing as pure pleasure; some anxiety always goes with it. +% +There is no time like the pleasant. +% +There is no time like the present for postponing what you ought to be doing. +% +There is nothing in this world constant but inconstancy. + ― Swift +% +There is nothing so deadly as not to hold up to people the opportunity to +do great and wonderful things, if we wish to stimulate them in an active way. + ― Dr. Harold Urey, Nobel Laureate in chemistry +% +There is only one thing in the world worse than being talked about, and +that is not being talked about. + ― Oscar Wilde +% +There is so much sand in Northern Africa that if it were spread out it +would completely cover the Sahara Desert. +% +There was nothing I hated more than to see a filthy old drunkie, a howling +away at the sons of his father and going blurp blurp in between as if it were +a filthy old orchestra in his stinking rotten guts. I could never stand to +see anyone like that, especially when they were old like this one was. + ― Alex in "Clockwork Orange" +% +There were in this country two very large monopolies. The larger of the +two had the following record: the Vietnam War, Watergate, double- digit +inflation, fuel and energy shortages, bankrupt airlines, and the 8-cent +postcard. The second was responsible for such things as the transistor, +the solar cell, lasers, synthetic crystals, high fidelity stereo recording, +sound motion pictures, radio astronomy, negative feedback, magnetic tape, +magnetic "bubbles", electronic switching systems, microwave radio and TV +relay systems, information theory, the first electrical digital computer, +and the first communications satellite. Guess which one got to tell the +other how to run the telephone business? +% +There will always be survivors. + ― Robert Heinlen +% +There will be big changes for you, but you will be happy. +% +There you go man, +Keep as cool as you can. +It riles them to believe that you perceive the web they weave. +Keep on being free! +% +There's a bug somewhere in your code. +% +There's a fine line between courage and foolishness. Too bad it's not a fence. +% +There's an old proverb that says just about whatever you want it to. +% +There's always someone, somewhere, +with a big nose, who knows +and who trips you up and laughs +when you fall. + ― The Smiths +% +There's at least one fool in every married couple. +% +There's got to be more to life than compile-and-go. +% +There's more than one way to skin a cat: + Way number 15 ― Krazy Glue and a toothbrush. +% +There's more than one way to skin a cat: + Way number 27 ― Use an electric sander. +% +There's more to life than sitting around in the sun in your underwear +playing the clarinet. +% +There's no future in time travel +% +There's no limit to how complicated things can get, on account of one +thing always leading to another. + ― E. B. White +% +There's no place like home. +% +There's no place like $HOME. +% +There's no point in being grown up if you can't be childish sometimes. + ― Dr. Who +% +There's nothing remarkable about it. All one has to do is hit the right +keys at the right time and the instrument plays itself. + ― J. S. Bach +% +There's nothing wrong with America that a good erection wouldn't cure. + ― David Mairowitz +% +There's only one way to have a happy marriage and as soon as I learn +what it is I'll get married again. + ― Clint Eastwood +% +There's so much plastic in this culture that vinyl leopard skin is +becoming an endangered synthetic. + ― Lily Tomlin +% +These patriots don't mince words... Okay, sure, they ARE dangerous, +hopelessly ignorant, inbred, retarded borderline lunatics with an +insatiable lust for the blood of sinners ― but at least they're HONEST +about it. + ― Reverend Ivan Stang, cofounder of the Church of the Subgenius, + about a group known as Free Love Ministries, in his book _High + Weirdness By Mail_ +% +They [preachers] dread the advance of science as witches do the approach +of daylight and scowl on the fatal harbinger announcing the subversions +of the duperies on which they live. + ― Thomas Jefferson +% +They also surf who only stand on waves. +% +They took some of the Van Goghs, most of the jewels, and all of the Chivas! +% +Things are always at their best in the beginning. + ― Pascal +% +Things are more like they are now than they ever were before. + ― Dwight D. Eisenhower +% +Things are more like they used to be than they are now. +% +Things are not as simple as they seems at first. + ― Edward Thorp +% +Things won't get any better, so get used to it. +% +Think honk if you're a telepath. +% +This fortune intentionally not included. +% +This fortune is false. +% +This fortune is inoperative. Please try another. +% +This fortune will self destruct in 5 years. +% +This isn't brain surgery; it's just television. + ― David Letterman +% +This space unintentionally left blank. +% +This was the ultimate form of ostentation among technology freaks ― to have +a system so complete and sophisticated that nothing showed; no machines, +no wires, no controls. + ― Michael Swanwick, "Vacuum Flowers" +% +Thoreau's Law: If you see a man approaching you with the obvious intent of +doing you good, you should run for your life. + ― Attributed to Thoreau by William H. Whyte, Jr., in + The Organization Man (1956) +% +Those of us who believe in the right of any human being to belong to whatever +church he sees fit, and to worship God in his own way, cannot be accused +of prejudice when we do not want to see public education connected with +religious control of the schools, which are paid for by taxpayers' money. + ― Eleanor Roosevelt +% +Those who are quick in deciding are in danger of being mistaken. + ― Sophocles +% +Those who believe in astrology are living in houses with foundations of +Silly Putty. + ― Dennis Rawlins, astronomer +% +Those who believe that they believe in God, but without passion in their +hearts, without anguish in mind, without uncertainty, without doubt, +without an element of despair even in their consolation, believe only in +the God idea, not God Himself. + ― Miguel de Unamuno, Spanish philosopher and writer +% +Those who bite the hand that feeds them usually lick the boot that kicks them. +% +Those who can, do; those who can't, simulate. +% +Those who can't repeat the past are condemned to remember it. + ― Mark O'Donnell +% +Those who do not understand Unix are condemned to reinvent it, poorly. + ― Henry Spencer, University of Toronto Unix hacker +% +Those who educate children well are more to be honored than parents, +for these only gave life, those the art of living well. + ― Aristotle +% +Those who in quarrels interpose, must often wipe a bloody nose. +% +Those who make peaceful revolution impossible will make violent +revolution inevitable. + ― John F. Kennedy +% +Those who talk don't know. Those who don't talk, know. +% +Those who want the Government to regulate matters of the mind and spirit +are like men who are so afraid of being murdered that they commit suicide +to avoid assassination. + ― Harry S Truman +% +Throw out your gold teeth / And see how they roll. +The answer they reveal: / Life is unreal. + ― Steely Dan +% +Time and tide wait for no man. +% +Time flies like an arrow. Fruit flies like a banana. +% +Time is an illusion perpetrated by the manufacturers of space. + ― Graffiti +% +Time is but the stream I go a-fishing in. +% +Time is nature's way of making sure that everything doesn't happen at once. +% +Time wounds all heels. +% +Times are bad. Children no longer obey their parents, and everyone is +writing a book. + ― Cicero +% +Tip the world over on its side and everything loose will land in Los Angeles. + ― Frank Lloyd Wright +% +To be awake is to be alive. + ― Henry David Thoreau, in "Walden Pond" +% +To be intoxicated is to feel sophisticated but not be able to say it. +% +To be is to program. +% +To be overbusy is a witless task. + ― Sophocles +% +To be perfect is to have changed often. + ― J. H. Newman +% +To be sure of hitting the target, shoot first, and call whatever you hit the +target. + ― Ashleigh Brilliant +% +To be wrong all the time is an effort, but some manage it. + ― William Feather +% +To be, or what? + ― Sylvester Stallone +% +To criticize the incompetent is easy; it is more difficult to criticize the +competent. +% +To do easily what is difficult for others is the mark of talent. + ― H. F. Amiel +% +To downgrade the human mind is bad theology. + ― C. K. Chesterton +% +To err is human, to compute divine. Trust your computer but not its programmer. + ― Morris Kingston +% +To err is human, to forgive divine. +% +To follow foolish precedents, and wink +With both our eyes, is easier than to think. + ― William Cowper +% +To invent products out of thin air, you don't ask people what they want ― +after all, who would've told you ten years ago that they needed a CD +player? You ask them what problems they have when they get up in the +morning. + ― Robert Hall, Sr. Vice President, GVO, as quoted in the December, + 1991, issue of Fortune +% +To invent, you need a good imagination and a pile of junk. + ― Thomas Edison +% +To iterate is human, to recurse, divine. +% +To knock a thing down, especially if it is cocked at an arrogant angle, is a +deep delight of the blood. + ― Georges Santayana +% +To know the world one must construct it. + ― Cesare Pavese +% +To laugh at men of sense is the privilege of fools. +% +To program anything that is programmable is obsession. +% +To program is to be. +% +To steal from a thief is not theft. It is merely irony. + ― Zorro, while retrieving money taxed from Californians +% +To steal from one person is theft. To steal from many is taxation. + ― Daiell's Law (a take-off on Felson's Law) +% +To teach is to learn. +% +To those accustomed to the precise, structured methods of conventional +system development, exploratory development techniques may seem messy, +inelegant, and unsatisfying. But it's a question of congruence: precision +and flexibility may be just as disfunctional in novel, uncertain situations +as sloppiness and vacillation are in familiar, well-defined ones. Those +who admire the massive, rigid bone structures of dinosaurs should remember +that jellyfish still enjoy their very secure ecological niche. + ― Beau Sheil, "Power Tools for Programmers" +% +Today is the first day of the rest of your lossage. +% +Today is the last day of your life so far. +% +Too clever is dumb. + ― Ogden Nash +% +Too much of a good thing is WONDERFUL. + ― Mae West +% +Trespassers will be shot. Survivors will be prosecuted. +% +Troglodytism does not necessarily imply a low cultural level. +% +True innovation often comes from the small startup who is lean enough to +launch a market but lacks the heft to own it. + ― Timm Martin +% +Truth has always been found to promote the best interests of mankind. + ― Percy Bysshe Shelley +% +Truthful, adj.: Dumb and illiterate. + ― Ambrose Bierce, "The Devil's Dictionary" +% +Try not to have a good time ... This is supposed to be educational. + ― Charles Schulz +% +Try to be the best of what you are, even if what you are is no good. + ― Ashleigh Brilliant +% +Trying to be happy is like trying to build a machine for which the only +specification is that it should run noiselessly. +% +Turnaucka's Law: The attention span of a computer is only as long as its +electrical cord. +% +Tussman's Law: Nothing is as inevitable as a mistake whose time has come. +% +Two can Live as Cheaply as One for Half as Long. + ― Howard Kandel +% +Two men look out through the same bars; one sees mud, and one the stars. +% +Two percent of zero is almost nothing. +% +UFO's are for real: the Air Force doesn't exist. +% +UFOs are for real. It's the Air Force that doesn't exist. +% +Uncertain fortune is thoroughly mastered by the equity of the calculation. + ― Blaise Pascal +% +Uncle Ed's Rule of Thumb: + Never use your thumb for a rule. You'll either hit it with a + hammer or get a splinter in it. +% +Uncompensated overtime? Just Say No. +% +Under any conditions, anywhere, whatever you are doing, there is some +ordinance under which you can be booked. + ― Robert D. Sprecht (Rand Corp) +% +Under deadline pressure for the next week. If you want something, it +can wait. Unless it's blind screaming paroxysmally hedonistic ... +% +Underlying Principle of Socio-Genetics: + Superiority is recessive. +% +United Nations, New York, December 25. The peace and joy of the +Christmas season was marred by a proclamation of a general strike of +all the military forces of the world. Panic reigns in the hearts of +all the patriots of every persuasion. + +Meanwhile, fears of universal disaster sank to an all-time low over the +world. + ― Isaac Asimov +% +Universe, n.: The problem. +% +University, n.: Like a software house, except the software's free, and it's +usable, and it works, and if it breaks they'll quickly tell you how to fix it. +% +UNIX *is* user friendly. It's just selective about who its friends are. + ― unknown +% +Unless one is a genius, it is best to aim at being intelligible. + ― Anthony Hope +% +Unless you are very rich and very eccentric, you will not enjoy the luxury of +a computer in your own home. + ― Edward Yourdon, 1975. +% +Use GOTOs only to implement a fundamental structure. +% +Use debugging compilers. +% +Use free-form input where possible. +% +Use library functions. +% +Use the Force, Luke. +% +Useful knowledge is a great support for intuition. + ― Charles B. Rogers +% +Users of a tool are willing to meet you halfway; if you do ninety percent +of the job, they will be ecstatic. + ― Software Tools, p.136. +% +VMS isn't an operating system, it's a playpen for DEC system programmers. + ― Herb Blashtfalt +% +Van Roy's Law: An unbreakable toy is useful for breaking other toys. +% +Variables won't. Constants aren't. +% +Velilind's Laws of Experimentation: + 1. If reproducibility may be a problem, conduct the test only + once. + 2. If a straight line fit is required, obtain only two data + points. +% +Very few profundities can be expressed in less than 80 characters. +% +Vests are to suits as seat-belts are to cars. +% +Violence is the last refuge of the incompetent. + ― Salvor Hardin +% +Vique's Law: +A man without religion is like a fish without a bicycle. +% +Virtue is its own punishment. +% +Vital papers will demonstrate their vitality by spontaneously moving +from where you left them to where you can't find them. +% +Vitamin C deficiency is apauling +% +Volcano - a mountain with hiccups. +% +Vote anarchist. +% +Walter, I love you, but sooner or later, you're going to have to face the +fact you're a goddamn moron. + ― The Dude ("The Big Lebowski") +% +War is menstruation envy. +% +Waste not, get your budget cut next year. +% +Wasting time is an important part of living. +% +Watch out for off-by-one errors. +% +We ARE as gods and might as well get good at it. + ― Whole Earth Catalog +% +We all know that no one understands anything that isn't funny. +% +We are all in the gutter, but some of us are looking at the stars. + ― Oscar Wilde +% +We are confronted with insurmountable opportunities. + ― Walt Kelly, "Pogo" +% +We are going to have peace even if we have to fight for it. + ― Dwight D. Eisenhower +% +We are not alone. +% +We are what we pretend to be. + ― Kurt Vonnegut, JR +% +We call our dog Egypt, because in every room he leaves a pyramid. +% +We can defeat gravity. The problem is the paperwork involved. +% +We can't let children think it's okay to dress up like Vikings and go +around hollering. + ― Dogbert, on opera +% +We can't schedule an orgy, it might be construed as fighting + ― Stanley Sutton +% +We cheat the other guy and pass the savings on to you. +% +We don't care. We don't have to. We're the Phone Company. +% +We don't know who discovered water, but we are certain it wasn't a fish. + ― John Culkin +% +We don't want to discourage the innovators and those who take risks because +they're afraid of getting sued by a lawsuit. + ― George W. Bush; Washington, D.C.; June 24, 2004 +% +We few, we happy few, we band of brothers; +For he to-day that sheds his blood with me +Shall be my brother; be he ne'er so vile, +This day shall gentle his condition: +And gentlemen in England now a-bed +Shall think themselves accursed they were not here, +And hold their manhoods cheap whiles any speaks +That fought with us upon Saint Crispin's day. + ― King Henry V, "Henry V", Act IV, Scene 3 +% +We have met the enemy and he is us + ― Walt Kelly (in POGO) +% +We learn from history that we do not learn anything from history. +% +We may not return the affection of those who like us, but we always +respect their good judgement. +% +We must all hang together, or we will surely all hang separately. + ― Benjamin Franklin +% +They that can give up essential liberty to obtain a little temporary safety +deserve neither liberty nor safety. + ― Benjamin Franklin +% +We must remember the First Amendment which protects any shrill jackass +no matter how self-seeking. + ― F. G. Withington +% +We now return you to your regularly scheduled program. +% +We want to create puppets that pull their own strings. + ― Ann Marion +% +We were spanking each other with meat and then suddenly it got weird. + ― Joe Hacket +% +We will have solar energy as soon as the utility companies solve one +technical problem ― how to run a sunbeam through a meter. +% +We work to become, not to acquire. + ― Elbert Hubbard +% +We'll be a great country where the fabrics are made up of groups and +loving centers. + ― George W. Bush, Kalamazoo, Michigan; March 27, 2001 +% +We're fighting for this woman's honor, which is more than she ever did. + ― Rufus T. Firefly, in "Duck Soup" +% +We're here to give you a computer, not a religion. + ― attributed to Bob Pariseau, at the introduction of the Amiga +% +We're the weirdest monkeys ever. + ― Karl Lehenbauer +% +We've sent a man to the moon, and that's 29,000 miles away. The center +of the Earth is only 4,000 miles away. You could drive that in a week, +but for some reason nobody's ever done it. + ― Andy Rooney +% +Wear me as a seal upon your heart, as a seal upon your arm; for love is strong +as death, passion cruel as the grave; it blazes up like blazing fire, fiercer +than any flame. + [Song of Solomon 8:6 (NEB)] +% +Weiler's Law: + Nothing is impossible for the man who doesn't have to do it himself. +% +Weinberg's First Law: Progress is made on alternate Fridays. +% +Weinberg's Second Law: If builders built buildings the way programmers +wrote programs, then the first woodpecker that came along would destroy +civilization. +% +Welcome back, my friends, to the show that never ends! +% +Welcome to the human race, with its wars, disease and brutality. + ― Chrissie Hynde (The Pretenders), "Show Me" +% +Welcome to The Machine. +% +Welcome to the working week. +I know it don't thrill you +I hope it don't kill you. +% +Well, I killed my own grandfather and here I am! Guess there's no paradox +when time travel isn't involved. + ― Andrew Kennedy +% +Well, well, well! Well if it isn't fat stinking billy goat Billy Boy in +poison! How art thou, thou globby bottle of cheap stinking chip oil? Come +and get one in the yarbles, if ya have any yarble, ya eunuch jelly thou! + ― Alex in "Clockwork Orange" +% +Well, you see, it's such a transitional creature. It's a piss-poor +reptile and not very much of a bird. + ― Melvin Konner, from "The Tangled Wing", quoting a zoologist who has + studied the archeopteryx and found it "very much like people" +% +Were there fewer fools, knaves would starve. + ― Anonymous +% +Westheimer's Discovery: A couple of months in the laboratory can frequently +save a couple of hours in the library. +% +Wethern's Law: Assumption is the mother of all screw-ups. +% +What a waste it is to lose one's mind ― or not to have a mind at all. +How true that is. + ― V.P. Dan Quayle, garbling the United Negro College Fund slogan + in an address to the group (from Newsweek, May 22nd, 1989) +% +What are you doing wrong with our bug-free product? +% +What cannot be eaten must be civilized. + ― Peter Taylor +% +What do you call a boomerang that doesn't work? A stick! + ― Bill Kirchenbaum, comedian +% +What does it mean if there is no fortune for you? +% +What garlic is to salad, insanity is to art. +% +What happens when you cut back the jungle? It recedes. +% +What is a magician but a practising theorist? + ― Obi-Wan Kenobi +% +What is mind? No matter. +What is matter? Never mind. + ― Thomas Hewitt Key, 1799-1875 +% +What is the difference between the modern computer and a Turing machine? +It's the same as that between Hillary's ascent of Everest and the +establishment of a Hilton on its peak. +% +What is tolerance? ― it is the consequence of humanity. We are all formed +of frailty and error; let us pardon reciprocally each other's folly ― +that is the first law of nature. + ― Voltaire +% +What is vice today may be virtue tomorrow. +% +What is virtue today may be vice tomorrow. +% +What is worth doing is worth delegating. +% +What is worth doing is worth the trouble of asking somebody to do. +% +What makes the Universe so hard to comprehend is that there's nothing +to compare it with. +% +What publishers are looking for these days isn't radical feminism. It's +corporate feminism ― a brand of feminism designed to sell books and +magazines, three-piece suits, airline tickets, Scotch, cigarettes and, most +important, corporate America's message, which runs: "Yes, women were +discriminated against in the past, but that unfortunate mistake has been +remedied; now every woman can attain wealth, prestige and power by dint of +individual rather than collective effort." + ― Susan Gordon +% +What sane person could live in this world and not be crazy? + ― Ursula K. LeGuin +% +What sin has not been committed in the name of efficiency? +% +What the hell, go ahead and put all your eggs in one basket. +% +What the large print giveth, the small print taketh away. +% +What this calls for is a special blend of psychology and extreme violence. + ― Vyvyan Basterd, "The Young Ones" +% +What this country needs is a good 5 dollar plasma weapon. +% +What this country needs is a good five cent ANYTHING! +% +What this country needs is a good five cent microcomputer. +% +What this country needs is a good five-cent nickel. +% +What use is magic if it can't save a unicorn? + ― Peter S. Beagle, "The Last Unicorn" +% +What we anticipate seldom occurs; what we least expect generally happens. + ― Bengamin Disraeli +% +What we do not understand we do not possess. + ― Goethe +% +What's so funny 'bout peace, love and understanding? +% +What, me worry? +% +What boots it at one gate to make defence, +And at another to let in the foe? + ― John Milton, Samson Agonistes (l. 560) +% +Whatever is not nailed down is mine. What I can pry loose is not nailed down. + ― Collis P. Huntingdon +% +When I said "we", officer, I was referring to myself, the four young +ladies, and, of course, the goat. +% +When I sell liquor, its called bootlegging; when my patrons serve +it on Lake Shore Drive, its called hospitality. + ― Al Capone +% +When I was a boy I was told that anybody could become President. Now +I'm beginning to believe it. + ― Clarence Darrow +% +When I was in my twenties, not shaving for a few days gave me a cool Don +Johnson/Miami Vice look. Now that I'm in my forties, though, it tends to +make me look more like Otis from Mayberry. + ― Tom Gray +% +When I was in school, I cheated on my metaphysics exam: I looked into +the soul of the boy sitting next to me. + ― Woody Allen +% +When you are in it up to your ears, keep your mouth shut. +% +When Yahweh your gods has settled you in the land you're about to occupy, and +driven out many infidels before you...you're to cut them down and exterminate +them. You're to make no compromise with them or show them any mercy. +[Deut. 7:1 (KJV)] +% +When a Banker jumps out of a window, jump after him ― that's where the +money is. + ― Robespierre +% +When a fellow says, "It ain't the money but the principle of the +thing," it's the money. + ― Kim Hubbard +% +When a fly lands on the ceiling, does it do a half roll or a half loop? +% +When a place gets crowded enough to require ID's, social collapse is +not far away. It is time to go elsewhere. The best thing about space +travel is that it made it possible to go elsewhere. + ― Robert Heinlein +% +When a shepherd goes to kill a wolf, and takes his dog along to see the +sport, he should take care to avoid mistakes. The dog has certain +relationships to the wolf the shepherd may have forgotten. + ― Robert Pirsig, "Zen and the Art of Motorcycle Maintenance" +% +When all other means of communication fail, try words. +% +When asked, "If you find so much that is unworthy of reverence in the United +States, then why do you live here?" Mencken replied, "Why do men go to zoos?" +% +When bad men combine, the good must associate; else they will fall one by one, +an unpitied sacrifice in a contemptible struggle. + ― Edmund Burke +% +When choosing between two evils I always like to take the one I've never tried +before. + ― Mae West +% +When does summertime come to Minnesota, you ask? Well, last year, I +think it was a Tuesday. +% +When everything has been seen to work, all integrated, you have four more +months of work to do. + ― C. Portman of ICL Ltd. +% +When in doubt, do what the President does ― guess. +% +When in doubt, lead trump. +% +When in doubt, punt. +% +When in doubt, use brute force. + ― Ken Thompson +% +When love is gone, there's always justice. +And when justice is gone, there's always force. +And when force is gone, there's always Mom. +Hi, Mom! + ― Laurie Anderson +% +When more and more people are thrown out of work, unemployment results. + ― Calvin Coolidge +% +When people thought the earth was flat, they were wrong. When people thought +the earth was spherical, they were wrong. But if you think that thinking the +earth is spherical is just as wrong as thinking the earth is flat, then your +view is wronger than both of them put together. + ― Isaac Asimov, "The Relativity of Wrong", + The Skeptical Inquirer, Vol. 14 No. 1, Fall 1989 +% +When someone says "I want a programming language in which I need only +say what I wish done," give him a lollipop. + ― Alan J. Perlis +% +When the government bureau's remedies do not match your problem, you +modify the problem, not the remedy. +% +When the wind is great, bow before it; when the wind is heavy, yield to it. +% +When two people are under the influence of the most violent, most +insane, most delusive, and most transient of passions, they are +required to swear that they will remain in that excited, abnormal, and +exhausting condition continuously until death do them part. + ― George Bernard Shaw +% +When we are ignorant of the answer to an important question, one way +to proceed is to ask which path of inquiry promises best to facilitate +learning. + ― Timothy Ferris, "The Mind's Sky: Human Intelligence in a + Cosmic Context." +% +When we are planning for posterity, we ought to remember that virtue is +not hereditary. + ― Thomas Paine +% +When we jumped into Sicily, the units became separated, and I couldn't find +anyone. Eventually I stumbled across two colonels, a major, three captains, +two lieutenants, and one rifleman, and we secured the bridge. Never in the +history of war have so few been led by so many. + ― General James Gavin +% +When you are alone you are all your own. + ― Leonardo da Vinci +% +When you are in it up to your ears, keep your mouth shut. +% +When you do not know what you are doing, do it neatly. +% +When you have an efficient government, you have a dictatorship. + ― Harry S Truman +% +When you make your mark in the world, watch out for guys with erasers. + ― The Wall Street Journal +% +Whenever anyone says, "theoretically", they really mean, "not really". + ― Dave Parnas +% +Whenever people agree with me I always feel I must be wrong. + ― Oscar Wilde +% +Where a new invention promises to be useful, it ought to be tried + ― Thomas Jefferson +% +Where humor is concerned there are no standards ― no one can say what +is good or bad, although you can be sure that everyone will. + ― John Kenneth Galbraith +% +Where is it written in the Constitution that you may take children from their +parents, and parents from their children, and compel them to fight the battles +of any war in which the folly or wickedness of government may engage it? + ― Daniel Webster, 1814 +% +Where there's a will, there's an Inheritance Tax. +% +Wherever you go, there you are. + ― Buckaroo Banzai +% +Whether you can hear it or not +The Universe is laughing behind your back + ― National Lampoon, "Deteriorada" +% +While Europe's eye is fix'd on mighty things, +The fate of empires and the fall of kings; +While quacks of State must each produce his plan, +And even children lisp the Rights of Man; +Amid this mighty fuss just let me mention, +The Rights of Woman merit some attention. + ― Robert Burns, Address on "The Rights of Woman", + November 26, 1792 +% +While anyone can admit to themselves they were wrong, the true test is +admission to someone else. +% +While money can't buy happiness, it certainly lets you choose your own +form of misery. +% +While most peoples' opinions change, the conviction of their correctness never +does. +% +While you don't greatly need the outside world, it's still very reassuring to +know that it's still there. +% +Whipit! Whipit good! +% +Whistler's Law: + You never know who is right, but you always know who is in charge. +% +Who has more leisure than a worm? + - Seneca +% +Who is W. O. Baker, and why is he saying those terrible things about me? +% +Who made the world I cannot tell; +'Tis made, and here am I in hell. +My hand, though now my knuckles bleed, +I never soiled with such a deed. + ― A. E. Housman +% +Who needs companionship when you can sit alone in your room and masturbate? +% +Who works achieves and who sows reaps. + ― Arab Proverb +% +Who's on first? +% +Whom computers would destroy, they must first drive mad. +% +Whoso diggeth a pit shall fall therein. + ― Book of Proverbs +% +Why did the Lord give us so much quickness of movement unless it was to +avoid responsibility with? +% +Why does man kill? He kills for food. And not only food: frequently +there must be a beverage. + ― Woody Allen, "Without Feathers" +% +Why does opportunity always knock at the least opportune moment? +% +Why is it that our memory is good enough to retain the least triviality that +happens to us, and yet not good enough to recollect how often we have told +it to the same person? + ― La Rochefoucauld +% +Why is it that there are so many more horses' asses than there are horses? + ― G. Gordon Liddy +% +Why isn't "palindrome" spelled the same way backwards? +% +Why isn't there a special name for the tops of your feet? + ― Lily Tomlin +% +Wiker's Law: Government expands to absorb all available revenue and then some. +% +Wiker's Law: + Government expands to absorb revenue and then some. +% +Will the highways on the Internet become more few? + ― George W. Bush, Concord, NH; January 29, 2000 +% +Williams and Holland's Law: + If enough data is collected, anything may be proven by + statistical methods. +% +Winter is the season in which people try to keep the house as warm as +it was in the summer, when they complained about the heat. +% +With all the fancy scientists in the world, why can't they just once +build a nuclear balm? +% +With clothes the new are best, with friends the old are best. +% +With every passing hour our solar system comes forty-three thousand +miles closer to globular cluster M13 in the constellation Hercules, and +still there are some misfits who continue to insist that there is no +such thing as progress. + ― Ransom K. Ferm +% +With friends like these, who need hallucinations? +% +With great effort, you move the rug aside, revealing a trap door. +% +Without coffee he could not work, or at least he could not have worked in +the way he did. In addition to paper and pens, he took with him everywhere +as an indispensable article of equipment the coffee machine, which was no +less important to him than his table or his white robe. + ― Stefan Zweigs, Biography of Balzac +% +Without ice cream life and fame are meaningless. +% +Words are the voice of the heart. +% +Words must be weighed, not counted. +% +Worst Vegetable of the Year: The brussels sprout. +This is also the worst vegetable of next year. + ― Steve Rubenstein +% +Wozencraft's Law: If you make all of your plans on the assumption that a +particular thing won't happen―it will. +% +Writing code has a place in the human hierarchy worth somewhere above grave +robbing and beneath managing. + ― Gerald Weinberg +% +Writing free verse is like playing tennis with the net down. +% +Writing in C or C++ is like running a chain saw with all the safety guards +removed. + ― Bob Gray +% +Writing programs needs genius to save the last order or the last millisecond. +It is great fun, but it is a young man's game. You start it with great +enthusiasm when you first start programming, but after ten years you get a +bit bored with it, and then you turn to automatic-programming languages and +use them because they enable you to get to the heart of the problem that you +want to do, instead of having to concentrate on the mechanics of getting the +program going as fast as you possibly can, which is really nothing more than +doing a sort of crossword puzzle. + ― Christopher Strachey, 1962 +% +Xerox does it again and again and again and ... +% +Xerox never comes up with anything original. +% +XML is just data with that Internet shit wrapped around it. + ― Joe Romello, by way of Steve Sapovits +% +Yes, but every time I try to see things your way, I get a headache. +% +Yes, but which self do you want to be? +% +Yes, many primitive people still believe this myth...But in today's technical +vastness of the future, we can guess that surely things were much different. + ― The Firesign Theater +% +Yes, we have no bonanzas. +% +Yesterday upon the stair +I met a man who wasn't there. +He wasn't there again today ― +I think he's from the CIA. +% +Yield to Temptation ... it may not pass your way again. + ― Lazarus Long, "Time Enough for Love" +% +Yinkel, n.: A person who combs his hair over his bald spot, hoping no one +will notice. + ― Rich Hall, "Sniglets" +% +You can do more with a kind word and a gun than with just a kind word. + ― Al Capone +% +You can make it illegal, but you can't make it unpopular. +% +You can measure a programmer's perspective by noting his attitude on +the continuing viability of FORTRAN. + ― Alan Perlis +% +You can never get all the facts from just one newspaper, and unless you +have all the facts, you cannot make proper judgements about what is going on. + ― Harry S Truman +% +You can observe a lot just by watching. + ― Yogi Berra +% +You can often profit from being at a loss for words. + ― Frank Tyger +% +You can take all the impact that science considerations have on funding +decisions at NASA, put them in the navel of a flea, and have room left +over for a caraway seed and Tony Calio's heart. + ― F. Allen +% +You can tell how far we have to go, when FORTRAN is the language of +supercomputers. + ― Steven Feiner +% +You can't antagonize and influence at the same time. +% +You can't carve your way to success without cutting remarks. +% +You can't depend on your eyes when your imagination is out of focus. +% +You can't get there from here. +% +You can't have great software without a great team, and most software teams +behave like dysfunctional families. + ― Jim McCarthy +% +You can't judge a book by the way it wears its hair. +% +You can't start worrying about what's going to happen. You get spastic +enough worrying about what's happening now. + ― Lauren Bacall +% +You can't teach self-esteem. Self-esteem arises from attempting challenging +tasks and mastering them. +% +You can't underestimate the power of fear. + ― Tricia Nixon +% +You cannot achieve the impossible without attempting the absurd. +% +You cannot build a reputation on what you are going to do. + ― Henry Ford +% +You cannot propel yourself forward by patting yourself on the back. +% +You cannot succeed by criticizing others. +% +You couldn't even prove the White House staff sane beyond a reasonable doubt. + ― Ed Meese, on the Hinckley verdict +% +You don't have to explain something you never said. + ― Calvin Coolidge +% +You don't have to think too hard when you talk to teachers. + ― J. D. Salinger +% +You know, you really half give me a buzz. + ― Stevie Ray Vaughan, "Honey Bee" (from "Couldn't Stand the Weather") +% +You know why there are so few sophisticated computer terrorists in the United +States? Because your hackers have so much mobility into the establishment. +Here, there is no such mobility. If you have the slightest bit of +intellectual integrity you cannot support the government.... That's why the +best computer minds belong to the opposition. + ― an anonymous member of the outlawed Polish trade union, Solidarity +% +You may call me by my name, Wirth, or by my value, Worth. + ― Nicklaus Wirth +% +You may have heard that a dean is to faculty as a hydrant is to a dog. + ― Alfred Kahn +% +You never know how many friends you have until you rent a house on the beach. +% +You never finish a program, you just stop working on it. +% +You or I must yield up his life to Ahrimanes. I would rather it were you. +I should have no hesitation in sacrificing my own life to spare yours, but +we take stock next week, and it would not be fair on the company. + ― J. Wellington Wells +% +You see but you do not observe. + ― Sir Arthur Conan Doyle, in "The Memoirs of Sherlock Holmes" +% +You should emulate your heros, but don't carry it too far. Especially +if they are dead. +% +You should never wear your best trousers when you go out to fight for +freedom and liberty. + ― Henrick Ibson +% +You're never too old to become younger. + ― Mae West +% +Your attitude determines your attitude. + ― Zig Ziglar, self-improvement doofus +% +Your conscience never stops you from doing anything. It just stops you +from enjoying it. +% +Your mind understands what you have been taught; your heart, what is true. +% +Your mother was a hamster, and your father smelt of elderberries. +% +Your reality is lies and balderdash, and I'm glad to say that I have no grasp +of it. + ― Baron von Munchausen +% +Your true value depends entirely on what you are compared with. +% +Youth is the trustee of posterity. +% +Youth is wasted on the young. + ― George Bernard Shaw +% +Youth is when you blame all your troubles on your parents; maturity is +when you learn that everything is the fault of the younger generation. +% +Zero Defects, n.: The result of shutting down a production line. +% +Zimmerman's Law of Complaints: Nobody notices when things go right. +% +Zounds! I was never so bethumped with words +since I first called my brother's father dad. + ― William Shakespeare, "King John" +% +Zymurgy's Law of Volunteer Labor: + People are always available for work in the past tense. +% +[In the U. S. Army] An officer does not take an oath of loyalty to the +Commander-in-Chief. He takes an oath of loyalty to the Constitution. + ― Sam Donaldson +% +[Leslie Stahl was] a pussy compared to Rather. + ― George H. W. Bush +% +grep me no patterns and I'll tell you no lines. +% +After all, all he did was string together a lot of old, well-known quotations. + ― H. L. Mencken, on Shakespeare +% +All successful newspapers are ceaselessly querulous and bellicose. They +never defend anyone or anything if they can help it; if the job is forced +upon them, they tackle it by denouncing someone or something else. + ― H.L. Mencken, Prejudices, 1919. +% +A man who can laugh, if only at himself, is never really miserable. + ― H.L. Mencken, Minority Report, 1956 +% +College football is a game which would be much more interesting if the +faculty played instead of the students, and even more interesting if the +trustees played. There would be a great increase in broken arms, legs, and +necks, and simultaneously an appreciable diminution in the loss to humanity. + ― H. L. Mencken +% +Conscience is the inner voice which warns us that someone may be looking. + ― H. L. Mencken, "Sententiae," The Vintage Mencken, 1955. +% +Democracy is also a form of worship. It is the worship of Jackals by +Jackasses. + ― H. L. Mencken +% +Democracy is a pathetic belief in the collective wisdom of individual ignorance. + ― H. L. Mencken +% +Every normal man must be tempted at times to spit on his hands, hoist the +black flag, and begin slitting throats. + ― H.L. Mencken +% +Faith may be defined briefly as an illogical belief in the occurrence of the +improbable. + ― H. L. Mencken +% +Explanations exist; they have existed for all time; there is always a +well-known solution to every human problem neat, plausible, and wrong. + ― H. L. Mencken, "The Divine Afflatus" (16 November 1917) +% +Equality before the law is probably forever inattainable. It is a noble +ideal, but it can never be realized, for what men value in this world is +not rights but privileges. + ― H.L. Mencken, Minority Report, 1956 +% +Faith may be defined briefly as an illogical belief in the occurrence of the +improbable. + ― H.L. Mencken, "Prejudices: Third Series", 1922 +% +For one American husband who maintains a chorus girl in Levantine luxury +around the corner, there are hundreds who are as true to their oaths, year +in and year out, as so many convicts in the deathhouse. + ― H.L. Mencken, In Defense of Women, 1922. +% +I believe that religion, generally speaking, has been a curse to mankind―that +its modest and greatly overestimated services on the ethical side have been +more than overborne by the damage it has done to clear and honest thinking. + ― H. L. Mencken, "Forum" (September, 1930) +% +I go on working for the same reason a hen goes on laying eggs. + ― H. L. Mencken +% +Judge: a law student who marks his own examination papers. + ― H.L. Mencken, "Sententiae," The Vintage Mencken, 1955 +% +Love is the triumph of imagination over intelligence. + ― attributed to H. L. Mencken +% +Men have a much better time of it than women. For one thing, they marry +later. For another thing, they die earlier. + ― H.L. Mencken, A Mencken Chrestomathy, 1949. +% +My guess is that well over eighty per cent of the human race goes through +life without ever having a single original thought. That is to say, they +never think anything that has not been thought before, and by thousands. A +society made up of individuals who were all capable of original thought +would probably be unendurable. The pressure of ideas would simply drive it +frantic. + ― H.L. Mencken, Minority Report, 1956 +% +Never let your inferiors do you a favor. It will be extremely costly. + ― H.L. Mencken, "Sententiae," The Vintage Mencken, 1955. +% +No government is ever really in favor of so-called civil rights. It always +tries to whittle them down. They are preserved under all governments, +insofar as they survive at all, by special classes of fanatics, often +highly dubious. + ― H.L. Mencken, Minority Report, 1956 +% +No one ever went broke underestimating the taste of the American public. + ― Attributed to H.L. Mencken. +% +Nowhere in the world is superiority more easily attained, or more eagerly +admitted. The chief business of the nation, as a nation, is the setting up +of heroes, mainly bogus. + ― H.L. Mencken, Prejudices, 1923. +% +Once he had one leg in the White House and the nation trembled under his +roars. Now he is a tinpot pope in the Coca-Cola belt and a brother to the +forlorn pastors who belabor halfwits in galvanized iron tabernacles behind +the railroad yards. + ― H. L. Mencken, writing of William Jennings Bryan, + counsel for the supporters of Tennessee's anti-evolution + law at the Scopes "Monkey Trial" in 1925. +% +Say what you will about the Ten Commandments, you must always come back to +the pleasant fact that there are only ten of them. + ― H. L. Mencken +% +Sin is a dangerous toy in the hands of the virtuous. It should be left to the +congenitally sinful, who know when to play with it and when to let it alone. + ― H. L. Mencken +% +Suppose two-thirds of the members of the national House of Representatives +were dumped into the Washington garbage incinerator tomorrow, what would we +lose to offset our gain of their salaries and the salaries of their parasites? + ― H. L. Mencken, "Prejudices, Fourth Series" (1924) +% +The capacity of human beings to bore one another seems to be vastly greater +than that of any other animal. + ― H. L. Mencken +% +The chief contribution of Protestantism to human thought is its massive proof +that God is a bore. + ― H.L. Mencken, "The Aesthetic Recoil," American Mercury, July, 1931. +% +The great artists of the world are never Puritans, and seldom even +ordinarily respectable. No virtuous man―that is, virtuous in the YMCA +sense―has ever painted a picture worth looking at, or written a symphony +worth hearing, or a book worth reading, and it is highly improbable that +the thing has ever been done by a virtuous woman. + ― H.L. Mencken, Prejudices, 1919. +% +The highfalutin aims of democracy, whether real or imaginary, are always +assumed to be identical with its achievements. This, of course, is sheer +hallucination. Not one of those aims, not even the aim of giving every +adult a vote, has been realized. It has no more made men wise and free than +Christianity has made them good. + ― H.L. Mencken, Minority Report, 1956 +% +The most costly of all follies is to believe passionately in the palpably not +true. It is the chief occupation of mankind. + ― H.L. Mencken, A Mencken Chrestomathy, 1949. +% +The notion that science does not concern itself with first causes ― that +it leaves the field to theology or metaphysics, and confines itself to mere +effects ― this notion has no support in the plain facts. If it could, +science would explain the origin of life on earth at once ― and there is +every reason to believe that it will do so on some not too remote tomorrow. +To argue that gaps in knowledge which will confront the seeker must be +filled, not by patient inquiry, but by intuition or revelation, is simply +to give ignorance a gratuitous and preposterous dignity.... + ― H. L. Mencken, 1930 +% +The one permanent emotion of the inferior man is fear―fear of the unknown, +the complex, the inexplicable. What he wants beyond everything else is safety. + ― H.L. Mencken, Prejudices, 1920. +% +The truth is that Christian theology, like every other theology, is not only +opposed to the scientific spirit; it is also opposed to all other attempts +at rational thinking. Not by accident does Genesis 3 make the father of +knowledge a serpent ― slimy, sneaking and abominable. Since the earliest +days the church as an organization has thrown itself violently against every +effort to liberate the body and mind of man. It has been, at all times and +everywhere, the habitual and incorrigible defender of bad governments, bad +laws, bad social theories, bad institutions. It was, for centuries, an +apologist for slavery, as it was the apologist for the divine right of kings. + ― H. L. Mencken +% +The whole aim of practical politics is to keep the populace alarmed (and hence +clamorous to be led to safety) by menacing it with an endless series of +hobgoblins, all of them imaginary. + ― H. L. Mencken +% +There is, in fact, no reason to believe that any given natural phenomenon, +however marvelous it may seem today, will remain forever inexplicable. +Soon or late the laws governing the production of life itself will be +discovered in the laboratory, and man may set up business as a creator on +his own account. The thing, indeed, is not only conceivable; it is even +highly probable. + ― H. L. Mencken, 1930 +% +To sum up: 1. The cosmos is a gigantic fly-wheel making 10,000 revolutions +a minute. 2. Man is a sick fly taking a dizzy ride on it. 3. Religion is the +theory that the wheel was designed and set spinning to give him the ride. + ― H. L. Mencken, Coda from "Smart Set", 1920 +% +When women kiss it always reminds one of prize-fighters shaking hands. + ― H. L. Mencken, "Sententiae," The Vintage Mencken, 1955. +% +When A annoys or injures B on the pretense of saving or improving X, A is a +scoundrel. + ― H. L. Mencken, "Newspaper Days: 1899-1906" (1941) +% +Whenever you hear a man speak of his love for his country it is a sign that +he expects to be paid for it. + ― H.L. Mencken, "Sententiae," The Vintage Mencken, 1955. +% +From Fronto I learned to observe what envy, and duplicity, and hypocrisy are +in a tyrant, and that generally those among us who are called Patricians are +rather deficient in paternal affection. + ― Marcus Aurelius, "The Meditations", Book I +% +The time of a man's life is as a point; the substance of it ever flowing, the +sense obscure; and the whole composition of the body tending to corruption. + ― Marcus Aurelius, "The Meditations", Book II +% +That [life] which is longest of duration, and that which is shortest, both +come to one effect. + ― Marcus Aurelius, "The Meditations", Book II +% +You must, therefore, hasten, not only because you are every day nearer to +death, but also because your intellect, which enables you to know the true +nature of things and to order all your actions by that knowledge, wastes and +decays daily―or, may fail you before you die. + ― Marcus Aurelius, "The Meditations", Book II +% +Never esteem of anything as profitable, which shell ever constrain thee to +break thy faith, or to lose thy modestroy; to hate any man, to suspect to +curse, to dissemble, to lust after anything, that requireth the secret of +walls or veils. + ― Marcus Aurelius, "The Meditations", Book III +% +He who prefers, before all things, his rational part and spirit... he shall +never lament and exclaim; never sigh; he shall never want either solitude +or company; and, which is chiefest of all, he shall live without either +desire or fear. + ― Marcus Aurelius, "The Meditations", Book III +% +Let no act be done without a purpose, nor otherwise than according to the +perfect principles of art. + ― Marcus Aurelius, "The Meditations", Book IV +% +Take away your opinion, and you then take away the complaint, "I have been +harmed." Take away the complaint, "I have been harmed," and the harm is taken +away. + ― Marcus Aurelius, "The Meditations", Book IV +% +Many grains of frankincense on the same altar: one falls before, another falls +after; but it makes no difference. + ― Marcus Aurelius, "The Meditations", Book IV +% +Do not act as if you were going to live ten thousand years. Death hangs over +you. While you live, while it is in your power, be good. + ― Marcus Aurelius, "The Meditations", Book IV +% +How much trouble he avoids who does not look to see what his neighbour says or +does or thinks, but only to what he does himself, that it may be just and pure. + ― Marcus Aurelius, "The Meditations", Book IV +% +Everything which is in any way beautiful is beautiful in itself, and +terminates in itself, not having praise as part of itself. Neither worse, +then, nor better is a thing made by being praised. + ― Marcus Aurelius, "The Meditations", Book IV +% +The words which were formerly familiar are now antiquated: so also the names +of those who were famed of old, are now in a manner antiquated... For all +things soon pass away and become a mere tale, and complete oblivion soon +buries them. + ― Marcus Aurelius, "The Meditations", Book IV +% +Everything is only for a day, both that which remembers and that which is +remembered. + ― Marcus Aurelius, "The Meditations", Book IV +% +Thou art a little soul bearing about a corpse, as Epictetus used to say. + ― Marcus Aurelius, "The Meditations", Book IV +% +Time is like a river made up of the events which happen, and a violent stream; +for as soon as a thing has been seen, it is carried away, and another comes in +its place, and this will be carried away too. + ― Marcus Aurelius, "The Meditations", Book IV +% +Be like the promontory against which the waves continually break, but it +stands firm and tames the fury of the water around it. + ― Marcus Aurelius, "The Meditations", Book IV +% +How easy it is to repel and to wipe away every impression which is troublesome +or unsuitable, and immediately to be in all tranquility. + ― Marcus Aurelius, "The Meditations", Book V +% +To seek what is impossible is madness: and it is impossible that the bad +should not do something of this kind. + ― Marcus Aurelius, "The Meditations", Book V +% +The best way of avenging yourself is not to become like the wrong-doer. + ― Marcus Aurelius, "The Meditations", Book VI +% +If any man is able to convince me and show me that I do not think or act +right, I will gladly change; for I seek the truth by which no man was ever +injured. But he is injured who abides in his error and ignorance. + ― Marcus Aurelius, "The Meditations", Book VI +% +Let not future things disturb you, for you will come to them, if it shall be +necessary, having with you the same reason which you now use for present +things. + ― Marcus Aurelius, "The Meditations", Book VII +% +Receive wealth or prosperity without arrogance; and be ready to let it go. + ― Marcus Aurelius, "The Meditations", Book VIII +% +He often acts unjustly who does not do a certain thing; not only he who does a +certain thing. + ― Marcus Aurelius, "The Meditations", Book IX +% +It is your duty to leave another man's wrongful act there, where it is. + ― Marcus Aurelius, "The Meditations", Book IX +% +America is a ball of Appalachia with a thin coating of civility. + ― Rich Simons +% +American justice is measured by the amount of money you are willing to risk +to make your point. + ― Rich Simons +% +America has become a tired old whore, selling her institutions like back alley +blowjobs to fat cat businessmen for their pocket change. + ― Rich Simons +% +But in the end I remind myself that people are merely shaved apes, and +pretty much spend their time masturbating and throwing feces. + ― Rich Simons +% +I am waiting for the "Internet Beermeister," so hackers can wage a +"Denial of Cerveza" attack. + ― Rich Simons +% +Money doesn't stretch―if somebody makes a killing, somebody else loses +his shirt. + ― Rich Simons +% +Never work anywhere where you can't find the guy in charge and break his nose. + ― Rich Simons +% +Nothing is more dangerous than a man whose actions are the responsibility +of his deity. + ― Rich Simons +% +Some people hold their noses when used as toilet paper by the shadowy +overlords; some people inhale the heady aroma with gusto. + ― Rich Simons +% +Those who sacrifice liberty for the sake of safety deserve neither, but those +who sacrifice creativity for safety end up with a velvet painting of Elvis. + ― Rich Simons +% +Windows is a manifestation of commerce; Unix is a manifestation of culture. + ― Rich Simons +% +Working in Windows is like baking moose shit pie. Sure, you're baking pies, but +look what's in 'em. + ― Rich Simons +% +I prefer the company of men without ovaries. + ― Rich Simons +% +The American business executive resembles the Ferengi more each day. In another +20 years, there will be dorm rooms full of toothless hillbillies at the Amazon +fulfillment centers and the Walmarts. + ― Rich Simons +% +Be cautious of those who give you advice. That's my advice to you. + ― Steve Mayr +% +If you fail to plan, you plan to fail. Sounds like a plan. + ― Steve Mayr +% +If you take the easy way out, nothing will come easy. + ― Steve Mayr +% +By and large, language is a tool for concealing the truth. + ― George Carlin +% +Here's a bumper sticker I'd like to see: "We are the proud parents of a child +whose self-esteem is sufficient that he doesn't need us promoting his minor +scholastic achievements on the back of our car." + ― George Carlin +% +Honesty may be the best policy, but it's important to remember that apparently, +by elimination, dishonesty is the second-best policy. + ― George Carlin +% +I have as much authority as the Pope, I just don't have as many people who +believe it. + ― George Carlin +% +I'm completely in favor of the separation of Church and State. My idea is that +these two institutions screw us up enough on their own, so both of them +together is certain death. + ― George Carlin +% +I think it's the duty of the comedian to find out where the line is drawn and +cross it deliberately. + ― George Carlin +% +If it's true that our species is alone in the universe, then I'd have to say +the universe aimed rather low and settled for very little. + ― George Carlin +% +If God had intended us not to masturbate, he would've made our arms shorter. + ― George Carlin +% +If this is the best God can do, I'm not impressed. + ― George Carlin +% +Just because your tattoo has Chinese characters in it doesn't make you +Spiritual. It's right above the crack of your butt. And it translates to +"beef with broccoli." The last time you did anything spiritual, you were +praying to God you weren't pregnant. You're not spiritual. + ― George Carlin +% +The very existence of flame-throwers proves that some time, somewhere, someone +said to themselves, "You know, I want to set those people over there on fire, +but I'm just not close enough to get the job done." + ― George Carlin +% +There are nights when the wolves are silent and only the moon howls. + ― George Carlin +% +American justice is measured by the amount of money you are willing to risk +to make your point. + ― Rich Simons +% +America has become a tired old whore, selling her institutions like back alley +blowjobs to fat cat businessmen for their pocket change. + ― Rich Simons +% +But in the end I remind myself that people are merely shaved apes, and +pretty much spend their time masturbating and throwing feces. + ― Rich Simons +% +Anybody who wants religion is welcome to it, as far as I'm concerned ― I +support your right to enjoy it. However, I would appreciate it if you +exhibited more respect for the rights of those people who do not wish to +share your dogma, rapture or necrodestination. + ― Frank Zappa, "The Real Frank Zappa Book" +% +Don't eat yellow snow. + ― Frank Zappa +% +Hey, you know something, people? I'm not black, but there's a whole lot of +times I wish I could say I'm not white. + ― Frank Zappa +% +I never set out to be weird. It was always other people who called me weird. + ― Frank Zappa +% +I think pop music has done more for oral intercourse than anything else +that has ever happened, and vice versa. + ― Frank Zappa +% +If you wind up with a boring, miserable life because you listened to your +mother, your Dad, your priest, to some guy on television, to any of the +people telling you how to do your shit, then you *deserve* it. If you +want to be a schmuck, be a schmuck ― but don't wait around for respect +from other people ― a schmuck is a schmuck. + ― Frank Zappa, "The Real Frank Zappa Book" +% +In the future, etiquette will become more and more important. That doesn't +mean knowing which fork to pick up ― I mean basic consideration for the +rights of other animals (human beings included) and the willingness, +whenever practical, to tolerate the other guy's idiosyncrasies. + ― Frank Zappa, "The Real Frank Zappa Book" +% +Is that a real poncho? I mean, is that a Mexican poncho or a Sears poncho? +Hmmm... No fooling. + ― Frank Zappa, "Camarillo Brillo" +% +Most people wouldn't know music if it came up and bit them on the ass. + ― Frank Zappa +% +Modern Americans behave as if intelligence were some sort of hideous deformity. + ― Frank Zappa +% +Most rock journalism is people who can't write interviewing people who can't +talk for the people who can't read. + ― Frank Zappa +% +My best advice to anyone who wants to raise a happy, mentally healthy child +is: Keep him or her as far away from a church as you can. + ― Frank Zappa +% +Remember, Information is not knowledge; Knowledge is not Wisdom; +Wisdom is not truth; Truth is not beauty; Beauty is not love; +Love is not music; Music is the best. + ― Frank Zappa +% +Remember, there's a big difference between kneeling down and bending over. + ― Frank Zappa +% +Take the Kama Sutra. How many people died from the Kama Sutra as opposed to +the Bible? Who wins? + ― Frank Zappa +% +The bassoon is one of my favorite instruments. It has a medieval aroma, +like the days when everything used to sound like that. Some people crave +baseball...I find this unfathomable, but I can easily understand why a +person could get excited about playing the bassoon. + ― Frank Zappa +% +The Book says BURN and DESTROY repent and redeem and revenge and deploy and +rumble thee forth to the land of the unbelieving scum 'cause they don't go +for what's in the Book and that makes 'em BAD. + ― Frank Zappa +% +The computer can't tell you the emotional story. It can give you the exact +mathematical design, but what's missing is the eyebrows. + ― Frank Zappa +% +The essence of Christianity is told to us in the Garden of Eden history. +The fruit that was forbidden was on the Tree of Knowledge. The subtext is, +"All the suffering you have is because you wanted to find out what was +going on. You could be in the Garden of Eden if you had just kept your +fucking mouth shut and hadn't asked any questions." + ― Frank Zappa +% +There is more stupidity than hydrogen in the universe, and it has a longer +shelf life. + ― Frank Zappa +% +There is no such thing as a dirty word. Nor is there a word so powerful, +that it's going to send the listener to the lake of fire upon hearing it. + ― Frank Zappa +% +Our brains have just one scale, and we resize our experiences to fit. + ― Randall Munroe, xkcd +% +There's no such thing as bad language. I don't believe that any more. That's +ridiculous. They call it a "debasing of the language?" No! We are adults. +These are the words that WE use, to express frustration, rage, anger―in +order that we don't pick up a tire iron and beat the shit out of someone. + ― Lewis Black +% +I don't know if you noticed, but our two-party system is a bowl of shit +looking in the mirror at itself. + ― Lewis Black +% +There is a big difference between the Old Testament and the New Testament, +and that is, the New Testament God is kind of a great guy (He is!), especially +when you compare him to the Old Testament God, who is a prick. + ― Lewis Black +% +The reason you should go to Las Vegas is because, for only the second time, +the second time, ever, they have rebuilt Sodom and Gomorrah. It's back!! +And you have the opportunity to see it before it turns to salt. And you +wanna get out there before the Christian Right finds out what we're up to +and shits all over it. + ― Lewis Black +% +[The Weather Channel] is the most watched cable channel in America. I'll +repeat that. It is the most watched cable channel in America. They were +worried about the terrorists immobilizing us, and a portion of our +countrymen watch weather. 'Kay, you don't get any more immobile than +that... unless you're in a goddamn coma. That means you're saying, "I'd go +to the window, but it's too far." If you want to know what the weather is +you go to a window and stick your hand out and if you want to know what the +temperature is you drive by a bank. + ― Lewis Black +% +There's no such thing as soy milk. It's soy juice. But they couldn't sell +soy juice, so they called it soy milk. Because anytime you say soy juice, +you actually... start to gag. + ― Lewis Black +% +You don't want another Enron? Here's the law: If you have a company, and it +can't explain, in one sentence... what it does... it's illegal! + ― Lewis Black +% +The one thing I think we learned this year is that the Democrats and the +Republicans are completely worthless. + ― Lewis Black +% +If mzero doesn't need to be a single, unambiguous value, then the algebra +of monads would seem to be a bit hinky. + ― A tweet from @djspiewak (Daniel J. Spiewak) +% +A monad is just a monoid in the category of endofunctors, what's the problem? + ― Saunders Mac Lane, filtered through James Iry +% +Real knowledge is to know the extent of one's ignorance. + ― Confucius +% +Rotten wood cannot be carved. + ― Confucius (Analects, Book 5, Chapter 9) +% +Men's natures are alike. It is their habits that carry them far apart. + ― Confucius +% +Our greatest glory is not in never falling, but in getting up every time we do. + ― Confucius +% +It does not matter how slowly you go so long as you do not stop. + ― Confucius +% +We like to think we spend most of our time power-typing. "I'm being productive, +I'm writing programs!" But, we don't. We spend most of our time looking into +the abyss, saying, "My God, what have I done?" + ― Douglas Crockford, during his keynote at YUIConf 2011 +% +"That hardly ever happens" is another way of saying, "It happens". + ― Douglas Crockford, during his keynote at YUIConf 2011 +% +I used to think everyone should learn programming. When I first starting +programming...I thought, "Wow, this is such an amazing way to organize +information! Everybody should learn to do this!" I don't think that any more. I +think there has to be something seriously wrong with you, in order to do this +work. A normal person, once they've looked into the abyss, will say, "I'm done. +This is stupid. I'm going to go to something else." But not us, 'cause there's +something really wrong with us. + ― Douglas Crockford, during his keynote at YUIConf 2011 +% +Confusion must be avoided. Confusion is the enemy. Confusion is what causes +bugs and security mishaps and all the other things that make us miserable. + ― Douglas Crockford, during his keynote at YUIConf 2011 +% +Write [code] in a way that clearly communicates your intent. + ― Douglas Crockford, during his keynote at YUIConf 2011 +% +Geriatric Relativity: The observation that time goes faster the older you get. + ― Brian M. Clapper +% +Critical thinking is the antidote to gullibility and credulity, which explains +why politicians aren't fond of critical thinking. + ― Brian M. Clapper +% +There's a certain freedom in being so tired that you just can't possibly do +another thing. + ― Brian M. Clapper +% +The president of the United States has claimed, on more than one occasion, to +be in dialogue with God. If he said that he was talking to God through his +hairdryer, this would precipitate a national emergency. I fail to see how the +addition of a hairdryer makes the claim more ridiculous or offensive. + ― Sam Harris, Letter to a Christian Nation +% +Man is manifestly not the measure of all things. This universe is shot through +with mystery. The very fact of its being, and of our own, is a mystery +absolute, and the only miracle worthy of the name. + ― Sam Harris, "The End of Faith" +% +What is so unnerving about the candidacy of Sarah Palin is the degree to which +she representsand her supporters celebratethe joyful marriage of confidence +and ignorance . . . Ask yourself: how has "elitism" become a bad word in +American politics? There is simply no other walk of life in which extraordinary +talent and rigorous training are denigrated. We want elite pilots to fly our +planes, elite troops to undertake our most critical missions, elite athletes to +represent us in competition and elite scientists to devote the most productive +years of their lives to curing our diseases. And yet, when it comes time to +vest people with even greater responsibilities, we consider it a virtue to shun +any and all standards of excellence. When it comes to choosing the people whose +thoughts and actions will decide the fates of millions, then we suddenly want +someone just like us, someone fit to have a beer with, someone down-to-earthin +fact, almost anyone, provided that he or she doesn't seem too intelligent or +well educated. + ― Sam Harris +% +Unreason is now ascendant in the United Statesin our schools, in our courts, +and in each branch of the federal government. + ― Sam Harris, "The Politics of Ignorance" (2005) +% +The point at which we fully acquire our humanity, and our capacity to suffer, +remains an open question, but anyone who would dogmatically insist that these +traits must arise coincident with the moment of conception has nothing to +contribute, apart from his ignorance, to this debate. + ― Sam Harris +% +Water is two parts hydrogen and one part oxygen. This seems as value-free an +utterance as human beings ever make. But what do we do when someone doubts the +truth of this proposition? Ok, all we can do is appeal to scientific values. +The value of understanding the world. The value of evidence. The value of +logical consistency. What if someone says, “Well, that’s not how I choose to +think about water. Ok, what can we say to such a person? Ok, all we can do is +appeal to scientific values. And if he doesn’t share those values, the +conversation is over. Ok, if someone doesn’t value evidence, what evidence are +you going to provide to prove that they should value it? If someone doesn’t +value logic, what logical argument could you provide to show the importance of +logic? + ― Sam Harris, during a Notre Dame debate with William Lane Craig +% +I love living in the future. ― Bill Cheswick +% +Sendmail(8) proved that if you polish a turd long enough, you may eventually +end up with a shiny coprolite. + ― Bill Cheswick +% +Salad is what food eats. ― Bill Cheswick +% +Angels we have heard on High/Tell us to go out and Buy. + ― Tom Lehrer +% +The Army has carried the American ... ideal to its logical conclusion. +Not only do they prohibit discrimination on the grounds of race, creed +and color, but also on ability. + ― Tom Lehrer +% +If, after hearing my songs, just one human being is inspired to say something +nasty to a friend, or perhaps to strike a loved one, it will all have been +worth the while. + ― Tom Lehrer +% +I'm not tempted to write a song about George W. Bush. I couldn't figure out +what sort of song I would write. That's the problem: I don't want to satirise +George Bush and his puppeteers, I want to vaporize them. + ― Tom Lehrer (2003) +% +I basically like "comments," though they can seem a little jarring: spit- +flecked rants that are appended to a product that at least tries for a measure +of objectivity and dignity. It's as though when you order a sirloin steak, it +comes with a side of maggots. + ― Gene Weingarten, Pulitzer Prize-winning Washington Post columnist +% +I disagree with those who suggest that we permanently close down the U.S. mail +on the grounds that it can kill you. That is sheer hysteria. I think we should +permanently close down the U.S. mail on the grounds that it has been making us +sick for quite a while. + ― Gene Weingarten, Pulitzer Prize-winning Washington Post columnist +% +Anyone who is capable of getting themselves made President should on no +account be allowed to do the job. + ― Douglas Adams, "The Hitchhiker's Guide to the Galaxy" +% +Bypasses are devices that allow some people to dash from point A to point B +very fast while other people dash from point B to point A very fast. People +living at point C, being a point directly in between, are often given to wonder +what's so great about point A that so many people from point B are so keen to +get there and what's so great about point B that so many people from point A +are so keen to get THERE. They often wish that people would just once and for +all work out where the hell they wanted to be. + ― Douglas Adams, "The Hitchhiker's Guide to the Galaxy" +% +Far out in the uncharted backwaters of the unfashionable end of the Western +Spiral arm of the Galaxy lies a small unregarded yellow sun. Orbiting this at a +distance of roughly ninety-eight million miles is an utterly insignificant +little blue-green planet whose ape-descended life forms are so amazingly +primitive that they still think digital watches are a pretty neat idea ... + ― Douglas Adams, "The Hitchhiker's Guide to the Galaxy" +% +Men were real men, women were real women, and small, furry creatures from Alpha +Centauri were REAL small, furry creatures from Alpha Centauri. Spirits were +brave, men boldly split infinitives that no man had split before. Thus was the +Empire forged. + ― "The Hitchhiker's Guide to the Galaxy", Douglas Adams +% +Space is big. You just won't believe how vastly, hugely, mind- bogglingly big +it is. I mean, you may think it's a long way down the road to the chemist's, +but that's just peanuts to space. + ― "The Hitchhiker's Guide to the Galaxy" +% +The word "spine" is, of course, an anagram of "penis". This is true in almost +fifty percent of the languages of the Galaxy, and many people have attempted to +explain why. Usually these explanations get bogged down in silly puns about +"standing erect". + ― Douglas Adams, "The Hitchhiker's Guide to the Galaxy" +% +There is a theory which states that if ever anyone discovers exactly what the +Universe is for and why it is here, it will instantly disappear and be replaced +by something even more bizarre and inexplicable. There is another theory which +states that this has already happened. + ― Douglas Adams, "The Hitchhiker's Guide to the Galaxy" +% +With a rubber duck, one's never alone. + ― "The Hitchhiker's Guide to the Galaxy" +% +Inspiration usually comes during work, rather than before it. + ― Madeleine L'Engle +% +That's the way things come clear. All of a sudden. And then you realize how +obvious they've been all along. + ― Madeleine L'Engle +% +When we were children, we used to think that when we were grown-up we would no +longer be vulnerable. But to grow up is to accept vulnerability... To be alive +is to be vulnerable. + ― Madeleine L'Engle +% +Because you're not what I would have you be, I blind myself to who, in truth, +you are. + ― Madeleine L'Engle +% +A good photograph is knowing where to stand. + ― Ansel Adams +% +A photograph is usually looked at - seldom looked into. + ― Ansel Adams +% +A true photograph need not be explained, nor can it be contained in words. + ― Ansel Adams +% +Dodging and burning are steps to take care of mistakes God made in +establishing tonal relationships. + ― Ansel Adams +% +In wisdom gathered over time I have found that every experience is a form of +exploration. + ― Ansel Adams +% +These people live again in print as intensely as when their images were +captured on old dry plates of sixty years ago... I am walking in their alleys, +standing in their rooms and sheds and workshops, looking in and out of their +windows. Any they in turn seem to be aware of me. + ― Ansel Adams +% +When I'm ready to make a photograph, I think I quite obviously see in my minds +eye something that is not literally there in the true meaning of the word. I'm +interested in something which is built up from within, rather than just +extracted from without. + ― Ansel Adams +When in doubt, tell the truth. + ― Mark Twain +% +A banker is a fellow who lends you his umbrella when the sun is shining +and wants it back the minute it begins to rain. + ― Mark Twain +% +A classic is something that everybody wants to have read and nobody +wants to read. + ― Mark Twain +% +[He was] a solemn, unsmiling, sanctimonious old iceberg who looked like he +was waiting for a vacancy in the Trinity. + ― Mark Twain +% +Clothes make the man. Naked people have little or no influence on society. + ― Mark Twain +% +Don't go around saying the world owes you a living. The world owes you +nothing. It was here first. + ― Mark Twain +% +God made the Idiot for practice, and then He made the School Board. + ― Mark Twain +% +I must have a prodigious quantity of mind; it takes me as much as a +week sometimes to make it up. + ― Mark Twain, "The Innocents Abroad" +% +I was gratified to be able to answer promptly, and I did. I said I +didn't know. + ― Mark Twain +% +If you pick up a starving dog and make him prosperous, he will not bite +you. This is the principal difference between a dog and a man. + ― Mark Twain +% +It is by the fortune of God that, in this country, we have three benefits: +freedom of speech, freedom of thought, and the wisdom never to use either. + ― Mark Twain +% +It is the difference of opinion that makes horse races. + ― Mark Twain +% +It usually takes me more than three weeks to prepare a good impromptu speech. + ― Mark Twain +% +Man is the only animal that blushes ― or needs to. + ― Mark Twain +% +My father was an amazing man. The older I got, the smarter he got. + ― Mark Twain +% +The human race has one really effective weapon, and that is laughter. + ― Mark Twain +% +It could probably be shown, by facts and figures, that there is no distinctly +native criminal class except Congress. + ― Mark Twain +% +There is no sadder sight than a young pessimist. + ― Mark Twain +% +There is something fascinating about science. One gets such wholesale +returns of conjecture out of such a trifling investment of fact. + ― Mark Twain +% +They spell it "da Vinci" and pronounce it "da Vinchy". Foreigners always spell +better than they pronounce. + ― Mark Twain +% +Under certain circumstances, profanity provides a relief denied even to prayer. + ― Mark Twain +% +Wagner's music is better than it sounds. + ― Mark Twain +% +When I was younger, I could remember anything, whether it had happened or not; +but my faculties are decaying now and soon I shall be so I cannot remember any +but the things that never happened. It is sad to go to pieces like this but we +all have to do it. + ― Mark Twain +% +Whenever the literary German dives into a sentence, that is the last you +are going to see of him until he emerges on the other side of the Atlantic +with his verb in his mouth. + ― Mark Twain in "A Connecticut Yankee in King Arthur's Court" +% +Whenever you find that you are on the side of the majority, it is time +to reform. + ― Mark Twain in "A Connecticut Yankee in King Arthur's Court" +% +Why is it that we rejoice at a birth and grieve at a funeral? It is +because we are not the person involved. + ― Mark Twain +% +He is now rising from affluence to poverty. + ― Mark Twain +% +A person with a new idea is a crank until the idea succeeds. + ― Mark Twain +% +A man is never more truthful than when he acknowledges himself a liar. + ― Mark Twain +% +Against the assault of laughter nothing can stand. + ― Mark Twain +% +But who prays for Satan? Who, in eighteen centuries, has had the common +humanity to pray for the one sinner that needed it most? + ― Mark Twain +% +Civilization is the limitless multiplication of unnecessary necessities. + ― Mark Twain +% +Drag your thoughts away from your troubles... by the ears, by the heels, or any +other way you can manage it. + ― Mark Twain +% +I can live for two months on a good compliment. + ― Mark Twain +% +If the world comes to an end, I want to be in Cincinnati. Everything comes +there ten years later. + ― Mark Twain +% +Martyrdom covers a multitude of sins. + ― Mark Twain +% +Patriot: the person who can holler the loudest without knowing what he is +hollering about. + ― Mark Twain +% +Prosperity is the best protector of principle. + ― Mark Twain +% +Suppose you were an idiot, and suppose you were a member of Congress. But I +repeat myself. + ― Mark Twain +% +The rule is perfect: in all matters of opinion our adversaries are insane. + ― Mark Twain +% +There are basically two types of people. People who accomplish things, and +people who claim to have accomplished things. The first group is less crowded. + ― Mark Twain +% +To be good is noble; but to show others how to be good is nobler and no +trouble. + ― Mark Twain +% +It could probably be shown by facts and figures that there is no distinctly +native American criminal class except Congress. + ― Mark Twain +% +To succeed in life, you need two things: ignorance and confidence. + ― Mark Twain +% +Truth is mighty and will prevail. There is nothing wrong with this, except that +it ain't so. + ― Mark Twain +% +We have the best government that money can buy. + ― Mark Twain +% +When angry, count to four; when very angry, swear. + ― Mark Twain +% +When people do not respect us we are sharply offended; yet in his private heart +no man much respects himself. + ― Mark Twain +% +When we remember we are all mad, the mysteries disappear and life stands +explained. + ― Mark Twain +% +Whenever you find yourself on the side of the majority, it is time to pause and +reflect. + ― Mark Twain +% +Wit is the sudden marriage of ideas which before their union were not perceived +to have any relation. + ― Mark Twain +% +[Silvio Berlusconi] is so thoroughly corrupt, every time he smiles, an +angel gets gonorrhea. + ― Dylan Moran +% +[Adulthood] feels like ... walking around in a desert, with a bag over +your head, bumping into people who rob you as they bore you. + ― Dylan Moran +% +Tequila isn't even a drink. It's just a way of getting the police round, +without using the phone. + ― Dylan Moran +% +I basically think I'm what would've happened if James Dean had lived, +and discovered carbohydrates and orthopedic shoes. + ― Dylan Moran +% +When did ignorance become a point of view? + ― Dilbert (Scott Adams) +% +There's no kill switch on awesome. + ― Dilbert (Scott Adams) +% +You want a toe? I can get you a toe, believe me. There are ways, Dude. You +don't wanna know about it, believe me. + ― Walter to The Dude ("The Big Lebowski") +% +Hey, careful, man, there's a beverage here! + ― The Dude ("The Big Lebowski") +% +"The Dude abides." I don't know about you but I take comfort in that. It's good +knowin' he's out there. The Dude. Takin' 'er easy for all us sinners. Shoosh. I +sure hope he makes the finals. + ― The Stranger ("The Big Lebowski") +% +We’ve bought into the idea that education is about training and +"success", defined monetarily, rather than learning to think critically +and to challenge. We should not forget that the true purpose of education +is to make minds, not careers. A culture that does not grasp the vital +interplay between morality and power, which mistakes management techniques +for wisdom, which fails to understand that the measure of a civilization +is its compassion, not its speed or ability to consume, condemns itself +to death. + ― Chris Hedges, "Empire of Illusion: The End of Literacy and the + Triumph of Spectacle" +% +Inverted totalitarianism, unlike classical totalitarianism, does not +revolve around a demagogue or charismatic leader. It finds expression in +the anonymity of the Corporate State. It purports to cherish democracy, +patriotism, and the Constitution while manipulating internal levers. + ― Chris Hedges, "Empire of Illusion: The End of Literacy and the + Triumph of Spectacle" +% +Washington has become our Versailles. We are ruled, entertained, +and informed by courtiers―and the media has evolved into a class of +courtiers. The Democrats, like the Republicans, are mostly courtiers. Our +pundits and experts, at least those with prominent public platforms, +are courtiers. We are captivated by the hollow stagecraft of political +theater as we are ruthlessly stripped of power. It is smoke and mirrors, +tricks and con games, and the purpose behind it is deception. + ― Chris Hedges, "Empire of Illusion: The End of Literacy and the + Triumph of Spectacle" +% +The split in America, rather than simply economic, is between those who +embrace reason, who function in the real world of cause and effect, and those +who, numbed by isolation and despair, now seek meaning in a mythical world +of intuition, a world that is no longer reality-based, a world of magic. + ― Chris Hedges, American Fascists: The Christian Right and the War + On America +% +Hope has a cost. Hope is not comfortable or easy. Hope requires personal +risk. It is not about the right attitude. Hope is not about peace of +mind. Hope is action. Hope is doing something. The more futile, the more +useless, the more irrelevant and incomprehensible an act of rebellion is, +the vaster and more potent hope becomes. Hope never makes sense. Hope is +weak, unorganized and absurd. Hope, which is always nonviolent, exposes in +its powerlessness, the lies, fraud and coercion employed by the state. Hope +knows that an injustice visited on our neighbor is an injustice visited on +all of us. Hope posits that people are drawn to the good by the good. This +is the secret of hope's power. Hope demands for others what we demand for +ourselves. Hope does not separate us from them. Hope sees in our enemy +our own face. + ― Chris Hedges +% +Racism towards Muslims is as evil as anti-Semitism, but try to express +this simple truth on a partisan Palestinian or Israeli website. + ― Chris Hedges, Death of the Liberal Class +% +A society without the means to detect lies and theft soon squanders its +liberty and freedom. + ― Chris Hedges +% +Really, the comforting side in most conspiracy theory arguments is the +one claiming that anyone who's in power has any plan at all. + ― xkcd #1081 (mouseover text) +% +A person who is nice to you, but rude to a waiter, is not a nice person. +(This is very important. Pay attention. It never fails.) + ― Dave Barry +% +Meetings are an addictive, highly self-indulgent activity that corporations +and other large organizations habitually engage in only because they cannot +actually masturbate. + ― Dave Barry +% +Styling mousse, which is gunk that looks like shaving cream ... was invented +by a French hair professional whom, if you met him, you would want to punch +directly in the mouth. + ― Dave Barry +% +There are two kinds of solar-heat systems: "passive" systems collect the +sunlight that hits your home, and "active" systems collect the sunlight +that hits your neighbors' homes, too. + ― Dave Barry, "Postpetroleum Guzzler" +% +There is more money being spent on breast implants and Viagra than on +Alzheimer's research. This means that by 2030, there should be a large +elderly population with perky boobs and huge erections and absolutely no +recollection of what to do with them. + ― Dave Barry +% +It is inhumane, in my opinion, to force people who have a genuine medical +need for coffee to wait in line behind people who apparently view it as +some kind of recreational activity. + ― Dave Barry +% +No matter what happens, somebody will find a way to take it too seriously. + ― Dave Barry +% +Although golf was originally restricted to wealthy, overweight Protestants, +today it's open to anybody who owns hideous clothing. + ― Dave Barry +% +People who want to share their religious views with you almost never want +you to share yours with them. + ― Dave Barry +% +It is a miracle that curiosity survives formal education. + ― Albert Einstein +% +Imagination is more important than knowledge. + ― Albert Einstein +% +If A equals success, then the formula is: + A= X + Y + Z +X is work. Y is play. Z is keep your mouth shut. + ― Albert Einstein +% +Great spirits have always found violent opposition from mediocrities. The +latter cannot understand it when a man does not thoughtlessly submit to +hereditary prejudices but honestly and courageously uses his intelligence. + ― Albert Einstein +% +The tyranny of the ignoramuses is insurmountable and assured for all time. + ― Albert Einstein +% +We can't solve problems by using the same kind of thinking we used when we +created them. + ― Albert Einstein +% +Man usually avoids attributing cleverness to somebody else, unless it is an +enemy. + ― A. Einstein +% +My religion consists of a humble admiration of the illimitable superior +spirit who reveals himself in the slight details we are able to perceive +with our frail and feeble mind. + ― Albert Einstein +% +Never do anything against conscience even if the state demands it. + ― Albert Einstein, as quoted by Virgil Henshaw in + "Albert Einstein: Philosopher Scientist" (1949) +% +The further the spiritual evolution of mankind advances, the more certain it +seems to me that the path to genuine religiosity does not lie through the +fear of life, and the fear of death, and blind faith, but through striving +after rational knowledge. + ― Albert Einstein +% +The hardest thing in the world to understand is the income tax. + ― Albert Einstein +% +The important thing is not to stop questioning. Curiosity has its own reason +for existing. + ― Albert Einstein +% +The most incomprehensible thing about the world is that it is comprehensible. + ― Albert Einstein +% +The only real valuable thing is intuition. + ― Albert Einstein +% +God may be subtle, but He isn't plain mean. + ― Albert Einstein +% +God does not care about our mathematical difficulties. He integrates +empirically. + ― Albert Einstein +% +Dear Posterity, If you have not become more just, more peaceful, and generally +more rational than we are (or were) ― why then, the Devil take you. + ― Albert Einstein, message for a time capsule +% +Common sense is the collection of prejudices acquired by age eighteen. + ― Albert Einstein +% +As far as the laws of mathematics refer to reality, they are not +certain; and as far as they are certain, they do not refer to reality. + ― Albert Einstein +% +Anyone who has never made a mistake has never tried anything new. + ― Albert Einstein +% +An autocratic system of coercion, in my opinion, soon degenerates. For +force always attracts men of low morality, and I believe it to be an +invariable rule that tyrants of genius are succeeded by scoundrels. + ― Albert Einstein, The World As I See It (1931) +% +"If I had only known, I would have been a locksmith." + ― Albert Einstein +% +"I know not with what weapons World War III will be fought, but +World War IV will be fought with sticks and stones." + ― Albert Einstein +% +A man should look for what is, and not for what he thinks should be. + ― Albert Einstein +% +All that is valuable in human society depends upon the opportunity +for development accorded the individual. + ― Albert Einstein +% +An empty stomach is not a good political adviser. + ― Albert Einstein +% +Any intelligent fool can make things bigger and more complex... It takes a +touch of genius - and a lot of courage to move in the opposite direction. + ― Albert Einstein +% +As far as I'm concerned, I prefer silent vice to ostentatious virtue. + ― Albert Einstein +% +Concern for man and his fate must always form the chief interest of all +technical endeavors. Never forget this in the midst of your diagrams and +equations. + ― Albert Einstein +% +Do not worry about your difficulties in Mathematics. I can assure you mine +are still greater. + ― Albert Einstein +% +Education is what remains after one has forgotten what one has learned in +school. + ― Albert Einstein +% +Everything that can be counted does not necessarily count; everything that +counts cannot necessarily be counted. + ― Albert Einstein +% +Great spirits have always encountered violent opposition from mediocre +minds. + ― Albert Einstein +% +He who joyfully marches to music in rank and file has already earned my +contempt. He has been given a large brain by mistake, since for him the +spinal cord would suffice. + ― Albert Einstein +% +I live in that solitude which is painful in youth, but delicious in the +years of maturity. + ― Albert Einstein +% +If you can't explain it simply, you don't understand it well enough. + ― Albert Einstein +% +People think my friend George is weird because he wears sideburns...behind his +ears. I think he's weird because he wears false teeth...with braces on them. + ― Steven Wright +% +I came home the other night and tried to open the door with my car keys...and +the building started up. So I took it out for a drive. A cop pulled me over +for speeding. He asked me where I live. I said, "Here." + ― Steven Wright +% +I was playing poker the other night... with Tarot cards. I got a full house +and 4 people died. + ― Steven Wright +% +My brother sent me a postcard the other day with this big satellite photo of +the entire earth on it. On the back it said: "Wish you were here". + ― Steven Wright +% +You can't have everything. Where would you put it? + ― Steven Wright +% +You know that feeling when you're leaning back on a stool and it starts to tip +over? Well, that's how I feel all the time. + ― Steven Wright +% +I'm making wine at home, but I make it out of raisins, so it'll be aged +automatically. + ― Steven Wright +% +Babies don't need a vacation, but I still see 'em at the beach. Pisses me off. + ― Steven Wright +% +Sponges grow in the ocean. That kills me. I wonder how much deeper the ocean +would be, if that didn't happen. + ― Steven Wright +% +It doesn't matter what temperature a room is, it's always room temperature. + ― Steven Wright +% +I remember the day the candle shop burned down. Everyone just stood around +and sang, "Happy birthday." + ― Steven Wright +% +If you shoot a mime, should you use a silencer? + ― Steven Wright +% +Once I stayed in a hotel where the pool was on the 23rd floor. I couldn't +believe how deep it was. + ― Steven Wright +% +There's a fine line between fishing and standing on the shore looking like +an idiot. + ― Steven Wright +% +What's another word for, "thesaurus?" + ― Steven Wright +% +Whenever I think about the past, it's just bring back so many memories. + ― Steven Wright +% +Once I was walking through the woods, and I saw a rabbit standing in front +of a candle, making shadows of people on a tree. I said, "Don't be so +sarcastic." + ― Steven Wright +% +I'm a peripheral visionary. I can see into the future, but just way off to +the side. + ― Steven Wright +% +It's hard for me to buy clothes, 'cause I'm not my size. + ― Steven Wright +% +Small keyboards make for big mistakes. + ― Joe Gunn +% +The last refuge of the insomniac is a sense of superiority to the sleeping world. + ― Leonard Cohen +% +Poetry is just the evidence of life. If your life is burning well, poetry is +just the ash. + ― Leonard Cohen +% +Children show scars like medals. Lovers use them as a secrets to reveal. A +scar is what happens when the word is made flesh. + ― Leonard Cohen, The Favorite Game +% +I don't consider myself a pessimist. I think of a pessimist as someone who +is waiting for it to rain. And I feel soaked to the skin.” + ― Leonard Cohen +% +The older I get, the surer I am that I’m not running the show. + ― Leonard Cohen +% +Deprivation is the mother of poetry. + ― Leonard Cohen, The Favorite Game +% +We are so lightly here. It is in love that we are made. In love we disappear. + ― Leonard Cohen +% +There is a crack, a crack in everything. That's how the light gets in. + ― Leonard Cohen, Selected Poems, 1956-1968 +% +This is a broken world, and we live with broken hearts and broken lives, +but still that is no alibi for anything. On the contrary, you have to stand +up and say, "Hallelujah," under those circumstances. + ― Leonard Cohen +% +A human is a system for converting dust billions of years ago into dust +billions of years from now via a roundabout process which involves checking +email a lot. + Randall Munroe (xkcd #1173) +% +Among the many invectives I invent when people piss me off, this is my +current favorite: 'Fuck yer own throat, you piss-dribbling monkey dick!' +I'm hoping it catches on with you folks. + Jon Miller, a.k.a., Doc Spender +% +"Well, vegans, as you know, don't have eggs, meat, dairy, or senses of humor." + Peter Sagal, on NPR's "Wait, Wait, Don't Tell Me" (21 Sep, 2013) +% +An ounce of perversion is worth a pound of pure. + ― Dr. Mark Crislip +% +Holy water is often contaminated with bacteria and, as a result, I +hypothesize that Pasteur went to Hell, since, if he'd gone to heaven, all +the water would be clean." + Dr. Mark Crislip +% +It is ignoring the nuances of a complicated topic to grind your axe that +annoys me. + Dr. Mark Crislip +% +Anybody who thinks that homeopathy is appropriate therapy for anything but +thirst is ... unfit to care for patients. + Dr. Mark Crislip +% +That woman speaks eight languages and can't say "no" in any of them. + ― Dorothy Parker +% +There's a hell of a distance between wise-cracking and wit. Wit has truth in +it; wise-cracking is simply calisthenics with words. + ― Dorothy Parker +% +If you have any young friends who aspire to become writers, the second +greatest favor you can do them is to present them with copies of The +Elements of Style. The first greatest, of course, is to shoot them now, +while they’re happy. + ― Dorothy Parker +% +I require three things in a man: he must be handsome, ruthless, and stupid. + ― Dorothy Parker +% +That would be a good thing for them to cut on my tombstone: Wherever she +went, including here, it was against her better judgment. + ― Dorothy Parker +% +The cure for boredom is curiosity. There is no cure for curiosity. + ― Dorothy Parker +% +Beauty is only skin deep, but ugly goes clean to the bone. + ― Dorothy Parker +% +This is not a novel to be tossed aside lightly. It should be thrown with +great force. + ― Dorothy Parker, on Ayn Rand's "Atlas Shrugged" +% +It's not the tragedies that kill us; it's the messes. + ― Dorothy Parker +% +All those writers who write about their own childhood! Gentle God, if I +wrote about mine you wouldn't sit in the same room with me. + ― Dorothy Parker +% +Sometimes, a grand adventure begins when you lick the evil. Joe Pizzirusso +% +Angels are very good at math. That's why they call them arc-angels. + ― Steven Novella (The Skeptics Guide to the Universe) +% +"Girls are complicated. The instruction manual that comes with girls is 800 +pages, with chapters 14, 19, 26 and 32 missing, and it's badly translated, +hard to figure out." + Huge Laurie, on raising a girl +% +There is no material safety data sheet for astatine. If there were, it would +just be the word "NO" scrawled over and over in charred blood. + Randall Munroe, "What If?" +% +Telling a child that everyone dies is the hardest thing about being a party +clown. + James Ferace +% +Last night, I told my kid that the night light only makes it easier for +the monsters to find her. + James Ferace \ No newline at end of file diff --git a/derp.ico b/derp.ico deleted file mode 100644 index bf7cde6107c7f01be02d4d4809fdf15e4db7b4c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 370070 zcmeI536K<3n#Zg9zPqdGrlGs*LL3eS6;K?}0r3Ej1_4177(q}F@c{3WOFbk4CGV937Uq^hMb>#8h z_x=9gd-*c+mB-`t)Ogz3JnApxSykonoTp!f`rrRteg13p*`bH-e}ACIb491eGi_S` z`_a=qp1>53XTyg5@9Vst6R+2=^H(NZT}_nax-y2^y_%=&w4swDjBR`FdhSz4D(h%w)qqa^&%X7M&w zCv0EotCPBkT~hze9vSh~oheOk-!P@yShsRWU1UEEGY*#Edz&Tv#qGwn!S`>H@MpJ0 z_7nd6b}>Hta+`#e1%IbW|T52NuH;+@% zTqi@nyHFaA?v?r@yTy0u3DS7#!Nz(G#~&ntH?EVOhnFU7XKrsUdtbOp0&i`UhN;1f z>zdn?_fnJ}ayOl4LdvEoGxN*_Be$s!V*l`Wx#U^uVK2)ymD0L$x-_45pj39$XT9$V zU!$}vIb53OjuLOfKu%V&%X%MrU7cHXyA^u(DycnaNY>j{e`A=@9);eyQYwcwWW8N{ z`69=E|5~X#q*FXq6F%J4aRrDcQ&Q;N$}kpjdlF5T$iv;@SV-ZcSEk2lJfW_|4pYK zk+6N;kt2=mTF#l8@SRy!-@2K`I$D3`XXdhX#k7paO?Uj~{^KKAwrrWCJN}k`+a(V? z@PJr7eq~pS)E_fS8fT1))MNJ7Kb6B@QvTg_b>uU%Zsv08zy3&Od~mmPKXQ?=PUyXB zq)GJ!>!%zbRo!h_*WdJmnSadv4|W-R>(Z?9Uqw^3X!BHhW6EeAKm6G((*4WT()Gg? zS=sQPUtrWf>G3PP#<7g!>GnXq55Bohg0Eg6b%zg2dVHe}1Q68iO(5_oQ@RF7!2yw6niH_LCFL+@E@TlvlL3q3wb`BV2_V*S5PI<8gMeV2^2 zWF6~|H<&bHT0sAYe!D?}uU}}{^cYYv_%V-Z=dzIe+gWaNUv`vV=ilM?o{-dfes+2! z*5)zoTFF6%`Ct9h zm&SG#6%~0ef8C_8v@D)tSlg=UF|j`D58LIs|9nA$+s;<^F)fMt&SW6ja>c*zFt+Qw zX})y*V0mP_;MT8X?kDZZS`CnFf)28!Blch}M?|tTyNIBatoDeCe@3NC4KIq-CF!Fi4j$`~^ zjPmclMz8xt@#PQeYrV>PpInr-{N{Q=8_RF*Go$}i`Hgks%CGM~()~7Xy}Dknt_S!0 zhjHxv`|P^qSn2)cX^HmJQ=~f77FpN0XDZ3q zjoz0&H|)2Kk=I7w{0FJ85f8fDNsg`ek*XgU*!k`3`k$)&rkPvF;bK zEP@~OeOl9$ZBS<3r{z)4ye9dh@0y|SuY87&@Bs|K01UtY48Q;kzyJ)moPo+=t)lOx z(bn_esnUJ_Olh8D@4W@l=N=6wj+5X!8>Q#x^Q7k&r%U$(Crj#yhK($72O&D8w|rL6zxvK8WW zspY>y)H(VX`K-U5@1i=`lGf^v48`ymUA98J*7a{ZA(*y|x(>_^&F4!Wh&(R{=VQHs!y20 z_NnI!o?j+8)&C4@b2$~#59yAj=i#FMgXdpAi_mq?vKZ6ndFgzuzti(!#cvn-IJbGZ zy6%lVe$S4z8IK>@duz<`J2xID4d3b=wEmOj$Kk(Nlkxbzwf%EyMQ`ta?S_ooCG%_i zeV~n}9+q)Gfjt{+scUrk&DYdFbNtuudq(!{+b2&y{d6P_xx`=R_Rqffow2XJzCL4L zPKf^<|NXl049&amzH7PufBC<^8v9zfu>aomV%J|kuQTM@*%9m9x*$Q1OaAb%eE*Mc z%Z8607d?lbw%`X_64pzm_vp`b{O|eWTgJYoes8U@pU!QIV)mowOB;H}d}+UOrnFx% z!?3pVr$zj3>Na1?`0=0U@)zQ@|H(6?c6{lKe-)z6(Z}#VxxnT1SMe{Q@z3bk6ymkP zzfJYm&mc!zMQh^R>G63aM*k{bh2FkQ<)gXMyzt1pSVvsG&9?q}uKlWEs(w)xGk2zX zPRIZFd}XKi+hcRp-2I1U%%d^&*W>Z(S?)rPe`j0&=6RzB>Za@X=xI{j+Z?H%SN+~W zG_QL6F1PwGD#`lmIkBVb7kKHs^z~PBSNP5!AMsB-_vZV=_&c-y9yNbYw14zGxW3hg zxTpT=S-IircP{jAUFc=k-DgVM*<+14#PvMlsjT6ckg<*4PTSC%rc2{g>vIR0e8n&8 zCLa)Uyv|KirSbS+%JP}zZd-A5%yvV+b8^P{;q`tqUCS7L_wgASiLZm*?>je775@_p zQkcr=kDQj%_)pWELnWl<{EgTL*A2W@pZg!3Bc)LP;Xhs#qupp7>(_dW*8cIYZQ@sL zB=s*o|M`l4t(y0`W6S)M<~#o|X+3jv(e>Z5>{}_zsLS8Jc8chE2<*-~?2l&xU;qYS z00v+H24DaNU;qYS00v;dQ4FYX@#j_#=y@VG=*oMe=7~_hg`VV(F(j8i@1~f50ek=h zFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE z00S@p126ysFaQHE00S@p12B-lK<&Z3#=P2kZf(@e z!_KT9@xL?1FQ$(|>Nk;$c^bS;3be^g{=pX%~fAmlPKY9N@Ro*O@&z+qA>kjKOeh*UrCZrYfU3hHD z^P_T!bEKlR^{?qKR2b1)ii5DTGP*u=Cc1> zw`ra;DQ$Uld3zpTXG@vu+a8_eBNBqluGC9h|?Y&b1dp5*a_|x06 z+E=YJSgDZsL#r(Z742{|h|7tUv!R zqW_mESC-@V#NXxlAN{AE|4)stgg;Z`VQLPb@W(ev&yGu^TipZWGz)%^`uV1k)W5pV zs&2y2jOJ~uvSrL7-S|)Njf=(q_QFH4!u|DKQd_dIY?#`raSvpZ$% zD(b5x@a$q`i;|ju$2?>I1&RMF=M(=y&i~r`(1N6K)A95_wb1Zq`uNwRyk4Pmn8_^h z&wM|c&Vz-{|G{@}Oc}q>hc{S{zse1|Js|#WjsGI)-F~W6k7`NThS=8rmwo>4zy53I z{7;tkUss(ne;E0H=Mp3SHKW>ye->?X`utyd@%Pqdi2n=csQC9u&1mAEO`b~||NZxW zl#>24#(($9{qgsqf2;a;a{LRC|6eZi^S=^|zo)W7+Llk1)+p2O+m=r=K5JPpUYci( zH0G>tJNqE9YQA$O#T+a8xGf6~k>DRfNjK3>b51N+ChEY78<&&vxn z{}b`g?)*O+R$3MuEPI){dmschKeE<6XN9RP! zi~c>*cAm94aP=Ij<~5o^#XtA?|F(($$ulD5CH}-en;cor>!5%8+EOQSLi~w;vin1_ z{fzeC+5Dh?XUETKo8!dzSBE;JW^7MRRz0FkszWV?RSj!&{rFGikfxmc81et8p%H(2 zD%`Clt6F4x_<;c!fB_hQ0T_S*7=Qs7fB_hQ0T_S*7=Qs7fB_hQ0T_S*7=Qs7fB_hQ z0T_S*7=Qs7fB_hQ0T_S*7=Qs7fB_hQ0T_S*7=Qs7fB_hQ0T_S*7=Qs7fB_gNA_MBs z{NVvSfCumZ9>4=`^1x_aS+BARy$I=d9#5#Me;NDV^>Z~Tci;nj00S@p126ysFaQHE z00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p z126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ys zFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE z00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p z126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ys zFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p12B*`1{!CKm#%x3rL~T0r%1<@ zN2Iqaju3BEMc&Hkfq?|y)=xelF>ZIArQ$R>eXQbRsbg1LnXrF+?kRhp_*Ne;Bfh#b ztp%Q4EdGaQrMK;~#9ISHh15**+(`*>3x9m0_#c^_K2~wD?0u+DDjKWHp7lb;#wo|j zO8>i-XXXk07hFH-_1~vrmd*z9Ir=aEc0N@;%0~aeS1&;SC3yakRR4RoNbv2;CG?x? zQ`>u2$HWu;qyKd00HF`Am%#3oG3I|_ehfo?+W*pM|G(TOVP)y!8UEt-nAo9z^q-EG zgzpqz!PnNrFogaK&rq`VKOt60#&*K{(0{7_u-iV*rvIOeso<|JLH|WQCqVy&&$;E6 zA9B|Jp0(&7{TKY4r`+^c?E2)a|2Nm6fAo+3i_C!4{DJUDeZjb)azg33NzjGNv|IUq_Ro&XPJ^FVpL+IbRv9n9R zR`-Mcoy!pVcW&&g>ejC9bJzc6jQ=tI$MwG=Ghj6jpnvDKA+-O_jh$89+O<9UcP>Nd z-?_1~OTSk4gZ`b%5c+p+?5yh6uI=sAf8CfNQZv$r703s^^QWeL&Nta}TlzDe|08dh z`NKB-$IU5~alSCtj~zeF!5@JaSD=4~kH48ZEY=eJ56pw*w48iJ7OFKep&obGeR|H&Ix^`DL}zDxgmD#i8>`bYohzqB=)&m4jN(Lee}|K@lG zrWOZ1;#t(9UfL;vU>{ku>1W-dbi=pX%~f6o8O z1N8shmj`J7(LL?I`*ctLAKja}H^nr{-b+S_vVuJ-+g(2_Mbd} z{@tg0+W+F}zInz78M^+clCiE^P89!3*W~mJnaL7M=jD-v_J4by4Ba%PWVkdmvf(JH zY^^P;-xu&L8*h2eH}jgU9m~M;OVPfX57TWqEMEV1u#}H|RCP9>|2)pCf&Sg6eVyyj ze{s$OX#d@*w^Hk0pnvqQ`)joS?#xHwFK+KY4^`*={!+5IzHZs||5qI$fq(jT3OieU zt}WH~(Vu6#-u`WNs^!ilvG(j@3BJ18b?3gN))p6|JmD|5N%(i)DV}|PtAtJa>}Cmn zv|0R5Ele02D>wZQxn>r6bK!VfF*NR|W2$_l+r9WPMD*{@{;8wbC7)Su)6l&`=rQFupMgP`)2#5I4sSKch*mWwql-oMH z=-;{z;Se7>l>zh*yG~`7a$9E?{ag1T9O6T#GJyVJ*QxAMZtLu#f9pPkLwx8|23(^5 z)&-NL`~LH++XJg)#J+7M#k+o{Z1|7PmEk|MZvGd`drq?Me^_aYpL(CZtfUyw&us)= zyCEmOySAPvLvJ{Gz}6ovl`Z8p|Cc%Erq!jlwo1aE-Bwbu4}Woocq+WM%-7^wJF}$f zX6y4vzrRx|>T7KAQ`4MDCFiG(^>b{gn^ldJ^Y-Z9!OumafAWLJ+WbT4AN}k0jrQM~ zj-1*@K>z3;{kv29I_~Hn{iA>MZ|k^}#cM~5|7DqzIREGTpY#8;3^4wmUE9X_e|COy z>Un;ua?}6MvaPk)r^!qIiuONk?oY)$pAY0Z^pF0v9%%muG~uTFP>TB3_akn&ag%J` zyg99f!{LniznuI3Vbv$OZcAoAO`JF}qo2?}`p-)rHOGGQpZ@k|$@DjM>eP%}m$m-Y zebWE+m;cS=CRx6Gc}72>fAo+3opmmtpOZlU?$oVa=O`uF|5tqm+W*YC2>qjdt9bzZ zXVzIM^^2m*g8tDz`cKaQ=l{a_zr}lGtZJ;3x2OH5{nval{+GTTDP;{?DI5An|LEVH z+ShSM|L7n6yIcPwJ}s^JfAkm^ep6Z>X&?GuzAh&}1>amJ{)cA`*!EdcH?C7^4)pcg$Tq3T(JDLZ z(Z7SnE`6(y&xxT@&=O_H+}}v%qXhjw)F%~9)#%niy0xnxg#L5WP%>RPjEM_oIJ9{)%G z=pX&N<~j)acW-~6@xOs~(5-y}^pF0{Jiz(C`|<($NB`*GeY!XMJLn(%qkr@t83Sbe zkMTdo|J*bF_ts@GM zkN(ZEVV32e59t59SMT)y%U|D_aya@&|7ISb|L?whfd0{c&idE$#{KR#3BPwuti5}+ zbZnd}LvEOZ703s}A6%8wHB0o5{&Uv9x=$ed=~f9mxljU6Efl}D$LEXx(K+I+spPs! z0q2lvo;wNs=iA@a72-R0+@P&ZZPRZD?_Z9S+VMk5P9M4S|HFHg{GKVAHf%HkN$Jj ztexAHyZ-$zT%FVP4XwT4>la3}S1kPpe|1Tu4Cp`gIf$K_aMQlff9iI*B=jGZgU~vkX{}R`~8Z(IL|Ci16Kl=Z6YdM$wq5l%s|I4c)`tN<{RB4(WD)=>`Ok6Sk@7#V# z?)twp!liDXO7;0)$DjYJ>jq}~-}}%h(r{`I`p@_Mnl9Qu`Y-YJ|FtzS`fr>SME@?* zXQsZF)$h@N{`Ftk)}XHceK)7;5WzPtiqU`5X<_t_{%vCb{TD$0trqkjHP51P{*V4` zW8Z4qSq|Ihtp7JT|Iar5l@|0LdjDG5f7<)J<-FYWAN%{ijQ^z`1Gc39->#3+zZ(BP zZA9K!$TpwFub0#K|0g%`{7(twHS}NF{r}K!Hw@^1JNl2$J-kod?quT|^zS77_o?>3 zOve9c|4X7DhyER=|8lwi=i?jc|2w(=zh`ZvU&{SI>HA<6&2~PnX{y- zqp>7(YnR`BD-J0wA1gn%E*Mo-KDH}XuG&v2>R+*0)!9&1Y@+`XZwE`@oW3Y|2mKc$ z&!B(wUle_3%4_H!{byo??+e06vGRle>2uXs+eHPi3)L~AOg$r~=j=`Y-Eq=x9AT z?R8Q0Py3(8egW;j)3jKO@)lM9ZaM#_{ippe(d#JapZNHGs#ucUZx>jMhRjM!j{FunC(m00S@p126ys zFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE z00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p z126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ys zFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE z00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p z126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ys zFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE00S@p126ysFaQHE z00S@p126ysFaQIEV8Fv49>4>501w~+Jb(xA03N^tcmNOJ0X%>Q@Bkjb19$)r-~l{< U2k-zMzyo*y58wej;A{{4KR^n?YybcN From 1295ed6206d2c8e2dbc509e80a59a1c6dc102831 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Fri, 15 Sep 2017 12:58:49 +0200 Subject: [PATCH 020/553] Add Checkem Command --- Geekbot.net/Lib/CheckEmImageProvider.cs | 40 ++++++ .../Lib/{Fortunes.cs => FortunesProvider.cs} | 9 +- Geekbot.net/Modules/CheckEm.cs | 38 ++++++ Geekbot.net/Modules/Fortune.cs | 4 +- Geekbot.net/Program.cs | 6 +- Geekbot.net/Storage/checkEmPics | 122 ++++++++++++++++++ Geekbot.net/{ => Storage}/fortunes | 0 7 files changed, 211 insertions(+), 8 deletions(-) create mode 100644 Geekbot.net/Lib/CheckEmImageProvider.cs rename Geekbot.net/Lib/{Fortunes.cs => FortunesProvider.cs} (77%) create mode 100644 Geekbot.net/Modules/CheckEm.cs create mode 100644 Geekbot.net/Storage/checkEmPics rename Geekbot.net/{ => Storage}/fortunes (100%) diff --git a/Geekbot.net/Lib/CheckEmImageProvider.cs b/Geekbot.net/Lib/CheckEmImageProvider.cs new file mode 100644 index 0000000..823d349 --- /dev/null +++ b/Geekbot.net/Lib/CheckEmImageProvider.cs @@ -0,0 +1,40 @@ +using System; +using System.IO; + +namespace Geekbot.net.Lib +{ + public class CheckEmImageProvider : ICheckEmImageProvider + { + private string[] checkEmImageArray; + private int totalCheckEmImages; + private Random rnd; + + public CheckEmImageProvider() + { + var path = Path.GetFullPath("./Storage/checkEmPics"); + if (File.Exists(path)) + { + var rawCheckEmPics = File.ReadAllText(path); + checkEmImageArray = rawCheckEmPics.Split("\n"); + totalCheckEmImages = checkEmImageArray.Length; + rnd = new Random(); + Console.WriteLine($"- Loaded {totalCheckEmImages} CheckEm Images"); + } + else + { + Console.WriteLine("checkEmPics File not found"); + Console.WriteLine($"Path should be {path}"); + } + } + + public string GetRandomCheckEmPic() + { + return checkEmImageArray[rnd.Next(0, totalCheckEmImages)]; + } + } + + public interface ICheckEmImageProvider + { + string GetRandomCheckEmPic(); + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Fortunes.cs b/Geekbot.net/Lib/FortunesProvider.cs similarity index 77% rename from Geekbot.net/Lib/Fortunes.cs rename to Geekbot.net/Lib/FortunesProvider.cs index 15cc710..b11c368 100644 --- a/Geekbot.net/Lib/Fortunes.cs +++ b/Geekbot.net/Lib/FortunesProvider.cs @@ -6,21 +6,22 @@ using System.Text.RegularExpressions; namespace Geekbot.net.Lib { - class Fortunes : IFortunes + class FortunesProvider : IFortunesProvider { private string[] fortuneArray; private int totalFortunes; private Random rnd; - public Fortunes() + public FortunesProvider() { - var path = Path.GetFullPath("./fortunes"); + var path = Path.GetFullPath("./Storage/fortunes"); if (File.Exists(path)) { var rawFortunes= File.ReadAllText(path); fortuneArray = rawFortunes.Split("%"); totalFortunes = fortuneArray.Length; rnd = new Random(); + Console.WriteLine($"- Loaded {totalFortunes} Fortunes"); } else { @@ -40,7 +41,7 @@ namespace Geekbot.net.Lib } } - public interface IFortunes + public interface IFortunesProvider { string GetRandomFortune(); string GetFortune(int id); diff --git a/Geekbot.net/Modules/CheckEm.cs b/Geekbot.net/Modules/CheckEm.cs new file mode 100644 index 0000000..6c5d45f --- /dev/null +++ b/Geekbot.net/Modules/CheckEm.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Discord.Commands; +using Geekbot.net.Lib; + +namespace Geekbot.net.Modules +{ + public class CheckEm : ModuleBase + { + private readonly Random rnd; + private readonly ICheckEmImageProvider checkEmImages; + public CheckEm(Random RandomClient, ICheckEmImageProvider checkEmImages) + { + this.rnd = RandomClient; + this.checkEmImages = checkEmImages; + } + [Command("checkem", RunMode = RunMode.Async), Summary("Check for dubs")] + public async Task MuhDubs() + { + try + { + var sb = new StringBuilder(); + + sb.AppendLine($"Check em {Context.User.Mention}"); + sb.AppendLine($"**{rnd.Next(100000, 99999999)}**"); + sb.AppendLine(checkEmImages.GetRandomCheckEmPic()); + + await ReplyAsync(sb.ToString()); + } + catch (Exception e) + { + Console.WriteLine(e.Message); + } + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Modules/Fortune.cs b/Geekbot.net/Modules/Fortune.cs index c898750..b4e4b07 100644 --- a/Geekbot.net/Modules/Fortune.cs +++ b/Geekbot.net/Modules/Fortune.cs @@ -7,8 +7,8 @@ namespace Geekbot.net.Modules { public class Fortune : ModuleBase { - private readonly IFortunes fortunes; - public Fortune(IFortunes fortunes) + private readonly IFortunesProvider fortunes; + public Fortune(IFortunesProvider fortunes) { this.fortunes = fortunes; } diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 63cebad..51699e1 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -68,9 +68,11 @@ namespace Geekbot.net } services = new ServiceCollection(); - var fortunes = new Fortunes(); + var fortunes = new FortunesProvider(); + var checkEmImages = new CheckEmImageProvider(); var RandomClient = new Random(); - services.AddSingleton(fortunes); + services.AddSingleton(fortunes); + services.AddSingleton(checkEmImages); services.AddSingleton(RandomClient); services.AddSingleton(redis); diff --git a/Geekbot.net/Storage/checkEmPics b/Geekbot.net/Storage/checkEmPics new file mode 100644 index 0000000..03be23e --- /dev/null +++ b/Geekbot.net/Storage/checkEmPics @@ -0,0 +1,122 @@ +http://s19.postimg.org/pcq2kwzoj/4cb.png +http://s19.postimg.org/cvetk0f4z/5_Dim_Dy6p.jpg +http://s19.postimg.org/5hzfl1v37/1310151998600.jpg +http://s19.postimg.org/53y3lgazn/1324181141954.jpg +http://s19.postimg.org/724rjg3hf/1392512742365.png +http://s19.postimg.org/3rgejkdk3/1393501296733.png +http://s19.postimg.org/a6ffg8k9v/1401667341503.jpg +http://s19.postimg.org/qiph5yylf/1419231572452.jpg +http://s19.postimg.org/fqwi4m8ir/1427600681401.png +http://s19.postimg.org/4c00zzw6b/1447813628974.png +http://s19.postimg.org/uuio8puw3/b5_3q_ycaaavxtf.jpg +http://s19.postimg.org/bghu913fn/check_em_by_boyboy99100_d57xp3y.png +http://s19.postimg.org/s1pgooujn/l_Hkppjs.jpg +http://s19.postimg.org/m08itft0j/checkem.jpg +https://old.postimg.org/image/6vx33rb1b/ +https://old.postimg.org/image/wxiaz1mov/ +https://old.postimg.org/image/azqfizx27/ +https://old.postimg.org/image/6iy2kbiu7/ +https://old.postimg.org/image/k8slt45y7/ +https://old.postimg.org/image/t7ruxmplr/ +https://old.postimg.org/image/ssbzqvean/ +https://old.postimg.org/image/kbchfy9lr/ +https://old.postimg.org/image/dl0lk9btr/ +https://old.postimg.org/image/e5k80oufz/ +https://old.postimg.org/image/er005baqn/ +https://old.postimg.org/image/bfk2uzcin/ +https://old.postimg.org/image/556fp0jkv/ +https://old.postimg.org/image/i0efbryu7/ +https://old.postimg.org/image/943n7u87z/ +https://old.postimg.org/image/xn5op5cm7/ +https://old.postimg.org/image/3l5p4d0kf/ +https://old.postimg.org/image/5boq5ui3j/ +https://old.postimg.org/image/ru082bqcf/ +https://old.postimg.org/image/ytea1oqan/ +https://old.postimg.org/image/vu7dekgtb/ +https://old.postimg.org/image/hl7qwi2an/ +https://old.postimg.org/image/5aescfg9r/ +https://old.postimg.org/image/9gzmrrfvj/ +https://old.postimg.org/image/50bv6tr1b/ +https://old.postimg.org/image/afkl7silb/ +https://old.postimg.org/image/nrdsgzllr/ +https://old.postimg.org/image/s32e5zsin/ +https://old.postimg.org/image/5sej60v8f/ +https://old.postimg.org/image/lgfqctau7/ +https://old.postimg.org/image/tn7q4e0wv/ +https://old.postimg.org/image/8612arz1b/ +https://old.postimg.org/image/w5tf52mn3/ +https://old.postimg.org/image/zdxwi48wv/ +https://old.postimg.org/image/lphwghd0f/ +https://old.postimg.org/image/uzu0k0nq7/ +https://old.postimg.org/image/3vqzsxjbz/ +https://old.postimg.org/image/5d7uqqyov/ +https://old.postimg.org/image/dntnyku8v/ +https://old.postimg.org/image/dsxf891jz/ +https://old.postimg.org/image/3nyrioizj/ +https://old.postimg.org/image/6zx2bzaqn/ +https://old.postimg.org/image/wu6v1raqn/ +https://old.postimg.org/image/hb9f4n2fz/ +https://old.postimg.org/image/p7yhqm3a7/ +https://old.postimg.org/image/oelvxzx9b/ +https://old.postimg.org/image/vcq03xvdr/ +https://old.postimg.org/image/b08t1yqlb/ +https://old.postimg.org/image/6yrpwayan/ +https://old.postimg.org/image/btleukwm7/ +https://old.postimg.org/image/62ztuldzz/ +https://old.postimg.org/image/w3iq9pxr3/ +https://old.postimg.org/image/byp6493xb/ +https://old.postimg.org/image/xp2lf9xcv/ +https://old.postimg.org/image/j9p9u49pb/ +https://old.postimg.org/image/hvxmytafz/ +https://old.postimg.org/image/5eqzbnfa7/ +https://old.postimg.org/image/do2uq290f/ +https://old.postimg.org/image/54o261q1r/ +https://old.postimg.org/image/94qm4jr4v/ +https://old.postimg.org/image/lee88y0pr/ +https://old.postimg.org/image/bncb58cv3/ +https://old.postimg.org/image/5246j7me7/ +https://old.postimg.org/image/4uby8ym1r/ +https://old.postimg.org/image/qn996tj4v/ +https://old.postimg.org/image/c1dn4twyn/ +https://old.postimg.org/image/6rd9ra23j/ +https://lehcark14.files.wordpress.com/2008/08/botan16.jpg +http://i.imgur.com/p9vALew.jpg +http://i.imgur.com/4a9l2Rm.png +http://i.imgur.com/RNtixMQ.jpg +https://pbs.twimg.com/media/Cro9aIGUEAAkXCP.jpg +http://s16.postimg.org/empvloimd/Check_em_Guts.png +https://s18.postimg.io/qgbhe7u09/1424491645996.gif +http://s19.postimg.org/hhemlt7xf/3eb.jpg +http://s19.postimg.org/cwsg6vo83/8aa.png +http://s19.postimg.org/rh9j1pj6r/28mohl4.png +http://s19.postimg.org/zba4n3qzn/86d.jpg +http://s19.postimg.org/cb3hart5v/2016_09_16_08_58_45.png +http://s19.postimg.org/m9ofx92lf/bb1.jpg +http://s19.postimg.org/maydqo4f7/e8b.jpg +http://s19.postimg.org/yqzoy5n4z/fbe.png +http://s19.postimg.org/xd822unvn/giphy.gif +http://s19.postimg.org/c4udlf9er/l_TU3eup.jpg +https://66.media.tumblr.com/cc893a0ee40d73d083da3df4bdaf45cc/tumblr_mx8psiFduG1t1g1k8o1_500.gif +http://i.imgur.com/swbXHSy.gif +http://img1.reactor.cc/pics/post/full/Anime-Touhou-Project-Yakumo-Yukari-%D0%A0%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D1%8F-1303807.jpeg +http://i.imgur.com/ftGLHE0.png +http://i.imgur.com/JELDhKQ.png +http://imgur.com/yBJound +http://i.imgur.com/f7gAVPJ.png +http://i.imgur.com/HxWyo2Z.jpg +http://i.imgur.com/8Eb9CxQ.png +http://i.imgur.com/kOECcjz.png +http://i.imgur.com/MJLu7oJ.jpg +http://i.imgur.com/itG3rPM.jpg +http://i.imgur.com/G83Go9t.jpg +http://i.imgur.com/jI2dBnU.jpg +http://i.imgur.com/FtALzg0.jpg +http://i.imgur.com/GwZpJEv.gif +http://i.imgur.com/TYGRD3B.gif +http://i.imgur.com/P6TxLS3.png +http://i.imgur.com/phTVTdn.jpg +http://i.imgur.com/thhR6UE.jpg +http://i.imgur.com/KbROufx.jpg +http://i.imgur.com/sQqWbcm.jpg +http://i.imgur.com/YYpis53.png +http://i.imgur.com/kwaRd54.gif \ No newline at end of file diff --git a/Geekbot.net/fortunes b/Geekbot.net/Storage/fortunes similarity index 100% rename from Geekbot.net/fortunes rename to Geekbot.net/Storage/fortunes From c82d6ec6668d22480869d0988c1527807c1daff2 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Fri, 15 Sep 2017 21:10:22 +0200 Subject: [PATCH 021/553] Add Dub, Trips and Quads check to !checkem (please fix if you see this) --- Geekbot.net/Modules/CheckEm.cs | 60 ++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/Geekbot.net/Modules/CheckEm.cs b/Geekbot.net/Modules/CheckEm.cs index 6c5d45f..150b97d 100644 --- a/Geekbot.net/Modules/CheckEm.cs +++ b/Geekbot.net/Modules/CheckEm.cs @@ -19,20 +19,54 @@ namespace Geekbot.net.Modules [Command("checkem", RunMode = RunMode.Async), Summary("Check for dubs")] public async Task MuhDubs() { - try - { - var sb = new StringBuilder(); - - sb.AppendLine($"Check em {Context.User.Mention}"); - sb.AppendLine($"**{rnd.Next(100000, 99999999)}**"); - sb.AppendLine(checkEmImages.GetRandomCheckEmPic()); - - await ReplyAsync(sb.ToString()); - } - catch (Exception e) - { - Console.WriteLine(e.Message); + try + { + int number = rnd.Next(10000000, 99999999); + var dubtriqua = ""; + + var ns = GetIntArray(number); + Console.WriteLine(ns.Length); + if (ns[7] == ns[6]) + { + dubtriqua = "DUBS"; + if (ns[6] == ns[5]) + { + dubtriqua = "TRIPS"; + if (ns[5] == ns[4]) + { + dubtriqua = "QUADS"; + } + } + } + + var sb = new StringBuilder(); + sb.AppendLine($"Check em {Context.User.Mention}"); + sb.AppendLine($"**{number}**"); + if (!string.IsNullOrEmpty(dubtriqua)) + { + sb.AppendLine($":tada: {dubtriqua} :tada:"); + } + sb.AppendLine(checkEmImages.GetRandomCheckEmPic()); + + await ReplyAsync(sb.ToString()); + } + catch (Exception e) + { + Console.WriteLine(e.Message); } + + } + + private int[] GetIntArray(int num) + { + List listOfInts = new List(); + while (num > 0) + { + listOfInts.Add(num % 10); + num = num / 10; + } + listOfInts.Reverse(); + return listOfInts.ToArray(); } } } \ No newline at end of file From 8911123b787b64975377d8fb23996754b10237d7 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Fri, 15 Sep 2017 22:56:03 +0200 Subject: [PATCH 022/553] Updated Help Command and code update --- Geekbot.net/Lib/CheckEmImageProvider.cs | 6 +- Geekbot.net/Lib/FortunesProvider.cs | 15 ++-- Geekbot.net/Lib/LevelCalc.cs | 14 ++-- Geekbot.net/Lib/StatsRecorder.cs | 4 +- Geekbot.net/Modules/AdminCmd.cs | 14 ++-- Geekbot.net/Modules/Cat.cs | 11 ++- Geekbot.net/Modules/CheckEm.cs | 94 ++++++++++++------------- Geekbot.net/Modules/Choose.cs | 6 +- Geekbot.net/Modules/Counters.cs | 37 +++++----- Geekbot.net/Modules/Dice.cs | 16 ++--- Geekbot.net/Modules/Dog.cs | 7 +- Geekbot.net/Modules/EightBall.cs | 13 ++-- Geekbot.net/Modules/Fortune.cs | 11 +-- Geekbot.net/Modules/GuildInfo.cs | 22 +++--- Geekbot.net/Modules/Help.cs | 47 +++++++++---- Geekbot.net/Modules/Info.cs | 4 +- Geekbot.net/Modules/Ping.cs | 4 +- Geekbot.net/Modules/Roll.cs | 10 +-- Geekbot.net/Modules/Say.cs | 8 ++- Geekbot.net/Modules/Ship.cs | 40 ++++------- Geekbot.net/Modules/UserInfo.cs | 50 +++++++------ Geekbot.net/Modules/Youtube.cs | 13 ++-- Geekbot.net/Program.cs | 40 +++++------ 23 files changed, 248 insertions(+), 238 deletions(-) diff --git a/Geekbot.net/Lib/CheckEmImageProvider.cs b/Geekbot.net/Lib/CheckEmImageProvider.cs index 823d349..5ead4a2 100644 --- a/Geekbot.net/Lib/CheckEmImageProvider.cs +++ b/Geekbot.net/Lib/CheckEmImageProvider.cs @@ -5,9 +5,9 @@ namespace Geekbot.net.Lib { public class CheckEmImageProvider : ICheckEmImageProvider { - private string[] checkEmImageArray; - private int totalCheckEmImages; - private Random rnd; + private readonly string[] checkEmImageArray; + private readonly Random rnd; + private readonly int totalCheckEmImages; public CheckEmImageProvider() { diff --git a/Geekbot.net/Lib/FortunesProvider.cs b/Geekbot.net/Lib/FortunesProvider.cs index b11c368..614d018 100644 --- a/Geekbot.net/Lib/FortunesProvider.cs +++ b/Geekbot.net/Lib/FortunesProvider.cs @@ -1,23 +1,20 @@ using System; -using System.Collections.Generic; using System.IO; -using System.Text; -using System.Text.RegularExpressions; namespace Geekbot.net.Lib { - class FortunesProvider : IFortunesProvider + internal class FortunesProvider : IFortunesProvider { - private string[] fortuneArray; - private int totalFortunes; - private Random rnd; + private readonly string[] fortuneArray; + private readonly Random rnd; + private readonly int totalFortunes; public FortunesProvider() { var path = Path.GetFullPath("./Storage/fortunes"); if (File.Exists(path)) { - var rawFortunes= File.ReadAllText(path); + var rawFortunes = File.ReadAllText(path); fortuneArray = rawFortunes.Split("%"); totalFortunes = fortuneArray.Length; rnd = new Random(); @@ -46,4 +43,4 @@ namespace Geekbot.net.Lib string GetRandomFortune(); string GetFortune(int id); } -} +} \ No newline at end of file diff --git a/Geekbot.net/Lib/LevelCalc.cs b/Geekbot.net/Lib/LevelCalc.cs index 1298319..5d47dc9 100644 --- a/Geekbot.net/Lib/LevelCalc.cs +++ b/Geekbot.net/Lib/LevelCalc.cs @@ -1,20 +1,16 @@ using System; -using System.Collections.Generic; -using System.Text; namespace Geekbot.net.Lib { - class LevelCalc + internal class LevelCalc { private static int GetExperienceAtLevel(int level) { double total = 0; - for (int i = 1; i < level; i++) - { + for (var i = 1; i < level; i++) total += Math.Floor(i + 300 * Math.Pow(2, i / 7.0)); - } - return (int)Math.Floor(total / 16); + return (int) Math.Floor(total / 16); } public static int GetLevelAtExperience(int experience) @@ -22,12 +18,10 @@ namespace Geekbot.net.Lib int index; for (index = 0; index < 120; index++) - { if (GetExperienceAtLevel(index + 1) > experience) break; - } return index; } } -} +} \ No newline at end of file diff --git a/Geekbot.net/Lib/StatsRecorder.cs b/Geekbot.net/Lib/StatsRecorder.cs index 85572fb..c88ec2d 100644 --- a/Geekbot.net/Lib/StatsRecorder.cs +++ b/Geekbot.net/Lib/StatsRecorder.cs @@ -1,5 +1,4 @@ -using System; -using System.Threading.Tasks; +using System.Threading.Tasks; using Discord.WebSocket; using StackExchange.Redis; @@ -7,7 +6,6 @@ namespace Geekbot.net.Lib { public class StatsRecorder { - private readonly SocketMessage message; private readonly IDatabase redis; diff --git a/Geekbot.net/Modules/AdminCmd.cs b/Geekbot.net/Modules/AdminCmd.cs index 9385409..72beb36 100644 --- a/Geekbot.net/Modules/AdminCmd.cs +++ b/Geekbot.net/Modules/AdminCmd.cs @@ -1,4 +1,5 @@ using System.Threading.Tasks; +using Discord; using Discord.Commands; using StackExchange.Redis; @@ -8,23 +9,26 @@ namespace Geekbot.net.Modules public class AdminCmd : ModuleBase { private readonly IDatabase redis; + public AdminCmd(IDatabase redis) { this.redis = redis; } - [RequireUserPermission(Discord.GuildPermission.Administrator)] - [Command("welcome", RunMode = RunMode.Async), Summary("Set a Welcome Message (use '$user' to mention the new joined user).")] - public async Task SetWelcomeMessage([Remainder, Summary("The message")] string welcomeMessage) + [RequireUserPermission(GuildPermission.Administrator)] + [Command("welcome", RunMode = RunMode.Async)] + [Summary("Set a Welcome Message (use '$user' to mention the new joined user).")] + public async Task SetWelcomeMessage([Remainder] [Summary("message")] string welcomeMessage) { var key = Context.Guild.Id + "-welcomeMsg"; redis.StringSet(key, welcomeMessage); var formatedMessage = welcomeMessage.Replace("$user", Context.User.Mention); await ReplyAsync("Welcome message has been changed\r\nHere is an example of how it would look:\r\n" + - formatedMessage); + formatedMessage); } - [Command("youtubekey", RunMode = RunMode.Async), Summary("Set the youtube api key")] + [Command("youtubekey", RunMode = RunMode.Async)] + [Summary("Set the youtube api key")] public async Task SetYoutubeKey([Summary("API Key")] string key) { var botOwner = redis.StringGet("botOwner"); diff --git a/Geekbot.net/Modules/Cat.cs b/Geekbot.net/Modules/Cat.cs index 2f9e63e..fe134ad 100644 --- a/Geekbot.net/Modules/Cat.cs +++ b/Geekbot.net/Modules/Cat.cs @@ -1,5 +1,4 @@ -using System; -using System.Threading.Tasks; +using System.Threading.Tasks; using Discord.Commands; using RestSharp; @@ -7,17 +6,15 @@ namespace Geekbot.net.Modules { public class Cat : ModuleBase { - [Command("cat", RunMode = RunMode.Async), Summary("Return a random image of a cat.")] + [Command("cat", RunMode = RunMode.Async)] + [Summary("Return a random image of a cat.")] public async Task Say() { var catClient = new RestClient("http://random.cat"); var request = new RestRequest("meow.php", Method.GET); - catClient.ExecuteAsync(request, async response => { - await ReplyAsync(response.Data.file); - }); + catClient.ExecuteAsync(request, async response => { await ReplyAsync(response.Data.file); }); } - } public class CatResponse diff --git a/Geekbot.net/Modules/CheckEm.cs b/Geekbot.net/Modules/CheckEm.cs index 150b97d..0d72241 100644 --- a/Geekbot.net/Modules/CheckEm.cs +++ b/Geekbot.net/Modules/CheckEm.cs @@ -9,64 +9,62 @@ namespace Geekbot.net.Modules { public class CheckEm : ModuleBase { - private readonly Random rnd; private readonly ICheckEmImageProvider checkEmImages; + private readonly Random rnd; + public CheckEm(Random RandomClient, ICheckEmImageProvider checkEmImages) { - this.rnd = RandomClient; + rnd = RandomClient; this.checkEmImages = checkEmImages; } - [Command("checkem", RunMode = RunMode.Async), Summary("Check for dubs")] + + [Command("checkem", RunMode = RunMode.Async)] + [Summary("Check for dubs")] public async Task MuhDubs() { - try - { - int number = rnd.Next(10000000, 99999999); - var dubtriqua = ""; - - var ns = GetIntArray(number); - Console.WriteLine(ns.Length); - if (ns[7] == ns[6]) - { - dubtriqua = "DUBS"; - if (ns[6] == ns[5]) - { - dubtriqua = "TRIPS"; - if (ns[5] == ns[4]) - { - dubtriqua = "QUADS"; - } - } - } - - var sb = new StringBuilder(); - sb.AppendLine($"Check em {Context.User.Mention}"); - sb.AppendLine($"**{number}**"); - if (!string.IsNullOrEmpty(dubtriqua)) - { - sb.AppendLine($":tada: {dubtriqua} :tada:"); - } - sb.AppendLine(checkEmImages.GetRandomCheckEmPic()); - - await ReplyAsync(sb.ToString()); - } - catch (Exception e) - { - Console.WriteLine(e.Message); + try + { + var number = rnd.Next(10000000, 99999999); + var dubtriqua = ""; + + var ns = GetIntArray(number); + Console.WriteLine(ns.Length); + if (ns[7] == ns[6]) + { + dubtriqua = "DUBS"; + if (ns[6] == ns[5]) + { + dubtriqua = "TRIPS"; + if (ns[5] == ns[4]) + dubtriqua = "QUADS"; + } + } + + var sb = new StringBuilder(); + sb.AppendLine($"Check em {Context.User.Mention}"); + sb.AppendLine($"**{number}**"); + if (!string.IsNullOrEmpty(dubtriqua)) + sb.AppendLine($":tada: {dubtriqua} :tada:"); + sb.AppendLine(checkEmImages.GetRandomCheckEmPic()); + + await ReplyAsync(sb.ToString()); + } + catch (Exception e) + { + Console.WriteLine(e.Message); } - } - private int[] GetIntArray(int num) - { - List listOfInts = new List(); - while (num > 0) - { - listOfInts.Add(num % 10); - num = num / 10; - } - listOfInts.Reverse(); - return listOfInts.ToArray(); + private int[] GetIntArray(int num) + { + var listOfInts = new List(); + while (num > 0) + { + listOfInts.Add(num % 10); + num = num / 10; + } + listOfInts.Reverse(); + return listOfInts.ToArray(); } } } \ No newline at end of file diff --git a/Geekbot.net/Modules/Choose.cs b/Geekbot.net/Modules/Choose.cs index 3242ed5..68ea4af 100644 --- a/Geekbot.net/Modules/Choose.cs +++ b/Geekbot.net/Modules/Choose.cs @@ -7,13 +7,15 @@ namespace Geekbot.net.Modules public class Choose : ModuleBase { private readonly Random rnd; + public Choose(Random RandomClient) { rnd = RandomClient; } - [Command("choose", RunMode = RunMode.Async), Summary("Let the bot make a choice for you.")] - public async Task Command([Remainder, Summary("The choices, sepperated by a ;")] string choices) + [Command("choose", RunMode = RunMode.Async)] + [Summary("Seperate options with a semicolon.")] + public async Task Command([Remainder] [Summary("option1;option2")] string choices) { var choicesArray = choices.Split(';'); var choice = rnd.Next(choicesArray.Length); diff --git a/Geekbot.net/Modules/Counters.cs b/Geekbot.net/Modules/Counters.cs index 9668ea3..66ecd9a 100644 --- a/Geekbot.net/Modules/Counters.cs +++ b/Geekbot.net/Modules/Counters.cs @@ -9,13 +9,15 @@ namespace Geekbot.net.Modules public class Counters : ModuleBase { private readonly IDatabase redis; + public Counters(IDatabase redis) { this.redis = redis; } - [Command("good", RunMode = RunMode.Async), Summary("Increase Someones Karma")] - public async Task Good([Summary("The someone")] IUser user) + [Command("good", RunMode = RunMode.Async)] + [Summary("Increase Someones Karma")] + public async Task Good([Summary("@someone")] IUser user) { var lastKarma = GetLastKarma(); if (user.Id == Context.User.Id) @@ -24,12 +26,13 @@ namespace Geekbot.net.Modules } else if (lastKarma > GetUnixTimestamp()) { - await ReplyAsync($"Sorry {Context.User.Username}, but you have to wait {GetTimeLeft(lastKarma)} before you can give karma again..."); + await ReplyAsync( + $"Sorry {Context.User.Username}, but you have to wait {GetTimeLeft(lastKarma)} before you can give karma again..."); } else { var key = Context.Guild.Id + "-" + user.Id + "-karma"; - var badJokes = (int)redis.StringGet(key); + var badJokes = (int) redis.StringGet(key); var newBadJokes = badJokes + 1; redis.StringSet(key, newBadJokes.ToString()); var lastKey = Context.Guild.Id + "-" + Context.User.Id + "-karma-timeout"; @@ -44,13 +47,14 @@ namespace Geekbot.net.Modules eb.Title = "Karma Increased"; eb.AddInlineField("By", Context.User.Username); eb.AddInlineField("amount", "+1"); - eb.AddInlineField("Current Karma",newBadJokes); + eb.AddInlineField("Current Karma", newBadJokes); await ReplyAsync("", false, eb.Build()); } } - [Command("bad", RunMode = RunMode.Async), Summary("Decrease Someones Karma")] - public async Task Bad([Summary("The someone")] IUser user) + [Command("bad", RunMode = RunMode.Async)] + [Summary("Decrease Someones Karma")] + public async Task Bad([Summary("@someone")] IUser user) { var lastKarma = GetLastKarma(); if (user.Id == Context.User.Id) @@ -59,17 +63,18 @@ namespace Geekbot.net.Modules } else if (lastKarma > GetUnixTimestamp()) { - await ReplyAsync($"Sorry {Context.User.Username}, but you have to wait {GetTimeLeft(lastKarma)} before you can take karma again..."); + await ReplyAsync( + $"Sorry {Context.User.Username}, but you have to wait {GetTimeLeft(lastKarma)} before you can take karma again..."); } else { var key = Context.Guild.Id + "-" + user.Id + "-karma"; - var badJokes = (int)redis.StringGet(key); + var badJokes = (int) redis.StringGet(key); var newBadJokes = badJokes - 1; redis.StringSet(key, newBadJokes.ToString()); var lastKey = Context.Guild.Id + "-" + Context.User.Id + "-karma-timeout"; redis.StringSet(lastKey, GetNewLastKarma()); - + var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder() .WithIconUrl(user.GetAvatarUrl()) @@ -79,7 +84,7 @@ namespace Geekbot.net.Modules eb.Title = "Karma Decreased"; eb.AddInlineField("By", Context.User.Username); eb.AddInlineField("amount", "-1"); - eb.AddInlineField("Current Karma",newBadJokes); + eb.AddInlineField("Current Karma", newBadJokes); await ReplyAsync("", false, eb.Build()); } } @@ -89,27 +94,25 @@ namespace Geekbot.net.Modules var lastKey = Context.Guild.Id + "-" + Context.User.Id + "-karma-timeout"; var redisReturn = redis.StringGet(lastKey); if (!int.TryParse(redisReturn.ToString(), out var i)) - { i = GetUnixTimestamp(); - } return i; } private int GetNewLastKarma() { var timeout = TimeSpan.FromMinutes(3); - return (int)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).Add(timeout)).TotalSeconds; + return (int) DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).Add(timeout).TotalSeconds; } private int GetUnixTimestamp() { - return (int)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds; + return (int) DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds; } private string GetTimeLeft(int time) { - DateTime dtDateTime = new DateTime(1970,1,1,0,0,0,0,DateTimeKind.Utc); - dtDateTime = dtDateTime.AddSeconds( time ).ToLocalTime(); + var dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + dtDateTime = dtDateTime.AddSeconds(time).ToLocalTime(); var dt = dtDateTime.Subtract(DateTime.Now); return $"{dt.Minutes} Minutes and {dt.Seconds} Seconds"; } diff --git a/Geekbot.net/Modules/Dice.cs b/Geekbot.net/Modules/Dice.cs index b559446..b44c7e8 100644 --- a/Geekbot.net/Modules/Dice.cs +++ b/Geekbot.net/Modules/Dice.cs @@ -1,25 +1,25 @@ using System; -using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; -using StackExchange.Redis; namespace Geekbot.net.Modules { public class Dice : ModuleBase { private readonly Random rnd; + public Dice(Random RandomClient) { rnd = RandomClient; } - [Command("dice", RunMode = RunMode.Async), Summary("Roll a dice.")] - public async Task RollCommand([Remainder, Summary("1d20, 1d6, 2d3, etc...")] string diceType = "1d6") + [Command("dice", RunMode = RunMode.Async)] + [Summary("Roll a dice.")] + public async Task RollCommand([Remainder] [Summary("diceType")] string diceType = "1d6") { - var dice = diceType.Split("d"); - + var dice = diceType.Split("d"); + if (dice.Length != 2 || !int.TryParse(dice[0], out int times) || !int.TryParse(dice[1], out int max)) @@ -45,9 +45,7 @@ namespace Geekbot.net.Modules eb.WithColor(new Color(133, 189, 219)); eb.Title = $":game_die: Dice Roll - Type {diceType} :game_die:"; for (var i = 0; i < times; i++) - { - eb.AddInlineField($"Dice {i+1}", rnd.Next(1, max)); - } + eb.AddInlineField($"Dice {i + 1}", rnd.Next(1, max)); await ReplyAsync("", false, eb.Build()); } } diff --git a/Geekbot.net/Modules/Dog.cs b/Geekbot.net/Modules/Dog.cs index 356cd09..80fd250 100644 --- a/Geekbot.net/Modules/Dog.cs +++ b/Geekbot.net/Modules/Dog.cs @@ -7,16 +7,15 @@ namespace Geekbot.net.Modules { public class Dog : ModuleBase { - [Command("dog", RunMode = RunMode.Async), Summary("Return a random image of a dog.")] + [Command("dog", RunMode = RunMode.Async)] + [Summary("Return a random image of a dog.")] public async Task Say() { var dogClient = new RestClient("http://random.dog"); var request = new RestRequest("woof.json", Method.GET); Console.WriteLine(dogClient.BaseUrl); - dogClient.ExecuteAsync(request, async response => { - await ReplyAsync(response.Data.url); - }); + dogClient.ExecuteAsync(request, async response => { await ReplyAsync(response.Data.url); }); } } diff --git a/Geekbot.net/Modules/EightBall.cs b/Geekbot.net/Modules/EightBall.cs index efce699..3f34d0b 100644 --- a/Geekbot.net/Modules/EightBall.cs +++ b/Geekbot.net/Modules/EightBall.cs @@ -8,14 +8,18 @@ namespace Geekbot.net.Modules public class EightBall : ModuleBase { private readonly Random rnd; + public EightBall(Random RandomClient) { rnd = RandomClient; } - [Command("8ball", RunMode = RunMode.Async), Summary("Ask 8Ball a Question.")] - public async Task Ball([Remainder, Summary("The Question")] string echo) + + [Command("8ball", RunMode = RunMode.Async)] + [Summary("Ask 8Ball a Question.")] + public async Task Ball([Remainder] [Summary("Question")] string echo) { - var replies = new List { + var replies = new List + { "It is certain", "It is decidedly so", "Without a doubt", @@ -35,7 +39,8 @@ namespace Geekbot.net.Modules "My reply is no", "My sources say no", "Outlook not so good", - "Very doubtful"}; + "Very doubtful" + }; var answer = rnd.Next(replies.Count); await ReplyAsync(replies[answer]); diff --git a/Geekbot.net/Modules/Fortune.cs b/Geekbot.net/Modules/Fortune.cs index b4e4b07..2040034 100644 --- a/Geekbot.net/Modules/Fortune.cs +++ b/Geekbot.net/Modules/Fortune.cs @@ -1,5 +1,4 @@ -using System; -using System.Threading.Tasks; +using System.Threading.Tasks; using Discord.Commands; using Geekbot.net.Lib; @@ -8,15 +7,17 @@ namespace Geekbot.net.Modules public class Fortune : ModuleBase { private readonly IFortunesProvider fortunes; + public Fortune(IFortunesProvider fortunes) { this.fortunes = fortunes; } - - [Command("fortune", RunMode = RunMode.Async), Summary("Get a random fortune")] + + [Command("fortune", RunMode = RunMode.Async)] + [Summary("Get a random fortune")] public async Task GetAFortune() { await ReplyAsync(fortunes.GetRandomFortune()); } } -} +} \ No newline at end of file diff --git a/Geekbot.net/Modules/GuildInfo.cs b/Geekbot.net/Modules/GuildInfo.cs index 6c357e5..20f4447 100644 --- a/Geekbot.net/Modules/GuildInfo.cs +++ b/Geekbot.net/Modules/GuildInfo.cs @@ -1,9 +1,9 @@ using System; -using System.Threading.Tasks; -using Discord.Commands; -using Discord; -using Geekbot.net.Lib; using System.Linq; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Geekbot.net.Lib; using StackExchange.Redis; namespace Geekbot.net.Modules @@ -11,25 +11,27 @@ namespace Geekbot.net.Modules public class GuildInfo : ModuleBase { private readonly IDatabase redis; + public GuildInfo(IDatabase redis) { this.redis = redis; } - [Command("serverstats", RunMode = RunMode.Async), Summary("Show some info about the bot.")] + [Command("serverstats", RunMode = RunMode.Async)] + [Summary("Show some info about the bot.")] public async Task getInfo() { var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder() - .WithIconUrl(Context.Guild.IconUrl) - .WithName(Context.Guild.Name)); + .WithIconUrl(Context.Guild.IconUrl) + .WithName(Context.Guild.Name)); eb.WithColor(new Color(110, 204, 147)); - + var created = Context.Guild.CreatedAt; var age = Math.Floor((DateTime.Now - created).TotalDays); var messages = redis.StringGet($"{Context.Guild.Id}-messages"); - var level = LevelCalc.GetLevelAtExperience((int)messages); + var level = LevelCalc.GetLevelAtExperience((int) messages); eb.AddField("Server Age", $"{created.Day}/{created.Month}/{created.Year} ({age} days)"); eb.AddInlineField("Level", level) @@ -40,7 +42,7 @@ namespace Geekbot.net.Modules public static string FirstCharToUpper(string input) { - if (String.IsNullOrEmpty(input)) + if (string.IsNullOrEmpty(input)) throw new ArgumentException("ARGH!"); return input.First().ToString().ToUpper() + input.Substring(1); } diff --git a/Geekbot.net/Modules/Help.cs b/Geekbot.net/Modules/Help.cs index 7064cba..9dd80a5 100644 --- a/Geekbot.net/Modules/Help.cs +++ b/Geekbot.net/Modules/Help.cs @@ -1,27 +1,48 @@ -using System.Threading.Tasks; +using System.Linq; +using System.Text; +using System.Threading.Tasks; using Discord.Commands; -using System.Reflection; namespace Geekbot.net.Modules { public class Help : ModuleBase { - [Command("help", RunMode = RunMode.Async), Summary("List all Commands")] + private readonly CommandService commands; + + public Help(CommandService commands) + { + this.commands = commands; + } + + [Command("help", RunMode = RunMode.Async)] + [Summary("List all Commands")] public async Task GetHelp() { - var commands = new CommandService(); - await commands.AddModulesAsync(Assembly.GetEntryAssembly()); - var cmdList = commands.Commands; - var reply = "**Geekbot Command list**\r\n"; - foreach (var cmd in cmdList) + var sb = new StringBuilder(); + sb.AppendLine("```"); + sb.AppendLine("**Geekbot Command list**"); + sb.AppendLine(""); + sb.AppendLine(tp("Name", 15) + tp("Parameters", 19) + "Description"); + foreach (var cmd in commands.Commands) { - var param = string.Join(", !",cmd.Aliases); + var param = string.Join(", !", cmd.Aliases); if (!param.Contains("admin")) - { - reply = reply + $"**{cmd.Name}** (!{param}) - {cmd.Summary}\r\n"; - } + if (cmd.Parameters.Any()) + sb.AppendLine(tp(param, 15) + + tp(string.Join(",", cmd.Parameters.Select(e => e.Summary)), 19) + + cmd.Summary); + else + sb.AppendLine(tp(param, 34) + cmd.Summary); } - await ReplyAsync(reply); + sb.AppendLine("```"); + var dm = await Context.User.GetOrCreateDMChannelAsync(); + await dm.SendMessageAsync(sb.ToString()); + } + + // Table Padding, short function name because of many usages + private string tp(string text, int shouldHave) + { + return text.PadRight(shouldHave); } } } \ No newline at end of file diff --git a/Geekbot.net/Modules/Info.cs b/Geekbot.net/Modules/Info.cs index 73e04fc..62d4a01 100644 --- a/Geekbot.net/Modules/Info.cs +++ b/Geekbot.net/Modules/Info.cs @@ -8,12 +8,14 @@ namespace Geekbot.net.Modules public class Info : ModuleBase { private readonly IDatabase redis; + public Info(IDatabase redis) { this.redis = redis; } - [Command("info", RunMode = RunMode.Async), Summary("Get Information about the bot")] + [Command("info", RunMode = RunMode.Async)] + [Summary("Get Information about the bot")] public async Task BotInfo() { var eb = new EmbedBuilder(); diff --git a/Geekbot.net/Modules/Ping.cs b/Geekbot.net/Modules/Ping.cs index 0803413..2ccca12 100644 --- a/Geekbot.net/Modules/Ping.cs +++ b/Geekbot.net/Modules/Ping.cs @@ -1,12 +1,12 @@ using System.Threading.Tasks; -using Discord; using Discord.Commands; namespace Geekbot.net.Modules { public class Ping : ModuleBase { - [Command("👀", RunMode = RunMode.Async), Summary("Look at the bot.")] + [Command("👀", RunMode = RunMode.Async)] + [Summary("Look at the bot.")] public async Task Eyes() { await ReplyAsync("S... Stop looking at me... baka!"); diff --git a/Geekbot.net/Modules/Roll.cs b/Geekbot.net/Modules/Roll.cs index 1c8755d..c46b887 100644 --- a/Geekbot.net/Modules/Roll.cs +++ b/Geekbot.net/Modules/Roll.cs @@ -9,14 +9,16 @@ namespace Geekbot.net.Modules { private readonly IDatabase redis; private readonly Random rnd; + public Roll(IDatabase redis, Random RandomClient) { this.redis = redis; - this.rnd = RandomClient; + rnd = RandomClient; } - [Command("roll", RunMode = RunMode.Async), Summary("Roll a number between 1 and 100.")] - public async Task RollCommand([Remainder, Summary("stuff...")] string stuff = "nothing") + [Command("roll", RunMode = RunMode.Async)] + [Summary("Roll a number between 1 and 100.")] + public async Task RollCommand([Remainder] [Summary("stuff...")] string stuff = "nothing") { var number = rnd.Next(1, 100); var guess = 1000; @@ -28,7 +30,7 @@ namespace Geekbot.net.Modules { await ReplyAsync($"Congratulations {Context.User.Username}, your guess was correct!"); var key = $"{Context.Guild.Id}-{Context.User.Id}-correctRolls"; - var messages = (int)redis.StringGet(key); + var messages = (int) redis.StringGet(key); redis.StringSet(key, (messages + 1).ToString()); } } diff --git a/Geekbot.net/Modules/Say.cs b/Geekbot.net/Modules/Say.cs index 35f0294..7d4b7af 100644 --- a/Geekbot.net/Modules/Say.cs +++ b/Geekbot.net/Modules/Say.cs @@ -1,13 +1,15 @@ using System.Threading.Tasks; +using Discord; using Discord.Commands; namespace Geekbot.net.Modules { public class Say : ModuleBase { - [RequireUserPermission(Discord.GuildPermission.Administrator)] - [Command("say", RunMode = RunMode.Async), Summary("Say Something.")] - public async Task Echo([Remainder, Summary("What?")] string echo) + [RequireUserPermission(GuildPermission.Administrator)] + [Command("say", RunMode = RunMode.Async)] + [Summary("Say Something.")] + public async Task Echo([Remainder] [Summary("What?")] string echo) { await Context.Message.DeleteAsync(); await ReplyAsync(echo); diff --git a/Geekbot.net/Modules/Ship.cs b/Geekbot.net/Modules/Ship.cs index 2049580..ed4365f 100644 --- a/Geekbot.net/Modules/Ship.cs +++ b/Geekbot.net/Modules/Ship.cs @@ -8,28 +8,25 @@ namespace Geekbot.net.Modules { public class Ship : ModuleBase { - private readonly IDatabase redis; private readonly Random rnd; + public Ship(IDatabase redis, Random RandomClient) { this.redis = redis; - this.rnd = RandomClient; + rnd = RandomClient; } - [Command("Ship", RunMode = RunMode.Async), Summary("Ask the Shipping meter")] - public async Task Command([Summary("User 1")] IUser user1, [Summary("User 2")] IUser user2) + [Command("Ship", RunMode = RunMode.Async)] + [Summary("Ask the Shipping meter")] + public async Task Command([Summary("@User1")] IUser user1, [Summary("@User2")] IUser user2) { // Create a String var dbstring = ""; if (user1.Id > user2.Id) - { dbstring = $"{user1.Id}-{user2.Id}"; - } else - { dbstring = $"{user2.Id}-{user1.Id}"; - } dbstring = $"{Context.Guild.Id}-{dbstring}"; Console.WriteLine(dbstring); @@ -54,21 +51,15 @@ namespace Geekbot.net.Modules private string DeterminateSuccess(int rate) { if (rate < 20) - { return "Not gonna happen"; - } if (rate >= 20 && rate < 40) - { + if (rate >= 20 && rate < 40) return "Not such a good idea"; - } if (rate >= 40 && rate < 60) - { + if (rate >= 40 && rate < 60) return "There might be a chance"; - } if (rate >= 60 && rate < 80) - { + if (rate >= 60 && rate < 80) return "Almost a match, but could work"; - } if (rate >= 80) - { + if (rate >= 80) return "It's a match"; - } return "a"; } @@ -77,20 +68,17 @@ namespace Geekbot.net.Modules var amount = Math.Floor(decimal.Floor(rate / 10)); Console.WriteLine(amount); var blocks = ""; - for(int i = 1; i <= 10; i++) - { - if(i <= amount) + for (var i = 1; i <= 10; i++) + if (i <= amount) { blocks = blocks + ":white_medium_small_square:"; - if(i == amount) - { + if (i == amount) blocks = blocks + $" {rate}% "; - } - } else + } + else { blocks = blocks + ":black_medium_small_square:"; } - } return blocks; } } diff --git a/Geekbot.net/Modules/UserInfo.cs b/Geekbot.net/Modules/UserInfo.cs index dd57ad6..1af885d 100644 --- a/Geekbot.net/Modules/UserInfo.cs +++ b/Geekbot.net/Modules/UserInfo.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Linq; using Discord; using Discord.Commands; using Geekbot.net.Lib; @@ -13,27 +13,28 @@ namespace Geekbot.net.Modules public class UserInfo : ModuleBase { private readonly IDatabase redis; + public UserInfo(IDatabase redis) { this.redis = redis; } - [Alias("stats")] - [Command("user", RunMode = RunMode.Async), Summary("Get information about this user")] - public async Task User([Summary("The (optional) user to get info for")] IUser user = null) + [Command("user", RunMode = RunMode.Async)] + [Summary("Get information about this user")] + public async Task User([Summary("@someone")] IUser user = null) { var userInfo = user ?? Context.Message.Author; var age = Math.Floor((DateTime.Now - userInfo.CreatedAt).TotalDays); var key = Context.Guild.Id + "-" + userInfo.Id; - var messages = (int)redis.StringGet(key + "-messages"); + var messages = (int) redis.StringGet(key + "-messages"); var level = LevelCalc.GetLevelAtExperience(messages); var guildKey = Context.Guild.Id.ToString(); - var guildMessages = (int)redis.StringGet(guildKey + "-messages"); + var guildMessages = (int) redis.StringGet(guildKey + "-messages"); - var percent = Math.Round((double)(100 * messages) / guildMessages, 2); + var percent = Math.Round((double) (100 * messages) / guildMessages, 2); var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder() @@ -42,57 +43,54 @@ namespace Geekbot.net.Modules eb.WithColor(new Color(221, 255, 119)); - eb.AddField("Discordian Since", $"{userInfo.CreatedAt.Day}/{userInfo.CreatedAt.Month}/{userInfo.CreatedAt.Year} ({age} days)"); + eb.AddField("Discordian Since", + $"{userInfo.CreatedAt.Day}/{userInfo.CreatedAt.Month}/{userInfo.CreatedAt.Year} ({age} days)"); eb.AddInlineField("Level", level) .AddInlineField("Messages Sent", messages) .AddInlineField("Server Total", $"{percent}%"); var karma = redis.StringGet(key + "-karma"); if (!karma.IsNullOrEmpty) - { eb.AddInlineField("Karma", karma); - } var correctRolls = redis.StringGet($"{Context.Guild.Id}-{userInfo.Id}-correctRolls"); if (!correctRolls.IsNullOrEmpty) - { eb.AddInlineField("Guessed Rolls", correctRolls); - } await ReplyAsync("", false, eb.Build()); } - [Alias("highscore")] - [Command("rank", RunMode = RunMode.Async), Summary("get user top 10")] - public async Task Rank() + [Command("rank", RunMode = RunMode.Async)] + [Summary("get user top 10")] + public async Task Rank() { await ReplyAsync("this will take a moment..."); var guildKey = Context.Guild.Id.ToString(); - var guildMessages = (int)redis.StringGet(guildKey + "-messages"); + var guildMessages = (int) redis.StringGet(guildKey + "-messages"); var allGuildUsers = await Context.Guild.GetUsersAsync(); var unsortedDict = new Dictionary(); - foreach(var user in allGuildUsers) + foreach (var user in allGuildUsers) { var key = Context.Guild.Id + "-" + user.Id; - var messages = (int)redis.StringGet(key + "-messages"); - if(messages > 0) { + var messages = (int) redis.StringGet(key + "-messages"); + if (messages > 0) unsortedDict.Add($"{user.Username}#{user.Discriminator}", messages); - } } var sortedDict = unsortedDict.OrderByDescending(x => x.Value); var reply = new StringBuilder(); reply.AppendLine($"Total Messages on {Context.Guild.Name}: {guildMessages}"); var count = 1; - foreach(KeyValuePair entry in sortedDict) - { - if(count < 11){ - var percent = Math.Round((double)(100 * entry.Value) / guildMessages, 2); + foreach (var entry in sortedDict) + if (count < 11) + { + var percent = Math.Round((double) (100 * entry.Value) / guildMessages, 2); reply.AppendLine($"#{count} - **{entry.Key}** - {percent}% of total - {entry.Value} messages"); count++; - } else { + } + else + { break; } - } await ReplyAsync(reply.ToString()); } } diff --git a/Geekbot.net/Modules/Youtube.cs b/Geekbot.net/Modules/Youtube.cs index 3127ff4..afb7027 100644 --- a/Geekbot.net/Modules/Youtube.cs +++ b/Geekbot.net/Modules/Youtube.cs @@ -10,13 +10,15 @@ namespace Geekbot.net.Modules public class Youtube : ModuleBase { private readonly IDatabase redis; + public Youtube(IDatabase redis) { this.redis = redis; } - [Command("yt", RunMode = RunMode.Async), Summary("Search for something on youtube.")] - public async Task Yt([Remainder, Summary("A Song Title")] string searchQuery) + [Command("yt", RunMode = RunMode.Async)] + [Summary("Search for something on youtube.")] + public async Task Yt([Remainder] [Summary("Title")] string searchQuery) { var key = redis.StringGet("youtubeKey"); if (key.IsNullOrEmpty) @@ -27,10 +29,10 @@ namespace Geekbot.net.Modules try { - var youtubeService = new YouTubeService(new BaseClientService.Initializer() + var youtubeService = new YouTubeService(new BaseClientService.Initializer { ApiKey = key.ToString(), - ApplicationName = this.GetType().ToString() + ApplicationName = GetType().ToString() }); var searchListRequest = youtubeService.Search.List("snippet"); @@ -49,7 +51,8 @@ namespace Geekbot.net.Modules await ReplyAsync("Something went wrong... informing my senpai..."); var botOwner = Context.Guild.GetUserAsync(ulong.Parse(redis.StringGet("botOwner"))).Result; var dm = await botOwner.GetOrCreateDMChannelAsync(); - await dm.SendMessageAsync($"Something went wrong while getting a video from youtube:\r\n```\r\n{e.Message}\r\n```"); + await dm.SendMessageAsync( + $"Something went wrong while getting a video from youtube:\r\n```\r\n{e.Message}\r\n```"); } } } diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 51699e1..319db04 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -1,30 +1,25 @@ using System; using System.Reflection; using System.Threading.Tasks; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; using Discord; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Lib; -using Geekbot.net.Modules; -using RestSharp; +using Microsoft.Extensions.DependencyInjection; using StackExchange.Redis; namespace Geekbot.net { - class Program + internal class Program { - private CommandService commands; private DiscordSocketClient client; + private CommandService commands; private IDatabase redis; - private RedisValue token; private IServiceCollection services; private IServiceProvider servicesProvider; + private RedisValue token; - private static void Main(string[] args) + private static void Main() { Console.WriteLine(@" ____ _____ _____ _ ______ ___ _____"); Console.WriteLine(@" / ___| ____| ____| |/ / __ ) / _ \\_ _|"); @@ -71,10 +66,10 @@ namespace Geekbot.net var fortunes = new FortunesProvider(); var checkEmImages = new CheckEmImageProvider(); var RandomClient = new Random(); + services.AddSingleton(redis); + services.AddSingleton(RandomClient); services.AddSingleton(fortunes); services.AddSingleton(checkEmImages); - services.AddSingleton(RandomClient); - services.AddSingleton(redis); Console.WriteLine("* Connecting to Discord"); @@ -101,6 +96,7 @@ namespace Geekbot.net client.MessageReceived += HandleMessageReceived; client.UserJoined += HandleUserJoined; await commands.AddModulesAsync(Assembly.GetEntryAssembly()); + services.AddSingleton(commands); servicesProvider = services.BuildServiceProvider(); Console.WriteLine("* Done and ready for use\n"); @@ -116,9 +112,7 @@ namespace Geekbot.net public async Task isConnected() { while (!client.ConnectionState.Equals(ConnectionState.Connected)) - { await Task.Delay(25); - } return true; } @@ -127,7 +121,7 @@ namespace Geekbot.net var message = messageParam as SocketUserMessage; if (message == null) return; if (message.Author.IsBot) return; - int argPos = 0; + var argPos = 0; var lowCaseMsg = message.ToString().ToLower(); if (lowCaseMsg.StartsWith("ping")) { @@ -139,7 +133,8 @@ namespace Geekbot.net await message.Channel.SendMessageAsync("hui!!!"); return; } - if (!(message.HasCharPrefix('!', ref argPos) || message.HasMentionPrefix(client.CurrentUser, ref argPos))) return; + if (!(message.HasCharPrefix('!', ref argPos) || + message.HasMentionPrefix(client.CurrentUser, ref argPos))) return; var context = new CommandContext(client, message); Task.Run(async () => await commands.ExecuteAsync(context, argPos, servicesProvider)); } @@ -148,14 +143,15 @@ namespace Geekbot.net { var message = messsageParam; if (message == null) return; - - var channel = (SocketGuildChannel)message.Channel; - - Console.WriteLine(channel.Guild.Name + " - " + message.Channel + " - " + message.Author.Username + " - " + message.Content); - + var statsRecorder = new StatsRecorder(message, redis); Task.Run(async () => await statsRecorder.UpdateUserRecordAsync()); Task.Run(async () => await statsRecorder.UpdateGuildRecordAsync()); + + if (message.Author.Id == client.CurrentUser.Id) return; + var channel = (SocketGuildChannel) message.Channel; + Console.WriteLine(channel.Guild.Name + " - " + message.Channel + " - " + message.Author.Username + " - " + + message.Content); } public async Task HandleUserJoined(SocketGuildUser user) @@ -171,4 +167,4 @@ namespace Geekbot.net } } } -} +} \ No newline at end of file From e57b80d4b4b8bf4ce2a818d72cdd84573d59f664 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Mon, 18 Sep 2017 23:31:11 +0200 Subject: [PATCH 023/553] Stats is stats again, dices now have modifiers --- Geekbot.net/Modules/Dice.cs | 26 ++++++++++++++++++++++---- Geekbot.net/Modules/UserInfo.cs | 2 +- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/Geekbot.net/Modules/Dice.cs b/Geekbot.net/Modules/Dice.cs index b44c7e8..4c76c3e 100644 --- a/Geekbot.net/Modules/Dice.cs +++ b/Geekbot.net/Modules/Dice.cs @@ -19,33 +19,51 @@ namespace Geekbot.net.Modules public async Task RollCommand([Remainder] [Summary("diceType")] string diceType = "1d6") { var dice = diceType.Split("d"); + var maxAndMod = dice[1].Split("+"); if (dice.Length != 2 || !int.TryParse(dice[0], out int times) - || !int.TryParse(dice[1], out int max)) + || !int.TryParse(maxAndMod[0], out int max)) { - await ReplyAsync("That is not a valid dice, examples are: 1d20, 1d6, 2d10, 5d12, etc..."); + await ReplyAsync("That is not a valid dice, examples are: 1d20, 1d6, 2d10, 5d12, 1d20+5, 1d6+2, etc..."); return; } - Console.WriteLine($"Max: {max} - Times {times}"); + + int modifier = 0; + if (maxAndMod.Length == 2 && !int.TryParse(maxAndMod[1], out modifier) || maxAndMod.Length > 2) + { + await ReplyAsync("That is not a valid dice, examples are: 1d20, 1d6, 2d10, 5d12, 1d20+5, 1d6+2, etc..."); + return; + } + if (times > 10 && !(times < 0)) { await ReplyAsync("You can only roll between 1 and 10 dices"); return; } + if (max > 100 && !(max < 1)) { await ReplyAsync("The dice must have between 1 and 100 sides"); return; } + var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder() .WithIconUrl(Context.User.GetAvatarUrl()) .WithName(Context.User.Username)); eb.WithColor(new Color(133, 189, 219)); eb.Title = $":game_die: Dice Roll - Type {diceType} :game_die:"; + + var total = 0; for (var i = 0; i < times; i++) - eb.AddInlineField($"Dice {i + 1}", rnd.Next(1, max)); + { + var roll = rnd.Next(1, max); + eb.AddInlineField($"Dice {i + 1}", roll); + total = total + roll; + } + + eb.AddField("Total", modifier == 0 ? $"{total}" : $"{total} (+{modifier})"); await ReplyAsync("", false, eb.Build()); } } diff --git a/Geekbot.net/Modules/UserInfo.cs b/Geekbot.net/Modules/UserInfo.cs index 1af885d..1f94e45 100644 --- a/Geekbot.net/Modules/UserInfo.cs +++ b/Geekbot.net/Modules/UserInfo.cs @@ -19,7 +19,7 @@ namespace Geekbot.net.Modules this.redis = redis; } - [Command("user", RunMode = RunMode.Async)] + [Command("stats", RunMode = RunMode.Async)] [Summary("Get information about this user")] public async Task User([Summary("@someone")] IUser user = null) { From 3a5a0df846ed74e3c33843a3d21e0a576fec02ee Mon Sep 17 00:00:00 2001 From: Runebaas Date: Tue, 19 Sep 2017 18:53:59 +0200 Subject: [PATCH 024/553] Add google command, small change in dice and help commands --- Geekbot.net/Geekbot.net.csproj | 84 +++++++++++++++++----------------- Geekbot.net/Modules/Dice.cs | 4 +- Geekbot.net/Modules/Google.cs | 17 +++++++ Geekbot.net/Modules/Help.cs | 2 +- Geekbot.net/Modules/Ping.cs | 3 +- Geekbot.net/Program.cs | 1 + 6 files changed, 65 insertions(+), 46 deletions(-) create mode 100644 Geekbot.net/Modules/Google.cs diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 5e543ab..4e2e121 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -1,43 +1,43 @@ - - - Exe - netcoreapp2.0 - derp.ico - 1.1.0 - Pizza and Coffee Studios - Pizza and Coffee Studios - A Discord bot - https://github.com/pizzaandcoffee/Geekbot.net - - - - 1.0.2 - - - 1.29.1.976 - - - 1.5.0.1 - - - - - - - 105.2.3 - - - 1.2.6 - - - 4.3.2 - - - - 4.3.0 - - - 4.3.0 - - + + + Exe + netcoreapp2.0 + derp.ico + 1.1.0 + Pizza and Coffee Studios + Pizza and Coffee Studios + A Discord bot + https://github.com/pizzaandcoffee/Geekbot.net + + + + 1.0.2 + + + 1.29.1.976 + + + 1.5.0.1 + + + + + + + 105.2.3 + + + 1.2.6 + + + 4.3.2 + + + + 4.3.0 + + + 4.3.0 + + \ No newline at end of file diff --git a/Geekbot.net/Modules/Dice.cs b/Geekbot.net/Modules/Dice.cs index 4c76c3e..c6409fc 100644 --- a/Geekbot.net/Modules/Dice.cs +++ b/Geekbot.net/Modules/Dice.cs @@ -63,8 +63,8 @@ namespace Geekbot.net.Modules total = total + roll; } - eb.AddField("Total", modifier == 0 ? $"{total}" : $"{total} (+{modifier})"); + eb.AddField("Total", modifier == 0 ? $"{total}" : $"{total + modifier} ({total} +{modifier})"); await ReplyAsync("", false, eb.Build()); } } -} \ No newline at end of file +} diff --git a/Geekbot.net/Modules/Google.cs b/Geekbot.net/Modules/Google.cs new file mode 100644 index 0000000..e2205aa --- /dev/null +++ b/Geekbot.net/Modules/Google.cs @@ -0,0 +1,17 @@ +using System.Threading.Tasks; +using Discord.Commands; + +namespace Geekbot.net.Modules +{ + public class Google : ModuleBase + { + [Command("google", RunMode = RunMode.Async)] + [Summary("Google Something.")] + public async Task Eyes([Remainder, Summary("SearchText")] string searchText) + { + var url = $"http://lmgtfy.com/?q={searchText.Replace(' ', '+')}"; + + await ReplyAsync($"Please click here :unamused:\r\n{url}"); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Modules/Help.cs b/Geekbot.net/Modules/Help.cs index 9dd80a5..57feb87 100644 --- a/Geekbot.net/Modules/Help.cs +++ b/Geekbot.net/Modules/Help.cs @@ -29,7 +29,7 @@ namespace Geekbot.net.Modules if (!param.Contains("admin")) if (cmd.Parameters.Any()) sb.AppendLine(tp(param, 15) + - tp(string.Join(",", cmd.Parameters.Select(e => e.Summary)), 19) + + tp(string.Join(" ", cmd.Parameters.Select(e => e.Summary)), 19) + cmd.Summary); else sb.AppendLine(tp(param, 34) + cmd.Summary); diff --git a/Geekbot.net/Modules/Ping.cs b/Geekbot.net/Modules/Ping.cs index 2ccca12..a3ba98d 100644 --- a/Geekbot.net/Modules/Ping.cs +++ b/Geekbot.net/Modules/Ping.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Linq; +using System.Threading.Tasks; using Discord.Commands; namespace Geekbot.net.Modules diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 319db04..38bea6a 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -42,6 +42,7 @@ namespace Geekbot.net { var redisMultiplexer = ConnectionMultiplexer.Connect("127.0.0.1:6379"); redis = redisMultiplexer.GetDatabase(6); + Console.WriteLine("- Connected to Redis (db6)"); } catch (Exception) { From d88e9a6f188a9135b038f8d644ac156904e5d708 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Tue, 19 Sep 2017 20:39:49 +0200 Subject: [PATCH 025/553] Pandas, rip restsharp, stuff --- Geekbot.net/Geekbot.net.csproj | 84 ++++++++++++------------- Geekbot.net/Lib/CheckEmImageProvider.cs | 6 +- Geekbot.net/Lib/FortunesProvider.cs | 12 +--- Geekbot.net/Lib/PandaProvider.cs | 40 ++++++++++++ Geekbot.net/Modules/Cat.cs | 25 ++++++-- Geekbot.net/Modules/CheckEm.cs | 1 - Geekbot.net/Modules/Dog.cs | 23 +++++-- Geekbot.net/Modules/Panda.cs | 23 +++++++ Geekbot.net/Program.cs | 30 ++++++--- Geekbot.net/Storage/pandas | 11 ++++ 10 files changed, 182 insertions(+), 73 deletions(-) create mode 100644 Geekbot.net/Lib/PandaProvider.cs create mode 100644 Geekbot.net/Modules/Panda.cs create mode 100644 Geekbot.net/Storage/pandas diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 4e2e121..5e543ab 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -1,43 +1,43 @@ - - - Exe - netcoreapp2.0 - derp.ico - 1.1.0 - Pizza and Coffee Studios - Pizza and Coffee Studios - A Discord bot - https://github.com/pizzaandcoffee/Geekbot.net - - - - 1.0.2 - - - 1.29.1.976 - - - 1.5.0.1 - - - - - - - 105.2.3 - - - 1.2.6 - - - 4.3.2 - - - - 4.3.0 - - - 4.3.0 - - + + + Exe + netcoreapp2.0 + derp.ico + 1.1.0 + Pizza and Coffee Studios + Pizza and Coffee Studios + A Discord bot + https://github.com/pizzaandcoffee/Geekbot.net + + + + 1.0.2 + + + 1.29.1.976 + + + 1.5.0.1 + + + + + + + 105.2.3 + + + 1.2.6 + + + 4.3.2 + + + + 4.3.0 + + + 4.3.0 + + \ No newline at end of file diff --git a/Geekbot.net/Lib/CheckEmImageProvider.cs b/Geekbot.net/Lib/CheckEmImageProvider.cs index 5ead4a2..b29a6a2 100644 --- a/Geekbot.net/Lib/CheckEmImageProvider.cs +++ b/Geekbot.net/Lib/CheckEmImageProvider.cs @@ -9,7 +9,7 @@ namespace Geekbot.net.Lib private readonly Random rnd; private readonly int totalCheckEmImages; - public CheckEmImageProvider() + public CheckEmImageProvider(Random rnd) { var path = Path.GetFullPath("./Storage/checkEmPics"); if (File.Exists(path)) @@ -17,8 +17,8 @@ namespace Geekbot.net.Lib var rawCheckEmPics = File.ReadAllText(path); checkEmImageArray = rawCheckEmPics.Split("\n"); totalCheckEmImages = checkEmImageArray.Length; - rnd = new Random(); - Console.WriteLine($"- Loaded {totalCheckEmImages} CheckEm Images"); + this.rnd = rnd; + Console.WriteLine($"-- Loaded {totalCheckEmImages} CheckEm Images"); } else { diff --git a/Geekbot.net/Lib/FortunesProvider.cs b/Geekbot.net/Lib/FortunesProvider.cs index 614d018..2c6a2e5 100644 --- a/Geekbot.net/Lib/FortunesProvider.cs +++ b/Geekbot.net/Lib/FortunesProvider.cs @@ -9,7 +9,7 @@ namespace Geekbot.net.Lib private readonly Random rnd; private readonly int totalFortunes; - public FortunesProvider() + public FortunesProvider(Random rnd) { var path = Path.GetFullPath("./Storage/fortunes"); if (File.Exists(path)) @@ -17,8 +17,8 @@ namespace Geekbot.net.Lib var rawFortunes = File.ReadAllText(path); fortuneArray = rawFortunes.Split("%"); totalFortunes = fortuneArray.Length; - rnd = new Random(); - Console.WriteLine($"- Loaded {totalFortunes} Fortunes"); + this.rnd = rnd; + Console.WriteLine($"-- Loaded {totalFortunes} Fortunes"); } else { @@ -31,16 +31,10 @@ namespace Geekbot.net.Lib { return fortuneArray[rnd.Next(0, totalFortunes)]; } - - public string GetFortune(int id) - { - return fortuneArray[id]; - } } public interface IFortunesProvider { string GetRandomFortune(); - string GetFortune(int id); } } \ No newline at end of file diff --git a/Geekbot.net/Lib/PandaProvider.cs b/Geekbot.net/Lib/PandaProvider.cs new file mode 100644 index 0000000..9a392e5 --- /dev/null +++ b/Geekbot.net/Lib/PandaProvider.cs @@ -0,0 +1,40 @@ +using System; +using System.IO; + +namespace Geekbot.net.Lib +{ + public class PandaProvider : IPandaProvider + { + private readonly string[] PandaArray; + private readonly Random rnd; + private readonly int totalPandas; + + public PandaProvider(Random rnd) + { + var path = Path.GetFullPath("./Storage/pandas"); + if (File.Exists(path)) + { + var rawFortunes = File.ReadAllText(path); + PandaArray = rawFortunes.Split("\n"); + totalPandas = PandaArray.Length; + this.rnd = rnd; + Console.WriteLine($"-- Loaded {totalPandas} Panda Images"); + } + else + { + Console.WriteLine("Pandas File not found"); + Console.WriteLine($"Path should be {path}"); + } + } + + public string GetRandomPanda() + { + return PandaArray[rnd.Next(0, totalPandas)]; + } + } + + public interface IPandaProvider + { + string GetRandomPanda(); + } +} \ No newline at end of file diff --git a/Geekbot.net/Modules/Cat.cs b/Geekbot.net/Modules/Cat.cs index fe134ad..bf6fa81 100644 --- a/Geekbot.net/Modules/Cat.cs +++ b/Geekbot.net/Modules/Cat.cs @@ -1,6 +1,8 @@ -using System.Threading.Tasks; +using System; +using System.Net.Http; +using System.Threading.Tasks; using Discord.Commands; -using RestSharp; +using Newtonsoft.Json; namespace Geekbot.net.Modules { @@ -10,10 +12,23 @@ namespace Geekbot.net.Modules [Summary("Return a random image of a cat.")] public async Task Say() { - var catClient = new RestClient("http://random.cat"); - var request = new RestRequest("meow.php", Method.GET); + using (var client = new HttpClient()) + { + try + { + client.BaseAddress = new Uri("http://random.cat"); + var response = await client.GetAsync("/meow.php"); + response.EnsureSuccessStatusCode(); - catClient.ExecuteAsync(request, async response => { await ReplyAsync(response.Data.file); }); + var stringResponse = await response.Content.ReadAsStringAsync(); + var catFile = JsonConvert.DeserializeObject(stringResponse); + await ReplyAsync(catFile.file); + } + catch (HttpRequestException e) + { + await ReplyAsync($"Seems like the dog cought the cat (error occured)\r\n{e.Message}"); + } + } } } diff --git a/Geekbot.net/Modules/CheckEm.cs b/Geekbot.net/Modules/CheckEm.cs index 0d72241..1751462 100644 --- a/Geekbot.net/Modules/CheckEm.cs +++ b/Geekbot.net/Modules/CheckEm.cs @@ -28,7 +28,6 @@ namespace Geekbot.net.Modules var dubtriqua = ""; var ns = GetIntArray(number); - Console.WriteLine(ns.Length); if (ns[7] == ns[6]) { dubtriqua = "DUBS"; diff --git a/Geekbot.net/Modules/Dog.cs b/Geekbot.net/Modules/Dog.cs index 80fd250..326e4ac 100644 --- a/Geekbot.net/Modules/Dog.cs +++ b/Geekbot.net/Modules/Dog.cs @@ -1,7 +1,8 @@ using System; +using System.Net.Http; using System.Threading.Tasks; using Discord.Commands; -using RestSharp; +using Newtonsoft.Json; namespace Geekbot.net.Modules { @@ -11,11 +12,23 @@ namespace Geekbot.net.Modules [Summary("Return a random image of a dog.")] public async Task Say() { - var dogClient = new RestClient("http://random.dog"); - var request = new RestRequest("woof.json", Method.GET); - Console.WriteLine(dogClient.BaseUrl); + using (var client = new HttpClient()) + { + try + { + client.BaseAddress = new Uri("http://random.dog"); + var response = await client.GetAsync("/woof.json"); + response.EnsureSuccessStatusCode(); - dogClient.ExecuteAsync(request, async response => { await ReplyAsync(response.Data.url); }); + var stringResponse = await response.Content.ReadAsStringAsync(); + var dogFile = JsonConvert.DeserializeObject(stringResponse); + await ReplyAsync(dogFile.url); + } + catch (HttpRequestException e) + { + await ReplyAsync($"Seems like the dog got lost (error occured)\r\n{e.Message}"); + } + } } } diff --git a/Geekbot.net/Modules/Panda.cs b/Geekbot.net/Modules/Panda.cs new file mode 100644 index 0000000..515dfed --- /dev/null +++ b/Geekbot.net/Modules/Panda.cs @@ -0,0 +1,23 @@ +using System.Threading.Tasks; +using Discord.Commands; +using Geekbot.net.Lib; + +namespace Geekbot.net.Modules +{ + public class Panda : ModuleBase + { + private readonly IPandaProvider pandaImages; + + public Panda(IPandaProvider pandaImages) + { + this.pandaImages = pandaImages; + } + + [Command("panda", RunMode = RunMode.Async)] + [Summary("Get a random panda")] + public async Task PandaCommand() + { + await ReplyAsync(pandaImages.GetRandomPanda()); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 38bea6a..edb18c1 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -1,4 +1,5 @@ using System; +using System.Net.NetworkInformation; using System.Reflection; using System.Threading.Tasks; using Discord; @@ -35,6 +36,15 @@ namespace Geekbot.net public async Task MainAsync() { Console.WriteLine("* Initing Stuff"); + + var ping = new Ping().Send("8.8.8.8"); + if(ping.Status != IPStatus.Success) + { + Console.WriteLine("It seems that you are offline"); + Console.WriteLine("Please connect to the Internet"); + Environment.Exit(101); + } + client = new DiscordSocketClient(); commands = new CommandService(); @@ -42,12 +52,12 @@ namespace Geekbot.net { var redisMultiplexer = ConnectionMultiplexer.Connect("127.0.0.1:6379"); redis = redisMultiplexer.GetDatabase(6); - Console.WriteLine("- Connected to Redis (db6)"); + Console.WriteLine("-- Connected to Redis (db6)"); } catch (Exception) { Console.WriteLine("Start Redis pls..."); - Environment.Exit(1); + Environment.Exit(102); } token = redis.StringGet("discordToken"); @@ -64,13 +74,15 @@ namespace Geekbot.net } services = new ServiceCollection(); - var fortunes = new FortunesProvider(); - var checkEmImages = new CheckEmImageProvider(); var RandomClient = new Random(); + var fortunes = new FortunesProvider(RandomClient); + var checkEmImages = new CheckEmImageProvider(RandomClient); + var pandaImages = new PandaProvider(RandomClient); services.AddSingleton(redis); services.AddSingleton(RandomClient); services.AddSingleton(fortunes); services.AddSingleton(checkEmImages); + services.AddSingleton(pandaImages); Console.WriteLine("* Connecting to Discord"); @@ -106,7 +118,7 @@ namespace Geekbot.net catch (AggregateException) { Console.WriteLine("Could not connect to discord..."); - Environment.Exit(1); + Environment.Exit(103); } } @@ -137,7 +149,7 @@ namespace Geekbot.net if (!(message.HasCharPrefix('!', ref argPos) || message.HasMentionPrefix(client.CurrentUser, ref argPos))) return; var context = new CommandContext(client, message); - Task.Run(async () => await commands.ExecuteAsync(context, argPos, servicesProvider)); + var commandExec = commands.ExecuteAsync(context, argPos, servicesProvider); } public async Task HandleMessageReceived(SocketMessage messsageParam) @@ -146,13 +158,15 @@ namespace Geekbot.net if (message == null) return; var statsRecorder = new StatsRecorder(message, redis); - Task.Run(async () => await statsRecorder.UpdateUserRecordAsync()); - Task.Run(async () => await statsRecorder.UpdateGuildRecordAsync()); + var userRec = statsRecorder.UpdateUserRecordAsync(); + var guildRec = statsRecorder.UpdateGuildRecordAsync(); if (message.Author.Id == client.CurrentUser.Id) return; var channel = (SocketGuildChannel) message.Channel; Console.WriteLine(channel.Guild.Name + " - " + message.Channel + " - " + message.Author.Username + " - " + message.Content); + await userRec; + await guildRec; } public async Task HandleUserJoined(SocketGuildUser user) diff --git a/Geekbot.net/Storage/pandas b/Geekbot.net/Storage/pandas new file mode 100644 index 0000000..9d5046c --- /dev/null +++ b/Geekbot.net/Storage/pandas @@ -0,0 +1,11 @@ +https://upload.wikimedia.org/wikipedia/commons/thumb/0/0f/Grosser_Panda.JPG/1200px-Grosser_Panda.JPG +https://c402277.ssl.cf1.rackcdn.com/photos/13100/images/featured_story/BIC_128.png?1485963152 +https://nationalzoo.si.edu/sites/default/files/styles/slide_1400x700/public/support/adopt/giantpanda-03.jpg?itok=3EdEO0Vi +https://media4.s-nbcnews.com/j/newscms/2016_36/1685951/ss-160826-twip-05_8cf6d4cb83758449fd400c7c3d71aa1f.nbcnews-ux-2880-1000.jpg +https://ichef-1.bbci.co.uk/news/660/cpsprodpb/169F6/production/_91026629_gettyimages-519508400.jpg +https://cdn.history.com/sites/2/2017/03/GettyImages-157278376.jpg +https://www.pandasinternational.org/wptemp/wp-content/uploads/2012/10/slider1.jpg +https://tctechcrunch2011.files.wordpress.com/2015/11/panda.jpg +http://www.nationalgeographic.com/content/dam/magazine/rights-exempt/2016/08/departments/panda-mania-12.jpg +http://animals.sandiegozoo.org/sites/default/files/2016-09/panda1_10.jpg +http://kids.nationalgeographic.com/content/dam/kids/photos/animals/Mammals/A-G/giant-panda-eating.adapt.945.1.jpg \ No newline at end of file From 16f78ddea4d78d54cd74f08408673a8a08228ae4 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Tue, 19 Sep 2017 20:41:28 +0200 Subject: [PATCH 026/553] remove online check --- Geekbot.net/Program.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index edb18c1..f9e250f 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -37,14 +37,6 @@ namespace Geekbot.net { Console.WriteLine("* Initing Stuff"); - var ping = new Ping().Send("8.8.8.8"); - if(ping.Status != IPStatus.Success) - { - Console.WriteLine("It seems that you are offline"); - Console.WriteLine("Please connect to the Internet"); - Environment.Exit(101); - } - client = new DiscordSocketClient(); commands = new CommandService(); From 7f833b05d357b1e2b2e9f40082120881ff829219 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Fri, 22 Sep 2017 21:07:04 +0200 Subject: [PATCH 027/553] Updating readme.me --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 90ef904..c38723c 100644 --- a/readme.md +++ b/readme.md @@ -6,7 +6,7 @@ You can invite Geekbot to your server with [this link](https://discordapp.com/oa ### Building -Geekbot.net Requires dotnet core 1.0.1 and dotnet core cli 1.1 +Geekbot.net Requires dotnet core 2.0.0 and dotnet core cli 2.0.0 `dotnet restore` From a7e3bb957f3755bb6b6b20a279eecf0c057ba7c7 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sun, 24 Sep 2017 22:45:49 +0200 Subject: [PATCH 028/553] Update dice to take multiple dices and take less space in the chat --- Geekbot.net/Modules/Dice.cs | 140 +++++++++++++++++++++++++----------- 1 file changed, 97 insertions(+), 43 deletions(-) diff --git a/Geekbot.net/Modules/Dice.cs b/Geekbot.net/Modules/Dice.cs index c6409fc..698e825 100644 --- a/Geekbot.net/Modules/Dice.cs +++ b/Geekbot.net/Modules/Dice.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; using System.Threading.Tasks; -using Discord; using Discord.Commands; namespace Geekbot.net.Modules @@ -16,55 +18,107 @@ namespace Geekbot.net.Modules [Command("dice", RunMode = RunMode.Async)] [Summary("Roll a dice.")] - public async Task RollCommand([Remainder] [Summary("diceType")] string diceType = "1d6") + public async Task RollCommand([Remainder] [Summary("diceType")] string diceType = "1d20") { - var dice = diceType.Split("d"); - var maxAndMod = dice[1].Split("+"); + var splitedDices = diceType.Split("+"); + var dices = new List(); + var mod = 0; + foreach (var i in splitedDices) + { + var dice = toDice(i); + if (dice.sides != 0 && dice.times != 0) + { + dices.Add(dice); + } + else if (dice.mod != 0) + { + if (mod != 0) + { + await ReplyAsync("You can only have one mod"); + return; + } + mod = dice.mod; + } + } - if (dice.Length != 2 - || !int.TryParse(dice[0], out int times) - || !int.TryParse(maxAndMod[0], out int max)) + if (!dices.Any()) { - await ReplyAsync("That is not a valid dice, examples are: 1d20, 1d6, 2d10, 5d12, 1d20+5, 1d6+2, etc..."); + await ReplyAsync( + "That is not a valid dice, examples are: 1d20, 1d6, 2d6, 1d6+2, 1d6+2d8+1d20+6, etc..."); return; } - - int modifier = 0; - if (maxAndMod.Length == 2 && !int.TryParse(maxAndMod[1], out modifier) || maxAndMod.Length > 2) - { - await ReplyAsync("That is not a valid dice, examples are: 1d20, 1d6, 2d10, 5d12, 1d20+5, 1d6+2, etc..."); - return; - } - - if (times > 10 && !(times < 0)) - { - await ReplyAsync("You can only roll between 1 and 10 dices"); - return; - } - - if (max > 100 && !(max < 1)) - { - await ReplyAsync("The dice must have between 1 and 100 sides"); - return; - } - - var eb = new EmbedBuilder(); - eb.WithAuthor(new EmbedAuthorBuilder() - .WithIconUrl(Context.User.GetAvatarUrl()) - .WithName(Context.User.Username)); - eb.WithColor(new Color(133, 189, 219)); - eb.Title = $":game_die: Dice Roll - Type {diceType} :game_die:"; - + + var rep = new StringBuilder(); + rep.AppendLine($":game_die: {Context.User.Mention}"); + rep.Append("**Result:** "); + var resultStrings = new List(); var total = 0; - for (var i = 0; i < times; i++) + var extraText = ""; + foreach (var dice in dices) { - var roll = rnd.Next(1, max); - eb.AddInlineField($"Dice {i + 1}", roll); - total = total + roll; + var results = new List(); + for (var i = 0; i < dice.times; i++) + { + var roll = rnd.Next(1, dice.sides); + total += roll; + results.Add(roll); + if (roll == dice.sides) + { + extraText = "**Critical Hit!**"; + } + if (roll == 1) + { + extraText = "**Critical Fail!**"; + } + } + resultStrings.Add($"{dice.diceType} ({string.Join(",", results)})"); } - - eb.AddField("Total", modifier == 0 ? $"{total}" : $"{total + modifier} ({total} +{modifier})"); - await ReplyAsync("", false, eb.Build()); + rep.Append(string.Join(" + ", resultStrings)); + if (mod != 0) + { + rep.Append($" + {mod}"); + total += mod; + } + rep.AppendLine(); + rep.AppendLine($"**Total:** {total}"); + if (extraText != "") + { + rep.AppendLine(extraText); + } + await ReplyAsync(rep.ToString()); + } + + private DiceTypeDto toDice(string dice) + { + var diceParts = dice.Split('d'); + if (diceParts.Length == 2 + && int.TryParse(diceParts[0], out int times) + && int.TryParse(diceParts[1], out int max)) + { + return new DiceTypeDto() + { + diceType = dice, + times = times, + sides = max + }; + } + if (dice.Length == 1 + && int.TryParse(diceParts[0], out int mod)) + { + return new DiceTypeDto() + { + mod = mod + }; + } + return new DiceTypeDto(); } } -} + + class DiceTypeDto + { + public string diceType { get; set; } + public int times { get; set; } + public int sides { get; set; } + public int mod { get; set; } + } +} \ No newline at end of file From 79e52774b8ed7d202b0d78b98b9b490e90aa1d5b Mon Sep 17 00:00:00 2001 From: Runebaas Date: Tue, 26 Sep 2017 13:02:38 +0200 Subject: [PATCH 029/553] Add Serilog --- .gitignore | 2 + Geekbot.net/Geekbot.net.csproj | 15 +++---- Geekbot.net/Lib/CheckEmImageProvider.cs | 9 ++-- Geekbot.net/Lib/FortunesProvider.cs | 9 ++-- Geekbot.net/Lib/PandaProvider.cs | 11 ++--- Geekbot.net/Logs/.keep | 0 Geekbot.net/Program.cs | 60 +++++++++++++++---------- 7 files changed, 60 insertions(+), 46 deletions(-) create mode 100755 Geekbot.net/Logs/.keep diff --git a/.gitignore b/.gitignore index bec8c02..2e43789 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ Backup/ UpgradeLog.htm .idea .vscode +Geekbot.net/Logs/* +!/Geekbot.net/Logs/.keep diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 5e543ab..37f26fa 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -13,9 +13,7 @@ 1.0.2 - - 1.29.1.976 - + 1.5.0.1 @@ -23,15 +21,14 @@ - - 105.2.3 - + + + + 1.2.6 - - 4.3.2 - + 4.3.0 diff --git a/Geekbot.net/Lib/CheckEmImageProvider.cs b/Geekbot.net/Lib/CheckEmImageProvider.cs index b29a6a2..8b66194 100644 --- a/Geekbot.net/Lib/CheckEmImageProvider.cs +++ b/Geekbot.net/Lib/CheckEmImageProvider.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using Serilog; namespace Geekbot.net.Lib { @@ -9,7 +10,7 @@ namespace Geekbot.net.Lib private readonly Random rnd; private readonly int totalCheckEmImages; - public CheckEmImageProvider(Random rnd) + public CheckEmImageProvider(Random rnd, ILogger logger) { var path = Path.GetFullPath("./Storage/checkEmPics"); if (File.Exists(path)) @@ -18,12 +19,12 @@ namespace Geekbot.net.Lib checkEmImageArray = rawCheckEmPics.Split("\n"); totalCheckEmImages = checkEmImageArray.Length; this.rnd = rnd; - Console.WriteLine($"-- Loaded {totalCheckEmImages} CheckEm Images"); + logger.Information($"-- Loaded {totalCheckEmImages} CheckEm Images"); } else { - Console.WriteLine("checkEmPics File not found"); - Console.WriteLine($"Path should be {path}"); + logger.Error("checkEmPics File not found"); + logger.Error($"Path should be {path}"); } } diff --git a/Geekbot.net/Lib/FortunesProvider.cs b/Geekbot.net/Lib/FortunesProvider.cs index 2c6a2e5..f485952 100644 --- a/Geekbot.net/Lib/FortunesProvider.cs +++ b/Geekbot.net/Lib/FortunesProvider.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using Serilog; namespace Geekbot.net.Lib { @@ -9,7 +10,7 @@ namespace Geekbot.net.Lib private readonly Random rnd; private readonly int totalFortunes; - public FortunesProvider(Random rnd) + public FortunesProvider(Random rnd, ILogger logger) { var path = Path.GetFullPath("./Storage/fortunes"); if (File.Exists(path)) @@ -18,12 +19,12 @@ namespace Geekbot.net.Lib fortuneArray = rawFortunes.Split("%"); totalFortunes = fortuneArray.Length; this.rnd = rnd; - Console.WriteLine($"-- Loaded {totalFortunes} Fortunes"); + logger.Information($"-- Loaded {totalFortunes} Fortunes"); } else { - Console.WriteLine("Fortunes File not found"); - Console.WriteLine($"Path should be {path}"); + logger.Error("Fortunes File not found"); + logger.Error($"Path should be {path}"); } } diff --git a/Geekbot.net/Lib/PandaProvider.cs b/Geekbot.net/Lib/PandaProvider.cs index 9a392e5..6ac927a 100644 --- a/Geekbot.net/Lib/PandaProvider.cs +++ b/Geekbot.net/Lib/PandaProvider.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using Serilog; namespace Geekbot.net.Lib { @@ -9,7 +10,7 @@ namespace Geekbot.net.Lib private readonly Random rnd; private readonly int totalPandas; - public PandaProvider(Random rnd) + public PandaProvider(Random rnd, ILogger logger) { var path = Path.GetFullPath("./Storage/pandas"); if (File.Exists(path)) @@ -18,12 +19,12 @@ namespace Geekbot.net.Lib PandaArray = rawFortunes.Split("\n"); totalPandas = PandaArray.Length; this.rnd = rnd; - Console.WriteLine($"-- Loaded {totalPandas} Panda Images"); + logger.Information($"-- Loaded {totalPandas} Panda Images"); } else { - Console.WriteLine("Pandas File not found"); - Console.WriteLine($"Path should be {path}"); + logger.Error("Pandas File not found"); + logger.Error($"Path should be {path}"); } } @@ -32,7 +33,7 @@ namespace Geekbot.net.Lib return PandaArray[rnd.Next(0, totalPandas)]; } } - + public interface IPandaProvider { string GetRandomPanda(); diff --git a/Geekbot.net/Logs/.keep b/Geekbot.net/Logs/.keep new file mode 100755 index 0000000..e69de29 diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index f9e250f..3edeb4e 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -1,12 +1,14 @@ using System; -using System.Net.NetworkInformation; using System.Reflection; +using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Lib; using Microsoft.Extensions.DependencyInjection; +using Serilog; +using Serilog.Sinks.SystemConsole.Themes; using StackExchange.Redis; namespace Geekbot.net @@ -19,23 +21,32 @@ namespace Geekbot.net private IServiceCollection services; private IServiceProvider servicesProvider; private RedisValue token; + private ILogger logger; - private static void Main() + private static void Main(string[] args) { - Console.WriteLine(@" ____ _____ _____ _ ______ ___ _____"); - Console.WriteLine(@" / ___| ____| ____| |/ / __ ) / _ \\_ _|"); - Console.WriteLine(@"| | _| _| | _| | ' /| _ \| | | || |"); - Console.WriteLine(@"| |_| | |___| |___| . \| |_) | |_| || |"); - Console.WriteLine(@" \____|_____|_____|_|\_\____/ \___/ |_|"); - Console.WriteLine("========================================="); - Console.WriteLine("* Starting..."); - - new Program().MainAsync().GetAwaiter().GetResult(); + var logger = new LoggerConfiguration() + .MinimumLevel.Debug() + .WriteTo.LiterateConsole() + .WriteTo.RollingFile("Logs/geekbot-{Hour}.txt", shared: true) + .CreateLogger(); + + var logo = new StringBuilder(); + logo.AppendLine(@" ____ _____ _____ _ ______ ___ _____"); + logo.AppendLine(@" / ___| ____| ____| |/ / __ ) / _ \\_ _|"); + logo.AppendLine(@"| | _| _| | _| | ' /| _ \| | | || |"); + logo.AppendLine(@"| |_| | |___| |___| . \| |_) | |_| || |"); + logo.AppendLine(@" \____|_____|_____|_|\_\____/ \___/ |_|"); + logo.AppendLine("========================================="); + Console.WriteLine(logo.ToString()); + logger.Information("* Starting..."); + new Program().MainAsync(logger).GetAwaiter().GetResult(); } - public async Task MainAsync() + private async Task MainAsync(ILogger logger) { - Console.WriteLine("* Initing Stuff"); + this.logger = logger; + logger.Information("* Initing Stuff"); client = new DiscordSocketClient(); commands = new CommandService(); @@ -44,11 +55,11 @@ namespace Geekbot.net { var redisMultiplexer = ConnectionMultiplexer.Connect("127.0.0.1:6379"); redis = redisMultiplexer.GetDatabase(6); - Console.WriteLine("-- Connected to Redis (db6)"); + logger.Information($"-- Connected to Redis ({redis.Database})"); } catch (Exception) { - Console.WriteLine("Start Redis pls..."); + logger.Information("Start Redis pls..."); Environment.Exit(102); } @@ -67,16 +78,17 @@ namespace Geekbot.net services = new ServiceCollection(); var RandomClient = new Random(); - var fortunes = new FortunesProvider(RandomClient); - var checkEmImages = new CheckEmImageProvider(RandomClient); - var pandaImages = new PandaProvider(RandomClient); + var fortunes = new FortunesProvider(RandomClient, logger); + var checkEmImages = new CheckEmImageProvider(RandomClient, logger); + var pandaImages = new PandaProvider(RandomClient, logger); services.AddSingleton(redis); services.AddSingleton(RandomClient); + services.AddSingleton(logger); services.AddSingleton(fortunes); services.AddSingleton(checkEmImages); services.AddSingleton(pandaImages); - Console.WriteLine("* Connecting to Discord"); + logger.Information("* Connecting to Discord", Color.Teal); await Login(); @@ -93,9 +105,9 @@ namespace Geekbot.net if (isConneted) { await client.SetGameAsync("Ping Pong"); - Console.WriteLine($"* Now Connected to {client.Guilds.Count} Servers"); + logger.Information($"* Now Connected to {client.Guilds.Count} Servers"); - Console.WriteLine("* Registering Stuff"); + logger.Information("* Registering Stuff", Color.Teal); client.MessageReceived += HandleCommand; client.MessageReceived += HandleMessageReceived; @@ -104,12 +116,12 @@ namespace Geekbot.net services.AddSingleton(commands); servicesProvider = services.BuildServiceProvider(); - Console.WriteLine("* Done and ready for use\n"); + logger.Information("* Done and ready for use\n", Color.Teal); } } catch (AggregateException) { - Console.WriteLine("Could not connect to discord..."); + logger.Information("Could not connect to discord..."); Environment.Exit(103); } } @@ -155,7 +167,7 @@ namespace Geekbot.net if (message.Author.Id == client.CurrentUser.Id) return; var channel = (SocketGuildChannel) message.Channel; - Console.WriteLine(channel.Guild.Name + " - " + message.Channel + " - " + message.Author.Username + " - " + + logger.Information(channel.Guild.Name + " - " + message.Channel + " - " + message.Author.Username + " - " + message.Content); await userRec; await guildRec; From 2a12d30d8f802803662259c416de5f1e9e18e737 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Tue, 26 Sep 2017 22:09:57 +0200 Subject: [PATCH 030/553] Add More logging Statements --- Geekbot.net/Lib/CheckEmImageProvider.cs | 2 +- Geekbot.net/Lib/ErrorHandler.cs | 32 +++++++++ Geekbot.net/Lib/FortunesProvider.cs | 2 +- Geekbot.net/Lib/PandaProvider.cs | 2 +- Geekbot.net/Modules/CheckEm.cs | 11 ++- Geekbot.net/Program.cs | 91 +++++++++++++++++-------- 6 files changed, 106 insertions(+), 34 deletions(-) create mode 100644 Geekbot.net/Lib/ErrorHandler.cs diff --git a/Geekbot.net/Lib/CheckEmImageProvider.cs b/Geekbot.net/Lib/CheckEmImageProvider.cs index 8b66194..43f4b94 100644 --- a/Geekbot.net/Lib/CheckEmImageProvider.cs +++ b/Geekbot.net/Lib/CheckEmImageProvider.cs @@ -19,7 +19,7 @@ namespace Geekbot.net.Lib checkEmImageArray = rawCheckEmPics.Split("\n"); totalCheckEmImages = checkEmImageArray.Length; this.rnd = rnd; - logger.Information($"-- Loaded {totalCheckEmImages} CheckEm Images"); + logger.Information($"[Geekbot] [CheckEm] Loaded {totalCheckEmImages} CheckEm Images"); } else { diff --git a/Geekbot.net/Lib/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandler.cs new file mode 100644 index 0000000..3dd06cc --- /dev/null +++ b/Geekbot.net/Lib/ErrorHandler.cs @@ -0,0 +1,32 @@ +using System; +using Discord.Commands; +using Serilog; + +namespace Geekbot.net.Lib +{ + public class ErrorHandler : IErrorHandler + { + private readonly ILogger logger; +// private readonly IDMChannel botOwnerDmChannel; + + public ErrorHandler(ILogger logger /*, IDMChannel botOwnerDmChannel*/) + { + this.logger = logger; +// this.botOwnerDmChannel = botOwnerDmChannel; + } + + public async void HandleCommandException(Exception e, ICommandContext Context) + { + var errorMsg = + $"Error Occured while executing \"{Context.Message.Content}\", executed by \"{Context.User.Username}\""; + logger.Error(e, errorMsg); +// await botOwnerDmChannel.SendMessageAsync($"{errorMsg}```{e.StackTrace}```"); +// await Context.Channel.SendMessageAsync("Something went wrong..."); + } + } + + public interface IErrorHandler + { + void HandleCommandException(Exception e, ICommandContext Context); + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/FortunesProvider.cs b/Geekbot.net/Lib/FortunesProvider.cs index f485952..3b839d1 100644 --- a/Geekbot.net/Lib/FortunesProvider.cs +++ b/Geekbot.net/Lib/FortunesProvider.cs @@ -19,7 +19,7 @@ namespace Geekbot.net.Lib fortuneArray = rawFortunes.Split("%"); totalFortunes = fortuneArray.Length; this.rnd = rnd; - logger.Information($"-- Loaded {totalFortunes} Fortunes"); + logger.Information($"[Geekbot] [Fortunes] Loaded {totalFortunes} Fortunes"); } else { diff --git a/Geekbot.net/Lib/PandaProvider.cs b/Geekbot.net/Lib/PandaProvider.cs index 6ac927a..25a6f95 100644 --- a/Geekbot.net/Lib/PandaProvider.cs +++ b/Geekbot.net/Lib/PandaProvider.cs @@ -19,7 +19,7 @@ namespace Geekbot.net.Lib PandaArray = rawFortunes.Split("\n"); totalPandas = PandaArray.Length; this.rnd = rnd; - logger.Information($"-- Loaded {totalPandas} Panda Images"); + logger.Information($"[Geekbot] [Pandas] Loaded {totalPandas} Panda Images"); } else { diff --git a/Geekbot.net/Modules/CheckEm.cs b/Geekbot.net/Modules/CheckEm.cs index 1751462..eea5a5f 100644 --- a/Geekbot.net/Modules/CheckEm.cs +++ b/Geekbot.net/Modules/CheckEm.cs @@ -4,6 +4,7 @@ using System.Text; using System.Threading.Tasks; using Discord.Commands; using Geekbot.net.Lib; +using Serilog; namespace Geekbot.net.Modules { @@ -11,11 +12,15 @@ namespace Geekbot.net.Modules { private readonly ICheckEmImageProvider checkEmImages; private readonly Random rnd; + private readonly ILogger logger; + private readonly IErrorHandler errorHandler; - public CheckEm(Random RandomClient, ICheckEmImageProvider checkEmImages) + public CheckEm(Random RandomClient, ICheckEmImageProvider checkEmImages, ILogger logger, IErrorHandler errorHandler) { - rnd = RandomClient; + this.rnd = RandomClient; this.checkEmImages = checkEmImages; + this.logger = logger; + this.errorHandler = errorHandler; } [Command("checkem", RunMode = RunMode.Async)] @@ -50,7 +55,7 @@ namespace Geekbot.net.Modules } catch (Exception e) { - Console.WriteLine(e.Message); + errorHandler.HandleCommandException(e, Context); } } diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 3edeb4e..6f33214 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -8,7 +8,6 @@ using Discord.WebSocket; using Geekbot.net.Lib; using Microsoft.Extensions.DependencyInjection; using Serilog; -using Serilog.Sinks.SystemConsole.Themes; using StackExchange.Redis; namespace Geekbot.net @@ -22,16 +21,17 @@ namespace Geekbot.net private IServiceProvider servicesProvider; private RedisValue token; private ILogger logger; + private ulong botOwnerId; private static void Main(string[] args) { var logger = new LoggerConfiguration() .MinimumLevel.Debug() .WriteTo.LiterateConsole() - .WriteTo.RollingFile("Logs/geekbot-{Hour}.txt", shared: true) + .WriteTo.RollingFile("Logs/geekbot-{Date}.txt", shared: true) .CreateLogger(); - - var logo = new StringBuilder(); + + var logo = new StringBuilder(); logo.AppendLine(@" ____ _____ _____ _ ______ ___ _____"); logo.AppendLine(@" / ___| ____| ____| |/ / __ ) / _ \\_ _|"); logo.AppendLine(@"| | _| _| | _| | ' /| _ \| | | || |"); @@ -39,23 +39,27 @@ namespace Geekbot.net logo.AppendLine(@" \____|_____|_____|_|\_\____/ \___/ |_|"); logo.AppendLine("========================================="); Console.WriteLine(logo.ToString()); - logger.Information("* Starting..."); + logger.Information("[Geekbot] Starting..."); new Program().MainAsync(logger).GetAwaiter().GetResult(); } private async Task MainAsync(ILogger logger) { this.logger = logger; - logger.Information("* Initing Stuff"); - - client = new DiscordSocketClient(); + logger.Information("[Geekbot] Initing Stuff"); + + client = new DiscordSocketClient(new DiscordSocketConfig + { + LogLevel = LogSeverity.Verbose + }); + client.Log += DiscordLogger; commands = new CommandService(); try { var redisMultiplexer = ConnectionMultiplexer.Connect("127.0.0.1:6379"); redis = redisMultiplexer.GetDatabase(6); - logger.Information($"-- Connected to Redis ({redis.Database})"); + logger.Information($"[Redis] Connected to db {redis.Database}"); } catch (Exception) { @@ -70,17 +74,24 @@ namespace Geekbot.net var newToken = Console.ReadLine(); redis.StringSet("discordToken", newToken); token = newToken; - - Console.Write("Bot Owner User ID: "); - var ownerId = Console.ReadLine(); - redis.StringSet("botOwner", ownerId); } + var botOwner = redis.StringGet("botOwner"); + if (botOwner.IsNullOrEmpty) + { + Console.Write("Bot Owner User ID: "); + botOwner = Console.ReadLine(); + redis.StringSet("botOwner", botOwner); + } + botOwnerId = (ulong) botOwner; + services = new ServiceCollection(); var RandomClient = new Random(); var fortunes = new FortunesProvider(RandomClient, logger); var checkEmImages = new CheckEmImageProvider(RandomClient, logger); var pandaImages = new PandaProvider(RandomClient, logger); + IErrorHandler errorHandler = new ErrorHandler(logger); + services.AddSingleton(errorHandler); services.AddSingleton(redis); services.AddSingleton(RandomClient); services.AddSingleton(logger); @@ -88,14 +99,14 @@ namespace Geekbot.net services.AddSingleton(checkEmImages); services.AddSingleton(pandaImages); - logger.Information("* Connecting to Discord", Color.Teal); + logger.Information("[Geekbot] Connecting to Discord"); await Login(); await Task.Delay(-1); } - public async Task Login() + private async Task Login() { try { @@ -105,18 +116,17 @@ namespace Geekbot.net if (isConneted) { await client.SetGameAsync("Ping Pong"); - logger.Information($"* Now Connected to {client.Guilds.Count} Servers"); + logger.Information($"[Geekbot] Now Connected to {client.Guilds.Count} Servers"); - logger.Information("* Registering Stuff", Color.Teal); + logger.Information("[Geekbot] Registering Stuff"); client.MessageReceived += HandleCommand; client.MessageReceived += HandleMessageReceived; client.UserJoined += HandleUserJoined; await commands.AddModulesAsync(Assembly.GetEntryAssembly()); services.AddSingleton(commands); - servicesProvider = services.BuildServiceProvider(); - - logger.Information("* Done and ready for use\n", Color.Teal); + this.servicesProvider = services.BuildServiceProvider(); + logger.Information("[Geekbot] Done and ready for use\n"); } } catch (AggregateException) @@ -126,14 +136,14 @@ namespace Geekbot.net } } - public async Task isConnected() + private async Task isConnected() { while (!client.ConnectionState.Equals(ConnectionState.Connected)) await Task.Delay(25); return true; } - public async Task HandleCommand(SocketMessage messageParam) + private async Task HandleCommand(SocketMessage messageParam) { var message = messageParam as SocketUserMessage; if (message == null) return; @@ -156,24 +166,23 @@ namespace Geekbot.net var commandExec = commands.ExecuteAsync(context, argPos, servicesProvider); } - public async Task HandleMessageReceived(SocketMessage messsageParam) + private async Task HandleMessageReceived(SocketMessage messsageParam) { var message = messsageParam; if (message == null) return; - + var statsRecorder = new StatsRecorder(message, redis); var userRec = statsRecorder.UpdateUserRecordAsync(); var guildRec = statsRecorder.UpdateGuildRecordAsync(); - + if (message.Author.Id == client.CurrentUser.Id) return; var channel = (SocketGuildChannel) message.Channel; - logger.Information(channel.Guild.Name + " - " + message.Channel + " - " + message.Author.Username + " - " + - message.Content); + logger.Information($"[Message] {channel.Guild.Name} - {message.Channel} - {message.Author.Username} - {message.Content}"); await userRec; await guildRec; } - public async Task HandleUserJoined(SocketGuildUser user) + private async Task HandleUserJoined(SocketGuildUser user) { if (!user.IsBot) { @@ -185,5 +194,31 @@ namespace Geekbot.net } } } + + private Task DiscordLogger(LogMessage message) + { + var logMessage = $"[{message.Source}] {message.Message}"; + switch (message.Severity) + { + case LogSeverity.Verbose: + logger.Verbose(logMessage); + break; + case LogSeverity.Debug: + logger.Debug(logMessage); + break; + case LogSeverity.Info: + logger.Information(logMessage); + break; + case LogSeverity.Critical: + case LogSeverity.Error: + case LogSeverity.Warning: + logger.Error(message.Exception, logMessage); + break; + default: + logger.Information($"{logMessage} --- {message.Severity.ToString()}"); + break; + } + return Task.CompletedTask; + } } } \ No newline at end of file From 7308e5257a3eafdc79afc690df312e034ef461c1 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Wed, 27 Sep 2017 17:18:31 +0200 Subject: [PATCH 031/553] Moved store providers to geekbot.net.lib.media --- Geekbot.net/Geekbot.net.csproj | 2 ++ Geekbot.net/Lib/ErrorHandler.cs | 2 +- Geekbot.net/Lib/{ => Media}/CheckEmImageProvider.cs | 2 +- Geekbot.net/Lib/{ => Media}/FortunesProvider.cs | 2 +- Geekbot.net/Lib/{ => Media}/PandaProvider.cs | 2 +- Geekbot.net/Modules/CheckEm.cs | 1 + Geekbot.net/Modules/Fortune.cs | 2 +- Geekbot.net/Modules/Panda.cs | 2 +- Geekbot.net/Program.cs | 7 ++++--- 9 files changed, 13 insertions(+), 9 deletions(-) rename Geekbot.net/Lib/{ => Media}/CheckEmImageProvider.cs (94%) rename Geekbot.net/Lib/{ => Media}/FortunesProvider.cs (93%) rename Geekbot.net/Lib/{ => Media}/PandaProvider.cs (93%) diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 37f26fa..0da2296 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -14,6 +14,8 @@ 1.0.2 + + 1.5.0.1 diff --git a/Geekbot.net/Lib/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandler.cs index 3dd06cc..4320df5 100644 --- a/Geekbot.net/Lib/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandler.cs @@ -15,7 +15,7 @@ namespace Geekbot.net.Lib // this.botOwnerDmChannel = botOwnerDmChannel; } - public async void HandleCommandException(Exception e, ICommandContext Context) + public void HandleCommandException(Exception e, ICommandContext Context) { var errorMsg = $"Error Occured while executing \"{Context.Message.Content}\", executed by \"{Context.User.Username}\""; diff --git a/Geekbot.net/Lib/CheckEmImageProvider.cs b/Geekbot.net/Lib/Media/CheckEmImageProvider.cs similarity index 94% rename from Geekbot.net/Lib/CheckEmImageProvider.cs rename to Geekbot.net/Lib/Media/CheckEmImageProvider.cs index 43f4b94..4f51a2e 100644 --- a/Geekbot.net/Lib/CheckEmImageProvider.cs +++ b/Geekbot.net/Lib/Media/CheckEmImageProvider.cs @@ -2,7 +2,7 @@ using System.IO; using Serilog; -namespace Geekbot.net.Lib +namespace Geekbot.net.Lib.Media { public class CheckEmImageProvider : ICheckEmImageProvider { diff --git a/Geekbot.net/Lib/FortunesProvider.cs b/Geekbot.net/Lib/Media/FortunesProvider.cs similarity index 93% rename from Geekbot.net/Lib/FortunesProvider.cs rename to Geekbot.net/Lib/Media/FortunesProvider.cs index 3b839d1..a1e8fb9 100644 --- a/Geekbot.net/Lib/FortunesProvider.cs +++ b/Geekbot.net/Lib/Media/FortunesProvider.cs @@ -2,7 +2,7 @@ using System.IO; using Serilog; -namespace Geekbot.net.Lib +namespace Geekbot.net.Lib.Media { internal class FortunesProvider : IFortunesProvider { diff --git a/Geekbot.net/Lib/PandaProvider.cs b/Geekbot.net/Lib/Media/PandaProvider.cs similarity index 93% rename from Geekbot.net/Lib/PandaProvider.cs rename to Geekbot.net/Lib/Media/PandaProvider.cs index 25a6f95..8bbd14e 100644 --- a/Geekbot.net/Lib/PandaProvider.cs +++ b/Geekbot.net/Lib/Media/PandaProvider.cs @@ -2,7 +2,7 @@ using System.IO; using Serilog; -namespace Geekbot.net.Lib +namespace Geekbot.net.Lib.Media { public class PandaProvider : IPandaProvider { diff --git a/Geekbot.net/Modules/CheckEm.cs b/Geekbot.net/Modules/CheckEm.cs index eea5a5f..8af8ae0 100644 --- a/Geekbot.net/Modules/CheckEm.cs +++ b/Geekbot.net/Modules/CheckEm.cs @@ -4,6 +4,7 @@ using System.Text; using System.Threading.Tasks; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.Media; using Serilog; namespace Geekbot.net.Modules diff --git a/Geekbot.net/Modules/Fortune.cs b/Geekbot.net/Modules/Fortune.cs index 2040034..cc52bcf 100644 --- a/Geekbot.net/Modules/Fortune.cs +++ b/Geekbot.net/Modules/Fortune.cs @@ -1,6 +1,6 @@ using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib; +using Geekbot.net.Lib.Media; namespace Geekbot.net.Modules { diff --git a/Geekbot.net/Modules/Panda.cs b/Geekbot.net/Modules/Panda.cs index 515dfed..f5675c9 100644 --- a/Geekbot.net/Modules/Panda.cs +++ b/Geekbot.net/Modules/Panda.cs @@ -1,6 +1,6 @@ using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib; +using Geekbot.net.Lib.Media; namespace Geekbot.net.Modules { diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 6f33214..1f36aa2 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -6,6 +6,7 @@ using Discord; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Lib; +using Geekbot.net.Lib.Media; using Microsoft.Extensions.DependencyInjection; using Serilog; using StackExchange.Redis; @@ -61,9 +62,9 @@ namespace Geekbot.net redis = redisMultiplexer.GetDatabase(6); logger.Information($"[Redis] Connected to db {redis.Database}"); } - catch (Exception) + catch (Exception e) { - logger.Information("Start Redis pls..."); + logger.Fatal(e, "Redis Connection Failed"); Environment.Exit(102); } @@ -90,7 +91,7 @@ namespace Geekbot.net var fortunes = new FortunesProvider(RandomClient, logger); var checkEmImages = new CheckEmImageProvider(RandomClient, logger); var pandaImages = new PandaProvider(RandomClient, logger); - IErrorHandler errorHandler = new ErrorHandler(logger); + var errorHandler = new ErrorHandler(logger); services.AddSingleton(errorHandler); services.AddSingleton(redis); services.AddSingleton(RandomClient); From 29c181ddda9f3a874b596f62f010ee4be960fe48 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Wed, 27 Sep 2017 22:48:09 +0200 Subject: [PATCH 032/553] Reworked Database, using hashtables now (mostly), ability to change game, several small improvents --- Geekbot.net/Lib/LoggerFactory.cs | 24 +++ Geekbot.net/Lib/Media/CheckEmImageProvider.cs | 2 +- Geekbot.net/Lib/Media/FortunesProvider.cs | 2 +- Geekbot.net/Lib/Media/PandaProvider.cs | 2 +- Geekbot.net/Lib/StatsRecorder.cs | 32 ---- Geekbot.net/Modules/AdminCmd.cs | 30 +++- Geekbot.net/Modules/Counters.cs | 155 +++++++++--------- Geekbot.net/Modules/GuildInfo.cs | 2 +- Geekbot.net/Modules/Info.cs | 2 +- Geekbot.net/Modules/Roll.cs | 4 +- Geekbot.net/Modules/Ship.cs | 6 +- Geekbot.net/Modules/UserInfo.cs | 80 +++++---- Geekbot.net/Program.cs | 101 +++++++++--- 13 files changed, 264 insertions(+), 178 deletions(-) create mode 100644 Geekbot.net/Lib/LoggerFactory.cs delete mode 100644 Geekbot.net/Lib/StatsRecorder.cs diff --git a/Geekbot.net/Lib/LoggerFactory.cs b/Geekbot.net/Lib/LoggerFactory.cs new file mode 100644 index 0000000..055c2f2 --- /dev/null +++ b/Geekbot.net/Lib/LoggerFactory.cs @@ -0,0 +1,24 @@ +using Serilog; +using System.Linq; + +namespace Geekbot.net.Lib +{ + public class LoggerFactory + { + public static ILogger createLogger(string[] args) + { + var loggerCreation = new LoggerConfiguration() + .WriteTo.LiterateConsole() + .WriteTo.RollingFile("Logs/geekbot-{Date}.txt", shared: true); + if (args.Length != 0 && args.Contains("--verbose")) + { + loggerCreation.MinimumLevel.Verbose(); + } + else + { + loggerCreation.MinimumLevel.Information(); + } + return loggerCreation.CreateLogger(); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Media/CheckEmImageProvider.cs b/Geekbot.net/Lib/Media/CheckEmImageProvider.cs index 4f51a2e..8f2fc77 100644 --- a/Geekbot.net/Lib/Media/CheckEmImageProvider.cs +++ b/Geekbot.net/Lib/Media/CheckEmImageProvider.cs @@ -19,7 +19,7 @@ namespace Geekbot.net.Lib.Media checkEmImageArray = rawCheckEmPics.Split("\n"); totalCheckEmImages = checkEmImageArray.Length; this.rnd = rnd; - logger.Information($"[Geekbot] [CheckEm] Loaded {totalCheckEmImages} CheckEm Images"); + logger.Verbose($"[Geekbot] [CheckEm] Loaded {totalCheckEmImages} CheckEm Images"); } else { diff --git a/Geekbot.net/Lib/Media/FortunesProvider.cs b/Geekbot.net/Lib/Media/FortunesProvider.cs index a1e8fb9..43e456f 100644 --- a/Geekbot.net/Lib/Media/FortunesProvider.cs +++ b/Geekbot.net/Lib/Media/FortunesProvider.cs @@ -19,7 +19,7 @@ namespace Geekbot.net.Lib.Media fortuneArray = rawFortunes.Split("%"); totalFortunes = fortuneArray.Length; this.rnd = rnd; - logger.Information($"[Geekbot] [Fortunes] Loaded {totalFortunes} Fortunes"); + logger.Verbose($"[Geekbot] [Fortunes] Loaded {totalFortunes} Fortunes"); } else { diff --git a/Geekbot.net/Lib/Media/PandaProvider.cs b/Geekbot.net/Lib/Media/PandaProvider.cs index 8bbd14e..2ec46b3 100644 --- a/Geekbot.net/Lib/Media/PandaProvider.cs +++ b/Geekbot.net/Lib/Media/PandaProvider.cs @@ -19,7 +19,7 @@ namespace Geekbot.net.Lib.Media PandaArray = rawFortunes.Split("\n"); totalPandas = PandaArray.Length; this.rnd = rnd; - logger.Information($"[Geekbot] [Pandas] Loaded {totalPandas} Panda Images"); + logger.Verbose($"[Geekbot] [Pandas] Loaded {totalPandas} Panda Images"); } else { diff --git a/Geekbot.net/Lib/StatsRecorder.cs b/Geekbot.net/Lib/StatsRecorder.cs deleted file mode 100644 index c88ec2d..0000000 --- a/Geekbot.net/Lib/StatsRecorder.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Threading.Tasks; -using Discord.WebSocket; -using StackExchange.Redis; - -namespace Geekbot.net.Lib -{ - public class StatsRecorder - { - private readonly SocketMessage message; - private readonly IDatabase redis; - - public StatsRecorder(SocketMessage message, IDatabase redis) - { - this.message = message; - this.redis = redis; - } - - public async Task UpdateUserRecordAsync() - { - var guildId = ((SocketGuildChannel) message.Channel).Guild.Id; - var key = guildId + "-" + message.Author.Id + "-messages"; - await redis.StringIncrementAsync(key); - } - - public async Task UpdateGuildRecordAsync() - { - var guildId = ((SocketGuildChannel) message.Channel).Guild.Id; - var key = guildId + "-messages"; - await redis.StringIncrementAsync(key); - } - } -} \ No newline at end of file diff --git a/Geekbot.net/Modules/AdminCmd.cs b/Geekbot.net/Modules/AdminCmd.cs index 72beb36..ac7ba2f 100644 --- a/Geekbot.net/Modules/AdminCmd.cs +++ b/Geekbot.net/Modules/AdminCmd.cs @@ -1,6 +1,8 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; +using Discord.WebSocket; +using Serilog; using StackExchange.Redis; namespace Geekbot.net.Modules @@ -9,10 +11,14 @@ namespace Geekbot.net.Modules public class AdminCmd : ModuleBase { private readonly IDatabase redis; - - public AdminCmd(IDatabase redis) + private readonly DiscordSocketClient client; + private readonly ILogger logger; + + public AdminCmd(IDatabase redis, DiscordSocketClient client, ILogger logger) { this.redis = redis; + this.client = client; + this.logger = logger; } [RequireUserPermission(GuildPermission.Administrator)] @@ -20,8 +26,7 @@ namespace Geekbot.net.Modules [Summary("Set a Welcome Message (use '$user' to mention the new joined user).")] public async Task SetWelcomeMessage([Remainder] [Summary("message")] string welcomeMessage) { - var key = Context.Guild.Id + "-welcomeMsg"; - redis.StringSet(key, welcomeMessage); + redis.HashSet($"{Context.Guild.Id}:Settings", new HashEntry[] { new HashEntry("WelcomeMsg", welcomeMessage) }); var formatedMessage = welcomeMessage.Replace("$user", Context.User.Mention); await ReplyAsync("Welcome message has been changed\r\nHere is an example of how it would look:\r\n" + formatedMessage); @@ -41,5 +46,22 @@ namespace Geekbot.net.Modules redis.StringSet("youtubeKey", key); await ReplyAsync("Apikey has been set"); } + + [Command("game", RunMode = RunMode.Async)] + [Summary("Set the game that the bot is playing")] + public async Task SetGame([Remainder] [Summary("Game")] string key) + { + var botOwner = redis.StringGet("botOwner"); + if (!Context.User.Id.ToString().Equals(botOwner.ToString())) + { + await ReplyAsync($"Sorry, only the botowner can do this ({botOwner}"); + return; + } + + redis.StringSet("Game", key); + await client.SetGameAsync(key); + logger.Information($"[Geekbot] Changed game to {key}"); + await ReplyAsync($"Now Playing {key}"); + } } } \ No newline at end of file diff --git a/Geekbot.net/Modules/Counters.cs b/Geekbot.net/Modules/Counters.cs index 66ecd9a..ee844ca 100644 --- a/Geekbot.net/Modules/Counters.cs +++ b/Geekbot.net/Modules/Counters.cs @@ -2,53 +2,64 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.net.Lib; using StackExchange.Redis; +using Serilog; namespace Geekbot.net.Modules { public class Counters : ModuleBase { private readonly IDatabase redis; + private readonly ILogger logger; + private readonly IErrorHandler errorHandler; - public Counters(IDatabase redis) + public Counters(IDatabase redis, ILogger logger, IErrorHandler errorHandler) { this.redis = redis; + this.logger = logger; + this.errorHandler = errorHandler; } [Command("good", RunMode = RunMode.Async)] [Summary("Increase Someones Karma")] public async Task Good([Summary("@someone")] IUser user) { - var lastKarma = GetLastKarma(); - if (user.Id == Context.User.Id) + try { - await ReplyAsync($"Sorry {Context.User.Username}, but you can't give yourself karma"); - } - else if (lastKarma > GetUnixTimestamp()) - { - await ReplyAsync( - $"Sorry {Context.User.Username}, but you have to wait {GetTimeLeft(lastKarma)} before you can give karma again..."); - } - else - { - var key = Context.Guild.Id + "-" + user.Id + "-karma"; - var badJokes = (int) redis.StringGet(key); - var newBadJokes = badJokes + 1; - redis.StringSet(key, newBadJokes.ToString()); - var lastKey = Context.Guild.Id + "-" + Context.User.Id + "-karma-timeout"; - redis.StringSet(lastKey, GetNewLastKarma()); + var lastKarmaFromRedis = redis.HashGet($"{Context.Guild.Id}:KarmaTimeout", Context.User.Id.ToString()); + var lastKarma = ConvertToDateTimeOffset(lastKarmaFromRedis.ToString()); + if (user.Id == Context.User.Id) + { + await ReplyAsync($"Sorry {Context.User.Username}, but you can't lower your own karma"); + } + else if (TimeoutFinished(lastKarma)) + { + await ReplyAsync( + $"Sorry {Context.User.Username}, but you have to wait {GetTimeLeft(lastKarma)} before you can give karma again..."); + } + else + { + var newKarma = redis.HashIncrement($"{Context.Guild.Id}:Karma", user.Id.ToString()); + redis.HashSet($"{Context.Guild.Id}:KarmaTimeout", + new HashEntry[] {new HashEntry(Context.User.Id.ToString(), DateTimeOffset.Now.ToString("u"))}); - var eb = new EmbedBuilder(); - eb.WithAuthor(new EmbedAuthorBuilder() - .WithIconUrl(user.GetAvatarUrl()) - .WithName(user.Username)); + var eb = new EmbedBuilder(); + eb.WithAuthor(new EmbedAuthorBuilder() + .WithIconUrl(user.GetAvatarUrl()) + .WithName(user.Username)); - eb.WithColor(new Color(138, 219, 146)); - eb.Title = "Karma Increased"; - eb.AddInlineField("By", Context.User.Username); - eb.AddInlineField("amount", "+1"); - eb.AddInlineField("Current Karma", newBadJokes); - await ReplyAsync("", false, eb.Build()); + eb.WithColor(new Color(138, 219, 146)); + eb.Title = "Karma Increased"; + eb.AddInlineField("By", Context.User.Username); + eb.AddInlineField("amount", "+1"); + eb.AddInlineField("Current Karma", newKarma); + await ReplyAsync("", false, eb.Build()); + } + } + catch (Exception e) + { + errorHandler.HandleCommandException(e, Context); } } @@ -56,64 +67,58 @@ namespace Geekbot.net.Modules [Summary("Decrease Someones Karma")] public async Task Bad([Summary("@someone")] IUser user) { - var lastKarma = GetLastKarma(); - if (user.Id == Context.User.Id) + try { - await ReplyAsync($"Sorry {Context.User.Username}, but you can't lower your own karma"); - } - else if (lastKarma > GetUnixTimestamp()) - { - await ReplyAsync( - $"Sorry {Context.User.Username}, but you have to wait {GetTimeLeft(lastKarma)} before you can take karma again..."); - } - else - { - var key = Context.Guild.Id + "-" + user.Id + "-karma"; - var badJokes = (int) redis.StringGet(key); - var newBadJokes = badJokes - 1; - redis.StringSet(key, newBadJokes.ToString()); - var lastKey = Context.Guild.Id + "-" + Context.User.Id + "-karma-timeout"; - redis.StringSet(lastKey, GetNewLastKarma()); + var lastKarmaFromRedis = redis.HashGet($"{Context.Guild.Id}:KarmaTimeout", Context.User.Id.ToString()); + var lastKarma = ConvertToDateTimeOffset(lastKarmaFromRedis.ToString()); + if (user.Id == Context.User.Id) + { + await ReplyAsync($"Sorry {Context.User.Username}, but you can't lower your own karma"); + } + else if (TimeoutFinished(lastKarma)) + { + await ReplyAsync( + $"Sorry {Context.User.Username}, but you have to wait {GetTimeLeft(lastKarma)} before you can take karma again..."); + } + else + { + var newKarma = redis.HashDecrement($"{Context.Guild.Id}:Karma", user.Id.ToString()); + redis.HashSet($"{Context.Guild.Id}:KarmaTimeout", + new HashEntry[] {new HashEntry(Context.User.Id.ToString(), DateTimeOffset.Now.ToString())}); - var eb = new EmbedBuilder(); - eb.WithAuthor(new EmbedAuthorBuilder() - .WithIconUrl(user.GetAvatarUrl()) - .WithName(user.Username)); + var eb = new EmbedBuilder(); + eb.WithAuthor(new EmbedAuthorBuilder() + .WithIconUrl(user.GetAvatarUrl()) + .WithName(user.Username)); - eb.WithColor(new Color(138, 219, 146)); - eb.Title = "Karma Decreased"; - eb.AddInlineField("By", Context.User.Username); - eb.AddInlineField("amount", "-1"); - eb.AddInlineField("Current Karma", newBadJokes); - await ReplyAsync("", false, eb.Build()); + eb.WithColor(new Color(138, 219, 146)); + eb.Title = "Karma Decreased"; + eb.AddInlineField("By", Context.User.Username); + eb.AddInlineField("amount", "-1"); + eb.AddInlineField("Current Karma", newKarma); + await ReplyAsync("", false, eb.Build()); + } + } + catch (Exception e) + { + errorHandler.HandleCommandException(e, Context); } } - private int GetLastKarma() + private DateTimeOffset ConvertToDateTimeOffset(string dateTimeOffsetString) { - var lastKey = Context.Guild.Id + "-" + Context.User.Id + "-karma-timeout"; - var redisReturn = redis.StringGet(lastKey); - if (!int.TryParse(redisReturn.ToString(), out var i)) - i = GetUnixTimestamp(); - return i; + if(string.IsNullOrEmpty(dateTimeOffsetString)) return DateTimeOffset.Now.Subtract(new TimeSpan(7, 18, 0, 0)); + return DateTimeOffset.Parse(dateTimeOffsetString); } - - private int GetNewLastKarma() + + private bool TimeoutFinished(DateTimeOffset lastKarma) { - var timeout = TimeSpan.FromMinutes(3); - return (int) DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).Add(timeout).TotalSeconds; + return lastKarma.AddMinutes(3) > DateTimeOffset.Now; } - - private int GetUnixTimestamp() + + private string GetTimeLeft(DateTimeOffset lastKarma) { - return (int) DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds; - } - - private string GetTimeLeft(int time) - { - var dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); - dtDateTime = dtDateTime.AddSeconds(time).ToLocalTime(); - var dt = dtDateTime.Subtract(DateTime.Now); + var dt = lastKarma.AddMinutes(3).Subtract(DateTimeOffset.Now); return $"{dt.Minutes} Minutes and {dt.Seconds} Seconds"; } } diff --git a/Geekbot.net/Modules/GuildInfo.cs b/Geekbot.net/Modules/GuildInfo.cs index 20f4447..11a3d44 100644 --- a/Geekbot.net/Modules/GuildInfo.cs +++ b/Geekbot.net/Modules/GuildInfo.cs @@ -30,7 +30,7 @@ namespace Geekbot.net.Modules var created = Context.Guild.CreatedAt; var age = Math.Floor((DateTime.Now - created).TotalDays); - var messages = redis.StringGet($"{Context.Guild.Id}-messages"); + var messages = redis.HashGet($"{Context.Guild.Id}:Messages", 0.ToString()); var level = LevelCalc.GetLevelAtExperience((int) messages); eb.AddField("Server Age", $"{created.Day}/{created.Month}/{created.Year} ({age} days)"); diff --git a/Geekbot.net/Modules/Info.cs b/Geekbot.net/Modules/Info.cs index 62d4a01..749594a 100644 --- a/Geekbot.net/Modules/Info.cs +++ b/Geekbot.net/Modules/Info.cs @@ -20,7 +20,7 @@ namespace Geekbot.net.Modules { var eb = new EmbedBuilder(); - eb.WithTitle("Geekbot V3.1"); + eb.WithTitle("Geekbot V3.2"); var botOwner = Context.Guild.GetUserAsync(ulong.Parse(redis.StringGet("botOwner"))).Result; diff --git a/Geekbot.net/Modules/Roll.cs b/Geekbot.net/Modules/Roll.cs index c46b887..9d84a8d 100644 --- a/Geekbot.net/Modules/Roll.cs +++ b/Geekbot.net/Modules/Roll.cs @@ -29,9 +29,7 @@ namespace Geekbot.net.Modules if (guess == number) { await ReplyAsync($"Congratulations {Context.User.Username}, your guess was correct!"); - var key = $"{Context.Guild.Id}-{Context.User.Id}-correctRolls"; - var messages = (int) redis.StringGet(key); - redis.StringSet(key, (messages + 1).ToString()); + redis.HashIncrement($"{Context.Guild.Id}:Rolls", Context.User.Id.ToString()); } } else diff --git a/Geekbot.net/Modules/Ship.cs b/Geekbot.net/Modules/Ship.cs index ed4365f..ea426e4 100644 --- a/Geekbot.net/Modules/Ship.cs +++ b/Geekbot.net/Modules/Ship.cs @@ -27,15 +27,13 @@ namespace Geekbot.net.Modules dbstring = $"{user1.Id}-{user2.Id}"; else dbstring = $"{user2.Id}-{user1.Id}"; - dbstring = $"{Context.Guild.Id}-{dbstring}"; - Console.WriteLine(dbstring); - var dbval = redis.StringGet(dbstring); + var dbval = redis.HashGet($"{Context.Guild.Id}:Ships", dbstring); var shippingRate = 0; if (dbval.IsNullOrEmpty) { shippingRate = rnd.Next(1, 100); - redis.StringSet(dbstring, shippingRate); + redis.HashSet($"{Context.Guild.Id}:Ships", dbstring, shippingRate); } else { diff --git a/Geekbot.net/Modules/UserInfo.cs b/Geekbot.net/Modules/UserInfo.cs index 1f94e45..faf6543 100644 --- a/Geekbot.net/Modules/UserInfo.cs +++ b/Geekbot.net/Modules/UserInfo.cs @@ -1,11 +1,11 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; +using Serilog; using StackExchange.Redis; namespace Geekbot.net.Modules @@ -13,10 +13,14 @@ namespace Geekbot.net.Modules public class UserInfo : ModuleBase { private readonly IDatabase redis; - - public UserInfo(IDatabase redis) + private readonly IErrorHandler errorHandler; + private readonly ILogger logger; + + public UserInfo(IDatabase redis, IErrorHandler errorHandler, ILogger logger) { this.redis = redis; + this.errorHandler = errorHandler; + this.logger = logger; } [Command("stats", RunMode = RunMode.Async)] @@ -27,12 +31,11 @@ namespace Geekbot.net.Modules var age = Math.Floor((DateTime.Now - userInfo.CreatedAt).TotalDays); - var key = Context.Guild.Id + "-" + userInfo.Id; - var messages = (int) redis.StringGet(key + "-messages"); + var messages = (int) redis.HashGet($"{Context.Guild.Id}:Messages", userInfo.Id.ToString()); var level = LevelCalc.GetLevelAtExperience(messages); var guildKey = Context.Guild.Id.ToString(); - var guildMessages = (int) redis.StringGet(guildKey + "-messages"); + var guildMessages = (int) redis.HashGet($"{Context.Guild.Id}:Messages", 0.ToString()); var percent = Math.Round((double) (100 * messages) / guildMessages, 2); @@ -49,11 +52,11 @@ namespace Geekbot.net.Modules .AddInlineField("Messages Sent", messages) .AddInlineField("Server Total", $"{percent}%"); - var karma = redis.StringGet(key + "-karma"); + var karma = redis.HashGet($"{Context.Guild.Id}:Karma", userInfo.Id.ToString()); if (!karma.IsNullOrEmpty) eb.AddInlineField("Karma", karma); - var correctRolls = redis.StringGet($"{Context.Guild.Id}-{userInfo.Id}-correctRolls"); + var correctRolls = redis.HashGet($"{Context.Guild.Id}:Rolls", userInfo.Id.ToString()); if (!correctRolls.IsNullOrEmpty) eb.AddInlineField("Guessed Rolls", correctRolls); @@ -64,34 +67,43 @@ namespace Geekbot.net.Modules [Summary("get user top 10")] public async Task Rank() { - await ReplyAsync("this will take a moment..."); - var guildKey = Context.Guild.Id.ToString(); - var guildMessages = (int) redis.StringGet(guildKey + "-messages"); - var allGuildUsers = await Context.Guild.GetUsersAsync(); - var unsortedDict = new Dictionary(); - foreach (var user in allGuildUsers) + try { - var key = Context.Guild.Id + "-" + user.Id; - var messages = (int) redis.StringGet(key + "-messages"); - if (messages > 0) - unsortedDict.Add($"{user.Username}#{user.Discriminator}", messages); + var messageList = redis.HashGetAll($"{Context.Guild.Id}:Messages"); + var sortedList = messageList.OrderByDescending(e => e.Value).ToList().Take(11).ToList(); + var guildMessages = (int) sortedList.First().Value; + sortedList.RemoveAt(0); + var highScore = new StringBuilder(); + highScore.AppendLine($":bar_chart: **Highscore for {Context.Guild.Name}**"); + var counter = 1; + foreach (var user in sortedList) + { + var guildUser = Context.Guild.GetUserAsync((ulong) user.Name).Result; + var percent = Math.Round((double) (100 * (int) user.Value) / guildMessages, 2); + highScore.AppendLine( + $"{NumerToEmoji(counter)} **{guildUser.Username}#{guildUser.Discriminator}** - {percent}% of total - {user.Value} messages"); + counter++; + } + await ReplyAsync(highScore.ToString()); + } + catch (Exception e) + { + errorHandler.HandleCommandException(e, Context); + } + } + + private string NumerToEmoji(int number) + { + var emojis = new string[] {":one:", ":two:", ":three:", ":four:", ":five:", ":six", ":seven:", ":eight:", ":nine:", ":keycap_ten:"}; + try + { + return emojis[number - 1]; + } + catch (Exception e) + { + logger.Warning(e, $"Can't provide emoji number {number}"); + return ":zero:"; } - var sortedDict = unsortedDict.OrderByDescending(x => x.Value); - var reply = new StringBuilder(); - reply.AppendLine($"Total Messages on {Context.Guild.Name}: {guildMessages}"); - var count = 1; - foreach (var entry in sortedDict) - if (count < 11) - { - var percent = Math.Round((double) (100 * entry.Value) / guildMessages, 2); - reply.AppendLine($"#{count} - **{entry.Key}** - {percent}% of total - {entry.Value} messages"); - count++; - } - else - { - break; - } - await ReplyAsync(reply.ToString()); } } } \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 1f36aa2..455429b 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; @@ -26,12 +28,7 @@ namespace Geekbot.net private static void Main(string[] args) { - var logger = new LoggerConfiguration() - .MinimumLevel.Debug() - .WriteTo.LiterateConsole() - .WriteTo.RollingFile("Logs/geekbot-{Date}.txt", shared: true) - .CreateLogger(); - + var logger = LoggerFactory.createLogger(args); var logo = new StringBuilder(); logo.AppendLine(@" ____ _____ _____ _ ______ ___ _____"); logo.AppendLine(@" / ___| ____| ____| |/ / __ ) / _ \\_ _|"); @@ -41,10 +38,10 @@ namespace Geekbot.net logo.AppendLine("========================================="); Console.WriteLine(logo.ToString()); logger.Information("[Geekbot] Starting..."); - new Program().MainAsync(logger).GetAwaiter().GetResult(); + new Program().MainAsync(args, logger).GetAwaiter().GetResult(); } - private async Task MainAsync(ILogger logger) + private async Task MainAsync(string[] args, ILogger logger) { this.logger = logger; logger.Information("[Geekbot] Initing Stuff"); @@ -64,16 +61,35 @@ namespace Geekbot.net } catch (Exception e) { - logger.Fatal(e, "Redis Connection Failed"); + logger.Fatal(e, "[Redis] Redis Connection Failed"); Environment.Exit(102); } + if (args.Length != 0 && args.Contains("--migrate")) + { + Console.WriteLine("\nYou are about to migrate the database, this will overwrite an already migrated database?"); + Console.Write("Are you sure [y:N]: "); + var migrateDbConfirm = Console.ReadKey(); + Console.WriteLine(); + if (migrateDbConfirm.Key == ConsoleKey.Y) + { + logger.Warning("[Geekbot] Starting Migration"); + await MigrateDatabaseToHash(); + logger.Warning("[Geekbot] Finished Migration"); + } + else + { + logger.Information("[Geekbot] Not Migrating db"); + } + } + token = redis.StringGet("discordToken"); if (token.IsNullOrEmpty) { Console.Write("Your bot Token: "); var newToken = Console.ReadLine(); redis.StringSet("discordToken", newToken); + redis.StringSet("Game", "Ping Pong"); token = newToken; } @@ -92,6 +108,7 @@ namespace Geekbot.net var checkEmImages = new CheckEmImageProvider(RandomClient, logger); var pandaImages = new PandaProvider(RandomClient, logger); var errorHandler = new ErrorHandler(logger); + services.AddSingleton(errorHandler); services.AddSingleton(redis); services.AddSingleton(RandomClient); @@ -116,7 +133,7 @@ namespace Geekbot.net var isConneted = await isConnected(); if (isConneted) { - await client.SetGameAsync("Ping Pong"); + await client.SetGameAsync(redis.StringGet("Game")); logger.Information($"[Geekbot] Now Connected to {client.Guilds.Count} Servers"); logger.Information("[Geekbot] Registering Stuff"); @@ -126,13 +143,14 @@ namespace Geekbot.net client.UserJoined += HandleUserJoined; await commands.AddModulesAsync(Assembly.GetEntryAssembly()); services.AddSingleton(commands); + services.AddSingleton(client); this.servicesProvider = services.BuildServiceProvider(); logger.Information("[Geekbot] Done and ready for use\n"); } } - catch (AggregateException) + catch (Exception e) { - logger.Information("Could not connect to discord..."); + logger.Fatal(e, "Could not connect to discord..."); Environment.Exit(103); } } @@ -171,23 +189,21 @@ namespace Geekbot.net { var message = messsageParam; if (message == null) return; - - var statsRecorder = new StatsRecorder(message, redis); - var userRec = statsRecorder.UpdateUserRecordAsync(); - var guildRec = statsRecorder.UpdateGuildRecordAsync(); - - if (message.Author.Id == client.CurrentUser.Id) return; + var channel = (SocketGuildChannel) message.Channel; + + await redis.HashIncrementAsync($"{channel.Guild.Id}:Messages", message.Author.Id.ToString()); + await redis.HashIncrementAsync($"{channel.Guild.Id}:Messages", 0.ToString()); + + if (message.Author.IsBot) return; logger.Information($"[Message] {channel.Guild.Name} - {message.Channel} - {message.Author.Username} - {message.Content}"); - await userRec; - await guildRec; } private async Task HandleUserJoined(SocketGuildUser user) { if (!user.IsBot) { - var message = redis.StringGet(user.Guild.Id + "-welcomeMsg"); + var message = redis.HashGet($"{user.Guild.Id}:Settings", "WelcomeMsg"); if (!message.IsNullOrEmpty) { message = message.ToString().Replace("$user", user.Mention); @@ -221,5 +237,48 @@ namespace Geekbot.net } return Task.CompletedTask; } + + // temporary db migration script + private Task MigrateDatabaseToHash() + { + foreach (var key in redis.Multiplexer.GetServer("127.0.0.1", 6379).Keys(6)) + { + var keyParts = key.ToString().Split("-"); + if (keyParts.Length == 2 || keyParts.Length == 3) + { + logger.Verbose($"Migrating key {key}"); + var stuff = new List(); + stuff.Add("messages"); + stuff.Add("karma"); + stuff.Add("welcomeMsg"); + stuff.Add("correctRolls"); + if(stuff.Contains(keyParts[keyParts.Length - 1])) + { + var val = redis.StringGet(key); + ulong.TryParse(keyParts[0], out ulong guildId); + ulong.TryParse(keyParts[1], out ulong userId); + + switch (keyParts[keyParts.Length - 1]) + { + case "messages": + redis.HashSet($"{guildId}:Messages", new HashEntry[] { new HashEntry(userId.ToString(), val) }); + break; + case "karma": + redis.HashSet($"{guildId}:Karma", new HashEntry[] { new HashEntry(userId.ToString(), val) }); + break; + case "correctRolls": + redis.HashSet($"{guildId}:Rolls", new HashEntry[] { new HashEntry(userId.ToString(), val) }); + break; + case "welcomeMsg": + redis.HashSet($"{guildId}:Settings", new HashEntry[] { new HashEntry("WelcomeMsg", val) }); + break; + } + //redis.KeyDelete(key); + + } + } + } + return Task.CompletedTask; + } } } \ No newline at end of file From a4cbc03202c61773ade2ed6a0ca378e551c48d6d Mon Sep 17 00:00:00 2001 From: Runebaas Date: Wed, 27 Sep 2017 23:26:32 +0200 Subject: [PATCH 033/553] Bugfix in rank, updated migration script --- Geekbot.net/Lib/ErrorHandler.cs | 2 +- Geekbot.net/Modules/UserInfo.cs | 31 ++++++++++++++++++++++++------- Geekbot.net/Program.cs | 3 +-- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/Geekbot.net/Lib/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandler.cs index 4320df5..249c837 100644 --- a/Geekbot.net/Lib/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandler.cs @@ -18,7 +18,7 @@ namespace Geekbot.net.Lib public void HandleCommandException(Exception e, ICommandContext Context) { var errorMsg = - $"Error Occured while executing \"{Context.Message.Content}\", executed by \"{Context.User.Username}\""; + $"Error Occured while executing \"{Context.Message.Content}\", executed by \"{Context.User.Username}\", complete message was \"{Context.Message}\""; logger.Error(e, errorMsg); // await botOwnerDmChannel.SendMessageAsync($"{errorMsg}```{e.StackTrace}```"); // await Context.Channel.SendMessageAsync("Something went wrong..."); diff --git a/Geekbot.net/Modules/UserInfo.cs b/Geekbot.net/Modules/UserInfo.cs index faf6543..21fc618 100644 --- a/Geekbot.net/Modules/UserInfo.cs +++ b/Geekbot.net/Modules/UserInfo.cs @@ -1,5 +1,8 @@ using System; +using System.Collections; +using System.Collections.Generic; using System.Linq; +using System.Runtime.InteropServices.ComTypes; using System.Text; using System.Threading.Tasks; using Discord; @@ -70,19 +73,33 @@ namespace Geekbot.net.Modules try { var messageList = redis.HashGetAll($"{Context.Guild.Id}:Messages"); - var sortedList = messageList.OrderByDescending(e => e.Value).ToList().Take(11).ToList(); + var sortedList = messageList.OrderByDescending(e => e.Value).ToList(); var guildMessages = (int) sortedList.First().Value; sortedList.RemoveAt(0); - var highScore = new StringBuilder(); - highScore.AppendLine($":bar_chart: **Highscore for {Context.Guild.Name}**"); - var counter = 1; + + var highscoreUsers = new Dictionary(); + var listLimiter = 1; foreach (var user in sortedList) { + if (listLimiter > 10) break; + var guildUser = Context.Guild.GetUserAsync((ulong) user.Name).Result; - var percent = Math.Round((double) (100 * (int) user.Value) / guildMessages, 2); + if (guildUser != null) + { + highscoreUsers.Add(guildUser, (int)user.Value); + listLimiter++; + } + } + + var highScore = new StringBuilder(); + highScore.AppendLine($":bar_chart: **Highscore for {Context.Guild.Name}**"); + var highscorePlace = 1; + foreach (var user in highscoreUsers) + { + var percent = Math.Round((double) (100 * user.Value) / guildMessages, 2); highScore.AppendLine( - $"{NumerToEmoji(counter)} **{guildUser.Username}#{guildUser.Discriminator}** - {percent}% of total - {user.Value} messages"); - counter++; + $"{NumerToEmoji(highscorePlace)} **{user.Key.Username}#{user.Key.Discriminator}** - {percent}% of total - {user.Value} messages"); + highscorePlace++; } await ReplyAsync(highScore.ToString()); } diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 455429b..d06b7ba 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -273,9 +273,8 @@ namespace Geekbot.net redis.HashSet($"{guildId}:Settings", new HashEntry[] { new HashEntry("WelcomeMsg", val) }); break; } - //redis.KeyDelete(key); - } + redis.KeyDelete(key); } } return Task.CompletedTask; From 0b680d7fb22a46ca0d5a730f0f8ccc450b4a4eb0 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Thu, 28 Sep 2017 18:55:57 +0200 Subject: [PATCH 034/553] new Quote command and bugfixes --- Geekbot.net/Lib/ErrorHandler.cs | 8 +- Geekbot.net/Modules/AdminCmd.cs | 12 +-- Geekbot.net/Modules/Quote.cs | 163 ++++++++++++++++++++++++++++++++ Geekbot.net/Modules/UserInfo.cs | 2 +- 4 files changed, 176 insertions(+), 9 deletions(-) create mode 100644 Geekbot.net/Modules/Quote.cs diff --git a/Geekbot.net/Lib/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandler.cs index 249c837..5ded3a2 100644 --- a/Geekbot.net/Lib/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandler.cs @@ -15,11 +15,15 @@ namespace Geekbot.net.Lib // this.botOwnerDmChannel = botOwnerDmChannel; } - public void HandleCommandException(Exception e, ICommandContext Context) + public void HandleCommandException(Exception e, ICommandContext Context, string errorMessage = "") { var errorMsg = $"Error Occured while executing \"{Context.Message.Content}\", executed by \"{Context.User.Username}\", complete message was \"{Context.Message}\""; logger.Error(e, errorMsg); + if (!string.IsNullOrEmpty(errorMessage)) + { + Context.Channel.SendMessageAsync(errorMessage); + } // await botOwnerDmChannel.SendMessageAsync($"{errorMsg}```{e.StackTrace}```"); // await Context.Channel.SendMessageAsync("Something went wrong..."); } @@ -27,6 +31,6 @@ namespace Geekbot.net.Lib public interface IErrorHandler { - void HandleCommandException(Exception e, ICommandContext Context); + void HandleCommandException(Exception e, ICommandContext Context, string errorMessage = ""); } } \ No newline at end of file diff --git a/Geekbot.net/Modules/AdminCmd.cs b/Geekbot.net/Modules/AdminCmd.cs index ac7ba2f..2229469 100644 --- a/Geekbot.net/Modules/AdminCmd.cs +++ b/Geekbot.net/Modules/AdminCmd.cs @@ -36,10 +36,10 @@ namespace Geekbot.net.Modules [Summary("Set the youtube api key")] public async Task SetYoutubeKey([Summary("API Key")] string key) { - var botOwner = redis.StringGet("botOwner"); - if (!Context.User.Id.ToString().Equals(botOwner.ToString())) + var botOwner = Context.Guild.GetUserAsync(ulong.Parse(redis.StringGet("botOwner"))).Result; + if (!Context.User.Id.ToString().Equals(botOwner.Id.ToString())) { - await ReplyAsync($"Sorry, only the botowner can do this ({botOwner}"); + await ReplyAsync($"Sorry, only the botowner can do this ({botOwner.Username}#{botOwner.Discriminator})"); return; } @@ -51,10 +51,10 @@ namespace Geekbot.net.Modules [Summary("Set the game that the bot is playing")] public async Task SetGame([Remainder] [Summary("Game")] string key) { - var botOwner = redis.StringGet("botOwner"); - if (!Context.User.Id.ToString().Equals(botOwner.ToString())) + var botOwner = Context.Guild.GetUserAsync(ulong.Parse(redis.StringGet("botOwner"))).Result; + if (!Context.User.Id.ToString().Equals(botOwner.Id.ToString())) { - await ReplyAsync($"Sorry, only the botowner can do this ({botOwner}"); + await ReplyAsync($"Sorry, only the botowner can do this ({botOwner.Username}#{botOwner.Discriminator})"); return; } diff --git a/Geekbot.net/Modules/Quote.cs b/Geekbot.net/Modules/Quote.cs new file mode 100644 index 0000000..107b036 --- /dev/null +++ b/Geekbot.net/Modules/Quote.cs @@ -0,0 +1,163 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Geekbot.net.Lib; +using Microsoft.Extensions.Configuration; +using Newtonsoft.Json; +using Serilog; +using StackExchange.Redis; + +namespace Geekbot.net.Modules +{ + [Group("quote")] + public class Quote : ModuleBase + { + private readonly IDatabase redis; + private readonly ILogger logger; + private readonly IErrorHandler errorHandler; + + public Quote(IDatabase redis, ILogger logger, IErrorHandler errorHandler) + { + this.redis = redis; + this.logger = logger; + this.errorHandler = errorHandler; + } + + [Command()] + [Summary("Return a random quoute from the database")] + public async Task getRandomQuote() + { + var randomQuote = redis.SetRandomMember($"{Context.Guild.Id}:Quotes"); + try + { + var quote = JsonConvert.DeserializeObject(randomQuote); + var embed = quoteBuilder(quote); + await ReplyAsync("", false, embed.Build()); + } + catch (Exception e) + { + errorHandler.HandleCommandException(e, Context, "Whoops, seems like the quote was to edgy to return"); + } + } + + [Command("save")] + [Summary("Save a quote from the last sent message by @user")] + public async Task saveQuote([Summary("@user")] IUser user) + { + try + { + var lastMessage = await getLastMessageByUser(user); + var quote = new QuoteObject() + { + userId = user.Id, + time = DateTime.Now, + quote = lastMessage.Content + }; + var quoteStore = JsonConvert.SerializeObject(quote); + redis.SetAdd($"{Context.Guild.Id}:Quotes", quoteStore); + await ReplyAsync("Quote Added"); + } + catch (Exception e) + { + errorHandler.HandleCommandException(e, Context, "I counldn't find a quote from that user :disappointed:"); + } + } + + [Command("save")] + [Summary("Save a quote from a message id")] + public async Task saveQuote([Summary("messageId")] ulong messageId) + { + try + { + var message = await Context.Channel.GetMessageAsync(messageId); + var quote = new QuoteObject() + { + userId = message.Author.Id, + time = DateTime.Now, + quote = message.Content + }; + var quoteStore = JsonConvert.SerializeObject(quote); + redis.SetAdd($"{Context.Guild.Id}:Quotes", quoteStore); + await ReplyAsync("Quote Added"); + } + catch (Exception e) + { + errorHandler.HandleCommandException(e, Context, "I couldn't find a message with that id :disappointed:"); + } + } + + [Command("make")] + [Summary("Create a quote from the last sent message by @user")] + public async Task returnSpecifiedQuote([Summary("@user")] IUser user) + { + try + { + var lastMessage = await getLastMessageByUser(user); + var quote = new QuoteObject() + { + userId = user.Id, + time = DateTime.Now, + quote = lastMessage.Content + }; + var embed = quoteBuilder(quote); + await ReplyAsync("", false, embed.Build()); + } + catch (Exception e) + { + errorHandler.HandleCommandException(e, Context, "I counldn't find a quote from that user :disappointed:"); + } + } + + [Command("make")] + [Summary("Create a quote from a message id")] + public async Task returnSpecifiedQuote([Summary("messageId")] ulong messageId) + { + try + { + var message = await Context.Channel.GetMessageAsync(messageId); + var quote = new QuoteObject() + { + userId = message.Author.Id, + time = DateTime.Now, + quote = message.Content + }; + var embed = quoteBuilder(quote); + await ReplyAsync("", false, embed.Build()); + } + catch (Exception e) + { + errorHandler.HandleCommandException(e, Context, "I couldn't find a message with that id :disappointed:"); + } + } + + private async Task getLastMessageByUser(IUser user) + { + Task> list = Context.Channel.GetMessagesAsync().Flatten(); + await list; + return list.Result.Where(msg => + msg.Author.Id == user.Id + && msg.Embeds.Count == 0 + && msg.Id != Context.Message.Id) + .First(); + } + + private EmbedBuilder quoteBuilder(QuoteObject quote) + { + var user = Context.Client.GetUserAsync(quote.userId).Result; + var eb = new EmbedBuilder(); + + eb.ThumbnailUrl = user.GetAvatarUrl(); + eb.AddField(quote.quote, $"-- {user.Username} - {quote.time.Day}.{quote.time.Month}.{quote.time.Year}"); + return eb; + } + } + + public class QuoteObject { + public ulong userId { get; set; } + public DateTime time { get; set; } + public string quote { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Modules/UserInfo.cs b/Geekbot.net/Modules/UserInfo.cs index 21fc618..4514b13 100644 --- a/Geekbot.net/Modules/UserInfo.cs +++ b/Geekbot.net/Modules/UserInfo.cs @@ -111,7 +111,7 @@ namespace Geekbot.net.Modules private string NumerToEmoji(int number) { - var emojis = new string[] {":one:", ":two:", ":three:", ":four:", ":five:", ":six", ":seven:", ":eight:", ":nine:", ":keycap_ten:"}; + var emojis = new string[] {":one:", ":two:", ":three:", ":four:", ":five:", ":six:", ":seven:", ":eight:", ":nine:", ":keycap_ten:"}; try { return emojis[number - 1]; From 9f4e23ff20cbbd00225db6f9baadded187879baf Mon Sep 17 00:00:00 2001 From: Runebaas Date: Fri, 29 Sep 2017 00:18:31 +0200 Subject: [PATCH 035/553] Quotes now have image support and a new look --- Geekbot.net/Modules/Quote.cs | 68 ++++++++++++++++++++---------------- Geekbot.net/Program.cs | 2 +- 2 files changed, 38 insertions(+), 32 deletions(-) diff --git a/Geekbot.net/Modules/Quote.cs b/Geekbot.net/Modules/Quote.cs index 107b036..8737c0a 100644 --- a/Geekbot.net/Modules/Quote.cs +++ b/Geekbot.net/Modules/Quote.cs @@ -50,12 +50,7 @@ namespace Geekbot.net.Modules try { var lastMessage = await getLastMessageByUser(user); - var quote = new QuoteObject() - { - userId = user.Id, - time = DateTime.Now, - quote = lastMessage.Content - }; + var quote = createQuoteObject(lastMessage); var quoteStore = JsonConvert.SerializeObject(quote); redis.SetAdd($"{Context.Guild.Id}:Quotes", quoteStore); await ReplyAsync("Quote Added"); @@ -73,12 +68,7 @@ namespace Geekbot.net.Modules try { var message = await Context.Channel.GetMessageAsync(messageId); - var quote = new QuoteObject() - { - userId = message.Author.Id, - time = DateTime.Now, - quote = message.Content - }; + var quote = createQuoteObject(message); var quoteStore = JsonConvert.SerializeObject(quote); redis.SetAdd($"{Context.Guild.Id}:Quotes", quoteStore); await ReplyAsync("Quote Added"); @@ -96,12 +86,7 @@ namespace Geekbot.net.Modules try { var lastMessage = await getLastMessageByUser(user); - var quote = new QuoteObject() - { - userId = user.Id, - time = DateTime.Now, - quote = lastMessage.Content - }; + var quote = createQuoteObject(lastMessage); var embed = quoteBuilder(quote); await ReplyAsync("", false, embed.Build()); } @@ -118,12 +103,7 @@ namespace Geekbot.net.Modules try { var message = await Context.Channel.GetMessageAsync(messageId); - var quote = new QuoteObject() - { - userId = message.Author.Id, - time = DateTime.Now, - quote = message.Content - }; + var quote = createQuoteObject(message); var embed = quoteBuilder(quote); await ReplyAsync("", false, embed.Build()); } @@ -137,27 +117,53 @@ namespace Geekbot.net.Modules { Task> list = Context.Channel.GetMessagesAsync().Flatten(); await list; - return list.Result.Where(msg => - msg.Author.Id == user.Id + return list.Result + .First(msg => msg.Author.Id == user.Id && msg.Embeds.Count == 0 - && msg.Id != Context.Message.Id) - .First(); + && msg.Id != Context.Message.Id + && !msg.Content.ToLower().StartsWith("!")); } private EmbedBuilder quoteBuilder(QuoteObject quote) { var user = Context.Client.GetUserAsync(quote.userId).Result; var eb = new EmbedBuilder(); - + eb.WithColor(new Color(143, 167, 232)); + eb.Title = $"{user.Username} @ {quote.time.Day}.{quote.time.Month}.{quote.time.Year}"; + eb.Description = quote.quote; eb.ThumbnailUrl = user.GetAvatarUrl(); - eb.AddField(quote.quote, $"-- {user.Username} - {quote.time.Day}.{quote.time.Month}.{quote.time.Year}"); + if (quote.image != null) + { + eb.ImageUrl = quote.image; + } return eb; } + + private QuoteObject createQuoteObject(IMessage message) + { + string image; + try + { + image = message.Attachments.First().Url; + } + catch (Exception) + { + image = null; + } + return new QuoteObject() + { + userId = message.Author.Id, + time = message.Timestamp.DateTime, + quote = message.Content, + image = image + }; + } } public class QuoteObject { public ulong userId { get; set; } - public DateTime time { get; set; } public string quote { get; set; } + public DateTime time { get; set; } + public string image { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index d06b7ba..6c3bede 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -238,7 +238,7 @@ namespace Geekbot.net return Task.CompletedTask; } - // temporary db migration script + // db migration script private Task MigrateDatabaseToHash() { foreach (var key in redis.Multiplexer.GetServer("127.0.0.1", 6379).Keys(6)) From 98a13c9069d6c807ffd53e9eb788ffd5c20d5ea0 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Fri, 29 Sep 2017 01:23:52 +0200 Subject: [PATCH 036/553] Highscores Bugfix, small stats changes --- Geekbot.net/Modules/UserInfo.cs | 65 +++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/Geekbot.net/Modules/UserInfo.cs b/Geekbot.net/Modules/UserInfo.cs index 4514b13..df2f3d9 100644 --- a/Geekbot.net/Modules/UserInfo.cs +++ b/Geekbot.net/Modules/UserInfo.cs @@ -1,8 +1,6 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Linq; -using System.Runtime.InteropServices.ComTypes; using System.Text; using System.Threading.Tasks; using Discord; @@ -35,18 +33,17 @@ namespace Geekbot.net.Modules var age = Math.Floor((DateTime.Now - userInfo.CreatedAt).TotalDays); var messages = (int) redis.HashGet($"{Context.Guild.Id}:Messages", userInfo.Id.ToString()); - var level = LevelCalc.GetLevelAtExperience(messages); - - var guildKey = Context.Guild.Id.ToString(); var guildMessages = (int) redis.HashGet($"{Context.Guild.Id}:Messages", 0.ToString()); + var level = LevelCalc.GetLevelAtExperience(messages); var percent = Math.Round((double) (100 * messages) / guildMessages, 2); var eb = new EmbedBuilder(); - eb.WithAuthor(new EmbedAuthorBuilder() - .WithIconUrl(userInfo.GetAvatarUrl()) - .WithName(userInfo.Username)); - +// eb.WithAuthor(new EmbedAuthorBuilder() +// .WithIconUrl(userInfo.GetAvatarUrl()) +// .WithName(userInfo.Username)); + eb.Title = $":bar_chart: {userInfo.Username}#{userInfo.Discriminator}"; + eb.ThumbnailUrl = userInfo.GetAvatarUrl(); eb.WithColor(new Color(221, 255, 119)); eb.AddField("Discordian Since", @@ -77,28 +74,57 @@ namespace Geekbot.net.Modules var guildMessages = (int) sortedList.First().Value; sortedList.RemoveAt(0); - var highscoreUsers = new Dictionary(); + var highscoreUsers = new Dictionary(); var listLimiter = 1; + var failedToRetrieveUser = false; foreach (var user in sortedList) { if (listLimiter > 10) break; - - var guildUser = Context.Guild.GetUserAsync((ulong) user.Name).Result; - if (guildUser != null) + try { - highscoreUsers.Add(guildUser, (int)user.Value); + var guildUser = Context.Guild.GetUserAsync((ulong) user.Name).Result; + if (guildUser != null) + { + highscoreUsers.Add(new RankUserPolyfill() + { + Username = guildUser.Username, + Discriminator = guildUser.Discriminator + }, (int) user.Value); + } + else + { + highscoreUsers.Add(new RankUserPolyfill() + { + Id = user.Name + }, (int) user.Value); + failedToRetrieveUser = true; + } listLimiter++; } + catch (Exception e) + { + logger.Warning(e, $"Could not retrieve user {user.Name}"); + } + } var highScore = new StringBuilder(); + if (failedToRetrieveUser) highScore.AppendLine(":warning: I couldn't get all userdata, i mentioned the missing ones, sorry!\n"); highScore.AppendLine($":bar_chart: **Highscore for {Context.Guild.Name}**"); var highscorePlace = 1; foreach (var user in highscoreUsers) { var percent = Math.Round((double) (100 * user.Value) / guildMessages, 2); - highScore.AppendLine( - $"{NumerToEmoji(highscorePlace)} **{user.Key.Username}#{user.Key.Discriminator}** - {percent}% of total - {user.Value} messages"); + if (user.Key.Username != null) + { + highScore.AppendLine( + $"{NumerToEmoji(highscorePlace)} **{user.Key.Username}#{user.Key.Discriminator}** - {percent}% of total - {user.Value} messages"); + } + else + { + highScore.AppendLine( + $"{NumerToEmoji(highscorePlace)} **<@{user.Key.Id}>** - {percent}% of total - {user.Value} messages"); + } highscorePlace++; } await ReplyAsync(highScore.ToString()); @@ -123,4 +149,11 @@ namespace Geekbot.net.Modules } } } + + class RankUserPolyfill + { + public string Username { get; set; } + public string Discriminator { get; set; } + public string Id { get; set; } + } } \ No newline at end of file From b1f4e8ad93209d595677de37d2fa0f747ca3ca78 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Fri, 29 Sep 2017 01:32:15 +0200 Subject: [PATCH 037/553] Updating server stats embed to be uniform with user stats --- Geekbot.net/Modules/GuildInfo.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Geekbot.net/Modules/GuildInfo.cs b/Geekbot.net/Modules/GuildInfo.cs index 11a3d44..3bc9b6f 100644 --- a/Geekbot.net/Modules/GuildInfo.cs +++ b/Geekbot.net/Modules/GuildInfo.cs @@ -22,10 +22,12 @@ namespace Geekbot.net.Modules public async Task getInfo() { var eb = new EmbedBuilder(); - eb.WithAuthor(new EmbedAuthorBuilder() - .WithIconUrl(Context.Guild.IconUrl) - .WithName(Context.Guild.Name)); +// eb.WithAuthor(new EmbedAuthorBuilder() +// .WithIconUrl(Context.Guild.IconUrl) +// .WithName(Context.Guild.Name)); eb.WithColor(new Color(110, 204, 147)); + eb.Title = $":bar_chart: {Context.Guild.Name}"; + eb.ThumbnailUrl = Context.Guild.IconUrl; var created = Context.Guild.CreatedAt; var age = Math.Floor((DateTime.Now - created).TotalDays); From a549950ad966b8e3dfebeb618caf7f85b774ec9c Mon Sep 17 00:00:00 2001 From: Runebaas Date: Fri, 29 Sep 2017 20:30:00 +0200 Subject: [PATCH 038/553] Async Stuff, !rank doesn't mention anymore, setup finalizer, minor tweaks --- Geekbot.net/Modules/GuildInfo.cs | 8 ++-- Geekbot.net/Modules/Quote.cs | 7 +++- Geekbot.net/Modules/UserInfo.cs | 12 +++--- Geekbot.net/Program.cs | 72 ++++++++++++++++++++------------ 4 files changed, 59 insertions(+), 40 deletions(-) diff --git a/Geekbot.net/Modules/GuildInfo.cs b/Geekbot.net/Modules/GuildInfo.cs index 3bc9b6f..11a3d44 100644 --- a/Geekbot.net/Modules/GuildInfo.cs +++ b/Geekbot.net/Modules/GuildInfo.cs @@ -22,12 +22,10 @@ namespace Geekbot.net.Modules public async Task getInfo() { var eb = new EmbedBuilder(); -// eb.WithAuthor(new EmbedAuthorBuilder() -// .WithIconUrl(Context.Guild.IconUrl) -// .WithName(Context.Guild.Name)); + eb.WithAuthor(new EmbedAuthorBuilder() + .WithIconUrl(Context.Guild.IconUrl) + .WithName(Context.Guild.Name)); eb.WithColor(new Color(110, 204, 147)); - eb.Title = $":bar_chart: {Context.Guild.Name}"; - eb.ThumbnailUrl = Context.Guild.IconUrl; var created = Context.Guild.CreatedAt; var age = Math.Floor((DateTime.Now - created).TotalDays); diff --git a/Geekbot.net/Modules/Quote.cs b/Geekbot.net/Modules/Quote.cs index 8737c0a..49e10ab 100644 --- a/Geekbot.net/Modules/Quote.cs +++ b/Geekbot.net/Modules/Quote.cs @@ -53,7 +53,8 @@ namespace Geekbot.net.Modules var quote = createQuoteObject(lastMessage); var quoteStore = JsonConvert.SerializeObject(quote); redis.SetAdd($"{Context.Guild.Id}:Quotes", quoteStore); - await ReplyAsync("Quote Added"); + var embed = quoteBuilder(quote); + await ReplyAsync("**Quote Added**", false, embed.Build()); } catch (Exception e) { @@ -71,7 +72,9 @@ namespace Geekbot.net.Modules var quote = createQuoteObject(message); var quoteStore = JsonConvert.SerializeObject(quote); redis.SetAdd($"{Context.Guild.Id}:Quotes", quoteStore); - await ReplyAsync("Quote Added"); + var embed = quoteBuilder(quote); + await ReplyAsync("**Quote Added**", false, embed.Build()); + } catch (Exception e) { diff --git a/Geekbot.net/Modules/UserInfo.cs b/Geekbot.net/Modules/UserInfo.cs index df2f3d9..83411a3 100644 --- a/Geekbot.net/Modules/UserInfo.cs +++ b/Geekbot.net/Modules/UserInfo.cs @@ -39,11 +39,9 @@ namespace Geekbot.net.Modules var percent = Math.Round((double) (100 * messages) / guildMessages, 2); var eb = new EmbedBuilder(); -// eb.WithAuthor(new EmbedAuthorBuilder() -// .WithIconUrl(userInfo.GetAvatarUrl()) -// .WithName(userInfo.Username)); - eb.Title = $":bar_chart: {userInfo.Username}#{userInfo.Discriminator}"; - eb.ThumbnailUrl = userInfo.GetAvatarUrl(); + eb.WithAuthor(new EmbedAuthorBuilder() + .WithIconUrl(userInfo.GetAvatarUrl()) + .WithName(userInfo.Username)); eb.WithColor(new Color(221, 255, 119)); eb.AddField("Discordian Since", @@ -109,7 +107,7 @@ namespace Geekbot.net.Modules } var highScore = new StringBuilder(); - if (failedToRetrieveUser) highScore.AppendLine(":warning: I couldn't get all userdata, i mentioned the missing ones, sorry!\n"); + if (failedToRetrieveUser) highScore.AppendLine(":warning: I couldn't get all userdata, sorry! (bugfix coming soon:tm:)\n"); highScore.AppendLine($":bar_chart: **Highscore for {Context.Guild.Name}**"); var highscorePlace = 1; foreach (var user in highscoreUsers) @@ -123,7 +121,7 @@ namespace Geekbot.net.Modules else { highScore.AppendLine( - $"{NumerToEmoji(highscorePlace)} **<@{user.Key.Id}>** - {percent}% of total - {user.Value} messages"); + $"{NumerToEmoji(highscorePlace)} **{user.Key.Id}** - {percent}% of total - {user.Value} messages"); } highscorePlace++; } diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 6c3bede..5cb003f 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Net; using System.Reflection; using System.Text; using System.Threading.Tasks; @@ -24,7 +26,8 @@ namespace Geekbot.net private IServiceProvider servicesProvider; private RedisValue token; private ILogger logger; - private ulong botOwnerId; + private string[] args; + private bool firstStart = false; private static void Main(string[] args) { @@ -44,6 +47,7 @@ namespace Geekbot.net private async Task MainAsync(string[] args, ILogger logger) { this.logger = logger; + this.args = args; logger.Information("[Geekbot] Initing Stuff"); client = new DiscordSocketClient(new DiscordSocketConfig @@ -91,17 +95,9 @@ namespace Geekbot.net redis.StringSet("discordToken", newToken); redis.StringSet("Game", "Ping Pong"); token = newToken; + firstStart = true; } - var botOwner = redis.StringGet("botOwner"); - if (botOwner.IsNullOrEmpty) - { - Console.Write("Bot Owner User ID: "); - botOwner = Console.ReadLine(); - redis.StringSet("botOwner", botOwner); - } - botOwnerId = (ulong) botOwner; - services = new ServiceCollection(); var RandomClient = new Random(); var fortunes = new FortunesProvider(RandomClient, logger); @@ -144,7 +140,15 @@ namespace Geekbot.net await commands.AddModulesAsync(Assembly.GetEntryAssembly()); services.AddSingleton(commands); services.AddSingleton(client); - this.servicesProvider = services.BuildServiceProvider(); + servicesProvider = services.BuildServiceProvider(); + + if (firstStart || (args.Length != 0 && args.Contains("--reset"))) + { + logger.Information("[Geekbot] Finishing setup"); + await FinishSetup(); + logger.Information("[Geekbot] Setup finished"); + } + logger.Information("[Geekbot] Done and ready for use\n"); } } @@ -162,44 +166,46 @@ namespace Geekbot.net return true; } - private async Task HandleCommand(SocketMessage messageParam) + private Task HandleCommand(SocketMessage messageParam) { var message = messageParam as SocketUserMessage; - if (message == null) return; - if (message.Author.IsBot) return; + if (message == null) return Task.CompletedTask; + if (message.Author.IsBot) return Task.CompletedTask; var argPos = 0; var lowCaseMsg = message.ToString().ToLower(); if (lowCaseMsg.StartsWith("ping")) { - await message.Channel.SendMessageAsync("pong"); - return; + message.Channel.SendMessageAsync("pong"); + return Task.CompletedTask; } if (lowCaseMsg.StartsWith("hui")) { - await message.Channel.SendMessageAsync("hui!!!"); - return; + message.Channel.SendMessageAsync("hui!!!"); + return Task.CompletedTask; } if (!(message.HasCharPrefix('!', ref argPos) || - message.HasMentionPrefix(client.CurrentUser, ref argPos))) return; + message.HasMentionPrefix(client.CurrentUser, ref argPos))) return Task.CompletedTask; var context = new CommandContext(client, message); var commandExec = commands.ExecuteAsync(context, argPos, servicesProvider); + return Task.CompletedTask; } - private async Task HandleMessageReceived(SocketMessage messsageParam) + private Task HandleMessageReceived(SocketMessage messsageParam) { var message = messsageParam; - if (message == null) return; + if (message == null) return Task.CompletedTask; var channel = (SocketGuildChannel) message.Channel; - await redis.HashIncrementAsync($"{channel.Guild.Id}:Messages", message.Author.Id.ToString()); - await redis.HashIncrementAsync($"{channel.Guild.Id}:Messages", 0.ToString()); + redis.HashIncrementAsync($"{channel.Guild.Id}:Messages", message.Author.Id.ToString()); + redis.HashIncrementAsync($"{channel.Guild.Id}:Messages", 0.ToString()); - if (message.Author.IsBot) return; + if (message.Author.IsBot) return Task.CompletedTask; logger.Information($"[Message] {channel.Guild.Name} - {message.Channel} - {message.Author.Username} - {message.Content}"); + return Task.CompletedTask; } - private async Task HandleUserJoined(SocketGuildUser user) + private Task HandleUserJoined(SocketGuildUser user) { if (!user.IsBot) { @@ -207,9 +213,23 @@ namespace Geekbot.net if (!message.IsNullOrEmpty) { message = message.ToString().Replace("$user", user.Mention); - await user.Guild.DefaultChannel.SendMessageAsync(message); + user.Guild.DefaultChannel.SendMessageAsync(message); } } + return Task.CompletedTask; + } + + private async Task FinishSetup() + { + var appInfo = await client.GetApplicationInfoAsync(); + redis.StringSet("botOwner", appInfo.Owner.Id); + + var req = HttpWebRequest.Create(appInfo.IconUrl); + using (Stream stream = req.GetResponse().GetResponseStream() ) + { + await client.CurrentUser.ModifyAsync(Avatar => new Image(stream)); + } + return Task.CompletedTask; } private Task DiscordLogger(LogMessage message) From 6dcfeabfbdb199c40f52e7fc73a8b678170232a7 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sat, 30 Sep 2017 01:38:10 +0200 Subject: [PATCH 039/553] UserRepository, Handler now have own class, uptime in !info --- Geekbot.net/Handlers.cs | 100 ++++++++++++++++++++++++++++++ Geekbot.net/Lib/UserRepository.cs | 84 +++++++++++++++++++++++++ Geekbot.net/Modules/AdminCmd.cs | 72 ++++++++++++++++----- Geekbot.net/Modules/Info.cs | 41 +++++++----- Geekbot.net/Modules/UserInfo.cs | 67 +++++++++++--------- Geekbot.net/Program.cs | 75 +++++----------------- 6 files changed, 322 insertions(+), 117 deletions(-) create mode 100644 Geekbot.net/Handlers.cs create mode 100644 Geekbot.net/Lib/UserRepository.cs diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs new file mode 100644 index 0000000..6c25104 --- /dev/null +++ b/Geekbot.net/Handlers.cs @@ -0,0 +1,100 @@ +using System; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Discord.WebSocket; +using Geekbot.net.Lib; +using Serilog; +using StackExchange.Redis; + +namespace Geekbot.net +{ + public class Handlers + { + private readonly IDiscordClient _client; + private readonly ILogger _logger; + private readonly IDatabase _redis; + private readonly IServiceProvider _servicesProvider; + private readonly CommandService _commands; + private readonly IUserRepository _userRepository; + + public Handlers(IDiscordClient client, ILogger logger, IDatabase redis, IServiceProvider servicesProvider, CommandService commands, IUserRepository userRepository) + { + _client = client; + _logger = logger; + _redis = redis; + _servicesProvider = servicesProvider; + _commands = commands; + _userRepository = userRepository; + } + + // + // Incoming Messages + // + + public Task RunCommand(SocketMessage messageParam) + { + var message = messageParam as SocketUserMessage; + if (message == null) return Task.CompletedTask; + if (message.Author.IsBot) return Task.CompletedTask; + var argPos = 0; + var lowCaseMsg = message.ToString().ToLower(); + if (lowCaseMsg.StartsWith("ping")) + { + message.Channel.SendMessageAsync("pong"); + return Task.CompletedTask; + } + if (lowCaseMsg.StartsWith("hui")) + { + message.Channel.SendMessageAsync("hui!!!"); + return Task.CompletedTask; + } + if (!(message.HasCharPrefix('!', ref argPos) || + message.HasMentionPrefix(_client.CurrentUser, ref argPos))) return Task.CompletedTask; + var context = new CommandContext(_client, message); + var commandExec = _commands.ExecuteAsync(context, argPos, _servicesProvider); + return Task.CompletedTask; + } + + public Task UpdateStats(SocketMessage messsageParam) + { + var message = messsageParam; + if (message == null) return Task.CompletedTask; + + var channel = (SocketGuildChannel) message.Channel; + + _redis.HashIncrementAsync($"{channel.Guild.Id}:Messages", message.Author.Id.ToString()); + _redis.HashIncrementAsync($"{channel.Guild.Id}:Messages", 0.ToString()); + + if (message.Author.IsBot) return Task.CompletedTask; + _logger.Information($"[Message] {channel.Guild.Name} - {message.Channel} - {message.Author.Username} - {message.Content}"); + return Task.CompletedTask; + } + + // + // User Stuff + // + + public Task UserJoined(SocketGuildUser user) + { + if (!user.IsBot) + { + var message = _redis.HashGet($"{user.Guild.Id}:Settings", "WelcomeMsg"); + if (!message.IsNullOrEmpty) + { + message = message.ToString().Replace("$user", user.Mention); + user.Guild.DefaultChannel.SendMessageAsync(message); + } + } + _userRepository.Update(user); + _logger.Information($"[Geekbot] {user.Id} ({user.Username}) joined {user.Guild.Id} ({user.Guild.Name})"); + return Task.CompletedTask; + } + + public Task UserUpdated(SocketUser oldUser, SocketUser newUser) + { + _userRepository.Update(newUser); + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/UserRepository.cs b/Geekbot.net/Lib/UserRepository.cs new file mode 100644 index 0000000..71faba3 --- /dev/null +++ b/Geekbot.net/Lib/UserRepository.cs @@ -0,0 +1,84 @@ +using System; +using System.Threading.Tasks; +using Discord.WebSocket; +using Serilog; +using StackExchange.Redis; + +namespace Geekbot.net.Lib +{ + public class UserRepository : IUserRepository + { + private readonly IDatabase _redis; + private readonly ILogger _logger; + public UserRepository(IDatabase redis, ILogger logger) + { + _redis = redis; + _logger = logger; + } + + public Task Update(SocketUser user) + { + try + { + _redis.HashSetAsync($"Users:{user.Id}", new HashEntry[] + { + new HashEntry("Id", user.Id.ToString()), + new HashEntry("Username", user.Username), + new HashEntry("Discriminator", user.Discriminator), + new HashEntry("AvatarUrl", user.GetAvatarUrl() ?? "0"), + new HashEntry("IsBot", user.IsBot), + }); + _logger.Information($"[UserRepository] Updated User {user.Id}"); + return Task.FromResult(true); + } + catch (Exception e) + { + _logger.Warning(e, $"[UserRepository] Failed to update {user.Id}"); + return Task.FromResult(false); + } + } + + public UserRepositoryUser Get(ulong userId) + { + var user = _redis.HashGetAll($"Users:{userId}").ToDictionary(); + var dto = new UserRepositoryUser(); + foreach (var a in user) + { + switch (a.Key) + { + case "Id": + dto.Id = ulong.Parse(a.Value); + break; + case "Username": + dto.Username = a.Value.ToString(); + break; + case "Discriminator": + dto.Discriminator = a.Value.ToString(); + break; + case "AvatarUrl": + dto.AvatarUrl = (a.Value != "0") ? a.Value.ToString() : null; + break; + case "IsBot": + dto.IsBot = a.Value == 1; + break; + } + } + return dto; + } + } + + public class UserRepositoryUser + { + public ulong Id { get; set; } + public string Username { get; set; } + public string Discriminator { get; set; } + public string AvatarUrl { get; set; } + public bool IsBot { get; set; } + } + + public interface IUserRepository + { + Task Update(SocketUser user); + UserRepositoryUser Get(ulong userId); + } +} \ No newline at end of file diff --git a/Geekbot.net/Modules/AdminCmd.cs b/Geekbot.net/Modules/AdminCmd.cs index 2229469..ea2bc05 100644 --- a/Geekbot.net/Modules/AdminCmd.cs +++ b/Geekbot.net/Modules/AdminCmd.cs @@ -1,7 +1,10 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.WebSocket; +using Geekbot.net.Lib; +using Google.Apis.YouTube.v3.Data; using Serilog; using StackExchange.Redis; @@ -10,15 +13,19 @@ namespace Geekbot.net.Modules [Group("admin")] public class AdminCmd : ModuleBase { - private readonly IDatabase redis; - private readonly DiscordSocketClient client; - private readonly ILogger logger; + private readonly IDatabase _redis; + private readonly DiscordSocketClient _client; + private readonly ILogger _logger; + private readonly IUserRepository _userRepository; + private readonly IErrorHandler _errorHandler; - public AdminCmd(IDatabase redis, DiscordSocketClient client, ILogger logger) + public AdminCmd(IDatabase redis, DiscordSocketClient client, ILogger logger, IUserRepository userRepositry, IErrorHandler errorHandler) { - this.redis = redis; - this.client = client; - this.logger = logger; + _redis = redis; + _client = client; + _logger = logger; + _userRepository = userRepositry; + _errorHandler = errorHandler; } [RequireUserPermission(GuildPermission.Administrator)] @@ -26,7 +33,7 @@ namespace Geekbot.net.Modules [Summary("Set a Welcome Message (use '$user' to mention the new joined user).")] public async Task SetWelcomeMessage([Remainder] [Summary("message")] string welcomeMessage) { - redis.HashSet($"{Context.Guild.Id}:Settings", new HashEntry[] { new HashEntry("WelcomeMsg", welcomeMessage) }); + _redis.HashSet($"{Context.Guild.Id}:Settings", new HashEntry[] { new HashEntry("WelcomeMsg", welcomeMessage) }); var formatedMessage = welcomeMessage.Replace("$user", Context.User.Mention); await ReplyAsync("Welcome message has been changed\r\nHere is an example of how it would look:\r\n" + formatedMessage); @@ -36,14 +43,14 @@ namespace Geekbot.net.Modules [Summary("Set the youtube api key")] public async Task SetYoutubeKey([Summary("API Key")] string key) { - var botOwner = Context.Guild.GetUserAsync(ulong.Parse(redis.StringGet("botOwner"))).Result; + var botOwner = Context.Guild.GetUserAsync(ulong.Parse(_redis.StringGet("botOwner"))).Result; if (!Context.User.Id.ToString().Equals(botOwner.Id.ToString())) { await ReplyAsync($"Sorry, only the botowner can do this ({botOwner.Username}#{botOwner.Discriminator})"); return; } - redis.StringSet("youtubeKey", key); + _redis.StringSet("youtubeKey", key); await ReplyAsync("Apikey has been set"); } @@ -51,17 +58,52 @@ namespace Geekbot.net.Modules [Summary("Set the game that the bot is playing")] public async Task SetGame([Remainder] [Summary("Game")] string key) { - var botOwner = Context.Guild.GetUserAsync(ulong.Parse(redis.StringGet("botOwner"))).Result; + var botOwner = Context.Guild.GetUserAsync(ulong.Parse(_redis.StringGet("botOwner"))).Result; if (!Context.User.Id.ToString().Equals(botOwner.Id.ToString())) { await ReplyAsync($"Sorry, only the botowner can do this ({botOwner.Username}#{botOwner.Discriminator})"); return; } - redis.StringSet("Game", key); - await client.SetGameAsync(key); - logger.Information($"[Geekbot] Changed game to {key}"); + _redis.StringSet("Game", key); + await _client.SetGameAsync(key); + _logger.Information($"[Geekbot] Changed game to {key}"); await ReplyAsync($"Now Playing {key}"); } + + [Command("popuserrepo", RunMode = RunMode.Async)] + [Summary("Set the game that the bot is playing")] + public async Task popUserRepoCommand() + { + var botOwner = Context.Guild.GetUserAsync(ulong.Parse(_redis.StringGet("botOwner"))).Result; + if (!Context.User.Id.ToString().Equals(botOwner.Id.ToString())) + { + await ReplyAsync($"Sorry, only the botowner can do this ({botOwner.Username}#{botOwner.Discriminator})"); + return; + } + var success = 0; + var failed = 0; + try + { + _logger.Warning("[UserRepository] Populating User Repositry"); + await ReplyAsync("Starting Population of User Repository"); + foreach (var guild in _client.Guilds) + { + _logger.Information($"[UserRepository] Populating users from {guild.Name}"); + foreach (var user in guild.Users) + { + var succeded = await _userRepository.Update(user); + var inc = succeded ? success++ : failed++; + } + } + _logger.Warning("[UserRepository] Finished Updating User Repositry"); + await ReplyAsync($"Successfully Populated User Repository with {success} Users in {_client.Guilds.Count} Guilds (Failed: {failed})"); + } + catch (Exception e) + { + await ReplyAsync("Couldn't complete User Repository, see console for more info"); + _errorHandler.HandleCommandException(e, Context); + } + } } } \ No newline at end of file diff --git a/Geekbot.net/Modules/Info.cs b/Geekbot.net/Modules/Info.cs index 749594a..bf02862 100644 --- a/Geekbot.net/Modules/Info.cs +++ b/Geekbot.net/Modules/Info.cs @@ -1,36 +1,49 @@ -using System.Threading.Tasks; +using System; +using System.Diagnostics; +using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.net.Lib; using StackExchange.Redis; namespace Geekbot.net.Modules { public class Info : ModuleBase { - private readonly IDatabase redis; + private readonly IDatabase _redis; + private readonly IErrorHandler _errorHandler; - public Info(IDatabase redis) + public Info(IDatabase redis, IErrorHandler errorHandler) { - this.redis = redis; + _redis = redis; + _errorHandler = errorHandler; } [Command("info", RunMode = RunMode.Async)] [Summary("Get Information about the bot")] public async Task BotInfo() { - var eb = new EmbedBuilder(); + try + { + var eb = new EmbedBuilder(); - eb.WithTitle("Geekbot V3.2"); + eb.WithTitle("Geekbot V3.3"); - var botOwner = Context.Guild.GetUserAsync(ulong.Parse(redis.StringGet("botOwner"))).Result; + var botOwner = Context.Guild.GetUserAsync(ulong.Parse(_redis.StringGet("botOwner"))).Result; + var uptime = (DateTime.Now.Subtract(Process.GetCurrentProcess().StartTime)); + + eb.AddInlineField("Bot Name", Context.Client.CurrentUser.Username) + .AddInlineField("Servers", Context.Client.GetGuildsAsync().Result.Count) + .AddInlineField("Uptime", $"{uptime.Days}D {uptime.Hours}H {uptime.Minutes}M {uptime.Seconds}S") + .AddInlineField("Bot Owner", $"{botOwner.Username}#{botOwner.Discriminator}") + .AddInlineField("Website", "https://geekbot.pizzaandcoffee.rocks/"); - eb.AddInlineField("Status", Context.Client.ConnectionState.ToString()) - .AddInlineField("Bot Name", Context.Client.CurrentUser.Username) - .AddInlineField("Bot Owner", $"{botOwner.Username}#{botOwner.Discriminator}"); - - eb.AddInlineField("Servers", Context.Client.GetGuildsAsync().Result.Count); - - await ReplyAsync("", false, eb.Build()); + await ReplyAsync("", false, eb.Build()); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } } } } \ No newline at end of file diff --git a/Geekbot.net/Modules/UserInfo.cs b/Geekbot.net/Modules/UserInfo.cs index 83411a3..cb7725d 100644 --- a/Geekbot.net/Modules/UserInfo.cs +++ b/Geekbot.net/Modules/UserInfo.cs @@ -16,49 +16,60 @@ namespace Geekbot.net.Modules private readonly IDatabase redis; private readonly IErrorHandler errorHandler; private readonly ILogger logger; + private readonly IUserRepository userRepository; - public UserInfo(IDatabase redis, IErrorHandler errorHandler, ILogger logger) + public UserInfo(IDatabase redis, IErrorHandler errorHandler, ILogger logger, IUserRepository userRepository) { this.redis = redis; this.errorHandler = errorHandler; this.logger = logger; + this.userRepository = userRepository; } [Command("stats", RunMode = RunMode.Async)] [Summary("Get information about this user")] public async Task User([Summary("@someone")] IUser user = null) { - var userInfo = user ?? Context.Message.Author; + try + { + var userInfo = user ?? Context.Message.Author; + var userGuildInfo = (IGuildUser) userInfo; + var createdAt = userInfo.CreatedAt; + var joinedAt = userGuildInfo.JoinedAt.Value; + var age = Math.Floor((DateTime.Now - createdAt).TotalDays); + var joinedDayAgo = Math.Floor((DateTime.Now - joinedAt).TotalDays); - var age = Math.Floor((DateTime.Now - userInfo.CreatedAt).TotalDays); + var messages = (int) redis.HashGet($"{Context.Guild.Id}:Messages", userInfo.Id.ToString()); + var guildMessages = (int) redis.HashGet($"{Context.Guild.Id}:Messages", 0.ToString()); + var level = LevelCalc.GetLevelAtExperience(messages); - var messages = (int) redis.HashGet($"{Context.Guild.Id}:Messages", userInfo.Id.ToString()); - var guildMessages = (int) redis.HashGet($"{Context.Guild.Id}:Messages", 0.ToString()); - var level = LevelCalc.GetLevelAtExperience(messages); + var percent = Math.Round((double) (100 * messages) / guildMessages, 2); - var percent = Math.Round((double) (100 * messages) / guildMessages, 2); + var eb = new EmbedBuilder(); + eb.WithAuthor(new EmbedAuthorBuilder() + .WithIconUrl(userInfo.GetAvatarUrl()) + .WithName(userInfo.Username)); + eb.WithColor(new Color(221, 255, 119)); + + var karma = redis.HashGet($"{Context.Guild.Id}:Karma", userInfo.Id); + var correctRolls = redis.HashGet($"{Context.Guild.Id}:Rolls", userInfo.Id.ToString()); - var eb = new EmbedBuilder(); - eb.WithAuthor(new EmbedAuthorBuilder() - .WithIconUrl(userInfo.GetAvatarUrl()) - .WithName(userInfo.Username)); - eb.WithColor(new Color(221, 255, 119)); + eb.AddInlineField("Discordian Since", $"{createdAt.Day}.{createdAt.Month}.{createdAt.Year} ({age} days)") + .AddInlineField("Joined Server", $"{joinedAt.Day}.{joinedAt.Month}.{joinedAt.Year} ({joinedDayAgo} days)") + .AddInlineField("Karma", karma.ToString() ?? "0") + .AddInlineField("Level", level) + .AddInlineField("Messages Sent", messages) + .AddInlineField("Server Total", $"{percent}%"); - eb.AddField("Discordian Since", - $"{userInfo.CreatedAt.Day}/{userInfo.CreatedAt.Month}/{userInfo.CreatedAt.Year} ({age} days)"); - eb.AddInlineField("Level", level) - .AddInlineField("Messages Sent", messages) - .AddInlineField("Server Total", $"{percent}%"); + if (!correctRolls.IsNullOrEmpty) + eb.AddInlineField("Guessed Rolls", correctRolls); - var karma = redis.HashGet($"{Context.Guild.Id}:Karma", userInfo.Id.ToString()); - if (!karma.IsNullOrEmpty) - eb.AddInlineField("Karma", karma); - - var correctRolls = redis.HashGet($"{Context.Guild.Id}:Rolls", userInfo.Id.ToString()); - if (!correctRolls.IsNullOrEmpty) - eb.AddInlineField("Guessed Rolls", correctRolls); - - await ReplyAsync("", false, eb.Build()); + await ReplyAsync("", false, eb.Build()); + } + catch (Exception e) + { + errorHandler.HandleCommandException(e, Context); + } } [Command("rank", RunMode = RunMode.Async)] @@ -80,8 +91,8 @@ namespace Geekbot.net.Modules if (listLimiter > 10) break; try { - var guildUser = Context.Guild.GetUserAsync((ulong) user.Name).Result; - if (guildUser != null) + var guildUser = userRepository.Get((ulong)user.Name); + if (guildUser.Username != null) { highscoreUsers.Add(new RankUserPolyfill() { diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 5cb003f..12bdb73 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -26,6 +26,7 @@ namespace Geekbot.net private IServiceProvider servicesProvider; private RedisValue token; private ILogger logger; + private IUserRepository userRepository; private string[] args; private bool firstStart = false; @@ -99,16 +100,19 @@ namespace Geekbot.net } services = new ServiceCollection(); + + userRepository = new UserRepository(redis, logger); + var errorHandler = new ErrorHandler(logger); var RandomClient = new Random(); var fortunes = new FortunesProvider(RandomClient, logger); var checkEmImages = new CheckEmImageProvider(RandomClient, logger); var pandaImages = new PandaProvider(RandomClient, logger); - var errorHandler = new ErrorHandler(logger); services.AddSingleton(errorHandler); services.AddSingleton(redis); - services.AddSingleton(RandomClient); services.AddSingleton(logger); + services.AddSingleton(userRepository); + services.AddSingleton(RandomClient); services.AddSingleton(fortunes); services.AddSingleton(checkEmImages); services.AddSingleton(pandaImages); @@ -133,14 +137,18 @@ namespace Geekbot.net logger.Information($"[Geekbot] Now Connected to {client.Guilds.Count} Servers"); logger.Information("[Geekbot] Registering Stuff"); - - client.MessageReceived += HandleCommand; - client.MessageReceived += HandleMessageReceived; - client.UserJoined += HandleUserJoined; + await commands.AddModulesAsync(Assembly.GetEntryAssembly()); services.AddSingleton(commands); services.AddSingleton(client); servicesProvider = services.BuildServiceProvider(); + + var handlers = new Handlers(client, logger, redis, servicesProvider, commands, userRepository); + + client.MessageReceived += handlers.RunCommand; + client.MessageReceived += handlers.UpdateStats; + client.UserJoined += handlers.UserJoined; + client.UserUpdated += handlers.UserUpdated; if (firstStart || (args.Length != 0 && args.Contains("--reset"))) { @@ -166,59 +174,6 @@ namespace Geekbot.net return true; } - private Task HandleCommand(SocketMessage messageParam) - { - var message = messageParam as SocketUserMessage; - if (message == null) return Task.CompletedTask; - if (message.Author.IsBot) return Task.CompletedTask; - var argPos = 0; - var lowCaseMsg = message.ToString().ToLower(); - if (lowCaseMsg.StartsWith("ping")) - { - message.Channel.SendMessageAsync("pong"); - return Task.CompletedTask; - } - if (lowCaseMsg.StartsWith("hui")) - { - message.Channel.SendMessageAsync("hui!!!"); - return Task.CompletedTask; - } - if (!(message.HasCharPrefix('!', ref argPos) || - message.HasMentionPrefix(client.CurrentUser, ref argPos))) return Task.CompletedTask; - var context = new CommandContext(client, message); - var commandExec = commands.ExecuteAsync(context, argPos, servicesProvider); - return Task.CompletedTask; - } - - private Task HandleMessageReceived(SocketMessage messsageParam) - { - var message = messsageParam; - if (message == null) return Task.CompletedTask; - - var channel = (SocketGuildChannel) message.Channel; - - redis.HashIncrementAsync($"{channel.Guild.Id}:Messages", message.Author.Id.ToString()); - redis.HashIncrementAsync($"{channel.Guild.Id}:Messages", 0.ToString()); - - if (message.Author.IsBot) return Task.CompletedTask; - logger.Information($"[Message] {channel.Guild.Name} - {message.Channel} - {message.Author.Username} - {message.Content}"); - return Task.CompletedTask; - } - - private Task HandleUserJoined(SocketGuildUser user) - { - if (!user.IsBot) - { - var message = redis.HashGet($"{user.Guild.Id}:Settings", "WelcomeMsg"); - if (!message.IsNullOrEmpty) - { - message = message.ToString().Replace("$user", user.Mention); - user.Guild.DefaultChannel.SendMessageAsync(message); - } - } - return Task.CompletedTask; - } - private async Task FinishSetup() { var appInfo = await client.GetApplicationInfoAsync(); @@ -252,7 +207,7 @@ namespace Geekbot.net logger.Error(message.Exception, logMessage); break; default: - logger.Information($"{logMessage} --- {message.Severity.ToString()}"); + logger.Information($"{logMessage} --- {message.Severity}"); break; } return Task.CompletedTask; From 5771fcddba3181dc4be89b5a30bae10f8ebbacdf Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sat, 30 Sep 2017 02:00:21 +0200 Subject: [PATCH 040/553] Update Readme.md --- readme.md | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/readme.md b/readme.md index c38723c..4257ac4 100644 --- a/readme.md +++ b/readme.md @@ -1,18 +1,25 @@ -# Geekbot.net +# [Geekbot.net](https://geekbot.pizzaandcoffee.rocks/) -A General Purpose Discord Bot written in DotNet Core +A General Purpose Discord Bot written in DotNet Core. You can invite Geekbot to your server with [this link](https://discordapp.com/oauth2/authorize?client_id=171249478546882561&scope=bot&permissions=1416834054) -### Building +### Technologies -Geekbot.net Requires dotnet core 2.0.0 and dotnet core cli 2.0.0 +* DotNet Core 2 +* Redis +* Discord.net -`dotnet restore` +### Running -`cd Geekbot.net` +Make sure redis is running -`dotnet run` +Run these commands + +* `dotnet restore` +* `dotnet run` + +On your first run geekbot will ask for your bot token, everything else is taken care of. ### Contributing From 8d08b87d090ceba200dcd1ae76430ca1f0002ee3 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sat, 30 Sep 2017 17:26:24 +0200 Subject: [PATCH 041/553] Ability to notify mods when user left or deleted message --- Geekbot.net/Handlers.cs | 60 +++++++++++++++++++ Geekbot.net/Lib/UserRepository.cs | 10 +++- Geekbot.net/Modules/AdminCmd.cs | 99 +++++++++++++++++++++++++++++-- Geekbot.net/Program.cs | 6 +- 4 files changed, 166 insertions(+), 9 deletions(-) diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index 6c25104..bf62cac 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -1,4 +1,5 @@ using System; +using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; @@ -96,5 +97,64 @@ namespace Geekbot.net _userRepository.Update(newUser); return Task.CompletedTask; } + + public async Task UserLeft(SocketGuildUser user) + { + try + { + var sendLeftEnabled = _redis.HashGet($"{user.Guild.Id}:Settings", "ShowLeave"); + if (sendLeftEnabled.ToString() == "1") + { + var modChannel = _redis.HashGet($"{user.Guild.Id}:Settings", "ModChannel"); + if (!string.IsNullOrEmpty(modChannel)) + { + var modChannelSocket = (ISocketMessageChannel) await _client.GetChannelAsync((ulong)modChannel); + await modChannelSocket.SendMessageAsync($"{user.Username}#{user.Discriminator} left the server"); + } + } + } + catch (Exception e) + { + _logger.Error(e, "Failed to send leave message..."); + } + _logger.Information($"[Geekbot] {user.Id} ({user.Username}) left {user.Guild.Id} ({user.Guild.Name})"); + } + + // + // Message Stuff + // + + public async Task MessageDeleted(Cacheable message, ISocketMessageChannel channel) + { + try + { + var guild = ((IGuildChannel) channel).Guild; + var sendLeftEnabled = _redis.HashGet($"{guild.Id}:Settings", "ShowDelete"); + if (sendLeftEnabled.ToString() == "1") + { + var modChannel = _redis.HashGet($"{guild.Id}:Settings", "ModChannel"); + if (!string.IsNullOrEmpty(modChannel)) + { + var modChannelSocket = (ISocketMessageChannel) await _client.GetChannelAsync((ulong)modChannel); + var sb = new StringBuilder(); + if (message.Value != null) + { + sb.AppendLine( + $"{message.Value.Author.Username}#{message.Value.Author.Discriminator} deleted the following message from <#{channel.Id}>"); + sb.AppendLine(message.Value.Content); + } + else + { + sb.AppendLine("Someone deleted a message, the message was not cached..."); + } + await modChannelSocket.SendMessageAsync(sb.ToString()); + } + } + } + catch (Exception e) + { + _logger.Error(e, "Failed to send delete message..."); + } + } } } \ No newline at end of file diff --git a/Geekbot.net/Lib/UserRepository.cs b/Geekbot.net/Lib/UserRepository.cs index 71faba3..9c85936 100644 --- a/Geekbot.net/Lib/UserRepository.cs +++ b/Geekbot.net/Lib/UserRepository.cs @@ -40,9 +40,15 @@ namespace Geekbot.net.Lib public UserRepositoryUser Get(ulong userId) { - var user = _redis.HashGetAll($"Users:{userId}").ToDictionary(); + var user = _redis.HashGetAll($"Users:{userId}"); + for (int i = 1; i < 6; i++) + { + if (user.Length != 0) break; + user = _redis.HashGetAll($"Users:{userId + (ulong)i}"); + + } var dto = new UserRepositoryUser(); - foreach (var a in user) + foreach (var a in user.ToDictionary()) { switch (a.Key) { diff --git a/Geekbot.net/Modules/AdminCmd.cs b/Geekbot.net/Modules/AdminCmd.cs index ea2bc05..f4a91de 100644 --- a/Geekbot.net/Modules/AdminCmd.cs +++ b/Geekbot.net/Modules/AdminCmd.cs @@ -1,10 +1,10 @@ using System; +using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Lib; -using Google.Apis.YouTube.v3.Data; using Serilog; using StackExchange.Redis; @@ -75,10 +75,20 @@ namespace Geekbot.net.Modules [Summary("Set the game that the bot is playing")] public async Task popUserRepoCommand() { - var botOwner = Context.Guild.GetUserAsync(ulong.Parse(_redis.StringGet("botOwner"))).Result; - if (!Context.User.Id.ToString().Equals(botOwner.Id.ToString())) + try { - await ReplyAsync($"Sorry, only the botowner can do this ({botOwner.Username}#{botOwner.Discriminator})"); + var botOwner = Context.Guild.GetUserAsync(ulong.Parse(_redis.StringGet("botOwner"))).Result; + if (!Context.User.Id.ToString().Equals(botOwner.Id.ToString())) + { + await ReplyAsync( + $"Sorry, only the botowner can do this ({botOwner.Username}#{botOwner.Discriminator})"); + return; + } + } + catch (Exception e) + { + await ReplyAsync( + $"Sorry, only the botowner can do this"); return; } var success = 0; @@ -101,8 +111,85 @@ namespace Geekbot.net.Modules } catch (Exception e) { - await ReplyAsync("Couldn't complete User Repository, see console for more info"); - _errorHandler.HandleCommandException(e, Context); + _errorHandler.HandleCommandException(e, Context, "Couldn't complete User Repository, see console for more info"); + } + } + + [RequireUserPermission(GuildPermission.Administrator)] + [Command("modchannel", RunMode = RunMode.Async)] + [Summary("Set the game that the bot is playing")] + public async Task selectModChannel([Summary("ChannelId")] ulong channelId) + { + try + { + var channel = (ISocketMessageChannel)_client.GetChannel(channelId); + if (string.IsNullOrEmpty(channel.Name)) + { + await ReplyAsync("I couldn't find that channel..."); + return; + } + var sb = new StringBuilder(); + sb.AppendLine("Successfully saved mod channel, you can now do the following"); + sb.AppendLine("- `!admin showleave true` - send message to mod channel when someone leaves"); + sb.AppendLine("- `!admin showdel true` - send message to mod channel when someone deletes a message"); + await channel.SendMessageAsync(sb.ToString()); + _redis.HashSet($"{Context.Guild.Id}:Settings", new HashEntry[] {new HashEntry("ModChannel", channel.Id.ToString())}); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context, "That channel doesn't seem to be valid"); + } + } + + [RequireUserPermission(GuildPermission.Administrator)] + [Command("showleave", RunMode = RunMode.Async)] + [Summary("Notify modchannel when someone leaves")] + public async Task showLeave([Summary("true/false")] bool enabled) + { + var modChannelId = (ulong)_redis.HashGet($"{Context.Guild.Id}:Settings", "ModChannel"); + try + { + var modChannel = (ISocketMessageChannel) _client.GetChannel(modChannelId); + if (enabled) + { + await modChannel.SendMessageAsync("Saved - now sending messages here when someone leaves"); + _redis.HashSet($"{Context.Guild.Id}:Settings", new HashEntry[] {new HashEntry("ShowLeave", true)}); + } + else + { + await modChannel.SendMessageAsync("Saved - stopping sending messages here when someone leaves"); + _redis.HashSet($"{Context.Guild.Id}:Settings", new HashEntry[] {new HashEntry("ShowLeave", false)}); + } + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context, "Modchannel doesn't seem to exist, please set one with `!admin modchannel [channelId]`"); + } + } + + [RequireUserPermission(GuildPermission.Administrator)] + [Command("showdel", RunMode = RunMode.Async)] + [Summary("Notify modchannel when someone leaves")] + public async Task showDelete([Summary("true/false")] bool enabled) + { + var modChannelId = (ulong)_redis.HashGet($"{Context.Guild.Id}:Settings", "ModChannel"); + try + { + var modChannel = (ISocketMessageChannel) _client.GetChannel(modChannelId); + if (enabled) + { + await modChannel.SendMessageAsync("Saved - now sending messages here when someone deletes a message"); + _redis.HashSet($"{Context.Guild.Id}:Settings", new HashEntry[] {new HashEntry("ShowDelete", true)}); + } + else + { + await modChannel.SendMessageAsync("Saved - stopping sending messages here when someone deletes a message"); + _redis.HashSet($"{Context.Guild.Id}:Settings", new HashEntry[] {new HashEntry("ShowDelete", false)}); + } + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context, "Modchannel doesn't seem to exist, please set one with `!admin modchannel [channelId]`"); } } } diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 12bdb73..cd43c43 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -53,7 +53,9 @@ namespace Geekbot.net client = new DiscordSocketClient(new DiscordSocketConfig { - LogLevel = LogSeverity.Verbose + LogLevel = LogSeverity.Verbose, + MessageCacheSize = 1000, + AlwaysDownloadUsers = true }); client.Log += DiscordLogger; commands = new CommandService(); @@ -147,8 +149,10 @@ namespace Geekbot.net client.MessageReceived += handlers.RunCommand; client.MessageReceived += handlers.UpdateStats; + client.MessageDeleted += handlers.MessageDeleted; client.UserJoined += handlers.UserJoined; client.UserUpdated += handlers.UserUpdated; + client.UserLeft += handlers.UserLeft; if (firstStart || (args.Length != 0 && args.Contains("--reset"))) { From 6732506daeb0b171b8fda0fa01e30599bfd48114 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sun, 1 Oct 2017 23:41:25 +0200 Subject: [PATCH 042/553] Adding mal integration --- Geekbot.net/Geekbot.net.csproj | 6 +- Geekbot.net/Lib/MalClient.cs | 78 ++++++++++++++++++++++ Geekbot.net/Modules/mal.cs | 116 +++++++++++++++++++++++++++++++++ Geekbot.net/Program.cs | 2 + 4 files changed, 197 insertions(+), 5 deletions(-) create mode 100644 Geekbot.net/Lib/MalClient.cs create mode 100644 Geekbot.net/Modules/mal.cs diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 0da2296..5764975 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -14,14 +14,10 @@ 1.0.2 - - - - 1.5.0.1 - + diff --git a/Geekbot.net/Lib/MalClient.cs b/Geekbot.net/Lib/MalClient.cs new file mode 100644 index 0000000..4827b13 --- /dev/null +++ b/Geekbot.net/Lib/MalClient.cs @@ -0,0 +1,78 @@ +using System.Threading.Tasks; +using MyAnimeListSharp.Auth; +using MyAnimeListSharp.Core; +using MyAnimeListSharp.Facade.Async; +using Serilog; +using StackExchange.Redis; + +namespace Geekbot.net.Lib +{ + public class MalClient : IMalClient + { + private readonly IDatabase _redis; + private readonly ILogger _logger; + private ICredentialContext _credentials; + private AnimeSearchMethodsAsync _animeSearch; + private MangaSearchMethodsAsync _mangaSearch; + + public MalClient(IDatabase redis, ILogger logger) + { + _redis = redis; + _logger = logger; + reloadClient(); + } + + public bool reloadClient() + { + var malCredentials = _redis.HashGetAll("malCredentials"); + if (malCredentials.Length != 0) + { + _credentials = new CredentialContext(); + foreach (var c in malCredentials) + { + switch (c.Name) + { + case "Username": + _credentials.UserName = c.Value; + break; + case "Password": + _credentials.Password = c.Value; + break; + } + } + _animeSearch = new AnimeSearchMethodsAsync(_credentials); + _mangaSearch = new MangaSearchMethodsAsync(_credentials); + _logger.Verbose($"[Geekbot] [MalClient] Logged in to Mal"); + return true; + } + _logger.Warning("[Geekbot] [MalClient] No Credentials Set!"); + return false; + + } + + public bool isLoggedIn() + { + return _credentials != null; + } + + public async Task getAnime(string query) + { + var response = await _animeSearch.SearchDeserializedAsync(query); + return response.Entries.Count == 0 ? null : response.Entries[0]; + } + + public async Task getManga(string query) + { + var response = await _mangaSearch.SearchDeserializedAsync(query); + return response.Entries.Count == 0 ? null : response.Entries[0]; + } + } + + public interface IMalClient + { + bool reloadClient(); + bool isLoggedIn(); + Task getAnime(string query); + Task getManga(string query); + } +} \ No newline at end of file diff --git a/Geekbot.net/Modules/mal.cs b/Geekbot.net/Modules/mal.cs new file mode 100644 index 0000000..662e7c8 --- /dev/null +++ b/Geekbot.net/Modules/mal.cs @@ -0,0 +1,116 @@ +using System; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Geekbot.net.Lib; + +namespace Geekbot.net.Modules +{ + public class mal : ModuleBase + { + private readonly IMalClient _malClient; + private readonly IErrorHandler _errorHandler; + + public mal(IMalClient malClient, IErrorHandler errorHandler) + { + _malClient = malClient; + _errorHandler = errorHandler; + } + + [Command("anime", RunMode = RunMode.Async)] + [Summary("Show Info about an Anime.")] + public async Task searchAnime([Remainder, Summary("AnimeName")] string animeName) + { + try + { + if (_malClient.isLoggedIn()) + { + var anime = await _malClient.getAnime(animeName); + if (anime != null) + { + var eb = new EmbedBuilder(); + + var description = System.Web.HttpUtility.HtmlDecode(anime.Synopsis) + .Replace("
", "") + .Replace("[i]", "*") + .Replace("[/i]", "*"); + + eb.Title = anime.Title; + eb.Description = description; + eb.ImageUrl = anime.Image; + eb.AddInlineField("Premiered", $"{anime.StartDate}"); + eb.AddInlineField("Ended", anime.EndDate == "0000-00-00" ? "???" : anime.EndDate); + eb.AddInlineField("Status", anime.Status); + eb.AddInlineField("Episodes", anime.Episodes); + eb.AddInlineField("MAL Score", anime.Score); + eb.AddInlineField("Type", anime.Type); + eb.AddField("MAL Link", $"https://myanimelist.net/anime/{anime.Id}"); + + await ReplyAsync("", false, eb.Build()); + } + else + { + await ReplyAsync("No anime found with that name..."); + } + } + else + { + await ReplyAsync( + "Unfortunally i'm not connected to MyAnimeList.net, please tell my senpai to connect me"); + } + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context, "Something went wrong..."); + } + } + + [Command("manga", RunMode = RunMode.Async)] + [Summary("Show Info about a Manga.")] + public async Task searchManga([Remainder, Summary("MangaName")] string mangaName) + { + try + { + if (_malClient.isLoggedIn()) + { + var manga = await _malClient.getManga(mangaName); + if (manga != null) + { + var eb = new EmbedBuilder(); + + var description = System.Web.HttpUtility.HtmlDecode(manga.Synopsis) + .Replace("
", "") + .Replace("[i]", "*") + .Replace("[/i]", "*"); + + eb.Title = manga.Title; + eb.Description = description; + eb.ImageUrl = manga.Image; + eb.AddInlineField("Premiered", $"{manga.StartDate}"); + eb.AddInlineField("Ended", manga.EndDate == "0000-00-00" ? "???" : manga.EndDate); + eb.AddInlineField("Status", manga.Status); + eb.AddInlineField("Volumes", manga.Volumes); + eb.AddInlineField("Chapters", manga.Chapters); + eb.AddInlineField("MAL Score", manga.Score); + eb.AddField("MAL Link", $"https://myanimelist.net/manga/{manga.Id}"); + + await ReplyAsync("", false, eb.Build()); + } + else + { + await ReplyAsync("No manga found with that name..."); + } + } + else + { + await ReplyAsync( + "Unfortunally i'm not connected to MyAnimeList.net, please tell my senpai to connect me"); + } + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context, "Something went wrong..."); + } + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index cd43c43..4cbc953 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -109,6 +109,7 @@ namespace Geekbot.net var fortunes = new FortunesProvider(RandomClient, logger); var checkEmImages = new CheckEmImageProvider(RandomClient, logger); var pandaImages = new PandaProvider(RandomClient, logger); + var malClient = new MalClient(redis, logger); services.AddSingleton(errorHandler); services.AddSingleton(redis); @@ -118,6 +119,7 @@ namespace Geekbot.net services.AddSingleton(fortunes); services.AddSingleton(checkEmImages); services.AddSingleton(pandaImages); + services.AddSingleton(malClient); logger.Information("[Geekbot] Connecting to Discord"); From 92015d8880be8741dee0072a15ae343e353e104f Mon Sep 17 00:00:00 2001 From: Runebaas Date: Mon, 2 Oct 2017 21:57:48 +0200 Subject: [PATCH 043/553] Adding Initial API support, updating readme --- Geekbot.net/{Modules => Commands}/AdminCmd.cs | 4 +-- Geekbot.net/{Modules => Commands}/Cat.cs | 2 +- Geekbot.net/{Modules => Commands}/CheckEm.cs | 2 +- Geekbot.net/{Modules => Commands}/Choose.cs | 2 +- Geekbot.net/{Modules => Commands}/Counters.cs | 4 +-- Geekbot.net/{Modules => Commands}/Dice.cs | 2 +- Geekbot.net/{Modules => Commands}/Dog.cs | 2 +- .../{Modules => Commands}/EightBall.cs | 2 +- Geekbot.net/{Modules => Commands}/Fortune.cs | 2 +- Geekbot.net/{Modules => Commands}/Google.cs | 2 +- .../{Modules => Commands}/GuildInfo.cs | 2 +- Geekbot.net/{Modules => Commands}/Help.cs | 2 +- Geekbot.net/{Modules => Commands}/Info.cs | 2 +- Geekbot.net/{Modules => Commands}/Panda.cs | 2 +- Geekbot.net/{Modules => Commands}/Ping.cs | 5 ++-- Geekbot.net/{Modules => Commands}/Quote.cs | 3 +- Geekbot.net/{Modules => Commands}/Roll.cs | 2 +- Geekbot.net/{Modules => Commands}/Say.cs | 2 +- Geekbot.net/{Modules => Commands}/Ship.cs | 2 +- Geekbot.net/{Modules => Commands}/UserInfo.cs | 2 +- Geekbot.net/{Modules => Commands}/Youtube.cs | 2 +- Geekbot.net/{Modules => Commands}/mal.cs | 2 +- Geekbot.net/Geekbot.net.csproj | 3 ++ Geekbot.net/Lib/LoggerFactory.cs | 2 +- Geekbot.net/Program.cs | 11 ++++++-- Geekbot.net/WebApi/Status.cs | 28 +++++++++++++++++++ readme.md | 15 ++++++++-- 27 files changed, 78 insertions(+), 33 deletions(-) rename Geekbot.net/{Modules => Commands}/AdminCmd.cs (97%) rename Geekbot.net/{Modules => Commands}/Cat.cs (94%) rename Geekbot.net/{Modules => Commands}/CheckEm.cs (98%) rename Geekbot.net/{Modules => Commands}/Choose.cs (92%) rename Geekbot.net/{Modules => Commands}/Counters.cs (99%) rename Geekbot.net/{Modules => Commands}/Dice.cs (99%) rename Geekbot.net/{Modules => Commands}/Dog.cs (94%) rename Geekbot.net/{Modules => Commands}/EightBall.cs (97%) rename Geekbot.net/{Modules => Commands}/Fortune.cs (90%) rename Geekbot.net/{Modules => Commands}/Google.cs (93%) rename Geekbot.net/{Modules => Commands}/GuildInfo.cs (95%) rename Geekbot.net/{Modules => Commands}/Help.cs (98%) rename Geekbot.net/{Modules => Commands}/Info.cs (95%) rename Geekbot.net/{Modules => Commands}/Panda.cs (90%) rename Geekbot.net/{Modules => Commands}/Ping.cs (77%) rename Geekbot.net/{Modules => Commands}/Quote.cs (98%) rename Geekbot.net/{Modules => Commands}/Roll.cs (97%) rename Geekbot.net/{Modules => Commands}/Say.cs (93%) rename Geekbot.net/{Modules => Commands}/Ship.cs (95%) rename Geekbot.net/{Modules => Commands}/UserInfo.cs (99%) rename Geekbot.net/{Modules => Commands}/Youtube.cs (95%) rename Geekbot.net/{Modules => Commands}/mal.cs (96%) create mode 100644 Geekbot.net/WebApi/Status.cs diff --git a/Geekbot.net/Modules/AdminCmd.cs b/Geekbot.net/Commands/AdminCmd.cs similarity index 97% rename from Geekbot.net/Modules/AdminCmd.cs rename to Geekbot.net/Commands/AdminCmd.cs index f4a91de..0d9292e 100644 --- a/Geekbot.net/Modules/AdminCmd.cs +++ b/Geekbot.net/Commands/AdminCmd.cs @@ -8,7 +8,7 @@ using Geekbot.net.Lib; using Serilog; using StackExchange.Redis; -namespace Geekbot.net.Modules +namespace Geekbot.net.Commands { [Group("admin")] public class AdminCmd : ModuleBase @@ -85,7 +85,7 @@ namespace Geekbot.net.Modules return; } } - catch (Exception e) + catch (Exception) { await ReplyAsync( $"Sorry, only the botowner can do this"); diff --git a/Geekbot.net/Modules/Cat.cs b/Geekbot.net/Commands/Cat.cs similarity index 94% rename from Geekbot.net/Modules/Cat.cs rename to Geekbot.net/Commands/Cat.cs index bf6fa81..3e7973b 100644 --- a/Geekbot.net/Modules/Cat.cs +++ b/Geekbot.net/Commands/Cat.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Discord.Commands; using Newtonsoft.Json; -namespace Geekbot.net.Modules +namespace Geekbot.net.Commands { public class Cat : ModuleBase { diff --git a/Geekbot.net/Modules/CheckEm.cs b/Geekbot.net/Commands/CheckEm.cs similarity index 98% rename from Geekbot.net/Modules/CheckEm.cs rename to Geekbot.net/Commands/CheckEm.cs index 8af8ae0..5aaef53 100644 --- a/Geekbot.net/Modules/CheckEm.cs +++ b/Geekbot.net/Commands/CheckEm.cs @@ -7,7 +7,7 @@ using Geekbot.net.Lib; using Geekbot.net.Lib.Media; using Serilog; -namespace Geekbot.net.Modules +namespace Geekbot.net.Commands { public class CheckEm : ModuleBase { diff --git a/Geekbot.net/Modules/Choose.cs b/Geekbot.net/Commands/Choose.cs similarity index 92% rename from Geekbot.net/Modules/Choose.cs rename to Geekbot.net/Commands/Choose.cs index 68ea4af..338851d 100644 --- a/Geekbot.net/Modules/Choose.cs +++ b/Geekbot.net/Commands/Choose.cs @@ -2,7 +2,7 @@ using System.Threading.Tasks; using Discord.Commands; -namespace Geekbot.net.Modules +namespace Geekbot.net.Commands { public class Choose : ModuleBase { diff --git a/Geekbot.net/Modules/Counters.cs b/Geekbot.net/Commands/Counters.cs similarity index 99% rename from Geekbot.net/Modules/Counters.cs rename to Geekbot.net/Commands/Counters.cs index ee844ca..45ffa3d 100644 --- a/Geekbot.net/Modules/Counters.cs +++ b/Geekbot.net/Commands/Counters.cs @@ -3,10 +3,10 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; -using StackExchange.Redis; using Serilog; +using StackExchange.Redis; -namespace Geekbot.net.Modules +namespace Geekbot.net.Commands { public class Counters : ModuleBase { diff --git a/Geekbot.net/Modules/Dice.cs b/Geekbot.net/Commands/Dice.cs similarity index 99% rename from Geekbot.net/Modules/Dice.cs rename to Geekbot.net/Commands/Dice.cs index 698e825..c40757c 100644 --- a/Geekbot.net/Modules/Dice.cs +++ b/Geekbot.net/Commands/Dice.cs @@ -5,7 +5,7 @@ using System.Text; using System.Threading.Tasks; using Discord.Commands; -namespace Geekbot.net.Modules +namespace Geekbot.net.Commands { public class Dice : ModuleBase { diff --git a/Geekbot.net/Modules/Dog.cs b/Geekbot.net/Commands/Dog.cs similarity index 94% rename from Geekbot.net/Modules/Dog.cs rename to Geekbot.net/Commands/Dog.cs index 326e4ac..481500e 100644 --- a/Geekbot.net/Modules/Dog.cs +++ b/Geekbot.net/Commands/Dog.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Discord.Commands; using Newtonsoft.Json; -namespace Geekbot.net.Modules +namespace Geekbot.net.Commands { public class Dog : ModuleBase { diff --git a/Geekbot.net/Modules/EightBall.cs b/Geekbot.net/Commands/EightBall.cs similarity index 97% rename from Geekbot.net/Modules/EightBall.cs rename to Geekbot.net/Commands/EightBall.cs index 3f34d0b..5ca4ae6 100644 --- a/Geekbot.net/Modules/EightBall.cs +++ b/Geekbot.net/Commands/EightBall.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using Discord.Commands; -namespace Geekbot.net.Modules +namespace Geekbot.net.Commands { public class EightBall : ModuleBase { diff --git a/Geekbot.net/Modules/Fortune.cs b/Geekbot.net/Commands/Fortune.cs similarity index 90% rename from Geekbot.net/Modules/Fortune.cs rename to Geekbot.net/Commands/Fortune.cs index cc52bcf..d97b437 100644 --- a/Geekbot.net/Modules/Fortune.cs +++ b/Geekbot.net/Commands/Fortune.cs @@ -2,7 +2,7 @@ using Discord.Commands; using Geekbot.net.Lib.Media; -namespace Geekbot.net.Modules +namespace Geekbot.net.Commands { public class Fortune : ModuleBase { diff --git a/Geekbot.net/Modules/Google.cs b/Geekbot.net/Commands/Google.cs similarity index 93% rename from Geekbot.net/Modules/Google.cs rename to Geekbot.net/Commands/Google.cs index e2205aa..05c8c55 100644 --- a/Geekbot.net/Modules/Google.cs +++ b/Geekbot.net/Commands/Google.cs @@ -1,7 +1,7 @@ using System.Threading.Tasks; using Discord.Commands; -namespace Geekbot.net.Modules +namespace Geekbot.net.Commands { public class Google : ModuleBase { diff --git a/Geekbot.net/Modules/GuildInfo.cs b/Geekbot.net/Commands/GuildInfo.cs similarity index 95% rename from Geekbot.net/Modules/GuildInfo.cs rename to Geekbot.net/Commands/GuildInfo.cs index 11a3d44..ff9c4a0 100644 --- a/Geekbot.net/Modules/GuildInfo.cs +++ b/Geekbot.net/Commands/GuildInfo.cs @@ -6,7 +6,7 @@ using Discord.Commands; using Geekbot.net.Lib; using StackExchange.Redis; -namespace Geekbot.net.Modules +namespace Geekbot.net.Commands { public class GuildInfo : ModuleBase { diff --git a/Geekbot.net/Modules/Help.cs b/Geekbot.net/Commands/Help.cs similarity index 98% rename from Geekbot.net/Modules/Help.cs rename to Geekbot.net/Commands/Help.cs index 57feb87..d8942e4 100644 --- a/Geekbot.net/Modules/Help.cs +++ b/Geekbot.net/Commands/Help.cs @@ -3,7 +3,7 @@ using System.Text; using System.Threading.Tasks; using Discord.Commands; -namespace Geekbot.net.Modules +namespace Geekbot.net.Commands { public class Help : ModuleBase { diff --git a/Geekbot.net/Modules/Info.cs b/Geekbot.net/Commands/Info.cs similarity index 95% rename from Geekbot.net/Modules/Info.cs rename to Geekbot.net/Commands/Info.cs index bf02862..85a01c5 100644 --- a/Geekbot.net/Modules/Info.cs +++ b/Geekbot.net/Commands/Info.cs @@ -6,7 +6,7 @@ using Discord.Commands; using Geekbot.net.Lib; using StackExchange.Redis; -namespace Geekbot.net.Modules +namespace Geekbot.net.Commands { public class Info : ModuleBase { diff --git a/Geekbot.net/Modules/Panda.cs b/Geekbot.net/Commands/Panda.cs similarity index 90% rename from Geekbot.net/Modules/Panda.cs rename to Geekbot.net/Commands/Panda.cs index f5675c9..6d9be69 100644 --- a/Geekbot.net/Modules/Panda.cs +++ b/Geekbot.net/Commands/Panda.cs @@ -2,7 +2,7 @@ using Discord.Commands; using Geekbot.net.Lib.Media; -namespace Geekbot.net.Modules +namespace Geekbot.net.Commands { public class Panda : ModuleBase { diff --git a/Geekbot.net/Modules/Ping.cs b/Geekbot.net/Commands/Ping.cs similarity index 77% rename from Geekbot.net/Modules/Ping.cs rename to Geekbot.net/Commands/Ping.cs index a3ba98d..698c383 100644 --- a/Geekbot.net/Modules/Ping.cs +++ b/Geekbot.net/Commands/Ping.cs @@ -1,8 +1,7 @@ -using System.Linq; -using System.Threading.Tasks; +using System.Threading.Tasks; using Discord.Commands; -namespace Geekbot.net.Modules +namespace Geekbot.net.Commands { public class Ping : ModuleBase { diff --git a/Geekbot.net/Modules/Quote.cs b/Geekbot.net/Commands/Quote.cs similarity index 98% rename from Geekbot.net/Modules/Quote.cs rename to Geekbot.net/Commands/Quote.cs index 49e10ab..053a63a 100644 --- a/Geekbot.net/Modules/Quote.cs +++ b/Geekbot.net/Commands/Quote.cs @@ -5,12 +5,11 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; -using Microsoft.Extensions.Configuration; using Newtonsoft.Json; using Serilog; using StackExchange.Redis; -namespace Geekbot.net.Modules +namespace Geekbot.net.Commands { [Group("quote")] public class Quote : ModuleBase diff --git a/Geekbot.net/Modules/Roll.cs b/Geekbot.net/Commands/Roll.cs similarity index 97% rename from Geekbot.net/Modules/Roll.cs rename to Geekbot.net/Commands/Roll.cs index 9d84a8d..66caa40 100644 --- a/Geekbot.net/Modules/Roll.cs +++ b/Geekbot.net/Commands/Roll.cs @@ -3,7 +3,7 @@ using System.Threading.Tasks; using Discord.Commands; using StackExchange.Redis; -namespace Geekbot.net.Modules +namespace Geekbot.net.Commands { public class Roll : ModuleBase { diff --git a/Geekbot.net/Modules/Say.cs b/Geekbot.net/Commands/Say.cs similarity index 93% rename from Geekbot.net/Modules/Say.cs rename to Geekbot.net/Commands/Say.cs index 7d4b7af..52b4477 100644 --- a/Geekbot.net/Modules/Say.cs +++ b/Geekbot.net/Commands/Say.cs @@ -2,7 +2,7 @@ using Discord; using Discord.Commands; -namespace Geekbot.net.Modules +namespace Geekbot.net.Commands { public class Say : ModuleBase { diff --git a/Geekbot.net/Modules/Ship.cs b/Geekbot.net/Commands/Ship.cs similarity index 95% rename from Geekbot.net/Modules/Ship.cs rename to Geekbot.net/Commands/Ship.cs index ea426e4..da2bd2e 100644 --- a/Geekbot.net/Modules/Ship.cs +++ b/Geekbot.net/Commands/Ship.cs @@ -4,7 +4,7 @@ using Discord; using Discord.Commands; using StackExchange.Redis; -namespace Geekbot.net.Modules +namespace Geekbot.net.Commands { public class Ship : ModuleBase { diff --git a/Geekbot.net/Modules/UserInfo.cs b/Geekbot.net/Commands/UserInfo.cs similarity index 99% rename from Geekbot.net/Modules/UserInfo.cs rename to Geekbot.net/Commands/UserInfo.cs index cb7725d..0730117 100644 --- a/Geekbot.net/Modules/UserInfo.cs +++ b/Geekbot.net/Commands/UserInfo.cs @@ -9,7 +9,7 @@ using Geekbot.net.Lib; using Serilog; using StackExchange.Redis; -namespace Geekbot.net.Modules +namespace Geekbot.net.Commands { public class UserInfo : ModuleBase { diff --git a/Geekbot.net/Modules/Youtube.cs b/Geekbot.net/Commands/Youtube.cs similarity index 95% rename from Geekbot.net/Modules/Youtube.cs rename to Geekbot.net/Commands/Youtube.cs index afb7027..c496cde 100644 --- a/Geekbot.net/Modules/Youtube.cs +++ b/Geekbot.net/Commands/Youtube.cs @@ -5,7 +5,7 @@ using Google.Apis.Services; using Google.Apis.YouTube.v3; using StackExchange.Redis; -namespace Geekbot.net.Modules +namespace Geekbot.net.Commands { public class Youtube : ModuleBase { diff --git a/Geekbot.net/Modules/mal.cs b/Geekbot.net/Commands/mal.cs similarity index 96% rename from Geekbot.net/Modules/mal.cs rename to Geekbot.net/Commands/mal.cs index 662e7c8..840c7c7 100644 --- a/Geekbot.net/Modules/mal.cs +++ b/Geekbot.net/Commands/mal.cs @@ -4,7 +4,7 @@ using Discord; using Discord.Commands; using Geekbot.net.Lib; -namespace Geekbot.net.Modules +namespace Geekbot.net.Commands { public class mal : ModuleBase { diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 5764975..056eb93 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -18,6 +18,8 @@ + + @@ -34,5 +36,6 @@ 4.3.0 +
\ No newline at end of file diff --git a/Geekbot.net/Lib/LoggerFactory.cs b/Geekbot.net/Lib/LoggerFactory.cs index 055c2f2..b52ad5a 100644 --- a/Geekbot.net/Lib/LoggerFactory.cs +++ b/Geekbot.net/Lib/LoggerFactory.cs @@ -10,7 +10,7 @@ namespace Geekbot.net.Lib var loggerCreation = new LoggerConfiguration() .WriteTo.LiterateConsole() .WriteTo.RollingFile("Logs/geekbot-{Date}.txt", shared: true); - if (args.Length != 0 && args.Contains("--verbose")) + if (args.Contains("--verbose")) { loggerCreation.MinimumLevel.Verbose(); } diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 4cbc953..be63aba 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -11,7 +11,9 @@ using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Lib; using Geekbot.net.Lib.Media; +using Geekbot.net.WebApi; using Microsoft.Extensions.DependencyInjection; +using Nancy.Hosting.Self; using Serilog; using StackExchange.Redis; @@ -72,7 +74,7 @@ namespace Geekbot.net Environment.Exit(102); } - if (args.Length != 0 && args.Contains("--migrate")) + if (args.Contains("--migrate")) { Console.WriteLine("\nYou are about to migrate the database, this will overwrite an already migrated database?"); Console.Write("Are you sure [y:N]: "); @@ -156,12 +158,17 @@ namespace Geekbot.net client.UserUpdated += handlers.UserUpdated; client.UserLeft += handlers.UserLeft; - if (firstStart || (args.Length != 0 && args.Contains("--reset"))) + if (firstStart || args.Contains("--reset")) { logger.Information("[Geekbot] Finishing setup"); await FinishSetup(); logger.Information("[Geekbot] Setup finished"); } + if (!args.Contains("--disable-api")) + { + logger.Information("[API] Starting Webserver"); + new NancyHost(new Uri("http://localhost:4567")).Start(); + } logger.Information("[Geekbot] Done and ready for use\n"); } diff --git a/Geekbot.net/WebApi/Status.cs b/Geekbot.net/WebApi/Status.cs new file mode 100644 index 0000000..0597e83 --- /dev/null +++ b/Geekbot.net/WebApi/Status.cs @@ -0,0 +1,28 @@ +using Nancy; + +namespace Geekbot.net.WebApi +{ + public class Status : NancyModule + { + public Status() + { + Get("/", args => + { + var responseBody = new ApiStatusDto() + { + GeekbotVersion = "3.4", + ApiVersion = "0.1", + Status = "Online" + }; + return Response.AsJson(responseBody); + }); + } + } + + public class ApiStatusDto + { + public string GeekbotVersion { get; set; } + public string ApiVersion { get; set; } + public string Status { get; set; } + } +} \ No newline at end of file diff --git a/readme.md b/readme.md index 4257ac4..90d91fa 100644 --- a/readme.md +++ b/readme.md @@ -4,13 +4,13 @@ A General Purpose Discord Bot written in DotNet Core. You can invite Geekbot to your server with [this link](https://discordapp.com/oauth2/authorize?client_id=171249478546882561&scope=bot&permissions=1416834054) -### Technologies +## Technologies * DotNet Core 2 * Redis * Discord.net -### Running +## Running Make sure redis is running @@ -21,6 +21,15 @@ Run these commands On your first run geekbot will ask for your bot token, everything else is taken care of. -### Contributing +### Launch Parameters + +| Parameter | Description | +| --- | --- | +| `--verbose` | Show more log information | +| `--disable-api` | Disables the webapi on startup | +| `--reset` | Resets certain parts of the bot | +| `--migrate` | Migrates the database from V3.1 to the new format from V3.2
(make sure to backup before running this) | + +## Contributing Everyone is free to open an issue or create a pull request From 09dbb6b14dd52e604ba7e56778702fc1ab9fc791 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Tue, 3 Oct 2017 00:22:26 +0200 Subject: [PATCH 044/553] Splitting and renaming userinfo.cs, adding commands endpoint to api, minor refactor in other places --- Geekbot.net/Commands/Help.cs | 6 +- Geekbot.net/Commands/Info.cs | 39 ++- Geekbot.net/Commands/{UserInfo.cs => Rank.cs} | 288 ++++++++---------- Geekbot.net/Commands/Stats.cs | 67 ++++ Geekbot.net/Lib/Constants.cs | 9 + Geekbot.net/Lib/DbMigration.cs | 51 ++++ Geekbot.net/Program.cs | 50 +-- Geekbot.net/WebApi/HelpController.cs | 75 +++++ .../WebApi/{Status.cs => StatusController.cs} | 9 +- 9 files changed, 364 insertions(+), 230 deletions(-) rename Geekbot.net/Commands/{UserInfo.cs => Rank.cs} (53%) create mode 100644 Geekbot.net/Commands/Stats.cs create mode 100644 Geekbot.net/Lib/Constants.cs create mode 100644 Geekbot.net/Lib/DbMigration.cs create mode 100644 Geekbot.net/WebApi/HelpController.cs rename Geekbot.net/WebApi/{Status.cs => StatusController.cs} (67%) diff --git a/Geekbot.net/Commands/Help.cs b/Geekbot.net/Commands/Help.cs index d8942e4..2a0ce13 100644 --- a/Geekbot.net/Commands/Help.cs +++ b/Geekbot.net/Commands/Help.cs @@ -7,11 +7,11 @@ namespace Geekbot.net.Commands { public class Help : ModuleBase { - private readonly CommandService commands; + private readonly CommandService _commands; public Help(CommandService commands) { - this.commands = commands; + _commands = commands; } [Command("help", RunMode = RunMode.Async)] @@ -23,7 +23,7 @@ namespace Geekbot.net.Commands sb.AppendLine("**Geekbot Command list**"); sb.AppendLine(""); sb.AppendLine(tp("Name", 15) + tp("Parameters", 19) + "Description"); - foreach (var cmd in commands.Commands) + foreach (var cmd in _commands.Commands) { var param = string.Join(", !", cmd.Aliases); if (!param.Contains("admin")) diff --git a/Geekbot.net/Commands/Info.cs b/Geekbot.net/Commands/Info.cs index 85a01c5..a620518 100644 --- a/Geekbot.net/Commands/Info.cs +++ b/Geekbot.net/Commands/Info.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Discord.WebSocket; using Geekbot.net.Lib; using StackExchange.Redis; @@ -12,11 +13,13 @@ namespace Geekbot.net.Commands { private readonly IDatabase _redis; private readonly IErrorHandler _errorHandler; + private readonly DiscordSocketClient _client; - public Info(IDatabase redis, IErrorHandler errorHandler) + public Info(IDatabase redis, IErrorHandler errorHandler, DiscordSocketClient client) { _redis = redis; _errorHandler = errorHandler; + _client = client; } [Command("info", RunMode = RunMode.Async)] @@ -26,17 +29,18 @@ namespace Geekbot.net.Commands try { var eb = new EmbedBuilder(); - - eb.WithTitle("Geekbot V3.3"); - - var botOwner = Context.Guild.GetUserAsync(ulong.Parse(_redis.StringGet("botOwner"))).Result; + + eb.WithAuthor(new EmbedAuthorBuilder() + .WithIconUrl(_client.CurrentUser.GetAvatarUrl()) + .WithName($"{Constants.Name} V{Constants.BotVersion}")); + var botOwner = await Context.Guild.GetUserAsync(ulong.Parse(_redis.StringGet("botOwner"))); var uptime = (DateTime.Now.Subtract(Process.GetCurrentProcess().StartTime)); - eb.AddInlineField("Bot Name", Context.Client.CurrentUser.Username) - .AddInlineField("Servers", Context.Client.GetGuildsAsync().Result.Count) - .AddInlineField("Uptime", $"{uptime.Days}D {uptime.Hours}H {uptime.Minutes}M {uptime.Seconds}S") - .AddInlineField("Bot Owner", $"{botOwner.Username}#{botOwner.Discriminator}") - .AddInlineField("Website", "https://geekbot.pizzaandcoffee.rocks/"); + eb.AddInlineField("Bot Name", _client.CurrentUser.Username); + eb.AddInlineField("Servers", Context.Client.GetGuildsAsync().Result.Count); + eb.AddInlineField("Uptime", $"{uptime.Days}D {uptime.Hours}H {uptime.Minutes}M {uptime.Seconds}S"); + eb.AddInlineField("Bot Owner", $"{botOwner.Username}#{botOwner.Discriminator}"); + eb.AddInlineField("Website", "https://geekbot.pizzaandcoffee.rocks/"); await ReplyAsync("", false, eb.Build()); } @@ -45,5 +49,20 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } + + [Command("uptime", RunMode = RunMode.Async)] + [Summary("Get the Bot Uptime")] + public async Task BotUptime() + { + try + { + var uptime = (DateTime.Now.Subtract(Process.GetCurrentProcess().StartTime)); + await ReplyAsync($"{uptime.Days}D {uptime.Hours}H {uptime.Minutes}M {uptime.Seconds}S"); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/UserInfo.cs b/Geekbot.net/Commands/Rank.cs similarity index 53% rename from Geekbot.net/Commands/UserInfo.cs rename to Geekbot.net/Commands/Rank.cs index 0730117..3ec6203 100644 --- a/Geekbot.net/Commands/UserInfo.cs +++ b/Geekbot.net/Commands/Rank.cs @@ -1,168 +1,122 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Discord; -using Discord.Commands; -using Geekbot.net.Lib; -using Serilog; -using StackExchange.Redis; - -namespace Geekbot.net.Commands -{ - public class UserInfo : ModuleBase - { - private readonly IDatabase redis; - private readonly IErrorHandler errorHandler; - private readonly ILogger logger; - private readonly IUserRepository userRepository; - - public UserInfo(IDatabase redis, IErrorHandler errorHandler, ILogger logger, IUserRepository userRepository) - { - this.redis = redis; - this.errorHandler = errorHandler; - this.logger = logger; - this.userRepository = userRepository; - } - - [Command("stats", RunMode = RunMode.Async)] - [Summary("Get information about this user")] - public async Task User([Summary("@someone")] IUser user = null) - { - try - { - var userInfo = user ?? Context.Message.Author; - var userGuildInfo = (IGuildUser) userInfo; - var createdAt = userInfo.CreatedAt; - var joinedAt = userGuildInfo.JoinedAt.Value; - var age = Math.Floor((DateTime.Now - createdAt).TotalDays); - var joinedDayAgo = Math.Floor((DateTime.Now - joinedAt).TotalDays); - - var messages = (int) redis.HashGet($"{Context.Guild.Id}:Messages", userInfo.Id.ToString()); - var guildMessages = (int) redis.HashGet($"{Context.Guild.Id}:Messages", 0.ToString()); - var level = LevelCalc.GetLevelAtExperience(messages); - - var percent = Math.Round((double) (100 * messages) / guildMessages, 2); - - var eb = new EmbedBuilder(); - eb.WithAuthor(new EmbedAuthorBuilder() - .WithIconUrl(userInfo.GetAvatarUrl()) - .WithName(userInfo.Username)); - eb.WithColor(new Color(221, 255, 119)); - - var karma = redis.HashGet($"{Context.Guild.Id}:Karma", userInfo.Id); - var correctRolls = redis.HashGet($"{Context.Guild.Id}:Rolls", userInfo.Id.ToString()); - - eb.AddInlineField("Discordian Since", $"{createdAt.Day}.{createdAt.Month}.{createdAt.Year} ({age} days)") - .AddInlineField("Joined Server", $"{joinedAt.Day}.{joinedAt.Month}.{joinedAt.Year} ({joinedDayAgo} days)") - .AddInlineField("Karma", karma.ToString() ?? "0") - .AddInlineField("Level", level) - .AddInlineField("Messages Sent", messages) - .AddInlineField("Server Total", $"{percent}%"); - - if (!correctRolls.IsNullOrEmpty) - eb.AddInlineField("Guessed Rolls", correctRolls); - - await ReplyAsync("", false, eb.Build()); - } - catch (Exception e) - { - errorHandler.HandleCommandException(e, Context); - } - } - - [Command("rank", RunMode = RunMode.Async)] - [Summary("get user top 10")] - public async Task Rank() - { - try - { - var messageList = redis.HashGetAll($"{Context.Guild.Id}:Messages"); - var sortedList = messageList.OrderByDescending(e => e.Value).ToList(); - var guildMessages = (int) sortedList.First().Value; - sortedList.RemoveAt(0); - - var highscoreUsers = new Dictionary(); - var listLimiter = 1; - var failedToRetrieveUser = false; - foreach (var user in sortedList) - { - if (listLimiter > 10) break; - try - { - var guildUser = userRepository.Get((ulong)user.Name); - if (guildUser.Username != null) - { - highscoreUsers.Add(new RankUserPolyfill() - { - Username = guildUser.Username, - Discriminator = guildUser.Discriminator - }, (int) user.Value); - } - else - { - highscoreUsers.Add(new RankUserPolyfill() - { - Id = user.Name - }, (int) user.Value); - failedToRetrieveUser = true; - } - listLimiter++; - } - catch (Exception e) - { - logger.Warning(e, $"Could not retrieve user {user.Name}"); - } - - } - - var highScore = new StringBuilder(); - if (failedToRetrieveUser) highScore.AppendLine(":warning: I couldn't get all userdata, sorry! (bugfix coming soon:tm:)\n"); - highScore.AppendLine($":bar_chart: **Highscore for {Context.Guild.Name}**"); - var highscorePlace = 1; - foreach (var user in highscoreUsers) - { - var percent = Math.Round((double) (100 * user.Value) / guildMessages, 2); - if (user.Key.Username != null) - { - highScore.AppendLine( - $"{NumerToEmoji(highscorePlace)} **{user.Key.Username}#{user.Key.Discriminator}** - {percent}% of total - {user.Value} messages"); - } - else - { - highScore.AppendLine( - $"{NumerToEmoji(highscorePlace)} **{user.Key.Id}** - {percent}% of total - {user.Value} messages"); - } - highscorePlace++; - } - await ReplyAsync(highScore.ToString()); - } - catch (Exception e) - { - errorHandler.HandleCommandException(e, Context); - } - } - - private string NumerToEmoji(int number) - { - var emojis = new string[] {":one:", ":two:", ":three:", ":four:", ":five:", ":six:", ":seven:", ":eight:", ":nine:", ":keycap_ten:"}; - try - { - return emojis[number - 1]; - } - catch (Exception e) - { - logger.Warning(e, $"Can't provide emoji number {number}"); - return ":zero:"; - } - } - } - - class RankUserPolyfill - { - public string Username { get; set; } - public string Discriminator { get; set; } - public string Id { get; set; } - } +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Geekbot.net.Lib; +using Serilog; +using StackExchange.Redis; + +namespace Geekbot.net.Commands +{ + public class Rank : ModuleBase + { + private readonly IDatabase _redis; + private readonly IErrorHandler _errorHandler; + private readonly ILogger _logger; + private readonly IUserRepository _userRepository; + + public Rank(IDatabase redis, IErrorHandler errorHandler, ILogger logger, IUserRepository userRepository) + { + _redis = redis; + _errorHandler = errorHandler; + _logger = logger; + _userRepository = userRepository; + } + + [Command("rank", RunMode = RunMode.Async)] + [Summary("get user top 10")] + public async Task RankCmd() + { + try + { + var messageList = _redis.HashGetAll($"{Context.Guild.Id}:Messages"); + var sortedList = messageList.OrderByDescending(e => e.Value).ToList(); + var guildMessages = (int) sortedList.First().Value; + sortedList.RemoveAt(0); + + var highscoreUsers = new Dictionary(); + var listLimiter = 1; + var failedToRetrieveUser = false; + foreach (var user in sortedList) + { + if (listLimiter > 10) break; + try + { + var guildUser = _userRepository.Get((ulong)user.Name); + if (guildUser.Username != null) + { + highscoreUsers.Add(new RankUserPolyfill() + { + Username = guildUser.Username, + Discriminator = guildUser.Discriminator + }, (int) user.Value); + } + else + { + highscoreUsers.Add(new RankUserPolyfill() + { + Id = user.Name + }, (int) user.Value); + failedToRetrieveUser = true; + } + listLimiter++; + } + catch (Exception e) + { + _logger.Warning(e, $"Could not retrieve user {user.Name}"); + } + + } + + var highScore = new StringBuilder(); + if (failedToRetrieveUser) highScore.AppendLine(":warning: I couldn't get all userdata, sorry! (bugfix coming soon:tm:)\n"); + highScore.AppendLine($":bar_chart: **Highscore for {Context.Guild.Name}**"); + var highscorePlace = 1; + foreach (var user in highscoreUsers) + { + var percent = Math.Round((double) (100 * user.Value) / guildMessages, 2); + if (user.Key.Username != null) + { + highScore.AppendLine( + $"{NumerToEmoji(highscorePlace)} **{user.Key.Username}#{user.Key.Discriminator}** - {percent}% of total - {user.Value} messages"); + } + else + { + highScore.AppendLine( + $"{NumerToEmoji(highscorePlace)} **{user.Key.Id}** - {percent}% of total - {user.Value} messages"); + } + highscorePlace++; + } + await ReplyAsync(highScore.ToString()); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + private string NumerToEmoji(int number) + { + var emojis = new string[] {":one:", ":two:", ":three:", ":four:", ":five:", ":six:", ":seven:", ":eight:", ":nine:", ":keycap_ten:"}; + try + { + return emojis[number - 1]; + } + catch (Exception e) + { + _logger.Warning(e, $"Can't provide emoji number {number}"); + return ":zero:"; + } + } + } + + class RankUserPolyfill + { + public string Username { get; set; } + public string Discriminator { get; set; } + public string Id { get; set; } + } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Stats.cs b/Geekbot.net/Commands/Stats.cs new file mode 100644 index 0000000..61b57d9 --- /dev/null +++ b/Geekbot.net/Commands/Stats.cs @@ -0,0 +1,67 @@ +using System; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Geekbot.net.Lib; +using StackExchange.Redis; + +namespace Geekbot.net.Commands +{ + public class Stats : ModuleBase + { + private readonly IDatabase _redis; + private readonly IErrorHandler _errorHandler; + + public Stats(IDatabase redis, IErrorHandler errorHandler) + { + _redis = redis; + _errorHandler = errorHandler; + } + + [Command("stats", RunMode = RunMode.Async)] + [Summary("Get information about this user")] + public async Task User([Summary("@someone")] IUser user = null) + { + try + { + var userInfo = user ?? Context.Message.Author; + var userGuildInfo = (IGuildUser) userInfo; + var createdAt = userInfo.CreatedAt; + var joinedAt = userGuildInfo.JoinedAt.Value; + var age = Math.Floor((DateTime.Now - createdAt).TotalDays); + var joinedDayAgo = Math.Floor((DateTime.Now - joinedAt).TotalDays); + + var messages = (int) _redis.HashGet($"{Context.Guild.Id}:Messages", userInfo.Id.ToString()); + var guildMessages = (int) _redis.HashGet($"{Context.Guild.Id}:Messages", 0.ToString()); + var level = LevelCalc.GetLevelAtExperience(messages); + + var percent = Math.Round((double) (100 * messages) / guildMessages, 2); + + var eb = new EmbedBuilder(); + eb.WithAuthor(new EmbedAuthorBuilder() + .WithIconUrl(userInfo.GetAvatarUrl()) + .WithName(userInfo.Username)); + eb.WithColor(new Color(221, 255, 119)); + + var karma = _redis.HashGet($"{Context.Guild.Id}:Karma", userInfo.Id); + var correctRolls = _redis.HashGet($"{Context.Guild.Id}:Rolls", userInfo.Id.ToString()); + + eb.AddInlineField("Discordian Since", $"{createdAt.Day}.{createdAt.Month}.{createdAt.Year} ({age} days)") + .AddInlineField("Joined Server", $"{joinedAt.Day}.{joinedAt.Month}.{joinedAt.Year} ({joinedDayAgo} days)") + .AddInlineField("Karma", karma.ToString() ?? "0") + .AddInlineField("Level", level) + .AddInlineField("Messages Sent", messages) + .AddInlineField("Server Total", $"{percent}%"); + + if (!correctRolls.IsNullOrEmpty) + eb.AddInlineField("Guessed Rolls", correctRolls); + + await ReplyAsync("", false, eb.Build()); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Constants.cs b/Geekbot.net/Lib/Constants.cs new file mode 100644 index 0000000..70506a8 --- /dev/null +++ b/Geekbot.net/Lib/Constants.cs @@ -0,0 +1,9 @@ +namespace Geekbot.net.Lib +{ + public class Constants + { + public const string Name = "Geekbot"; + public const double BotVersion = 3.4; + public const double ApiVersion = 1; + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/DbMigration.cs b/Geekbot.net/Lib/DbMigration.cs new file mode 100644 index 0000000..63b652c --- /dev/null +++ b/Geekbot.net/Lib/DbMigration.cs @@ -0,0 +1,51 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Serilog; +using StackExchange.Redis; + +namespace Geekbot.net.Lib +{ + public class DbMigration + { + public static Task MigrateDatabaseToHash(IDatabase redis, ILogger logger) + { + foreach (var key in redis.Multiplexer.GetServer("127.0.0.1", 6379).Keys(6)) + { + var keyParts = key.ToString().Split("-"); + if (keyParts.Length == 2 || keyParts.Length == 3) + { + logger.Verbose($"Migrating key {key}"); + var stuff = new List(); + stuff.Add("messages"); + stuff.Add("karma"); + stuff.Add("welcomeMsg"); + stuff.Add("correctRolls"); + if(stuff.Contains(keyParts[keyParts.Length - 1])) + { + var val = redis.StringGet(key); + ulong.TryParse(keyParts[0], out ulong guildId); + ulong.TryParse(keyParts[1], out ulong userId); + + switch (keyParts[keyParts.Length - 1]) + { + case "messages": + redis.HashSet($"{guildId}:Messages", new HashEntry[] { new HashEntry(userId.ToString(), val) }); + break; + case "karma": + redis.HashSet($"{guildId}:Karma", new HashEntry[] { new HashEntry(userId.ToString(), val) }); + break; + case "correctRolls": + redis.HashSet($"{guildId}:Rolls", new HashEntry[] { new HashEntry(userId.ToString(), val) }); + break; + case "welcomeMsg": + redis.HashSet($"{guildId}:Settings", new HashEntry[] { new HashEntry("WelcomeMsg", val) }); + break; + } + } + redis.KeyDelete(key); + } + } + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index be63aba..b3ea79a 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; @@ -11,7 +10,6 @@ using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Lib; using Geekbot.net.Lib.Media; -using Geekbot.net.WebApi; using Microsoft.Extensions.DependencyInjection; using Nancy.Hosting.Self; using Serilog; @@ -83,7 +81,7 @@ namespace Geekbot.net if (migrateDbConfirm.Key == ConsoleKey.Y) { logger.Warning("[Geekbot] Starting Migration"); - await MigrateDatabaseToHash(); + await DbMigration.MigrateDatabaseToHash(redis, logger); logger.Warning("[Geekbot] Finished Migration"); } else @@ -167,7 +165,9 @@ namespace Geekbot.net if (!args.Contains("--disable-api")) { logger.Information("[API] Starting Webserver"); - new NancyHost(new Uri("http://localhost:4567")).Start(); + var webApiUrl = new Uri("http://localhost:12995"); + new NancyHost(webApiUrl).Start(); + logger.Information($"[API] Webserver now running on {webApiUrl}"); } logger.Information("[Geekbot] Done and ready for use\n"); @@ -225,47 +225,5 @@ namespace Geekbot.net } return Task.CompletedTask; } - - // db migration script - private Task MigrateDatabaseToHash() - { - foreach (var key in redis.Multiplexer.GetServer("127.0.0.1", 6379).Keys(6)) - { - var keyParts = key.ToString().Split("-"); - if (keyParts.Length == 2 || keyParts.Length == 3) - { - logger.Verbose($"Migrating key {key}"); - var stuff = new List(); - stuff.Add("messages"); - stuff.Add("karma"); - stuff.Add("welcomeMsg"); - stuff.Add("correctRolls"); - if(stuff.Contains(keyParts[keyParts.Length - 1])) - { - var val = redis.StringGet(key); - ulong.TryParse(keyParts[0], out ulong guildId); - ulong.TryParse(keyParts[1], out ulong userId); - - switch (keyParts[keyParts.Length - 1]) - { - case "messages": - redis.HashSet($"{guildId}:Messages", new HashEntry[] { new HashEntry(userId.ToString(), val) }); - break; - case "karma": - redis.HashSet($"{guildId}:Karma", new HashEntry[] { new HashEntry(userId.ToString(), val) }); - break; - case "correctRolls": - redis.HashSet($"{guildId}:Rolls", new HashEntry[] { new HashEntry(userId.ToString(), val) }); - break; - case "welcomeMsg": - redis.HashSet($"{guildId}:Settings", new HashEntry[] { new HashEntry("WelcomeMsg", val) }); - break; - } - } - redis.KeyDelete(key); - } - } - return Task.CompletedTask; - } } } \ No newline at end of file diff --git a/Geekbot.net/WebApi/HelpController.cs b/Geekbot.net/WebApi/HelpController.cs new file mode 100644 index 0000000..b318b63 --- /dev/null +++ b/Geekbot.net/WebApi/HelpController.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Nancy; +using Geekbot.net.Lib; + +namespace Geekbot.net.WebApi +{ + public class HelpController : NancyModule + { + public HelpController() + { + Get("/v1/commands", args => + { + var commands = getCommands().Result; + + var commandList = new List(); + foreach (var cmd in commands.Commands) + { + var cmdParamsObj = new List(); + foreach (var cmdParam in cmd.Parameters) + { + var singleParamObj = new CommandParamDto() + { + Summary = cmdParam.Summary, + Default = cmdParam?.DefaultValue?.ToString() ?? null, + Type = cmdParam?.Type?.ToString() + }; + cmdParamsObj.Add(singleParamObj); + } + + var param = string.Join(", !", cmd.Aliases); + var cmdObj = new CommandDto() + { + Name = cmd.Name, + Summary = cmd.Summary, + IsAdminCommand = (param.Contains("admin")), + Aliases = cmd.Aliases.ToArray(), + Params = cmdParamsObj + }; + commandList.Add(cmdObj); + } + return Response.AsJson(commandList); + + }); + } + + private async Task getCommands() + { + var commands = new CommandService(); + await commands.AddModulesAsync(Assembly.GetEntryAssembly()); + return commands; + } + } + + public class CommandDto + { + public string Name { get; set; } + public string Summary { get; set; } + public bool IsAdminCommand { get; set; } + public Array Aliases { get; set; } + public List Params { get; set; } + } + + public class CommandParamDto + { + public string Summary { get; set; } + public string Default { get; set; } + public string Type { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/WebApi/Status.cs b/Geekbot.net/WebApi/StatusController.cs similarity index 67% rename from Geekbot.net/WebApi/Status.cs rename to Geekbot.net/WebApi/StatusController.cs index 0597e83..2fd84f8 100644 --- a/Geekbot.net/WebApi/Status.cs +++ b/Geekbot.net/WebApi/StatusController.cs @@ -1,17 +1,18 @@ using Nancy; +using Geekbot.net.Lib; namespace Geekbot.net.WebApi { - public class Status : NancyModule + public class StatusController : NancyModule { - public Status() + public StatusController() { Get("/", args => { var responseBody = new ApiStatusDto() { - GeekbotVersion = "3.4", - ApiVersion = "0.1", + GeekbotVersion = Constants.BotVersion.ToString(), + ApiVersion = Constants.ApiVersion.ToString(), Status = "Online" }; return Response.AsJson(responseBody); From c48a3b5d84c547c8101e9e1e1b3c19d811b184b7 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Tue, 3 Oct 2017 18:46:14 +0200 Subject: [PATCH 045/553] Stop people from saving their own quotes --- Geekbot.net/Commands/Quote.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Geekbot.net/Commands/Quote.cs b/Geekbot.net/Commands/Quote.cs index 053a63a..699a731 100644 --- a/Geekbot.net/Commands/Quote.cs +++ b/Geekbot.net/Commands/Quote.cs @@ -48,6 +48,11 @@ namespace Geekbot.net.Commands { try { + if (user.Id == Context.Message.Author.Id) + { + await ReplyAsync("You can't save your own quotes..."); + return; + } var lastMessage = await getLastMessageByUser(user); var quote = createQuoteObject(lastMessage); var quoteStore = JsonConvert.SerializeObject(quote); @@ -68,6 +73,11 @@ namespace Geekbot.net.Commands try { var message = await Context.Channel.GetMessageAsync(messageId); + if (message.Author.Id == Context.Message.Author.Id) + { + await ReplyAsync("You can't save your own quotes..."); + return; + } var quote = createQuoteObject(message); var quoteStore = JsonConvert.SerializeObject(quote); redis.SetAdd($"{Context.Guild.Id}:Quotes", quoteStore); From ef6fd15116f38333f8d35b5b6b7a919ac71ce2e3 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Tue, 3 Oct 2017 21:47:09 +0200 Subject: [PATCH 046/553] Addin Pokedex Command --- Geekbot.net/Commands/Pokedex.cs | 83 +++++++++++++++++++++++++++++++++ Geekbot.net/Geekbot.net.csproj | 1 + Geekbot.net/Lib/ErrorHandler.cs | 4 +- 3 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 Geekbot.net/Commands/Pokedex.cs diff --git a/Geekbot.net/Commands/Pokedex.cs b/Geekbot.net/Commands/Pokedex.cs new file mode 100644 index 0000000..19d5776 --- /dev/null +++ b/Geekbot.net/Commands/Pokedex.cs @@ -0,0 +1,83 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Geekbot.net.Lib; +using PokeAPI; +using Serilog; + +namespace Geekbot.net.Commands +{ + public class Pokedex : ModuleBase + { + private readonly IErrorHandler _errorHandler; + private readonly ILogger _logger; + + public Pokedex(IErrorHandler errorHandler, ILogger logger) + { + _errorHandler = errorHandler; + _logger = logger; + } + + [Command("pokedex", RunMode = RunMode.Async)] + [Summary("A Pokedex Tool")] + public async Task GetPokemon([Summary("pokemonName")] string pokemonName) + { + try + { + DataFetcher.ShouldCacheData = true; + Pokemon pokemon; + try + { + pokemon = await DataFetcher.GetNamedApiObject(pokemonName.ToLower()); + } + catch + { + await ReplyAsync("I couldn't find that pokemon :confused:"); + return; + } + var embed = await pokemonEmbedBuilder(pokemon); + await ReplyAsync("", false, embed.Build()); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + private async Task pokemonEmbedBuilder(Pokemon pokemon) + { + var eb = new EmbedBuilder(); + var species = await DataFetcher.GetApiObject(pokemon.ID); + eb.Title = $"#{pokemon.ID} {toUpper(pokemon.Name)}"; + eb.Description = species.FlavorTexts[1].FlavorText; + eb.ThumbnailUrl = pokemon.Sprites.FrontMale ?? pokemon.Sprites.FrontFemale; + eb.AddInlineField(getSingularOrPlural(pokemon.Types.Length, "Type"), string.Join(", ", pokemon.Types.Select(t => toUpper(t.Type.Name)))); + eb.AddInlineField(getSingularOrPlural(pokemon.Abilities.Length, "Ability"), string.Join(", ", pokemon.Abilities.Select(t => toUpper(t.Ability.Name)))); + eb.AddInlineField("Height", pokemon.Height); + eb.AddInlineField("Weight", pokemon.Mass); + return eb; + } + + private string getSingularOrPlural(int lenght, string word) + { + if (lenght == 1) + { + return word; + } + return word.EndsWith("y") ? $"{word.Remove(word.Length-1)}ies" : $"{word}s"; + } + + private string toUpper(string s) + { + if (string.IsNullOrEmpty(s)) + { + return string.Empty; + } + return char.ToUpper(s[0]) + s.Substring(1); + } + + + } +} \ No newline at end of file diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 056eb93..f139230 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -21,6 +21,7 @@ + diff --git a/Geekbot.net/Lib/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandler.cs index 5ded3a2..dfba5fa 100644 --- a/Geekbot.net/Lib/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandler.cs @@ -15,7 +15,7 @@ namespace Geekbot.net.Lib // this.botOwnerDmChannel = botOwnerDmChannel; } - public void HandleCommandException(Exception e, ICommandContext Context, string errorMessage = "") + public void HandleCommandException(Exception e, ICommandContext Context, string errorMessage = "Something went wrong :confused:") { var errorMsg = $"Error Occured while executing \"{Context.Message.Content}\", executed by \"{Context.User.Username}\", complete message was \"{Context.Message}\""; @@ -31,6 +31,6 @@ namespace Geekbot.net.Lib public interface IErrorHandler { - void HandleCommandException(Exception e, ICommandContext Context, string errorMessage = ""); + void HandleCommandException(Exception e, ICommandContext Context, string errorMessage = "Something went wrong :confused:"); } } \ No newline at end of file From 0c9a2a56192131c092ba90b2dc5b4a6704ffe95f Mon Sep 17 00:00:00 2001 From: Runebaas Date: Wed, 4 Oct 2017 01:35:25 +0200 Subject: [PATCH 047/553] Adding battletag saving, settings in user repo, cors, help now reffers to website --- Geekbot.net/Commands/BattleTag.cs | 77 +++++++++++++++++++++++++++++++ Geekbot.net/Commands/Help.cs | 51 ++++++++++++-------- Geekbot.net/Commands/Pokedex.cs | 4 +- Geekbot.net/Geekbot.net.csproj | 1 + Geekbot.net/Lib/UserRepository.cs | 16 +++++++ Geekbot.net/WebApi/WebConfig.cs | 22 +++++++++ 6 files changed, 149 insertions(+), 22 deletions(-) create mode 100644 Geekbot.net/Commands/BattleTag.cs create mode 100644 Geekbot.net/WebApi/WebConfig.cs diff --git a/Geekbot.net/Commands/BattleTag.cs b/Geekbot.net/Commands/BattleTag.cs new file mode 100644 index 0000000..0003f58 --- /dev/null +++ b/Geekbot.net/Commands/BattleTag.cs @@ -0,0 +1,77 @@ +using System; +using System.Threading.Tasks; +using Discord.Commands; +using Geekbot.net.Lib; +using StackExchange.Redis; + +namespace Geekbot.net.Commands +{ + [Group("battletag")] + public class BattleTag : ModuleBase + { + private readonly IErrorHandler _errorHandler; + private readonly IDatabase _redis; + private readonly IUserRepository _userRepository; + + public BattleTag(IErrorHandler errorHandler, IDatabase redis, IUserRepository userRepository) + { + _errorHandler = errorHandler; + _redis = redis; + _userRepository = userRepository; + } + + [Command(RunMode = RunMode.Async)] + [Summary("Get your battletag")] + public async Task BattleTagCmd() + { + try + { + var tag = _userRepository.getUserSetting(Context.User.Id, "BattleTag"); + if (!string.IsNullOrEmpty(tag)) + { + + await ReplyAsync($"Your BattleTag is {tag}"); + } + else + { + await ReplyAsync("You haven't set your BattleTag, set it with `!battletag user#1234`"); + } + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + [Command(RunMode = RunMode.Async)] + [Summary("Save your battletag")] + public async Task BattleTagCmd([Summary("Battletag")] string tag) + { + try + { + if (isValidTag(tag)) + { + _userRepository.saveUserSetting(Context.User.Id, "BattleTag", tag); + await ReplyAsync("Saved!"); + } + else + { + await ReplyAsync("That doesn't seem to be a valid battletag"); + } + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + private bool isValidTag(string tag) + { + var splited = tag.Split("#"); + if (splited.Length != 2) return false; + if (!int.TryParse(splited[1], out int discriminator)) return false; + if (splited[1].Length == 4 || splited[1].Length == 5) return true; + return false; + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Help.cs b/Geekbot.net/Commands/Help.cs index 2a0ce13..5ab8270 100644 --- a/Geekbot.net/Commands/Help.cs +++ b/Geekbot.net/Commands/Help.cs @@ -1,42 +1,55 @@ -using System.Linq; +using System; +using System.Linq; using System.Text; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.net.Lib; namespace Geekbot.net.Commands { public class Help : ModuleBase { private readonly CommandService _commands; + private readonly IErrorHandler _errorHandler; - public Help(CommandService commands) + public Help(CommandService commands, IErrorHandler errorHandler) { _commands = commands; + _errorHandler = errorHandler; } [Command("help", RunMode = RunMode.Async)] [Summary("List all Commands")] public async Task GetHelp() { - var sb = new StringBuilder(); - sb.AppendLine("```"); - sb.AppendLine("**Geekbot Command list**"); - sb.AppendLine(""); - sb.AppendLine(tp("Name", 15) + tp("Parameters", 19) + "Description"); - foreach (var cmd in _commands.Commands) + try { - var param = string.Join(", !", cmd.Aliases); - if (!param.Contains("admin")) - if (cmd.Parameters.Any()) - sb.AppendLine(tp(param, 15) + - tp(string.Join(" ", cmd.Parameters.Select(e => e.Summary)), 19) + - cmd.Summary); - else - sb.AppendLine(tp(param, 34) + cmd.Summary); + var sb = new StringBuilder(); +// sb.AppendLine("```"); +// sb.AppendLine("**Geekbot Command list**"); +// sb.AppendLine(""); +// sb.AppendLine(tp("Name", 15) + tp("Parameters", 19) + "Description"); +// foreach (var cmd in _commands.Commands) +// { +// var param = string.Join(", !", cmd.Aliases); +// if (!param.Contains("admin")) +// if (cmd.Parameters.Any()) +// sb.AppendLine(tp(param, 15) + +// tp(string.Join(" ", cmd.Parameters.Select(e => e.Summary)), 19) + +// cmd.Summary); +// else +// sb.AppendLine(tp(param, 34) + cmd.Summary); +// } +// sb.AppendLine("```"); + sb.AppendLine("For a list of all commands, please visit the following page"); + sb.AppendLine("https://geekbot.pizzaandcoffee.rocks/commands"); + var dm = await Context.User.GetOrCreateDMChannelAsync(); + await dm.SendMessageAsync(sb.ToString()); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); } - sb.AppendLine("```"); - var dm = await Context.User.GetOrCreateDMChannelAsync(); - await dm.SendMessageAsync(sb.ToString()); } // Table Padding, short function name because of many usages diff --git a/Geekbot.net/Commands/Pokedex.cs b/Geekbot.net/Commands/Pokedex.cs index 19d5776..0a36e37 100644 --- a/Geekbot.net/Commands/Pokedex.cs +++ b/Geekbot.net/Commands/Pokedex.cs @@ -12,12 +12,10 @@ namespace Geekbot.net.Commands public class Pokedex : ModuleBase { private readonly IErrorHandler _errorHandler; - private readonly ILogger _logger; - public Pokedex(IErrorHandler errorHandler, ILogger logger) + public Pokedex(IErrorHandler errorHandler) { _errorHandler = errorHandler; - _logger = logger; } [Command("pokedex", RunMode = RunMode.Async)] diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index f139230..f2a8f2d 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -21,6 +21,7 @@ + diff --git a/Geekbot.net/Lib/UserRepository.cs b/Geekbot.net/Lib/UserRepository.cs index 9c85936..4832aac 100644 --- a/Geekbot.net/Lib/UserRepository.cs +++ b/Geekbot.net/Lib/UserRepository.cs @@ -71,6 +71,20 @@ namespace Geekbot.net.Lib } return dto; } + + public string getUserSetting(ulong userId, string setting) + { + return _redis.HashGet($"Users:{userId}", setting); + } + + public bool saveUserSetting(ulong userId, string setting, string value) + { + _redis.HashSet($"Users:{userId}", new HashEntry[] + { + new HashEntry(setting, value) + }); + return true; + } } public class UserRepositoryUser @@ -86,5 +100,7 @@ namespace Geekbot.net.Lib { Task Update(SocketUser user); UserRepositoryUser Get(ulong userId); + string getUserSetting(ulong userId, string setting); + bool saveUserSetting(ulong userId, string setting, string value); } } \ No newline at end of file diff --git a/Geekbot.net/WebApi/WebConfig.cs b/Geekbot.net/WebApi/WebConfig.cs new file mode 100644 index 0000000..dfcfe01 --- /dev/null +++ b/Geekbot.net/WebApi/WebConfig.cs @@ -0,0 +1,22 @@ +using Nancy; +using Nancy.Bootstrapper; +using Nancy.TinyIoc; + +namespace Geekbot.net.WebApi +{ + public class WebConfig : DefaultNancyBootstrapper + { + protected override void RequestStartup(TinyIoCContainer container, IPipelines pipelines, NancyContext context) + { + + //CORS Enable + pipelines.AfterRequest.AddItemToEndOfPipeline((ctx) => + { + ctx.Response.WithHeader("Access-Control-Allow-Origin", "*") + .WithHeader("Access-Control-Allow-Methods", "POST,GET") + .WithHeader("Access-Control-Allow-Headers", "Accept, Origin, Content-type"); + + }); + } + } +} \ No newline at end of file From f30c136785b36dce8655be708aaad860aea1ac2d Mon Sep 17 00:00:00 2001 From: Runebaas Date: Thu, 5 Oct 2017 21:42:27 +0200 Subject: [PATCH 048/553] Adding random images of squirrels, croissants, pumpkins and turtles, combined all in mediaprovider class --- Geekbot.net/Commands/CheckEm.cs | 8 +- Geekbot.net/Commands/Panda.cs | 23 ---- Geekbot.net/Commands/RandomAnimals.cs | 52 ++++++++ Geekbot.net/Lib/Media/CheckEmImageProvider.cs | 41 ------ Geekbot.net/Lib/Media/MediaProvider.cs | 117 ++++++++++++++++++ Geekbot.net/Lib/Media/PandaProvider.cs | 41 ------ Geekbot.net/Program.cs | 6 +- Geekbot.net/Storage/croissant | 17 +++ Geekbot.net/Storage/pumpkin | 23 ++++ Geekbot.net/Storage/squirrel | 45 +++++++ Geekbot.net/Storage/turtles | 21 ++++ 11 files changed, 281 insertions(+), 113 deletions(-) delete mode 100644 Geekbot.net/Commands/Panda.cs create mode 100644 Geekbot.net/Commands/RandomAnimals.cs delete mode 100644 Geekbot.net/Lib/Media/CheckEmImageProvider.cs create mode 100644 Geekbot.net/Lib/Media/MediaProvider.cs delete mode 100644 Geekbot.net/Lib/Media/PandaProvider.cs create mode 100644 Geekbot.net/Storage/croissant create mode 100644 Geekbot.net/Storage/pumpkin create mode 100644 Geekbot.net/Storage/squirrel create mode 100644 Geekbot.net/Storage/turtles diff --git a/Geekbot.net/Commands/CheckEm.cs b/Geekbot.net/Commands/CheckEm.cs index 5aaef53..15b2cfd 100644 --- a/Geekbot.net/Commands/CheckEm.cs +++ b/Geekbot.net/Commands/CheckEm.cs @@ -11,15 +11,15 @@ namespace Geekbot.net.Commands { public class CheckEm : ModuleBase { - private readonly ICheckEmImageProvider checkEmImages; + private readonly IMediaProvider checkEmImages; private readonly Random rnd; private readonly ILogger logger; private readonly IErrorHandler errorHandler; - public CheckEm(Random RandomClient, ICheckEmImageProvider checkEmImages, ILogger logger, IErrorHandler errorHandler) + public CheckEm(Random RandomClient, IMediaProvider mediaProvider, ILogger logger, IErrorHandler errorHandler) { this.rnd = RandomClient; - this.checkEmImages = checkEmImages; + this.checkEmImages = mediaProvider; this.logger = logger; this.errorHandler = errorHandler; } @@ -50,7 +50,7 @@ namespace Geekbot.net.Commands sb.AppendLine($"**{number}**"); if (!string.IsNullOrEmpty(dubtriqua)) sb.AppendLine($":tada: {dubtriqua} :tada:"); - sb.AppendLine(checkEmImages.GetRandomCheckEmPic()); + sb.AppendLine(checkEmImages.getCheckem()); await ReplyAsync(sb.ToString()); } diff --git a/Geekbot.net/Commands/Panda.cs b/Geekbot.net/Commands/Panda.cs deleted file mode 100644 index 6d9be69..0000000 --- a/Geekbot.net/Commands/Panda.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading.Tasks; -using Discord.Commands; -using Geekbot.net.Lib.Media; - -namespace Geekbot.net.Commands -{ - public class Panda : ModuleBase - { - private readonly IPandaProvider pandaImages; - - public Panda(IPandaProvider pandaImages) - { - this.pandaImages = pandaImages; - } - - [Command("panda", RunMode = RunMode.Async)] - [Summary("Get a random panda")] - public async Task PandaCommand() - { - await ReplyAsync(pandaImages.GetRandomPanda()); - } - } -} \ No newline at end of file diff --git a/Geekbot.net/Commands/RandomAnimals.cs b/Geekbot.net/Commands/RandomAnimals.cs new file mode 100644 index 0000000..e879428 --- /dev/null +++ b/Geekbot.net/Commands/RandomAnimals.cs @@ -0,0 +1,52 @@ +using System.Threading.Tasks; +using Discord.Commands; +using Geekbot.net.Lib.Media; + +namespace Geekbot.net.Commands +{ + public class RandomAnimals : ModuleBase + { + private readonly IMediaProvider _mediaProvider; + + public RandomAnimals(IMediaProvider mediaProvider) + { + _mediaProvider = mediaProvider; + } + + [Command("panda", RunMode = RunMode.Async)] + [Summary("Get a random panda image")] + public async Task panda() + { + await ReplyAsync(_mediaProvider.getPanda()); + } + + [Command("croissant", RunMode = RunMode.Async)] + [Alias("gipfeli")] + [Summary("Get a random croissant image")] + public async Task croissant() + { + await ReplyAsync(_mediaProvider.getCrossant()); + } + + [Command("pumpkin", RunMode = RunMode.Async)] + [Summary("Get a random pumpkin image")] + public async Task pumpkin() + { + await ReplyAsync(_mediaProvider.getPumpkin()); + } + + [Command("squirrel", RunMode = RunMode.Async)] + [Summary("Get a random squirrel image")] + public async Task squirrel() + { + await ReplyAsync(_mediaProvider.getSquirrel()); + } + + [Command("turtle", RunMode = RunMode.Async)] + [Summary("Get a random turtle image")] + public async Task turtle() + { + await ReplyAsync(_mediaProvider.getTurtle()); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Media/CheckEmImageProvider.cs b/Geekbot.net/Lib/Media/CheckEmImageProvider.cs deleted file mode 100644 index 8f2fc77..0000000 --- a/Geekbot.net/Lib/Media/CheckEmImageProvider.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.IO; -using Serilog; - -namespace Geekbot.net.Lib.Media -{ - public class CheckEmImageProvider : ICheckEmImageProvider - { - private readonly string[] checkEmImageArray; - private readonly Random rnd; - private readonly int totalCheckEmImages; - - public CheckEmImageProvider(Random rnd, ILogger logger) - { - var path = Path.GetFullPath("./Storage/checkEmPics"); - if (File.Exists(path)) - { - var rawCheckEmPics = File.ReadAllText(path); - checkEmImageArray = rawCheckEmPics.Split("\n"); - totalCheckEmImages = checkEmImageArray.Length; - this.rnd = rnd; - logger.Verbose($"[Geekbot] [CheckEm] Loaded {totalCheckEmImages} CheckEm Images"); - } - else - { - logger.Error("checkEmPics File not found"); - logger.Error($"Path should be {path}"); - } - } - - public string GetRandomCheckEmPic() - { - return checkEmImageArray[rnd.Next(0, totalCheckEmImages)]; - } - } - - public interface ICheckEmImageProvider - { - string GetRandomCheckEmPic(); - } -} \ No newline at end of file diff --git a/Geekbot.net/Lib/Media/MediaProvider.cs b/Geekbot.net/Lib/Media/MediaProvider.cs new file mode 100644 index 0000000..e67b9c9 --- /dev/null +++ b/Geekbot.net/Lib/Media/MediaProvider.cs @@ -0,0 +1,117 @@ +using System; +using System.IO; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using Serilog; + +namespace Geekbot.net.Lib.Media +{ + public class MediaProvider : IMediaProvider + { + private readonly Random _random; + private readonly ILogger _logger; + private string[] _checkemImages; + private string[] _pandaImages; + private string[] _croissantImages; + private string[] _squirrelImages; + private string[] _pumpkinImages; + private string[] _turtlesImages; + + public MediaProvider(Random rnd, ILogger logger) + { + _random = rnd; + _logger = logger; + + logger.Information("[Geekbot] Loading Media Files"); + + loadCheckem(); + loadPandas(); + bakeCroissants(); + loadSquirrels(); + loadPumpkins(); + loadTurtles(); + } + + private void loadCheckem() + { + var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/checkEmPics")); + _checkemImages = rawLinks.Split("\n"); + _logger.Verbose($"[Geekbot] [Media] Loaded {_checkemImages.Length} CheckEm Images"); + } + + private void loadPandas() + { + var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/pandas")); + _pandaImages = rawLinks.Split("\n"); + _logger.Verbose($"[Geekbot] [Media] Loaded {_pandaImages.Length} Panda Images"); + } + + private void bakeCroissants() + { + var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/croissant")); + _croissantImages = rawLinks.Split("\n"); + _logger.Verbose($"[Geekbot] [Media] Loaded {_croissantImages.Length} Croissant Images"); + } + + private void loadSquirrels() + { + var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/squirrel")); + _squirrelImages = rawLinks.Split("\n"); + _logger.Verbose($"[Geekbot] [Media] Loaded {_squirrelImages.Length} Squirrel Images"); + } + + private void loadPumpkins() + { + var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/pumpkin")); + _pumpkinImages = rawLinks.Split("\n"); + _logger.Verbose($"[Geekbot] [Media] Loaded {_pumpkinImages.Length} Pumpkin Images"); + } + + private void loadTurtles() + { + var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/turtles")); + _turtlesImages = rawLinks.Split("\n"); + _logger.Verbose($"[Geekbot] [Media] Loaded {_turtlesImages.Length} Turtle Images"); + } + + public string getCheckem() + { + return _checkemImages[_random.Next(0, _checkemImages.Length)]; + } + + public string getPanda() + { + return _pandaImages[_random.Next(0, _pandaImages.Length)]; + } + + public string getCrossant() + { + return _croissantImages[_random.Next(0, _croissantImages.Length)]; + } + + public string getSquirrel() + { + return _squirrelImages[_random.Next(0, _squirrelImages.Length)]; + } + + public string getPumpkin() + { + return _pumpkinImages[_random.Next(0, _pumpkinImages.Length)]; + } + + public string getTurtle() + { + return _turtlesImages[_random.Next(0, _turtlesImages.Length)]; + } + } + + public interface IMediaProvider + { + string getCheckem(); + string getPanda(); + string getCrossant(); + string getSquirrel(); + string getPumpkin(); + string getTurtle(); + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Media/PandaProvider.cs b/Geekbot.net/Lib/Media/PandaProvider.cs deleted file mode 100644 index 2ec46b3..0000000 --- a/Geekbot.net/Lib/Media/PandaProvider.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.IO; -using Serilog; - -namespace Geekbot.net.Lib.Media -{ - public class PandaProvider : IPandaProvider - { - private readonly string[] PandaArray; - private readonly Random rnd; - private readonly int totalPandas; - - public PandaProvider(Random rnd, ILogger logger) - { - var path = Path.GetFullPath("./Storage/pandas"); - if (File.Exists(path)) - { - var rawFortunes = File.ReadAllText(path); - PandaArray = rawFortunes.Split("\n"); - totalPandas = PandaArray.Length; - this.rnd = rnd; - logger.Verbose($"[Geekbot] [Pandas] Loaded {totalPandas} Panda Images"); - } - else - { - logger.Error("Pandas File not found"); - logger.Error($"Path should be {path}"); - } - } - - public string GetRandomPanda() - { - return PandaArray[rnd.Next(0, totalPandas)]; - } - } - - public interface IPandaProvider - { - string GetRandomPanda(); - } -} \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index b3ea79a..4693a51 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -107,8 +107,7 @@ namespace Geekbot.net var errorHandler = new ErrorHandler(logger); var RandomClient = new Random(); var fortunes = new FortunesProvider(RandomClient, logger); - var checkEmImages = new CheckEmImageProvider(RandomClient, logger); - var pandaImages = new PandaProvider(RandomClient, logger); + var mediaProvider = new MediaProvider(RandomClient, logger); var malClient = new MalClient(redis, logger); services.AddSingleton(errorHandler); @@ -117,8 +116,7 @@ namespace Geekbot.net services.AddSingleton(userRepository); services.AddSingleton(RandomClient); services.AddSingleton(fortunes); - services.AddSingleton(checkEmImages); - services.AddSingleton(pandaImages); + services.AddSingleton(mediaProvider); services.AddSingleton(malClient); logger.Information("[Geekbot] Connecting to Discord"); diff --git a/Geekbot.net/Storage/croissant b/Geekbot.net/Storage/croissant new file mode 100644 index 0000000..281b790 --- /dev/null +++ b/Geekbot.net/Storage/croissant @@ -0,0 +1,17 @@ +https://i2.wp.com/epicureandculture.com/wp-content/uploads/2014/12/shutterstock_172040546.jpg +http://www.bakespace.com/images/large/5d79070cf21b2f33c3a1dd4336cb27d2.jpeg +http://food.fnr.sndimg.com/content/dam/images/food/fullset/2015/5/7/1/SD1B43_croissants-recipe_s4x3.jpg.rend.hgtvcom.616.462.suffix/1431052139248.jpeg +http://img.taste.com.au/u-Bwjfm_/taste/2016/11/mini-croissants-with-3-fillings-14692-1.jpeg +https://media.newyorker.com/photos/590974702179605b11ad8096/16:9/w_1200,h_630,c_limit/Gopnik-TheMurkyMeaningsofStraightenedOutCroissants.jpg +http://bt.static-redmouse.ch/sites/bielertagblatt.ch/files/styles/bt_article_showroom_landscape/hash/84/c9/84c9aed08415265911ec05c46d25d3ef.jpg?itok=hP5PnHaT +https://www.dermann.at/wp-content/uploads/Schokocroissant_HPBild_1400x900px.jpeg +https://www.bettybossi.ch/static/rezepte/x/bb_bkxx060101_0360a_x.jpg +http://www.engel-beck.ch/uploads/pics/tete-de-moine-gipfel-.jpg +https://storage.cpstatic.ch/storage/og_image/laugengipfel--425319.jpg +https://www.backhaus-kutzer.de/fileadmin/templates/Resources/Public/img/produkte/suesses-gebaeck/Milchhoernchen.png +https://www.kuechengoetter.de/uploads/media/1000x524/00/36390-vanillekipferl-0.jpg?v=1-0 +https://c1.staticflickr.com/3/2835/10874180753_2b2916e3ce_b.jpg +http://www.mistercool.ch/wp-content/uploads/2017/02/Gipfel-mit-Cerealien-7168.png +https://scontent-sea1-1.cdninstagram.com/t51.2885-15/s480x480/e35/c40.0.999.999/15099604_105396696611384_2866237281000226816_n.jpg?ig_cache_key=MTM4MzQxOTU1MDc5NjUxNzcwMA%3D%3D.2.c +http://www.lecrobag.de/wp-content/uploads/2014/03/Wurst_2014_l.jpg +https://www.thecookierookie.com/wp-content/uploads/2017/02/sheet-pan-chocolate-croissants-collage1.jpeg \ No newline at end of file diff --git a/Geekbot.net/Storage/pumpkin b/Geekbot.net/Storage/pumpkin new file mode 100644 index 0000000..4b8e6f2 --- /dev/null +++ b/Geekbot.net/Storage/pumpkin @@ -0,0 +1,23 @@ +https://i.pinimg.com/736x/0a/a7/8a/0aa78af25e114836e1a42585fb7b09ed--funny-pumpkins-pumkin-carving.jpg +http://wdy.h-cdn.co/assets/16/31/980x1470/gallery-1470321728-shot-two-021.jpg +https://i.pinimg.com/736x/6c/62/bf/6c62bfa73a19ffd9fc6f2d720d5e9764--cool-pumpkin-carving-carving-pumpkins.jpg +http://images6.fanpop.com/image/photos/38900000/Jack-o-Lantern-halloween-38991566-500-415.jpg +http://ghk.h-cdn.co/assets/15/37/1441834730-pumpkin-carve-2.jpg +http://diy.sndimg.com/content/dam/images/diy/fullset/2011/7/26/1/iStock-10761186_halloween-pumpkin-in-garden_s4x3.jpg.rend.hgtvcom.966.725.suffix/1420851319631.jpeg +http://ghk.h-cdn.co/assets/cm/15/11/54ffe537af882-snail-pumpkin-de.jpg +https://www.digsdigs.com/photos/2009/10/100-halloween-pumpkin-carving-ideas-12.jpg +http://diy.sndimg.com/content/dam/images/diy/fullset/2010/6/4/0/CI-Kyle-Nishioka_big-teeth-Jack-O-Lantern_s4x3.jpg.rend.hgtvcom.966.725.suffix/1420699522718.jpeg +https://twistedsifter.files.wordpress.com/2011/10/most-amazing-pumpkin-carving-ray-villafane-10.jpg?w=521&h=739 +https://i.pinimg.com/736x/09/c4/b1/09c4b187b266c1f65332294f66009944--funny-pumpkins-halloween-pumpkins.jpg +http://www.evilmilk.com/pictures/The_Pumpkin_Man.jpg +http://cache.lovethispic.com/uploaded_images/blogs/13-Funny-Pumpkin-Carvings-5773-9.JPG +http://ihappyhalloweenpictures.com/wp-content/uploads/2016/10/funny-halloween-pumpkin.jpg +http://www.smallhomelove.com/wp-content/uploads/2012/08/leg-eating-pumpkin.jpg +https://cdn.shopify.com/s/files/1/0773/6789/articles/Halloween_Feature_8ff7a7c4-2cb3-4584-a85f-5d4d1e6ca26e.jpg?v=1476211360 +http://4vector.com/i/free-vector-pumpkin-boy-color-version-clip-art_107714_Pumpkin_Boy_Color_Version_clip_art_hight.png +https://i.pinimg.com/736x/59/8a/0f/598a0fbf789631b76c1ffd4443194d8e--halloween-pumpkins-fall-halloween.jpg +https://i.pinimg.com/originals/8f/86/f9/8f86f95457467872b371ba697d341961.jpg +http://nerdist.com/wp-content/uploads/2015/08/taleshalloween1.jpg +http://www.designbolts.com/wp-content/uploads/2014/09/Scary-Pumpkin_Grin_stencil-Ideas.jpg +http://vignette2.wikia.nocookie.net/scoobydoo/images/7/75/Pumpkin_monsters_%28Witch%27s_Ghost%29.png/revision/latest?cb=20140520070213 +https://taholtorf.files.wordpress.com/2013/10/36307-1920x1280.jpg diff --git a/Geekbot.net/Storage/squirrel b/Geekbot.net/Storage/squirrel new file mode 100644 index 0000000..2216465 --- /dev/null +++ b/Geekbot.net/Storage/squirrel @@ -0,0 +1,45 @@ +http://orig14.deviantart.net/6016/f/2010/035/c/b/first_squirrel_assassin_by_shotokanteddy.jpg +https://thumbs-prod.si-cdn.com/eoEYA_2Hau4795uKoecUZZgz-3w=/800x600/filters:no_upscale()/https://public-media.smithsonianmag.com/filer/52/f9/52f93262-c29b-4a4f-b031-0c7ad145ed5f/42-33051942.jpg +http://images5.fanpop.com/image/photos/30700000/Squirrel-squirrels-30710732-400-300.jpg +https://www.lovethegarden.com/sites/default/files/files/Red%20%26%20Grey%20Squirrel%20picture%20side%20by%20side-LR.jpg +http://i.dailymail.co.uk/i/pix/2016/02/24/16/158F7E7C000005DC-3462228-image-a-65_1456331226865.jpg +http://2.bp.blogspot.com/-egfnMhUb8tg/T_dAIu1m6cI/AAAAAAAAPPU/v4x9q4WqWl8/s640/cute-squirrel-hey-watcha-thinkin-about.jpg +https://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Squirrel_posing.jpg/287px-Squirrel_posing.jpg +https://i.pinimg.com/736x/51/db/9b/51db9bad4a87d445d321923c7d56b501--red-squirrel-animal-kingdom.jpg +https://metrouk2.files.wordpress.com/2016/10/ad_223291521.jpg?w=620&h=949&crop=1 +http://www.redsquirrelsunited.org.uk/wp-content/uploads/2016/07/layer-slider.jpg +http://images.mentalfloss.com/sites/default/files/squirrel-hero.jpg?resize=1100x740 +https://i.pinimg.com/736x/ce/9c/59/ce9c5990b193046400d98724595cdaf3--red-squirrel-chipmunks.jpg +https://www.brooklynpaper.com/assets/photos/40/30/dtg-squirrel-attacks-prospect-park-patrons-2017-07-28-bk01_z.jpg +http://www.freakingnews.com/pictures/16000/Squirrel-Shark-16467.jpg +http://img09.deviantart.net/5c1c/i/2013/138/0/6/barbarian_squirel_by_coucoucmoa-d64r9m4.jpg +https://i.pinimg.com/736x/b4/5c/0d/b45c0d00b1a57e9f84f27f13cb019001--baby-squirrel-red-squirrel.jpg +https://i.pinimg.com/736x/0f/75/87/0f7587bb613ab524763afe8c9a532e5c--cute-squirrel-squirrels.jpg +http://cdn.images.express.co.uk/img/dynamic/128/590x/Grey-squirrel-828838.jpg +http://www.lovethispic.com/uploaded_images/79964-Squirrel-Smelling-A-Flower.jpg +https://i.pinimg.com/736x/23/d5/f9/23d5f9868f7d76c79c49bef53ae08f7f--squirrel-funny-red-squirrel.jpg +http://stories.barkpost.com/wp-content/uploads/2016/01/squirrel-3-copy.jpg +https://i.ytimg.com/vi/pzUs0DdzK3Y/hqdefault.jpg +https://www.askideas.com/media/41/I-Swear-It-Wasnt-Me-Funny-Squirrel-Meme-Picture-For-Facebook.jpg +https://i.pinimg.com/736x/2d/54/d8/2d54d8d2a9b3ab9d3e78544b75afd88e--funny-animal-pictures-humorous-pictures.jpg +http://www.funny-animalpictures.com/media/content/items/images/funnysquirrels0012_O.jpg +http://funny-pics.co/wp-content/uploads/funny-squirrel-and-coffee-picture.jpg +https://pbs.twimg.com/media/Bi4Ij6CIgAAgEdZ.jpg +http://www.funnyjunksite.com/pictures/wp-content/uploads/2015/06/Funny-Superman-Squirrels.jpg +https://i.pinimg.com/736x/bf/35/00/bf3500104f8394909d116259d1f0575e--funny-squirrel-squirrel-girl.jpg +http://quotespill.com/wp-content/uploads/2017/07/Squirrel-Meme-Draw-me-like-one-of-your-french-squirrrels-min.jpg +https://i.pinimg.com/736x/e2/16/bb/e216bba53f80fc8e0111d371e9850159--funny-squirrels-cute-squirrel.jpg +https://i.pinimg.com/736x/52/43/c9/5243c93377245be1f686218c266d775c--funny-squirrel-baby-squirrel.jpg +https://i.pinimg.com/736x/0c/be/1d/0cbe1da8ad2c0cf3882a806b6fd88965--cute-pictures-funny-animal-pictures.jpg +https://i.pinimg.com/736x/e5/08/67/e508670aa00ca3c896eccb81c4f6e2a8--funny-squirrel-baby-squirrel.jpg +https://i.pinimg.com/736x/1c/7d/4f/1c7d4f067a10066aad802ce5ac468d71--group-boards-a-squirrel.jpg +http://funny-pics.co/wp-content/uploads/funny-squirrel-on-a-branch.jpg +http://loldamn.com/wp-content/uploads/2016/06/funny-squirrel-playing-water-bending.jpg +https://cdn.trendhunterstatic.com/thumbs/squirrel-photography.jpeg +https://i.pinimg.com/736x/d6/42/12/d64212cc6221916db4173962bf6c131a--cute-squirrel-baby-squirrel.jpg +https://i.pinimg.com/236x/10/13/58/101358f2afc2c7d6b6a668046e7b8382--funny-animal-pictures-funny-animals.jpg +https://i.pinimg.com/736x/da/0d/fe/da0dfe93bb26887795f906e8fa97d68e--secret-squirrel-cute-squirrel.jpg +http://2.bp.blogspot.com/-HLieBqEuQoM/UDkRmeyzB5I/AAAAAAAABHs/RtsEynn5t6Y/s1600/hd-squirrel-wallpaper-with-a-brown-squirrel-eating-watermelon-wallpapers-backgrounds-pictures-photos.jpg +http://www.city-data.com/forum/members/brenda-starz-328928-albums-brenda-s-funny-squirrel-comment-pic-s-pic5075-punk-squirrels.jpg +http://img15.deviantart.net/9c50/i/2011/213/c/9/just_taking_it_easy_by_lou_in_canada-d42do3d.jpg +http://3.bp.blogspot.com/-AwsSk76R2Is/USQa3-dszKI/AAAAAAAABUQ/KF_F8HbtP1U/w1200-h630-p-k-no-nu/crazySquirrel.jpg diff --git a/Geekbot.net/Storage/turtles b/Geekbot.net/Storage/turtles new file mode 100644 index 0000000..9dbbf72 --- /dev/null +++ b/Geekbot.net/Storage/turtles @@ -0,0 +1,21 @@ +https://i.guim.co.uk/img/media/6b9be13031738e642f93f9271f3592044726a9b1/0_0_2863_1610/2863.jpg?w=640&h=360&q=55&auto=format&usm=12&fit=max&s=85f3b33cc158b5aa120c143dae1916ed +http://cf.ltkcdn.net/small-pets/images/std/212089-676x450-Turtle-feeding-on-leaf.jpg +https://static1.squarespace.com/static/5369465be4b0507a1fd05af0/53767a6be4b0ad0822345e52/57e40ba4893fc031e05a018f/1498243318058/solvin.jpg?format=1500w +https://c402277.ssl.cf1.rackcdn.com/photos/419/images/story_full_width/HI_287338Hero.jpg?1433950119 +https://www.cdc.gov/salmonella/agbeni-08-17/images/turtle.jpg +https://cdn.arstechnica.net/wp-content/uploads/2017/08/GettyImages-524757168.jpg +http://pmdvod.nationalgeographic.com/NG_Video/595/319/4504517_098_05_TOS_thumbnail_640x360_636296259676.jpg +http://cdn1.arkive.org/media/7D/7D46329A-6ED2-4F08-909E-7B596417994A/Presentation.Large/Big-headed-turtle-close-up.jpg +http://s7d2.scene7.com/is/image/PetSmart/ARTHMB-CleaningYourTortoiseOrTurtlesHabitat-20160818?$AR1104$ +https://fthmb.tqn.com/9VGWzK_GWlvrjxtdFPX6EJxOq24=/960x0/filters:no_upscale()/133605352-56a2bce53df78cf7727960db.jpg +https://i.imgur.com/46QmzgF.jpg +https://www.wildgratitude.com/wp-content/uploads/2015/07/turtle-spirit-animal1.jpg +http://www.backwaterreptiles.com/images/turtles/red-eared-slider-turtle-for-sale.jpg +https://i.pinimg.com/736x/f1/f4/13/f1f413d6d07912be6080c08b186630ac--happy-turtle-funny-stuff.jpg +http://www.dupageforest.org/uploadedImages/Content/District_News/Nature_Stories/2016/Snapping%20Turtle%20Scott%20Plantier%20STP4793.jpg +http://turtlebackzoo.com/wp-content/uploads/2016/07/exhibit-headers_0008_SOUTH-AMERICA-600x400.jpg +https://i.ytimg.com/vi/_YfYHFM3Das/maxresdefault.jpg +https://i.pinimg.com/736x/dd/4e/7f/dd4e7f2f921ac28b1d5a59174d477131--cute-baby-sea-turtles-adorable-turtles.jpg +http://kids.nationalgeographic.com/content/dam/kids/photos/animals/Reptiles/A-G/green-sea-turtle-closeup-underwater.adapt.945.1.jpg +https://i.ytimg.com/vi/p4Jj9QZFJvw/hqdefault.jpg +https://fthmb.tqn.com/nirxHkH3jBAe74ife6fJJu6k6q8=/2121x1414/filters:fill(auto,1)/Red-eared-sliders-GettyImages-617946009-58fae8835f9b581d59a5bab6.jpg From b0a61bc63e06cc4f6f96a7f43709cdd66937a77c Mon Sep 17 00:00:00 2001 From: Runebaas Date: Tue, 10 Oct 2017 20:27:39 +0200 Subject: [PATCH 049/553] Only reply with pong when user writes ping with space or just ping (Issue #10) --- Geekbot.net/Handlers.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index bf62cac..d671c76 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -40,7 +40,7 @@ namespace Geekbot.net if (message.Author.IsBot) return Task.CompletedTask; var argPos = 0; var lowCaseMsg = message.ToString().ToLower(); - if (lowCaseMsg.StartsWith("ping")) + if (lowCaseMsg.Equals("ping") || lowCaseMsg.StartsWith("ping ")) { message.Channel.SendMessageAsync("pong"); return Task.CompletedTask; From 58ba2980f97cf2c0125e277d31f8bf37e204428f Mon Sep 17 00:00:00 2001 From: Runebaas Date: Thu, 12 Oct 2017 16:34:10 +0200 Subject: [PATCH 050/553] Command Categories (more or less) --- Geekbot.net/Commands/AdminCmd.cs | 13 ++++++++++--- Geekbot.net/Commands/BattleTag.cs | 2 ++ Geekbot.net/Commands/Cat.cs | 2 ++ Geekbot.net/Commands/CheckEm.cs | 1 + Geekbot.net/Commands/Choose.cs | 4 +++- Geekbot.net/Commands/Counters.cs | 2 ++ Geekbot.net/Commands/Dice.cs | 2 ++ Geekbot.net/Commands/Dog.cs | 2 ++ Geekbot.net/Commands/EightBall.cs | 2 ++ Geekbot.net/Commands/Fortune.cs | 2 ++ Geekbot.net/Commands/Google.cs | 2 ++ Geekbot.net/Commands/GuildInfo.cs | 1 + Geekbot.net/Commands/Help.cs | 1 + Geekbot.net/Commands/Info.cs | 2 ++ Geekbot.net/Commands/Ping.cs | 2 ++ Geekbot.net/Commands/Pokedex.cs | 1 + Geekbot.net/Commands/Quote.cs | 5 +++++ Geekbot.net/Commands/RandomAnimals.cs | 6 ++++++ Geekbot.net/Commands/Rank.cs | 1 + Geekbot.net/Commands/Roll.cs | 6 ++++-- Geekbot.net/Commands/Say.cs | 2 ++ Geekbot.net/Commands/Ship.cs | 2 ++ Geekbot.net/Commands/Stats.cs | 1 + Geekbot.net/Commands/Youtube.cs | 2 ++ Geekbot.net/Commands/mal.cs | 2 ++ Geekbot.net/Lib/CommandCategories.cs | 15 +++++++++++++++ Geekbot.net/Program.cs | 21 +++++++++++++-------- Geekbot.net/WebApi/HelpController.cs | 2 ++ Geekbot.net/WebApi/WebConfig.cs | 8 +++++--- 29 files changed, 97 insertions(+), 17 deletions(-) create mode 100644 Geekbot.net/Lib/CommandCategories.cs diff --git a/Geekbot.net/Commands/AdminCmd.cs b/Geekbot.net/Commands/AdminCmd.cs index 0d9292e..060fc78 100644 --- a/Geekbot.net/Commands/AdminCmd.cs +++ b/Geekbot.net/Commands/AdminCmd.cs @@ -30,6 +30,7 @@ namespace Geekbot.net.Commands [RequireUserPermission(GuildPermission.Administrator)] [Command("welcome", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Admin)] [Summary("Set a Welcome Message (use '$user' to mention the new joined user).")] public async Task SetWelcomeMessage([Remainder] [Summary("message")] string welcomeMessage) { @@ -40,6 +41,7 @@ namespace Geekbot.net.Commands } [Command("youtubekey", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Admin)] [Summary("Set the youtube api key")] public async Task SetYoutubeKey([Summary("API Key")] string key) { @@ -55,6 +57,7 @@ namespace Geekbot.net.Commands } [Command("game", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Admin)] [Summary("Set the game that the bot is playing")] public async Task SetGame([Remainder] [Summary("Game")] string key) { @@ -72,7 +75,8 @@ namespace Geekbot.net.Commands } [Command("popuserrepo", RunMode = RunMode.Async)] - [Summary("Set the game that the bot is playing")] + [Remarks(CommandCategories.Admin)] + [Summary("Populate user cache")] public async Task popUserRepoCommand() { try @@ -117,7 +121,8 @@ namespace Geekbot.net.Commands [RequireUserPermission(GuildPermission.Administrator)] [Command("modchannel", RunMode = RunMode.Async)] - [Summary("Set the game that the bot is playing")] + [Remarks(CommandCategories.Admin)] + [Summary("Set a channel for moderation purposes")] public async Task selectModChannel([Summary("ChannelId")] ulong channelId) { try @@ -143,6 +148,7 @@ namespace Geekbot.net.Commands [RequireUserPermission(GuildPermission.Administrator)] [Command("showleave", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Admin)] [Summary("Notify modchannel when someone leaves")] public async Task showLeave([Summary("true/false")] bool enabled) { @@ -169,7 +175,8 @@ namespace Geekbot.net.Commands [RequireUserPermission(GuildPermission.Administrator)] [Command("showdel", RunMode = RunMode.Async)] - [Summary("Notify modchannel when someone leaves")] + [Remarks(CommandCategories.Admin)] + [Summary("Notify modchannel when someone deletes a message")] public async Task showDelete([Summary("true/false")] bool enabled) { var modChannelId = (ulong)_redis.HashGet($"{Context.Guild.Id}:Settings", "ModChannel"); diff --git a/Geekbot.net/Commands/BattleTag.cs b/Geekbot.net/Commands/BattleTag.cs index 0003f58..65a9444 100644 --- a/Geekbot.net/Commands/BattleTag.cs +++ b/Geekbot.net/Commands/BattleTag.cs @@ -21,6 +21,7 @@ namespace Geekbot.net.Commands } [Command(RunMode = RunMode.Async)] + [Remarks(CommandCategories.Games)] [Summary("Get your battletag")] public async Task BattleTagCmd() { @@ -44,6 +45,7 @@ namespace Geekbot.net.Commands } [Command(RunMode = RunMode.Async)] + [Remarks(CommandCategories.Games)] [Summary("Save your battletag")] public async Task BattleTagCmd([Summary("Battletag")] string tag) { diff --git a/Geekbot.net/Commands/Cat.cs b/Geekbot.net/Commands/Cat.cs index 3e7973b..4d5f001 100644 --- a/Geekbot.net/Commands/Cat.cs +++ b/Geekbot.net/Commands/Cat.cs @@ -2,6 +2,7 @@ using System.Net.Http; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.net.Lib; using Newtonsoft.Json; namespace Geekbot.net.Commands @@ -9,6 +10,7 @@ namespace Geekbot.net.Commands public class Cat : ModuleBase { [Command("cat", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Randomness)] [Summary("Return a random image of a cat.")] public async Task Say() { diff --git a/Geekbot.net/Commands/CheckEm.cs b/Geekbot.net/Commands/CheckEm.cs index 15b2cfd..be49cd1 100644 --- a/Geekbot.net/Commands/CheckEm.cs +++ b/Geekbot.net/Commands/CheckEm.cs @@ -25,6 +25,7 @@ namespace Geekbot.net.Commands } [Command("checkem", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Randomness)] [Summary("Check for dubs")] public async Task MuhDubs() { diff --git a/Geekbot.net/Commands/Choose.cs b/Geekbot.net/Commands/Choose.cs index 338851d..9d19c84 100644 --- a/Geekbot.net/Commands/Choose.cs +++ b/Geekbot.net/Commands/Choose.cs @@ -1,6 +1,7 @@ using System; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.net.Lib; namespace Geekbot.net.Commands { @@ -14,7 +15,8 @@ namespace Geekbot.net.Commands } [Command("choose", RunMode = RunMode.Async)] - [Summary("Seperate options with a semicolon.")] + [Remarks(CommandCategories.Helpers)] + [Summary("Let the bot choose for you, seperate options with a semicolon.")] public async Task Command([Remainder] [Summary("option1;option2")] string choices) { var choicesArray = choices.Split(';'); diff --git a/Geekbot.net/Commands/Counters.cs b/Geekbot.net/Commands/Counters.cs index 45ffa3d..f999f1e 100644 --- a/Geekbot.net/Commands/Counters.cs +++ b/Geekbot.net/Commands/Counters.cs @@ -22,6 +22,7 @@ namespace Geekbot.net.Commands } [Command("good", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Karma)] [Summary("Increase Someones Karma")] public async Task Good([Summary("@someone")] IUser user) { @@ -64,6 +65,7 @@ namespace Geekbot.net.Commands } [Command("bad", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Karma)] [Summary("Decrease Someones Karma")] public async Task Bad([Summary("@someone")] IUser user) { diff --git a/Geekbot.net/Commands/Dice.cs b/Geekbot.net/Commands/Dice.cs index c40757c..a0aa03c 100644 --- a/Geekbot.net/Commands/Dice.cs +++ b/Geekbot.net/Commands/Dice.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.net.Lib; namespace Geekbot.net.Commands { @@ -17,6 +18,7 @@ namespace Geekbot.net.Commands } [Command("dice", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Randomness)] [Summary("Roll a dice.")] public async Task RollCommand([Remainder] [Summary("diceType")] string diceType = "1d20") { diff --git a/Geekbot.net/Commands/Dog.cs b/Geekbot.net/Commands/Dog.cs index 481500e..7ce9470 100644 --- a/Geekbot.net/Commands/Dog.cs +++ b/Geekbot.net/Commands/Dog.cs @@ -2,6 +2,7 @@ using System.Net.Http; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.net.Lib; using Newtonsoft.Json; namespace Geekbot.net.Commands @@ -9,6 +10,7 @@ namespace Geekbot.net.Commands public class Dog : ModuleBase { [Command("dog", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Randomness)] [Summary("Return a random image of a dog.")] public async Task Say() { diff --git a/Geekbot.net/Commands/EightBall.cs b/Geekbot.net/Commands/EightBall.cs index 5ca4ae6..3138c69 100644 --- a/Geekbot.net/Commands/EightBall.cs +++ b/Geekbot.net/Commands/EightBall.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.net.Lib; namespace Geekbot.net.Commands { @@ -15,6 +16,7 @@ namespace Geekbot.net.Commands } [Command("8ball", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Randomness)] [Summary("Ask 8Ball a Question.")] public async Task Ball([Remainder] [Summary("Question")] string echo) { diff --git a/Geekbot.net/Commands/Fortune.cs b/Geekbot.net/Commands/Fortune.cs index d97b437..ba4bc07 100644 --- a/Geekbot.net/Commands/Fortune.cs +++ b/Geekbot.net/Commands/Fortune.cs @@ -1,5 +1,6 @@ using System.Threading.Tasks; using Discord.Commands; +using Geekbot.net.Lib; using Geekbot.net.Lib.Media; namespace Geekbot.net.Commands @@ -14,6 +15,7 @@ namespace Geekbot.net.Commands } [Command("fortune", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Randomness)] [Summary("Get a random fortune")] public async Task GetAFortune() { diff --git a/Geekbot.net/Commands/Google.cs b/Geekbot.net/Commands/Google.cs index 05c8c55..16151c5 100644 --- a/Geekbot.net/Commands/Google.cs +++ b/Geekbot.net/Commands/Google.cs @@ -1,11 +1,13 @@ using System.Threading.Tasks; using Discord.Commands; +using Geekbot.net.Lib; namespace Geekbot.net.Commands { public class Google : ModuleBase { [Command("google", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Fun)] [Summary("Google Something.")] public async Task Eyes([Remainder, Summary("SearchText")] string searchText) { diff --git a/Geekbot.net/Commands/GuildInfo.cs b/Geekbot.net/Commands/GuildInfo.cs index ff9c4a0..7ee3d43 100644 --- a/Geekbot.net/Commands/GuildInfo.cs +++ b/Geekbot.net/Commands/GuildInfo.cs @@ -18,6 +18,7 @@ namespace Geekbot.net.Commands } [Command("serverstats", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Statistics)] [Summary("Show some info about the bot.")] public async Task getInfo() { diff --git a/Geekbot.net/Commands/Help.cs b/Geekbot.net/Commands/Help.cs index 5ab8270..9ba8792 100644 --- a/Geekbot.net/Commands/Help.cs +++ b/Geekbot.net/Commands/Help.cs @@ -19,6 +19,7 @@ namespace Geekbot.net.Commands } [Command("help", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Helpers)] [Summary("List all Commands")] public async Task GetHelp() { diff --git a/Geekbot.net/Commands/Info.cs b/Geekbot.net/Commands/Info.cs index a620518..29ee180 100644 --- a/Geekbot.net/Commands/Info.cs +++ b/Geekbot.net/Commands/Info.cs @@ -23,6 +23,7 @@ namespace Geekbot.net.Commands } [Command("info", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Helpers)] [Summary("Get Information about the bot")] public async Task BotInfo() { @@ -51,6 +52,7 @@ namespace Geekbot.net.Commands } [Command("uptime", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Helpers)] [Summary("Get the Bot Uptime")] public async Task BotUptime() { diff --git a/Geekbot.net/Commands/Ping.cs b/Geekbot.net/Commands/Ping.cs index 698c383..c41700e 100644 --- a/Geekbot.net/Commands/Ping.cs +++ b/Geekbot.net/Commands/Ping.cs @@ -1,5 +1,6 @@ using System.Threading.Tasks; using Discord.Commands; +using Geekbot.net.Lib; namespace Geekbot.net.Commands { @@ -7,6 +8,7 @@ namespace Geekbot.net.Commands { [Command("👀", RunMode = RunMode.Async)] [Summary("Look at the bot.")] + [Remarks(CommandCategories.Fun)] public async Task Eyes() { await ReplyAsync("S... Stop looking at me... baka!"); diff --git a/Geekbot.net/Commands/Pokedex.cs b/Geekbot.net/Commands/Pokedex.cs index 0a36e37..b187841 100644 --- a/Geekbot.net/Commands/Pokedex.cs +++ b/Geekbot.net/Commands/Pokedex.cs @@ -19,6 +19,7 @@ namespace Geekbot.net.Commands } [Command("pokedex", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Helpers)] [Summary("A Pokedex Tool")] public async Task GetPokemon([Summary("pokemonName")] string pokemonName) { diff --git a/Geekbot.net/Commands/Quote.cs b/Geekbot.net/Commands/Quote.cs index 699a731..ca2d134 100644 --- a/Geekbot.net/Commands/Quote.cs +++ b/Geekbot.net/Commands/Quote.cs @@ -26,6 +26,7 @@ namespace Geekbot.net.Commands } [Command()] + [Remarks(CommandCategories.Quotes)] [Summary("Return a random quoute from the database")] public async Task getRandomQuote() { @@ -43,6 +44,7 @@ namespace Geekbot.net.Commands } [Command("save")] + [Remarks(CommandCategories.Quotes)] [Summary("Save a quote from the last sent message by @user")] public async Task saveQuote([Summary("@user")] IUser user) { @@ -67,6 +69,7 @@ namespace Geekbot.net.Commands } [Command("save")] + [Remarks(CommandCategories.Quotes)] [Summary("Save a quote from a message id")] public async Task saveQuote([Summary("messageId")] ulong messageId) { @@ -92,6 +95,7 @@ namespace Geekbot.net.Commands } [Command("make")] + [Remarks(CommandCategories.Quotes)] [Summary("Create a quote from the last sent message by @user")] public async Task returnSpecifiedQuote([Summary("@user")] IUser user) { @@ -109,6 +113,7 @@ namespace Geekbot.net.Commands } [Command("make")] + [Remarks(CommandCategories.Quotes)] [Summary("Create a quote from a message id")] public async Task returnSpecifiedQuote([Summary("messageId")] ulong messageId) { diff --git a/Geekbot.net/Commands/RandomAnimals.cs b/Geekbot.net/Commands/RandomAnimals.cs index e879428..7d1f723 100644 --- a/Geekbot.net/Commands/RandomAnimals.cs +++ b/Geekbot.net/Commands/RandomAnimals.cs @@ -1,5 +1,6 @@ using System.Threading.Tasks; using Discord.Commands; +using Geekbot.net.Lib; using Geekbot.net.Lib.Media; namespace Geekbot.net.Commands @@ -14,6 +15,7 @@ namespace Geekbot.net.Commands } [Command("panda", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Randomness)] [Summary("Get a random panda image")] public async Task panda() { @@ -22,6 +24,7 @@ namespace Geekbot.net.Commands [Command("croissant", RunMode = RunMode.Async)] [Alias("gipfeli")] + [Remarks(CommandCategories.Randomness)] [Summary("Get a random croissant image")] public async Task croissant() { @@ -29,6 +32,7 @@ namespace Geekbot.net.Commands } [Command("pumpkin", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Randomness)] [Summary("Get a random pumpkin image")] public async Task pumpkin() { @@ -36,6 +40,7 @@ namespace Geekbot.net.Commands } [Command("squirrel", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Randomness)] [Summary("Get a random squirrel image")] public async Task squirrel() { @@ -43,6 +48,7 @@ namespace Geekbot.net.Commands } [Command("turtle", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Randomness)] [Summary("Get a random turtle image")] public async Task turtle() { diff --git a/Geekbot.net/Commands/Rank.cs b/Geekbot.net/Commands/Rank.cs index 3ec6203..274b7ef 100644 --- a/Geekbot.net/Commands/Rank.cs +++ b/Geekbot.net/Commands/Rank.cs @@ -27,6 +27,7 @@ namespace Geekbot.net.Commands } [Command("rank", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Statistics)] [Summary("get user top 10")] public async Task RankCmd() { diff --git a/Geekbot.net/Commands/Roll.cs b/Geekbot.net/Commands/Roll.cs index 66caa40..5103c9f 100644 --- a/Geekbot.net/Commands/Roll.cs +++ b/Geekbot.net/Commands/Roll.cs @@ -1,6 +1,7 @@ using System; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.net.Lib; using StackExchange.Redis; namespace Geekbot.net.Commands @@ -17,8 +18,9 @@ namespace Geekbot.net.Commands } [Command("roll", RunMode = RunMode.Async)] - [Summary("Roll a number between 1 and 100.")] - public async Task RollCommand([Remainder] [Summary("stuff...")] string stuff = "nothing") + [Remarks(CommandCategories.Fun)] + [Summary("Guess which number the bot will roll (1-100")] + public async Task RollCommand([Remainder] [Summary("guess")] string stuff = "noGuess") { var number = rnd.Next(1, 100); var guess = 1000; diff --git a/Geekbot.net/Commands/Say.cs b/Geekbot.net/Commands/Say.cs index 52b4477..4f057db 100644 --- a/Geekbot.net/Commands/Say.cs +++ b/Geekbot.net/Commands/Say.cs @@ -1,6 +1,7 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.net.Lib; namespace Geekbot.net.Commands { @@ -8,6 +9,7 @@ namespace Geekbot.net.Commands { [RequireUserPermission(GuildPermission.Administrator)] [Command("say", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Admin)] [Summary("Say Something.")] public async Task Echo([Remainder] [Summary("What?")] string echo) { diff --git a/Geekbot.net/Commands/Ship.cs b/Geekbot.net/Commands/Ship.cs index da2bd2e..ea1e942 100644 --- a/Geekbot.net/Commands/Ship.cs +++ b/Geekbot.net/Commands/Ship.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.net.Lib; using StackExchange.Redis; namespace Geekbot.net.Commands @@ -18,6 +19,7 @@ namespace Geekbot.net.Commands } [Command("Ship", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Fun)] [Summary("Ask the Shipping meter")] public async Task Command([Summary("@User1")] IUser user1, [Summary("@User2")] IUser user2) { diff --git a/Geekbot.net/Commands/Stats.cs b/Geekbot.net/Commands/Stats.cs index 61b57d9..b35cc45 100644 --- a/Geekbot.net/Commands/Stats.cs +++ b/Geekbot.net/Commands/Stats.cs @@ -19,6 +19,7 @@ namespace Geekbot.net.Commands } [Command("stats", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Statistics)] [Summary("Get information about this user")] public async Task User([Summary("@someone")] IUser user = null) { diff --git a/Geekbot.net/Commands/Youtube.cs b/Geekbot.net/Commands/Youtube.cs index c496cde..ee743b3 100644 --- a/Geekbot.net/Commands/Youtube.cs +++ b/Geekbot.net/Commands/Youtube.cs @@ -1,6 +1,7 @@ using System; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.net.Lib; using Google.Apis.Services; using Google.Apis.YouTube.v3; using StackExchange.Redis; @@ -17,6 +18,7 @@ namespace Geekbot.net.Commands } [Command("yt", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Helpers)] [Summary("Search for something on youtube.")] public async Task Yt([Remainder] [Summary("Title")] string searchQuery) { diff --git a/Geekbot.net/Commands/mal.cs b/Geekbot.net/Commands/mal.cs index 840c7c7..4e364ee 100644 --- a/Geekbot.net/Commands/mal.cs +++ b/Geekbot.net/Commands/mal.cs @@ -18,6 +18,7 @@ namespace Geekbot.net.Commands } [Command("anime", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Helpers)] [Summary("Show Info about an Anime.")] public async Task searchAnime([Remainder, Summary("AnimeName")] string animeName) { @@ -66,6 +67,7 @@ namespace Geekbot.net.Commands } [Command("manga", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Helpers)] [Summary("Show Info about a Manga.")] public async Task searchManga([Remainder, Summary("MangaName")] string mangaName) { diff --git a/Geekbot.net/Lib/CommandCategories.cs b/Geekbot.net/Lib/CommandCategories.cs new file mode 100644 index 0000000..ca7ea58 --- /dev/null +++ b/Geekbot.net/Lib/CommandCategories.cs @@ -0,0 +1,15 @@ +namespace Geekbot.net.Lib +{ + public class CommandCategories + { + public const string Randomness = "Randomness"; + public const string Karma = "Karma"; + public const string Quotes = "Quotes"; + public const string Fun = "Fun"; + public const string Statistics = "Statistics"; + public const string Helpers = "Helpers"; + public const string Games = "Games"; + public const string Admin = "Admin"; + public const string Uncategorized = "Uncategorized"; + } +} \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 4693a51..637a8be 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -105,16 +105,16 @@ namespace Geekbot.net userRepository = new UserRepository(redis, logger); var errorHandler = new ErrorHandler(logger); - var RandomClient = new Random(); - var fortunes = new FortunesProvider(RandomClient, logger); - var mediaProvider = new MediaProvider(RandomClient, logger); + var randomClient = new Random(); + var fortunes = new FortunesProvider(randomClient, logger); + var mediaProvider = new MediaProvider(randomClient, logger); var malClient = new MalClient(redis, logger); services.AddSingleton(errorHandler); services.AddSingleton(redis); services.AddSingleton(logger); services.AddSingleton(userRepository); - services.AddSingleton(RandomClient); + services.AddSingleton(randomClient); services.AddSingleton(fortunes); services.AddSingleton(mediaProvider); services.AddSingleton(malClient); @@ -162,10 +162,7 @@ namespace Geekbot.net } if (!args.Contains("--disable-api")) { - logger.Information("[API] Starting Webserver"); - var webApiUrl = new Uri("http://localhost:12995"); - new NancyHost(webApiUrl).Start(); - logger.Information($"[API] Webserver now running on {webApiUrl}"); + startWebApi(); } logger.Information("[Geekbot] Done and ready for use\n"); @@ -185,6 +182,14 @@ namespace Geekbot.net return true; } + private async Task startWebApi() + { + logger.Information("[API] Starting Webserver"); + var webApiUrl = new Uri("http://localhost:12995"); + new NancyHost(webApiUrl).Start(); + logger.Information($"[API] Webserver now running on {webApiUrl}"); + } + private async Task FinishSetup() { var appInfo = await client.GetApplicationInfoAsync(); diff --git a/Geekbot.net/WebApi/HelpController.cs b/Geekbot.net/WebApi/HelpController.cs index b318b63..6146352 100644 --- a/Geekbot.net/WebApi/HelpController.cs +++ b/Geekbot.net/WebApi/HelpController.cs @@ -38,6 +38,7 @@ namespace Geekbot.net.WebApi { Name = cmd.Name, Summary = cmd.Summary, + Category = cmd.Remarks ?? CommandCategories.Uncategorized, IsAdminCommand = (param.Contains("admin")), Aliases = cmd.Aliases.ToArray(), Params = cmdParamsObj @@ -60,6 +61,7 @@ namespace Geekbot.net.WebApi public class CommandDto { public string Name { get; set; } + public string Category { get; set; } public string Summary { get; set; } public bool IsAdminCommand { get; set; } public Array Aliases { get; set; } diff --git a/Geekbot.net/WebApi/WebConfig.cs b/Geekbot.net/WebApi/WebConfig.cs index dfcfe01..7875ccb 100644 --- a/Geekbot.net/WebApi/WebConfig.cs +++ b/Geekbot.net/WebApi/WebConfig.cs @@ -1,4 +1,5 @@ -using Nancy; +using System; +using Nancy; using Nancy.Bootstrapper; using Nancy.TinyIoc; @@ -13,8 +14,9 @@ namespace Geekbot.net.WebApi pipelines.AfterRequest.AddItemToEndOfPipeline((ctx) => { ctx.Response.WithHeader("Access-Control-Allow-Origin", "*") - .WithHeader("Access-Control-Allow-Methods", "POST,GET") - .WithHeader("Access-Control-Allow-Headers", "Accept, Origin, Content-type"); + .WithHeader("Access-Control-Allow-Methods", "GET") + .WithHeader("Access-Control-Allow-Headers", "Accept, Origin, Content-type") + .WithHeader("Last-Modified", DateTime.Now.ToString()); }); } From 60fbe3d3fa3d9e66c984666ba619d8bb0e0ac02b Mon Sep 17 00:00:00 2001 From: Runebaas Date: Fri, 13 Oct 2017 23:40:39 +0200 Subject: [PATCH 051/553] Super basic overwatch command --- Geekbot.net/Commands/BattleTag.cs | 2 +- Geekbot.net/Commands/Overwatch.cs | 132 ++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 Geekbot.net/Commands/Overwatch.cs diff --git a/Geekbot.net/Commands/BattleTag.cs b/Geekbot.net/Commands/BattleTag.cs index 65a9444..e466abb 100644 --- a/Geekbot.net/Commands/BattleTag.cs +++ b/Geekbot.net/Commands/BattleTag.cs @@ -67,7 +67,7 @@ namespace Geekbot.net.Commands } } - private bool isValidTag(string tag) + public static bool isValidTag(string tag) { var splited = tag.Split("#"); if (splited.Length != 2) return false; diff --git a/Geekbot.net/Commands/Overwatch.cs b/Geekbot.net/Commands/Overwatch.cs new file mode 100644 index 0000000..3527cdf --- /dev/null +++ b/Geekbot.net/Commands/Overwatch.cs @@ -0,0 +1,132 @@ +using System; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Geekbot.net.Lib; +using Google.Apis.Util; +using OverwatchAPI; +using OverwatchAPI.Config; +using Serilog; +using StackExchange.Redis; + +namespace Geekbot.net.Commands +{ + [Group("ow")] + public class Overwatch : ModuleBase + { + private readonly IErrorHandler _errorHandler; + private readonly ILogger _logger; + private readonly IUserRepository _userRepository; + + public Overwatch(IErrorHandler errorHandler, ILogger logger, IDatabase redis, IUserRepository userRepository) + { + _errorHandler = errorHandler; + _logger = logger; + _userRepository = userRepository; + } + + [Command("profile", RunMode = RunMode.Async)] + [Summary("Get someones overwatch profile. EU on PC only. Default battletag is your own (if set).")] + [Remarks(CommandCategories.Games)] + public async Task owProfile() + { + try + { + var tag = _userRepository.getUserSetting(Context.User.Id, "BattleTag"); + if (string.IsNullOrEmpty(tag)) + { + await ReplyAsync("You have no battle Tag saved, use `!battletag`"); + return; + } + var profile = await createProfile(tag); + if (profile == null) + { + await ReplyAsync("That player doesn't seem to exist"); + return; + } + await ReplyAsync("", false, profile.Build()); + + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + [Command("profile", RunMode = RunMode.Async)] + [Summary("Get someones overwatch profile. EU on PC only. Default battletag is your own (if set).")] + [Remarks(CommandCategories.Games)] + public async Task owProfile([Summary("BattleTag")] string tag) + { + try + { + if (!BattleTag.isValidTag(tag)) + { + await ReplyAsync("That doesn't seem to be a valid battletag..."); + return; + } + var profile = await createProfile(tag); + if (profile == null) + { + await ReplyAsync("That player doesn't seem to exist"); + return; + } + await ReplyAsync("", false, profile.Build()); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + [Command("profile", RunMode = RunMode.Async)] + [Summary("Get someones overwatch profile. EU on PC only.")] + [Remarks(CommandCategories.Games)] + public async Task owProfile([Summary("@someone")] IUser user) + { + try + { + var tag = _userRepository.getUserSetting(user.Id, "BattleTag"); + if (string.IsNullOrEmpty(tag)) + { + await ReplyAsync("This user didn't set a battletag"); + return; + } + var profile = await createProfile(tag); + if (profile == null) + { + await ReplyAsync("That player doesn't seem to exist"); + return; + } + await ReplyAsync("", false, profile.Build()); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + private async Task createProfile(string battletag) + { + var owConfig = new OverwatchConfig.Builder().WithRegions(Region.Eu).WithPlatforms(Platform.Pc); + using (var owClient = new OverwatchClient(owConfig)) + { + var player = await owClient.GetPlayerAsync(battletag); + if (player.Username == null) + { + return null; + } + _logger.Debug($"[OW] Username = {player.Username}"); + var eb = new EmbedBuilder(); + eb.WithAuthor(new EmbedAuthorBuilder() + .WithIconUrl(player.ProfilePortraitUrl) + .WithName(player.Username)); + eb.Url = player.ProfileUrl; + eb.AddInlineField("Level", player.PlayerLevel); + eb.AddInlineField("Current Rank", player.CompetitiveRank > 0 ? player.CompetitiveRank.ToString() : "Unranked"); + + return eb; + } + } + } +} From 2eca82e8994e47608e2432c59ac0a4650f660b7d Mon Sep 17 00:00:00 2001 From: Runebaas Date: Thu, 19 Oct 2017 21:43:37 +0200 Subject: [PATCH 052/553] Add role self service commands --- Geekbot.net/Commands/Role.cs | 122 ++++++++++++++++++++++++++++++++ Geekbot.net/Lib/ErrorHandler.cs | 15 ++-- 2 files changed, 128 insertions(+), 9 deletions(-) create mode 100644 Geekbot.net/Commands/Role.cs diff --git a/Geekbot.net/Commands/Role.cs b/Geekbot.net/Commands/Role.cs new file mode 100644 index 0000000..2e1939e --- /dev/null +++ b/Geekbot.net/Commands/Role.cs @@ -0,0 +1,122 @@ +using System; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using AngleSharp; +using Discord; +using Discord.Commands; +using Geekbot.net.Lib; +using StackExchange.Redis; + +namespace Geekbot.net.Commands +{ + [Group("role")] + public class Role : ModuleBase + { + private readonly IErrorHandler _errorHandler; + private readonly IDatabase _redis; + + public Role(IErrorHandler errorHandler, IDatabase redis) + { + _errorHandler = errorHandler; + _redis = redis; + } + + [Command(RunMode = RunMode.Async)] + [Remarks(CommandCategories.Helpers)] + [Summary("Get a list of all available roles.")] + public async Task getAllRoles() + { + try + { + var roles = _redis.HashGetAll($"{Context.Guild.Id}:RoleWhitelist"); + if (roles.Length == 0) + { + await ReplyAsync("There are no roles configured for this server"); + return; + } + var sb = new StringBuilder(); + sb.AppendLine($"**Self Service Roles on {Context.Guild.Name}**"); + sb.AppendLine("To get a role, use `!role name`"); + foreach (var role in roles) + { + sb.AppendLine($"- {role.Name}"); + } + await ReplyAsync(sb.ToString()); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + [Command(RunMode = RunMode.Async)] + [Remarks(CommandCategories.Helpers)] + [Summary("Get a role by mentioning it.")] + public async Task giveRole([Summary("roleNickname")] string roleName) + { + try + { + if (_redis.HashExists($"{Context.Guild.Id}:RoleWhitelist", roleName)) + { + var guildUser = (IGuildUser) Context.User; + var roleId = ulong.Parse(_redis.HashGet($"{Context.Guild.Id}:RoleWhitelist", roleName)); + var role = Context.Guild.Roles.First(r => r.Id == roleId); + if (role == null) + { + await ReplyAsync("That role doesn't seem to exist"); + return; + } + if (guildUser.RoleIds.Contains(roleId)) + { + guildUser.RemoveRoleAsync(role); + await ReplyAsync($"Removed you from {role.Name}"); + return; + } + await guildUser.AddRoleAsync(role); + await ReplyAsync($"Added you to {role.Name}"); + return; + } + await ReplyAsync("That role doesn't seem to exist"); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + [RequireUserPermission(GuildPermission.Administrator)] + [Command("add", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Admin)] + [Summary("Add a role to the whitelist.")] + public async Task addRole([Summary("@role")] IRole role, [Summary("alias")] string roleName) + { + try + { + _redis.HashSet($"{Context.Guild.Id}:RoleWhitelist", new HashEntry[] { new HashEntry(roleName, role.Id.ToString()) }); + await ReplyAsync($"Added {role.Name} to the whitelist"); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + [RequireUserPermission(GuildPermission.Administrator)] + [Command("remove", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Admin)] + [Summary("Remove a role from the whitelist.")] + public async Task removeRole([Summary("roleNickname")] string roleName) + { + try + { + _redis.HashDelete($"{Context.Guild.Id}:RoleWhitelist", roleName); + await ReplyAsync($"Removed {roleName} from the whitelist"); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandler.cs index dfba5fa..65b61ef 100644 --- a/Geekbot.net/Lib/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandler.cs @@ -6,26 +6,23 @@ namespace Geekbot.net.Lib { public class ErrorHandler : IErrorHandler { - private readonly ILogger logger; -// private readonly IDMChannel botOwnerDmChannel; + private readonly ILogger _logger; - public ErrorHandler(ILogger logger /*, IDMChannel botOwnerDmChannel*/) + public ErrorHandler(ILogger logger) { - this.logger = logger; -// this.botOwnerDmChannel = botOwnerDmChannel; + _logger = logger; } public void HandleCommandException(Exception e, ICommandContext Context, string errorMessage = "Something went wrong :confused:") { var errorMsg = - $"Error Occured while executing \"{Context.Message.Content}\", executed by \"{Context.User.Username}\", complete message was \"{Context.Message}\""; - logger.Error(e, errorMsg); + $"Error Occured while executing \"{Context.Message.Content}\", executed by \"{Context.User.Username}\""; + _logger.Error(e, errorMsg); if (!string.IsNullOrEmpty(errorMessage)) { Context.Channel.SendMessageAsync(errorMessage); } -// await botOwnerDmChannel.SendMessageAsync($"{errorMsg}```{e.StackTrace}```"); -// await Context.Channel.SendMessageAsync("Something went wrong..."); + } } From 75c699e25b8df2a70894da24f81a84dc384c6612 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Thu, 19 Oct 2017 22:01:42 +0200 Subject: [PATCH 053/553] Make modchannel command easier and some random stuff --- Geekbot.net/Commands/AdminCmd.cs | 12 +++--------- Geekbot.net/Commands/Role.cs | 2 +- Geekbot.net/Handlers.cs | 14 +++++++------- Geekbot.net/Program.cs | 2 +- 4 files changed, 12 insertions(+), 18 deletions(-) diff --git a/Geekbot.net/Commands/AdminCmd.cs b/Geekbot.net/Commands/AdminCmd.cs index 060fc78..213f9cc 100644 --- a/Geekbot.net/Commands/AdminCmd.cs +++ b/Geekbot.net/Commands/AdminCmd.cs @@ -123,16 +123,10 @@ namespace Geekbot.net.Commands [Command("modchannel", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Set a channel for moderation purposes")] - public async Task selectModChannel([Summary("ChannelId")] ulong channelId) + public async Task selectModChannel([Summary("#Channel")] ISocketMessageChannel channel) { try { - var channel = (ISocketMessageChannel)_client.GetChannel(channelId); - if (string.IsNullOrEmpty(channel.Name)) - { - await ReplyAsync("I couldn't find that channel..."); - return; - } var sb = new StringBuilder(); sb.AppendLine("Successfully saved mod channel, you can now do the following"); sb.AppendLine("- `!admin showleave true` - send message to mod channel when someone leaves"); @@ -152,7 +146,7 @@ namespace Geekbot.net.Commands [Summary("Notify modchannel when someone leaves")] public async Task showLeave([Summary("true/false")] bool enabled) { - var modChannelId = (ulong)_redis.HashGet($"{Context.Guild.Id}:Settings", "ModChannel"); + var modChannelId = ulong.Parse(_redis.HashGet($"{Context.Guild.Id}:Settings", "ModChannel")); try { var modChannel = (ISocketMessageChannel) _client.GetChannel(modChannelId); @@ -179,7 +173,7 @@ namespace Geekbot.net.Commands [Summary("Notify modchannel when someone deletes a message")] public async Task showDelete([Summary("true/false")] bool enabled) { - var modChannelId = (ulong)_redis.HashGet($"{Context.Guild.Id}:Settings", "ModChannel"); + var modChannelId = ulong.Parse(_redis.HashGet($"{Context.Guild.Id}:Settings", "ModChannel")); try { var modChannel = (ISocketMessageChannel) _client.GetChannel(modChannelId); diff --git a/Geekbot.net/Commands/Role.cs b/Geekbot.net/Commands/Role.cs index 2e1939e..8be5fe6 100644 --- a/Geekbot.net/Commands/Role.cs +++ b/Geekbot.net/Commands/Role.cs @@ -69,7 +69,7 @@ namespace Geekbot.net.Commands } if (guildUser.RoleIds.Contains(roleId)) { - guildUser.RemoveRoleAsync(role); + await guildUser.RemoveRoleAsync(role); await ReplyAsync($"Removed you from {role.Name}"); return; } diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index d671c76..a98731c 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -105,10 +105,10 @@ namespace Geekbot.net var sendLeftEnabled = _redis.HashGet($"{user.Guild.Id}:Settings", "ShowLeave"); if (sendLeftEnabled.ToString() == "1") { - var modChannel = _redis.HashGet($"{user.Guild.Id}:Settings", "ModChannel"); - if (!string.IsNullOrEmpty(modChannel)) + var modChannel = ulong.Parse(_redis.HashGet($"{user.Guild.Id}:Settings", "ModChannel")); + if (!string.IsNullOrEmpty(modChannel.ToString())) { - var modChannelSocket = (ISocketMessageChannel) await _client.GetChannelAsync((ulong)modChannel); + var modChannelSocket = (ISocketMessageChannel) await _client.GetChannelAsync(modChannel); await modChannelSocket.SendMessageAsync($"{user.Username}#{user.Discriminator} left the server"); } } @@ -132,15 +132,15 @@ namespace Geekbot.net var sendLeftEnabled = _redis.HashGet($"{guild.Id}:Settings", "ShowDelete"); if (sendLeftEnabled.ToString() == "1") { - var modChannel = _redis.HashGet($"{guild.Id}:Settings", "ModChannel"); - if (!string.IsNullOrEmpty(modChannel)) + var modChannel = ulong.Parse(_redis.HashGet($"{guild.Id}:Settings", "ModChannel")); + if (!string.IsNullOrEmpty(modChannel.ToString()) && modChannel != channel.Id) { - var modChannelSocket = (ISocketMessageChannel) await _client.GetChannelAsync((ulong)modChannel); + var modChannelSocket = (ISocketMessageChannel) await _client.GetChannelAsync(modChannel); var sb = new StringBuilder(); if (message.Value != null) { sb.AppendLine( - $"{message.Value.Author.Username}#{message.Value.Author.Discriminator} deleted the following message from <#{channel.Id}>"); + $"The following message from {message.Value.Author.Username}#{message.Value.Author.Discriminator} was deleted in <#{channel.Id}>"); sb.AppendLine(message.Value.Content); } else diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 637a8be..0a78266 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -182,7 +182,7 @@ namespace Geekbot.net return true; } - private async Task startWebApi() + private void startWebApi() { logger.Information("[API] Starting Webserver"); var webApiUrl = new Uri("http://localhost:12995"); From 73f29a5cf1a92534174a2f190a8368895a3d4378 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Thu, 19 Oct 2017 23:55:09 +0200 Subject: [PATCH 054/553] Make it impossible to add roles with evaluated permissions to self service (because people are stupid enough to do so apparently) --- Geekbot.net/Commands/Role.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Geekbot.net/Commands/Role.cs b/Geekbot.net/Commands/Role.cs index 8be5fe6..ae93a57 100644 --- a/Geekbot.net/Commands/Role.cs +++ b/Geekbot.net/Commands/Role.cs @@ -93,6 +93,20 @@ namespace Geekbot.net.Commands { try { + if (role.IsManaged) + { + await ReplyAsync("You can't add a role that is managed by discord"); + return; + } + if (role.Permissions.ManageRoles + || role.Permissions.Administrator + || role.Permissions.ManageGuild + || role.Permissions.BanMembers + || role.Permissions.KickMembers) + { + await ReplyAsync("Woah, i don't think you want to add that role to self service as it contains some dangerous permissions"); + return; + } _redis.HashSet($"{Context.Guild.Id}:RoleWhitelist", new HashEntry[] { new HashEntry(roleName, role.Id.ToString()) }); await ReplyAsync($"Added {role.Name} to the whitelist"); } From ac73a8e6f91e14021cc6d8a02a493e3cf95425cf Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sat, 21 Oct 2017 20:25:14 +0200 Subject: [PATCH 055/553] Geekbot now uses the GNU GPLv3 license --- LICENSE | 687 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 670 insertions(+), 17 deletions(-) diff --git a/LICENSE b/LICENSE index a0a211e..f288702 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,674 @@ -MIT License + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 -Copyright (c) 2017 Pizza and Coffee Studios + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + Preamble -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. + The GNU General Public License is a free, copyleft license for +software and other kinds of works. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. From 1f48d0387bd70f6216a00187fd618b74713b7c48 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Wed, 25 Oct 2017 00:58:59 +0200 Subject: [PATCH 056/553] Making the level calculator more efficient --- Geekbot.net/Commands/GuildInfo.cs | 43 +++++++++++++++++++------------ Geekbot.net/Commands/Stats.cs | 6 +++-- Geekbot.net/Lib/LevelCalc.cs | 41 ++++++++++++++++++----------- Geekbot.net/Program.cs | 2 ++ 4 files changed, 59 insertions(+), 33 deletions(-) diff --git a/Geekbot.net/Commands/GuildInfo.cs b/Geekbot.net/Commands/GuildInfo.cs index 7ee3d43..8eae02e 100644 --- a/Geekbot.net/Commands/GuildInfo.cs +++ b/Geekbot.net/Commands/GuildInfo.cs @@ -10,11 +10,15 @@ namespace Geekbot.net.Commands { public class GuildInfo : ModuleBase { - private readonly IDatabase redis; + private readonly IDatabase _redis; + private readonly ILevelCalc _levelCalc; + private readonly IErrorHandler _errorHandler; - public GuildInfo(IDatabase redis) + public GuildInfo(IDatabase redis, ILevelCalc levelCalc, IErrorHandler errorHandler) { - this.redis = redis; + _redis = redis; + _levelCalc = levelCalc; + _errorHandler = errorHandler; } [Command("serverstats", RunMode = RunMode.Async)] @@ -22,23 +26,30 @@ namespace Geekbot.net.Commands [Summary("Show some info about the bot.")] public async Task getInfo() { - var eb = new EmbedBuilder(); - eb.WithAuthor(new EmbedAuthorBuilder() - .WithIconUrl(Context.Guild.IconUrl) - .WithName(Context.Guild.Name)); - eb.WithColor(new Color(110, 204, 147)); + try + { + var eb = new EmbedBuilder(); + eb.WithAuthor(new EmbedAuthorBuilder() + .WithIconUrl(Context.Guild.IconUrl) + .WithName(Context.Guild.Name)); + eb.WithColor(new Color(110, 204, 147)); - var created = Context.Guild.CreatedAt; - var age = Math.Floor((DateTime.Now - created).TotalDays); + var created = Context.Guild.CreatedAt; + var age = Math.Floor((DateTime.Now - created).TotalDays); - var messages = redis.HashGet($"{Context.Guild.Id}:Messages", 0.ToString()); - var level = LevelCalc.GetLevelAtExperience((int) messages); + var messages = _redis.HashGet($"{Context.Guild.Id}:Messages", 0.ToString()); + var level = _levelCalc.GetLevelAtExperience((int) messages); - eb.AddField("Server Age", $"{created.Day}/{created.Month}/{created.Year} ({age} days)"); - eb.AddInlineField("Level", level) - .AddInlineField("Messages", messages); + eb.AddField("Server Age", $"{created.Day}/{created.Month}/{created.Year} ({age} days)"); + eb.AddInlineField("Level", level) + .AddInlineField("Messages", messages); - await ReplyAsync("", false, eb.Build()); + await ReplyAsync("", false, eb.Build()); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } } public static string FirstCharToUpper(string input) diff --git a/Geekbot.net/Commands/Stats.cs b/Geekbot.net/Commands/Stats.cs index b35cc45..37c3ea9 100644 --- a/Geekbot.net/Commands/Stats.cs +++ b/Geekbot.net/Commands/Stats.cs @@ -11,11 +11,13 @@ namespace Geekbot.net.Commands { private readonly IDatabase _redis; private readonly IErrorHandler _errorHandler; + private readonly ILevelCalc _levelCalc; - public Stats(IDatabase redis, IErrorHandler errorHandler) + public Stats(IDatabase redis, IErrorHandler errorHandler, ILevelCalc levelCalc) { _redis = redis; _errorHandler = errorHandler; + _levelCalc = levelCalc; } [Command("stats", RunMode = RunMode.Async)] @@ -34,7 +36,7 @@ namespace Geekbot.net.Commands var messages = (int) _redis.HashGet($"{Context.Guild.Id}:Messages", userInfo.Id.ToString()); var guildMessages = (int) _redis.HashGet($"{Context.Guild.Id}:Messages", 0.ToString()); - var level = LevelCalc.GetLevelAtExperience(messages); + var level = _levelCalc.GetLevelAtExperience(messages); var percent = Math.Round((double) (100 * messages) / guildMessages, 2); diff --git a/Geekbot.net/Lib/LevelCalc.cs b/Geekbot.net/Lib/LevelCalc.cs index 5d47dc9..6ab5162 100644 --- a/Geekbot.net/Lib/LevelCalc.cs +++ b/Geekbot.net/Lib/LevelCalc.cs @@ -1,27 +1,38 @@ using System; +using System.Collections.Generic; namespace Geekbot.net.Lib { - internal class LevelCalc + internal class LevelCalc : ILevelCalc { - private static int GetExperienceAtLevel(int level) - { - double total = 0; - for (var i = 1; i < level; i++) - total += Math.Floor(i + 300 * Math.Pow(2, i / 7.0)); + private int[] _levels; - return (int) Math.Floor(total / 16); + public LevelCalc() + { + var levels = new List(); + double total = 0; + for (var i = 1; i < 120; i++) + { + total += Math.Floor(i + 300 * Math.Pow(2, i / 7.0)); + levels.Add((int) Math.Floor(total / 16)); + } + _levels = levels.ToArray(); } - public static int GetLevelAtExperience(int experience) + public int GetLevelAtExperience(int experience) { - int index; - - for (index = 0; index < 120; index++) - if (GetExperienceAtLevel(index + 1) > experience) - break; - - return index; + var returnVal = 1; + foreach (var level in _levels) + { + if (level > experience) break; + returnVal++; + } + return returnVal; } } + + public interface ILevelCalc + { + int GetLevelAtExperience(int experience); + } } \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 0a78266..2488827 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -109,11 +109,13 @@ namespace Geekbot.net var fortunes = new FortunesProvider(randomClient, logger); var mediaProvider = new MediaProvider(randomClient, logger); var malClient = new MalClient(redis, logger); + var levelCalc = new LevelCalc(); services.AddSingleton(errorHandler); services.AddSingleton(redis); services.AddSingleton(logger); services.AddSingleton(userRepository); + services.AddSingleton(levelCalc); services.AddSingleton(randomClient); services.AddSingleton(fortunes); services.AddSingleton(mediaProvider); From 2e083bc188b9eb78365e4afe1e4ec996ea0f9b4a Mon Sep 17 00:00:00 2001 From: Runebaas Date: Wed, 25 Oct 2017 19:33:22 +0200 Subject: [PATCH 057/553] Fixing the highscore bug (hopefully) --- Geekbot.net/Lib/UserRepository.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Geekbot.net/Lib/UserRepository.cs b/Geekbot.net/Lib/UserRepository.cs index 4832aac..4f5de16 100644 --- a/Geekbot.net/Lib/UserRepository.cs +++ b/Geekbot.net/Lib/UserRepository.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using AngleSharp.Dom.Css; using Discord.WebSocket; using Serilog; using StackExchange.Redis; @@ -20,13 +21,14 @@ namespace Geekbot.net.Lib { try { - _redis.HashSetAsync($"Users:{user.Id}", new HashEntry[] + _redis.HashSetAsync($"Users:{user.Id.ToString()}", new HashEntry[] { new HashEntry("Id", user.Id.ToString()), new HashEntry("Username", user.Username), new HashEntry("Discriminator", user.Discriminator), new HashEntry("AvatarUrl", user.GetAvatarUrl() ?? "0"), new HashEntry("IsBot", user.IsBot), + new HashEntry("Joined", user.CreatedAt.ToString()), }); _logger.Information($"[UserRepository] Updated User {user.Id}"); return Task.FromResult(true); @@ -40,11 +42,11 @@ namespace Geekbot.net.Lib public UserRepositoryUser Get(ulong userId) { - var user = _redis.HashGetAll($"Users:{userId}"); - for (int i = 1; i < 6; i++) + var user = _redis.HashGetAll($"Users:{userId.ToString()}"); + for (int i = 1; i < 11; i++) { if (user.Length != 0) break; - user = _redis.HashGetAll($"Users:{userId + (ulong)i}"); + user = _redis.HashGetAll($"Users:{(userId + (ulong)i).ToString()}"); } var dto = new UserRepositoryUser(); @@ -67,6 +69,9 @@ namespace Geekbot.net.Lib case "IsBot": dto.IsBot = a.Value == 1; break; + case "Joined": + dto.Joined = DateTimeOffset.Parse(a.Value); + break; } } return dto; @@ -94,6 +99,7 @@ namespace Geekbot.net.Lib public string Discriminator { get; set; } public string AvatarUrl { get; set; } public bool IsBot { get; set; } + public DateTimeOffset Joined { get; set; } } public interface IUserRepository From 9efac29956556471261c6f24e50774bf0d1e20ba Mon Sep 17 00:00:00 2001 From: Runebaas Date: Thu, 26 Oct 2017 00:55:04 +0200 Subject: [PATCH 058/553] Fixed code inconsistencies and adding support for logging to sentryio --- Geekbot.net/Commands/Cat.cs | 38 +++++++++++++------ Geekbot.net/Commands/CheckEm.cs | 23 +++++------ Geekbot.net/Commands/Choose.cs | 21 ++++++++--- Geekbot.net/Commands/Counters.cs | 28 +++++++------- Geekbot.net/Commands/Dog.cs | 38 +++++++++++++------ Geekbot.net/Commands/EightBall.cs | 63 ++++++++++++++++++------------- Geekbot.net/Commands/GuildInfo.cs | 2 +- Geekbot.net/Commands/Help.cs | 23 +---------- Geekbot.net/Commands/Say.cs | 21 +++++++++-- Geekbot.net/Commands/Ship.cs | 60 ++++++++++++++++------------- Geekbot.net/Commands/Stats.cs | 2 +- Geekbot.net/Commands/Youtube.cs | 16 ++++---- Geekbot.net/Geekbot.net.csproj | 1 + Geekbot.net/Handlers.cs | 22 +++++++---- Geekbot.net/Lib/ErrorHandler.cs | 2 +- Geekbot.net/Lib/LevelCalc.cs | 7 ++-- Geekbot.net/Lib/LoggerFactory.cs | 10 ++++- Geekbot.net/Program.cs | 12 +++++- 18 files changed, 228 insertions(+), 161 deletions(-) diff --git a/Geekbot.net/Commands/Cat.cs b/Geekbot.net/Commands/Cat.cs index 4d5f001..8e528d9 100644 --- a/Geekbot.net/Commands/Cat.cs +++ b/Geekbot.net/Commands/Cat.cs @@ -9,28 +9,42 @@ namespace Geekbot.net.Commands { public class Cat : ModuleBase { + private readonly IErrorHandler _errorHandler; + + public Cat(IErrorHandler errorHandler) + { + _errorHandler = errorHandler; + } + [Command("cat", RunMode = RunMode.Async)] [Remarks(CommandCategories.Randomness)] [Summary("Return a random image of a cat.")] public async Task Say() { - using (var client = new HttpClient()) + try { - try + using (var client = new HttpClient()) { - client.BaseAddress = new Uri("http://random.cat"); - var response = await client.GetAsync("/meow.php"); - response.EnsureSuccessStatusCode(); + try + { + client.BaseAddress = new Uri("http://random.cat"); + var response = await client.GetAsync("/meow.php"); + response.EnsureSuccessStatusCode(); - var stringResponse = await response.Content.ReadAsStringAsync(); - var catFile = JsonConvert.DeserializeObject(stringResponse); - await ReplyAsync(catFile.file); - } - catch (HttpRequestException e) - { - await ReplyAsync($"Seems like the dog cought the cat (error occured)\r\n{e.Message}"); + var stringResponse = await response.Content.ReadAsStringAsync(); + var catFile = JsonConvert.DeserializeObject(stringResponse); + await ReplyAsync(catFile.file); + } + catch (HttpRequestException e) + { + await ReplyAsync($"Seems like the dog cought the cat (error occured)\r\n{e.Message}"); + } } } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } } } diff --git a/Geekbot.net/Commands/CheckEm.cs b/Geekbot.net/Commands/CheckEm.cs index be49cd1..1c488bd 100644 --- a/Geekbot.net/Commands/CheckEm.cs +++ b/Geekbot.net/Commands/CheckEm.cs @@ -5,23 +5,20 @@ using System.Threading.Tasks; using Discord.Commands; using Geekbot.net.Lib; using Geekbot.net.Lib.Media; -using Serilog; namespace Geekbot.net.Commands { public class CheckEm : ModuleBase { - private readonly IMediaProvider checkEmImages; - private readonly Random rnd; - private readonly ILogger logger; - private readonly IErrorHandler errorHandler; + private readonly IMediaProvider _checkEmImages; + private readonly Random _rnd; + private readonly IErrorHandler _errorHandler; - public CheckEm(Random RandomClient, IMediaProvider mediaProvider, ILogger logger, IErrorHandler errorHandler) + public CheckEm(Random RandomClient, IMediaProvider mediaProvider, IErrorHandler errorHandler) { - this.rnd = RandomClient; - this.checkEmImages = mediaProvider; - this.logger = logger; - this.errorHandler = errorHandler; + _rnd = RandomClient; + _checkEmImages = mediaProvider; + _errorHandler = errorHandler; } [Command("checkem", RunMode = RunMode.Async)] @@ -31,7 +28,7 @@ namespace Geekbot.net.Commands { try { - var number = rnd.Next(10000000, 99999999); + var number = _rnd.Next(10000000, 99999999); var dubtriqua = ""; var ns = GetIntArray(number); @@ -51,13 +48,13 @@ namespace Geekbot.net.Commands sb.AppendLine($"**{number}**"); if (!string.IsNullOrEmpty(dubtriqua)) sb.AppendLine($":tada: {dubtriqua} :tada:"); - sb.AppendLine(checkEmImages.getCheckem()); + sb.AppendLine(_checkEmImages.getCheckem()); await ReplyAsync(sb.ToString()); } catch (Exception e) { - errorHandler.HandleCommandException(e, Context); + _errorHandler.HandleCommandException(e, Context); } } diff --git a/Geekbot.net/Commands/Choose.cs b/Geekbot.net/Commands/Choose.cs index 9d19c84..a607cdf 100644 --- a/Geekbot.net/Commands/Choose.cs +++ b/Geekbot.net/Commands/Choose.cs @@ -7,11 +7,13 @@ namespace Geekbot.net.Commands { public class Choose : ModuleBase { - private readonly Random rnd; + private readonly Random _rnd; + private readonly IErrorHandler _errorHandler; - public Choose(Random RandomClient) + public Choose(Random RandomClient, IErrorHandler errorHandler) { - rnd = RandomClient; + _rnd = RandomClient; + _errorHandler = errorHandler; } [Command("choose", RunMode = RunMode.Async)] @@ -19,9 +21,16 @@ namespace Geekbot.net.Commands [Summary("Let the bot choose for you, seperate options with a semicolon.")] public async Task Command([Remainder] [Summary("option1;option2")] string choices) { - var choicesArray = choices.Split(';'); - var choice = rnd.Next(choicesArray.Length); - await ReplyAsync($"I choose **{choicesArray[choice]}**"); + try + { + var choicesArray = choices.Split(';'); + var choice = _rnd.Next(choicesArray.Length); + await ReplyAsync($"I choose **{choicesArray[choice]}**"); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Counters.cs b/Geekbot.net/Commands/Counters.cs index f999f1e..54e3c0e 100644 --- a/Geekbot.net/Commands/Counters.cs +++ b/Geekbot.net/Commands/Counters.cs @@ -10,15 +10,13 @@ namespace Geekbot.net.Commands { public class Counters : ModuleBase { - private readonly IDatabase redis; - private readonly ILogger logger; - private readonly IErrorHandler errorHandler; + private readonly IDatabase _redis; + private readonly IErrorHandler _errorHandler; - public Counters(IDatabase redis, ILogger logger, IErrorHandler errorHandler) + public Counters(IDatabase redis, IErrorHandler errorHandler) { - this.redis = redis; - this.logger = logger; - this.errorHandler = errorHandler; + _redis = redis; + _errorHandler = errorHandler; } [Command("good", RunMode = RunMode.Async)] @@ -28,7 +26,7 @@ namespace Geekbot.net.Commands { try { - var lastKarmaFromRedis = redis.HashGet($"{Context.Guild.Id}:KarmaTimeout", Context.User.Id.ToString()); + var lastKarmaFromRedis = _redis.HashGet($"{Context.Guild.Id}:KarmaTimeout", Context.User.Id.ToString()); var lastKarma = ConvertToDateTimeOffset(lastKarmaFromRedis.ToString()); if (user.Id == Context.User.Id) { @@ -41,8 +39,8 @@ namespace Geekbot.net.Commands } else { - var newKarma = redis.HashIncrement($"{Context.Guild.Id}:Karma", user.Id.ToString()); - redis.HashSet($"{Context.Guild.Id}:KarmaTimeout", + var newKarma = _redis.HashIncrement($"{Context.Guild.Id}:Karma", user.Id.ToString()); + _redis.HashSet($"{Context.Guild.Id}:KarmaTimeout", new HashEntry[] {new HashEntry(Context.User.Id.ToString(), DateTimeOffset.Now.ToString("u"))}); var eb = new EmbedBuilder(); @@ -60,7 +58,7 @@ namespace Geekbot.net.Commands } catch (Exception e) { - errorHandler.HandleCommandException(e, Context); + _errorHandler.HandleCommandException(e, Context); } } @@ -71,7 +69,7 @@ namespace Geekbot.net.Commands { try { - var lastKarmaFromRedis = redis.HashGet($"{Context.Guild.Id}:KarmaTimeout", Context.User.Id.ToString()); + var lastKarmaFromRedis = _redis.HashGet($"{Context.Guild.Id}:KarmaTimeout", Context.User.Id.ToString()); var lastKarma = ConvertToDateTimeOffset(lastKarmaFromRedis.ToString()); if (user.Id == Context.User.Id) { @@ -84,8 +82,8 @@ namespace Geekbot.net.Commands } else { - var newKarma = redis.HashDecrement($"{Context.Guild.Id}:Karma", user.Id.ToString()); - redis.HashSet($"{Context.Guild.Id}:KarmaTimeout", + var newKarma = _redis.HashDecrement($"{Context.Guild.Id}:Karma", user.Id.ToString()); + _redis.HashSet($"{Context.Guild.Id}:KarmaTimeout", new HashEntry[] {new HashEntry(Context.User.Id.ToString(), DateTimeOffset.Now.ToString())}); var eb = new EmbedBuilder(); @@ -103,7 +101,7 @@ namespace Geekbot.net.Commands } catch (Exception e) { - errorHandler.HandleCommandException(e, Context); + _errorHandler.HandleCommandException(e, Context); } } diff --git a/Geekbot.net/Commands/Dog.cs b/Geekbot.net/Commands/Dog.cs index 7ce9470..f0c8e52 100644 --- a/Geekbot.net/Commands/Dog.cs +++ b/Geekbot.net/Commands/Dog.cs @@ -9,28 +9,42 @@ namespace Geekbot.net.Commands { public class Dog : ModuleBase { + private readonly IErrorHandler _errorHandler; + + public Dog(IErrorHandler errorHandler) + { + _errorHandler = errorHandler; + } + [Command("dog", RunMode = RunMode.Async)] [Remarks(CommandCategories.Randomness)] [Summary("Return a random image of a dog.")] public async Task Say() { - using (var client = new HttpClient()) + try { - try + using (var client = new HttpClient()) { - client.BaseAddress = new Uri("http://random.dog"); - var response = await client.GetAsync("/woof.json"); - response.EnsureSuccessStatusCode(); + try + { + client.BaseAddress = new Uri("http://random.dog"); + var response = await client.GetAsync("/woof.json"); + response.EnsureSuccessStatusCode(); - var stringResponse = await response.Content.ReadAsStringAsync(); - var dogFile = JsonConvert.DeserializeObject(stringResponse); - await ReplyAsync(dogFile.url); - } - catch (HttpRequestException e) - { - await ReplyAsync($"Seems like the dog got lost (error occured)\r\n{e.Message}"); + var stringResponse = await response.Content.ReadAsStringAsync(); + var dogFile = JsonConvert.DeserializeObject(stringResponse); + await ReplyAsync(dogFile.url); + } + catch (HttpRequestException e) + { + await ReplyAsync($"Seems like the dog got lost (error occured)\r\n{e.Message}"); + } } } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } } } diff --git a/Geekbot.net/Commands/EightBall.cs b/Geekbot.net/Commands/EightBall.cs index 3138c69..4a369a4 100644 --- a/Geekbot.net/Commands/EightBall.cs +++ b/Geekbot.net/Commands/EightBall.cs @@ -8,11 +8,13 @@ namespace Geekbot.net.Commands { public class EightBall : ModuleBase { - private readonly Random rnd; + private readonly Random _rnd; + private readonly IErrorHandler _errorHandler; - public EightBall(Random RandomClient) + public EightBall(Random RandomClient, IErrorHandler errorHandler) { - rnd = RandomClient; + _rnd = RandomClient; + _errorHandler = errorHandler; } [Command("8ball", RunMode = RunMode.Async)] @@ -20,32 +22,39 @@ namespace Geekbot.net.Commands [Summary("Ask 8Ball a Question.")] public async Task Ball([Remainder] [Summary("Question")] string echo) { - var replies = new List + try { - "It is certain", - "It is decidedly so", - "Without a doubt", - "Yes, definitely", - "You may rely on it", - "As I see it, yes", - "Most likely", - "Outlook good", - "Yes", - "Signs point to yes", - "Reply hazy try again", - "Ask again later", - "Better not tell you now", - "Cannot predict now", - "Concentrate and ask again", - "Don't count on it", - "My reply is no", - "My sources say no", - "Outlook not so good", - "Very doubtful" - }; + var replies = new List + { + "It is certain", + "It is decidedly so", + "Without a doubt", + "Yes, definitely", + "You may rely on it", + "As I see it, yes", + "Most likely", + "Outlook good", + "Yes", + "Signs point to yes", + "Reply hazy try again", + "Ask again later", + "Better not tell you now", + "Cannot predict now", + "Concentrate and ask again", + "Don't count on it", + "My reply is no", + "My sources say no", + "Outlook not so good", + "Very doubtful" + }; - var answer = rnd.Next(replies.Count); - await ReplyAsync(replies[answer]); + var answer = _rnd.Next(replies.Count); + await ReplyAsync(replies[answer]); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/GuildInfo.cs b/Geekbot.net/Commands/GuildInfo.cs index 8eae02e..f195472 100644 --- a/Geekbot.net/Commands/GuildInfo.cs +++ b/Geekbot.net/Commands/GuildInfo.cs @@ -38,7 +38,7 @@ namespace Geekbot.net.Commands var age = Math.Floor((DateTime.Now - created).TotalDays); var messages = _redis.HashGet($"{Context.Guild.Id}:Messages", 0.ToString()); - var level = _levelCalc.GetLevelAtExperience((int) messages); + var level = _levelCalc.GetLevel((int) messages); eb.AddField("Server Age", $"{created.Day}/{created.Month}/{created.Year} ({age} days)"); eb.AddInlineField("Level", level) diff --git a/Geekbot.net/Commands/Help.cs b/Geekbot.net/Commands/Help.cs index 9ba8792..2ffa323 100644 --- a/Geekbot.net/Commands/Help.cs +++ b/Geekbot.net/Commands/Help.cs @@ -26,22 +26,7 @@ namespace Geekbot.net.Commands try { var sb = new StringBuilder(); -// sb.AppendLine("```"); -// sb.AppendLine("**Geekbot Command list**"); -// sb.AppendLine(""); -// sb.AppendLine(tp("Name", 15) + tp("Parameters", 19) + "Description"); -// foreach (var cmd in _commands.Commands) -// { -// var param = string.Join(", !", cmd.Aliases); -// if (!param.Contains("admin")) -// if (cmd.Parameters.Any()) -// sb.AppendLine(tp(param, 15) + -// tp(string.Join(" ", cmd.Parameters.Select(e => e.Summary)), 19) + -// cmd.Summary); -// else -// sb.AppendLine(tp(param, 34) + cmd.Summary); -// } -// sb.AppendLine("```"); + sb.AppendLine("For a list of all commands, please visit the following page"); sb.AppendLine("https://geekbot.pizzaandcoffee.rocks/commands"); var dm = await Context.User.GetOrCreateDMChannelAsync(); @@ -52,11 +37,5 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } - - // Table Padding, short function name because of many usages - private string tp(string text, int shouldHave) - { - return text.PadRight(shouldHave); - } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Say.cs b/Geekbot.net/Commands/Say.cs index 4f057db..7ddcbbc 100644 --- a/Geekbot.net/Commands/Say.cs +++ b/Geekbot.net/Commands/Say.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; @@ -7,14 +8,28 @@ namespace Geekbot.net.Commands { public class Say : ModuleBase { + private readonly IErrorHandler _errorHandler; + + public Say(IErrorHandler errorHandler) + { + _errorHandler = errorHandler; + } + [RequireUserPermission(GuildPermission.Administrator)] [Command("say", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Say Something.")] public async Task Echo([Remainder] [Summary("What?")] string echo) { - await Context.Message.DeleteAsync(); - await ReplyAsync(echo); + try + { + await Context.Message.DeleteAsync(); + await ReplyAsync(echo); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Ship.cs b/Geekbot.net/Commands/Ship.cs index ea1e942..0b87f90 100644 --- a/Geekbot.net/Commands/Ship.cs +++ b/Geekbot.net/Commands/Ship.cs @@ -9,13 +9,15 @@ namespace Geekbot.net.Commands { public class Ship : ModuleBase { - private readonly IDatabase redis; - private readonly Random rnd; + private readonly IDatabase _redis; + private readonly Random _rnd; + private readonly IErrorHandler _errorHandler; - public Ship(IDatabase redis, Random RandomClient) + public Ship(IDatabase redis, Random randomClient, IErrorHandler errorHandler) { - this.redis = redis; - rnd = RandomClient; + _redis = redis; + _rnd = randomClient; + _errorHandler = errorHandler; } [Command("Ship", RunMode = RunMode.Async)] @@ -23,29 +25,35 @@ namespace Geekbot.net.Commands [Summary("Ask the Shipping meter")] public async Task Command([Summary("@User1")] IUser user1, [Summary("@User2")] IUser user2) { - // Create a String - var dbstring = ""; - if (user1.Id > user2.Id) - dbstring = $"{user1.Id}-{user2.Id}"; - else - dbstring = $"{user2.Id}-{user1.Id}"; - - var dbval = redis.HashGet($"{Context.Guild.Id}:Ships", dbstring); - var shippingRate = 0; - if (dbval.IsNullOrEmpty) + try { - shippingRate = rnd.Next(1, 100); - redis.HashSet($"{Context.Guild.Id}:Ships", dbstring, shippingRate); - } - else - { - shippingRate = int.Parse(dbval.ToString()); - } + var dbstring = ""; + if (user1.Id > user2.Id) + dbstring = $"{user1.Id}-{user2.Id}"; + else + dbstring = $"{user2.Id}-{user1.Id}"; - var reply = ":heartpulse: **Matchmaking** :heartpulse:\r\n"; - reply = reply + $":two_hearts: {user1.Mention} :heart: {user2.Mention} :two_hearts:\r\n"; - reply = reply + $"0% [{BlockCounter(shippingRate)}] 100% - {DeterminateSuccess(shippingRate)}"; - await ReplyAsync(reply); + var dbval = _redis.HashGet($"{Context.Guild.Id}:Ships", dbstring); + var shippingRate = 0; + if (dbval.IsNullOrEmpty) + { + shippingRate = _rnd.Next(1, 100); + _redis.HashSet($"{Context.Guild.Id}:Ships", dbstring, shippingRate); + } + else + { + shippingRate = int.Parse(dbval.ToString()); + } + + var reply = ":heartpulse: **Matchmaking** :heartpulse:\r\n"; + reply = reply + $":two_hearts: {user1.Mention} :heart: {user2.Mention} :two_hearts:\r\n"; + reply = reply + $"0% [{BlockCounter(shippingRate)}] 100% - {DeterminateSuccess(shippingRate)}"; + await ReplyAsync(reply); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } } private string DeterminateSuccess(int rate) diff --git a/Geekbot.net/Commands/Stats.cs b/Geekbot.net/Commands/Stats.cs index 37c3ea9..c800ed2 100644 --- a/Geekbot.net/Commands/Stats.cs +++ b/Geekbot.net/Commands/Stats.cs @@ -36,7 +36,7 @@ namespace Geekbot.net.Commands var messages = (int) _redis.HashGet($"{Context.Guild.Id}:Messages", userInfo.Id.ToString()); var guildMessages = (int) _redis.HashGet($"{Context.Guild.Id}:Messages", 0.ToString()); - var level = _levelCalc.GetLevelAtExperience(messages); + var level = _levelCalc.GetLevel(messages); var percent = Math.Round((double) (100 * messages) / guildMessages, 2); diff --git a/Geekbot.net/Commands/Youtube.cs b/Geekbot.net/Commands/Youtube.cs index ee743b3..043cd3e 100644 --- a/Geekbot.net/Commands/Youtube.cs +++ b/Geekbot.net/Commands/Youtube.cs @@ -10,11 +10,13 @@ namespace Geekbot.net.Commands { public class Youtube : ModuleBase { - private readonly IDatabase redis; + private readonly IDatabase _redis; + private readonly IErrorHandler _errorHandler; - public Youtube(IDatabase redis) + public Youtube(IDatabase redis, IErrorHandler errorHandler) { - this.redis = redis; + _redis = redis; + _errorHandler = errorHandler; } [Command("yt", RunMode = RunMode.Async)] @@ -22,7 +24,7 @@ namespace Geekbot.net.Commands [Summary("Search for something on youtube.")] public async Task Yt([Remainder] [Summary("Title")] string searchQuery) { - var key = redis.StringGet("youtubeKey"); + var key = _redis.StringGet("youtubeKey"); if (key.IsNullOrEmpty) { await ReplyAsync("No youtube key set, please tell my senpai to set one"); @@ -50,11 +52,7 @@ namespace Geekbot.net.Commands } catch (Exception e) { - await ReplyAsync("Something went wrong... informing my senpai..."); - var botOwner = Context.Guild.GetUserAsync(ulong.Parse(redis.StringGet("botOwner"))).Result; - var dm = await botOwner.GetOrCreateDMChannelAsync(); - await dm.SendMessageAsync( - $"Something went wrong while getting a video from youtube:\r\n```\r\n{e.Message}\r\n```"); + _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index f2a8f2d..09f59f0 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -27,6 +27,7 @@ + 1.2.6 diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index a98731c..a848568 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -78,17 +78,25 @@ namespace Geekbot.net public Task UserJoined(SocketGuildUser user) { - if (!user.IsBot) + try { - var message = _redis.HashGet($"{user.Guild.Id}:Settings", "WelcomeMsg"); - if (!message.IsNullOrEmpty) + if (!user.IsBot) { - message = message.ToString().Replace("$user", user.Mention); - user.Guild.DefaultChannel.SendMessageAsync(message); + var message = _redis.HashGet($"{user.Guild.Id}:Settings", "WelcomeMsg"); + if (!message.IsNullOrEmpty) + { + message = message.ToString().Replace("$user", user.Mention); + user.Guild.DefaultChannel.SendMessageAsync(message); + } } + _userRepository.Update(user); + _logger.Information( + $"[Geekbot] {user.Id} ({user.Username}) joined {user.Guild.Id} ({user.Guild.Name})"); + } + catch (Exception e) + { + _logger.Error(e, "[Geekbot] Failed to send welcome message"); } - _userRepository.Update(user); - _logger.Information($"[Geekbot] {user.Id} ({user.Username}) joined {user.Guild.Id} ({user.Guild.Name})"); return Task.CompletedTask; } diff --git a/Geekbot.net/Lib/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandler.cs index 65b61ef..cbd8f29 100644 --- a/Geekbot.net/Lib/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandler.cs @@ -16,7 +16,7 @@ namespace Geekbot.net.Lib public void HandleCommandException(Exception e, ICommandContext Context, string errorMessage = "Something went wrong :confused:") { var errorMsg = - $"Error Occured while executing \"{Context.Message.Content}\", executed by \"{Context.User.Username}\""; + $"Error Occured while executing \"{Context.Message.Content}\", executed by \"{Context.User.Username}\" in \"{Context.Guild.Name}/{Context.Channel.Name}\""; _logger.Error(e, errorMsg); if (!string.IsNullOrEmpty(errorMessage)) { diff --git a/Geekbot.net/Lib/LevelCalc.cs b/Geekbot.net/Lib/LevelCalc.cs index 6ab5162..6951f5e 100644 --- a/Geekbot.net/Lib/LevelCalc.cs +++ b/Geekbot.net/Lib/LevelCalc.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; namespace Geekbot.net.Lib { @@ -19,12 +20,12 @@ namespace Geekbot.net.Lib _levels = levels.ToArray(); } - public int GetLevelAtExperience(int experience) + public int GetLevel(int messages) { var returnVal = 1; foreach (var level in _levels) { - if (level > experience) break; + if (level > messages) break; returnVal++; } return returnVal; @@ -33,6 +34,6 @@ namespace Geekbot.net.Lib public interface ILevelCalc { - int GetLevelAtExperience(int experience); + int GetLevel(int experience); } } \ No newline at end of file diff --git a/Geekbot.net/Lib/LoggerFactory.cs b/Geekbot.net/Lib/LoggerFactory.cs index b52ad5a..8cfabec 100644 --- a/Geekbot.net/Lib/LoggerFactory.cs +++ b/Geekbot.net/Lib/LoggerFactory.cs @@ -1,4 +1,5 @@ -using Serilog; +using System; +using Serilog; using System.Linq; namespace Geekbot.net.Lib @@ -10,6 +11,13 @@ namespace Geekbot.net.Lib var loggerCreation = new LoggerConfiguration() .WriteTo.LiterateConsole() .WriteTo.RollingFile("Logs/geekbot-{Date}.txt", shared: true); + var sentryDsn = Environment.GetEnvironmentVariable("SENTRY"); + if (!string.IsNullOrEmpty(sentryDsn)) + { + loggerCreation.WriteTo.SentryIO(sentryDsn) + .Enrich.FromLogContext(); + Console.WriteLine($"Logging to Sentry Enabled: {sentryDsn}"); + } if (args.Contains("--verbose")) { loggerCreation.MinimumLevel.Verbose(); diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 2488827..da50610 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; @@ -32,7 +33,6 @@ namespace Geekbot.net private static void Main(string[] args) { - var logger = LoggerFactory.createLogger(args); var logo = new StringBuilder(); logo.AppendLine(@" ____ _____ _____ _ ______ ___ _____"); logo.AppendLine(@" / ___| ____| ____| |/ / __ ) / _ \\_ _|"); @@ -41,8 +41,16 @@ namespace Geekbot.net logo.AppendLine(@" \____|_____|_____|_|\_\____/ \___/ |_|"); logo.AppendLine("========================================="); Console.WriteLine(logo.ToString()); + var logger = LoggerFactory.createLogger(args); logger.Information("[Geekbot] Starting..."); - new Program().MainAsync(args, logger).GetAwaiter().GetResult(); + try + { + new Program().MainAsync(args, logger).GetAwaiter().GetResult(); + } + catch (Exception e) + { + logger.Fatal(e, "[Geekbot] RIP"); + } } private async Task MainAsync(string[] args, ILogger logger) From 14dfbca3898313d5850201175b725d0ddd9e0ec5 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Thu, 26 Oct 2017 23:31:51 +0200 Subject: [PATCH 059/553] Adding username history to user repo --- Geekbot.net/Commands/Role.cs | 2 +- Geekbot.net/Lib/UserRepository.cs | 114 +++++++++++++++++++----------- 2 files changed, 75 insertions(+), 41 deletions(-) diff --git a/Geekbot.net/Commands/Role.cs b/Geekbot.net/Commands/Role.cs index ae93a57..9de24fb 100644 --- a/Geekbot.net/Commands/Role.cs +++ b/Geekbot.net/Commands/Role.cs @@ -107,7 +107,7 @@ namespace Geekbot.net.Commands await ReplyAsync("Woah, i don't think you want to add that role to self service as it contains some dangerous permissions"); return; } - _redis.HashSet($"{Context.Guild.Id}:RoleWhitelist", new HashEntry[] { new HashEntry(roleName, role.Id.ToString()) }); + _redis.HashSet($"{Context.Guild.Id}:RoleWhitelist", new HashEntry[] { new HashEntry(roleName.ToLower(), role.Id.ToString()) }); await ReplyAsync($"Added {role.Name} to the whitelist"); } catch (Exception e) diff --git a/Geekbot.net/Lib/UserRepository.cs b/Geekbot.net/Lib/UserRepository.cs index 4f5de16..2982866 100644 --- a/Geekbot.net/Lib/UserRepository.cs +++ b/Geekbot.net/Lib/UserRepository.cs @@ -1,9 +1,12 @@ using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; using System.Threading.Tasks; -using AngleSharp.Dom.Css; using Discord.WebSocket; using Serilog; using StackExchange.Redis; +using Utf8Json; namespace Geekbot.net.Lib { @@ -21,60 +24,90 @@ namespace Geekbot.net.Lib { try { - _redis.HashSetAsync($"Users:{user.Id.ToString()}", new HashEntry[] + var savedUser = Get(user.Id); + savedUser.Id = user.Id; + savedUser.Username = user.Username; + savedUser.Discriminator = user.Discriminator; + savedUser.AvatarUrl = user.GetAvatarUrl() ?? "0"; + savedUser.IsBot = user.IsBot; + savedUser.Joined = user.CreatedAt; + if(savedUser.UsedNames == null) savedUser.UsedNames = new List(); + if (!savedUser.UsedNames.Contains(user.Username)) { - new HashEntry("Id", user.Id.ToString()), - new HashEntry("Username", user.Username), - new HashEntry("Discriminator", user.Discriminator), - new HashEntry("AvatarUrl", user.GetAvatarUrl() ?? "0"), - new HashEntry("IsBot", user.IsBot), - new HashEntry("Joined", user.CreatedAt.ToString()), - }); - _logger.Information($"[UserRepository] Updated User {user.Id}"); + savedUser.UsedNames.Add(user.Username); + } + Store(savedUser); + + _logger.Information($"[UserRepository] Updated User {user.Username}#{user.Discriminator} ({user.Id})"); return Task.FromResult(true); } catch (Exception e) { - _logger.Warning(e, $"[UserRepository] Failed to update {user.Id}"); + _logger.Warning(e, $"[UserRepository] Failed to update {user.Username}#{user.Discriminator} ({user.Id})"); return Task.FromResult(false); } } + private void Store(UserRepositoryUser user) + { + _redis.HashSetAsync($"Users:{user.Id.ToString()}", new HashEntry[] + { + new HashEntry("Id", user.Id.ToString()), + new HashEntry("Username", user.Username), + new HashEntry("Discriminator", user.Discriminator), + new HashEntry("AvatarUrl", user.AvatarUrl), + new HashEntry("IsBot", user.IsBot), + new HashEntry("Joined", user.Joined.ToString()), + new HashEntry("UsedNames", JsonSerializer.Serialize(user.UsedNames)), + }); + } + public UserRepositoryUser Get(ulong userId) { - var user = _redis.HashGetAll($"Users:{userId.ToString()}"); - for (int i = 1; i < 11; i++) + try { - if (user.Length != 0) break; - user = _redis.HashGetAll($"Users:{(userId + (ulong)i).ToString()}"); - - } - var dto = new UserRepositoryUser(); - foreach (var a in user.ToDictionary()) - { - switch (a.Key) + var user = _redis.HashGetAll($"Users:{userId.ToString()}"); + for (int i = 1; i < 11; i++) { - case "Id": - dto.Id = ulong.Parse(a.Value); - break; - case "Username": - dto.Username = a.Value.ToString(); - break; - case "Discriminator": - dto.Discriminator = a.Value.ToString(); - break; - case "AvatarUrl": - dto.AvatarUrl = (a.Value != "0") ? a.Value.ToString() : null; - break; - case "IsBot": - dto.IsBot = a.Value == 1; - break; - case "Joined": - dto.Joined = DateTimeOffset.Parse(a.Value); - break; + if (user.Length != 0) break; + user = _redis.HashGetAll($"Users:{(userId + (ulong) i).ToString()}"); + } + var dto = new UserRepositoryUser(); + foreach (var a in user.ToDictionary()) + { + switch (a.Key) + { + case "Id": + dto.Id = ulong.Parse(a.Value); + break; + case "Username": + dto.Username = a.Value.ToString(); + break; + case "Discriminator": + dto.Discriminator = a.Value.ToString(); + break; + case "AvatarUrl": + dto.AvatarUrl = (a.Value != "0") ? a.Value.ToString() : null; + break; + case "IsBot": + dto.IsBot = a.Value == 1; + break; + case "Joined": + dto.Joined = DateTimeOffset.Parse(a.Value.ToString()); + break; + case "UsedNames": + dto.UsedNames = JsonSerializer.Deserialize>(a.Value.ToString()) ?? new List(); + break; + } + } + return dto; + } + catch (Exception e) + { + _logger.Warning(e, $"[UserRepository] Failed to get {userId} from repository"); + return new UserRepositoryUser(); } - return dto; } public string getUserSetting(ulong userId, string setting) @@ -100,6 +133,7 @@ namespace Geekbot.net.Lib public string AvatarUrl { get; set; } public bool IsBot { get; set; } public DateTimeOffset Joined { get; set; } + public List UsedNames { get; set; } } public interface IUserRepository From 7167ea3ebc3e340cdc91c04cdf68ffbcbeab485f Mon Sep 17 00:00:00 2001 From: Runebaas Date: Fri, 27 Oct 2017 00:18:58 +0200 Subject: [PATCH 060/553] Dividing admincmd into owner, admin and mod commands, add username history command --- .../Commands/{AdminCmd.cs => Admin.cs} | 92 +-------------- Geekbot.net/Commands/Mod.cs | 47 ++++++++ Geekbot.net/Commands/Owner.cs | 110 ++++++++++++++++++ 3 files changed, 160 insertions(+), 89 deletions(-) rename Geekbot.net/Commands/{AdminCmd.cs => Admin.cs} (53%) create mode 100644 Geekbot.net/Commands/Mod.cs create mode 100644 Geekbot.net/Commands/Owner.cs diff --git a/Geekbot.net/Commands/AdminCmd.cs b/Geekbot.net/Commands/Admin.cs similarity index 53% rename from Geekbot.net/Commands/AdminCmd.cs rename to Geekbot.net/Commands/Admin.cs index 213f9cc..376101a 100644 --- a/Geekbot.net/Commands/AdminCmd.cs +++ b/Geekbot.net/Commands/Admin.cs @@ -11,24 +11,20 @@ using StackExchange.Redis; namespace Geekbot.net.Commands { [Group("admin")] - public class AdminCmd : ModuleBase + [RequireUserPermission(GuildPermission.Administrator)] + public class Admin : ModuleBase { private readonly IDatabase _redis; private readonly DiscordSocketClient _client; - private readonly ILogger _logger; - private readonly IUserRepository _userRepository; private readonly IErrorHandler _errorHandler; - public AdminCmd(IDatabase redis, DiscordSocketClient client, ILogger logger, IUserRepository userRepositry, IErrorHandler errorHandler) + public Admin(IDatabase redis, DiscordSocketClient client, IErrorHandler errorHandler) { _redis = redis; _client = client; - _logger = logger; - _userRepository = userRepositry; _errorHandler = errorHandler; } - [RequireUserPermission(GuildPermission.Administrator)] [Command("welcome", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Set a Welcome Message (use '$user' to mention the new joined user).")] @@ -40,86 +36,6 @@ namespace Geekbot.net.Commands formatedMessage); } - [Command("youtubekey", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Admin)] - [Summary("Set the youtube api key")] - public async Task SetYoutubeKey([Summary("API Key")] string key) - { - var botOwner = Context.Guild.GetUserAsync(ulong.Parse(_redis.StringGet("botOwner"))).Result; - if (!Context.User.Id.ToString().Equals(botOwner.Id.ToString())) - { - await ReplyAsync($"Sorry, only the botowner can do this ({botOwner.Username}#{botOwner.Discriminator})"); - return; - } - - _redis.StringSet("youtubeKey", key); - await ReplyAsync("Apikey has been set"); - } - - [Command("game", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Admin)] - [Summary("Set the game that the bot is playing")] - public async Task SetGame([Remainder] [Summary("Game")] string key) - { - var botOwner = Context.Guild.GetUserAsync(ulong.Parse(_redis.StringGet("botOwner"))).Result; - if (!Context.User.Id.ToString().Equals(botOwner.Id.ToString())) - { - await ReplyAsync($"Sorry, only the botowner can do this ({botOwner.Username}#{botOwner.Discriminator})"); - return; - } - - _redis.StringSet("Game", key); - await _client.SetGameAsync(key); - _logger.Information($"[Geekbot] Changed game to {key}"); - await ReplyAsync($"Now Playing {key}"); - } - - [Command("popuserrepo", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Admin)] - [Summary("Populate user cache")] - public async Task popUserRepoCommand() - { - try - { - var botOwner = Context.Guild.GetUserAsync(ulong.Parse(_redis.StringGet("botOwner"))).Result; - if (!Context.User.Id.ToString().Equals(botOwner.Id.ToString())) - { - await ReplyAsync( - $"Sorry, only the botowner can do this ({botOwner.Username}#{botOwner.Discriminator})"); - return; - } - } - catch (Exception) - { - await ReplyAsync( - $"Sorry, only the botowner can do this"); - return; - } - var success = 0; - var failed = 0; - try - { - _logger.Warning("[UserRepository] Populating User Repositry"); - await ReplyAsync("Starting Population of User Repository"); - foreach (var guild in _client.Guilds) - { - _logger.Information($"[UserRepository] Populating users from {guild.Name}"); - foreach (var user in guild.Users) - { - var succeded = await _userRepository.Update(user); - var inc = succeded ? success++ : failed++; - } - } - _logger.Warning("[UserRepository] Finished Updating User Repositry"); - await ReplyAsync($"Successfully Populated User Repository with {success} Users in {_client.Guilds.Count} Guilds (Failed: {failed})"); - } - catch (Exception e) - { - _errorHandler.HandleCommandException(e, Context, "Couldn't complete User Repository, see console for more info"); - } - } - - [RequireUserPermission(GuildPermission.Administrator)] [Command("modchannel", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Set a channel for moderation purposes")] @@ -140,7 +56,6 @@ namespace Geekbot.net.Commands } } - [RequireUserPermission(GuildPermission.Administrator)] [Command("showleave", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Notify modchannel when someone leaves")] @@ -167,7 +82,6 @@ namespace Geekbot.net.Commands } } - [RequireUserPermission(GuildPermission.Administrator)] [Command("showdel", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Notify modchannel when someone deletes a message")] diff --git a/Geekbot.net/Commands/Mod.cs b/Geekbot.net/Commands/Mod.cs new file mode 100644 index 0000000..62eb494 --- /dev/null +++ b/Geekbot.net/Commands/Mod.cs @@ -0,0 +1,47 @@ +using System; +using System.Text; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Geekbot.net.Lib; + +namespace Geekbot.net.Commands +{ + [Group("mod")] + [RequireUserPermission(GuildPermission.KickMembers)] + [RequireUserPermission(GuildPermission.ManageMessages)] + [RequireUserPermission(GuildPermission.ManageRoles)] + public class Mod : ModuleBase + { + private readonly IUserRepository _userRepository; + private readonly IErrorHandler _errorHandler; + + public Mod(IUserRepository userRepositry, IErrorHandler errorHandler) + { + _userRepository = userRepositry; + _errorHandler = errorHandler; + } + + [Command("namehistory", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Admin)] + [Summary("See past usernames of an user")] + public async Task usernameHistory([Summary("@user")] IUser user) + { + try + { + var userRepo = _userRepository.Get(user.Id); + var sb = new StringBuilder(); + sb.AppendLine($":bust_in_silhouette: {user.Username} has been known as:"); + foreach (var name in userRepo.UsedNames) + { + sb.AppendLine($"- `{name}`"); + } + await ReplyAsync(sb.ToString()); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context, "Modchannel doesn't seem to exist, please set one with `!admin modchannel [channelId]`"); + } + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Owner.cs b/Geekbot.net/Commands/Owner.cs new file mode 100644 index 0000000..c05700c --- /dev/null +++ b/Geekbot.net/Commands/Owner.cs @@ -0,0 +1,110 @@ +using System; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Discord.WebSocket; +using Geekbot.net.Lib; +using Serilog; +using StackExchange.Redis; + +namespace Geekbot.net.Commands +{ + [Group("owner")] + [RequireUserPermission(GuildPermission.Administrator)] + public class Owner : ModuleBase + { + private readonly IDatabase _redis; + private readonly DiscordSocketClient _client; + private readonly ILogger _logger; + private readonly IUserRepository _userRepository; + private readonly IErrorHandler _errorHandler; + + public Owner(IDatabase redis, DiscordSocketClient client, ILogger logger, IUserRepository userRepositry, IErrorHandler errorHandler) + { + _redis = redis; + _client = client; + _logger = logger; + _userRepository = userRepositry; + _errorHandler = errorHandler; + } + + [Command("youtubekey", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Admin)] + [Summary("Set the youtube api key")] + public async Task SetYoutubeKey([Summary("API Key")] string key) + { + var botOwner = Context.Guild.GetUserAsync(ulong.Parse(_redis.StringGet("botOwner"))).Result; + if (!Context.User.Id.ToString().Equals(botOwner.Id.ToString())) + { + await ReplyAsync($"Sorry, only the botowner can do this ({botOwner.Username}#{botOwner.Discriminator})"); + return; + } + + _redis.StringSet("youtubeKey", key); + await ReplyAsync("Apikey has been set"); + } + + [Command("game", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Admin)] + [Summary("Set the game that the bot is playing")] + public async Task SetGame([Remainder] [Summary("Game")] string key) + { + var botOwner = Context.Guild.GetUserAsync(ulong.Parse(_redis.StringGet("botOwner"))).Result; + if (!Context.User.Id.ToString().Equals(botOwner.Id.ToString())) + { + await ReplyAsync($"Sorry, only the botowner can do this ({botOwner.Username}#{botOwner.Discriminator})"); + return; + } + + _redis.StringSet("Game", key); + await _client.SetGameAsync(key); + _logger.Information($"[Geekbot] Changed game to {key}"); + await ReplyAsync($"Now Playing {key}"); + } + + [Command("popuserrepo", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Admin)] + [Summary("Populate user cache")] + public async Task popUserRepoCommand() + { + try + { + var botOwner = Context.Guild.GetUserAsync(ulong.Parse(_redis.StringGet("botOwner"))).Result; + if (!Context.User.Id.ToString().Equals(botOwner.Id.ToString())) + { + await ReplyAsync( + $"Sorry, only the botowner can do this ({botOwner.Username}#{botOwner.Discriminator})"); + return; + } + } + catch (Exception) + { + await ReplyAsync( + $"Sorry, only the botowner can do this"); + return; + } + var success = 0; + var failed = 0; + try + { + _logger.Warning("[UserRepository] Populating User Repositry"); + await ReplyAsync("Starting Population of User Repository"); + foreach (var guild in _client.Guilds) + { + _logger.Information($"[UserRepository] Populating users from {guild.Name}"); + foreach (var user in guild.Users) + { + var succeded = await _userRepository.Update(user); + var inc = succeded ? success++ : failed++; + } + } + _logger.Warning("[UserRepository] Finished Updating User Repositry"); + await ReplyAsync($"Successfully Populated User Repository with {success} Users in {_client.Guilds.Count} Guilds (Failed: {failed})"); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context, "Couldn't complete User Repository, see console for more info"); + } + } + } +} \ No newline at end of file From 001b937415a2f94c2597c4fac48cd7828f5293f1 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Mon, 30 Oct 2017 18:35:08 +0100 Subject: [PATCH 061/553] Add kick command --- Geekbot.net/Commands/Mod.cs | 48 ++++++++++++++++++++++++++++++++-- Geekbot.net/Commands/Role.cs | 3 ++- Geekbot.net/Geekbot.net.csproj | 4 +-- 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/Geekbot.net/Commands/Mod.cs b/Geekbot.net/Commands/Mod.cs index 62eb494..6dfba53 100644 --- a/Geekbot.net/Commands/Mod.cs +++ b/Geekbot.net/Commands/Mod.cs @@ -3,7 +3,9 @@ using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Discord.WebSocket; using Geekbot.net.Lib; +using StackExchange.Redis; namespace Geekbot.net.Commands { @@ -15,11 +17,15 @@ namespace Geekbot.net.Commands { private readonly IUserRepository _userRepository; private readonly IErrorHandler _errorHandler; + private readonly IDatabase _redis; + private readonly DiscordSocketClient _client; - public Mod(IUserRepository userRepositry, IErrorHandler errorHandler) + public Mod(IUserRepository userRepositry, IErrorHandler errorHandler, IDatabase redis, DiscordSocketClient client) { _userRepository = userRepositry; _errorHandler = errorHandler; + _redis = redis; + _client = client; } [Command("namehistory", RunMode = RunMode.Async)] @@ -40,7 +46,45 @@ namespace Geekbot.net.Commands } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context, "Modchannel doesn't seem to exist, please set one with `!admin modchannel [channelId]`"); + _errorHandler.HandleCommandException(e, Context, $"I don't have enough permissions to give {user.Username} that role"); + } + } + + [Command("kick", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Admin)] + [Summary("Ban a user")] + public async Task kick([Summary("@user")] IUser userNormal, [Summary("reason"), Remainder] string reason) + { + try + { + var user = (IGuildUser)userNormal; + if (string.IsNullOrEmpty(reason)) + { + reason = "No reason provided"; + } + + await user.KickAsync(); + await user.GetOrCreateDMChannelAsync().Result.SendMessageAsync( + $"You have been kicked from {Context.Guild.Name} for the following reason: \"{reason}\""); + try + { + var modChannelId = ulong.Parse(_redis.HashGet($"{Context.Guild.Id}:Settings", "ModChannel")); + var modChannel = (ISocketMessageChannel) _client.GetChannel(modChannelId); + var eb = new EmbedBuilder(); + eb.Title = "Kicked"; + eb.AddInlineField("User", user.Username); + eb.AddInlineField("By Mod", Context.User.Username); + eb.AddField("Reason", reason); + await modChannel.SendMessageAsync("", false, eb.Build()); + } + catch + { + await ReplyAsync($"{user.Username} was kicked for the following reason: \"{reason}\""); + } + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context, "I don't have enough permissions to kick someone"); } } } diff --git a/Geekbot.net/Commands/Role.cs b/Geekbot.net/Commands/Role.cs index 9de24fb..579dbc6 100644 --- a/Geekbot.net/Commands/Role.cs +++ b/Geekbot.net/Commands/Role.cs @@ -53,10 +53,11 @@ namespace Geekbot.net.Commands [Command(RunMode = RunMode.Async)] [Remarks(CommandCategories.Helpers)] [Summary("Get a role by mentioning it.")] - public async Task giveRole([Summary("roleNickname")] string roleName) + public async Task giveRole([Summary("roleNickname")] string roleNameRaw) { try { + var roleName = roleNameRaw.ToLower(); if (_redis.HashExists($"{Context.Guild.Id}:RoleWhitelist", roleName)) { var guildUser = (IGuildUser) Context.User; diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 09f59f0..d438225 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -21,7 +21,7 @@ - + @@ -39,6 +39,6 @@ 4.3.0 - +
\ No newline at end of file From e96d469c5a685548859bce2a7ae1be55bf07e0ae Mon Sep 17 00:00:00 2001 From: Runebaas Date: Mon, 30 Oct 2017 18:51:57 +0100 Subject: [PATCH 062/553] Add avocado reaction to all messages by user 148542729658302464 --- Geekbot.net/Handlers.cs | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index a848568..c688fb5 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -35,26 +35,39 @@ namespace Geekbot.net public Task RunCommand(SocketMessage messageParam) { - var message = messageParam as SocketUserMessage; - if (message == null) return Task.CompletedTask; - if (message.Author.IsBot) return Task.CompletedTask; - var argPos = 0; - var lowCaseMsg = message.ToString().ToLower(); - if (lowCaseMsg.Equals("ping") || lowCaseMsg.StartsWith("ping ")) + try { - message.Channel.SendMessageAsync("pong"); + var message = messageParam as SocketUserMessage; + if (message == null) return Task.CompletedTask; + if (message.Author.IsBot) return Task.CompletedTask; + var argPos = 0; + var lowCaseMsg = message.ToString().ToLower(); + if (lowCaseMsg.Equals("ping") || lowCaseMsg.StartsWith("ping ")) + { + message.Channel.SendMessageAsync("pong"); + return Task.CompletedTask; + } + if (lowCaseMsg.StartsWith("hui")) + { + message.Channel.SendMessageAsync("hui!!!"); + return Task.CompletedTask; + } + if (message.Author.Id == 148542729658302464) + { + var avocado = new Emoji("🥑"); + var avocadoAdder = message.AddReactionAsync(avocado); + } + if (!(message.HasCharPrefix('!', ref argPos) || + message.HasMentionPrefix(_client.CurrentUser, ref argPos))) return Task.CompletedTask; + var context = new CommandContext(_client, message); + var commandExec = _commands.ExecuteAsync(context, argPos, _servicesProvider); return Task.CompletedTask; } - if (lowCaseMsg.StartsWith("hui")) + catch (Exception e) { - message.Channel.SendMessageAsync("hui!!!"); + _logger.Error(e, "[Geekbot] Failed to run commands"); return Task.CompletedTask; } - if (!(message.HasCharPrefix('!', ref argPos) || - message.HasMentionPrefix(_client.CurrentUser, ref argPos))) return Task.CompletedTask; - var context = new CommandContext(_client, message); - var commandExec = _commands.ExecuteAsync(context, argPos, _servicesProvider); - return Task.CompletedTask; } public Task UpdateStats(SocketMessage messsageParam) From 3d93fe1a7a9df340349404f07de9ca4825f79e48 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Mon, 30 Oct 2017 19:31:56 +0100 Subject: [PATCH 063/553] making geekbot avocado free --- Geekbot.net/Handlers.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index c688fb5..ba86e37 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -52,11 +52,6 @@ namespace Geekbot.net message.Channel.SendMessageAsync("hui!!!"); return Task.CompletedTask; } - if (message.Author.Id == 148542729658302464) - { - var avocado = new Emoji("🥑"); - var avocadoAdder = message.AddReactionAsync(avocado); - } if (!(message.HasCharPrefix('!', ref argPos) || message.HasMentionPrefix(_client.CurrentUser, ref argPos))) return Task.CompletedTask; var context = new CommandContext(_client, message); From 9aa2b17d1c352e0f6ca6d2c3fcca9b858892ae4a Mon Sep 17 00:00:00 2001 From: Runebaas Date: Mon, 30 Oct 2017 20:43:07 +0100 Subject: [PATCH 064/553] Fix kick command --- Geekbot.net/Commands/Mod.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Geekbot.net/Commands/Mod.cs b/Geekbot.net/Commands/Mod.cs index 6dfba53..01c4bd7 100644 --- a/Geekbot.net/Commands/Mod.cs +++ b/Geekbot.net/Commands/Mod.cs @@ -53,25 +53,24 @@ namespace Geekbot.net.Commands [Command("kick", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Ban a user")] - public async Task kick([Summary("@user")] IUser userNormal, [Summary("reason"), Remainder] string reason) + public async Task kick([Summary("@user")] IUser userNormal, [Summary("reason"), Remainder] string reason = "none") { try { var user = (IGuildUser)userNormal; - if (string.IsNullOrEmpty(reason)) + if (reason == "none") { reason = "No reason provided"; } - - await user.KickAsync(); await user.GetOrCreateDMChannelAsync().Result.SendMessageAsync( $"You have been kicked from {Context.Guild.Name} for the following reason: \"{reason}\""); + await user.KickAsync(); try { var modChannelId = ulong.Parse(_redis.HashGet($"{Context.Guild.Id}:Settings", "ModChannel")); var modChannel = (ISocketMessageChannel) _client.GetChannel(modChannelId); var eb = new EmbedBuilder(); - eb.Title = "Kicked"; + eb.Title = ":x: User Kicked"; eb.AddInlineField("User", user.Username); eb.AddInlineField("By Mod", Context.User.Username); eb.AddField("Reason", reason); From ea76629d6e50020d35b28a98ac5f7660584b16ec Mon Sep 17 00:00:00 2001 From: Runebaas Date: Mon, 6 Nov 2017 23:55:28 +0100 Subject: [PATCH 065/553] WIP: poll command --- Geekbot.net/Commands/Help.cs | 5 +- Geekbot.net/Commands/Poll.cs | 163 ++++++++++++++++++++++++++++++ Geekbot.net/Commands/Rank.cs | 24 ++--- Geekbot.net/Lib/EmojiConverter.cs | 28 +++++ Geekbot.net/Program.cs | 3 + 5 files changed, 201 insertions(+), 22 deletions(-) create mode 100644 Geekbot.net/Commands/Poll.cs create mode 100644 Geekbot.net/Lib/EmojiConverter.cs diff --git a/Geekbot.net/Commands/Help.cs b/Geekbot.net/Commands/Help.cs index 2ffa323..aa2cc57 100644 --- a/Geekbot.net/Commands/Help.cs +++ b/Geekbot.net/Commands/Help.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using System.Text; using System.Threading.Tasks; using Discord.Commands; @@ -9,12 +8,10 @@ namespace Geekbot.net.Commands { public class Help : ModuleBase { - private readonly CommandService _commands; private readonly IErrorHandler _errorHandler; - public Help(CommandService commands, IErrorHandler errorHandler) + public Help(IErrorHandler errorHandler) { - _commands = commands; _errorHandler = errorHandler; } diff --git a/Geekbot.net/Commands/Poll.cs b/Geekbot.net/Commands/Poll.cs new file mode 100644 index 0000000..d93111d --- /dev/null +++ b/Geekbot.net/Commands/Poll.cs @@ -0,0 +1,163 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Geekbot.net.Lib; +using Newtonsoft.Json; +using StackExchange.Redis; + +namespace Geekbot.net.Commands +{ + [Group("poll")] + public class Poll : ModuleBase + { + private readonly IErrorHandler _errorHandler; + private readonly IDatabase _redis; + private readonly IEmojiConverter _emojiConverter; + private readonly IUserRepository _userRepository; + + public Poll(IErrorHandler errorHandler, IDatabase redis, IEmojiConverter emojiConverter, IUserRepository userRepository) + { + _errorHandler = errorHandler; + _redis = redis; + _emojiConverter = emojiConverter; + _userRepository = userRepository; + } + + [Command(RunMode = RunMode.Async)] + [Remarks(CommandCategories.Helpers)] + [Summary("Check status of the current poll")] + public async Task Dflt() + { + try + { + var currentPoll = GetCurrentPoll(); + if (currentPoll.Question == null) + { + await ReplyAsync( + "There is no poll in this channel ongoing at the moment\r\nYou can create one with `!poll create question;option1;option2;option3`"); + return; + } + var results = await getPollResults(currentPoll); + + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + [Command("create", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Helpers)] + [Summary("Create a poll")] + public async Task Create([Remainder, Summary("question;option1;option2")] string rawPollString) + { + try + { + var pollList = rawPollString.Split(';').ToList(); + if (pollList.Count <= 2) + { + await ReplyAsync( + "You need a question with atleast 2 options, a valid creation would look like this `question;option1;option2`"); + return; + } + + var eb = new EmbedBuilder(); + eb.Title = $":bar_chart: Poll by {Context.User.Username}"; + var question = pollList[0]; + eb.Description = question; + pollList.RemoveAt(0); + var i = 1; + pollList.ForEach(option => + { + eb.AddInlineField($"Option {_emojiConverter.numberToEmoji(i)}", option); + i++; + }); + var pollMessage = await ReplyAsync("", false, eb.Build()); + i = 1; + pollList.ForEach(option => + { + pollMessage.AddReactionAsync(new Emoji(_emojiConverter.numberToEmoji(i))); + i++; + }); + var poll = new PollData() + { + Creator = Context.User.Id, + MessageId = pollMessage.Id, + IsFinshed = false, + Question = question, + Options = pollList + }; + var pollJson = JsonConvert.SerializeObject(poll); + _redis.HashSet($"{Context.Guild.Id}:Polls", new HashEntry[] {new HashEntry(Context.Channel.Id, pollJson)}); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + [Command("end", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Helpers)] + [Summary("End the current poll")] + public async Task End() + { + try + { + var hasPoll = _redis.HashGet($"{Context.Guild.Id}:Polls", Context.Channel.Id); + if (hasPoll.IsNullOrEmpty) + { + await ReplyAsync( + "There is no poll in this channel ongoing at the moment\r\nYou can create one with `!poll create question;answer1;answer2;answer3`"); + return; + } + + + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + private PollData GetCurrentPoll() + { + try + { + var currentPoll = _redis.HashGet($"{Context.Guild.Id}:Polls", Context.Channel.Id); + return JsonConvert.DeserializeObject(currentPoll.ToString()); + } + catch + { + return new PollData(); + } + } + + private async Task> getPollResults(PollData poll) + { + var message = (IUserMessage)(await Context.Channel.GetMessageAsync(poll.MessageId)); + foreach (var r in message.Reactions) + { + Console.WriteLine($"{r.Key.Name}: {r.Value.ReactionCount}"); + } + return new List(); + } + + private class PollData + { + public ulong Creator { get; set; } + public ulong MessageId { get; set; } + public bool IsFinshed { get; set; } + public string Question { get; set; } + public List Options { get; set; } + } + + private class PollResult + { + public string Option { get; set; } + public string VoteCount { get; set; } + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Rank.cs b/Geekbot.net/Commands/Rank.cs index 274b7ef..dc99eb9 100644 --- a/Geekbot.net/Commands/Rank.cs +++ b/Geekbot.net/Commands/Rank.cs @@ -17,13 +17,15 @@ namespace Geekbot.net.Commands private readonly IErrorHandler _errorHandler; private readonly ILogger _logger; private readonly IUserRepository _userRepository; + private readonly IEmojiConverter _emojiConverter; - public Rank(IDatabase redis, IErrorHandler errorHandler, ILogger logger, IUserRepository userRepository) + public Rank(IDatabase redis, IErrorHandler errorHandler, ILogger logger, IUserRepository userRepository, IEmojiConverter emojiConverter) { _redis = redis; _errorHandler = errorHandler; _logger = logger; _userRepository = userRepository; + _emojiConverter = emojiConverter; } [Command("rank", RunMode = RunMode.Async)] @@ -73,7 +75,7 @@ namespace Geekbot.net.Commands } var highScore = new StringBuilder(); - if (failedToRetrieveUser) highScore.AppendLine(":warning: I couldn't get all userdata, sorry! (bugfix coming soon:tm:)\n"); + if (failedToRetrieveUser) highScore.AppendLine(":warning: I couldn't get all userdata, sorry!\n"); highScore.AppendLine($":bar_chart: **Highscore for {Context.Guild.Name}**"); var highscorePlace = 1; foreach (var user in highscoreUsers) @@ -82,12 +84,12 @@ namespace Geekbot.net.Commands if (user.Key.Username != null) { highScore.AppendLine( - $"{NumerToEmoji(highscorePlace)} **{user.Key.Username}#{user.Key.Discriminator}** - {percent}% of total - {user.Value} messages"); + $"{_emojiConverter.numberToEmoji(highscorePlace)} **{user.Key.Username}#{user.Key.Discriminator}** - {percent}% of total - {user.Value} messages"); } else { highScore.AppendLine( - $"{NumerToEmoji(highscorePlace)} **{user.Key.Id}** - {percent}% of total - {user.Value} messages"); + $"{_emojiConverter.numberToEmoji(highscorePlace)} **{user.Key.Id}** - {percent}% of total - {user.Value} messages"); } highscorePlace++; } @@ -98,20 +100,6 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } - - private string NumerToEmoji(int number) - { - var emojis = new string[] {":one:", ":two:", ":three:", ":four:", ":five:", ":six:", ":seven:", ":eight:", ":nine:", ":keycap_ten:"}; - try - { - return emojis[number - 1]; - } - catch (Exception e) - { - _logger.Warning(e, $"Can't provide emoji number {number}"); - return ":zero:"; - } - } } class RankUserPolyfill diff --git a/Geekbot.net/Lib/EmojiConverter.cs b/Geekbot.net/Lib/EmojiConverter.cs new file mode 100644 index 0000000..6689346 --- /dev/null +++ b/Geekbot.net/Lib/EmojiConverter.cs @@ -0,0 +1,28 @@ +using System.Text; + +namespace Geekbot.net.Lib +{ + public class EmojiConverter : IEmojiConverter + { + public string numberToEmoji(int number) + { + if (number == 10) + { + return "🔟"; + } + var emojiMap = new string[] {"0⃣", "1⃣", "2⃣", "3⃣", "4⃣", "5⃣", "6⃣", "7⃣", "8⃣", "9⃣"}; + var numbers = number.ToString().ToCharArray(); + var returnString = new StringBuilder(); + foreach (var n in numbers) + { + returnString.Append(emojiMap[int.Parse(n.ToString())]); + } + return returnString.ToString(); + } + } + + public interface IEmojiConverter + { + string numberToEmoji(int number); + } +} \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index da50610..b1bf433 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Net; using System.Reflection; +using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using Discord; @@ -118,12 +119,14 @@ namespace Geekbot.net var mediaProvider = new MediaProvider(randomClient, logger); var malClient = new MalClient(redis, logger); var levelCalc = new LevelCalc(); + var emojiConverter = new EmojiConverter(); services.AddSingleton(errorHandler); services.AddSingleton(redis); services.AddSingleton(logger); services.AddSingleton(userRepository); services.AddSingleton(levelCalc); + services.AddSingleton(emojiConverter); services.AddSingleton(randomClient); services.AddSingleton(fortunes); services.AddSingleton(mediaProvider); From f96954a7e12a64de61d3fb09b2171eaadf01a7c4 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Wed, 8 Nov 2017 01:30:50 +0100 Subject: [PATCH 066/553] Finalize poll command and add emojify command (the fuck am i doing with my life) --- Geekbot.net/Commands/Emojify.cs | 37 +++++++++++++++++++ Geekbot.net/Commands/Poll.cs | 40 +++++++++++++------- Geekbot.net/Lib/EmojiConverter.cs | 61 ++++++++++++++++++++++++++++++- 3 files changed, 124 insertions(+), 14 deletions(-) create mode 100644 Geekbot.net/Commands/Emojify.cs diff --git a/Geekbot.net/Commands/Emojify.cs b/Geekbot.net/Commands/Emojify.cs new file mode 100644 index 0000000..b16432e --- /dev/null +++ b/Geekbot.net/Commands/Emojify.cs @@ -0,0 +1,37 @@ +using System; +using System.Text; +using System.Threading.Tasks; +using Discord.Commands; +using Geekbot.net.Lib; + +namespace Geekbot.net.Commands +{ + public class Emojify : ModuleBase + { + private readonly IErrorHandler _errorHandler; + private readonly IEmojiConverter _emojiConverter; + + public Emojify(IErrorHandler errorHandler, IEmojiConverter emojiConverter) + { + _errorHandler = errorHandler; + _emojiConverter = emojiConverter; + } + + [Command("emojify", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Helpers)] + [Summary("Emojify text")] + public async Task Dflt([Remainder, Summary("text")] string text) + { + try + { + var sb = new StringBuilder(); + await ReplyAsync($"*{Context.User.Username}#{Context.User.Discriminator} said:*"); + await ReplyAsync(_emojiConverter.textToEmoji(text)); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Poll.cs b/Geekbot.net/Commands/Poll.cs index d93111d..11f6879 100644 --- a/Geekbot.net/Commands/Poll.cs +++ b/Geekbot.net/Commands/Poll.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; @@ -34,14 +35,13 @@ namespace Geekbot.net.Commands try { var currentPoll = GetCurrentPoll(); - if (currentPoll.Question == null) + if (currentPoll.Question == null || currentPoll.IsFinshed) { await ReplyAsync( "There is no poll in this channel ongoing at the moment\r\nYou can create one with `!poll create question;option1;option2;option3`"); return; } - var results = await getPollResults(currentPoll); - + await ReplyAsync("There is a poll running at the moment"); } catch (Exception e) { @@ -65,7 +65,7 @@ namespace Geekbot.net.Commands } var eb = new EmbedBuilder(); - eb.Title = $":bar_chart: Poll by {Context.User.Username}"; + eb.Title = $"Poll by {Context.User.Username}"; var question = pollList[0]; eb.Description = question; pollList.RemoveAt(0); @@ -106,15 +106,21 @@ namespace Geekbot.net.Commands { try { - var hasPoll = _redis.HashGet($"{Context.Guild.Id}:Polls", Context.Channel.Id); - if (hasPoll.IsNullOrEmpty) + var currentPoll = GetCurrentPoll(); + if (currentPoll.Question == null || currentPoll.IsFinshed) { - await ReplyAsync( - "There is no poll in this channel ongoing at the moment\r\nYou can create one with `!poll create question;answer1;answer2;answer3`"); + await ReplyAsync("There is no ongoing poll at the moment"); return; } - - + var results = await getPollResults(currentPoll); + var sb = new StringBuilder(); + sb.AppendLine("**Poll Results**"); + sb.AppendLine(currentPoll.Question); + foreach (var result in results) + { + sb.AppendLine($"{result.VoteCount} - {result.Option}"); + } + await ReplyAsync(sb.ToString()); } catch (Exception e) { @@ -138,11 +144,19 @@ namespace Geekbot.net.Commands private async Task> getPollResults(PollData poll) { var message = (IUserMessage)(await Context.Channel.GetMessageAsync(poll.MessageId)); + var results = new List(); foreach (var r in message.Reactions) { - Console.WriteLine($"{r.Key.Name}: {r.Value.ReactionCount}"); + var option = int.Parse(r.Key.Name.ToCharArray()[0].ToString()); + var result = new PollResult() + { + Option = poll.Options[option - 1], + VoteCount = r.Value.ReactionCount + }; + results.Add(result); } - return new List(); + results.Sort((x,y) => y.VoteCount.CompareTo(x.VoteCount)); + return results; } private class PollData @@ -157,7 +171,7 @@ namespace Geekbot.net.Commands private class PollResult { public string Option { get; set; } - public string VoteCount { get; set; } + public int VoteCount { get; set; } } } } \ No newline at end of file diff --git a/Geekbot.net/Lib/EmojiConverter.cs b/Geekbot.net/Lib/EmojiConverter.cs index 6689346..8d6e80b 100644 --- a/Geekbot.net/Lib/EmojiConverter.cs +++ b/Geekbot.net/Lib/EmojiConverter.cs @@ -1,4 +1,5 @@ -using System.Text; +using System.Collections; +using System.Text; namespace Geekbot.net.Lib { @@ -19,10 +20,68 @@ namespace Geekbot.net.Lib } return returnString.ToString(); } + + public string textToEmoji(string text) + { + var emojiMap = new Hashtable + { + ['A'] = ":regional_indicator_a:", + ['B'] = ":b:", + ['C'] = ":regional_indicator_c:", + ['D'] = ":regional_indicator_d:", + ['E'] = ":regional_indicator_e:", + ['F'] = ":regional_indicator_f:", + ['G'] = ":regional_indicator_g:", + ['H'] = ":regional_indicator_h:", + ['I'] = ":regional_indicator_i:", + ['J'] = ":regional_indicator_j:", + ['K'] = ":regional_indicator_k:", + ['L'] = ":regional_indicator_l:", + ['M'] = ":regional_indicator_m:", + ['N'] = ":regional_indicator_n:", + ['O'] = ":regional_indicator_o:", + ['P'] = ":regional_indicator_p:", + ['Q'] = ":regional_indicator_q:", + ['R'] = ":regional_indicator_r:", + ['S'] = ":regional_indicator_s:", + ['T'] = ":regional_indicator_t:", + ['U'] = ":regional_indicator_u:", + ['V'] = ":regional_indicator_v:", + ['W'] = ":regional_indicator_w:", + ['X'] = ":regional_indicator_x:", + ['Y'] = ":regional_indicator_y:", + ['Z'] = ":regional_indicator_z:", + ['!'] = ":exclamation:", + ['?'] = ":question:", + ['#'] = ":hash:", + ['*'] = ":star2:", + ['+'] = ":heavy_plus_sign:", + ['0'] = ":zero:", + ['1'] = ":one:", + ['2'] = ":two:", + ['3'] = ":three:", + ['4'] = ":four:", + ['5'] = ":five", + ['6'] = ":six", + ['7'] = ":seven:", + ['8'] = ":eight", + ['9'] = ":nine:", + [' '] = " " + }; + var letters = text.ToUpper().ToCharArray(); + var returnString = new StringBuilder(); + foreach (var n in letters) + { + var emoji = emojiMap[n] ?? n; + returnString.Append(emoji); + } + return returnString.ToString(); + } } public interface IEmojiConverter { string numberToEmoji(int number); + string textToEmoji(string text); } } \ No newline at end of file From 0e217b8db1d67e19d993d5ab4738375ee4ae1272 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Wed, 8 Nov 2017 19:19:43 +0100 Subject: [PATCH 067/553] Bug fixes in polls, emoji stuff and quotes --- Geekbot.net/Commands/Emojify.cs | 8 +++++++- Geekbot.net/Commands/Poll.cs | 25 +++++++++++++++++++------ Geekbot.net/Commands/Quote.cs | 10 ++++++++++ Geekbot.net/Lib/EmojiConverter.cs | 6 +++--- 4 files changed, 39 insertions(+), 10 deletions(-) diff --git a/Geekbot.net/Commands/Emojify.cs b/Geekbot.net/Commands/Emojify.cs index b16432e..855bd65 100644 --- a/Geekbot.net/Commands/Emojify.cs +++ b/Geekbot.net/Commands/Emojify.cs @@ -25,8 +25,14 @@ namespace Geekbot.net.Commands try { var sb = new StringBuilder(); + var emojis = _emojiConverter.textToEmoji(text); + if (emojis.Length > 1999) + { + await ReplyAsync("I can't take that much at once!"); + return; + } await ReplyAsync($"*{Context.User.Username}#{Context.User.Discriminator} said:*"); - await ReplyAsync(_emojiConverter.textToEmoji(text)); + await ReplyAsync(emojis); } catch (Exception e) { diff --git a/Geekbot.net/Commands/Poll.cs b/Geekbot.net/Commands/Poll.cs index 11f6879..ae2ae77 100644 --- a/Geekbot.net/Commands/Poll.cs +++ b/Geekbot.net/Commands/Poll.cs @@ -56,6 +56,12 @@ namespace Geekbot.net.Commands { try { + var currentPoll = GetCurrentPoll(); + if (currentPoll.Question != null && !currentPoll.IsFinshed) + { + await ReplyAsync("You have not finished you last poll yet. To finish it use `!poll end`"); + return; + } var pollList = rawPollString.Split(';').ToList(); if (pollList.Count <= 2) { @@ -121,6 +127,9 @@ namespace Geekbot.net.Commands sb.AppendLine($"{result.VoteCount} - {result.Option}"); } await ReplyAsync(sb.ToString()); + currentPoll.IsFinshed = true; + var pollJson = JsonConvert.SerializeObject(currentPoll); + _redis.HashSet($"{Context.Guild.Id}:Polls", new HashEntry[] {new HashEntry(Context.Channel.Id, pollJson)}); } catch (Exception e) { @@ -147,13 +156,17 @@ namespace Geekbot.net.Commands var results = new List(); foreach (var r in message.Reactions) { - var option = int.Parse(r.Key.Name.ToCharArray()[0].ToString()); - var result = new PollResult() + try { - Option = poll.Options[option - 1], - VoteCount = r.Value.ReactionCount - }; - results.Add(result); + var option = int.Parse(r.Key.Name.ToCharArray()[0].ToString()); + var result = new PollResult() + { + Option = poll.Options[option - 1], + VoteCount = r.Value.ReactionCount + }; + results.Add(result); + } + catch {} } results.Sort((x,y) => y.VoteCount.CompareTo(x.VoteCount)); return results; diff --git a/Geekbot.net/Commands/Quote.cs b/Geekbot.net/Commands/Quote.cs index ca2d134..d6eae26 100644 --- a/Geekbot.net/Commands/Quote.cs +++ b/Geekbot.net/Commands/Quote.cs @@ -55,6 +55,11 @@ namespace Geekbot.net.Commands await ReplyAsync("You can't save your own quotes..."); return; } + if (user.IsBot) + { + await ReplyAsync("You can't save quotes by a bot..."); + return; + } var lastMessage = await getLastMessageByUser(user); var quote = createQuoteObject(lastMessage); var quoteStore = JsonConvert.SerializeObject(quote); @@ -81,6 +86,11 @@ namespace Geekbot.net.Commands await ReplyAsync("You can't save your own quotes..."); return; } + if (message.Author.IsBot) + { + await ReplyAsync("You can't save quotes by a bot..."); + return; + } var quote = createQuoteObject(message); var quoteStore = JsonConvert.SerializeObject(quote); redis.SetAdd($"{Context.Guild.Id}:Quotes", quoteStore); diff --git a/Geekbot.net/Lib/EmojiConverter.cs b/Geekbot.net/Lib/EmojiConverter.cs index 8d6e80b..4cf7a23 100644 --- a/Geekbot.net/Lib/EmojiConverter.cs +++ b/Geekbot.net/Lib/EmojiConverter.cs @@ -61,10 +61,10 @@ namespace Geekbot.net.Lib ['2'] = ":two:", ['3'] = ":three:", ['4'] = ":four:", - ['5'] = ":five", - ['6'] = ":six", + ['5'] = ":five:", + ['6'] = ":six:", ['7'] = ":seven:", - ['8'] = ":eight", + ['8'] = ":eight:", ['9'] = ":nine:", [' '] = " " }; From 38eb9f02a1aeb849c0059948389002b7387b6721 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Fri, 10 Nov 2017 21:36:41 +0100 Subject: [PATCH 068/553] Fix Initial Setup issues --- Geekbot.net/Program.cs | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index b1bf433..bb674b1 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -206,12 +206,25 @@ namespace Geekbot.net private async Task FinishSetup() { var appInfo = await client.GetApplicationInfoAsync(); - redis.StringSet("botOwner", appInfo.Owner.Id); - - var req = HttpWebRequest.Create(appInfo.IconUrl); - using (Stream stream = req.GetResponse().GetResponseStream() ) + logger.Information($"[Setup] Just a moment while i setup everything {appInfo.Owner.Username}"); + try { - await client.CurrentUser.ModifyAsync(Avatar => new Image(stream)); + redis.StringSet("botOwner", appInfo.Owner.Id); + var req = HttpWebRequest.Create(appInfo.IconUrl); + using (Stream stream = req.GetResponse().GetResponseStream()) + { + await client.CurrentUser.ModifyAsync(User => + { + User.Avatar = new Image(stream); + User.Username = appInfo.Name.ToString(); + }); + } + logger.Information($"[Setup] Everything done, enjoy!"); + } + catch (Exception e) + { + logger.Warning(e, $"[Setup] Oha, it seems like something went wrong while running the setup"); + logger.Warning(e, $"[Setup] Geekbot will work never the less, some features might be disabled though"); } return Task.CompletedTask; } From 667d928ca4aaec5a707da44c01df28d2c8295063 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Fri, 10 Nov 2017 21:37:39 +0100 Subject: [PATCH 069/553] Don't download users on startup --- Geekbot.net/Program.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index bb674b1..7246dd4 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -63,8 +63,8 @@ namespace Geekbot.net client = new DiscordSocketClient(new DiscordSocketConfig { LogLevel = LogSeverity.Verbose, - MessageCacheSize = 1000, - AlwaysDownloadUsers = true + MessageCacheSize = 1000 +// AlwaysDownloadUsers = true }); client.Log += DiscordLogger; commands = new CommandService(); From 45f289d071416955122785cf55cd111199223789 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sat, 11 Nov 2017 16:20:26 +0100 Subject: [PATCH 070/553] Urban Dictionary command, small improvents in message handler, emojis are in embeds now, avatar command --- Geekbot.net/Commands/AvatarGetter.cs | 37 +++++++++++ Geekbot.net/Commands/Cat.cs | 10 +-- Geekbot.net/Commands/Dog.cs | 10 +-- Geekbot.net/Commands/Emojify.cs | 14 +++- Geekbot.net/Commands/UrbanDictionary.cs | 85 +++++++++++++++++++++++++ Geekbot.net/Handlers.cs | 36 +++++++---- Geekbot.net/Program.cs | 3 +- 7 files changed, 168 insertions(+), 27 deletions(-) create mode 100644 Geekbot.net/Commands/AvatarGetter.cs create mode 100644 Geekbot.net/Commands/UrbanDictionary.cs diff --git a/Geekbot.net/Commands/AvatarGetter.cs b/Geekbot.net/Commands/AvatarGetter.cs new file mode 100644 index 0000000..aa968db --- /dev/null +++ b/Geekbot.net/Commands/AvatarGetter.cs @@ -0,0 +1,37 @@ +using System; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Geekbot.net.Lib; + +namespace Geekbot.net.Commands +{ + public class AvatarGetter : ModuleBase + { + private readonly IErrorHandler _errorHandler; + + public AvatarGetter(IErrorHandler errorHandler) + { + _errorHandler = errorHandler; + } + + [Command("avatar", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Randomness)] + [Summary("Get someones avatar")] + public async Task getAvatar([Remainder, Summary("user")] IUser user = null) + { + try + { + if (user == null) + { + user = Context.User; + } + await ReplyAsync(user.GetAvatarUrl()); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Cat.cs b/Geekbot.net/Commands/Cat.cs index 8e528d9..6b83122 100644 --- a/Geekbot.net/Commands/Cat.cs +++ b/Geekbot.net/Commands/Cat.cs @@ -46,10 +46,10 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } - } - - public class CatResponse - { - public string file { get; set; } + + private class CatResponse + { + public string file { get; set; } + } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Dog.cs b/Geekbot.net/Commands/Dog.cs index f0c8e52..6a19741 100644 --- a/Geekbot.net/Commands/Dog.cs +++ b/Geekbot.net/Commands/Dog.cs @@ -46,10 +46,10 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } - } - - public class DogResponse - { - public string url { get; set; } + + private class DogResponse + { + public string url { get; set; } + } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Emojify.cs b/Geekbot.net/Commands/Emojify.cs index 855bd65..7d8d102 100644 --- a/Geekbot.net/Commands/Emojify.cs +++ b/Geekbot.net/Commands/Emojify.cs @@ -1,6 +1,7 @@ using System; using System.Text; using System.Threading.Tasks; +using Discord; using Discord.Commands; using Geekbot.net.Lib; @@ -30,9 +31,16 @@ namespace Geekbot.net.Commands { await ReplyAsync("I can't take that much at once!"); return; - } - await ReplyAsync($"*{Context.User.Username}#{Context.User.Discriminator} said:*"); - await ReplyAsync(emojis); + } + var eb = new EmbedBuilder(); + eb.WithAuthor(new EmbedAuthorBuilder() + { + IconUrl = Context.User.GetAvatarUrl(), + Name = $"{Context.User.Username}#{Context.User.Discriminator}" + }); + eb.WithColor(new Color(59, 136, 195)); + eb.Description = emojis; + await ReplyAsync("", false, eb.Build()); } catch (Exception e) { diff --git a/Geekbot.net/Commands/UrbanDictionary.cs b/Geekbot.net/Commands/UrbanDictionary.cs new file mode 100644 index 0000000..ffd1394 --- /dev/null +++ b/Geekbot.net/Commands/UrbanDictionary.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Geekbot.net.Lib; +using Newtonsoft.Json; + +namespace Geekbot.net.Commands +{ + public class UrbanDictionary : ModuleBase + { + private readonly IErrorHandler _errorHandler; + + public UrbanDictionary(IErrorHandler errorHandler) + { + _errorHandler = errorHandler; + } + + [Command("urban", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Randomness)] + [Summary("Lookup something on urban dictionary")] + public async Task urbanDefine([Remainder, Summary("word")] string word) + { + try + { + using (var client = new HttpClient()) + { + client.BaseAddress = new Uri("https://api.urbandictionary.com"); + var response = await client.GetAsync($"/v0/define?term={word}"); + response.EnsureSuccessStatusCode(); + + var stringResponse = await response.Content.ReadAsStringAsync(); + var definitions = JsonConvert.DeserializeObject(stringResponse); + if (definitions.list.Count == 0) + { + await ReplyAsync("That word is not defined..."); + return; + } + var definition = definitions.list.OrderBy(e => e.thumbs_up).First(); + + var eb = new EmbedBuilder(); + eb.Title = definition.word; + eb.WithColor(new Color(239,255,0)); + eb.Description = definition.definition; + eb.AddField("Example", definition.example); + eb.AddInlineField("Upvotes", definition.thumbs_up); + eb.AddInlineField("Downvotes", definition.thumbs_down); + eb.WithFooter(new EmbedFooterBuilder() + { + Text = definition.permalink + }); + + await ReplyAsync("", false, eb.Build()); + } + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + private class UrbanResponse + { + public string[] tags { get; set; } + public string result_type { get; set; } + public List list { get; set; } + } + + private class UrbanListItem + { + public string definition { get; set; } + public string permalink { get; set; } + public string thumbs_up { get; set; } + public string author { get; set; } + public string word { get; set; } + public string defid { get; set; } + public string current_vote { get; set; } + public string example { get; set; } + public string thumbs_down { get; set; } + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index ba86e37..89fb61e 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Text; using System.Threading.Tasks; using Discord; @@ -37,8 +38,7 @@ namespace Geekbot.net { try { - var message = messageParam as SocketUserMessage; - if (message == null) return Task.CompletedTask; + if (!(messageParam is SocketUserMessage message)) return Task.CompletedTask; if (message.Author.IsBot) return Task.CompletedTask; var argPos = 0; var lowCaseMsg = message.ToString().ToLower(); @@ -65,18 +65,30 @@ namespace Geekbot.net } } - public Task UpdateStats(SocketMessage messsageParam) + public Task UpdateStats(SocketMessage message) { - var message = messsageParam; - if (message == null) return Task.CompletedTask; - - var channel = (SocketGuildChannel) message.Channel; - - _redis.HashIncrementAsync($"{channel.Guild.Id}:Messages", message.Author.Id.ToString()); - _redis.HashIncrementAsync($"{channel.Guild.Id}:Messages", 0.ToString()); + try + { + if (message == null) return Task.CompletedTask; + if (message.Channel.Name.StartsWith('@')) + { + _logger.Information( + $"[Message] DM-Channel - {message.Channel.Name} - {message.Content}"); + return Task.CompletedTask; + } + var channel = (SocketGuildChannel) message.Channel; - if (message.Author.IsBot) return Task.CompletedTask; - _logger.Information($"[Message] {channel.Guild.Name} - {message.Channel} - {message.Author.Username} - {message.Content}"); + _redis.HashIncrementAsync($"{channel.Guild.Id}:Messages", message.Author.Id.ToString()); + _redis.HashIncrementAsync($"{channel.Guild.Id}:Messages", 0.ToString()); + + if (message.Author.IsBot) return Task.CompletedTask; + _logger.Information( + $"[Message] {channel.Guild.Name} ({channel.Guild.Id}) - {message.Channel} ({message.Channel.Id}) - {message.Author.Username}#{message.Author.Discriminator} ({message.Author.Id}) - {message.Content}"); + } + catch (Exception e) + { + _logger.Error(e, "Could not process message stats"); + } return Task.CompletedTask; } diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 7246dd4..d57a269 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -64,7 +64,6 @@ namespace Geekbot.net { LogLevel = LogSeverity.Verbose, MessageCacheSize = 1000 -// AlwaysDownloadUsers = true }); client.Log += DiscordLogger; commands = new CommandService(); @@ -149,7 +148,7 @@ namespace Geekbot.net if (isConneted) { await client.SetGameAsync(redis.StringGet("Game")); - logger.Information($"[Geekbot] Now Connected to {client.Guilds.Count} Servers"); + logger.Information($"[Geekbot] Now Connected as {client.CurrentUser.Username} to {client.Guilds.Count} Servers"); logger.Information("[Geekbot] Registering Stuff"); From 98a0a302df7b036e399f1dd7b3a77df5ba095ee4 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sat, 11 Nov 2017 16:44:47 +0100 Subject: [PATCH 071/553] Cat and dog in embeds, avatar getter gets 1024px instead of 128, urban shows tags --- Geekbot.net/Commands/AvatarGetter.cs | 5 +++-- Geekbot.net/Commands/Cat.cs | 5 ++++- Geekbot.net/Commands/Dog.cs | 5 ++++- Geekbot.net/Commands/UrbanDictionary.cs | 13 +++++++------ 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/Geekbot.net/Commands/AvatarGetter.cs b/Geekbot.net/Commands/AvatarGetter.cs index aa968db..41be8af 100644 --- a/Geekbot.net/Commands/AvatarGetter.cs +++ b/Geekbot.net/Commands/AvatarGetter.cs @@ -16,7 +16,7 @@ namespace Geekbot.net.Commands } [Command("avatar", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Randomness)] + [Remarks(CommandCategories.Helpers)] [Summary("Get someones avatar")] public async Task getAvatar([Remainder, Summary("user")] IUser user = null) { @@ -26,7 +26,8 @@ namespace Geekbot.net.Commands { user = Context.User; } - await ReplyAsync(user.GetAvatarUrl()); + var url = user.GetAvatarUrl().Replace("128", "1024"); + await ReplyAsync(url); } catch (Exception e) { diff --git a/Geekbot.net/Commands/Cat.cs b/Geekbot.net/Commands/Cat.cs index 6b83122..57a3289 100644 --- a/Geekbot.net/Commands/Cat.cs +++ b/Geekbot.net/Commands/Cat.cs @@ -1,6 +1,7 @@ using System; using System.Net.Http; using System.Threading.Tasks; +using Discord; using Discord.Commands; using Geekbot.net.Lib; using Newtonsoft.Json; @@ -33,7 +34,9 @@ namespace Geekbot.net.Commands var stringResponse = await response.Content.ReadAsStringAsync(); var catFile = JsonConvert.DeserializeObject(stringResponse); - await ReplyAsync(catFile.file); + var eb = new EmbedBuilder(); + eb.ImageUrl = catFile.file; + await ReplyAsync("", false, eb.Build()); } catch (HttpRequestException e) { diff --git a/Geekbot.net/Commands/Dog.cs b/Geekbot.net/Commands/Dog.cs index 6a19741..978e5dd 100644 --- a/Geekbot.net/Commands/Dog.cs +++ b/Geekbot.net/Commands/Dog.cs @@ -1,6 +1,7 @@ using System; using System.Net.Http; using System.Threading.Tasks; +using Discord; using Discord.Commands; using Geekbot.net.Lib; using Newtonsoft.Json; @@ -33,7 +34,9 @@ namespace Geekbot.net.Commands var stringResponse = await response.Content.ReadAsStringAsync(); var dogFile = JsonConvert.DeserializeObject(stringResponse); - await ReplyAsync(dogFile.url); + var eb = new EmbedBuilder(); + eb.ImageUrl = dogFile.url; + await ReplyAsync("", false, eb.Build()); } catch (HttpRequestException e) { diff --git a/Geekbot.net/Commands/UrbanDictionary.cs b/Geekbot.net/Commands/UrbanDictionary.cs index ffd1394..2bb3c66 100644 --- a/Geekbot.net/Commands/UrbanDictionary.cs +++ b/Geekbot.net/Commands/UrbanDictionary.cs @@ -20,7 +20,7 @@ namespace Geekbot.net.Commands } [Command("urban", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Randomness)] + [Remarks(CommandCategories.Helpers)] [Summary("Lookup something on urban dictionary")] public async Task urbanDefine([Remainder, Summary("word")] string word) { @@ -42,16 +42,17 @@ namespace Geekbot.net.Commands var definition = definitions.list.OrderBy(e => e.thumbs_up).First(); var eb = new EmbedBuilder(); - eb.Title = definition.word; + eb.WithAuthor(new EmbedAuthorBuilder() + { + Name = definition.word, + Url = definition.permalink + }); eb.WithColor(new Color(239,255,0)); eb.Description = definition.definition; eb.AddField("Example", definition.example); eb.AddInlineField("Upvotes", definition.thumbs_up); eb.AddInlineField("Downvotes", definition.thumbs_down); - eb.WithFooter(new EmbedFooterBuilder() - { - Text = definition.permalink - }); + eb.AddField("Tags", string.Join(", ", definitions.tags)); await ReplyAsync("", false, eb.Build()); } From 2ef08ae924fa942aa0bd13d11017cd022d15c95c Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sat, 11 Nov 2017 17:04:03 +0100 Subject: [PATCH 072/553] Take most relevant urban dict definition --- Geekbot.net/Commands/UrbanDictionary.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Geekbot.net/Commands/UrbanDictionary.cs b/Geekbot.net/Commands/UrbanDictionary.cs index 2bb3c66..65d6382 100644 --- a/Geekbot.net/Commands/UrbanDictionary.cs +++ b/Geekbot.net/Commands/UrbanDictionary.cs @@ -39,7 +39,7 @@ namespace Geekbot.net.Commands await ReplyAsync("That word is not defined..."); return; } - var definition = definitions.list.OrderBy(e => e.thumbs_up).First(); + var definition = definitions.list.First(); var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder() From 12919acf95321c292546b8aaffb50d1eda64a83c Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sat, 11 Nov 2017 17:33:50 +0100 Subject: [PATCH 073/553] Bugfix in !urban and karma bugfix in !stats --- Geekbot.net/Commands/Stats.cs | 2 +- Geekbot.net/Commands/UrbanDictionary.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Geekbot.net/Commands/Stats.cs b/Geekbot.net/Commands/Stats.cs index c800ed2..90e878a 100644 --- a/Geekbot.net/Commands/Stats.cs +++ b/Geekbot.net/Commands/Stats.cs @@ -46,7 +46,7 @@ namespace Geekbot.net.Commands .WithName(userInfo.Username)); eb.WithColor(new Color(221, 255, 119)); - var karma = _redis.HashGet($"{Context.Guild.Id}:Karma", userInfo.Id); + var karma = _redis.HashGet($"{Context.Guild.Id}:Karma", userInfo.Id.ToString()); var correctRolls = _redis.HashGet($"{Context.Guild.Id}:Rolls", userInfo.Id.ToString()); eb.AddInlineField("Discordian Since", $"{createdAt.Day}.{createdAt.Month}.{createdAt.Year} ({age} days)") diff --git a/Geekbot.net/Commands/UrbanDictionary.cs b/Geekbot.net/Commands/UrbanDictionary.cs index 65d6382..b14fbf4 100644 --- a/Geekbot.net/Commands/UrbanDictionary.cs +++ b/Geekbot.net/Commands/UrbanDictionary.cs @@ -36,7 +36,7 @@ namespace Geekbot.net.Commands var definitions = JsonConvert.DeserializeObject(stringResponse); if (definitions.list.Count == 0) { - await ReplyAsync("That word is not defined..."); + await ReplyAsync("That word hasn't been defined..."); return; } var definition = definitions.list.First(); @@ -49,7 +49,7 @@ namespace Geekbot.net.Commands }); eb.WithColor(new Color(239,255,0)); eb.Description = definition.definition; - eb.AddField("Example", definition.example); + eb.AddField("Example", definition.example ?? "(no example given...)"); eb.AddInlineField("Upvotes", definition.thumbs_up); eb.AddInlineField("Downvotes", definition.thumbs_down); eb.AddField("Tags", string.Join(", ", definitions.tags)); From b45370cf9edcbb7af0f51858696d87f940fa40a6 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sat, 11 Nov 2017 19:31:31 +0100 Subject: [PATCH 074/553] !changelog command, slightly improved info command, foundation for voice features --- Geekbot.net/Commands/Changelog.cs | 91 +++++++++++++++++++++++++++++ Geekbot.net/Commands/Info.cs | 14 +++-- Geekbot.net/Commands/Voice.cs | 85 +++++++++++++++++++++++++++ Geekbot.net/Lib/AudioClientCache.cs | 31 ++++++++++ Geekbot.net/Program.cs | 2 + 5 files changed, 219 insertions(+), 4 deletions(-) create mode 100644 Geekbot.net/Commands/Changelog.cs create mode 100644 Geekbot.net/Commands/Voice.cs create mode 100644 Geekbot.net/Lib/AudioClientCache.cs diff --git a/Geekbot.net/Commands/Changelog.cs b/Geekbot.net/Commands/Changelog.cs new file mode 100644 index 0000000..2354481 --- /dev/null +++ b/Geekbot.net/Commands/Changelog.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Discord.WebSocket; +using Geekbot.net.Lib; +using Newtonsoft.Json; + +namespace Geekbot.net.Commands +{ + public class Changelog : ModuleBase + { + private readonly IErrorHandler _errorHandler; + private readonly DiscordSocketClient _client; + + public Changelog(IErrorHandler errorHandler, DiscordSocketClient client) + { + _errorHandler = errorHandler; + _client = client; + } + + [Command("changelog", RunMode = RunMode.Async)] + [Alias("updates")] + [Remarks(CommandCategories.Helpers)] + [Summary("Show the latest 5 updates")] + public async Task getChangelog() + { + try + { + using (var client = new HttpClient()) + { + client.BaseAddress = new Uri("https://api.github.com"); + client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "http://developer.github.com/v3/#user-agent-required"); + var response = await client.GetAsync("/repos/pizzaandcoffee/geekbot.net/commits"); + response.EnsureSuccessStatusCode(); + + var stringResponse = await response.Content.ReadAsStringAsync(); + var commits = JsonConvert.DeserializeObject>(stringResponse); + var eb = new EmbedBuilder(); + eb.WithColor(new Color(143, 165, 102)); + eb.WithAuthor(new EmbedAuthorBuilder() + { + IconUrl = _client.CurrentUser.GetAvatarUrl(), + Name = "Latest Updates", + Url = "https://geekbot.pizzaandcoffee.rocks/updates" + }); + var sb = new StringBuilder(); + foreach (var commit in commits.Take(10)) + { + sb.AppendLine($"- {commit.commit.message} ({commit.commit.author.date:yyyy-MM-dd})"); + } + eb.Description = sb.ToString(); + eb.WithFooter(new EmbedFooterBuilder() + { + Text = $"List generated from github commits on {DateTime.Now:yyyy-MM-dd}" + }); + await ReplyAsync("", false, eb.Build()); + } + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + private class Commit + { + public string sha { get; set; } + public CommitInfo commit { get; set; } + public Uri html_url { get; set; } + } + + private class CommitInfo + { + public commitAuthor author { get; set; } + public string message { get; set; } + } + + private class commitAuthor + { + public string name { get; set; } + public string email { get; set; } + public DateTimeOffset date { get; set; } + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Info.cs b/Geekbot.net/Commands/Info.cs index 29ee180..7f7f6f4 100644 --- a/Geekbot.net/Commands/Info.cs +++ b/Geekbot.net/Commands/Info.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; @@ -14,12 +15,14 @@ namespace Geekbot.net.Commands private readonly IDatabase _redis; private readonly IErrorHandler _errorHandler; private readonly DiscordSocketClient _client; + private readonly CommandService _commands; - public Info(IDatabase redis, IErrorHandler errorHandler, DiscordSocketClient client) + public Info(IDatabase redis, IErrorHandler errorHandler, DiscordSocketClient client, CommandService commands) { _redis = redis; _errorHandler = errorHandler; _client = client; + _commands = commands; } [Command("info", RunMode = RunMode.Async)] @@ -38,10 +41,13 @@ namespace Geekbot.net.Commands var uptime = (DateTime.Now.Subtract(Process.GetCurrentProcess().StartTime)); eb.AddInlineField("Bot Name", _client.CurrentUser.Username); - eb.AddInlineField("Servers", Context.Client.GetGuildsAsync().Result.Count); - eb.AddInlineField("Uptime", $"{uptime.Days}D {uptime.Hours}H {uptime.Minutes}M {uptime.Seconds}S"); eb.AddInlineField("Bot Owner", $"{botOwner.Username}#{botOwner.Discriminator}"); - eb.AddInlineField("Website", "https://geekbot.pizzaandcoffee.rocks/"); + eb.AddInlineField("Library", "Discord.NET V1.0.2"); + eb.AddInlineField("Uptime", $"{uptime.Days}D {uptime.Hours}H {uptime.Minutes}M {uptime.Seconds}S"); + eb.AddInlineField("Servers", Context.Client.GetGuildsAsync().Result.Count); + eb.AddInlineField("Total Commands", _commands.Commands.Count()); + + eb.AddField("Website", "https://geekbot.pizzaandcoffee.rocks/"); await ReplyAsync("", false, eb.Build()); } diff --git a/Geekbot.net/Commands/Voice.cs b/Geekbot.net/Commands/Voice.cs new file mode 100644 index 0000000..8fc230e --- /dev/null +++ b/Geekbot.net/Commands/Voice.cs @@ -0,0 +1,85 @@ +using System; +using System.Threading.Tasks; +using Discord; +using Discord.Audio; +using Discord.Commands; +using Geekbot.net.Lib; + +namespace Geekbot.net.Commands +{ + public class Voice : ModuleBase + { + private readonly IErrorHandler _errorHandler; + private readonly IAudioUtils _audioUtils; + + public Voice(IErrorHandler errorHandler, IAudioUtils audioUtils) + { + _errorHandler = errorHandler; + _audioUtils = audioUtils; + } + + [Command("join")] + public async Task JoinChannel() + { + try + { + // Get the audio channel + var channel = (Context.User as IGuildUser)?.VoiceChannel; + if (channel == null) + { + await Context.Channel.SendMessageAsync( + "User must be in a voice channel, or a voice channel must be passed as an argument."); + return; + } + + // For the next step with transmitting audio, you would want to pass this Audio Client in to a service. + var audioClient = await channel.ConnectAsync(); + _audioUtils.StoreAudioClient(Context.Guild.Id, audioClient); + await ReplyAsync($"Connected to {channel.Name}"); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + [Command("disconnect")] + public async Task DisconnectChannel() + { + try + { + var audioClient = _audioUtils.GetAudioClient(Context.Guild.Id); + if (audioClient == null) + { + await Context.Channel.SendMessageAsync("I'm not in a voice channel at the moment"); + return; + } + await audioClient.StopAsync(); + await ReplyAsync("Disconnected from channel!"); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + +// [Command("play")] +// public async Task play(IVoiceChannel channel = null) +// { +// try +// { +// var audioClient = _audioUtils.GetAudioClient(Context.Guild.Id); +// if (audioClient == null) +// { +// await Context.Channel.SendMessageAsync("I'm not in a voice channel at the moment"); +// return; +// } +// +// } +// catch (Exception e) +// { +// _errorHandler.HandleCommandException(e, Context); +// } +// } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/AudioClientCache.cs b/Geekbot.net/Lib/AudioClientCache.cs new file mode 100644 index 0000000..cf94c38 --- /dev/null +++ b/Geekbot.net/Lib/AudioClientCache.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using Discord.Audio; + +namespace Geekbot.net.Lib +{ + public class AudioUtils : IAudioUtils + { + private Dictionary _audioClients; + + public AudioUtils() + { + _audioClients = new Dictionary(); + } + + public IAudioClient GetAudioClient(ulong guildId) + { + return _audioClients[guildId]; + } + + public void StoreAudioClient(ulong guildId, IAudioClient client) + { + _audioClients[guildId] = client; + } + } + + public interface IAudioUtils + { + IAudioClient GetAudioClient(ulong guildId); + void StoreAudioClient(ulong guildId, IAudioClient client); + } +} \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index d57a269..e79824e 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -119,6 +119,7 @@ namespace Geekbot.net var malClient = new MalClient(redis, logger); var levelCalc = new LevelCalc(); var emojiConverter = new EmojiConverter(); + var audioUtils = new AudioUtils(); services.AddSingleton(errorHandler); services.AddSingleton(redis); @@ -126,6 +127,7 @@ namespace Geekbot.net services.AddSingleton(userRepository); services.AddSingleton(levelCalc); services.AddSingleton(emojiConverter); + services.AddSingleton(audioUtils); services.AddSingleton(randomClient); services.AddSingleton(fortunes); services.AddSingleton(mediaProvider); From 6cef559601c904b59ed82fe2d309307370ad3db4 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Tue, 14 Nov 2017 23:08:36 +0100 Subject: [PATCH 075/553] Add json information to command error handler --- Geekbot.net/Lib/ErrorHandler.cs | 69 ++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 5 deletions(-) diff --git a/Geekbot.net/Lib/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandler.cs index cbd8f29..76e1e1f 100644 --- a/Geekbot.net/Lib/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandler.cs @@ -1,6 +1,7 @@ using System; using Discord.Commands; using Serilog; +using Utf8Json; namespace Geekbot.net.Lib { @@ -15,14 +16,72 @@ namespace Geekbot.net.Lib public void HandleCommandException(Exception e, ICommandContext Context, string errorMessage = "Something went wrong :confused:") { - var errorMsg = - $"Error Occured while executing \"{Context.Message.Content}\", executed by \"{Context.User.Username}\" in \"{Context.Guild.Name}/{Context.Channel.Name}\""; - _logger.Error(e, errorMsg); - if (!string.IsNullOrEmpty(errorMessage)) + try { - Context.Channel.SendMessageAsync(errorMessage); + var errorObj = new ErrorObject() + { + Message = new ErrorMessage() + { + Content = Context.Message.Content, + Id = Context.Message.Id.ToString(), + Attachments = Context.Message.Attachments.Count, + ChannelMentions = Context.Message.MentionedChannelIds.Count, + UserMentions = Context.Message.MentionedUserIds.Count, + RoleMentions = Context.Message.MentionedRoleIds.Count + }, + User = new IdAndName() + { + Id = Context.User.Id.ToString(), + Name = $"{Context.User.Username}#{Context.User.Discriminator}" + }, + Guild = new IdAndName() + { + Id = Context.Guild.Id.ToString(), + Name = Context.Guild.Name + }, + Channel = new IdAndName() + { + Id = Context.Channel.Id.ToString(), + Name = Context.Channel.Name + }, + TimeStamp = DateTime.Now.ToString() + }; + var errorJson = JsonSerializer.ToJsonString(errorObj); + _logger.Error(e, errorJson); + if (!string.IsNullOrEmpty(errorMessage)) + { + Context.Channel.SendMessageAsync(errorMessage); + } } + catch (Exception ex) + { + _logger.Error(ex, "Errorception"); + } + } + + public class ErrorObject + { + public ErrorMessage Message { get; set; } + public IdAndName User { get; set; } + public IdAndName Guild { get; set; } + public IdAndName Channel { get; set; } + public string TimeStamp { get; set; } + } + + public class ErrorMessage + { + public string Content { get; set; } + public string Id { get; set; } + public int Attachments { get; set; } + public int ChannelMentions { get; set; } + public int UserMentions { get; set; } + public int RoleMentions { get; set; } + } + public class IdAndName + { + public string Id { get; set; } + public string Name { get; set; } } } From 7584b09d3545ef5f346f3088ef99451958500f37 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Wed, 15 Nov 2017 01:08:20 +0100 Subject: [PATCH 076/553] Groudwork for multilanguage --- Geekbot.net/Commands/Admin.cs | 27 +++++- Geekbot.net/Lib/TranslationHandler.cs | 119 ++++++++++++++++++++++++++ Geekbot.net/Program.cs | 3 +- Geekbot.net/Storage/Translations.json | 8 ++ 4 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 Geekbot.net/Lib/TranslationHandler.cs create mode 100644 Geekbot.net/Storage/Translations.json diff --git a/Geekbot.net/Commands/Admin.cs b/Geekbot.net/Commands/Admin.cs index 376101a..a0fcc58 100644 --- a/Geekbot.net/Commands/Admin.cs +++ b/Geekbot.net/Commands/Admin.cs @@ -17,12 +17,14 @@ namespace Geekbot.net.Commands private readonly IDatabase _redis; private readonly DiscordSocketClient _client; private readonly IErrorHandler _errorHandler; + private readonly ITranslationHandler _translation; - public Admin(IDatabase redis, DiscordSocketClient client, IErrorHandler errorHandler) + public Admin(IDatabase redis, DiscordSocketClient client, IErrorHandler errorHandler, ITranslationHandler translationHandler) { _redis = redis; _client = client; _errorHandler = errorHandler; + _translation = translationHandler; } [Command("welcome", RunMode = RunMode.Async)] @@ -107,5 +109,28 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context, "Modchannel doesn't seem to exist, please set one with `!admin modchannel [channelId]`"); } } + + [Command("setlang", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Admin)] + [Summary("Change the bots language")] + public async Task setLanguage([Summary("language")] string languageRaw) + { + try + { + var language = languageRaw.ToUpper(); + var success = _translation.SetLanguage(Context.Guild.Id, language); + if (success) + { + await ReplyAsync(_translation.GetString(Context.Guild.Id, "LanguageChanger", "Confirm")); + return; + } + await ReplyAsync( + $"That doesn't seem to be a supported language\r\nSupported Languages are {string.Join(", ", _translation.GetSupportedLanguages())}"); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } } } \ No newline at end of file diff --git a/Geekbot.net/Lib/TranslationHandler.cs b/Geekbot.net/Lib/TranslationHandler.cs new file mode 100644 index 0000000..06587e6 --- /dev/null +++ b/Geekbot.net/Lib/TranslationHandler.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Discord.WebSocket; +using Serilog; +using StackExchange.Redis; + +namespace Geekbot.net.Lib +{ + public class TranslationHandler : ITranslationHandler + { + private readonly ILogger _logger; + private readonly IDatabase _redis; + private Dictionary>> _translations; + private Dictionary _serverLanguages; + public List _supportedLanguages; + + public TranslationHandler(IReadOnlyCollection clientGuilds, IDatabase redis, ILogger logger) + { + _logger = logger; + _redis = redis; + _logger.Information("[Geekbot] Loading Translations"); + LoadTranslations(); + CheckSupportedLanguages(); + LoadServerLanguages(clientGuilds); + } + + private void LoadTranslations() + { + try + { + var translations = File.ReadAllText(Path.GetFullPath("./Storage/Translations.json")); + _translations = + Utf8Json.JsonSerializer.Deserialize>>>( + translations); + } + catch (Exception e) + { + _logger.Fatal(e, "Failed to load Translations"); + Environment.Exit(110); + } + } + + private void CheckSupportedLanguages() + { + try + { + _supportedLanguages = new List(); + foreach (var lang in _translations.First().Value.First().Value) + { + _supportedLanguages.Add(lang.Key); + } + } + catch (Exception e) + { + _logger.Fatal(e, "Failed to load Translations"); + Environment.Exit(110); + } + } + + private void LoadServerLanguages(IReadOnlyCollection clientGuilds) + { + _serverLanguages = new Dictionary(); + foreach (var guild in clientGuilds) + { + var language = _redis.HashGet($"{guild.Id}:Settings", "Language"); + if (string.IsNullOrEmpty(language) || !_supportedLanguages.Contains(language)) + { + _serverLanguages[guild.Id] = "EN"; + } + else + { + _serverLanguages[guild.Id] = language.ToString(); + } + } + } + + public string GetString(ulong guildId, string command, string stringName) + { + var translation = _translations[command][stringName][_serverLanguages[guildId]]; + if (!string.IsNullOrWhiteSpace(translation)) return translation; + translation = _translations[command][stringName]["EN"]; + if (string.IsNullOrWhiteSpace(translation)) + { + _logger.Warning($"No translation found for {command} - {stringName}"); + } + return translation; + } + + public bool SetLanguage(ulong guildId, string language) + { + try + { + if (!_supportedLanguages.Contains(language)) return false; + _redis.HashSet($"{guildId}:Settings", new HashEntry[]{ new HashEntry("Language", language), }); + _serverLanguages[guildId] = language; + return true; + } + catch (Exception e) + { + _logger.Error(e, "[Geekbot] Error while changing language"); + return false; + } + } + + public List GetSupportedLanguages() + { + return _supportedLanguages; + } + } + + public interface ITranslationHandler + { + string GetString(ulong guildId, string command, string stringName); + bool SetLanguage(ulong guildId, string language); + List GetSupportedLanguages(); + } +} \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index e79824e..7f397c0 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -153,9 +153,10 @@ namespace Geekbot.net logger.Information($"[Geekbot] Now Connected as {client.CurrentUser.Username} to {client.Guilds.Count} Servers"); logger.Information("[Geekbot] Registering Stuff"); - + var translationHandler = new TranslationHandler(client.Guilds, redis, logger); await commands.AddModulesAsync(Assembly.GetEntryAssembly()); services.AddSingleton(commands); + services.AddSingleton(translationHandler); services.AddSingleton(client); servicesProvider = services.BuildServiceProvider(); diff --git a/Geekbot.net/Storage/Translations.json b/Geekbot.net/Storage/Translations.json new file mode 100644 index 0000000..b801411 --- /dev/null +++ b/Geekbot.net/Storage/Translations.json @@ -0,0 +1,8 @@ +{ + "LanguageChanger": { + "Confirm": { + "EN": "I will in english from now on", + "CHDE": "I werd ab jetzt in schwiizerdüütsch antworte, äuuä" + } + } +} \ No newline at end of file From f0ba7bb9fc2dbb452c8c5f1ed0ea07ddd2d251b9 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Thu, 16 Nov 2017 00:51:36 +0100 Subject: [PATCH 077/553] Make Translations easier to get --- Geekbot.net/Commands/Admin.cs | 20 +++++++- Geekbot.net/Lib/TranslationHandler.cs | 73 +++++++++++++++++++-------- Geekbot.net/Program.cs | 1 + Geekbot.net/Storage/Translations.json | 10 ++-- 4 files changed, 78 insertions(+), 26 deletions(-) diff --git a/Geekbot.net/Commands/Admin.cs b/Geekbot.net/Commands/Admin.cs index a0fcc58..74b0ca8 100644 --- a/Geekbot.net/Commands/Admin.cs +++ b/Geekbot.net/Commands/Admin.cs @@ -5,7 +5,6 @@ using Discord; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Lib; -using Serilog; using StackExchange.Redis; namespace Geekbot.net.Commands @@ -121,7 +120,8 @@ namespace Geekbot.net.Commands var success = _translation.SetLanguage(Context.Guild.Id, language); if (success) { - await ReplyAsync(_translation.GetString(Context.Guild.Id, "LanguageChanger", "Confirm")); + var trans = _translation.GetDict(Context); + await ReplyAsync(trans["Confirm"]); return; } await ReplyAsync( @@ -132,5 +132,21 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } + + [Command("lang", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Admin)] + [Summary("Change the bots language")] + public async Task getLanguage() + { + try + { + var trans = _translation.GetDict(Context); + await ReplyAsync(trans["GetLanguage"]); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } } } \ No newline at end of file diff --git a/Geekbot.net/Lib/TranslationHandler.cs b/Geekbot.net/Lib/TranslationHandler.cs index 06587e6..1b90da1 100644 --- a/Geekbot.net/Lib/TranslationHandler.cs +++ b/Geekbot.net/Lib/TranslationHandler.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using Discord.Commands; using Discord.WebSocket; using Serilog; using StackExchange.Redis; @@ -14,7 +15,7 @@ namespace Geekbot.net.Lib private readonly IDatabase _redis; private Dictionary>> _translations; private Dictionary _serverLanguages; - public List _supportedLanguages; + private List _supportedLanguages; public TranslationHandler(IReadOnlyCollection clientGuilds, IDatabase redis, ILogger logger) { @@ -22,7 +23,6 @@ namespace Geekbot.net.Lib _redis = redis; _logger.Information("[Geekbot] Loading Translations"); LoadTranslations(); - CheckSupportedLanguages(); LoadServerLanguages(clientGuilds); } @@ -30,24 +30,40 @@ namespace Geekbot.net.Lib { try { - var translations = File.ReadAllText(Path.GetFullPath("./Storage/Translations.json")); - _translations = - Utf8Json.JsonSerializer.Deserialize>>>( - translations); - } - catch (Exception e) - { - _logger.Fatal(e, "Failed to load Translations"); - Environment.Exit(110); - } - } - - private void CheckSupportedLanguages() - { - try - { + var translationFile = File.ReadAllText(Path.GetFullPath("./Storage/Translations.json")); + var rawTranslations = Utf8Json.JsonSerializer.Deserialize>>>(translationFile); + var sortedPerLanguage = new Dictionary>>(); + foreach (var command in rawTranslations) + { + foreach (var str in command.Value) + { + foreach (var lang in str.Value) + { + if (!sortedPerLanguage.ContainsKey(lang.Key)) + { + var commandDict = new Dictionary>(); + var strDict = new Dictionary(); + strDict.Add(str.Key, lang.Value); + commandDict.Add(command.Key, strDict); + sortedPerLanguage.Add(lang.Key, commandDict); + } + if (!sortedPerLanguage[lang.Key].ContainsKey(command.Key)) + { + var strDict = new Dictionary(); + strDict.Add(str.Key, lang.Value); + sortedPerLanguage[lang.Key].Add(command.Key, strDict); + } + if (!sortedPerLanguage[lang.Key][command.Key].ContainsKey(str.Key)) + { + sortedPerLanguage[lang.Key][command.Key].Add(str.Key, lang.Value); + } + } + } + } + _translations = sortedPerLanguage; + _supportedLanguages = new List(); - foreach (var lang in _translations.First().Value.First().Value) + foreach (var lang in sortedPerLanguage) { _supportedLanguages.Add(lang.Key); } @@ -58,7 +74,7 @@ namespace Geekbot.net.Lib Environment.Exit(110); } } - + private void LoadServerLanguages(IReadOnlyCollection clientGuilds) { _serverLanguages = new Dictionary(); @@ -78,7 +94,7 @@ namespace Geekbot.net.Lib public string GetString(ulong guildId, string command, string stringName) { - var translation = _translations[command][stringName][_serverLanguages[guildId]]; + var translation = _translations[_serverLanguages[guildId]][command][stringName]; if (!string.IsNullOrWhiteSpace(translation)) return translation; translation = _translations[command][stringName]["EN"]; if (string.IsNullOrWhiteSpace(translation)) @@ -88,6 +104,20 @@ namespace Geekbot.net.Lib return translation; } + public Dictionary GetDict(ICommandContext context) + { + try + { + var command = context.Message.Content.Split(' ').First().TrimStart('!').ToLower(); + return _translations[_serverLanguages[context.Guild.Id]][command]; + } + catch (Exception e) + { + _logger.Error(e, "lol nope"); + return new Dictionary(); + } + } + public bool SetLanguage(ulong guildId, string language) { try @@ -113,6 +143,7 @@ namespace Geekbot.net.Lib public interface ITranslationHandler { string GetString(ulong guildId, string command, string stringName); + Dictionary GetDict(ICommandContext context); bool SetLanguage(ulong guildId, string language); List GetSupportedLanguages(); } diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 7f397c0..cde241f 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -248,6 +248,7 @@ namespace Geekbot.net case LogSeverity.Critical: case LogSeverity.Error: case LogSeverity.Warning: + if (logMessage.Contains("VOICE_STATE_UPDATE")) break; logger.Error(message.Exception, logMessage); break; default: diff --git a/Geekbot.net/Storage/Translations.json b/Geekbot.net/Storage/Translations.json index b801411..2d32dad 100644 --- a/Geekbot.net/Storage/Translations.json +++ b/Geekbot.net/Storage/Translations.json @@ -1,8 +1,12 @@ { - "LanguageChanger": { - "Confirm": { + "admin": { + "NewLanguageSet": { "EN": "I will in english from now on", - "CHDE": "I werd ab jetzt in schwiizerdüütsch antworte, äuuä" + "CHDE": "I werd ab jetzt uf schwiizerdüütsch antworte, äuuä" + }, + "GetLanguage": { + "EN": "I'm talking english", + "CHDE": "I red schwiizerdüütsch" } } } \ No newline at end of file From 119ce579b75195d4635e8a1554ae09025f2879ca Mon Sep 17 00:00:00 2001 From: Runebaas Date: Thu, 16 Nov 2017 10:27:59 +0100 Subject: [PATCH 078/553] Update Version number to 3.5 and remove database migration script --- Geekbot.net/Lib/Constants.cs | 2 +- Geekbot.net/Lib/DbMigration.cs | 51 ---------------------------------- Geekbot.net/Program.cs | 18 ------------ 3 files changed, 1 insertion(+), 70 deletions(-) delete mode 100644 Geekbot.net/Lib/DbMigration.cs diff --git a/Geekbot.net/Lib/Constants.cs b/Geekbot.net/Lib/Constants.cs index 70506a8..db5c875 100644 --- a/Geekbot.net/Lib/Constants.cs +++ b/Geekbot.net/Lib/Constants.cs @@ -3,7 +3,7 @@ public class Constants { public const string Name = "Geekbot"; - public const double BotVersion = 3.4; + public const double BotVersion = 3.5; public const double ApiVersion = 1; } } \ No newline at end of file diff --git a/Geekbot.net/Lib/DbMigration.cs b/Geekbot.net/Lib/DbMigration.cs deleted file mode 100644 index 63b652c..0000000 --- a/Geekbot.net/Lib/DbMigration.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Serilog; -using StackExchange.Redis; - -namespace Geekbot.net.Lib -{ - public class DbMigration - { - public static Task MigrateDatabaseToHash(IDatabase redis, ILogger logger) - { - foreach (var key in redis.Multiplexer.GetServer("127.0.0.1", 6379).Keys(6)) - { - var keyParts = key.ToString().Split("-"); - if (keyParts.Length == 2 || keyParts.Length == 3) - { - logger.Verbose($"Migrating key {key}"); - var stuff = new List(); - stuff.Add("messages"); - stuff.Add("karma"); - stuff.Add("welcomeMsg"); - stuff.Add("correctRolls"); - if(stuff.Contains(keyParts[keyParts.Length - 1])) - { - var val = redis.StringGet(key); - ulong.TryParse(keyParts[0], out ulong guildId); - ulong.TryParse(keyParts[1], out ulong userId); - - switch (keyParts[keyParts.Length - 1]) - { - case "messages": - redis.HashSet($"{guildId}:Messages", new HashEntry[] { new HashEntry(userId.ToString(), val) }); - break; - case "karma": - redis.HashSet($"{guildId}:Karma", new HashEntry[] { new HashEntry(userId.ToString(), val) }); - break; - case "correctRolls": - redis.HashSet($"{guildId}:Rolls", new HashEntry[] { new HashEntry(userId.ToString(), val) }); - break; - case "welcomeMsg": - redis.HashSet($"{guildId}:Settings", new HashEntry[] { new HashEntry("WelcomeMsg", val) }); - break; - } - } - redis.KeyDelete(key); - } - } - return Task.CompletedTask; - } - } -} \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index cde241f..0f66838 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -79,24 +79,6 @@ namespace Geekbot.net logger.Fatal(e, "[Redis] Redis Connection Failed"); Environment.Exit(102); } - - if (args.Contains("--migrate")) - { - Console.WriteLine("\nYou are about to migrate the database, this will overwrite an already migrated database?"); - Console.Write("Are you sure [y:N]: "); - var migrateDbConfirm = Console.ReadKey(); - Console.WriteLine(); - if (migrateDbConfirm.Key == ConsoleKey.Y) - { - logger.Warning("[Geekbot] Starting Migration"); - await DbMigration.MigrateDatabaseToHash(redis, logger); - logger.Warning("[Geekbot] Finished Migration"); - } - else - { - logger.Information("[Geekbot] Not Migrating db"); - } - } token = redis.StringGet("discordToken"); if (token.IsNullOrEmpty) From 14fcf74aeaf54c3fec04464e4af4442bb4554acb Mon Sep 17 00:00:00 2001 From: Runebaas Date: Thu, 16 Nov 2017 17:19:43 +0100 Subject: [PATCH 079/553] Translate common commands and fix bug in !urban --- Geekbot.net/Commands/Admin.cs | 2 +- Geekbot.net/Commands/Choose.cs | 7 ++- Geekbot.net/Commands/Counters.cs | 34 ++++++----- Geekbot.net/Commands/Roll.cs | 42 ++++++++----- Geekbot.net/Commands/UrbanDictionary.cs | 2 +- Geekbot.net/Commands/mal.cs | 4 +- Geekbot.net/Geekbot.net.csproj | 26 ++++++++ Geekbot.net/Lib/ErrorHandler.cs | 11 ++-- Geekbot.net/Lib/TranslationHandler.cs | 14 +++++ Geekbot.net/Program.cs | 4 +- Geekbot.net/Storage/Translations.json | 80 ++++++++++++++++++++++++- 11 files changed, 182 insertions(+), 44 deletions(-) diff --git a/Geekbot.net/Commands/Admin.cs b/Geekbot.net/Commands/Admin.cs index 74b0ca8..5191dcb 100644 --- a/Geekbot.net/Commands/Admin.cs +++ b/Geekbot.net/Commands/Admin.cs @@ -121,7 +121,7 @@ namespace Geekbot.net.Commands if (success) { var trans = _translation.GetDict(Context); - await ReplyAsync(trans["Confirm"]); + await ReplyAsync(trans["NewLanguageSet"]); return; } await ReplyAsync( diff --git a/Geekbot.net/Commands/Choose.cs b/Geekbot.net/Commands/Choose.cs index a607cdf..d8f1cf2 100644 --- a/Geekbot.net/Commands/Choose.cs +++ b/Geekbot.net/Commands/Choose.cs @@ -9,11 +9,13 @@ namespace Geekbot.net.Commands { private readonly Random _rnd; private readonly IErrorHandler _errorHandler; + private readonly ITranslationHandler _translation; - public Choose(Random RandomClient, IErrorHandler errorHandler) + public Choose(Random RandomClient, IErrorHandler errorHandler, ITranslationHandler translation) { _rnd = RandomClient; _errorHandler = errorHandler; + _translation = translation; } [Command("choose", RunMode = RunMode.Async)] @@ -23,9 +25,10 @@ namespace Geekbot.net.Commands { try { + var transDict = _translation.GetDict(Context); var choicesArray = choices.Split(';'); var choice = _rnd.Next(choicesArray.Length); - await ReplyAsync($"I choose **{choicesArray[choice]}**"); + await ReplyAsync(string.Format(transDict["Choice"], choicesArray[choice])); } catch (Exception e) { diff --git a/Geekbot.net/Commands/Counters.cs b/Geekbot.net/Commands/Counters.cs index 54e3c0e..b999eeb 100644 --- a/Geekbot.net/Commands/Counters.cs +++ b/Geekbot.net/Commands/Counters.cs @@ -12,11 +12,13 @@ namespace Geekbot.net.Commands { private readonly IDatabase _redis; private readonly IErrorHandler _errorHandler; + private readonly ITranslationHandler _translation; - public Counters(IDatabase redis, IErrorHandler errorHandler) + public Counters(IDatabase redis, IErrorHandler errorHandler, ITranslationHandler translation) { _redis = redis; _errorHandler = errorHandler; + _translation = translation; } [Command("good", RunMode = RunMode.Async)] @@ -26,18 +28,18 @@ namespace Geekbot.net.Commands { try { + var transDict = _translation.GetDict(Context); var lastKarmaFromRedis = _redis.HashGet($"{Context.Guild.Id}:KarmaTimeout", Context.User.Id.ToString()); var lastKarma = ConvertToDateTimeOffset(lastKarmaFromRedis.ToString()); if (user.Id == Context.User.Id) { - await ReplyAsync($"Sorry {Context.User.Username}, but you can't lower your own karma"); + await ReplyAsync(string.Format(transDict["CannotChangeOwn"], Context.User.Username)); } else if (TimeoutFinished(lastKarma)) { - await ReplyAsync( - $"Sorry {Context.User.Username}, but you have to wait {GetTimeLeft(lastKarma)} before you can give karma again..."); + await ReplyAsync(string.Format(transDict["WaitUntill"], Context.User.Username, GetTimeLeft(lastKarma))); } - else + else { var newKarma = _redis.HashIncrement($"{Context.Guild.Id}:Karma", user.Id.ToString()); _redis.HashSet($"{Context.Guild.Id}:KarmaTimeout", @@ -49,10 +51,10 @@ namespace Geekbot.net.Commands .WithName(user.Username)); eb.WithColor(new Color(138, 219, 146)); - eb.Title = "Karma Increased"; - eb.AddInlineField("By", Context.User.Username); - eb.AddInlineField("amount", "+1"); - eb.AddInlineField("Current Karma", newKarma); + eb.Title = transDict["Increased"]; + eb.AddInlineField(transDict["By"], Context.User.Username); + eb.AddInlineField(transDict["Amount"], "+1"); + eb.AddInlineField(transDict["Current"], newKarma); await ReplyAsync("", false, eb.Build()); } } @@ -69,16 +71,16 @@ namespace Geekbot.net.Commands { try { + var transDict = _translation.GetDict(Context); var lastKarmaFromRedis = _redis.HashGet($"{Context.Guild.Id}:KarmaTimeout", Context.User.Id.ToString()); var lastKarma = ConvertToDateTimeOffset(lastKarmaFromRedis.ToString()); if (user.Id == Context.User.Id) { - await ReplyAsync($"Sorry {Context.User.Username}, but you can't lower your own karma"); + await ReplyAsync(string.Format(transDict["CannotChangeOwn"], Context.User.Username)); } else if (TimeoutFinished(lastKarma)) { - await ReplyAsync( - $"Sorry {Context.User.Username}, but you have to wait {GetTimeLeft(lastKarma)} before you can take karma again..."); + await ReplyAsync(string.Format(transDict["WaitUntill"], Context.User.Username, GetTimeLeft(lastKarma))); } else { @@ -92,10 +94,10 @@ namespace Geekbot.net.Commands .WithName(user.Username)); eb.WithColor(new Color(138, 219, 146)); - eb.Title = "Karma Decreased"; - eb.AddInlineField("By", Context.User.Username); - eb.AddInlineField("amount", "-1"); - eb.AddInlineField("Current Karma", newKarma); + eb.Title = transDict["Decreased"]; + eb.AddInlineField(transDict["By"], Context.User.Username); + eb.AddInlineField(transDict["Amount"], "-1"); + eb.AddInlineField(transDict["Current"], newKarma); await ReplyAsync("", false, eb.Build()); } } diff --git a/Geekbot.net/Commands/Roll.cs b/Geekbot.net/Commands/Roll.cs index 5103c9f..1ed8408 100644 --- a/Geekbot.net/Commands/Roll.cs +++ b/Geekbot.net/Commands/Roll.cs @@ -8,13 +8,17 @@ namespace Geekbot.net.Commands { public class Roll : ModuleBase { - private readonly IDatabase redis; - private readonly Random rnd; + private readonly IDatabase _redis; + private readonly Random _rnd; + private readonly ITranslationHandler _translation; + private readonly IErrorHandler _errorHandler; - public Roll(IDatabase redis, Random RandomClient) + public Roll(IDatabase redis, Random RandomClient, IErrorHandler errorHandler, ITranslationHandler translation) { - this.redis = redis; - rnd = RandomClient; + _redis = redis; + _rnd = RandomClient; + _translation = translation; + _errorHandler = errorHandler; } [Command("roll", RunMode = RunMode.Async)] @@ -22,21 +26,29 @@ namespace Geekbot.net.Commands [Summary("Guess which number the bot will roll (1-100")] public async Task RollCommand([Remainder] [Summary("guess")] string stuff = "noGuess") { - var number = rnd.Next(1, 100); - var guess = 1000; - int.TryParse(stuff, out guess); - if (guess <= 100 && guess > 0) + try { - await ReplyAsync($"{Context.Message.Author.Mention} you rolled {number}, your guess was {guess}"); - if (guess == number) + var number = _rnd.Next(1, 100); + var guess = 1000; + int.TryParse(stuff, out guess); + var transDict = _translation.GetDict(Context); + if (guess <= 100 && guess > 0) { - await ReplyAsync($"Congratulations {Context.User.Username}, your guess was correct!"); - redis.HashIncrement($"{Context.Guild.Id}:Rolls", Context.User.Id.ToString()); + await ReplyAsync(string.Format(transDict["Rolled"], Context.Message.Author.Mention, number, guess)); + if (guess == number) + { + await ReplyAsync(string.Format(transDict["Gratz"], Context.Message.Author)); + _redis.HashIncrement($"{Context.Guild.Id}:Rolls", Context.User.Id.ToString()); + } + } + else + { + await ReplyAsync(string.Format(transDict["RolledNoGuess"], Context.Message.Author.Mention, number)); } } - else + catch (Exception e) { - await ReplyAsync(Context.Message.Author.Mention + ", you rolled " + number); + _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Commands/UrbanDictionary.cs b/Geekbot.net/Commands/UrbanDictionary.cs index b14fbf4..2c64b58 100644 --- a/Geekbot.net/Commands/UrbanDictionary.cs +++ b/Geekbot.net/Commands/UrbanDictionary.cs @@ -39,7 +39,7 @@ namespace Geekbot.net.Commands await ReplyAsync("That word hasn't been defined..."); return; } - var definition = definitions.list.First(); + var definition = definitions.list.First(e => !string.IsNullOrWhiteSpace(e.example)); var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder() diff --git a/Geekbot.net/Commands/mal.cs b/Geekbot.net/Commands/mal.cs index 4e364ee..261b39f 100644 --- a/Geekbot.net/Commands/mal.cs +++ b/Geekbot.net/Commands/mal.cs @@ -62,7 +62,7 @@ namespace Geekbot.net.Commands } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context, "Something went wrong..."); + _errorHandler.HandleCommandException(e, Context); } } @@ -111,7 +111,7 @@ namespace Geekbot.net.Commands } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context, "Something went wrong..."); + _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index d438225..49779c1 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -41,4 +41,30 @@ + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + +
\ No newline at end of file diff --git a/Geekbot.net/Lib/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandler.cs index 76e1e1f..70a95e2 100644 --- a/Geekbot.net/Lib/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandler.cs @@ -8,16 +8,19 @@ namespace Geekbot.net.Lib public class ErrorHandler : IErrorHandler { private readonly ILogger _logger; + private readonly ITranslationHandler _translation; - public ErrorHandler(ILogger logger) + public ErrorHandler(ILogger logger, ITranslationHandler translation) { _logger = logger; + _translation = translation; } - public void HandleCommandException(Exception e, ICommandContext Context, string errorMessage = "Something went wrong :confused:") + public void HandleCommandException(Exception e, ICommandContext Context, string errorMessage = "def") { try { + var errorString = errorMessage == "def" ? _translation.GetString(Context.Guild.Id, "errorHandler", "SomethingWentWrong") : errorMessage; var errorObj = new ErrorObject() { Message = new ErrorMessage() @@ -50,7 +53,7 @@ namespace Geekbot.net.Lib _logger.Error(e, errorJson); if (!string.IsNullOrEmpty(errorMessage)) { - Context.Channel.SendMessageAsync(errorMessage); + Context.Channel.SendMessageAsync(errorString); } } catch (Exception ex) @@ -87,6 +90,6 @@ namespace Geekbot.net.Lib public interface IErrorHandler { - void HandleCommandException(Exception e, ICommandContext Context, string errorMessage = "Something went wrong :confused:"); + void HandleCommandException(Exception e, ICommandContext Context, string errorMessage = "def"); } } \ No newline at end of file diff --git a/Geekbot.net/Lib/TranslationHandler.cs b/Geekbot.net/Lib/TranslationHandler.cs index 1b90da1..7103574 100644 --- a/Geekbot.net/Lib/TranslationHandler.cs +++ b/Geekbot.net/Lib/TranslationHandler.cs @@ -117,6 +117,19 @@ namespace Geekbot.net.Lib return new Dictionary(); } } + + public Dictionary GetDict(ICommandContext context, string command) + { + try + { + return _translations[_serverLanguages[context.Guild.Id]][command]; + } + catch (Exception e) + { + _logger.Error(e, "lol nope"); + return new Dictionary(); + } + } public bool SetLanguage(ulong guildId, string language) { @@ -144,6 +157,7 @@ namespace Geekbot.net.Lib { string GetString(ulong guildId, string command, string stringName); Dictionary GetDict(ICommandContext context); + Dictionary GetDict(ICommandContext context, string command); bool SetLanguage(ulong guildId, string language); List GetSupportedLanguages(); } diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 0f66838..66d20f8 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -94,7 +94,6 @@ namespace Geekbot.net services = new ServiceCollection(); userRepository = new UserRepository(redis, logger); - var errorHandler = new ErrorHandler(logger); var randomClient = new Random(); var fortunes = new FortunesProvider(randomClient, logger); var mediaProvider = new MediaProvider(randomClient, logger); @@ -103,7 +102,6 @@ namespace Geekbot.net var emojiConverter = new EmojiConverter(); var audioUtils = new AudioUtils(); - services.AddSingleton(errorHandler); services.AddSingleton(redis); services.AddSingleton(logger); services.AddSingleton(userRepository); @@ -136,8 +134,10 @@ namespace Geekbot.net logger.Information("[Geekbot] Registering Stuff"); var translationHandler = new TranslationHandler(client.Guilds, redis, logger); + var errorHandler = new ErrorHandler(logger, translationHandler); await commands.AddModulesAsync(Assembly.GetEntryAssembly()); services.AddSingleton(commands); + services.AddSingleton(errorHandler); services.AddSingleton(translationHandler); services.AddSingleton(client); servicesProvider = services.BuildServiceProvider(); diff --git a/Geekbot.net/Storage/Translations.json b/Geekbot.net/Storage/Translations.json index 2d32dad..ad02cba 100644 --- a/Geekbot.net/Storage/Translations.json +++ b/Geekbot.net/Storage/Translations.json @@ -1,12 +1,90 @@ { "admin": { "NewLanguageSet": { - "EN": "I will in english from now on", + "EN": "I will reply in english from now on", "CHDE": "I werd ab jetzt uf schwiizerdüütsch antworte, äuuä" }, "GetLanguage": { "EN": "I'm talking english", "CHDE": "I red schwiizerdüütsch" } + }, + "errorHandler": { + "SomethingWentWrong": { + "EN": "Something went wrong :confused:", + "CHDE": "Öppis isch schief gange :confused:" + } + }, + "choose": { + "Choice": { + "EN": "I Choose **{0}**", + "CHDE": "I nimme **{0}**" + } + }, + "good": { + "CannotChangeOwn": { + "EN": "Sorry {0}, but you can't give yourself karma", + "CHDE": "Sorry {0}, aber du chasch dr selber kei karma geh" + }, + "WaitUntill": { + "EN": "Sorry {0}, but you have to wait {1} before you can give karma again...", + "CHDE": "Sorry {0}, aber du musch no {1} warte bisch d wieder karma chasch geh..." + }, + "Increased": { + "EN": "Karma gained", + "CHDE": "Karma becho" + }, + "By": { + "EN": "By", + "CHDE": "Vo" + }, + "Amount": { + "EN": "Amount", + "CHDE": "Mengi" + }, + "Current": { + "EN": "Current", + "CHDE": "Jetzt" + } + }, + "bad": { + "CannotChangeOwn": { + "EN": "Sorry {0}, but you can't lower your own karma", + "CHDE": "Sorry {0}, aber du chasch dr din eigete karma nid weg neh" + }, + "WaitUntill": { + "EN": "Sorry {0}, but you have to wait {1} before you can lower karma again...", + "CHDE": "Sorry {0}, aber du musch no {1} warte bisch d wieder karma chasch senke..." + }, + "Decreased": { + "EN": "Karma lowered", + "CHDE": "Karma gsenkt" + }, + "By": { + "EN": "By", + "CHDE": "Vo" + }, + "Amount": { + "EN": "Amount", + "CHDE": "Mengi" + }, + "Current": { + "EN": "Current", + "CHDE": "Jetzt" + } + }, + "roll": { + "Rolled": { + "EN": "{0}, you rolled {1}, your guess was {2}", + "CHDE": "{0}, du hesch {1} grollt und hesch {2} grate" + }, + "Gratz": { + "EN": "Congratulations {0}, your guess was correct!", + "CHDE": "Gratuliere {0}, du hesch richtig grate!" + }, + "RolledNoGuess": { + "EN": "{0}, you rolled {1}", + "CHDE": "{0}, du hesch {1} grollt" + } } } \ No newline at end of file From fb169738fe899723dfded30998317938574199f1 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Thu, 16 Nov 2017 17:33:07 +0100 Subject: [PATCH 080/553] Yet another bugfix in !urban --- Geekbot.net/Commands/UrbanDictionary.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Geekbot.net/Commands/UrbanDictionary.cs b/Geekbot.net/Commands/UrbanDictionary.cs index 2c64b58..520fb2a 100644 --- a/Geekbot.net/Commands/UrbanDictionary.cs +++ b/Geekbot.net/Commands/UrbanDictionary.cs @@ -52,8 +52,11 @@ namespace Geekbot.net.Commands eb.AddField("Example", definition.example ?? "(no example given...)"); eb.AddInlineField("Upvotes", definition.thumbs_up); eb.AddInlineField("Downvotes", definition.thumbs_down); - eb.AddField("Tags", string.Join(", ", definitions.tags)); - + if (definitions.tags.Length > 0) + { + eb.AddField("Tags", string.Join(", ", definitions.tags)); + } + await ReplyAsync("", false, eb.Build()); } } From c4f10f3f7b35dee41c68f1b9a46e5a4fb1286a9f Mon Sep 17 00:00:00 2001 From: Runebaas Date: Mon, 27 Nov 2017 21:57:26 +0100 Subject: [PATCH 081/553] Only report command errors to sentry and other minor tweaks --- Geekbot.net/Commands/Role.cs | 5 +++++ Geekbot.net/Geekbot.net.csproj | 2 +- Geekbot.net/Lib/ErrorHandler.cs | 32 ++++++++++++++++++++++++++++++++ Geekbot.net/Lib/LoggerFactory.cs | 7 ------- Geekbot.net/Program.cs | 6 +++--- Geekbot.net/WebApi/WebConfig.cs | 7 +++---- 6 files changed, 44 insertions(+), 15 deletions(-) diff --git a/Geekbot.net/Commands/Role.cs b/Geekbot.net/Commands/Role.cs index 579dbc6..851ff02 100644 --- a/Geekbot.net/Commands/Role.cs +++ b/Geekbot.net/Commands/Role.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using AngleSharp; using Discord; using Discord.Commands; +using Discord.Net; using Geekbot.net.Lib; using StackExchange.Redis; @@ -80,6 +81,10 @@ namespace Geekbot.net.Commands } await ReplyAsync("That role doesn't seem to exist"); } + catch (HttpException e) + { + await Context.Channel.SendMessageAsync("Seems like i don't have enough permission to give roles..."); + } catch (Exception e) { _errorHandler.HandleCommandException(e, Context); diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 49779c1..dd62e3a 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -27,7 +27,7 @@ - + 1.2.6 diff --git a/Geekbot.net/Lib/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandler.cs index 70a95e2..109ba03 100644 --- a/Geekbot.net/Lib/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandler.cs @@ -1,6 +1,12 @@ using System; +using System.Runtime.InteropServices.ComTypes; +using System.Security.Principal; using Discord.Commands; +using Nancy.Extensions; using Serilog; +using SharpRaven; +using SharpRaven.Data; +using SharpRaven.Utilities; using Utf8Json; namespace Geekbot.net.Lib @@ -9,11 +15,23 @@ namespace Geekbot.net.Lib { private readonly ILogger _logger; private readonly ITranslationHandler _translation; + private readonly IRavenClient _raven; public ErrorHandler(ILogger logger, ITranslationHandler translation) { _logger = logger; _translation = translation; + + var sentryDsn = Environment.GetEnvironmentVariable("SENTRY"); + if (!string.IsNullOrEmpty(sentryDsn)) + { + _raven = new RavenClient(sentryDsn); + _logger.Information($"Command Errors will be logged to Sentry: {sentryDsn}"); + } + else + { + _raven = null; + } } public void HandleCommandException(Exception e, ICommandContext Context, string errorMessage = "def") @@ -55,6 +73,20 @@ namespace Geekbot.net.Lib { Context.Channel.SendMessageAsync(errorString); } + + if (_raven == null) return; + + var sentryEvent = new SentryEvent(e) + { + Tags = + { + ["discord_server"] = errorObj.Guild.Name, + ["discord_user"] = errorObj.User.Name + }, + Message = errorObj.Message.Content, + Extra = errorObj + }; + _raven.Capture(sentryEvent); } catch (Exception ex) { diff --git a/Geekbot.net/Lib/LoggerFactory.cs b/Geekbot.net/Lib/LoggerFactory.cs index 8cfabec..988c300 100644 --- a/Geekbot.net/Lib/LoggerFactory.cs +++ b/Geekbot.net/Lib/LoggerFactory.cs @@ -11,13 +11,6 @@ namespace Geekbot.net.Lib var loggerCreation = new LoggerConfiguration() .WriteTo.LiterateConsole() .WriteTo.RollingFile("Logs/geekbot-{Date}.txt", shared: true); - var sentryDsn = Environment.GetEnvironmentVariable("SENTRY"); - if (!string.IsNullOrEmpty(sentryDsn)) - { - loggerCreation.WriteTo.SentryIO(sentryDsn) - .Enrich.FromLogContext(); - Console.WriteLine($"Logging to Sentry Enabled: {sentryDsn}"); - } if (args.Contains("--verbose")) { loggerCreation.MinimumLevel.Verbose(); diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 66d20f8..4382309 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -195,7 +195,7 @@ namespace Geekbot.net { redis.StringSet("botOwner", appInfo.Owner.Id); var req = HttpWebRequest.Create(appInfo.IconUrl); - using (Stream stream = req.GetResponse().GetResponseStream()) + using (var stream = req.GetResponse().GetResponseStream()) { await client.CurrentUser.ModifyAsync(User => { @@ -207,8 +207,8 @@ namespace Geekbot.net } catch (Exception e) { - logger.Warning(e, $"[Setup] Oha, it seems like something went wrong while running the setup"); - logger.Warning(e, $"[Setup] Geekbot will work never the less, some features might be disabled though"); + logger.Warning(e, "[Setup] Oha, it seems like something went wrong while running the setup"); + logger.Warning("[Setup] Geekbot will work never the less, some features might be disabled though"); } return Task.CompletedTask; } diff --git a/Geekbot.net/WebApi/WebConfig.cs b/Geekbot.net/WebApi/WebConfig.cs index 7875ccb..f0b9ca3 100644 --- a/Geekbot.net/WebApi/WebConfig.cs +++ b/Geekbot.net/WebApi/WebConfig.cs @@ -1,4 +1,4 @@ -using System; +using System.Diagnostics; using Nancy; using Nancy.Bootstrapper; using Nancy.TinyIoc; @@ -11,13 +11,12 @@ namespace Geekbot.net.WebApi { //CORS Enable - pipelines.AfterRequest.AddItemToEndOfPipeline((ctx) => + pipelines.AfterRequest.AddItemToEndOfPipeline(ctx => { ctx.Response.WithHeader("Access-Control-Allow-Origin", "*") .WithHeader("Access-Control-Allow-Methods", "GET") .WithHeader("Access-Control-Allow-Headers", "Accept, Origin, Content-type") - .WithHeader("Last-Modified", DateTime.Now.ToString()); - + .WithHeader("Last-Modified", Process.GetCurrentProcess().StartTime.ToString()); }); } } From 53debf9c9d04e511b9b8e2f111ec304421bafaa1 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Mon, 27 Nov 2017 22:07:05 +0100 Subject: [PATCH 082/553] Add httpErrorHandler --- Geekbot.net/Commands/Role.cs | 2 +- Geekbot.net/Lib/ErrorHandler.cs | 19 +++++++++++++++++-- Geekbot.net/Storage/Translations.json | 6 ++++++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/Geekbot.net/Commands/Role.cs b/Geekbot.net/Commands/Role.cs index 851ff02..f40ccf1 100644 --- a/Geekbot.net/Commands/Role.cs +++ b/Geekbot.net/Commands/Role.cs @@ -83,7 +83,7 @@ namespace Geekbot.net.Commands } catch (HttpException e) { - await Context.Channel.SendMessageAsync("Seems like i don't have enough permission to give roles..."); + _errorHandler.HandleHttpException(e, Context); } catch (Exception e) { diff --git a/Geekbot.net/Lib/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandler.cs index 109ba03..1d6ffd8 100644 --- a/Geekbot.net/Lib/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandler.cs @@ -1,7 +1,9 @@ using System; +using System.Net; using System.Runtime.InteropServices.ComTypes; using System.Security.Principal; using Discord.Commands; +using Discord.Net; using Nancy.Extensions; using Serilog; using SharpRaven; @@ -26,7 +28,7 @@ namespace Geekbot.net.Lib if (!string.IsNullOrEmpty(sentryDsn)) { _raven = new RavenClient(sentryDsn); - _logger.Information($"Command Errors will be logged to Sentry: {sentryDsn}"); + _logger.Information($"[Geekbot] Command Errors will be logged to Sentry: {sentryDsn}"); } else { @@ -93,7 +95,19 @@ namespace Geekbot.net.Lib _logger.Error(ex, "Errorception"); } } - + + public async void HandleHttpException(HttpException e, ICommandContext Context) + { + var errorStrings = _translation.GetDict(Context, "httpErrors"); + switch(e.HttpCode) + { + case HttpStatusCode.Forbidden: + await Context.Channel.SendMessageAsync(errorStrings["403"]); + break; + } + } + + public class ErrorObject { public ErrorMessage Message { get; set; } @@ -123,5 +137,6 @@ namespace Geekbot.net.Lib public interface IErrorHandler { void HandleCommandException(Exception e, ICommandContext Context, string errorMessage = "def"); + void HandleHttpException(HttpException e, ICommandContext Context); } } \ No newline at end of file diff --git a/Geekbot.net/Storage/Translations.json b/Geekbot.net/Storage/Translations.json index ad02cba..93a7421 100644 --- a/Geekbot.net/Storage/Translations.json +++ b/Geekbot.net/Storage/Translations.json @@ -15,6 +15,12 @@ "CHDE": "Öppis isch schief gange :confused:" } }, + "httpErrors": { + "403": { + "EN": "Seems like i don't have enough permission to that :confused:", + "CHDE": "Gseht danach us das ich nid gnueg recht han zum das mache :confused:" + } + }, "choose": { "Choice": { "EN": "I Choose **{0}**", From 98fedb4517d9bfb3a383f1a0598e06af36617480 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 24 Dec 2017 13:11:16 +0100 Subject: [PATCH 083/553] Limit dices to 120 sides and 60 total --- Geekbot.net/Commands/Dice.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Geekbot.net/Commands/Dice.cs b/Geekbot.net/Commands/Dice.cs index a0aa03c..edb155a 100644 --- a/Geekbot.net/Commands/Dice.cs +++ b/Geekbot.net/Commands/Dice.cs @@ -50,6 +50,18 @@ namespace Geekbot.net.Commands return; } + + if (dices.Any(d => d.times > 20)) + { + await ReplyAsync("You can't throw more than 20 dices"); + return; + } + if (dices.Any(d => d.sides > 120)) + { + await ReplyAsync("A dice can't have more than 120 sides"); + return; + } + var rep = new StringBuilder(); rep.AppendLine($":game_die: {Context.User.Mention}"); rep.Append("**Result:** "); From 038a15aa2437825ccaae8ff06025627052f7d90c Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 24 Dec 2017 14:54:35 +0100 Subject: [PATCH 084/553] Add Magic the Gathering Command --- Geekbot.net/Commands/MagicTheGathering.cs | 90 +++++++++++++++++++++++ Geekbot.net/Geekbot.net.csproj | 1 + 2 files changed, 91 insertions(+) create mode 100644 Geekbot.net/Commands/MagicTheGathering.cs diff --git a/Geekbot.net/Commands/MagicTheGathering.cs b/Geekbot.net/Commands/MagicTheGathering.cs new file mode 100644 index 0000000..219e5f8 --- /dev/null +++ b/Geekbot.net/Commands/MagicTheGathering.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Geekbot.net.Lib; +using MtgApiManager.Lib.Service; +using Serilog; + +namespace Geekbot.net.Commands +{ + public class Magicthegathering : ModuleBase + { + private ILogger _logger; + private IErrorHandler _errorHandler; + + public Magicthegathering(ILogger logger, IErrorHandler errorHandler) + { + _logger = logger; + _errorHandler = errorHandler; + } + + [Command("mtg", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Games)] + [Summary("Find a Magic The Gathering Card.")] + public async Task getCard([Remainder] [Summary("name")] string cardName) + { + try + { + var service = new CardService(); + var result = service.Where(x => x.Name, cardName); + + var card = result.All().Value.FirstOrDefault(); + if (card == null) + { + await ReplyAsync("I couldn't find that card..."); + return; + } + var eb = new EmbedBuilder(); + eb.Title = card.Name; + eb.Description = card.Type; + + if (card.Colors != null) eb.WithColor(GetColor(card.Colors)); + + if (card.ImageUrl != null) eb.ImageUrl = card.ImageUrl.ToString(); + + if (!string.IsNullOrEmpty(card.Text)) eb.AddField("Text", card.Text); + + if (!string.IsNullOrEmpty(card.Flavor)) eb.AddField("Flavor", card.Flavor); + if (!string.IsNullOrEmpty(card.SetName)) eb.AddInlineField("Set", card.SetName); + if (!string.IsNullOrEmpty(card.Power)) eb.AddInlineField("Power", card.Power); + if (!string.IsNullOrEmpty(card.Loyalty)) eb.AddInlineField("Loyality", card.Loyalty); + if (!string.IsNullOrEmpty(card.Toughness)) eb.AddInlineField("Thoughness", card.Toughness); + + if (!string.IsNullOrEmpty(card.ManaCost)) eb.AddInlineField("Cost", card.ManaCost); + if (!string.IsNullOrEmpty(card.Rarity)) eb.AddInlineField("Rarity", card.Rarity); + + if (card.Legalities != null) eb.AddField("Legality", string.Join(", ", card.Legalities.Select(e => e.Format))); + + await ReplyAsync("", false, eb.Build()); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + private Color GetColor(IEnumerable colors) + { + var color = colors.FirstOrDefault(); + switch (color) + { + case "Black": + return new Color(177, 171, 170); + case "White": + return new Color(255, 252, 214); + case "Blue": + return new Color(156, 189, 204); + case "Red": + return new Color(204, 156, 140); + case "Green": + return new Color(147, 181, 159); + default: + return new Color(255, 252, 214); + } + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index dd62e3a..6fcd62d 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -17,6 +17,7 @@ + From d8b34f867b4b05fa290582d0819e9bd76f2de9f4 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 28 Dec 2017 22:38:49 +0100 Subject: [PATCH 085/553] Extend !rank command with karma and list length (it got super hacky) --- Geekbot.net/Commands/Rank.cs | 60 ++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/Geekbot.net/Commands/Rank.cs b/Geekbot.net/Commands/Rank.cs index dc99eb9..32879a7 100644 --- a/Geekbot.net/Commands/Rank.cs +++ b/Geekbot.net/Commands/Rank.cs @@ -30,12 +30,29 @@ namespace Geekbot.net.Commands [Command("rank", RunMode = RunMode.Async)] [Remarks(CommandCategories.Statistics)] - [Summary("get user top 10")] - public async Task RankCmd() + [Summary("get user top 10 in messages or karma")] + public async Task RankCmd([Summary("type")] string typeUnformated = "messages", [Summary("amount")] int amount = 10) { try { - var messageList = _redis.HashGetAll($"{Context.Guild.Id}:Messages"); + var type = typeUnformated.ToCharArray().First().ToString().ToUpper() + typeUnformated.Substring(1); + + if (!type.Equals("Messages") && !type.Equals("Karma")) + { + await ReplyAsync("Valid types are '`messages`' and '`karma`'"); + return; + } + + + var replyBuilder = new StringBuilder(); + + if (amount > 20) + { + replyBuilder.AppendLine(":warning: Limiting to 20"); + amount = 20; + } + + var messageList = _redis.HashGetAll($"{Context.Guild.Id}:{type}"); var sortedList = messageList.OrderByDescending(e => e.Value).ToList(); var guildMessages = (int) sortedList.First().Value; sortedList.RemoveAt(0); @@ -45,7 +62,7 @@ namespace Geekbot.net.Commands var failedToRetrieveUser = false; foreach (var user in sortedList) { - if (listLimiter > 10) break; + if (listLimiter > amount) break; try { var guildUser = _userRepository.Get((ulong)user.Name); @@ -74,26 +91,35 @@ namespace Geekbot.net.Commands } - var highScore = new StringBuilder(); - if (failedToRetrieveUser) highScore.AppendLine(":warning: I couldn't get all userdata, sorry!\n"); - highScore.AppendLine($":bar_chart: **Highscore for {Context.Guild.Name}**"); + if (failedToRetrieveUser) replyBuilder.AppendLine(":warning: Couldn't get all userdata\n"); + replyBuilder.AppendLine($":bar_chart: **{type} Highscore for {Context.Guild.Name}**"); var highscorePlace = 1; foreach (var user in highscoreUsers) { - var percent = Math.Round((double) (100 * user.Value) / guildMessages, 2); - if (user.Key.Username != null) + replyBuilder.Append(highscorePlace < 11 + ? $"{_emojiConverter.numberToEmoji(highscorePlace)} " + : $"`{highscorePlace}.` "); + + replyBuilder.Append(user.Key.Username != null + ? $"**{user.Key.Username}#{user.Key.Discriminator}**" + : $"**{user.Key.Id}**"); + + switch (type) { - highScore.AppendLine( - $"{_emojiConverter.numberToEmoji(highscorePlace)} **{user.Key.Username}#{user.Key.Discriminator}** - {percent}% of total - {user.Value} messages"); - } - else - { - highScore.AppendLine( - $"{_emojiConverter.numberToEmoji(highscorePlace)} **{user.Key.Id}** - {percent}% of total - {user.Value} messages"); + case "Messages": + var percent = Math.Round((double) (100 * user.Value) / guildMessages, 2); + replyBuilder.Append($" - {percent}% of total - {user.Value} messages"); + break; + case "Karma": + replyBuilder.Append($" - {user.Value} Karma"); + break; } + + replyBuilder.Append("\n"); + highscorePlace++; } - await ReplyAsync(highScore.ToString()); + await ReplyAsync(replyBuilder.ToString()); } catch (Exception e) { From cb9c7c97dcc9463004f35fe7d9f4129ea654d943 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 28 Dec 2017 22:58:29 +0100 Subject: [PATCH 086/553] !rank bugfix --- Geekbot.net/Commands/Rank.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Geekbot.net/Commands/Rank.cs b/Geekbot.net/Commands/Rank.cs index 32879a7..3c24f24 100644 --- a/Geekbot.net/Commands/Rank.cs +++ b/Geekbot.net/Commands/Rank.cs @@ -55,7 +55,7 @@ namespace Geekbot.net.Commands var messageList = _redis.HashGetAll($"{Context.Guild.Id}:{type}"); var sortedList = messageList.OrderByDescending(e => e.Value).ToList(); var guildMessages = (int) sortedList.First().Value; - sortedList.RemoveAt(0); + if (type == "Messages") sortedList.RemoveAt(0); var highscoreUsers = new Dictionary(); var listLimiter = 1; From 08b36c18509d9656d23d4145265218a1edeb4e1c Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 29 Dec 2017 01:03:38 +0100 Subject: [PATCH 087/553] Add Rolls to !rank --- Geekbot.net/Commands/Rank.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Geekbot.net/Commands/Rank.cs b/Geekbot.net/Commands/Rank.cs index 3c24f24..2c232f9 100644 --- a/Geekbot.net/Commands/Rank.cs +++ b/Geekbot.net/Commands/Rank.cs @@ -37,13 +37,12 @@ namespace Geekbot.net.Commands { var type = typeUnformated.ToCharArray().First().ToString().ToUpper() + typeUnformated.Substring(1); - if (!type.Equals("Messages") && !type.Equals("Karma")) + if (!type.Equals("Messages") && !type.Equals("Karma") && !type.Equals("Rolls")) { - await ReplyAsync("Valid types are '`messages`' and '`karma`'"); + await ReplyAsync("Valid types are '`messages`' '`karma`', '`rolls`'"); return; } - var replyBuilder = new StringBuilder(); if (amount > 20) @@ -113,6 +112,9 @@ namespace Geekbot.net.Commands case "Karma": replyBuilder.Append($" - {user.Value} Karma"); break; + case "Rolls": + replyBuilder.Append($" - {user.Value} Guessed"); + break; } replyBuilder.Append("\n"); From 00035ac4b1e6dd35511c7da514fab9edcf871906 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 29 Dec 2017 01:19:20 +0100 Subject: [PATCH 088/553] Prevent people from guessing the same thing twice with !roll --- Geekbot.net/Commands/Roll.cs | 7 +++++++ Geekbot.net/Storage/Translations.json | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/Geekbot.net/Commands/Roll.cs b/Geekbot.net/Commands/Roll.cs index 1ed8408..9d7b576 100644 --- a/Geekbot.net/Commands/Roll.cs +++ b/Geekbot.net/Commands/Roll.cs @@ -34,6 +34,13 @@ namespace Geekbot.net.Commands var transDict = _translation.GetDict(Context); if (guess <= 100 && guess > 0) { + var prevRoll = _redis.HashGet($"{Context.Guild.Id}:RollsPrevious", Context.Message.Author.Id); + if (!prevRoll.IsNullOrEmpty && prevRoll.ToString() == guess.ToString()) + { + await ReplyAsync(string.Format(transDict["NoPrevGuess"], Context.Message.Author.Mention)); + return; + } + _redis.HashSet($"{Context.Guild.Id}:RollsPrevious", new HashEntry[]{ new HashEntry(Context.Message.Author.Id, guess), }); await ReplyAsync(string.Format(transDict["Rolled"], Context.Message.Author.Mention, number, guess)); if (guess == number) { diff --git a/Geekbot.net/Storage/Translations.json b/Geekbot.net/Storage/Translations.json index 93a7421..2d3414e 100644 --- a/Geekbot.net/Storage/Translations.json +++ b/Geekbot.net/Storage/Translations.json @@ -91,6 +91,10 @@ "RolledNoGuess": { "EN": "{0}, you rolled {1}", "CHDE": "{0}, du hesch {1} grollt" + }, + "NoPrevGuess": { + "EN": ":red_circle: {0}, you can't guess the same number again", + "CHDE": ":red_circle: {0}, du chasch nid nomol es gliche rate" } } } \ No newline at end of file From 813698394a81067ca43183c32873c9d4229a35c5 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 29 Dec 2017 01:53:50 +0100 Subject: [PATCH 089/553] Code Cleanup, thanks resharper --- Geekbot.net/Commands/Admin.cs | 39 ++++++----- Geekbot.net/Commands/AvatarGetter.cs | 9 +-- Geekbot.net/Commands/BattleTag.cs | 16 ++--- Geekbot.net/Commands/Cat.cs | 6 +- Geekbot.net/Commands/Changelog.cs | 20 +++--- Geekbot.net/Commands/CheckEm.cs | 3 +- Geekbot.net/Commands/Choose.cs | 5 +- Geekbot.net/Commands/Dice.cs | 42 +++++------- Geekbot.net/Commands/Dog.cs | 6 +- Geekbot.net/Commands/EightBall.cs | 2 +- Geekbot.net/Commands/Emojify.cs | 21 ++---- Geekbot.net/Commands/Fortune.cs | 6 +- Geekbot.net/Commands/Google.cs | 19 ------ Geekbot.net/Commands/GuildInfo.cs | 4 +- Geekbot.net/Commands/Info.cs | 20 +++--- .../Commands/{Counters.cs => Karma.cs} | 26 ++++---- Geekbot.net/Commands/MagicTheGathering.cs | 20 +++--- Geekbot.net/Commands/Mod.cs | 31 ++++----- Geekbot.net/Commands/Overwatch.cs | 22 ++++--- Geekbot.net/Commands/Owner.cs | 31 +++++---- Geekbot.net/Commands/Pokedex.cs | 26 +++----- Geekbot.net/Commands/Poll.cs | 39 +++++------ Geekbot.net/Commands/Quote.cs | 64 ++++++++++--------- Geekbot.net/Commands/RandomAnimals.cs | 12 ++-- Geekbot.net/Commands/Rank.cs | 38 +++++------ Geekbot.net/Commands/Role.cs | 22 ++++--- Geekbot.net/Commands/Roll.cs | 6 +- Geekbot.net/Commands/Say.cs | 2 +- Geekbot.net/Commands/Ship.cs | 3 +- Geekbot.net/Commands/Stats.cs | 12 ++-- Geekbot.net/Commands/UrbanDictionary.cs | 22 +++---- Geekbot.net/Commands/Voice.cs | 8 +-- Geekbot.net/Commands/Youtube.cs | 2 +- Geekbot.net/Commands/mal.cs | 19 +++--- 34 files changed, 298 insertions(+), 325 deletions(-) delete mode 100644 Geekbot.net/Commands/Google.cs rename Geekbot.net/Commands/{Counters.cs => Karma.cs} (87%) diff --git a/Geekbot.net/Commands/Admin.cs b/Geekbot.net/Commands/Admin.cs index 5191dcb..0b76b4b 100644 --- a/Geekbot.net/Commands/Admin.cs +++ b/Geekbot.net/Commands/Admin.cs @@ -13,12 +13,13 @@ namespace Geekbot.net.Commands [RequireUserPermission(GuildPermission.Administrator)] public class Admin : ModuleBase { - private readonly IDatabase _redis; private readonly DiscordSocketClient _client; private readonly IErrorHandler _errorHandler; + private readonly IDatabase _redis; private readonly ITranslationHandler _translation; - - public Admin(IDatabase redis, DiscordSocketClient client, IErrorHandler errorHandler, ITranslationHandler translationHandler) + + public Admin(IDatabase redis, DiscordSocketClient client, IErrorHandler errorHandler, + ITranslationHandler translationHandler) { _redis = redis; _client = client; @@ -31,7 +32,7 @@ namespace Geekbot.net.Commands [Summary("Set a Welcome Message (use '$user' to mention the new joined user).")] public async Task SetWelcomeMessage([Remainder] [Summary("message")] string welcomeMessage) { - _redis.HashSet($"{Context.Guild.Id}:Settings", new HashEntry[] { new HashEntry("WelcomeMsg", welcomeMessage) }); + _redis.HashSet($"{Context.Guild.Id}:Settings", new[] {new HashEntry("WelcomeMsg", welcomeMessage)}); var formatedMessage = welcomeMessage.Replace("$user", Context.User.Mention); await ReplyAsync("Welcome message has been changed\r\nHere is an example of how it would look:\r\n" + formatedMessage); @@ -49,7 +50,8 @@ namespace Geekbot.net.Commands sb.AppendLine("- `!admin showleave true` - send message to mod channel when someone leaves"); sb.AppendLine("- `!admin showdel true` - send message to mod channel when someone deletes a message"); await channel.SendMessageAsync(sb.ToString()); - _redis.HashSet($"{Context.Guild.Id}:Settings", new HashEntry[] {new HashEntry("ModChannel", channel.Id.ToString())}); + _redis.HashSet($"{Context.Guild.Id}:Settings", + new[] {new HashEntry("ModChannel", channel.Id.ToString())}); } catch (Exception e) { @@ -69,20 +71,21 @@ namespace Geekbot.net.Commands if (enabled) { await modChannel.SendMessageAsync("Saved - now sending messages here when someone leaves"); - _redis.HashSet($"{Context.Guild.Id}:Settings", new HashEntry[] {new HashEntry("ShowLeave", true)}); + _redis.HashSet($"{Context.Guild.Id}:Settings", new[] {new HashEntry("ShowLeave", true)}); } else { await modChannel.SendMessageAsync("Saved - stopping sending messages here when someone leaves"); - _redis.HashSet($"{Context.Guild.Id}:Settings", new HashEntry[] {new HashEntry("ShowLeave", false)}); + _redis.HashSet($"{Context.Guild.Id}:Settings", new[] {new HashEntry("ShowLeave", false)}); } } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context, "Modchannel doesn't seem to exist, please set one with `!admin modchannel [channelId]`"); + _errorHandler.HandleCommandException(e, Context, + "Modchannel doesn't seem to exist, please set one with `!admin modchannel [channelId]`"); } } - + [Command("showdel", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Notify modchannel when someone deletes a message")] @@ -94,21 +97,24 @@ namespace Geekbot.net.Commands var modChannel = (ISocketMessageChannel) _client.GetChannel(modChannelId); if (enabled) { - await modChannel.SendMessageAsync("Saved - now sending messages here when someone deletes a message"); - _redis.HashSet($"{Context.Guild.Id}:Settings", new HashEntry[] {new HashEntry("ShowDelete", true)}); + await modChannel.SendMessageAsync( + "Saved - now sending messages here when someone deletes a message"); + _redis.HashSet($"{Context.Guild.Id}:Settings", new[] {new HashEntry("ShowDelete", true)}); } else { - await modChannel.SendMessageAsync("Saved - stopping sending messages here when someone deletes a message"); - _redis.HashSet($"{Context.Guild.Id}:Settings", new HashEntry[] {new HashEntry("ShowDelete", false)}); + await modChannel.SendMessageAsync( + "Saved - stopping sending messages here when someone deletes a message"); + _redis.HashSet($"{Context.Guild.Id}:Settings", new[] {new HashEntry("ShowDelete", false)}); } } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context, "Modchannel doesn't seem to exist, please set one with `!admin modchannel [channelId]`"); + _errorHandler.HandleCommandException(e, Context, + "Modchannel doesn't seem to exist, please set one with `!admin modchannel [channelId]`"); } } - + [Command("setlang", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Change the bots language")] @@ -124,6 +130,7 @@ namespace Geekbot.net.Commands await ReplyAsync(trans["NewLanguageSet"]); return; } + await ReplyAsync( $"That doesn't seem to be a supported language\r\nSupported Languages are {string.Join(", ", _translation.GetSupportedLanguages())}"); } @@ -132,7 +139,7 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } - + [Command("lang", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Change the bots language")] diff --git a/Geekbot.net/Commands/AvatarGetter.cs b/Geekbot.net/Commands/AvatarGetter.cs index 41be8af..9e31b6b 100644 --- a/Geekbot.net/Commands/AvatarGetter.cs +++ b/Geekbot.net/Commands/AvatarGetter.cs @@ -9,7 +9,7 @@ namespace Geekbot.net.Commands public class AvatarGetter : ModuleBase { private readonly IErrorHandler _errorHandler; - + public AvatarGetter(IErrorHandler errorHandler) { _errorHandler = errorHandler; @@ -18,14 +18,11 @@ namespace Geekbot.net.Commands [Command("avatar", RunMode = RunMode.Async)] [Remarks(CommandCategories.Helpers)] [Summary("Get someones avatar")] - public async Task getAvatar([Remainder, Summary("user")] IUser user = null) + public async Task getAvatar([Remainder] [Summary("user")] IUser user = null) { try { - if (user == null) - { - user = Context.User; - } + if (user == null) user = Context.User; var url = user.GetAvatarUrl().Replace("128", "1024"); await ReplyAsync(url); } diff --git a/Geekbot.net/Commands/BattleTag.cs b/Geekbot.net/Commands/BattleTag.cs index e466abb..cbc5ecc 100644 --- a/Geekbot.net/Commands/BattleTag.cs +++ b/Geekbot.net/Commands/BattleTag.cs @@ -2,7 +2,6 @@ using System.Threading.Tasks; using Discord.Commands; using Geekbot.net.Lib; -using StackExchange.Redis; namespace Geekbot.net.Commands { @@ -10,13 +9,11 @@ namespace Geekbot.net.Commands public class BattleTag : ModuleBase { private readonly IErrorHandler _errorHandler; - private readonly IDatabase _redis; private readonly IUserRepository _userRepository; - - public BattleTag(IErrorHandler errorHandler, IDatabase redis, IUserRepository userRepository) + + public BattleTag(IErrorHandler errorHandler, IUserRepository userRepository) { _errorHandler = errorHandler; - _redis = redis; _userRepository = userRepository; } @@ -29,21 +26,16 @@ namespace Geekbot.net.Commands { var tag = _userRepository.getUserSetting(Context.User.Id, "BattleTag"); if (!string.IsNullOrEmpty(tag)) - { - await ReplyAsync($"Your BattleTag is {tag}"); - } else - { await ReplyAsync("You haven't set your BattleTag, set it with `!battletag user#1234`"); - } } catch (Exception e) { _errorHandler.HandleCommandException(e, Context); } } - + [Command(RunMode = RunMode.Async)] [Remarks(CommandCategories.Games)] [Summary("Save your battletag")] @@ -71,7 +63,7 @@ namespace Geekbot.net.Commands { var splited = tag.Split("#"); if (splited.Length != 2) return false; - if (!int.TryParse(splited[1], out int discriminator)) return false; + if (!int.TryParse(splited[1], out var discriminator)) return false; if (splited[1].Length == 4 || splited[1].Length == 5) return true; return false; } diff --git a/Geekbot.net/Commands/Cat.cs b/Geekbot.net/Commands/Cat.cs index 57a3289..2120fe7 100644 --- a/Geekbot.net/Commands/Cat.cs +++ b/Geekbot.net/Commands/Cat.cs @@ -11,12 +11,12 @@ namespace Geekbot.net.Commands public class Cat : ModuleBase { private readonly IErrorHandler _errorHandler; - + public Cat(IErrorHandler errorHandler) { _errorHandler = errorHandler; } - + [Command("cat", RunMode = RunMode.Async)] [Remarks(CommandCategories.Randomness)] [Summary("Return a random image of a cat.")] @@ -49,7 +49,7 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } - + private class CatResponse { public string file { get; set; } diff --git a/Geekbot.net/Commands/Changelog.cs b/Geekbot.net/Commands/Changelog.cs index 2354481..e060152 100644 --- a/Geekbot.net/Commands/Changelog.cs +++ b/Geekbot.net/Commands/Changelog.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Text; -using System.Threading; using System.Threading.Tasks; using Discord; using Discord.Commands; @@ -15,15 +14,15 @@ namespace Geekbot.net.Commands { public class Changelog : ModuleBase { - private readonly IErrorHandler _errorHandler; private readonly DiscordSocketClient _client; - + private readonly IErrorHandler _errorHandler; + public Changelog(IErrorHandler errorHandler, DiscordSocketClient client) { _errorHandler = errorHandler; _client = client; } - + [Command("changelog", RunMode = RunMode.Async)] [Alias("updates")] [Remarks(CommandCategories.Helpers)] @@ -35,7 +34,8 @@ namespace Geekbot.net.Commands using (var client = new HttpClient()) { client.BaseAddress = new Uri("https://api.github.com"); - client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "http://developer.github.com/v3/#user-agent-required"); + client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", + "http://developer.github.com/v3/#user-agent-required"); var response = await client.GetAsync("/repos/pizzaandcoffee/geekbot.net/commits"); response.EnsureSuccessStatusCode(); @@ -43,7 +43,7 @@ namespace Geekbot.net.Commands var commits = JsonConvert.DeserializeObject>(stringResponse); var eb = new EmbedBuilder(); eb.WithColor(new Color(143, 165, 102)); - eb.WithAuthor(new EmbedAuthorBuilder() + eb.WithAuthor(new EmbedAuthorBuilder { IconUrl = _client.CurrentUser.GetAvatarUrl(), Name = "Latest Updates", @@ -51,11 +51,9 @@ namespace Geekbot.net.Commands }); var sb = new StringBuilder(); foreach (var commit in commits.Take(10)) - { sb.AppendLine($"- {commit.commit.message} ({commit.commit.author.date:yyyy-MM-dd})"); - } eb.Description = sb.ToString(); - eb.WithFooter(new EmbedFooterBuilder() + eb.WithFooter(new EmbedFooterBuilder { Text = $"List generated from github commits on {DateTime.Now:yyyy-MM-dd}" }); @@ -67,14 +65,14 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } - + private class Commit { public string sha { get; set; } public CommitInfo commit { get; set; } public Uri html_url { get; set; } } - + private class CommitInfo { public commitAuthor author { get; set; } diff --git a/Geekbot.net/Commands/CheckEm.cs b/Geekbot.net/Commands/CheckEm.cs index 1c488bd..11d0cef 100644 --- a/Geekbot.net/Commands/CheckEm.cs +++ b/Geekbot.net/Commands/CheckEm.cs @@ -11,8 +11,8 @@ namespace Geekbot.net.Commands public class CheckEm : ModuleBase { private readonly IMediaProvider _checkEmImages; - private readonly Random _rnd; private readonly IErrorHandler _errorHandler; + private readonly Random _rnd; public CheckEm(Random RandomClient, IMediaProvider mediaProvider, IErrorHandler errorHandler) { @@ -66,6 +66,7 @@ namespace Geekbot.net.Commands listOfInts.Add(num % 10); num = num / 10; } + listOfInts.Reverse(); return listOfInts.ToArray(); } diff --git a/Geekbot.net/Commands/Choose.cs b/Geekbot.net/Commands/Choose.cs index d8f1cf2..214a1a8 100644 --- a/Geekbot.net/Commands/Choose.cs +++ b/Geekbot.net/Commands/Choose.cs @@ -7,8 +7,8 @@ namespace Geekbot.net.Commands { public class Choose : ModuleBase { - private readonly Random _rnd; private readonly IErrorHandler _errorHandler; + private readonly Random _rnd; private readonly ITranslationHandler _translation; public Choose(Random RandomClient, IErrorHandler errorHandler, ITranslationHandler translation) @@ -21,7 +21,8 @@ namespace Geekbot.net.Commands [Command("choose", RunMode = RunMode.Async)] [Remarks(CommandCategories.Helpers)] [Summary("Let the bot choose for you, seperate options with a semicolon.")] - public async Task Command([Remainder] [Summary("option1;option2")] string choices) + public async Task Command([Remainder] [Summary("option1;option2")] + string choices) { try { diff --git a/Geekbot.net/Commands/Dice.cs b/Geekbot.net/Commands/Dice.cs index edb155a..9195be8 100644 --- a/Geekbot.net/Commands/Dice.cs +++ b/Geekbot.net/Commands/Dice.cs @@ -10,11 +10,11 @@ namespace Geekbot.net.Commands { public class Dice : ModuleBase { - private readonly Random rnd; + private readonly Random _rnd; public Dice(Random RandomClient) { - rnd = RandomClient; + _rnd = RandomClient; } [Command("dice", RunMode = RunMode.Async)] @@ -39,6 +39,7 @@ namespace Geekbot.net.Commands await ReplyAsync("You can only have one mod"); return; } + mod = dice.mod; } } @@ -56,6 +57,7 @@ namespace Geekbot.net.Commands await ReplyAsync("You can't throw more than 20 dices"); return; } + if (dices.Any(d => d.sides > 120)) { await ReplyAsync("A dice can't have more than 120 sides"); @@ -73,32 +75,26 @@ namespace Geekbot.net.Commands var results = new List(); for (var i = 0; i < dice.times; i++) { - var roll = rnd.Next(1, dice.sides); + var roll = _rnd.Next(1, dice.sides); total += roll; results.Add(roll); - if (roll == dice.sides) - { - extraText = "**Critical Hit!**"; - } - if (roll == 1) - { - extraText = "**Critical Fail!**"; - } + if (roll == dice.sides) extraText = "**Critical Hit!**"; + if (roll == 1) extraText = "**Critical Fail!**"; } + resultStrings.Add($"{dice.diceType} ({string.Join(",", results)})"); } + rep.Append(string.Join(" + ", resultStrings)); if (mod != 0) { rep.Append($" + {mod}"); total += mod; } + rep.AppendLine(); rep.AppendLine($"**Total:** {total}"); - if (extraText != "") - { - rep.AppendLine(extraText); - } + if (extraText != "") rep.AppendLine(extraText); await ReplyAsync(rep.ToString()); } @@ -106,29 +102,25 @@ namespace Geekbot.net.Commands { var diceParts = dice.Split('d'); if (diceParts.Length == 2 - && int.TryParse(diceParts[0], out int times) - && int.TryParse(diceParts[1], out int max)) - { - return new DiceTypeDto() + && int.TryParse(diceParts[0], out var times) + && int.TryParse(diceParts[1], out var max)) + return new DiceTypeDto { diceType = dice, times = times, sides = max }; - } if (dice.Length == 1 - && int.TryParse(diceParts[0], out int mod)) - { - return new DiceTypeDto() + && int.TryParse(diceParts[0], out var mod)) + return new DiceTypeDto { mod = mod }; - } return new DiceTypeDto(); } } - class DiceTypeDto + internal class DiceTypeDto { public string diceType { get; set; } public int times { get; set; } diff --git a/Geekbot.net/Commands/Dog.cs b/Geekbot.net/Commands/Dog.cs index 978e5dd..485b7f0 100644 --- a/Geekbot.net/Commands/Dog.cs +++ b/Geekbot.net/Commands/Dog.cs @@ -11,12 +11,12 @@ namespace Geekbot.net.Commands public class Dog : ModuleBase { private readonly IErrorHandler _errorHandler; - + public Dog(IErrorHandler errorHandler) { _errorHandler = errorHandler; } - + [Command("dog", RunMode = RunMode.Async)] [Remarks(CommandCategories.Randomness)] [Summary("Return a random image of a dog.")] @@ -49,7 +49,7 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } - + private class DogResponse { public string url { get; set; } diff --git a/Geekbot.net/Commands/EightBall.cs b/Geekbot.net/Commands/EightBall.cs index 4a369a4..5cadee5 100644 --- a/Geekbot.net/Commands/EightBall.cs +++ b/Geekbot.net/Commands/EightBall.cs @@ -8,8 +8,8 @@ namespace Geekbot.net.Commands { public class EightBall : ModuleBase { - private readonly Random _rnd; private readonly IErrorHandler _errorHandler; + private readonly Random _rnd; public EightBall(Random RandomClient, IErrorHandler errorHandler) { diff --git a/Geekbot.net/Commands/Emojify.cs b/Geekbot.net/Commands/Emojify.cs index 7d8d102..7bdbf8a 100644 --- a/Geekbot.net/Commands/Emojify.cs +++ b/Geekbot.net/Commands/Emojify.cs @@ -1,7 +1,5 @@ using System; -using System.Text; using System.Threading.Tasks; -using Discord; using Discord.Commands; using Geekbot.net.Lib; @@ -9,38 +7,31 @@ namespace Geekbot.net.Commands { public class Emojify : ModuleBase { - private readonly IErrorHandler _errorHandler; private readonly IEmojiConverter _emojiConverter; + private readonly IErrorHandler _errorHandler; public Emojify(IErrorHandler errorHandler, IEmojiConverter emojiConverter) { _errorHandler = errorHandler; _emojiConverter = emojiConverter; } - + [Command("emojify", RunMode = RunMode.Async)] [Remarks(CommandCategories.Helpers)] [Summary("Emojify text")] - public async Task Dflt([Remainder, Summary("text")] string text) + public async Task Dflt([Remainder] [Summary("text")] string text) { try { - var sb = new StringBuilder(); var emojis = _emojiConverter.textToEmoji(text); if (emojis.Length > 1999) { await ReplyAsync("I can't take that much at once!"); return; } - var eb = new EmbedBuilder(); - eb.WithAuthor(new EmbedAuthorBuilder() - { - IconUrl = Context.User.GetAvatarUrl(), - Name = $"{Context.User.Username}#{Context.User.Discriminator}" - }); - eb.WithColor(new Color(59, 136, 195)); - eb.Description = emojis; - await ReplyAsync("", false, eb.Build()); + + await ReplyAsync($"{Context.User.Username}#{Context.User.Discriminator} said:"); + await ReplyAsync(emojis); } catch (Exception e) { diff --git a/Geekbot.net/Commands/Fortune.cs b/Geekbot.net/Commands/Fortune.cs index ba4bc07..1335139 100644 --- a/Geekbot.net/Commands/Fortune.cs +++ b/Geekbot.net/Commands/Fortune.cs @@ -7,11 +7,11 @@ namespace Geekbot.net.Commands { public class Fortune : ModuleBase { - private readonly IFortunesProvider fortunes; + private readonly IFortunesProvider _fortunes; public Fortune(IFortunesProvider fortunes) { - this.fortunes = fortunes; + _fortunes = fortunes; } [Command("fortune", RunMode = RunMode.Async)] @@ -19,7 +19,7 @@ namespace Geekbot.net.Commands [Summary("Get a random fortune")] public async Task GetAFortune() { - await ReplyAsync(fortunes.GetRandomFortune()); + await ReplyAsync(_fortunes.GetRandomFortune()); } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Google.cs b/Geekbot.net/Commands/Google.cs deleted file mode 100644 index 16151c5..0000000 --- a/Geekbot.net/Commands/Google.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Threading.Tasks; -using Discord.Commands; -using Geekbot.net.Lib; - -namespace Geekbot.net.Commands -{ - public class Google : ModuleBase - { - [Command("google", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Fun)] - [Summary("Google Something.")] - public async Task Eyes([Remainder, Summary("SearchText")] string searchText) - { - var url = $"http://lmgtfy.com/?q={searchText.Replace(' ', '+')}"; - - await ReplyAsync($"Please click here :unamused:\r\n{url}"); - } - } -} \ No newline at end of file diff --git a/Geekbot.net/Commands/GuildInfo.cs b/Geekbot.net/Commands/GuildInfo.cs index f195472..2ca76c6 100644 --- a/Geekbot.net/Commands/GuildInfo.cs +++ b/Geekbot.net/Commands/GuildInfo.cs @@ -10,9 +10,9 @@ namespace Geekbot.net.Commands { public class GuildInfo : ModuleBase { - private readonly IDatabase _redis; - private readonly ILevelCalc _levelCalc; private readonly IErrorHandler _errorHandler; + private readonly ILevelCalc _levelCalc; + private readonly IDatabase _redis; public GuildInfo(IDatabase redis, ILevelCalc levelCalc, IErrorHandler errorHandler) { diff --git a/Geekbot.net/Commands/Info.cs b/Geekbot.net/Commands/Info.cs index 7f7f6f4..e8c35dc 100644 --- a/Geekbot.net/Commands/Info.cs +++ b/Geekbot.net/Commands/Info.cs @@ -12,10 +12,10 @@ namespace Geekbot.net.Commands { public class Info : ModuleBase { - private readonly IDatabase _redis; - private readonly IErrorHandler _errorHandler; private readonly DiscordSocketClient _client; private readonly CommandService _commands; + private readonly IErrorHandler _errorHandler; + private readonly IDatabase _redis; public Info(IDatabase redis, IErrorHandler errorHandler, DiscordSocketClient client, CommandService commands) { @@ -33,30 +33,30 @@ namespace Geekbot.net.Commands try { var eb = new EmbedBuilder(); - + eb.WithAuthor(new EmbedAuthorBuilder() .WithIconUrl(_client.CurrentUser.GetAvatarUrl()) .WithName($"{Constants.Name} V{Constants.BotVersion}")); var botOwner = await Context.Guild.GetUserAsync(ulong.Parse(_redis.StringGet("botOwner"))); - var uptime = (DateTime.Now.Subtract(Process.GetCurrentProcess().StartTime)); - + var uptime = DateTime.Now.Subtract(Process.GetCurrentProcess().StartTime); + eb.AddInlineField("Bot Name", _client.CurrentUser.Username); eb.AddInlineField("Bot Owner", $"{botOwner.Username}#{botOwner.Discriminator}"); eb.AddInlineField("Library", "Discord.NET V1.0.2"); eb.AddInlineField("Uptime", $"{uptime.Days}D {uptime.Hours}H {uptime.Minutes}M {uptime.Seconds}S"); eb.AddInlineField("Servers", Context.Client.GetGuildsAsync().Result.Count); eb.AddInlineField("Total Commands", _commands.Commands.Count()); - + eb.AddField("Website", "https://geekbot.pizzaandcoffee.rocks/"); await ReplyAsync("", false, eb.Build()); } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + _errorHandler.HandleCommandException(e, Context); } } - + [Command("uptime", RunMode = RunMode.Async)] [Remarks(CommandCategories.Helpers)] [Summary("Get the Bot Uptime")] @@ -64,12 +64,12 @@ namespace Geekbot.net.Commands { try { - var uptime = (DateTime.Now.Subtract(Process.GetCurrentProcess().StartTime)); + var uptime = DateTime.Now.Subtract(Process.GetCurrentProcess().StartTime); await ReplyAsync($"{uptime.Days}D {uptime.Hours}H {uptime.Minutes}M {uptime.Seconds}S"); } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Commands/Counters.cs b/Geekbot.net/Commands/Karma.cs similarity index 87% rename from Geekbot.net/Commands/Counters.cs rename to Geekbot.net/Commands/Karma.cs index b999eeb..1affa82 100644 --- a/Geekbot.net/Commands/Counters.cs +++ b/Geekbot.net/Commands/Karma.cs @@ -3,18 +3,17 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; -using Serilog; using StackExchange.Redis; namespace Geekbot.net.Commands { - public class Counters : ModuleBase + public class Karma : ModuleBase { - private readonly IDatabase _redis; private readonly IErrorHandler _errorHandler; + private readonly IDatabase _redis; private readonly ITranslationHandler _translation; - public Counters(IDatabase redis, IErrorHandler errorHandler, ITranslationHandler translation) + public Karma(IDatabase redis, IErrorHandler errorHandler, ITranslationHandler translation) { _redis = redis; _errorHandler = errorHandler; @@ -37,13 +36,14 @@ namespace Geekbot.net.Commands } else if (TimeoutFinished(lastKarma)) { - await ReplyAsync(string.Format(transDict["WaitUntill"], Context.User.Username, GetTimeLeft(lastKarma))); + await ReplyAsync(string.Format(transDict["WaitUntill"], Context.User.Username, + GetTimeLeft(lastKarma))); } - else + else { var newKarma = _redis.HashIncrement($"{Context.Guild.Id}:Karma", user.Id.ToString()); _redis.HashSet($"{Context.Guild.Id}:KarmaTimeout", - new HashEntry[] {new HashEntry(Context.User.Id.ToString(), DateTimeOffset.Now.ToString("u"))}); + new[] {new HashEntry(Context.User.Id.ToString(), DateTimeOffset.Now.ToString("u"))}); var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder() @@ -80,13 +80,14 @@ namespace Geekbot.net.Commands } else if (TimeoutFinished(lastKarma)) { - await ReplyAsync(string.Format(transDict["WaitUntill"], Context.User.Username, GetTimeLeft(lastKarma))); + await ReplyAsync(string.Format(transDict["WaitUntill"], Context.User.Username, + GetTimeLeft(lastKarma))); } else { var newKarma = _redis.HashDecrement($"{Context.Guild.Id}:Karma", user.Id.ToString()); _redis.HashSet($"{Context.Guild.Id}:KarmaTimeout", - new HashEntry[] {new HashEntry(Context.User.Id.ToString(), DateTimeOffset.Now.ToString())}); + new[] {new HashEntry(Context.User.Id.ToString(), DateTimeOffset.Now.ToString())}); var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder() @@ -109,15 +110,16 @@ namespace Geekbot.net.Commands private DateTimeOffset ConvertToDateTimeOffset(string dateTimeOffsetString) { - if(string.IsNullOrEmpty(dateTimeOffsetString)) return DateTimeOffset.Now.Subtract(new TimeSpan(7, 18, 0, 0)); + if (string.IsNullOrEmpty(dateTimeOffsetString)) + return DateTimeOffset.Now.Subtract(new TimeSpan(7, 18, 0, 0)); return DateTimeOffset.Parse(dateTimeOffsetString); } - + private bool TimeoutFinished(DateTimeOffset lastKarma) { return lastKarma.AddMinutes(3) > DateTimeOffset.Now; } - + private string GetTimeLeft(DateTimeOffset lastKarma) { var dt = lastKarma.AddMinutes(3).Subtract(DateTimeOffset.Now); diff --git a/Geekbot.net/Commands/MagicTheGathering.cs b/Geekbot.net/Commands/MagicTheGathering.cs index 219e5f8..e2702b1 100644 --- a/Geekbot.net/Commands/MagicTheGathering.cs +++ b/Geekbot.net/Commands/MagicTheGathering.cs @@ -1,24 +1,20 @@ using System; using System.Collections.Generic; -using System.Collections.Immutable; using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; using MtgApiManager.Lib.Service; -using Serilog; namespace Geekbot.net.Commands { public class Magicthegathering : ModuleBase { - private ILogger _logger; - private IErrorHandler _errorHandler; + private readonly IErrorHandler _errorHandler; - public Magicthegathering(ILogger logger, IErrorHandler errorHandler) + public Magicthegathering(IErrorHandler errorHandler) { - _logger = logger; _errorHandler = errorHandler; } @@ -38,26 +34,28 @@ namespace Geekbot.net.Commands await ReplyAsync("I couldn't find that card..."); return; } + var eb = new EmbedBuilder(); eb.Title = card.Name; eb.Description = card.Type; - + if (card.Colors != null) eb.WithColor(GetColor(card.Colors)); if (card.ImageUrl != null) eb.ImageUrl = card.ImageUrl.ToString(); if (!string.IsNullOrEmpty(card.Text)) eb.AddField("Text", card.Text); - + if (!string.IsNullOrEmpty(card.Flavor)) eb.AddField("Flavor", card.Flavor); if (!string.IsNullOrEmpty(card.SetName)) eb.AddInlineField("Set", card.SetName); if (!string.IsNullOrEmpty(card.Power)) eb.AddInlineField("Power", card.Power); if (!string.IsNullOrEmpty(card.Loyalty)) eb.AddInlineField("Loyality", card.Loyalty); if (!string.IsNullOrEmpty(card.Toughness)) eb.AddInlineField("Thoughness", card.Toughness); - + if (!string.IsNullOrEmpty(card.ManaCost)) eb.AddInlineField("Cost", card.ManaCost); if (!string.IsNullOrEmpty(card.Rarity)) eb.AddInlineField("Rarity", card.Rarity); - - if (card.Legalities != null) eb.AddField("Legality", string.Join(", ", card.Legalities.Select(e => e.Format))); + + if (card.Legalities != null) + eb.AddField("Legality", string.Join(", ", card.Legalities.Select(e => e.Format))); await ReplyAsync("", false, eb.Build()); } diff --git a/Geekbot.net/Commands/Mod.cs b/Geekbot.net/Commands/Mod.cs index 01c4bd7..c927b0d 100644 --- a/Geekbot.net/Commands/Mod.cs +++ b/Geekbot.net/Commands/Mod.cs @@ -15,19 +15,20 @@ namespace Geekbot.net.Commands [RequireUserPermission(GuildPermission.ManageRoles)] public class Mod : ModuleBase { - private readonly IUserRepository _userRepository; + private readonly DiscordSocketClient _client; private readonly IErrorHandler _errorHandler; private readonly IDatabase _redis; - private readonly DiscordSocketClient _client; - - public Mod(IUserRepository userRepositry, IErrorHandler errorHandler, IDatabase redis, DiscordSocketClient client) + private readonly IUserRepository _userRepository; + + public Mod(IUserRepository userRepositry, IErrorHandler errorHandler, IDatabase redis, + DiscordSocketClient client) { _userRepository = userRepositry; _errorHandler = errorHandler; _redis = redis; _client = client; } - + [Command("namehistory", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("See past usernames of an user")] @@ -38,30 +39,26 @@ namespace Geekbot.net.Commands var userRepo = _userRepository.Get(user.Id); var sb = new StringBuilder(); sb.AppendLine($":bust_in_silhouette: {user.Username} has been known as:"); - foreach (var name in userRepo.UsedNames) - { - sb.AppendLine($"- `{name}`"); - } + foreach (var name in userRepo.UsedNames) sb.AppendLine($"- `{name}`"); await ReplyAsync(sb.ToString()); } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context, $"I don't have enough permissions to give {user.Username} that role"); + _errorHandler.HandleCommandException(e, Context, + $"I don't have enough permissions to give {user.Username} that role"); } } - + [Command("kick", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Ban a user")] - public async Task kick([Summary("@user")] IUser userNormal, [Summary("reason"), Remainder] string reason = "none") + public async Task kick([Summary("@user")] IUser userNormal, + [Summary("reason")] [Remainder] string reason = "none") { try { - var user = (IGuildUser)userNormal; - if (reason == "none") - { - reason = "No reason provided"; - } + var user = (IGuildUser) userNormal; + if (reason == "none") reason = "No reason provided"; await user.GetOrCreateDMChannelAsync().Result.SendMessageAsync( $"You have been kicked from {Context.Guild.Name} for the following reason: \"{reason}\""); await user.KickAsync(); diff --git a/Geekbot.net/Commands/Overwatch.cs b/Geekbot.net/Commands/Overwatch.cs index 3527cdf..9007804 100644 --- a/Geekbot.net/Commands/Overwatch.cs +++ b/Geekbot.net/Commands/Overwatch.cs @@ -3,7 +3,6 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; -using Google.Apis.Util; using OverwatchAPI; using OverwatchAPI.Config; using Serilog; @@ -17,7 +16,7 @@ namespace Geekbot.net.Commands private readonly IErrorHandler _errorHandler; private readonly ILogger _logger; private readonly IUserRepository _userRepository; - + public Overwatch(IErrorHandler errorHandler, ILogger logger, IDatabase redis, IUserRepository userRepository) { _errorHandler = errorHandler; @@ -38,21 +37,22 @@ namespace Geekbot.net.Commands await ReplyAsync("You have no battle Tag saved, use `!battletag`"); return; } + var profile = await createProfile(tag); if (profile == null) { await ReplyAsync("That player doesn't seem to exist"); return; } - await ReplyAsync("", false, profile.Build()); + await ReplyAsync("", false, profile.Build()); } catch (Exception e) { _errorHandler.HandleCommandException(e, Context); } } - + [Command("profile", RunMode = RunMode.Async)] [Summary("Get someones overwatch profile. EU on PC only. Default battletag is your own (if set).")] [Remarks(CommandCategories.Games)] @@ -65,12 +65,14 @@ namespace Geekbot.net.Commands await ReplyAsync("That doesn't seem to be a valid battletag..."); return; } + var profile = await createProfile(tag); if (profile == null) { await ReplyAsync("That player doesn't seem to exist"); return; } + await ReplyAsync("", false, profile.Build()); } catch (Exception e) @@ -92,12 +94,14 @@ namespace Geekbot.net.Commands await ReplyAsync("This user didn't set a battletag"); return; } + var profile = await createProfile(tag); if (profile == null) { await ReplyAsync("That player doesn't seem to exist"); return; } + await ReplyAsync("", false, profile.Build()); } catch (Exception e) @@ -112,10 +116,7 @@ namespace Geekbot.net.Commands using (var owClient = new OverwatchClient(owConfig)) { var player = await owClient.GetPlayerAsync(battletag); - if (player.Username == null) - { - return null; - } + if (player.Username == null) return null; _logger.Debug($"[OW] Username = {player.Username}"); var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder() @@ -123,10 +124,11 @@ namespace Geekbot.net.Commands .WithName(player.Username)); eb.Url = player.ProfileUrl; eb.AddInlineField("Level", player.PlayerLevel); - eb.AddInlineField("Current Rank", player.CompetitiveRank > 0 ? player.CompetitiveRank.ToString() : "Unranked"); + eb.AddInlineField("Current Rank", + player.CompetitiveRank > 0 ? player.CompetitiveRank.ToString() : "Unranked"); return eb; } } } -} +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Owner.cs b/Geekbot.net/Commands/Owner.cs index c05700c..c3c9cc0 100644 --- a/Geekbot.net/Commands/Owner.cs +++ b/Geekbot.net/Commands/Owner.cs @@ -13,13 +13,14 @@ namespace Geekbot.net.Commands [RequireUserPermission(GuildPermission.Administrator)] public class Owner : ModuleBase { - private readonly IDatabase _redis; private readonly DiscordSocketClient _client; - private readonly ILogger _logger; - private readonly IUserRepository _userRepository; private readonly IErrorHandler _errorHandler; - - public Owner(IDatabase redis, DiscordSocketClient client, ILogger logger, IUserRepository userRepositry, IErrorHandler errorHandler) + private readonly ILogger _logger; + private readonly IDatabase _redis; + private readonly IUserRepository _userRepository; + + public Owner(IDatabase redis, DiscordSocketClient client, ILogger logger, IUserRepository userRepositry, + IErrorHandler errorHandler) { _redis = redis; _client = client; @@ -27,7 +28,7 @@ namespace Geekbot.net.Commands _userRepository = userRepositry; _errorHandler = errorHandler; } - + [Command("youtubekey", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Set the youtube api key")] @@ -36,14 +37,15 @@ namespace Geekbot.net.Commands var botOwner = Context.Guild.GetUserAsync(ulong.Parse(_redis.StringGet("botOwner"))).Result; if (!Context.User.Id.ToString().Equals(botOwner.Id.ToString())) { - await ReplyAsync($"Sorry, only the botowner can do this ({botOwner.Username}#{botOwner.Discriminator})"); + await ReplyAsync( + $"Sorry, only the botowner can do this ({botOwner.Username}#{botOwner.Discriminator})"); return; } _redis.StringSet("youtubeKey", key); await ReplyAsync("Apikey has been set"); } - + [Command("game", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Set the game that the bot is playing")] @@ -52,7 +54,8 @@ namespace Geekbot.net.Commands var botOwner = Context.Guild.GetUserAsync(ulong.Parse(_redis.StringGet("botOwner"))).Result; if (!Context.User.Id.ToString().Equals(botOwner.Id.ToString())) { - await ReplyAsync($"Sorry, only the botowner can do this ({botOwner.Username}#{botOwner.Discriminator})"); + await ReplyAsync( + $"Sorry, only the botowner can do this ({botOwner.Username}#{botOwner.Discriminator})"); return; } @@ -61,7 +64,7 @@ namespace Geekbot.net.Commands _logger.Information($"[Geekbot] Changed game to {key}"); await ReplyAsync($"Now Playing {key}"); } - + [Command("popuserrepo", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Populate user cache")] @@ -83,6 +86,7 @@ namespace Geekbot.net.Commands $"Sorry, only the botowner can do this"); return; } + var success = 0; var failed = 0; try @@ -98,12 +102,15 @@ namespace Geekbot.net.Commands var inc = succeded ? success++ : failed++; } } + _logger.Warning("[UserRepository] Finished Updating User Repositry"); - await ReplyAsync($"Successfully Populated User Repository with {success} Users in {_client.Guilds.Count} Guilds (Failed: {failed})"); + await ReplyAsync( + $"Successfully Populated User Repository with {success} Users in {_client.Guilds.Count} Guilds (Failed: {failed})"); } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context, "Couldn't complete User Repository, see console for more info"); + _errorHandler.HandleCommandException(e, Context, + "Couldn't complete User Repository, see console for more info"); } } } diff --git a/Geekbot.net/Commands/Pokedex.cs b/Geekbot.net/Commands/Pokedex.cs index b187841..2b43693 100644 --- a/Geekbot.net/Commands/Pokedex.cs +++ b/Geekbot.net/Commands/Pokedex.cs @@ -5,14 +5,13 @@ using Discord; using Discord.Commands; using Geekbot.net.Lib; using PokeAPI; -using Serilog; namespace Geekbot.net.Commands { public class Pokedex : ModuleBase { private readonly IErrorHandler _errorHandler; - + public Pokedex(IErrorHandler errorHandler) { _errorHandler = errorHandler; @@ -36,6 +35,7 @@ namespace Geekbot.net.Commands await ReplyAsync("I couldn't find that pokemon :confused:"); return; } + var embed = await pokemonEmbedBuilder(pokemon); await ReplyAsync("", false, embed.Build()); } @@ -52,8 +52,10 @@ namespace Geekbot.net.Commands eb.Title = $"#{pokemon.ID} {toUpper(pokemon.Name)}"; eb.Description = species.FlavorTexts[1].FlavorText; eb.ThumbnailUrl = pokemon.Sprites.FrontMale ?? pokemon.Sprites.FrontFemale; - eb.AddInlineField(getSingularOrPlural(pokemon.Types.Length, "Type"), string.Join(", ", pokemon.Types.Select(t => toUpper(t.Type.Name)))); - eb.AddInlineField(getSingularOrPlural(pokemon.Abilities.Length, "Ability"), string.Join(", ", pokemon.Abilities.Select(t => toUpper(t.Ability.Name)))); + eb.AddInlineField(getSingularOrPlural(pokemon.Types.Length, "Type"), + string.Join(", ", pokemon.Types.Select(t => toUpper(t.Type.Name)))); + eb.AddInlineField(getSingularOrPlural(pokemon.Abilities.Length, "Ability"), + string.Join(", ", pokemon.Abilities.Select(t => toUpper(t.Ability.Name)))); eb.AddInlineField("Height", pokemon.Height); eb.AddInlineField("Weight", pokemon.Mass); return eb; @@ -61,22 +63,14 @@ namespace Geekbot.net.Commands private string getSingularOrPlural(int lenght, string word) { - if (lenght == 1) - { - return word; - } - return word.EndsWith("y") ? $"{word.Remove(word.Length-1)}ies" : $"{word}s"; + if (lenght == 1) return word; + return word.EndsWith("y") ? $"{word.Remove(word.Length - 1)}ies" : $"{word}s"; } - + private string toUpper(string s) { - if (string.IsNullOrEmpty(s)) - { - return string.Empty; - } + if (string.IsNullOrEmpty(s)) return string.Empty; return char.ToUpper(s[0]) + s.Substring(1); } - - } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Poll.cs b/Geekbot.net/Commands/Poll.cs index ae2ae77..51b6742 100644 --- a/Geekbot.net/Commands/Poll.cs +++ b/Geekbot.net/Commands/Poll.cs @@ -14,12 +14,13 @@ namespace Geekbot.net.Commands [Group("poll")] public class Poll : ModuleBase { + private readonly IEmojiConverter _emojiConverter; private readonly IErrorHandler _errorHandler; private readonly IDatabase _redis; - private readonly IEmojiConverter _emojiConverter; private readonly IUserRepository _userRepository; - public Poll(IErrorHandler errorHandler, IDatabase redis, IEmojiConverter emojiConverter, IUserRepository userRepository) + public Poll(IErrorHandler errorHandler, IDatabase redis, IEmojiConverter emojiConverter, + IUserRepository userRepository) { _errorHandler = errorHandler; _redis = redis; @@ -41,6 +42,7 @@ namespace Geekbot.net.Commands "There is no poll in this channel ongoing at the moment\r\nYou can create one with `!poll create question;option1;option2;option3`"); return; } + await ReplyAsync("There is a poll running at the moment"); } catch (Exception e) @@ -48,11 +50,12 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } - + [Command("create", RunMode = RunMode.Async)] [Remarks(CommandCategories.Helpers)] [Summary("Create a poll")] - public async Task Create([Remainder, Summary("question;option1;option2")] string rawPollString) + public async Task Create([Remainder] [Summary("question;option1;option2")] + string rawPollString) { try { @@ -62,6 +65,7 @@ namespace Geekbot.net.Commands await ReplyAsync("You have not finished you last poll yet. To finish it use `!poll end`"); return; } + var pollList = rawPollString.Split(';').ToList(); if (pollList.Count <= 2) { @@ -88,7 +92,7 @@ namespace Geekbot.net.Commands pollMessage.AddReactionAsync(new Emoji(_emojiConverter.numberToEmoji(i))); i++; }); - var poll = new PollData() + var poll = new PollData { Creator = Context.User.Id, MessageId = pollMessage.Id, @@ -97,14 +101,14 @@ namespace Geekbot.net.Commands Options = pollList }; var pollJson = JsonConvert.SerializeObject(poll); - _redis.HashSet($"{Context.Guild.Id}:Polls", new HashEntry[] {new HashEntry(Context.Channel.Id, pollJson)}); + _redis.HashSet($"{Context.Guild.Id}:Polls", new[] {new HashEntry(Context.Channel.Id, pollJson)}); } catch (Exception e) { _errorHandler.HandleCommandException(e, Context); } } - + [Command("end", RunMode = RunMode.Async)] [Remarks(CommandCategories.Helpers)] [Summary("End the current poll")] @@ -118,18 +122,16 @@ namespace Geekbot.net.Commands await ReplyAsync("There is no ongoing poll at the moment"); return; } + var results = await getPollResults(currentPoll); var sb = new StringBuilder(); sb.AppendLine("**Poll Results**"); sb.AppendLine(currentPoll.Question); - foreach (var result in results) - { - sb.AppendLine($"{result.VoteCount} - {result.Option}"); - } + foreach (var result in results) sb.AppendLine($"{result.VoteCount} - {result.Option}"); await ReplyAsync(sb.ToString()); currentPoll.IsFinshed = true; var pollJson = JsonConvert.SerializeObject(currentPoll); - _redis.HashSet($"{Context.Guild.Id}:Polls", new HashEntry[] {new HashEntry(Context.Channel.Id, pollJson)}); + _redis.HashSet($"{Context.Guild.Id}:Polls", new[] {new HashEntry(Context.Channel.Id, pollJson)}); } catch (Exception e) { @@ -144,7 +146,7 @@ namespace Geekbot.net.Commands var currentPoll = _redis.HashGet($"{Context.Guild.Id}:Polls", Context.Channel.Id); return JsonConvert.DeserializeObject(currentPoll.ToString()); } - catch + catch { return new PollData(); } @@ -152,14 +154,13 @@ namespace Geekbot.net.Commands private async Task> getPollResults(PollData poll) { - var message = (IUserMessage)(await Context.Channel.GetMessageAsync(poll.MessageId)); + var message = (IUserMessage) await Context.Channel.GetMessageAsync(poll.MessageId); var results = new List(); foreach (var r in message.Reactions) - { try { var option = int.Parse(r.Key.Name.ToCharArray()[0].ToString()); - var result = new PollResult() + var result = new PollResult { Option = poll.Options[option - 1], VoteCount = r.Value.ReactionCount @@ -167,8 +168,8 @@ namespace Geekbot.net.Commands results.Add(result); } catch {} - } - results.Sort((x,y) => y.VoteCount.CompareTo(x.VoteCount)); + + results.Sort((x, y) => y.VoteCount.CompareTo(x.VoteCount)); return results; } @@ -180,7 +181,7 @@ namespace Geekbot.net.Commands public string Question { get; set; } public List Options { get; set; } } - + private class PollResult { public string Option { get; set; } diff --git a/Geekbot.net/Commands/Quote.cs b/Geekbot.net/Commands/Quote.cs index d6eae26..5b7e2ee 100644 --- a/Geekbot.net/Commands/Quote.cs +++ b/Geekbot.net/Commands/Quote.cs @@ -1,12 +1,10 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; using Newtonsoft.Json; -using Serilog; using StackExchange.Redis; namespace Geekbot.net.Commands @@ -14,23 +12,21 @@ namespace Geekbot.net.Commands [Group("quote")] public class Quote : ModuleBase { - private readonly IDatabase redis; - private readonly ILogger logger; private readonly IErrorHandler errorHandler; - - public Quote(IDatabase redis, ILogger logger, IErrorHandler errorHandler) + private readonly IDatabase redis; + + public Quote(IDatabase redis, IErrorHandler errorHandler) { this.redis = redis; - this.logger = logger; this.errorHandler = errorHandler; } - [Command()] + [Command] [Remarks(CommandCategories.Quotes)] [Summary("Return a random quoute from the database")] public async Task getRandomQuote() { - var randomQuote = redis.SetRandomMember($"{Context.Guild.Id}:Quotes"); + var randomQuote = redis.SetRandomMember($"{Context.Guild.Id}:Quotes"); try { var quote = JsonConvert.DeserializeObject(randomQuote); @@ -42,7 +38,7 @@ namespace Geekbot.net.Commands errorHandler.HandleCommandException(e, Context, "Whoops, seems like the quote was to edgy to return"); } } - + [Command("save")] [Remarks(CommandCategories.Quotes)] [Summary("Save a quote from the last sent message by @user")] @@ -55,11 +51,13 @@ namespace Geekbot.net.Commands await ReplyAsync("You can't save your own quotes..."); return; } + if (user.IsBot) { await ReplyAsync("You can't save quotes by a bot..."); return; } + var lastMessage = await getLastMessageByUser(user); var quote = createQuoteObject(lastMessage); var quoteStore = JsonConvert.SerializeObject(quote); @@ -69,10 +67,11 @@ namespace Geekbot.net.Commands } catch (Exception e) { - errorHandler.HandleCommandException(e, Context, "I counldn't find a quote from that user :disappointed:"); + errorHandler.HandleCommandException(e, Context, + "I counldn't find a quote from that user :disappointed:"); } } - + [Command("save")] [Remarks(CommandCategories.Quotes)] [Summary("Save a quote from a message id")] @@ -86,24 +85,26 @@ namespace Geekbot.net.Commands await ReplyAsync("You can't save your own quotes..."); return; } + if (message.Author.IsBot) { await ReplyAsync("You can't save quotes by a bot..."); return; } + var quote = createQuoteObject(message); var quoteStore = JsonConvert.SerializeObject(quote); redis.SetAdd($"{Context.Guild.Id}:Quotes", quoteStore); var embed = quoteBuilder(quote); await ReplyAsync("**Quote Added**", false, embed.Build()); - } catch (Exception e) { - errorHandler.HandleCommandException(e, Context, "I couldn't find a message with that id :disappointed:"); + errorHandler.HandleCommandException(e, Context, + "I couldn't find a message with that id :disappointed:"); } } - + [Command("make")] [Remarks(CommandCategories.Quotes)] [Summary("Create a quote from the last sent message by @user")] @@ -118,10 +119,11 @@ namespace Geekbot.net.Commands } catch (Exception e) { - errorHandler.HandleCommandException(e, Context, "I counldn't find a quote from that user :disappointed:"); + errorHandler.HandleCommandException(e, Context, + "I counldn't find a quote from that user :disappointed:"); } } - + [Command("make")] [Remarks(CommandCategories.Quotes)] [Summary("Create a quote from a message id")] @@ -136,21 +138,22 @@ namespace Geekbot.net.Commands } catch (Exception e) { - errorHandler.HandleCommandException(e, Context, "I couldn't find a message with that id :disappointed:"); + errorHandler.HandleCommandException(e, Context, + "I couldn't find a message with that id :disappointed:"); } } private async Task getLastMessageByUser(IUser user) { - Task> list = Context.Channel.GetMessagesAsync().Flatten(); + var list = Context.Channel.GetMessagesAsync().Flatten(); await list; return list.Result - .First(msg => msg.Author.Id == user.Id - && msg.Embeds.Count == 0 - && msg.Id != Context.Message.Id - && !msg.Content.ToLower().StartsWith("!")); + .First(msg => msg.Author.Id == user.Id + && msg.Embeds.Count == 0 + && msg.Id != Context.Message.Id + && !msg.Content.ToLower().StartsWith("!")); } - + private EmbedBuilder quoteBuilder(QuoteObject quote) { var user = Context.Client.GetUserAsync(quote.userId).Result; @@ -159,10 +162,7 @@ namespace Geekbot.net.Commands eb.Title = $"{user.Username} @ {quote.time.Day}.{quote.time.Month}.{quote.time.Year}"; eb.Description = quote.quote; eb.ThumbnailUrl = user.GetAvatarUrl(); - if (quote.image != null) - { - eb.ImageUrl = quote.image; - } + if (quote.image != null) eb.ImageUrl = quote.image; return eb; } @@ -177,7 +177,8 @@ namespace Geekbot.net.Commands { image = null; } - return new QuoteObject() + + return new QuoteObject { userId = message.Author.Id, time = message.Timestamp.DateTime, @@ -186,8 +187,9 @@ namespace Geekbot.net.Commands }; } } - - public class QuoteObject { + + public class QuoteObject + { public ulong userId { get; set; } public string quote { get; set; } public DateTime time { get; set; } diff --git a/Geekbot.net/Commands/RandomAnimals.cs b/Geekbot.net/Commands/RandomAnimals.cs index 7d1f723..29930eb 100644 --- a/Geekbot.net/Commands/RandomAnimals.cs +++ b/Geekbot.net/Commands/RandomAnimals.cs @@ -8,12 +8,12 @@ namespace Geekbot.net.Commands public class RandomAnimals : ModuleBase { private readonly IMediaProvider _mediaProvider; - + public RandomAnimals(IMediaProvider mediaProvider) { _mediaProvider = mediaProvider; } - + [Command("panda", RunMode = RunMode.Async)] [Remarks(CommandCategories.Randomness)] [Summary("Get a random panda image")] @@ -21,7 +21,7 @@ namespace Geekbot.net.Commands { await ReplyAsync(_mediaProvider.getPanda()); } - + [Command("croissant", RunMode = RunMode.Async)] [Alias("gipfeli")] [Remarks(CommandCategories.Randomness)] @@ -30,7 +30,7 @@ namespace Geekbot.net.Commands { await ReplyAsync(_mediaProvider.getCrossant()); } - + [Command("pumpkin", RunMode = RunMode.Async)] [Remarks(CommandCategories.Randomness)] [Summary("Get a random pumpkin image")] @@ -38,7 +38,7 @@ namespace Geekbot.net.Commands { await ReplyAsync(_mediaProvider.getPumpkin()); } - + [Command("squirrel", RunMode = RunMode.Async)] [Remarks(CommandCategories.Randomness)] [Summary("Get a random squirrel image")] @@ -46,7 +46,7 @@ namespace Geekbot.net.Commands { await ReplyAsync(_mediaProvider.getSquirrel()); } - + [Command("turtle", RunMode = RunMode.Async)] [Remarks(CommandCategories.Randomness)] [Summary("Get a random turtle image")] diff --git a/Geekbot.net/Commands/Rank.cs b/Geekbot.net/Commands/Rank.cs index 2c232f9..4052d4c 100644 --- a/Geekbot.net/Commands/Rank.cs +++ b/Geekbot.net/Commands/Rank.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; -using Discord; using Discord.Commands; using Geekbot.net.Lib; using Serilog; @@ -13,13 +12,14 @@ namespace Geekbot.net.Commands { public class Rank : ModuleBase { - private readonly IDatabase _redis; + private readonly IEmojiConverter _emojiConverter; private readonly IErrorHandler _errorHandler; private readonly ILogger _logger; + private readonly IDatabase _redis; private readonly IUserRepository _userRepository; - private readonly IEmojiConverter _emojiConverter; - - public Rank(IDatabase redis, IErrorHandler errorHandler, ILogger logger, IUserRepository userRepository, IEmojiConverter emojiConverter) + + public Rank(IDatabase redis, IErrorHandler errorHandler, ILogger logger, IUserRepository userRepository, + IEmojiConverter emojiConverter) { _redis = redis; _errorHandler = errorHandler; @@ -27,11 +27,12 @@ namespace Geekbot.net.Commands _userRepository = userRepository; _emojiConverter = emojiConverter; } - + [Command("rank", RunMode = RunMode.Async)] [Remarks(CommandCategories.Statistics)] [Summary("get user top 10 in messages or karma")] - public async Task RankCmd([Summary("type")] string typeUnformated = "messages", [Summary("amount")] int amount = 10) + public async Task RankCmd([Summary("type")] string typeUnformated = "messages", + [Summary("amount")] int amount = 10) { try { @@ -42,7 +43,7 @@ namespace Geekbot.net.Commands await ReplyAsync("Valid types are '`messages`' '`karma`', '`rolls`'"); return; } - + var replyBuilder = new StringBuilder(); if (amount > 20) @@ -50,7 +51,7 @@ namespace Geekbot.net.Commands replyBuilder.AppendLine(":warning: Limiting to 20"); amount = 20; } - + var messageList = _redis.HashGetAll($"{Context.Guild.Id}:{type}"); var sortedList = messageList.OrderByDescending(e => e.Value).ToList(); var guildMessages = (int) sortedList.First().Value; @@ -64,10 +65,10 @@ namespace Geekbot.net.Commands if (listLimiter > amount) break; try { - var guildUser = _userRepository.Get((ulong)user.Name); + var guildUser = _userRepository.Get((ulong) user.Name); if (guildUser.Username != null) { - highscoreUsers.Add(new RankUserPolyfill() + highscoreUsers.Add(new RankUserPolyfill { Username = guildUser.Username, Discriminator = guildUser.Discriminator @@ -75,21 +76,21 @@ namespace Geekbot.net.Commands } else { - highscoreUsers.Add(new RankUserPolyfill() + highscoreUsers.Add(new RankUserPolyfill { Id = user.Name }, (int) user.Value); failedToRetrieveUser = true; } + listLimiter++; } catch (Exception e) { _logger.Warning(e, $"Could not retrieve user {user.Name}"); } - } - + if (failedToRetrieveUser) replyBuilder.AppendLine(":warning: Couldn't get all userdata\n"); replyBuilder.AppendLine($":bar_chart: **{type} Highscore for {Context.Guild.Name}**"); var highscorePlace = 1; @@ -114,13 +115,14 @@ namespace Geekbot.net.Commands break; case "Rolls": replyBuilder.Append($" - {user.Value} Guessed"); - break; + break; } replyBuilder.Append("\n"); - + highscorePlace++; } + await ReplyAsync(replyBuilder.ToString()); } catch (Exception e) @@ -129,8 +131,8 @@ namespace Geekbot.net.Commands } } } - - class RankUserPolyfill + + internal class RankUserPolyfill { public string Username { get; set; } public string Discriminator { get; set; } diff --git a/Geekbot.net/Commands/Role.cs b/Geekbot.net/Commands/Role.cs index f40ccf1..77e917f 100644 --- a/Geekbot.net/Commands/Role.cs +++ b/Geekbot.net/Commands/Role.cs @@ -2,7 +2,6 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using AngleSharp; using Discord; using Discord.Commands; using Discord.Net; @@ -16,13 +15,13 @@ namespace Geekbot.net.Commands { private readonly IErrorHandler _errorHandler; private readonly IDatabase _redis; - + public Role(IErrorHandler errorHandler, IDatabase redis) { _errorHandler = errorHandler; _redis = redis; } - + [Command(RunMode = RunMode.Async)] [Remarks(CommandCategories.Helpers)] [Summary("Get a list of all available roles.")] @@ -36,13 +35,11 @@ namespace Geekbot.net.Commands await ReplyAsync("There are no roles configured for this server"); return; } + var sb = new StringBuilder(); sb.AppendLine($"**Self Service Roles on {Context.Guild.Name}**"); sb.AppendLine("To get a role, use `!role name`"); - foreach (var role in roles) - { - sb.AppendLine($"- {role.Name}"); - } + foreach (var role in roles) sb.AppendLine($"- {role.Name}"); await ReplyAsync(sb.ToString()); } catch (Exception e) @@ -69,16 +66,19 @@ namespace Geekbot.net.Commands await ReplyAsync("That role doesn't seem to exist"); return; } + if (guildUser.RoleIds.Contains(roleId)) { await guildUser.RemoveRoleAsync(role); await ReplyAsync($"Removed you from {role.Name}"); return; } + await guildUser.AddRoleAsync(role); await ReplyAsync($"Added you to {role.Name}"); return; } + await ReplyAsync("That role doesn't seem to exist"); } catch (HttpException e) @@ -104,16 +104,20 @@ namespace Geekbot.net.Commands await ReplyAsync("You can't add a role that is managed by discord"); return; } + if (role.Permissions.ManageRoles || role.Permissions.Administrator || role.Permissions.ManageGuild || role.Permissions.BanMembers || role.Permissions.KickMembers) { - await ReplyAsync("Woah, i don't think you want to add that role to self service as it contains some dangerous permissions"); + await ReplyAsync( + "Woah, i don't think you want to add that role to self service as it contains some dangerous permissions"); return; } - _redis.HashSet($"{Context.Guild.Id}:RoleWhitelist", new HashEntry[] { new HashEntry(roleName.ToLower(), role.Id.ToString()) }); + + _redis.HashSet($"{Context.Guild.Id}:RoleWhitelist", + new[] {new HashEntry(roleName.ToLower(), role.Id.ToString())}); await ReplyAsync($"Added {role.Name} to the whitelist"); } catch (Exception e) diff --git a/Geekbot.net/Commands/Roll.cs b/Geekbot.net/Commands/Roll.cs index 9d7b576..33cdf67 100644 --- a/Geekbot.net/Commands/Roll.cs +++ b/Geekbot.net/Commands/Roll.cs @@ -8,10 +8,10 @@ namespace Geekbot.net.Commands { public class Roll : ModuleBase { + private readonly IErrorHandler _errorHandler; private readonly IDatabase _redis; private readonly Random _rnd; private readonly ITranslationHandler _translation; - private readonly IErrorHandler _errorHandler; public Roll(IDatabase redis, Random RandomClient, IErrorHandler errorHandler, ITranslationHandler translation) { @@ -40,7 +40,9 @@ namespace Geekbot.net.Commands await ReplyAsync(string.Format(transDict["NoPrevGuess"], Context.Message.Author.Mention)); return; } - _redis.HashSet($"{Context.Guild.Id}:RollsPrevious", new HashEntry[]{ new HashEntry(Context.Message.Author.Id, guess), }); + + _redis.HashSet($"{Context.Guild.Id}:RollsPrevious", + new[] {new HashEntry(Context.Message.Author.Id, guess)}); await ReplyAsync(string.Format(transDict["Rolled"], Context.Message.Author.Mention, number, guess)); if (guess == number) { diff --git a/Geekbot.net/Commands/Say.cs b/Geekbot.net/Commands/Say.cs index 7ddcbbc..4c878c4 100644 --- a/Geekbot.net/Commands/Say.cs +++ b/Geekbot.net/Commands/Say.cs @@ -14,7 +14,7 @@ namespace Geekbot.net.Commands { _errorHandler = errorHandler; } - + [RequireUserPermission(GuildPermission.Administrator)] [Command("say", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] diff --git a/Geekbot.net/Commands/Ship.cs b/Geekbot.net/Commands/Ship.cs index 0b87f90..7b85eb0 100644 --- a/Geekbot.net/Commands/Ship.cs +++ b/Geekbot.net/Commands/Ship.cs @@ -9,9 +9,9 @@ namespace Geekbot.net.Commands { public class Ship : ModuleBase { + private readonly IErrorHandler _errorHandler; private readonly IDatabase _redis; private readonly Random _rnd; - private readonly IErrorHandler _errorHandler; public Ship(IDatabase redis, Random randomClient, IErrorHandler errorHandler) { @@ -87,6 +87,7 @@ namespace Geekbot.net.Commands { blocks = blocks + ":black_medium_small_square:"; } + return blocks; } } diff --git a/Geekbot.net/Commands/Stats.cs b/Geekbot.net/Commands/Stats.cs index 90e878a..67b76b9 100644 --- a/Geekbot.net/Commands/Stats.cs +++ b/Geekbot.net/Commands/Stats.cs @@ -9,10 +9,10 @@ namespace Geekbot.net.Commands { public class Stats : ModuleBase { - private readonly IDatabase _redis; private readonly IErrorHandler _errorHandler; private readonly ILevelCalc _levelCalc; - + private readonly IDatabase _redis; + public Stats(IDatabase redis, IErrorHandler errorHandler, ILevelCalc levelCalc) { _redis = redis; @@ -45,12 +45,14 @@ namespace Geekbot.net.Commands .WithIconUrl(userInfo.GetAvatarUrl()) .WithName(userInfo.Username)); eb.WithColor(new Color(221, 255, 119)); - + var karma = _redis.HashGet($"{Context.Guild.Id}:Karma", userInfo.Id.ToString()); var correctRolls = _redis.HashGet($"{Context.Guild.Id}:Rolls", userInfo.Id.ToString()); - eb.AddInlineField("Discordian Since", $"{createdAt.Day}.{createdAt.Month}.{createdAt.Year} ({age} days)") - .AddInlineField("Joined Server", $"{joinedAt.Day}.{joinedAt.Month}.{joinedAt.Year} ({joinedDayAgo} days)") + eb.AddInlineField("Discordian Since", + $"{createdAt.Day}.{createdAt.Month}.{createdAt.Year} ({age} days)") + .AddInlineField("Joined Server", + $"{joinedAt.Day}.{joinedAt.Month}.{joinedAt.Year} ({joinedDayAgo} days)") .AddInlineField("Karma", karma.ToString() ?? "0") .AddInlineField("Level", level) .AddInlineField("Messages Sent", messages) diff --git a/Geekbot.net/Commands/UrbanDictionary.cs b/Geekbot.net/Commands/UrbanDictionary.cs index 520fb2a..573b289 100644 --- a/Geekbot.net/Commands/UrbanDictionary.cs +++ b/Geekbot.net/Commands/UrbanDictionary.cs @@ -13,16 +13,16 @@ namespace Geekbot.net.Commands public class UrbanDictionary : ModuleBase { private readonly IErrorHandler _errorHandler; - + public UrbanDictionary(IErrorHandler errorHandler) { _errorHandler = errorHandler; } - + [Command("urban", RunMode = RunMode.Async)] [Remarks(CommandCategories.Helpers)] [Summary("Lookup something on urban dictionary")] - public async Task urbanDefine([Remainder, Summary("word")] string word) + public async Task urbanDefine([Remainder] [Summary("word")] string word) { try { @@ -39,23 +39,21 @@ namespace Geekbot.net.Commands await ReplyAsync("That word hasn't been defined..."); return; } + var definition = definitions.list.First(e => !string.IsNullOrWhiteSpace(e.example)); - + var eb = new EmbedBuilder(); - eb.WithAuthor(new EmbedAuthorBuilder() + eb.WithAuthor(new EmbedAuthorBuilder { Name = definition.word, Url = definition.permalink }); - eb.WithColor(new Color(239,255,0)); + eb.WithColor(new Color(239, 255, 0)); eb.Description = definition.definition; eb.AddField("Example", definition.example ?? "(no example given...)"); eb.AddInlineField("Upvotes", definition.thumbs_up); eb.AddInlineField("Downvotes", definition.thumbs_down); - if (definitions.tags.Length > 0) - { - eb.AddField("Tags", string.Join(", ", definitions.tags)); - } + if (definitions.tags.Length > 0) eb.AddField("Tags", string.Join(", ", definitions.tags)); await ReplyAsync("", false, eb.Build()); } @@ -65,14 +63,14 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } - + private class UrbanResponse { public string[] tags { get; set; } public string result_type { get; set; } public List list { get; set; } } - + private class UrbanListItem { public string definition { get; set; } diff --git a/Geekbot.net/Commands/Voice.cs b/Geekbot.net/Commands/Voice.cs index 8fc230e..242d642 100644 --- a/Geekbot.net/Commands/Voice.cs +++ b/Geekbot.net/Commands/Voice.cs @@ -1,7 +1,6 @@ using System; using System.Threading.Tasks; using Discord; -using Discord.Audio; using Discord.Commands; using Geekbot.net.Lib; @@ -9,8 +8,8 @@ namespace Geekbot.net.Commands { public class Voice : ModuleBase { - private readonly IErrorHandler _errorHandler; private readonly IAudioUtils _audioUtils; + private readonly IErrorHandler _errorHandler; public Voice(IErrorHandler errorHandler, IAudioUtils audioUtils) { @@ -42,7 +41,7 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } - + [Command("disconnect")] public async Task DisconnectChannel() { @@ -54,6 +53,7 @@ namespace Geekbot.net.Commands await Context.Channel.SendMessageAsync("I'm not in a voice channel at the moment"); return; } + await audioClient.StopAsync(); await ReplyAsync("Disconnected from channel!"); } @@ -62,7 +62,7 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } - + // [Command("play")] // public async Task play(IVoiceChannel channel = null) // { diff --git a/Geekbot.net/Commands/Youtube.cs b/Geekbot.net/Commands/Youtube.cs index 043cd3e..305052b 100644 --- a/Geekbot.net/Commands/Youtube.cs +++ b/Geekbot.net/Commands/Youtube.cs @@ -10,8 +10,8 @@ namespace Geekbot.net.Commands { public class Youtube : ModuleBase { - private readonly IDatabase _redis; private readonly IErrorHandler _errorHandler; + private readonly IDatabase _redis; public Youtube(IDatabase redis, IErrorHandler errorHandler) { diff --git a/Geekbot.net/Commands/mal.cs b/Geekbot.net/Commands/mal.cs index 261b39f..22b3d4a 100644 --- a/Geekbot.net/Commands/mal.cs +++ b/Geekbot.net/Commands/mal.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using System.Web; using Discord; using Discord.Commands; using Geekbot.net.Lib; @@ -8,19 +9,19 @@ namespace Geekbot.net.Commands { public class mal : ModuleBase { - private readonly IMalClient _malClient; private readonly IErrorHandler _errorHandler; + private readonly IMalClient _malClient; public mal(IMalClient malClient, IErrorHandler errorHandler) { _malClient = malClient; _errorHandler = errorHandler; } - + [Command("anime", RunMode = RunMode.Async)] [Remarks(CommandCategories.Helpers)] [Summary("Show Info about an Anime.")] - public async Task searchAnime([Remainder, Summary("AnimeName")] string animeName) + public async Task searchAnime([Remainder] [Summary("AnimeName")] string animeName) { try { @@ -31,11 +32,11 @@ namespace Geekbot.net.Commands { var eb = new EmbedBuilder(); - var description = System.Web.HttpUtility.HtmlDecode(anime.Synopsis) + var description = HttpUtility.HtmlDecode(anime.Synopsis) .Replace("
", "") .Replace("[i]", "*") .Replace("[/i]", "*"); - + eb.Title = anime.Title; eb.Description = description; eb.ImageUrl = anime.Image; @@ -65,11 +66,11 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } - + [Command("manga", RunMode = RunMode.Async)] [Remarks(CommandCategories.Helpers)] [Summary("Show Info about a Manga.")] - public async Task searchManga([Remainder, Summary("MangaName")] string mangaName) + public async Task searchManga([Remainder] [Summary("MangaName")] string mangaName) { try { @@ -80,11 +81,11 @@ namespace Geekbot.net.Commands { var eb = new EmbedBuilder(); - var description = System.Web.HttpUtility.HtmlDecode(manga.Synopsis) + var description = HttpUtility.HtmlDecode(manga.Synopsis) .Replace("
", "") .Replace("[i]", "*") .Replace("[/i]", "*"); - + eb.Title = manga.Title; eb.Description = description; eb.ImageUrl = manga.Image; From 19e763c2e22ff84f5cfc2040010d3febc65ffcdc Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 29 Dec 2017 03:26:05 +0100 Subject: [PATCH 090/553] Create actual google command that leaverages the google knowledge graph --- Geekbot.net/Commands/Google.cs | 102 +++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 Geekbot.net/Commands/Google.cs diff --git a/Geekbot.net/Commands/Google.cs b/Geekbot.net/Commands/Google.cs new file mode 100644 index 0000000..b10bc02 --- /dev/null +++ b/Geekbot.net/Commands/Google.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Discord.Net; +using Geekbot.net.Lib; +using Newtonsoft.Json; +using StackExchange.Redis; + +namespace Geekbot.net.Commands +{ + public class Google : ModuleBase + { + private readonly IErrorHandler _errorHandler; + private readonly IDatabase _redis; + + public Google(IErrorHandler errorHandler, IDatabase redis) + { + _errorHandler = errorHandler; + _redis = redis; + } + + [Command("google", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Helpers)] + [Summary("Google Something.")] + public async Task askGoogle([Remainder, Summary("SearchText")] string searchText) + { + try + { + using (var client = new WebClient()) + { + var apiKey = _redis.StringGet("googleGraphKey"); + if (!apiKey.HasValue) + { + await ReplyAsync("No Google API key has been set, please contact my owner"); + return; + } + + var url = new Uri($"https://kgsearch.googleapis.com/v1/entities:search?languages=en&limit=1&query={searchText}&key={apiKey}"); + var responseString = client.DownloadString(url); + var response = Utf8Json.JsonSerializer.Deserialize(responseString); + + if (!response.itemListElement.Any()) + { + await ReplyAsync("No results were found..."); + return; + } + + var data = response.itemListElement.First().result; + var eb = new EmbedBuilder(); + eb.Title = data.name; + if(!string.IsNullOrEmpty(data.description)) eb.WithDescription(data.description); + if(!string.IsNullOrEmpty(data.detailedDescription?.url)) eb.WithUrl(data.detailedDescription.url); + if(!string.IsNullOrEmpty(data.detailedDescription?.articleBody)) eb.AddField("Details", data.detailedDescription.articleBody); + if(!string.IsNullOrEmpty(data.image?.contentUrl)) eb.WithThumbnailUrl(data.image.contentUrl); + + await ReplyAsync("", false, eb.Build()); + } + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + public class GoogleKGApiResponse + { + public List itemListElement { get; set; } + + public class GoogleKGApiElement + { + public GoogleKGApiResult result { get; set; } + public double resultScore { get; set; } + } + + public class GoogleKGApiResult + { + public string name { get; set; } + public string description { get; set; } + public GoogleKGApiImage image { get; set; } + public GoogleKGApiDetailed detailedDescription { get; set; } + } + + public class GoogleKGApiImage + { + public string contentUrl { get; set; } + public string url { get; set; } + } + + public class GoogleKGApiDetailed + { + public string articleBody { get; set; } + public string url { get; set; } + public string license { get; set; } + } + } + } +} \ No newline at end of file From 3d43d29ee8bdfcab03ddfb36fbc75586eed49b7d Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 1 Jan 2018 17:42:18 +0100 Subject: [PATCH 091/553] Add gitlab-ci.yml --- .gitlab-ci.yml | 12 ++++++++++++ readme.md | 2 ++ 2 files changed, 14 insertions(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..0277327 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,12 @@ +image: microsoft/dotnet:2.0.3-sdk-stretch + +before_script: + - set -e + - set -u + - set -o pipefail + + +build: + script: + - dotnet restore + - dotnet build diff --git a/readme.md b/readme.md index 90d91fa..4c828d7 100644 --- a/readme.md +++ b/readme.md @@ -1,3 +1,5 @@ +[![pipeline status](https://git.boerlage.me/open/Geekbot.net/badges/master/pipeline.svg)](https://git.boerlage.me/open/Geekbot.net/commits/master) + # [Geekbot.net](https://geekbot.pizzaandcoffee.rocks/) A General Purpose Discord Bot written in DotNet Core. From a1de3538cd968a4b9227be4e46dac59364f40157 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 7 Jan 2018 23:26:20 +0100 Subject: [PATCH 092/553] Add !gdq command --- Geekbot.net/Commands/Gdq.cs | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 Geekbot.net/Commands/Gdq.cs diff --git a/Geekbot.net/Commands/Gdq.cs b/Geekbot.net/Commands/Gdq.cs new file mode 100644 index 0000000..b191d6c --- /dev/null +++ b/Geekbot.net/Commands/Gdq.cs @@ -0,0 +1,41 @@ +using System; +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Geekbot.net.Lib; + +namespace Geekbot.net.Commands +{ + public class Gdq : ModuleBase + { + private readonly IErrorHandler _errorHandler; + + public Gdq(IErrorHandler errorHandler) + { + _errorHandler = errorHandler; + } + + [Command("gdq", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Games)] + [Summary("Get a quote from the GDQ donation generator.")] + public async Task getQuote() + { + try + { + using (var client = new WebClient()) + { + var url = new Uri("http://taskinoz.com/gdq/api/"); + var response = client.DownloadString(url); + + await ReplyAsync(response); + } + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + } +} \ No newline at end of file From a52982cbcdb3e555665e0551ab713a7d73fe7e53 Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 8 Jan 2018 00:55:01 +0100 Subject: [PATCH 093/553] Add trump quotes (!trump) --- Geekbot.net/Commands/Trump.cs | 73 +++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 Geekbot.net/Commands/Trump.cs diff --git a/Geekbot.net/Commands/Trump.cs b/Geekbot.net/Commands/Trump.cs new file mode 100644 index 0000000..ad87f51 --- /dev/null +++ b/Geekbot.net/Commands/Trump.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Geekbot.net.Lib; + +namespace Geekbot.net.Commands +{ + public class Trump : ModuleBase + { + private readonly IErrorHandler _errorHandler; + + public Trump(IErrorHandler errorHandler) + { + _errorHandler = errorHandler; + } + + [Command("trump", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Games)] + [Summary("Get a trump quote")] + public async Task getQuote() + { + try + { + using (var client = new WebClient()) + { + var url = new Uri("https://api.tronalddump.io/random/quote"); + var response = client.DownloadString(url); + var quote = Utf8Json.JsonSerializer.Deserialize(response); + + var eb = new EmbedBuilder(); + eb.WithTitle($"Trump @ {quote.appeared_at.Day}.{quote.appeared_at.Month}.{quote.appeared_at.Year}"); + eb.WithDescription(quote.value); + eb.WithUrl(quote._embedded.source.FirstOrDefault()?.url.ToString()); + eb.WithColor(new Color(143, 167, 232)); + await ReplyAsync("", false, eb.Build()); + } + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + public class TrumpQuote + { + public DateTimeOffset appeared_at { get; set; } + public DateTimeOffset created_at { get; set; } + public string quote_id { get; set; } + public DateTimeOffset updated_at { get; set; } + public string value { get; set; } + public Embedded _embedded { get; set; } + + public class Embedded + { + public List source { get; set; } + + public class Source + { + public DateTimeOffset created_at { get; set; } + public string filename { get; set; } + public string quote_source_id { get; set; } + public string remarks { get; set; } + public DateTimeOffset updated_at { get; set; } + public Uri url { get; set; } + } + } + } + } +} \ No newline at end of file From 1ee627a915dd6018c2cd629698d378e6d5a5a555 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 11 Jan 2018 00:16:04 +0100 Subject: [PATCH 094/553] Groundwork for playing youtube videos to voice --- Geekbot.net/Commands/Voice.cs | 46 ++++++++++++-------- Geekbot.net/Lib/AudioClientCache.cs | 66 ++++++++++++++++++++++++++++- readme.md | 1 + 3 files changed, 93 insertions(+), 20 deletions(-) diff --git a/Geekbot.net/Commands/Voice.cs b/Geekbot.net/Commands/Voice.cs index 242d642..6fbcaa9 100644 --- a/Geekbot.net/Commands/Voice.cs +++ b/Geekbot.net/Commands/Voice.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using System.Threading.Tasks; using Discord; using Discord.Commands; @@ -63,23 +64,32 @@ namespace Geekbot.net.Commands } } -// [Command("play")] -// public async Task play(IVoiceChannel channel = null) -// { -// try -// { -// var audioClient = _audioUtils.GetAudioClient(Context.Guild.Id); -// if (audioClient == null) -// { -// await Context.Channel.SendMessageAsync("I'm not in a voice channel at the moment"); -// return; -// } -// -// } -// catch (Exception e) -// { -// _errorHandler.HandleCommandException(e, Context); -// } -// } + [Command("ytplay")] + public async Task ytplay(string url) + { + try + { + if (!url.Contains("youtube")) + { + await ReplyAsync("I can only play youtube videos"); + return; + } + var audioClient = _audioUtils.GetAudioClient(Context.Guild.Id); + if (audioClient == null) + { + await ReplyAsync("I'm not in a voice channel at the moment"); + return; + } + var ffmpeg = _audioUtils.CreateStreamFromYoutube(url, Context.Guild.Id); + var output = ffmpeg.StandardOutput.BaseStream; + var discord = audioClient.CreatePCMStream(Discord.Audio.AudioApplication.Mixed); + await output.CopyToAsync(discord); + await discord.FlushAsync(); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } } } \ No newline at end of file diff --git a/Geekbot.net/Lib/AudioClientCache.cs b/Geekbot.net/Lib/AudioClientCache.cs index cf94c38..0869525 100644 --- a/Geekbot.net/Lib/AudioClientCache.cs +++ b/Geekbot.net/Lib/AudioClientCache.cs @@ -1,17 +1,28 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Security.Cryptography; using Discord.Audio; +using Discord.Net; namespace Geekbot.net.Lib { public class AudioUtils : IAudioUtils { + private string _tempFolderPath; private Dictionary _audioClients; public AudioUtils() { _audioClients = new Dictionary(); + _tempFolderPath = Path.GetFullPath("./temp/"); + if (!Directory.Exists(_tempFolderPath)) + { + Directory.CreateDirectory(_tempFolderPath); + } } - + public IAudioClient GetAudioClient(ulong guildId) { return _audioClients[guildId]; @@ -21,11 +32,62 @@ namespace Geekbot.net.Lib { _audioClients[guildId] = client; } + + public Process CreateStreamFromFile(string path) + { + var ffmpeg = new ProcessStartInfo + { + FileName = "ffmpeg", + Arguments = $"-i {path} -ac 2 -f s16le -ar 48000 pipe:1", + UseShellExecute = false, + RedirectStandardOutput = true, + }; + return Process.Start(ffmpeg); + } + + public Process CreateStreamFromYoutube(string url, ulong guildId) + { + var ytdlMediaUrl = GetYoutubeMediaUrl(url); + DownloadMediaUrl(ytdlMediaUrl, guildId); + return CreateStreamFromFile($"{_tempFolderPath}\\{guildId}.mp3"); + } + + private string GetYoutubeMediaUrl(string url) + { + var ytdl = new ProcessStartInfo() + { + FileName = "youtube-dl", + Arguments = $"-f bestaudio -g {url}", + UseShellExecute = false, + RedirectStandardOutput = true + }; + var output = Process.Start(ytdl).StandardOutput.ReadToEnd(); + if (string.IsNullOrWhiteSpace(output)) + { + throw new System.Exception("Could not get Youtube Media URL"); + } + return output; + } + + private void DownloadMediaUrl(string url, ulong guildId) + { + var ffmpeg = new ProcessStartInfo + { + FileName = "ffmpeg", + Arguments = $"-re -i \"${url}\" -c:a mp3 -b:a 256k {_tempFolderPath}\\{guildId}.mp3", + UseShellExecute = false, + RedirectStandardOutput = true, + }; + Process.Start(ffmpeg).WaitForExit(); + return; + } } public interface IAudioUtils { IAudioClient GetAudioClient(ulong guildId); void StoreAudioClient(ulong guildId, IAudioClient client); + Process CreateStreamFromFile(string path); + Process CreateStreamFromYoutube(string url, ulong guildId); } } \ No newline at end of file diff --git a/readme.md b/readme.md index 4c828d7..be5ba0a 100644 --- a/readme.md +++ b/readme.md @@ -11,6 +11,7 @@ You can invite Geekbot to your server with [this link](https://discordapp.com/oa * DotNet Core 2 * Redis * Discord.net +* ffmpeg ## Running From ceff1cc3b929541b2f4a93acbf67d577f246f475 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Thu, 11 Jan 2018 01:16:30 +0100 Subject: [PATCH 095/553] Finish experimental version of voice utils --- .gitignore | 1 + Geekbot.net/Commands/Voice.cs | 7 ++++++ Geekbot.net/Lib/AudioClientCache.cs | 37 +++++++++++++++++++---------- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 2e43789..c99d9e6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ Geekbot.net/bin Geekbot.net/obj +Geekbot.net/tmp/ Tests/bin Tests/obj Backup/ diff --git a/Geekbot.net/Commands/Voice.cs b/Geekbot.net/Commands/Voice.cs index 6fbcaa9..cda1f8b 100644 --- a/Geekbot.net/Commands/Voice.cs +++ b/Geekbot.net/Commands/Voice.cs @@ -57,10 +57,12 @@ namespace Geekbot.net.Commands await audioClient.StopAsync(); await ReplyAsync("Disconnected from channel!"); + _audioUtils.Cleanup(Context.Guild.Id); } catch (Exception e) { _errorHandler.HandleCommandException(e, Context); + _audioUtils.Cleanup(Context.Guild.Id); } } @@ -80,15 +82,20 @@ namespace Geekbot.net.Commands await ReplyAsync("I'm not in a voice channel at the moment"); return; } + + var message = await Context.Channel.SendMessageAsync("Just a second, i'm still a bit slow at this"); var ffmpeg = _audioUtils.CreateStreamFromYoutube(url, Context.Guild.Id); var output = ffmpeg.StandardOutput.BaseStream; + await message.ModifyAsync(msg => msg.Content = "**Playing!** Please note that this feature is experimental"); var discord = audioClient.CreatePCMStream(Discord.Audio.AudioApplication.Mixed); await output.CopyToAsync(discord); await discord.FlushAsync(); + _audioUtils.Cleanup(Context.Guild.Id); } catch (Exception e) { _errorHandler.HandleCommandException(e, Context); + _audioUtils.Cleanup(Context.Guild.Id); } } } diff --git a/Geekbot.net/Lib/AudioClientCache.cs b/Geekbot.net/Lib/AudioClientCache.cs index 0869525..d43b98a 100644 --- a/Geekbot.net/Lib/AudioClientCache.cs +++ b/Geekbot.net/Lib/AudioClientCache.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Net; using System.Security.Cryptography; using Discord.Audio; using Discord.Net; @@ -16,11 +17,12 @@ namespace Geekbot.net.Lib public AudioUtils() { _audioClients = new Dictionary(); - _tempFolderPath = Path.GetFullPath("./temp/"); - if (!Directory.Exists(_tempFolderPath)) + _tempFolderPath = Path.GetFullPath("./tmp/"); + if (Directory.Exists(_tempFolderPath)) { - Directory.CreateDirectory(_tempFolderPath); + Directory.Delete(_tempFolderPath, true); } + Directory.CreateDirectory(_tempFolderPath); } public IAudioClient GetAudioClient(ulong guildId) @@ -49,7 +51,12 @@ namespace Geekbot.net.Lib { var ytdlMediaUrl = GetYoutubeMediaUrl(url); DownloadMediaUrl(ytdlMediaUrl, guildId); - return CreateStreamFromFile($"{_tempFolderPath}\\{guildId}.mp3"); + return CreateStreamFromFile($"{_tempFolderPath}{guildId}"); + } + + public void Cleanup(ulong guildId) + { + File.Delete($"{_tempFolderPath}{guildId}"); } private string GetYoutubeMediaUrl(string url) @@ -64,21 +71,26 @@ namespace Geekbot.net.Lib var output = Process.Start(ytdl).StandardOutput.ReadToEnd(); if (string.IsNullOrWhiteSpace(output)) { - throw new System.Exception("Could not get Youtube Media URL"); + throw new Exception("Could not get Youtube Media URL"); } return output; } private void DownloadMediaUrl(string url, ulong guildId) { - var ffmpeg = new ProcessStartInfo + using (var web = new WebClient()) { - FileName = "ffmpeg", - Arguments = $"-re -i \"${url}\" -c:a mp3 -b:a 256k {_tempFolderPath}\\{guildId}.mp3", - UseShellExecute = false, - RedirectStandardOutput = true, - }; - Process.Start(ffmpeg).WaitForExit(); + web.DownloadFile(url, $"{_tempFolderPath}{guildId}"); + } +// var ffmpeg = new ProcessStartInfo +// { +// FileName = "ffmpeg", +// Arguments = $"-i \"{_tempFolderPath}{guildId}\" -c:a mp3 -b:a 256k {_tempFolderPath}{guildId}.mp3", +// UseShellExecute = false, +// RedirectStandardOutput = true, +// }; +// Process.Start(ffmpeg).WaitForExit(); +// File.Delete($"{_tempFolderPath}{guildId}"); return; } } @@ -89,5 +101,6 @@ namespace Geekbot.net.Lib void StoreAudioClient(ulong guildId, IAudioClient client); Process CreateStreamFromFile(string path); Process CreateStreamFromYoutube(string url, ulong guildId); + void Cleanup(ulong guildId); } } \ No newline at end of file From 70e4cf249f3dd572781618a251331c3be3c003ca Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 15 Jan 2018 18:40:54 +0100 Subject: [PATCH 096/553] Add Auto Deployment --- .gitlab-ci.yml | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0277327..ecbead2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,12 +1,36 @@ -image: microsoft/dotnet:2.0.3-sdk-stretch +stages: + - build + - deploy before_script: - set -e - set -u - set -o pipefail - build: + stage: build + image: microsoft/dotnet:2.0.3-sdk-stretch + artifacts: + expire_in: 1h + paths: + - Geekbot.net/Binaries/ script: - dotnet restore - - dotnet build + - dotnet publish --configuration Release -o Binaries ./ + +deploy: + stage: deploy + image: instrumentisto/rsync-ssh + only: + - master + dependencies: + - build + before_script: + - eval $(ssh-agent -s) + - mkdir -p ~/.ssh + - '[[ -f /.dockerenv ]] && echo -e "Host *\n StrictHostKeyChecking no" > ~/.ssh/config' + - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null + - chmod 700 ~/.ssh + script: + - rsync -rav -e "ssh -p 65432" ./Geekbot.net/Binaries/* www-data@31.220.42.224:$DEPPATH + - ssh -p 65432 www-data@31.220.42.224 "sudo systemctl restart geekbot.service" \ No newline at end of file From b6d7e76bdbb0a69426733abb4d90e4cdb836d264 Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 15 Jan 2018 19:31:49 +0100 Subject: [PATCH 097/553] Don't log to console if running from folder containing 'deploy' in name --- Geekbot.net/Lib/LoggerFactory.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Geekbot.net/Lib/LoggerFactory.cs b/Geekbot.net/Lib/LoggerFactory.cs index 988c300..d1fe698 100644 --- a/Geekbot.net/Lib/LoggerFactory.cs +++ b/Geekbot.net/Lib/LoggerFactory.cs @@ -9,8 +9,11 @@ namespace Geekbot.net.Lib public static ILogger createLogger(string[] args) { var loggerCreation = new LoggerConfiguration() - .WriteTo.LiterateConsole() .WriteTo.RollingFile("Logs/geekbot-{Date}.txt", shared: true); + if (!Environment.CurrentDirectory.Contains("deploy")) + { + loggerCreation.WriteTo.LiterateConsole(); + } if (args.Contains("--verbose")) { loggerCreation.MinimumLevel.Verbose(); From 828980c6503b9c1a735dcadf6f4e3192f23d2aa1 Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 15 Jan 2018 20:01:13 +0100 Subject: [PATCH 098/553] Don't show geekbot in rank lists --- Geekbot.net/Commands/Rank.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Geekbot.net/Commands/Rank.cs b/Geekbot.net/Commands/Rank.cs index 4052d4c..349bd47 100644 --- a/Geekbot.net/Commands/Rank.cs +++ b/Geekbot.net/Commands/Rank.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Discord.Commands; +using Discord.WebSocket; using Geekbot.net.Lib; using Serilog; using StackExchange.Redis; @@ -17,15 +18,17 @@ namespace Geekbot.net.Commands private readonly ILogger _logger; private readonly IDatabase _redis; private readonly IUserRepository _userRepository; + private readonly DiscordSocketClient _client; public Rank(IDatabase redis, IErrorHandler errorHandler, ILogger logger, IUserRepository userRepository, - IEmojiConverter emojiConverter) + IEmojiConverter emojiConverter, DiscordSocketClient client) { _redis = redis; _errorHandler = errorHandler; _logger = logger; _userRepository = userRepository; _emojiConverter = emojiConverter; + _client = client; } [Command("rank", RunMode = RunMode.Async)] @@ -55,6 +58,7 @@ namespace Geekbot.net.Commands var messageList = _redis.HashGetAll($"{Context.Guild.Id}:{type}"); var sortedList = messageList.OrderByDescending(e => e.Value).ToList(); var guildMessages = (int) sortedList.First().Value; + sortedList.Remove(sortedList.Single(e => e.Name.ToString().Equals(_client.CurrentUser.Id.ToString()))); if (type == "Messages") sortedList.RemoveAt(0); var highscoreUsers = new Dictionary(); From 0adb4b99f2e755f8227dfa9a7c0d759671f36214 Mon Sep 17 00:00:00 2001 From: Daan Date: Thu, 18 Jan 2018 14:40:06 +0000 Subject: [PATCH 099/553] Remove !trump command --- Geekbot.net/Commands/Trump.cs | 73 ----------------------------------- 1 file changed, 73 deletions(-) delete mode 100644 Geekbot.net/Commands/Trump.cs diff --git a/Geekbot.net/Commands/Trump.cs b/Geekbot.net/Commands/Trump.cs deleted file mode 100644 index ad87f51..0000000 --- a/Geekbot.net/Commands/Trump.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Threading.Tasks; -using Discord; -using Discord.Commands; -using Geekbot.net.Lib; - -namespace Geekbot.net.Commands -{ - public class Trump : ModuleBase - { - private readonly IErrorHandler _errorHandler; - - public Trump(IErrorHandler errorHandler) - { - _errorHandler = errorHandler; - } - - [Command("trump", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Games)] - [Summary("Get a trump quote")] - public async Task getQuote() - { - try - { - using (var client = new WebClient()) - { - var url = new Uri("https://api.tronalddump.io/random/quote"); - var response = client.DownloadString(url); - var quote = Utf8Json.JsonSerializer.Deserialize(response); - - var eb = new EmbedBuilder(); - eb.WithTitle($"Trump @ {quote.appeared_at.Day}.{quote.appeared_at.Month}.{quote.appeared_at.Year}"); - eb.WithDescription(quote.value); - eb.WithUrl(quote._embedded.source.FirstOrDefault()?.url.ToString()); - eb.WithColor(new Color(143, 167, 232)); - await ReplyAsync("", false, eb.Build()); - } - } - catch (Exception e) - { - _errorHandler.HandleCommandException(e, Context); - } - } - - public class TrumpQuote - { - public DateTimeOffset appeared_at { get; set; } - public DateTimeOffset created_at { get; set; } - public string quote_id { get; set; } - public DateTimeOffset updated_at { get; set; } - public string value { get; set; } - public Embedded _embedded { get; set; } - - public class Embedded - { - public List source { get; set; } - - public class Source - { - public DateTimeOffset created_at { get; set; } - public string filename { get; set; } - public string quote_source_id { get; set; } - public string remarks { get; set; } - public DateTimeOffset updated_at { get; set; } - public Uri url { get; set; } - } - } - } - } -} \ No newline at end of file From 2db4db24516926f837c1e07ccb4ade53d0fe1313 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 18 Jan 2018 22:51:29 +0100 Subject: [PATCH 100/553] Add !slap --- Geekbot.net/Commands/Slap.cs | 46 ++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 Geekbot.net/Commands/Slap.cs diff --git a/Geekbot.net/Commands/Slap.cs b/Geekbot.net/Commands/Slap.cs new file mode 100644 index 0000000..ecbbe83 --- /dev/null +++ b/Geekbot.net/Commands/Slap.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Geekbot.net.Lib; +namespace Geekbot.net.Commands +{ + public class Slap : ModuleBase + { + private readonly IErrorHandler _errorHandler; + private readonly Random _random; + + public Slap(IErrorHandler errorHandler, Random random) + { + _errorHandler = errorHandler; + _random = random; + } + + [Command("slap", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Fun)] + [Summary("slap someone")] + public async Task Slapper([Summary("@user")] IUser user) + { + try + { + var things = new List() + { + "thing", + "rubber duck", + "leek stick", + "large trout", + "flat hand", + "strip of bacon", + "feather", + "piece of pizza" + }; + await ReplyAsync($"{Context.User.Username} slapped {user.Username} with a {things[_random.Next(things.Count - 1)]}"); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + } +} \ No newline at end of file From aa971d04f5f54dd47b9b6e03044fe55d94174e03 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 18 Jan 2018 23:40:38 +0100 Subject: [PATCH 101/553] adding more stuff to !slap --- Geekbot.net/Commands/Slap.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Geekbot.net/Commands/Slap.cs b/Geekbot.net/Commands/Slap.cs index ecbbe83..570ddda 100644 --- a/Geekbot.net/Commands/Slap.cs +++ b/Geekbot.net/Commands/Slap.cs @@ -33,7 +33,16 @@ namespace Geekbot.net.Commands "flat hand", "strip of bacon", "feather", - "piece of pizza" + "piece of pizza", + "moldy banana", + "sharp retort", + "printed version of wikipedia", + "panda paw", + "spiked sledgehammer", + "monstertruck", + "dirty toilet brush", + "sleeping seagull", + "sunflower" }; await ReplyAsync($"{Context.User.Username} slapped {user.Username} with a {things[_random.Next(things.Count - 1)]}"); } From e5ff638ce40b39a216248e772da133d7d16a6df1 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 18 Jan 2018 23:47:42 +0100 Subject: [PATCH 102/553] Add ci deployment environment --- .gitlab-ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ecbead2..e8963d8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -25,6 +25,9 @@ deploy: - master dependencies: - build + environment: + name: Production + url: https://discordapp.com/oauth2/authorize?client_id=171249478546882561&scope=bot&permissions=1416834054 before_script: - eval $(ssh-agent -s) - mkdir -p ~/.ssh From 41f8b1bc0b00a3fa71ff9fd665596a5d37132111 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 18 Jan 2018 23:59:55 +0100 Subject: [PATCH 103/553] Add github mirroring to ci job --- .gitlab-ci.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e8963d8..4be995d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -36,4 +36,13 @@ deploy: - chmod 700 ~/.ssh script: - rsync -rav -e "ssh -p 65432" ./Geekbot.net/Binaries/* www-data@31.220.42.224:$DEPPATH - - ssh -p 65432 www-data@31.220.42.224 "sudo systemctl restart geekbot.service" \ No newline at end of file + - ssh -p 65432 www-data@31.220.42.224 "sudo systemctl restart geekbot.service" + +mirror: + stage: deploy + image: bravissimolabs/alpine-git:latest + only: + - master + script: + - git push https://runebaas:$TOKEN@github.com/pizzaandcoffee/Geekbot.net.git origin/master:master -f + \ No newline at end of file From 11df9d79559c0af1bcd1bd28a2cf0bd91b2bc34f Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 19 Jan 2018 00:59:21 +0100 Subject: [PATCH 104/553] Add Simple Unit Tests --- .gitlab-ci.yml | 6 +++ Geekbot.net.sln | 6 +++ Geekbot.net/Geekbot.net.csproj | 1 + Geekbot.net/Lib/EmojiConverter.cs | 14 +++++- Tests/Lib/EmojiConverter.test.cs | 75 +++++++++++++++++++++++++++++++ Tests/Tests.csproj | 16 +++++++ 6 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 Tests/Lib/EmojiConverter.test.cs create mode 100644 Tests/Tests.csproj diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4be995d..3928542 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,12 +10,18 @@ before_script: build: stage: build image: microsoft/dotnet:2.0.3-sdk-stretch + variables: + NUGET_PACKAGES: "${CI_PROJECT_DIR}/.nugetcache" + cache: + paths: + - .nugetcache artifacts: expire_in: 1h paths: - Geekbot.net/Binaries/ script: - dotnet restore + - dotnet test Tests - dotnet publish --configuration Release -o Binaries ./ deploy: diff --git a/Geekbot.net.sln b/Geekbot.net.sln index 990eb42..5011ad4 100644 --- a/Geekbot.net.sln +++ b/Geekbot.net.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 12.0.0.0 MinimumVisualStudioVersion = 10.0.0.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Geekbot.net", "Geekbot.net/Geekbot.net.csproj", "{FDCB3D92-E7B5-47BB-A9B5-CFAEFA57CDB4}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +17,10 @@ Global {FDCB3D92-E7B5-47BB-A9B5-CFAEFA57CDB4}.Debug|Any CPU.Build.0 = Debug|Any CPU {FDCB3D92-E7B5-47BB-A9B5-CFAEFA57CDB4}.Release|Any CPU.ActiveCfg = Release|Any CPU {FDCB3D92-E7B5-47BB-A9B5-CFAEFA57CDB4}.Release|Any CPU.Build.0 = Release|Any CPU + {4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 6fcd62d..38e7f94 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -8,6 +8,7 @@ Pizza and Coffee Studios A Discord bot https://github.com/pizzaandcoffee/Geekbot.net + NU1701 diff --git a/Geekbot.net/Lib/EmojiConverter.cs b/Geekbot.net/Lib/EmojiConverter.cs index 4cf7a23..60e75f4 100644 --- a/Geekbot.net/Lib/EmojiConverter.cs +++ b/Geekbot.net/Lib/EmojiConverter.cs @@ -11,7 +11,19 @@ namespace Geekbot.net.Lib { return "🔟"; } - var emojiMap = new string[] {"0⃣", "1⃣", "2⃣", "3⃣", "4⃣", "5⃣", "6⃣", "7⃣", "8⃣", "9⃣"}; + var emojiMap = new string[] + { + ":zero:", + ":one:", + ":two:", + ":three:", + ":four:", + ":five:", + ":six:", + ":seven:", + ":eight:", + ":nine:", + }; var numbers = number.ToString().ToCharArray(); var returnString = new StringBuilder(); foreach (var n in numbers) diff --git a/Tests/Lib/EmojiConverter.test.cs b/Tests/Lib/EmojiConverter.test.cs new file mode 100644 index 0000000..ca4ecbc --- /dev/null +++ b/Tests/Lib/EmojiConverter.test.cs @@ -0,0 +1,75 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Geekbot.net.Lib; +using Xunit; + +namespace Tests.Lib +{ + public class EmojiConverter_test + { + public static IEnumerable NumberToEmojiTestData + { + get + { + yield return new object[] + { + 2, + ":two:" + }; + + yield return new object[] + { + 10, + "🔟" + }; + + yield return new object[] + { + 15, + ":one::five:" + }; + + yield return new object[] + { + null, + ":zero:" + }; + } + } + + + [Theory, MemberData(nameof(NumberToEmojiTestData))] + public async Task NumberToEmoji(int number, string expectedResult) + { + var emojiConverter = new EmojiConverter(); + var result = emojiConverter.numberToEmoji(number); + Assert.Equal(result, expectedResult); + } + + public static IEnumerable textToEmojiTestData + { + get + { + yield return new object[] + { + "test", + ":regional_indicator_t::regional_indicator_e::regional_indicator_s::regional_indicator_t:" + }; + yield return new object[] + { + "Best3+?", + ":b::regional_indicator_e::regional_indicator_s::regional_indicator_t::three::heavy_plus_sign::question:" + }; + } + } + + + [Theory, MemberData(nameof(textToEmojiTestData))] + public async Task TextToEmoji(string text, string expectedResult) + { + var emojiConverter = new EmojiConverter(); + var result = emojiConverter.textToEmoji(text); + Assert.Equal(result, expectedResult); + } + } +} \ No newline at end of file diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj new file mode 100644 index 0000000..c838db0 --- /dev/null +++ b/Tests/Tests.csproj @@ -0,0 +1,16 @@ + + + netcoreapp2.0 + false + NU1701 + + + + + + + + + + + \ No newline at end of file From fdb38192fe944748880445581c7d2de860a39905 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 19 Jan 2018 01:17:05 +0100 Subject: [PATCH 105/553] Add LevelCalc unit test --- Geekbot.net/Lib/LevelCalc.cs | 2 +- Tests/Lib/LevelCalc.test.cs | 49 ++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 Tests/Lib/LevelCalc.test.cs diff --git a/Geekbot.net/Lib/LevelCalc.cs b/Geekbot.net/Lib/LevelCalc.cs index 6951f5e..d075754 100644 --- a/Geekbot.net/Lib/LevelCalc.cs +++ b/Geekbot.net/Lib/LevelCalc.cs @@ -4,7 +4,7 @@ using System.Linq; namespace Geekbot.net.Lib { - internal class LevelCalc : ILevelCalc + public class LevelCalc : ILevelCalc { private int[] _levels; diff --git a/Tests/Lib/LevelCalc.test.cs b/Tests/Lib/LevelCalc.test.cs new file mode 100644 index 0000000..74e6105 --- /dev/null +++ b/Tests/Lib/LevelCalc.test.cs @@ -0,0 +1,49 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Geekbot.net.Lib; +using Xunit; + +namespace Tests.Lib +{ + public class LevelCalc_test + { + public static IEnumerable LevelCalcTestData + { + get + { + yield return new object[] + { + 500, + 13 + }; + + yield return new object[] + { + 41659, + 55 + }; + + yield return new object[] + { + 0, + 1 + }; + + yield return new object[] + { + 4000000, + 101 + }; + } + } + + + [Theory, MemberData(nameof(LevelCalcTestData))] + public async Task GetLevel(int messages, int expectedResult) + { + var levelCalc = new LevelCalc(); + var result = levelCalc.GetLevel(messages); + Assert.Equal(result, expectedResult); + } + } +} \ No newline at end of file From efadbe9a21472473d02af60905ebc47482ffe30c Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 19 Jan 2018 23:46:11 +0100 Subject: [PATCH 106/553] Add slap counter --- Geekbot.net/Commands/Slap.cs | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/Geekbot.net/Commands/Slap.cs b/Geekbot.net/Commands/Slap.cs index 570ddda..134752c 100644 --- a/Geekbot.net/Commands/Slap.cs +++ b/Geekbot.net/Commands/Slap.cs @@ -4,17 +4,21 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; +using StackExchange.Redis; + namespace Geekbot.net.Commands { public class Slap : ModuleBase { private readonly IErrorHandler _errorHandler; private readonly Random _random; + private readonly IDatabase _redis; - public Slap(IErrorHandler errorHandler, Random random) + public Slap(IErrorHandler errorHandler, Random random, IDatabase redis) { _errorHandler = errorHandler; _random = random; + _redis = redis; } [Command("slap", RunMode = RunMode.Async)] @@ -24,10 +28,16 @@ namespace Geekbot.net.Commands { try { + if (user.Id == Context.User.Id) + { + await ReplyAsync("Why would you slap yourself?"); + return; + } + var things = new List() { "thing", - "rubber duck", + "rubber chicken", "leek stick", "large trout", "flat hand", @@ -42,8 +52,15 @@ namespace Geekbot.net.Commands "monstertruck", "dirty toilet brush", "sleeping seagull", - "sunflower" + "sunflower", + "mousepad", + "lolipop", + "bottle of rum" }; + + _redis.HashIncrement($"{Context.Guild.Id}:SlapsRecieved", user.Id.ToString()); + _redis.HashIncrement($"{Context.Guild.Id}:SlapsGiven", Context.User.Id.ToString()); + await ReplyAsync($"{Context.User.Username} slapped {user.Username} with a {things[_random.Next(things.Count - 1)]}"); } catch (Exception e) From 82b2b4c815d9857e03d82e145a43e056d7a9edef Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 29 Dec 2017 01:00:31 +0100 Subject: [PATCH 107/553] Groundwork for sumologic --- Geekbot.net/Handlers.cs | 8 +- Geekbot.net/Lib/ErrorHandler.cs | 53 +----------- Geekbot.net/Lib/GeekbotLogger.cs | 69 ++++++++++++++++ Geekbot.net/Lib/SimpleConextConverter.cs | 100 +++++++++++++++++++++++ Geekbot.net/Program.cs | 10 ++- 5 files changed, 182 insertions(+), 58 deletions(-) create mode 100644 Geekbot.net/Lib/GeekbotLogger.cs create mode 100644 Geekbot.net/Lib/SimpleConextConverter.cs diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index 89fb61e..240be2b 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -15,15 +15,17 @@ namespace Geekbot.net { private readonly IDiscordClient _client; private readonly ILogger _logger; + private readonly IGeekbotLogger _gLogger; private readonly IDatabase _redis; private readonly IServiceProvider _servicesProvider; private readonly CommandService _commands; private readonly IUserRepository _userRepository; - public Handlers(IDiscordClient client, ILogger logger, IDatabase redis, IServiceProvider servicesProvider, CommandService commands, IUserRepository userRepository) + public Handlers(IDiscordClient client, ILogger logger, IDatabase redis, IServiceProvider servicesProvider, CommandService commands, IUserRepository userRepository, IGeekbotLogger gLogger) { _client = client; _logger = logger; + _gLogger = gLogger; _redis = redis; _servicesProvider = servicesProvider; _commands = commands; @@ -82,8 +84,8 @@ namespace Geekbot.net _redis.HashIncrementAsync($"{channel.Guild.Id}:Messages", 0.ToString()); if (message.Author.IsBot) return Task.CompletedTask; - _logger.Information( - $"[Message] {channel.Guild.Name} ({channel.Guild.Id}) - {message.Channel} ({message.Channel.Id}) - {message.Author.Username}#{message.Author.Discriminator} ({message.Author.Id}) - {message.Content}"); + _gLogger.Info("Message", message.Content, SimpleConextConverter.ConvertSocketMessage(message)); +// _logger.Information($"[Message] {channel.Guild.Name} ({channel.Guild.Id}) - {message.Channel} ({message.Channel.Id}) - {message.Author.Username}#{message.Author.Discriminator} ({message.Author.Id}) - {message.Content}"); } catch (Exception e) { diff --git a/Geekbot.net/Lib/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandler.cs index 1d6ffd8..20b326c 100644 --- a/Geekbot.net/Lib/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandler.cs @@ -41,34 +41,7 @@ namespace Geekbot.net.Lib try { var errorString = errorMessage == "def" ? _translation.GetString(Context.Guild.Id, "errorHandler", "SomethingWentWrong") : errorMessage; - var errorObj = new ErrorObject() - { - Message = new ErrorMessage() - { - Content = Context.Message.Content, - Id = Context.Message.Id.ToString(), - Attachments = Context.Message.Attachments.Count, - ChannelMentions = Context.Message.MentionedChannelIds.Count, - UserMentions = Context.Message.MentionedUserIds.Count, - RoleMentions = Context.Message.MentionedRoleIds.Count - }, - User = new IdAndName() - { - Id = Context.User.Id.ToString(), - Name = $"{Context.User.Username}#{Context.User.Discriminator}" - }, - Guild = new IdAndName() - { - Id = Context.Guild.Id.ToString(), - Name = Context.Guild.Name - }, - Channel = new IdAndName() - { - Id = Context.Channel.Id.ToString(), - Name = Context.Channel.Name - }, - TimeStamp = DateTime.Now.ToString() - }; + var errorObj = SimpleConextConverter.ConvertContext(Context); var errorJson = JsonSerializer.ToJsonString(errorObj); _logger.Error(e, errorJson); if (!string.IsNullOrEmpty(errorMessage)) @@ -107,31 +80,7 @@ namespace Geekbot.net.Lib } } - - public class ErrorObject - { - public ErrorMessage Message { get; set; } - public IdAndName User { get; set; } - public IdAndName Guild { get; set; } - public IdAndName Channel { get; set; } - public string TimeStamp { get; set; } - } - public class ErrorMessage - { - public string Content { get; set; } - public string Id { get; set; } - public int Attachments { get; set; } - public int ChannelMentions { get; set; } - public int UserMentions { get; set; } - public int RoleMentions { get; set; } - } - - public class IdAndName - { - public string Id { get; set; } - public string Name { get; set; } - } } public interface IErrorHandler diff --git a/Geekbot.net/Lib/GeekbotLogger.cs b/Geekbot.net/Lib/GeekbotLogger.cs new file mode 100644 index 0000000..f4e191c --- /dev/null +++ b/Geekbot.net/Lib/GeekbotLogger.cs @@ -0,0 +1,69 @@ +using System; +using System.Threading.Tasks; +using Utf8Json; +using Utf8Json.Resolvers; + +namespace Geekbot.net.Lib +{ + public class GeekbotLogger : IGeekbotLogger + { + public GeekbotLogger() + { + JsonSerializer.SetDefaultResolver(StandardResolver.AllowPrivateExcludeNullSnakeCase); + Info("Geekbot", "Using GeekbotLogger"); + } + + public void Debug(string source, string message, object extra = null) + { + HandleLogObject("Debug", source, message, null, extra); + } + + public void Info(string source, string message, object extra = null) + { + HandleLogObject("Information", source, message, null, extra); + } + + public void Error(string source, string message, Exception stackTrace, object extra = null) + { + HandleLogObject("Debug", source, message, stackTrace, extra); + } + + private Task HandleLogObject(string type, string source, string message, Exception stackTrace = null, object extra = null) + { + var logJson = CreateLogObject(type, source, message, null, extra); + Console.WriteLine(logJson); + return Task.CompletedTask; + } + + private string CreateLogObject(string type, string source, string message, Exception stackTrace = null, object extra = null) + { + var logObject = new GeekbotLoggerObject() + { + Timestamp = DateTime.Now, + Type = type, + Source = source, + Message = message, + StackTrace = stackTrace, + Extra = extra + }; + return Utf8Json.JsonSerializer.ToJsonString(logObject); + } + } + + public class GeekbotLoggerObject + { + public DateTime Timestamp { get; set; } + public string Type { get; set; } + public string Source { get; set; } + public string Message { get; set; } + public Exception StackTrace { get; set; } + public object Extra { get; set; } + } + + public interface IGeekbotLogger + { + void Debug(string source, string message, object extra = null); + void Info(string source, string message, object extra = null); + void Error(string source, string message, Exception stackTrace, object extra = null); + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/SimpleConextConverter.cs b/Geekbot.net/Lib/SimpleConextConverter.cs new file mode 100644 index 0000000..ff6c2ef --- /dev/null +++ b/Geekbot.net/Lib/SimpleConextConverter.cs @@ -0,0 +1,100 @@ +using System; +using Discord.Commands; +using Discord.WebSocket; + +namespace Geekbot.net.Lib +{ + public class SimpleConextConverter + { + public static MessageDto ConvertContext(ICommandContext context) + { + return new MessageDto() + { + Message = new MessageDto.MessageContent() + { + Content = context.Message.Content, + Id = context.Message.Id.ToString(), + Attachments = context.Message.Attachments.Count, + ChannelMentions = context.Message.MentionedChannelIds.Count, + UserMentions = context.Message.MentionedUserIds.Count, + RoleMentions = context.Message.MentionedRoleIds.Count + }, + User = new MessageDto.IdAndName() + { + Id = context.User.Id.ToString(), + Name = $"{context.User.Username}#{context.User.Discriminator}" + }, + Guild = new MessageDto.IdAndName() + { + Id = context.Guild.Id.ToString(), + Name = context.Guild.Name + }, + Channel = new MessageDto.IdAndName() + { + Id = context.Channel.Id.ToString(), + Name = context.Channel.Name + }, + TimeStamp = DateTime.Now.ToString() + }; + } + public static MessageDto ConvertSocketMessage(SocketMessage message) + { + var channel = (SocketGuildChannel) message.Channel; + return new MessageDto() + { + Message = new MessageDto.MessageContent() + { + Content = message.Content, + Id = message.Id.ToString(), + Attachments = message.Attachments.Count, + ChannelMentions = message.MentionedChannels.Count, + UserMentions = message.MentionedUsers.Count, + RoleMentions = message.MentionedRoles.Count + }, + User = new MessageDto.IdAndName() + { + Id = message.Author.Id.ToString(), + Name = $"{message.Author.Username}#{message.Author.Discriminator}" + }, + Guild = new MessageDto.IdAndName() + { + Id = channel.Guild.Id.ToString(), + Name = channel.Guild.Name + }, + Channel = new MessageDto.IdAndName() + { + Id = channel.Id.ToString(), + Name = channel.Name + }, + TimeStamp = DateTime.Now.ToString() + }; + } + + } + + + public class MessageDto + { + public MessageContent Message { get; set; } + public IdAndName User { get; set; } + public IdAndName Guild { get; set; } + public IdAndName Channel { get; set; } + public string TimeStamp { get; set; } + + public class MessageContent + { + public string Content { get; set; } + public string Id { get; set; } + public int Attachments { get; set; } + public int ChannelMentions { get; set; } + public int UserMentions { get; set; } + public int RoleMentions { get; set; } + } + + public class IdAndName + { + public string Id { get; set; } + public string Name { get; set; } + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 4382309..9e25718 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -28,6 +28,7 @@ namespace Geekbot.net private IServiceProvider servicesProvider; private RedisValue token; private ILogger logger; + private IGeekbotLogger gLogger; private IUserRepository userRepository; private string[] args; private bool firstStart = false; @@ -43,10 +44,11 @@ namespace Geekbot.net logo.AppendLine("========================================="); Console.WriteLine(logo.ToString()); var logger = LoggerFactory.createLogger(args); + var gLogger = new GeekbotLogger(); logger.Information("[Geekbot] Starting..."); try { - new Program().MainAsync(args, logger).GetAwaiter().GetResult(); + new Program().MainAsync(args, logger, gLogger).GetAwaiter().GetResult(); } catch (Exception e) { @@ -54,11 +56,13 @@ namespace Geekbot.net } } - private async Task MainAsync(string[] args, ILogger logger) + private async Task MainAsync(string[] args, ILogger logger, IGeekbotLogger gLogger) { this.logger = logger; + this.gLogger = gLogger; this.args = args; logger.Information("[Geekbot] Initing Stuff"); + gLogger.Info("Geekbot", "Initing Stuff"); client = new DiscordSocketClient(new DiscordSocketConfig { @@ -142,7 +146,7 @@ namespace Geekbot.net services.AddSingleton(client); servicesProvider = services.BuildServiceProvider(); - var handlers = new Handlers(client, logger, redis, servicesProvider, commands, userRepository); + var handlers = new Handlers(client, logger, redis, servicesProvider, commands, userRepository, gLogger); client.MessageReceived += handlers.RunCommand; client.MessageReceived += handlers.UpdateStats; From 07ca1e1548110783b1f253ccc2c064537286cd12 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 20 Jan 2018 01:38:49 +0100 Subject: [PATCH 108/553] Replace all ocurences of the Serilog with GeekbotLogger --- Geekbot.net/Commands/Overwatch.cs | 5 +- Geekbot.net/Commands/Owner.cs | 12 ++--- Geekbot.net/Commands/Rank.cs | 6 +-- Geekbot.net/Handlers.cs | 26 ++++------ Geekbot.net/Lib/ErrorHandler.cs | 11 ++-- Geekbot.net/Lib/GeekbotLogger.cs | 14 ++++-- Geekbot.net/Lib/MalClient.cs | 8 +-- Geekbot.net/Lib/Media/FortunesProvider.cs | 7 ++- Geekbot.net/Lib/Media/MediaProvider.cs | 42 ++++++++-------- Geekbot.net/Lib/SimpleConextConverter.cs | 5 +- Geekbot.net/Lib/TranslationHandler.cs | 16 +++--- Geekbot.net/Lib/UserRepository.cs | 10 ++-- Geekbot.net/Program.cs | 61 ++++++++++------------- 13 files changed, 105 insertions(+), 118 deletions(-) diff --git a/Geekbot.net/Commands/Overwatch.cs b/Geekbot.net/Commands/Overwatch.cs index 9007804..10dc459 100644 --- a/Geekbot.net/Commands/Overwatch.cs +++ b/Geekbot.net/Commands/Overwatch.cs @@ -14,13 +14,11 @@ namespace Geekbot.net.Commands public class Overwatch : ModuleBase { private readonly IErrorHandler _errorHandler; - private readonly ILogger _logger; private readonly IUserRepository _userRepository; - public Overwatch(IErrorHandler errorHandler, ILogger logger, IDatabase redis, IUserRepository userRepository) + public Overwatch(IErrorHandler errorHandler, IDatabase redis, IUserRepository userRepository) { _errorHandler = errorHandler; - _logger = logger; _userRepository = userRepository; } @@ -117,7 +115,6 @@ namespace Geekbot.net.Commands { var player = await owClient.GetPlayerAsync(battletag); if (player.Username == null) return null; - _logger.Debug($"[OW] Username = {player.Username}"); var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder() .WithIconUrl(player.ProfilePortraitUrl) diff --git a/Geekbot.net/Commands/Owner.cs b/Geekbot.net/Commands/Owner.cs index c3c9cc0..c4adb25 100644 --- a/Geekbot.net/Commands/Owner.cs +++ b/Geekbot.net/Commands/Owner.cs @@ -15,11 +15,11 @@ namespace Geekbot.net.Commands { private readonly DiscordSocketClient _client; private readonly IErrorHandler _errorHandler; - private readonly ILogger _logger; + private readonly IGeekbotLogger _logger; private readonly IDatabase _redis; private readonly IUserRepository _userRepository; - public Owner(IDatabase redis, DiscordSocketClient client, ILogger logger, IUserRepository userRepositry, + public Owner(IDatabase redis, DiscordSocketClient client, IGeekbotLogger logger, IUserRepository userRepositry, IErrorHandler errorHandler) { _redis = redis; @@ -61,7 +61,7 @@ namespace Geekbot.net.Commands _redis.StringSet("Game", key); await _client.SetGameAsync(key); - _logger.Information($"[Geekbot] Changed game to {key}"); + _logger.Information("Geekbot", $"Changed game to {key}"); await ReplyAsync($"Now Playing {key}"); } @@ -91,11 +91,11 @@ namespace Geekbot.net.Commands var failed = 0; try { - _logger.Warning("[UserRepository] Populating User Repositry"); + _logger.Warning("UserRepository", "Populating User Repositry"); await ReplyAsync("Starting Population of User Repository"); foreach (var guild in _client.Guilds) { - _logger.Information($"[UserRepository] Populating users from {guild.Name}"); + _logger.Information("UserRepository", $"Populating users from {guild.Name}"); foreach (var user in guild.Users) { var succeded = await _userRepository.Update(user); @@ -103,7 +103,7 @@ namespace Geekbot.net.Commands } } - _logger.Warning("[UserRepository] Finished Updating User Repositry"); + _logger.Warning("UserRepository", "Finished Updating User Repositry"); await ReplyAsync( $"Successfully Populated User Repository with {success} Users in {_client.Guilds.Count} Guilds (Failed: {failed})"); } diff --git a/Geekbot.net/Commands/Rank.cs b/Geekbot.net/Commands/Rank.cs index 349bd47..516c2aa 100644 --- a/Geekbot.net/Commands/Rank.cs +++ b/Geekbot.net/Commands/Rank.cs @@ -15,12 +15,12 @@ namespace Geekbot.net.Commands { private readonly IEmojiConverter _emojiConverter; private readonly IErrorHandler _errorHandler; - private readonly ILogger _logger; + private readonly IGeekbotLogger _logger; private readonly IDatabase _redis; private readonly IUserRepository _userRepository; private readonly DiscordSocketClient _client; - public Rank(IDatabase redis, IErrorHandler errorHandler, ILogger logger, IUserRepository userRepository, + public Rank(IDatabase redis, IErrorHandler errorHandler, IGeekbotLogger logger, IUserRepository userRepository, IEmojiConverter emojiConverter, DiscordSocketClient client) { _redis = redis; @@ -91,7 +91,7 @@ namespace Geekbot.net.Commands } catch (Exception e) { - _logger.Warning(e, $"Could not retrieve user {user.Name}"); + _logger.Warning("Geekbot", $"Could not retrieve user {user.Name}", e); } } diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index 240be2b..13ce041 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -14,18 +14,16 @@ namespace Geekbot.net public class Handlers { private readonly IDiscordClient _client; - private readonly ILogger _logger; - private readonly IGeekbotLogger _gLogger; + private readonly IGeekbotLogger _logger; private readonly IDatabase _redis; private readonly IServiceProvider _servicesProvider; private readonly CommandService _commands; private readonly IUserRepository _userRepository; - public Handlers(IDiscordClient client, ILogger logger, IDatabase redis, IServiceProvider servicesProvider, CommandService commands, IUserRepository userRepository, IGeekbotLogger gLogger) + public Handlers(IDiscordClient client, IGeekbotLogger logger, IDatabase redis, IServiceProvider servicesProvider, CommandService commands, IUserRepository userRepository) { _client = client; _logger = logger; - _gLogger = gLogger; _redis = redis; _servicesProvider = servicesProvider; _commands = commands; @@ -62,7 +60,7 @@ namespace Geekbot.net } catch (Exception e) { - _logger.Error(e, "[Geekbot] Failed to run commands"); + _logger.Error("Geekbot", "Failed to run commands", e); return Task.CompletedTask; } } @@ -74,8 +72,7 @@ namespace Geekbot.net if (message == null) return Task.CompletedTask; if (message.Channel.Name.StartsWith('@')) { - _logger.Information( - $"[Message] DM-Channel - {message.Channel.Name} - {message.Content}"); + _logger.Information("Message", "DM-Channel - {message.Channel.Name} - {message.Content}"); return Task.CompletedTask; } var channel = (SocketGuildChannel) message.Channel; @@ -84,12 +81,12 @@ namespace Geekbot.net _redis.HashIncrementAsync($"{channel.Guild.Id}:Messages", 0.ToString()); if (message.Author.IsBot) return Task.CompletedTask; - _gLogger.Info("Message", message.Content, SimpleConextConverter.ConvertSocketMessage(message)); + _logger.Information("Message", message.Content, SimpleConextConverter.ConvertSocketMessage(message)); // _logger.Information($"[Message] {channel.Guild.Name} ({channel.Guild.Id}) - {message.Channel} ({message.Channel.Id}) - {message.Author.Username}#{message.Author.Discriminator} ({message.Author.Id}) - {message.Content}"); } catch (Exception e) { - _logger.Error(e, "Could not process message stats"); + _logger.Error("Message", "Could not process message stats", e); } return Task.CompletedTask; } @@ -112,12 +109,11 @@ namespace Geekbot.net } } _userRepository.Update(user); - _logger.Information( - $"[Geekbot] {user.Id} ({user.Username}) joined {user.Guild.Id} ({user.Guild.Name})"); + _logger.Information("Geekbot", $"{user.Username} ({user.Id}) joined {user.Guild.Name} ({user.Guild.Id})"); } catch (Exception e) { - _logger.Error(e, "[Geekbot] Failed to send welcome message"); + _logger.Error("Geekbot", "Failed to send welcome message", e); } return Task.CompletedTask; } @@ -145,9 +141,9 @@ namespace Geekbot.net } catch (Exception e) { - _logger.Error(e, "Failed to send leave message..."); + _logger.Error("Geekbot", "Failed to send leave message", e); } - _logger.Information($"[Geekbot] {user.Id} ({user.Username}) left {user.Guild.Id} ({user.Guild.Name})"); + _logger.Information("Geekbot", $"{user.Username} ({user.Id}) joined {user.Guild.Name} ({user.Guild.Id})"); } // @@ -183,7 +179,7 @@ namespace Geekbot.net } catch (Exception e) { - _logger.Error(e, "Failed to send delete message..."); + _logger.Error("Geekbot", "Failed to send delete message...", e); } } } diff --git a/Geekbot.net/Lib/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandler.cs index 20b326c..6cc6644 100644 --- a/Geekbot.net/Lib/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandler.cs @@ -15,11 +15,11 @@ namespace Geekbot.net.Lib { public class ErrorHandler : IErrorHandler { - private readonly ILogger _logger; + private readonly IGeekbotLogger _logger; private readonly ITranslationHandler _translation; private readonly IRavenClient _raven; - public ErrorHandler(ILogger logger, ITranslationHandler translation) + public ErrorHandler(IGeekbotLogger logger, ITranslationHandler translation) { _logger = logger; _translation = translation; @@ -28,7 +28,7 @@ namespace Geekbot.net.Lib if (!string.IsNullOrEmpty(sentryDsn)) { _raven = new RavenClient(sentryDsn); - _logger.Information($"[Geekbot] Command Errors will be logged to Sentry: {sentryDsn}"); + _logger.Information("Geekbot", $"Command Errors will be logged to Sentry: {sentryDsn}"); } else { @@ -42,8 +42,7 @@ namespace Geekbot.net.Lib { var errorString = errorMessage == "def" ? _translation.GetString(Context.Guild.Id, "errorHandler", "SomethingWentWrong") : errorMessage; var errorObj = SimpleConextConverter.ConvertContext(Context); - var errorJson = JsonSerializer.ToJsonString(errorObj); - _logger.Error(e, errorJson); + _logger.Error("Geekbot", "An error ocured", e, errorObj); if (!string.IsNullOrEmpty(errorMessage)) { Context.Channel.SendMessageAsync(errorString); @@ -65,7 +64,7 @@ namespace Geekbot.net.Lib } catch (Exception ex) { - _logger.Error(ex, "Errorception"); + _logger.Error("Geekbot", "Errorception", ex); } } diff --git a/Geekbot.net/Lib/GeekbotLogger.cs b/Geekbot.net/Lib/GeekbotLogger.cs index f4e191c..46799af 100644 --- a/Geekbot.net/Lib/GeekbotLogger.cs +++ b/Geekbot.net/Lib/GeekbotLogger.cs @@ -10,7 +10,7 @@ namespace Geekbot.net.Lib public GeekbotLogger() { JsonSerializer.SetDefaultResolver(StandardResolver.AllowPrivateExcludeNullSnakeCase); - Info("Geekbot", "Using GeekbotLogger"); + Information("Geekbot", "Using GeekbotLogger"); } public void Debug(string source, string message, object extra = null) @@ -18,14 +18,19 @@ namespace Geekbot.net.Lib HandleLogObject("Debug", source, message, null, extra); } - public void Info(string source, string message, object extra = null) + public void Information(string source, string message, object extra = null) { HandleLogObject("Information", source, message, null, extra); } + public void Warning(string source, string message, Exception stackTrace = null, object extra = null) + { + HandleLogObject("Warning", source, message, stackTrace, extra); + } + public void Error(string source, string message, Exception stackTrace, object extra = null) { - HandleLogObject("Debug", source, message, stackTrace, extra); + HandleLogObject("Error", source, message, stackTrace, extra); } private Task HandleLogObject(string type, string source, string message, Exception stackTrace = null, object extra = null) @@ -63,7 +68,8 @@ namespace Geekbot.net.Lib public interface IGeekbotLogger { void Debug(string source, string message, object extra = null); - void Info(string source, string message, object extra = null); + void Information(string source, string message, object extra = null); + void Warning(string source, string message, Exception stackTrace = null, object extra = null); void Error(string source, string message, Exception stackTrace, object extra = null); } } \ No newline at end of file diff --git a/Geekbot.net/Lib/MalClient.cs b/Geekbot.net/Lib/MalClient.cs index 4827b13..bc09036 100644 --- a/Geekbot.net/Lib/MalClient.cs +++ b/Geekbot.net/Lib/MalClient.cs @@ -10,12 +10,12 @@ namespace Geekbot.net.Lib public class MalClient : IMalClient { private readonly IDatabase _redis; - private readonly ILogger _logger; + private readonly IGeekbotLogger _logger; private ICredentialContext _credentials; private AnimeSearchMethodsAsync _animeSearch; private MangaSearchMethodsAsync _mangaSearch; - public MalClient(IDatabase redis, ILogger logger) + public MalClient(IDatabase redis, IGeekbotLogger logger) { _redis = redis; _logger = logger; @@ -42,10 +42,10 @@ namespace Geekbot.net.Lib } _animeSearch = new AnimeSearchMethodsAsync(_credentials); _mangaSearch = new MangaSearchMethodsAsync(_credentials); - _logger.Verbose($"[Geekbot] [MalClient] Logged in to Mal"); + _logger.Debug("Geekbot", "Logged in to MAL"); return true; } - _logger.Warning("[Geekbot] [MalClient] No Credentials Set!"); + _logger.Debug("Geekbot", "No MAL Credentials Set!"); return false; } diff --git a/Geekbot.net/Lib/Media/FortunesProvider.cs b/Geekbot.net/Lib/Media/FortunesProvider.cs index 43e456f..f536074 100644 --- a/Geekbot.net/Lib/Media/FortunesProvider.cs +++ b/Geekbot.net/Lib/Media/FortunesProvider.cs @@ -10,7 +10,7 @@ namespace Geekbot.net.Lib.Media private readonly Random rnd; private readonly int totalFortunes; - public FortunesProvider(Random rnd, ILogger logger) + public FortunesProvider(Random rnd, IGeekbotLogger logger) { var path = Path.GetFullPath("./Storage/fortunes"); if (File.Exists(path)) @@ -19,12 +19,11 @@ namespace Geekbot.net.Lib.Media fortuneArray = rawFortunes.Split("%"); totalFortunes = fortuneArray.Length; this.rnd = rnd; - logger.Verbose($"[Geekbot] [Fortunes] Loaded {totalFortunes} Fortunes"); + logger.Debug("Geekbot", "Loaded {totalFortunes} Fortunes"); } else { - logger.Error("Fortunes File not found"); - logger.Error($"Path should be {path}"); + logger.Information("Geekbot", $"Fortunes File not found at {path}"); } } diff --git a/Geekbot.net/Lib/Media/MediaProvider.cs b/Geekbot.net/Lib/Media/MediaProvider.cs index e67b9c9..ce5a0cd 100644 --- a/Geekbot.net/Lib/Media/MediaProvider.cs +++ b/Geekbot.net/Lib/Media/MediaProvider.cs @@ -9,7 +9,7 @@ namespace Geekbot.net.Lib.Media public class MediaProvider : IMediaProvider { private readonly Random _random; - private readonly ILogger _logger; + private readonly IGeekbotLogger _logger; private string[] _checkemImages; private string[] _pandaImages; private string[] _croissantImages; @@ -17,61 +17,61 @@ namespace Geekbot.net.Lib.Media private string[] _pumpkinImages; private string[] _turtlesImages; - public MediaProvider(Random rnd, ILogger logger) + public MediaProvider(Random rnd, IGeekbotLogger logger) { _random = rnd; _logger = logger; - logger.Information("[Geekbot] Loading Media Files"); + logger.Information("Geekbot", "Loading Media Files"); - loadCheckem(); - loadPandas(); - bakeCroissants(); - loadSquirrels(); - loadPumpkins(); - loadTurtles(); + LoadCheckem(); + LoadPandas(); + BakeCroissants(); + LoadSquirrels(); + LoadPumpkins(); + LoadTurtles(); } - private void loadCheckem() + private void LoadCheckem() { var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/checkEmPics")); _checkemImages = rawLinks.Split("\n"); - _logger.Verbose($"[Geekbot] [Media] Loaded {_checkemImages.Length} CheckEm Images"); + _logger.Debug("Geekbot", $"Loaded {_checkemImages.Length} CheckEm Images"); } - private void loadPandas() + private void LoadPandas() { var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/pandas")); _pandaImages = rawLinks.Split("\n"); - _logger.Verbose($"[Geekbot] [Media] Loaded {_pandaImages.Length} Panda Images"); + _logger.Debug("Geekbot", $"Loaded {_pandaImages.Length} Panda Images"); } - private void bakeCroissants() + private void BakeCroissants() { var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/croissant")); _croissantImages = rawLinks.Split("\n"); - _logger.Verbose($"[Geekbot] [Media] Loaded {_croissantImages.Length} Croissant Images"); + _logger.Debug("Geekbot", $"Loaded {_croissantImages.Length} Croissant Images"); } - private void loadSquirrels() + private void LoadSquirrels() { var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/squirrel")); _squirrelImages = rawLinks.Split("\n"); - _logger.Verbose($"[Geekbot] [Media] Loaded {_squirrelImages.Length} Squirrel Images"); + _logger.Debug("Geekbot", $"Loaded {_squirrelImages.Length} Squirrel Images"); } - private void loadPumpkins() + private void LoadPumpkins() { var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/pumpkin")); _pumpkinImages = rawLinks.Split("\n"); - _logger.Verbose($"[Geekbot] [Media] Loaded {_pumpkinImages.Length} Pumpkin Images"); + _logger.Debug("Geekbot", $"Loaded {_pumpkinImages.Length} Pumpkin Images"); } - private void loadTurtles() + private void LoadTurtles() { var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/turtles")); _turtlesImages = rawLinks.Split("\n"); - _logger.Verbose($"[Geekbot] [Media] Loaded {_turtlesImages.Length} Turtle Images"); + _logger.Debug("Geekbot", $"Loaded {_turtlesImages.Length} Turtle Images"); } public string getCheckem() diff --git a/Geekbot.net/Lib/SimpleConextConverter.cs b/Geekbot.net/Lib/SimpleConextConverter.cs index ff6c2ef..3dbc58b 100644 --- a/Geekbot.net/Lib/SimpleConextConverter.cs +++ b/Geekbot.net/Lib/SimpleConextConverter.cs @@ -33,8 +33,7 @@ namespace Geekbot.net.Lib { Id = context.Channel.Id.ToString(), Name = context.Channel.Name - }, - TimeStamp = DateTime.Now.ToString() + } }; } public static MessageDto ConvertSocketMessage(SocketMessage message) @@ -66,7 +65,6 @@ namespace Geekbot.net.Lib Id = channel.Id.ToString(), Name = channel.Name }, - TimeStamp = DateTime.Now.ToString() }; } @@ -79,7 +77,6 @@ namespace Geekbot.net.Lib public IdAndName User { get; set; } public IdAndName Guild { get; set; } public IdAndName Channel { get; set; } - public string TimeStamp { get; set; } public class MessageContent { diff --git a/Geekbot.net/Lib/TranslationHandler.cs b/Geekbot.net/Lib/TranslationHandler.cs index 7103574..cdacac8 100644 --- a/Geekbot.net/Lib/TranslationHandler.cs +++ b/Geekbot.net/Lib/TranslationHandler.cs @@ -11,17 +11,17 @@ namespace Geekbot.net.Lib { public class TranslationHandler : ITranslationHandler { - private readonly ILogger _logger; + private readonly IGeekbotLogger _logger; private readonly IDatabase _redis; private Dictionary>> _translations; private Dictionary _serverLanguages; private List _supportedLanguages; - public TranslationHandler(IReadOnlyCollection clientGuilds, IDatabase redis, ILogger logger) + public TranslationHandler(IReadOnlyCollection clientGuilds, IDatabase redis, IGeekbotLogger logger) { _logger = logger; _redis = redis; - _logger.Information("[Geekbot] Loading Translations"); + _logger.Information("Geekbot", "Loading Translations"); LoadTranslations(); LoadServerLanguages(clientGuilds); } @@ -70,7 +70,7 @@ namespace Geekbot.net.Lib } catch (Exception e) { - _logger.Fatal(e, "Failed to load Translations"); + _logger.Error("Geekbot", "Failed to load Translations", e); Environment.Exit(110); } } @@ -99,7 +99,7 @@ namespace Geekbot.net.Lib translation = _translations[command][stringName]["EN"]; if (string.IsNullOrWhiteSpace(translation)) { - _logger.Warning($"No translation found for {command} - {stringName}"); + _logger.Warning("Geekbot", $"No translation found for {command} - {stringName}"); } return translation; } @@ -113,7 +113,7 @@ namespace Geekbot.net.Lib } catch (Exception e) { - _logger.Error(e, "lol nope"); + _logger.Error("Geekbot", "lol nope", e); return new Dictionary(); } } @@ -126,7 +126,7 @@ namespace Geekbot.net.Lib } catch (Exception e) { - _logger.Error(e, "lol nope"); + _logger.Error("Geekbot", "lol nope", e); return new Dictionary(); } } @@ -142,7 +142,7 @@ namespace Geekbot.net.Lib } catch (Exception e) { - _logger.Error(e, "[Geekbot] Error while changing language"); + _logger.Error("Geekbot", "Error while changing language", e); return false; } } diff --git a/Geekbot.net/Lib/UserRepository.cs b/Geekbot.net/Lib/UserRepository.cs index 2982866..b180ef9 100644 --- a/Geekbot.net/Lib/UserRepository.cs +++ b/Geekbot.net/Lib/UserRepository.cs @@ -13,8 +13,8 @@ namespace Geekbot.net.Lib public class UserRepository : IUserRepository { private readonly IDatabase _redis; - private readonly ILogger _logger; - public UserRepository(IDatabase redis, ILogger logger) + private readonly IGeekbotLogger _logger; + public UserRepository(IDatabase redis, IGeekbotLogger logger) { _redis = redis; _logger = logger; @@ -38,12 +38,12 @@ namespace Geekbot.net.Lib } Store(savedUser); - _logger.Information($"[UserRepository] Updated User {user.Username}#{user.Discriminator} ({user.Id})"); + _logger.Information("UserRepository", "Updated User", savedUser); return Task.FromResult(true); } catch (Exception e) { - _logger.Warning(e, $"[UserRepository] Failed to update {user.Username}#{user.Discriminator} ({user.Id})"); + _logger.Warning("UserRepository", $"Failed to update user: {user.Username}#{user.Discriminator} ({user.Id})", e); return Task.FromResult(false); } } @@ -105,7 +105,7 @@ namespace Geekbot.net.Lib } catch (Exception e) { - _logger.Warning(e, $"[UserRepository] Failed to get {userId} from repository"); + _logger.Warning("UserRepository", "Failed to get {userId} from repository", e); return new UserRepositoryUser(); } } diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 9e25718..da74508 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -27,8 +27,7 @@ namespace Geekbot.net private IServiceCollection services; private IServiceProvider servicesProvider; private RedisValue token; - private ILogger logger; - private IGeekbotLogger gLogger; + private IGeekbotLogger logger; private IUserRepository userRepository; private string[] args; private bool firstStart = false; @@ -43,26 +42,23 @@ namespace Geekbot.net logo.AppendLine(@" \____|_____|_____|_|\_\____/ \___/ |_|"); logo.AppendLine("========================================="); Console.WriteLine(logo.ToString()); - var logger = LoggerFactory.createLogger(args); - var gLogger = new GeekbotLogger(); - logger.Information("[Geekbot] Starting..."); + var logger = new GeekbotLogger(); + logger.Information("Geekbot", "Starting..."); try { - new Program().MainAsync(args, logger, gLogger).GetAwaiter().GetResult(); + new Program().MainAsync(args, logger).GetAwaiter().GetResult(); } catch (Exception e) { - logger.Fatal(e, "[Geekbot] RIP"); + logger.Error("Geekbot", "RIP", e); } } - private async Task MainAsync(string[] args, ILogger logger, IGeekbotLogger gLogger) + private async Task MainAsync(string[] args, IGeekbotLogger logger) { this.logger = logger; - this.gLogger = gLogger; this.args = args; - logger.Information("[Geekbot] Initing Stuff"); - gLogger.Info("Geekbot", "Initing Stuff"); + logger.Information("Geekbot", "Initing Stuff"); client = new DiscordSocketClient(new DiscordSocketConfig { @@ -76,11 +72,11 @@ namespace Geekbot.net { var redisMultiplexer = ConnectionMultiplexer.Connect("127.0.0.1:6379"); redis = redisMultiplexer.GetDatabase(6); - logger.Information($"[Redis] Connected to db {redis.Database}"); + logger.Information("Redis", $"Connected to db {redis.Database}"); } catch (Exception e) { - logger.Fatal(e, "[Redis] Redis Connection Failed"); + logger.Error("Redis", "Redis Connection Failed", e); Environment.Exit(102); } @@ -107,7 +103,7 @@ namespace Geekbot.net var audioUtils = new AudioUtils(); services.AddSingleton(redis); - services.AddSingleton(logger); + services.AddSingleton(logger); services.AddSingleton(userRepository); services.AddSingleton(levelCalc); services.AddSingleton(emojiConverter); @@ -117,7 +113,7 @@ namespace Geekbot.net services.AddSingleton(mediaProvider); services.AddSingleton(malClient); - logger.Information("[Geekbot] Connecting to Discord"); + logger.Information("Geekbot", "Connecting to Discord"); await Login(); @@ -134,9 +130,9 @@ namespace Geekbot.net if (isConneted) { await client.SetGameAsync(redis.StringGet("Game")); - logger.Information($"[Geekbot] Now Connected as {client.CurrentUser.Username} to {client.Guilds.Count} Servers"); + logger.Information("Geekbot", $"Now Connected as {client.CurrentUser.Username} to {client.Guilds.Count} Servers"); - logger.Information("[Geekbot] Registering Stuff"); + logger.Information("Geekbot", "Registering Stuff"); var translationHandler = new TranslationHandler(client.Guilds, redis, logger); var errorHandler = new ErrorHandler(logger, translationHandler); await commands.AddModulesAsync(Assembly.GetEntryAssembly()); @@ -146,7 +142,7 @@ namespace Geekbot.net services.AddSingleton(client); servicesProvider = services.BuildServiceProvider(); - var handlers = new Handlers(client, logger, redis, servicesProvider, commands, userRepository, gLogger); + var handlers = new Handlers(client, logger, redis, servicesProvider, commands, userRepository); client.MessageReceived += handlers.RunCommand; client.MessageReceived += handlers.UpdateStats; @@ -157,21 +153,21 @@ namespace Geekbot.net if (firstStart || args.Contains("--reset")) { - logger.Information("[Geekbot] Finishing setup"); + logger.Information("Geekbot", "Finishing setup"); await FinishSetup(); - logger.Information("[Geekbot] Setup finished"); + logger.Information("Geekbot", "Setup finished"); } if (!args.Contains("--disable-api")) { startWebApi(); } - logger.Information("[Geekbot] Done and ready for use\n"); + logger.Information("Geekbot", "Done and ready for use"); } } catch (Exception e) { - logger.Fatal(e, "Could not connect to discord..."); + logger.Error("Discord", "Could not connect...", e); Environment.Exit(103); } } @@ -185,16 +181,16 @@ namespace Geekbot.net private void startWebApi() { - logger.Information("[API] Starting Webserver"); + logger.Information("API", "Starting Webserver"); var webApiUrl = new Uri("http://localhost:12995"); new NancyHost(webApiUrl).Start(); - logger.Information($"[API] Webserver now running on {webApiUrl}"); + logger.Information("API", $"Webserver now running on {webApiUrl}"); } private async Task FinishSetup() { var appInfo = await client.GetApplicationInfoAsync(); - logger.Information($"[Setup] Just a moment while i setup everything {appInfo.Owner.Username}"); + logger.Information("Setup", $"Just a moment while i setup everything {appInfo.Owner.Username}"); try { redis.StringSet("botOwner", appInfo.Owner.Id); @@ -207,12 +203,11 @@ namespace Geekbot.net User.Username = appInfo.Name.ToString(); }); } - logger.Information($"[Setup] Everything done, enjoy!"); + logger.Information("Setup", "Everything done, enjoy!"); } catch (Exception e) { - logger.Warning(e, "[Setup] Oha, it seems like something went wrong while running the setup"); - logger.Warning("[Setup] Geekbot will work never the less, some features might be disabled though"); + logger.Warning("Setup", "Oha, it seems like something went wrong while running the setup, geekbot will work never the less though", e); } return Task.CompletedTask; } @@ -223,22 +218,20 @@ namespace Geekbot.net switch (message.Severity) { case LogSeverity.Verbose: - logger.Verbose(logMessage); - break; case LogSeverity.Debug: - logger.Debug(logMessage); + logger.Debug(message.Source, message.Message); break; case LogSeverity.Info: - logger.Information(logMessage); + logger.Information(message.Source, message.Message); break; case LogSeverity.Critical: case LogSeverity.Error: case LogSeverity.Warning: if (logMessage.Contains("VOICE_STATE_UPDATE")) break; - logger.Error(message.Exception, logMessage); + logger.Error(message.Source, message.Message, message.Exception); break; default: - logger.Information($"{logMessage} --- {message.Severity}"); + logger.Information(message.Source, $"{logMessage} --- {message.Severity}"); break; } return Task.CompletedTask; From 751c164c820a7daffb84db02176f6bdc1503c10d Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 20 Jan 2018 03:30:42 +0100 Subject: [PATCH 109/553] Log everything to sumologic --- Geekbot.net/Geekbot.net.csproj | 3 ++- Geekbot.net/Lib/GeekbotLogger.cs | 11 ++++++++--- Geekbot.net/Lib/LoggerFactory.cs | 22 +++++++++++----------- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 38e7f94..82b605a 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -25,10 +25,11 @@ - + + 1.2.6 diff --git a/Geekbot.net/Lib/GeekbotLogger.cs b/Geekbot.net/Lib/GeekbotLogger.cs index 46799af..18e8c54 100644 --- a/Geekbot.net/Lib/GeekbotLogger.cs +++ b/Geekbot.net/Lib/GeekbotLogger.cs @@ -1,15 +1,19 @@ using System; using System.Threading.Tasks; +using Serilog; using Utf8Json; +using Utf8Json.Formatters; using Utf8Json.Resolvers; namespace Geekbot.net.Lib { public class GeekbotLogger : IGeekbotLogger { + private readonly ILogger _serilog; public GeekbotLogger() { - JsonSerializer.SetDefaultResolver(StandardResolver.AllowPrivateExcludeNullSnakeCase); + _serilog = LoggerFactory.createLogger(); + //JsonSerializer.SetDefaultResolver(StandardResolver.AllowPrivateExcludeNullSnakeCase); Information("Geekbot", "Using GeekbotLogger"); } @@ -36,7 +40,8 @@ namespace Geekbot.net.Lib private Task HandleLogObject(string type, string source, string message, Exception stackTrace = null, object extra = null) { var logJson = CreateLogObject(type, source, message, null, extra); - Console.WriteLine(logJson); + // fuck serilog + _serilog.Information(logJson + "}"); return Task.CompletedTask; } @@ -51,7 +56,7 @@ namespace Geekbot.net.Lib StackTrace = stackTrace, Extra = extra }; - return Utf8Json.JsonSerializer.ToJsonString(logObject); + return JsonSerializer.ToJsonString(logObject); } } diff --git a/Geekbot.net/Lib/LoggerFactory.cs b/Geekbot.net/Lib/LoggerFactory.cs index d1fe698..789bdc6 100644 --- a/Geekbot.net/Lib/LoggerFactory.cs +++ b/Geekbot.net/Lib/LoggerFactory.cs @@ -1,26 +1,26 @@ using System; using Serilog; -using System.Linq; +using Serilog.Formatting.Json; +using Serilog.Sinks.SumoLogic; namespace Geekbot.net.Lib { public class LoggerFactory { - public static ILogger createLogger(string[] args) + public static ILogger createLogger() { - var loggerCreation = new LoggerConfiguration() - .WriteTo.RollingFile("Logs/geekbot-{Date}.txt", shared: true); - if (!Environment.CurrentDirectory.Contains("deploy")) + var loggerCreation = new LoggerConfiguration(); + var template = "{Message}{NewLine}"; + if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("GEEKBOT_SUMO"))) { - loggerCreation.WriteTo.LiterateConsole(); - } - if (args.Contains("--verbose")) - { - loggerCreation.MinimumLevel.Verbose(); + Console.WriteLine("Logging Geekbot Logs to Sumologic"); + loggerCreation.WriteTo.SumoLogic(Environment.GetEnvironmentVariable("GEEKBOT_SUMO"), + outputTemplate: template); } else { - loggerCreation.MinimumLevel.Information(); + loggerCreation.WriteTo.LiterateConsole(outputTemplate: template); + loggerCreation.WriteTo.RollingFile("Logs/geekbot-{Date}.txt", shared: true, outputTemplate: template); } return loggerCreation.CreateLogger(); } From 815b7d616354dba2fed762f97b5e655161e296b0 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 21 Jan 2018 16:01:43 +0100 Subject: [PATCH 110/553] Add posibility to remove quotes --- Geekbot.net/Commands/Quote.cs | 63 ++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/Geekbot.net/Commands/Quote.cs b/Geekbot.net/Commands/Quote.cs index 5b7e2ee..2567279 100644 --- a/Geekbot.net/Commands/Quote.cs +++ b/Geekbot.net/Commands/Quote.cs @@ -12,13 +12,13 @@ namespace Geekbot.net.Commands [Group("quote")] public class Quote : ModuleBase { - private readonly IErrorHandler errorHandler; - private readonly IDatabase redis; + private readonly IErrorHandler _errorHandler; + private readonly IDatabase _redis; - public Quote(IDatabase redis, IErrorHandler errorHandler) + public Quote(IDatabase redis, IErrorHandler errorHandler, Random random) { - this.redis = redis; - this.errorHandler = errorHandler; + _redis = redis; + _errorHandler = errorHandler; } [Command] @@ -26,16 +26,18 @@ namespace Geekbot.net.Commands [Summary("Return a random quoute from the database")] public async Task getRandomQuote() { - var randomQuote = redis.SetRandomMember($"{Context.Guild.Id}:Quotes"); try { + var randomQuotes = _redis.SetMembers($"{Context.Guild.Id}:Quotes"); + var randomNumber = new Random().Next(randomQuotes.Length - 1); + var randomQuote = randomQuotes[randomNumber]; var quote = JsonConvert.DeserializeObject(randomQuote); - var embed = quoteBuilder(quote); + var embed = quoteBuilder(quote, randomNumber + 1); await ReplyAsync("", false, embed.Build()); } catch (Exception e) { - errorHandler.HandleCommandException(e, Context, "Whoops, seems like the quote was to edgy to return"); + _errorHandler.HandleCommandException(e, Context, "Whoops, seems like the quote was to edgy to return"); } } @@ -61,13 +63,13 @@ namespace Geekbot.net.Commands var lastMessage = await getLastMessageByUser(user); var quote = createQuoteObject(lastMessage); var quoteStore = JsonConvert.SerializeObject(quote); - redis.SetAdd($"{Context.Guild.Id}:Quotes", quoteStore); + _redis.SetAdd($"{Context.Guild.Id}:Quotes", quoteStore); var embed = quoteBuilder(quote); await ReplyAsync("**Quote Added**", false, embed.Build()); } catch (Exception e) { - errorHandler.HandleCommandException(e, Context, + _errorHandler.HandleCommandException(e, Context, "I counldn't find a quote from that user :disappointed:"); } } @@ -94,13 +96,13 @@ namespace Geekbot.net.Commands var quote = createQuoteObject(message); var quoteStore = JsonConvert.SerializeObject(quote); - redis.SetAdd($"{Context.Guild.Id}:Quotes", quoteStore); + _redis.SetAdd($"{Context.Guild.Id}:Quotes", quoteStore); var embed = quoteBuilder(quote); await ReplyAsync("**Quote Added**", false, embed.Build()); } catch (Exception e) { - errorHandler.HandleCommandException(e, Context, + _errorHandler.HandleCommandException(e, Context, "I couldn't find a message with that id :disappointed:"); } } @@ -119,7 +121,7 @@ namespace Geekbot.net.Commands } catch (Exception e) { - errorHandler.HandleCommandException(e, Context, + _errorHandler.HandleCommandException(e, Context, "I counldn't find a quote from that user :disappointed:"); } } @@ -138,10 +140,38 @@ namespace Geekbot.net.Commands } catch (Exception e) { - errorHandler.HandleCommandException(e, Context, + _errorHandler.HandleCommandException(e, Context, "I couldn't find a message with that id :disappointed:"); } } + + [Command("remove")] + [RequireUserPermission(GuildPermission.KickMembers)] + [RequireUserPermission(GuildPermission.ManageMessages)] + [RequireUserPermission(GuildPermission.ManageRoles)] + [Remarks(CommandCategories.Quotes)] + [Summary("Remove a quote (required mod permissions)")] + public async Task removeQuote([Summary("quoteId")] int id) + { + try + { + var quotes = _redis.SetMembers($"{Context.Guild.Id}:Quotes"); + var success = _redis.SetRemove($"{Context.Guild.Id}:Quotes", quotes[id - 1]); + if (success) + { + await ReplyAsync($"Removed quote #{id}"); + } + else + { + await ReplyAsync($"I couldn't find a quote with that id :disappointed:"); + } + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context, + "I couldn't find a quote with that id :disappointed:"); + } + } private async Task getLastMessageByUser(IUser user) { @@ -154,12 +184,13 @@ namespace Geekbot.net.Commands && !msg.Content.ToLower().StartsWith("!")); } - private EmbedBuilder quoteBuilder(QuoteObject quote) + private EmbedBuilder quoteBuilder(QuoteObject quote, int id = 0) { var user = Context.Client.GetUserAsync(quote.userId).Result; var eb = new EmbedBuilder(); eb.WithColor(new Color(143, 167, 232)); - eb.Title = $"{user.Username} @ {quote.time.Day}.{quote.time.Month}.{quote.time.Year}"; + eb.Title = id == 0 ? "" : $"#{id} | "; + eb.Title += $"{user.Username} @ {quote.time.Day}.{quote.time.Month}.{quote.time.Year}"; eb.Description = quote.quote; eb.ThumbnailUrl = user.GetAvatarUrl(); if (quote.image != null) eb.ImageUrl = quote.image; From a65f9d29639385d29d8eafa0ba7942afc197be9e Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 21 Jan 2018 17:17:55 +0100 Subject: [PATCH 111/553] Show removed quote as conformation --- Geekbot.net/Commands/Quote.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Geekbot.net/Commands/Quote.cs b/Geekbot.net/Commands/Quote.cs index 2567279..c3bb235 100644 --- a/Geekbot.net/Commands/Quote.cs +++ b/Geekbot.net/Commands/Quote.cs @@ -159,7 +159,9 @@ namespace Geekbot.net.Commands var success = _redis.SetRemove($"{Context.Guild.Id}:Quotes", quotes[id - 1]); if (success) { - await ReplyAsync($"Removed quote #{id}"); + var quote = JsonConvert.DeserializeObject(quotes[id - 1]); + var embed = quoteBuilder(quote); + await ReplyAsync($"**Removed #{id}**", false, embed.Build()); } else { From ffaedfa96214d07c700b8787f3ea59e5b8a572a9 Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 29 Jan 2018 23:27:28 +0100 Subject: [PATCH 112/553] Add space to emojis in emojihandler --- Geekbot.net/Lib/EmojiConverter.cs | 84 +++++++++++++++---------------- Tests/Lib/EmojiConverter.test.cs | 4 +- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/Geekbot.net/Lib/EmojiConverter.cs b/Geekbot.net/Lib/EmojiConverter.cs index 60e75f4..7091f0c 100644 --- a/Geekbot.net/Lib/EmojiConverter.cs +++ b/Geekbot.net/Lib/EmojiConverter.cs @@ -37,48 +37,48 @@ namespace Geekbot.net.Lib { var emojiMap = new Hashtable { - ['A'] = ":regional_indicator_a:", - ['B'] = ":b:", - ['C'] = ":regional_indicator_c:", - ['D'] = ":regional_indicator_d:", - ['E'] = ":regional_indicator_e:", - ['F'] = ":regional_indicator_f:", - ['G'] = ":regional_indicator_g:", - ['H'] = ":regional_indicator_h:", - ['I'] = ":regional_indicator_i:", - ['J'] = ":regional_indicator_j:", - ['K'] = ":regional_indicator_k:", - ['L'] = ":regional_indicator_l:", - ['M'] = ":regional_indicator_m:", - ['N'] = ":regional_indicator_n:", - ['O'] = ":regional_indicator_o:", - ['P'] = ":regional_indicator_p:", - ['Q'] = ":regional_indicator_q:", - ['R'] = ":regional_indicator_r:", - ['S'] = ":regional_indicator_s:", - ['T'] = ":regional_indicator_t:", - ['U'] = ":regional_indicator_u:", - ['V'] = ":regional_indicator_v:", - ['W'] = ":regional_indicator_w:", - ['X'] = ":regional_indicator_x:", - ['Y'] = ":regional_indicator_y:", - ['Z'] = ":regional_indicator_z:", - ['!'] = ":exclamation:", - ['?'] = ":question:", - ['#'] = ":hash:", - ['*'] = ":star2:", - ['+'] = ":heavy_plus_sign:", - ['0'] = ":zero:", - ['1'] = ":one:", - ['2'] = ":two:", - ['3'] = ":three:", - ['4'] = ":four:", - ['5'] = ":five:", - ['6'] = ":six:", - ['7'] = ":seven:", - ['8'] = ":eight:", - ['9'] = ":nine:", - [' '] = " " + ['A'] = ":regional_indicator_a: ", + ['B'] = ":b: ", + ['C'] = ":regional_indicator_c: ", + ['D'] = ":regional_indicator_d: ", + ['E'] = ":regional_indicator_e: ", + ['F'] = ":regional_indicator_f: ", + ['G'] = ":regional_indicator_g: ", + ['H'] = ":regional_indicator_h: ", + ['I'] = ":regional_indicator_i: ", + ['J'] = ":regional_indicator_j: ", + ['K'] = ":regional_indicator_k: ", + ['L'] = ":regional_indicator_l: ", + ['M'] = ":regional_indicator_m: ", + ['N'] = ":regional_indicator_n: ", + ['O'] = ":regional_indicator_o: ", + ['P'] = ":regional_indicator_p: ", + ['Q'] = ":regional_indicator_q: ", + ['R'] = ":regional_indicator_r: ", + ['S'] = ":regional_indicator_s: ", + ['T'] = ":regional_indicator_t: ", + ['U'] = ":regional_indicator_u: ", + ['V'] = ":regional_indicator_v: ", + ['W'] = ":regional_indicator_w: ", + ['X'] = ":regional_indicator_x: ", + ['Y'] = ":regional_indicator_y: ", + ['Z'] = ":regional_indicator_z: ", + ['!'] = ":exclamation: ", + ['?'] = ":question: ", + ['#'] = ":hash: ", + ['*'] = ":star2: ", + ['+'] = ":heavy_plus_sign: ", + ['0'] = ":zero: ", + ['1'] = ":one: ", + ['2'] = ":two: ", + ['3'] = ":three: ", + ['4'] = ":four: ", + ['5'] = ":five: ", + ['6'] = ":six: ", + ['7'] = ":seven: ", + ['8'] = ":eight: ", + ['9'] = ":nine: ", + [' '] = " " }; var letters = text.ToUpper().ToCharArray(); var returnString = new StringBuilder(); diff --git a/Tests/Lib/EmojiConverter.test.cs b/Tests/Lib/EmojiConverter.test.cs index ca4ecbc..bf41596 100644 --- a/Tests/Lib/EmojiConverter.test.cs +++ b/Tests/Lib/EmojiConverter.test.cs @@ -53,12 +53,12 @@ namespace Tests.Lib yield return new object[] { "test", - ":regional_indicator_t::regional_indicator_e::regional_indicator_s::regional_indicator_t:" + ":regional_indicator_t: :regional_indicator_e: :regional_indicator_s: :regional_indicator_t: " }; yield return new object[] { "Best3+?", - ":b::regional_indicator_e::regional_indicator_s::regional_indicator_t::three::heavy_plus_sign::question:" + ":b: :regional_indicator_e: :regional_indicator_s: :regional_indicator_t: :three: :heavy_plus_sign: :question: " }; } } From 91d178049b19fbd7e951eeec245abf3ff698de64 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sat, 3 Feb 2018 15:14:11 +0100 Subject: [PATCH 113/553] Error when removing non-existing role from whitelist --- Geekbot.net/Commands/Role.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Geekbot.net/Commands/Role.cs b/Geekbot.net/Commands/Role.cs index 77e917f..80ef4af 100644 --- a/Geekbot.net/Commands/Role.cs +++ b/Geekbot.net/Commands/Role.cs @@ -134,8 +134,16 @@ namespace Geekbot.net.Commands { try { - _redis.HashDelete($"{Context.Guild.Id}:RoleWhitelist", roleName); - await ReplyAsync($"Removed {roleName} from the whitelist"); + + var success = _redis.HashDelete($"{Context.Guild.Id}:RoleWhitelist", roleName.ToLower()); + if (success) + { + await ReplyAsync($"Removed {roleName} from the whitelist"); + return; + } + + await ReplyAsync("There is not whitelisted role with that name..."); + } catch (Exception e) { From ff1619a62ff12727c1552ba9fe267b10dfd694a6 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 4 Feb 2018 14:47:10 +0100 Subject: [PATCH 114/553] Ignore error 50007 and 50013 --- Geekbot.net/Lib/ErrorHandler.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Geekbot.net/Lib/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandler.cs index 6cc6644..e6ea44e 100644 --- a/Geekbot.net/Lib/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandler.cs @@ -42,6 +42,8 @@ namespace Geekbot.net.Lib { var errorString = errorMessage == "def" ? _translation.GetString(Context.Guild.Id, "errorHandler", "SomethingWentWrong") : errorMessage; var errorObj = SimpleConextConverter.ConvertContext(Context); + if (errorObj.Message.Content.Contains("50007")) return; + if (errorObj.Message.Content.Contains("50013")) return; _logger.Error("Geekbot", "An error ocured", e, errorObj); if (!string.IsNullOrEmpty(errorMessage)) { @@ -49,7 +51,7 @@ namespace Geekbot.net.Lib } if (_raven == null) return; - + var sentryEvent = new SentryEvent(e) { Tags = From 8d23420031aa6e27c7ea96131ee2bf5ef7a57d13 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 4 Feb 2018 14:52:30 +0100 Subject: [PATCH 115/553] Remove test warnings --- Tests/Lib/EmojiConverter.test.cs | 4 ++-- Tests/Lib/LevelCalc.test.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Tests/Lib/EmojiConverter.test.cs b/Tests/Lib/EmojiConverter.test.cs index bf41596..b9e7b4f 100644 --- a/Tests/Lib/EmojiConverter.test.cs +++ b/Tests/Lib/EmojiConverter.test.cs @@ -39,7 +39,7 @@ namespace Tests.Lib [Theory, MemberData(nameof(NumberToEmojiTestData))] - public async Task NumberToEmoji(int number, string expectedResult) + public void NumberToEmoji(int number, string expectedResult) { var emojiConverter = new EmojiConverter(); var result = emojiConverter.numberToEmoji(number); @@ -65,7 +65,7 @@ namespace Tests.Lib [Theory, MemberData(nameof(textToEmojiTestData))] - public async Task TextToEmoji(string text, string expectedResult) + public void TextToEmoji(string text, string expectedResult) { var emojiConverter = new EmojiConverter(); var result = emojiConverter.textToEmoji(text); diff --git a/Tests/Lib/LevelCalc.test.cs b/Tests/Lib/LevelCalc.test.cs index 74e6105..7c00392 100644 --- a/Tests/Lib/LevelCalc.test.cs +++ b/Tests/Lib/LevelCalc.test.cs @@ -39,7 +39,7 @@ namespace Tests.Lib [Theory, MemberData(nameof(LevelCalcTestData))] - public async Task GetLevel(int messages, int expectedResult) + public void GetLevel(int messages, int expectedResult) { var levelCalc = new LevelCalc(); var result = levelCalc.GetLevel(messages); From 46696549d77a2f17c9350f0d45716c6f0cb70471 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 4 Feb 2018 17:36:55 +0100 Subject: [PATCH 116/553] Check correct string to ignore errors *facepalm* --- Geekbot.net/Lib/ErrorHandler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Geekbot.net/Lib/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandler.cs index e6ea44e..bd82668 100644 --- a/Geekbot.net/Lib/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandler.cs @@ -42,8 +42,8 @@ namespace Geekbot.net.Lib { var errorString = errorMessage == "def" ? _translation.GetString(Context.Guild.Id, "errorHandler", "SomethingWentWrong") : errorMessage; var errorObj = SimpleConextConverter.ConvertContext(Context); - if (errorObj.Message.Content.Contains("50007")) return; - if (errorObj.Message.Content.Contains("50013")) return; + if (e.Message.Contains("50007")) return; + if (e.Message.Contains("50013")) return; _logger.Error("Geekbot", "An error ocured", e, errorObj); if (!string.IsNullOrEmpty(errorMessage)) { From 6fd36e0bb254a2bb81e242db0df17809ba9a5315 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Tue, 13 Feb 2018 22:29:37 +0100 Subject: [PATCH 117/553] Show mana costs as emojis in mtg --- Geekbot.net/Commands/MagicTheGathering.cs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/Geekbot.net/Commands/MagicTheGathering.cs b/Geekbot.net/Commands/MagicTheGathering.cs index e2702b1..bd0fd0a 100644 --- a/Geekbot.net/Commands/MagicTheGathering.cs +++ b/Geekbot.net/Commands/MagicTheGathering.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.RegularExpressions; using System.Threading.Tasks; using Discord; using Discord.Commands; @@ -12,10 +13,12 @@ namespace Geekbot.net.Commands public class Magicthegathering : ModuleBase { private readonly IErrorHandler _errorHandler; + private readonly IEmojiConverter _emojiConverter; - public Magicthegathering(IErrorHandler errorHandler) + public Magicthegathering(IErrorHandler errorHandler, IEmojiConverter emojiConverter) { _errorHandler = errorHandler; + _emojiConverter = emojiConverter; } [Command("mtg", RunMode = RunMode.Async)] @@ -51,7 +54,7 @@ namespace Geekbot.net.Commands if (!string.IsNullOrEmpty(card.Loyalty)) eb.AddInlineField("Loyality", card.Loyalty); if (!string.IsNullOrEmpty(card.Toughness)) eb.AddInlineField("Thoughness", card.Toughness); - if (!string.IsNullOrEmpty(card.ManaCost)) eb.AddInlineField("Cost", card.ManaCost); + if (!string.IsNullOrEmpty(card.ManaCost)) eb.AddInlineField("Cost", ManaConverter(card.ManaCost)); if (!string.IsNullOrEmpty(card.Rarity)) eb.AddInlineField("Rarity", card.Rarity); if (card.Legalities != null) @@ -84,5 +87,21 @@ namespace Geekbot.net.Commands return new Color(255, 252, 214); } } + + private string ManaConverter(string mana) + { + var rgx = new Regex("{(\\d)}"); + var groups = rgx.Match(mana).Groups; + if (groups.Count == 2) + { + mana = mana.Replace(groups[0].Value, _emojiConverter.numberToEmoji(int.Parse(groups[1].Value))); + } + return mana + .Replace("{W}", ":sunny:") + .Replace("{U}", ":droplet:") + .Replace("{B}", ":skull:") + .Replace("{R}", ":fire:") + .Replace("{G}", ":deciduous_tree:"); + } } } \ No newline at end of file From 03ed80d3d452f476ebd920e526a49909d7671fea Mon Sep 17 00:00:00 2001 From: Runebaas Date: Tue, 13 Feb 2018 23:42:31 +0100 Subject: [PATCH 118/553] Log command usage --- Geekbot.net/Handlers.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index 13ce041..1aa2a05 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -56,6 +56,9 @@ namespace Geekbot.net message.HasMentionPrefix(_client.CurrentUser, ref argPos))) return Task.CompletedTask; var context = new CommandContext(_client, message); var commandExec = _commands.ExecuteAsync(context, argPos, _servicesProvider); + _logger.Information("Command", + context.Message.Content.Split(" ")[0].Replace("!", ""), + SimpleConextConverter.ConvertContext(context)); return Task.CompletedTask; } catch (Exception e) From cabf9423623ff554e10eb3b886df7b4962320cc1 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Wed, 14 Feb 2018 11:35:12 +0100 Subject: [PATCH 119/553] unpin --- Geekbot.net/Handlers.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index 1aa2a05..aa8a154 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -42,11 +42,6 @@ namespace Geekbot.net if (message.Author.IsBot) return Task.CompletedTask; var argPos = 0; var lowCaseMsg = message.ToString().ToLower(); - if (lowCaseMsg.Equals("ping") || lowCaseMsg.StartsWith("ping ")) - { - message.Channel.SendMessageAsync("pong"); - return Task.CompletedTask; - } if (lowCaseMsg.StartsWith("hui")) { message.Channel.SendMessageAsync("hui!!!"); @@ -186,4 +181,4 @@ namespace Geekbot.net } } } -} \ No newline at end of file +} From acc8947782fb848afb7b7154c534ca962490c4c0 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Wed, 14 Feb 2018 23:01:28 +0100 Subject: [PATCH 120/553] Make random more random than the google bot --- Geekbot.net/Commands/CheckEm.cs | 6 ++---- Geekbot.net/Commands/Choose.cs | 6 ++---- Geekbot.net/Commands/Dice.cs | 9 +-------- Geekbot.net/Commands/EightBall.cs | 6 ++---- Geekbot.net/Commands/Quote.cs | 2 +- Geekbot.net/Commands/Roll.cs | 6 ++---- Geekbot.net/Commands/Ship.cs | 6 ++---- Geekbot.net/Commands/Slap.cs | 6 ++---- Geekbot.net/Lib/Media/FortunesProvider.cs | 6 ++---- Geekbot.net/Lib/Media/MediaProvider.cs | 4 ++-- Geekbot.net/Program.cs | 6 ++---- 11 files changed, 20 insertions(+), 43 deletions(-) diff --git a/Geekbot.net/Commands/CheckEm.cs b/Geekbot.net/Commands/CheckEm.cs index 11d0cef..61de091 100644 --- a/Geekbot.net/Commands/CheckEm.cs +++ b/Geekbot.net/Commands/CheckEm.cs @@ -12,11 +12,9 @@ namespace Geekbot.net.Commands { private readonly IMediaProvider _checkEmImages; private readonly IErrorHandler _errorHandler; - private readonly Random _rnd; - public CheckEm(Random RandomClient, IMediaProvider mediaProvider, IErrorHandler errorHandler) + public CheckEm(IMediaProvider mediaProvider, IErrorHandler errorHandler) { - _rnd = RandomClient; _checkEmImages = mediaProvider; _errorHandler = errorHandler; } @@ -28,7 +26,7 @@ namespace Geekbot.net.Commands { try { - var number = _rnd.Next(10000000, 99999999); + var number = new Random().Next(10000000, 99999999); var dubtriqua = ""; var ns = GetIntArray(number); diff --git a/Geekbot.net/Commands/Choose.cs b/Geekbot.net/Commands/Choose.cs index 214a1a8..a726741 100644 --- a/Geekbot.net/Commands/Choose.cs +++ b/Geekbot.net/Commands/Choose.cs @@ -8,12 +8,10 @@ namespace Geekbot.net.Commands public class Choose : ModuleBase { private readonly IErrorHandler _errorHandler; - private readonly Random _rnd; private readonly ITranslationHandler _translation; - public Choose(Random RandomClient, IErrorHandler errorHandler, ITranslationHandler translation) + public Choose(IErrorHandler errorHandler, ITranslationHandler translation) { - _rnd = RandomClient; _errorHandler = errorHandler; _translation = translation; } @@ -28,7 +26,7 @@ namespace Geekbot.net.Commands { var transDict = _translation.GetDict(Context); var choicesArray = choices.Split(';'); - var choice = _rnd.Next(choicesArray.Length); + var choice = new Random().Next(choicesArray.Length); await ReplyAsync(string.Format(transDict["Choice"], choicesArray[choice])); } catch (Exception e) diff --git a/Geekbot.net/Commands/Dice.cs b/Geekbot.net/Commands/Dice.cs index 9195be8..774f8b9 100644 --- a/Geekbot.net/Commands/Dice.cs +++ b/Geekbot.net/Commands/Dice.cs @@ -10,13 +10,6 @@ namespace Geekbot.net.Commands { public class Dice : ModuleBase { - private readonly Random _rnd; - - public Dice(Random RandomClient) - { - _rnd = RandomClient; - } - [Command("dice", RunMode = RunMode.Async)] [Remarks(CommandCategories.Randomness)] [Summary("Roll a dice.")] @@ -75,7 +68,7 @@ namespace Geekbot.net.Commands var results = new List(); for (var i = 0; i < dice.times; i++) { - var roll = _rnd.Next(1, dice.sides); + var roll = new Random().Next(1, dice.sides); total += roll; results.Add(roll); if (roll == dice.sides) extraText = "**Critical Hit!**"; diff --git a/Geekbot.net/Commands/EightBall.cs b/Geekbot.net/Commands/EightBall.cs index 5cadee5..94b01a1 100644 --- a/Geekbot.net/Commands/EightBall.cs +++ b/Geekbot.net/Commands/EightBall.cs @@ -9,11 +9,9 @@ namespace Geekbot.net.Commands public class EightBall : ModuleBase { private readonly IErrorHandler _errorHandler; - private readonly Random _rnd; - public EightBall(Random RandomClient, IErrorHandler errorHandler) + public EightBall(IErrorHandler errorHandler) { - _rnd = RandomClient; _errorHandler = errorHandler; } @@ -48,7 +46,7 @@ namespace Geekbot.net.Commands "Very doubtful" }; - var answer = _rnd.Next(replies.Count); + var answer = new Random().Next(replies.Count); await ReplyAsync(replies[answer]); } catch (Exception e) diff --git a/Geekbot.net/Commands/Quote.cs b/Geekbot.net/Commands/Quote.cs index c3bb235..fc4e2ce 100644 --- a/Geekbot.net/Commands/Quote.cs +++ b/Geekbot.net/Commands/Quote.cs @@ -15,7 +15,7 @@ namespace Geekbot.net.Commands private readonly IErrorHandler _errorHandler; private readonly IDatabase _redis; - public Quote(IDatabase redis, IErrorHandler errorHandler, Random random) + public Quote(IDatabase redis, IErrorHandler errorHandler) { _redis = redis; _errorHandler = errorHandler; diff --git a/Geekbot.net/Commands/Roll.cs b/Geekbot.net/Commands/Roll.cs index 33cdf67..8d4854c 100644 --- a/Geekbot.net/Commands/Roll.cs +++ b/Geekbot.net/Commands/Roll.cs @@ -10,13 +10,11 @@ namespace Geekbot.net.Commands { private readonly IErrorHandler _errorHandler; private readonly IDatabase _redis; - private readonly Random _rnd; private readonly ITranslationHandler _translation; - public Roll(IDatabase redis, Random RandomClient, IErrorHandler errorHandler, ITranslationHandler translation) + public Roll(IDatabase redis, IErrorHandler errorHandler, ITranslationHandler translation) { _redis = redis; - _rnd = RandomClient; _translation = translation; _errorHandler = errorHandler; } @@ -28,7 +26,7 @@ namespace Geekbot.net.Commands { try { - var number = _rnd.Next(1, 100); + var number = new Random().Next(1, 100); var guess = 1000; int.TryParse(stuff, out guess); var transDict = _translation.GetDict(Context); diff --git a/Geekbot.net/Commands/Ship.cs b/Geekbot.net/Commands/Ship.cs index 7b85eb0..4727bc8 100644 --- a/Geekbot.net/Commands/Ship.cs +++ b/Geekbot.net/Commands/Ship.cs @@ -11,12 +11,10 @@ namespace Geekbot.net.Commands { private readonly IErrorHandler _errorHandler; private readonly IDatabase _redis; - private readonly Random _rnd; - public Ship(IDatabase redis, Random randomClient, IErrorHandler errorHandler) + public Ship(IDatabase redis, IErrorHandler errorHandler) { _redis = redis; - _rnd = randomClient; _errorHandler = errorHandler; } @@ -37,7 +35,7 @@ namespace Geekbot.net.Commands var shippingRate = 0; if (dbval.IsNullOrEmpty) { - shippingRate = _rnd.Next(1, 100); + shippingRate = new Random().Next(1, 100); _redis.HashSet($"{Context.Guild.Id}:Ships", dbstring, shippingRate); } else diff --git a/Geekbot.net/Commands/Slap.cs b/Geekbot.net/Commands/Slap.cs index 134752c..24ba835 100644 --- a/Geekbot.net/Commands/Slap.cs +++ b/Geekbot.net/Commands/Slap.cs @@ -11,13 +11,11 @@ namespace Geekbot.net.Commands public class Slap : ModuleBase { private readonly IErrorHandler _errorHandler; - private readonly Random _random; private readonly IDatabase _redis; - public Slap(IErrorHandler errorHandler, Random random, IDatabase redis) + public Slap(IErrorHandler errorHandler, IDatabase redis) { _errorHandler = errorHandler; - _random = random; _redis = redis; } @@ -61,7 +59,7 @@ namespace Geekbot.net.Commands _redis.HashIncrement($"{Context.Guild.Id}:SlapsRecieved", user.Id.ToString()); _redis.HashIncrement($"{Context.Guild.Id}:SlapsGiven", Context.User.Id.ToString()); - await ReplyAsync($"{Context.User.Username} slapped {user.Username} with a {things[_random.Next(things.Count - 1)]}"); + await ReplyAsync($"{Context.User.Username} slapped {user.Username} with a {things[new Random().Next(things.Count - 1)]}"); } catch (Exception e) { diff --git a/Geekbot.net/Lib/Media/FortunesProvider.cs b/Geekbot.net/Lib/Media/FortunesProvider.cs index f536074..8a9b6f0 100644 --- a/Geekbot.net/Lib/Media/FortunesProvider.cs +++ b/Geekbot.net/Lib/Media/FortunesProvider.cs @@ -7,10 +7,9 @@ namespace Geekbot.net.Lib.Media internal class FortunesProvider : IFortunesProvider { private readonly string[] fortuneArray; - private readonly Random rnd; private readonly int totalFortunes; - public FortunesProvider(Random rnd, IGeekbotLogger logger) + public FortunesProvider(IGeekbotLogger logger) { var path = Path.GetFullPath("./Storage/fortunes"); if (File.Exists(path)) @@ -18,7 +17,6 @@ namespace Geekbot.net.Lib.Media var rawFortunes = File.ReadAllText(path); fortuneArray = rawFortunes.Split("%"); totalFortunes = fortuneArray.Length; - this.rnd = rnd; logger.Debug("Geekbot", "Loaded {totalFortunes} Fortunes"); } else @@ -29,7 +27,7 @@ namespace Geekbot.net.Lib.Media public string GetRandomFortune() { - return fortuneArray[rnd.Next(0, totalFortunes)]; + return fortuneArray[new Random().Next(0, totalFortunes)]; } } diff --git a/Geekbot.net/Lib/Media/MediaProvider.cs b/Geekbot.net/Lib/Media/MediaProvider.cs index ce5a0cd..0a3ff6c 100644 --- a/Geekbot.net/Lib/Media/MediaProvider.cs +++ b/Geekbot.net/Lib/Media/MediaProvider.cs @@ -17,9 +17,9 @@ namespace Geekbot.net.Lib.Media private string[] _pumpkinImages; private string[] _turtlesImages; - public MediaProvider(Random rnd, IGeekbotLogger logger) + public MediaProvider(IGeekbotLogger logger) { - _random = rnd; + _random = new Random(); _logger = logger; logger.Information("Geekbot", "Loading Media Files"); diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index da74508..c47fdb4 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -94,9 +94,8 @@ namespace Geekbot.net services = new ServiceCollection(); userRepository = new UserRepository(redis, logger); - var randomClient = new Random(); - var fortunes = new FortunesProvider(randomClient, logger); - var mediaProvider = new MediaProvider(randomClient, logger); + var fortunes = new FortunesProvider(logger); + var mediaProvider = new MediaProvider(logger); var malClient = new MalClient(redis, logger); var levelCalc = new LevelCalc(); var emojiConverter = new EmojiConverter(); @@ -108,7 +107,6 @@ namespace Geekbot.net services.AddSingleton(levelCalc); services.AddSingleton(emojiConverter); services.AddSingleton(audioUtils); - services.AddSingleton(randomClient); services.AddSingleton(fortunes); services.AddSingleton(mediaProvider); services.AddSingleton(malClient); From d40d89506e8a04c3c931628be218705a98d37408 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Wed, 14 Feb 2018 23:40:44 +0100 Subject: [PATCH 121/553] Upgrade UTF8JSON to 1.3.7 --- Geekbot.net/Geekbot.net.csproj | 2 +- Geekbot.net/Lib/ErrorHandler.cs | 6 ------ Geekbot.net/Lib/GeekbotLogger.cs | 4 +--- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 82b605a..89aab56 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -42,7 +42,7 @@ 4.3.0 - + diff --git a/Geekbot.net/Lib/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandler.cs index bd82668..3410e91 100644 --- a/Geekbot.net/Lib/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandler.cs @@ -1,15 +1,9 @@ using System; using System.Net; -using System.Runtime.InteropServices.ComTypes; -using System.Security.Principal; using Discord.Commands; using Discord.Net; -using Nancy.Extensions; -using Serilog; using SharpRaven; using SharpRaven.Data; -using SharpRaven.Utilities; -using Utf8Json; namespace Geekbot.net.Lib { diff --git a/Geekbot.net/Lib/GeekbotLogger.cs b/Geekbot.net/Lib/GeekbotLogger.cs index 18e8c54..f2feda7 100644 --- a/Geekbot.net/Lib/GeekbotLogger.cs +++ b/Geekbot.net/Lib/GeekbotLogger.cs @@ -2,8 +2,6 @@ using System.Threading.Tasks; using Serilog; using Utf8Json; -using Utf8Json.Formatters; -using Utf8Json.Resolvers; namespace Geekbot.net.Lib { @@ -39,7 +37,7 @@ namespace Geekbot.net.Lib private Task HandleLogObject(string type, string source, string message, Exception stackTrace = null, object extra = null) { - var logJson = CreateLogObject(type, source, message, null, extra); + var logJson = CreateLogObject(type, source, message, stackTrace, extra); // fuck serilog _serilog.Information(logJson + "}"); return Task.CompletedTask; From 1c88dea796ea9c5ad91f6db6be20d10bca1823eb Mon Sep 17 00:00:00 2001 From: Runebaas Date: Thu, 15 Feb 2018 00:07:11 +0100 Subject: [PATCH 122/553] Don't error in rank when no entries are found or bot is not included --- Geekbot.net/Commands/Rank.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Geekbot.net/Commands/Rank.cs b/Geekbot.net/Commands/Rank.cs index 516c2aa..8c11171 100644 --- a/Geekbot.net/Commands/Rank.cs +++ b/Geekbot.net/Commands/Rank.cs @@ -56,9 +56,18 @@ namespace Geekbot.net.Commands } var messageList = _redis.HashGetAll($"{Context.Guild.Id}:{type}"); + if (messageList.Length == 0) + { + await ReplyAsync($"No {type.ToLowerInvariant()} found on this server"); + return; + } var sortedList = messageList.OrderByDescending(e => e.Value).ToList(); var guildMessages = (int) sortedList.First().Value; - sortedList.Remove(sortedList.Single(e => e.Name.ToString().Equals(_client.CurrentUser.Id.ToString()))); + var theBot = sortedList.FirstOrDefault(e => e.Name.ToString().Equals(_client.CurrentUser.Id.ToString())); + if (!string.IsNullOrEmpty(theBot.Name)) + { + sortedList.Remove(theBot); + } if (type == "Messages") sortedList.RemoveAt(0); var highscoreUsers = new Dictionary(); From 0498998630c1236dafb447ce78fded1fe7872723 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Fri, 16 Feb 2018 08:36:26 +0100 Subject: [PATCH 123/553] Add more things to slap --- Geekbot.net/Commands/Slap.cs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/Geekbot.net/Commands/Slap.cs b/Geekbot.net/Commands/Slap.cs index 24ba835..09a6c15 100644 --- a/Geekbot.net/Commands/Slap.cs +++ b/Geekbot.net/Commands/Slap.cs @@ -53,7 +53,28 @@ namespace Geekbot.net.Commands "sunflower", "mousepad", "lolipop", - "bottle of rum" + "bottle of rum", + "cheese slice", + "critical 1", + "natural 20", + "mjölnir (aka mewmew)", + "kamehameha", + "copy of Twilight", + "med pack (get ready for the end boss)", + "derp", + "condom (used)", + "gremlin fed after midnight", + "wet baguette", + "exploding kitten", + "shiny piece of shit", + "mismatched pair of socks", + "horcrux", + "tuna", + "suggestion", + "teapot", + "candle", + "dictionary", + "powerless banhammer" }; _redis.HashIncrement($"{Context.Guild.Id}:SlapsRecieved", user.Id.ToString()); From 3e859e85332caac505963d864052bfb04cac9662 Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 19 Feb 2018 21:35:45 +0100 Subject: [PATCH 124/553] Add real mana icons to mtg command --- Geekbot.net/Commands/MagicTheGathering.cs | 26 ++----- Geekbot.net/Lib/MtgManaConverter.cs | 85 +++++++++++++++++++++++ Geekbot.net/Lib/SimpleConextConverter.cs | 28 +------- Geekbot.net/Program.cs | 2 + 4 files changed, 93 insertions(+), 48 deletions(-) create mode 100644 Geekbot.net/Lib/MtgManaConverter.cs diff --git a/Geekbot.net/Commands/MagicTheGathering.cs b/Geekbot.net/Commands/MagicTheGathering.cs index bd0fd0a..e3cc864 100644 --- a/Geekbot.net/Commands/MagicTheGathering.cs +++ b/Geekbot.net/Commands/MagicTheGathering.cs @@ -13,12 +13,12 @@ namespace Geekbot.net.Commands public class Magicthegathering : ModuleBase { private readonly IErrorHandler _errorHandler; - private readonly IEmojiConverter _emojiConverter; + private readonly IMtgManaConverter _manaConverter; - public Magicthegathering(IErrorHandler errorHandler, IEmojiConverter emojiConverter) + public Magicthegathering(IErrorHandler errorHandler, IMtgManaConverter manaConverter) { _errorHandler = errorHandler; - _emojiConverter = emojiConverter; + _manaConverter = manaConverter; } [Command("mtg", RunMode = RunMode.Async)] @@ -46,7 +46,7 @@ namespace Geekbot.net.Commands if (card.ImageUrl != null) eb.ImageUrl = card.ImageUrl.ToString(); - if (!string.IsNullOrEmpty(card.Text)) eb.AddField("Text", card.Text); + if (!string.IsNullOrEmpty(card.Text)) eb.AddField("Text", _manaConverter.ConvertMana(card.Text)); if (!string.IsNullOrEmpty(card.Flavor)) eb.AddField("Flavor", card.Flavor); if (!string.IsNullOrEmpty(card.SetName)) eb.AddInlineField("Set", card.SetName); @@ -54,7 +54,7 @@ namespace Geekbot.net.Commands if (!string.IsNullOrEmpty(card.Loyalty)) eb.AddInlineField("Loyality", card.Loyalty); if (!string.IsNullOrEmpty(card.Toughness)) eb.AddInlineField("Thoughness", card.Toughness); - if (!string.IsNullOrEmpty(card.ManaCost)) eb.AddInlineField("Cost", ManaConverter(card.ManaCost)); + if (!string.IsNullOrEmpty(card.ManaCost)) eb.AddInlineField("Cost", _manaConverter.ConvertMana(card.ManaCost)); if (!string.IsNullOrEmpty(card.Rarity)) eb.AddInlineField("Rarity", card.Rarity); if (card.Legalities != null) @@ -87,21 +87,5 @@ namespace Geekbot.net.Commands return new Color(255, 252, 214); } } - - private string ManaConverter(string mana) - { - var rgx = new Regex("{(\\d)}"); - var groups = rgx.Match(mana).Groups; - if (groups.Count == 2) - { - mana = mana.Replace(groups[0].Value, _emojiConverter.numberToEmoji(int.Parse(groups[1].Value))); - } - return mana - .Replace("{W}", ":sunny:") - .Replace("{U}", ":droplet:") - .Replace("{B}", ":skull:") - .Replace("{R}", ":fire:") - .Replace("{G}", ":deciduous_tree:"); - } } } \ No newline at end of file diff --git a/Geekbot.net/Lib/MtgManaConverter.cs b/Geekbot.net/Lib/MtgManaConverter.cs new file mode 100644 index 0000000..176c1a4 --- /dev/null +++ b/Geekbot.net/Lib/MtgManaConverter.cs @@ -0,0 +1,85 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; + +namespace Geekbot.net.Lib +{ + public class MtgManaConverter : IMtgManaConverter + { + private Dictionary _manaDict; + + public MtgManaConverter() + { + // these emotes can be found at https://discord.gg/bz8HyA7 + + var manaDict = new Dictionary(); + manaDict.Add("{0}", "<:mtg_0:415216130043412482>"); + manaDict.Add("{1}", "<:mtg_1:415216130253389835>"); + manaDict.Add("{2}", "<:mtg_2:415216130031091713>"); + manaDict.Add("{3}", "<:mtg_3:415216130467037194>"); + manaDict.Add("{4}", "<:mtg_4:415216130026635295>"); + manaDict.Add("{5}", "<:mtg_5:415216130492203008>"); + manaDict.Add("{6}", "<:mtg_6:415216130458779658>"); + manaDict.Add("{7}", "<:mtg_7:415216130190475265>"); + manaDict.Add("{8}", "<:mtg_8:415216130517630986>"); + manaDict.Add("{9}", "<:mtg_9:415216130500722689>"); + manaDict.Add("{10", "<:mtg_10:415216130450391051>"); + manaDict.Add("{11}", "<:mtg_11:415216130811101185>"); + manaDict.Add("{12}", "<:mtg_12:415216130525888532>"); + manaDict.Add("{13}", "<:mtg_13:415216130517631000>"); + manaDict.Add("{14}", "<:mtg_14:415216130165178370>"); + manaDict.Add("{15}", "<:mtg_15:415216130576089108>"); + manaDict.Add("{16}", "<:mtg_16:415216130358247425>"); + manaDict.Add("{17}", "<:mtg_17:415216130601517056>"); + manaDict.Add("{18}", "<:mtg_18:415216130462842891>"); + manaDict.Add("{19}", "<:mtg_19:415216130614099988>"); + manaDict.Add("{20}", "<:mtg_20:415216130656043038>"); + manaDict.Add("{W}", "<:mtg_white:415216131515744256>"); + manaDict.Add("{U}", "<:mtg_blue:415216130521694209>"); + manaDict.Add("{B}", "<:mtg_black:415216130873884683>"); + manaDict.Add("{R}", "<:mtg_red:415216131322806272>"); + manaDict.Add("{G}", "<:mtg_green:415216131180331009>"); + manaDict.Add("{S}", "<:mtg_s:415216131293446144>"); + manaDict.Add("{2/W}", "<:mtg_2w:415216130446065664>"); + manaDict.Add("{2/U}", "<:mtg_2u:415216130429550592>"); + manaDict.Add("{2/B}", "<:mtg_2b:415216130160984065>"); + manaDict.Add("{2/R}", "<:mtg_2r:415216130454716436>"); + manaDict.Add("{2/G}", "<:mtg_2g:415216130420899840>"); + manaDict.Add("{W/U}", "<:mtg_wu:415216130970484736>"); + manaDict.Add("{W/B}", "<:mtg_wb:415216131222011914>"); + manaDict.Add("{U/R}", "<:mtg_ur:415216130962096128>"); + manaDict.Add("{U/B}", "<:mtg_ub:415216130865758218>"); + manaDict.Add("{R/W}", "<:mtg_rw:415216130878210057>"); + manaDict.Add("{G/W}", "<:mtg_gw:415216130567962646>"); + manaDict.Add("{G/U}", "<:mtg_gu:415216130739666945>"); + manaDict.Add("{B/R}", "<:mtg_br:415216130580283394>"); + manaDict.Add("{B/G}", "<:mtg_bg:415216130781609994>"); + manaDict.Add("{U/P}", "<:mtg_up:415216130861432842>"); + manaDict.Add("{R/P}", "<:mtg_rp:415216130597322783>"); + manaDict.Add("{G/P}", "<:mtg_gp:415216130760769546>"); + manaDict.Add("{W/P}", "<:mtg_wp:415216131541041172>"); + manaDict.Add("{B/P}", "<:mtg_bp:415216130664169482>"); + + _manaDict = manaDict; + } + + public string ConvertMana(string mana) + { + var rgx = Regex.Matches(mana, "(\\{(.*?)\\})"); + foreach (Match manaTypes in rgx) + { + var m = _manaDict.FirstOrDefault(x => x.Key == manaTypes.Value).Value; + if (!string.IsNullOrEmpty(m)) + { + mana = mana.Replace(manaTypes.Value, m); + } + } + return mana; + } + } + + public interface IMtgManaConverter + { + string ConvertMana(string mana); + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/SimpleConextConverter.cs b/Geekbot.net/Lib/SimpleConextConverter.cs index 3dbc58b..2e12e50 100644 --- a/Geekbot.net/Lib/SimpleConextConverter.cs +++ b/Geekbot.net/Lib/SimpleConextConverter.cs @@ -8,33 +8,7 @@ namespace Geekbot.net.Lib { public static MessageDto ConvertContext(ICommandContext context) { - return new MessageDto() - { - Message = new MessageDto.MessageContent() - { - Content = context.Message.Content, - Id = context.Message.Id.ToString(), - Attachments = context.Message.Attachments.Count, - ChannelMentions = context.Message.MentionedChannelIds.Count, - UserMentions = context.Message.MentionedUserIds.Count, - RoleMentions = context.Message.MentionedRoleIds.Count - }, - User = new MessageDto.IdAndName() - { - Id = context.User.Id.ToString(), - Name = $"{context.User.Username}#{context.User.Discriminator}" - }, - Guild = new MessageDto.IdAndName() - { - Id = context.Guild.Id.ToString(), - Name = context.Guild.Name - }, - Channel = new MessageDto.IdAndName() - { - Id = context.Channel.Id.ToString(), - Name = context.Channel.Name - } - }; + return ConvertSocketMessage((SocketMessage) context.Message); } public static MessageDto ConvertSocketMessage(SocketMessage message) { diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index c47fdb4..266f562 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -100,6 +100,7 @@ namespace Geekbot.net var levelCalc = new LevelCalc(); var emojiConverter = new EmojiConverter(); var audioUtils = new AudioUtils(); + var mtgManaConverter = new MtgManaConverter(); services.AddSingleton(redis); services.AddSingleton(logger); @@ -110,6 +111,7 @@ namespace Geekbot.net services.AddSingleton(fortunes); services.AddSingleton(mediaProvider); services.AddSingleton(malClient); + services.AddSingleton(mtgManaConverter); logger.Information("Geekbot", "Connecting to Discord"); From 4c1cdc361205f2272bdd67438769b510bf3fb112 Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 19 Feb 2018 22:31:40 +0100 Subject: [PATCH 125/553] Merge Rolebot into Geekbot --- Geekbot.net/Commands/Role.cs | 43 ++++++++++++- Geekbot.net/Handlers.cs | 24 ++++++- Geekbot.net/Lib/MtgManaConverter.cs | 1 + Geekbot.net/Lib/ReactionListener.cs | 98 +++++++++++++++++++++++++++++ Geekbot.net/Program.cs | 6 +- 5 files changed, 167 insertions(+), 5 deletions(-) create mode 100644 Geekbot.net/Lib/ReactionListener.cs diff --git a/Geekbot.net/Commands/Role.cs b/Geekbot.net/Commands/Role.cs index 80ef4af..1de55ab 100644 --- a/Geekbot.net/Commands/Role.cs +++ b/Geekbot.net/Commands/Role.cs @@ -15,11 +15,13 @@ namespace Geekbot.net.Commands { private readonly IErrorHandler _errorHandler; private readonly IDatabase _redis; + private readonly IReactionListener _reactionListener; - public Role(IErrorHandler errorHandler, IDatabase redis) + public Role(IErrorHandler errorHandler, IDatabase redis, IReactionListener reactionListener) { _errorHandler = errorHandler; _redis = redis; + _reactionListener = reactionListener; } [Command(RunMode = RunMode.Async)] @@ -91,7 +93,7 @@ namespace Geekbot.net.Commands } } - [RequireUserPermission(GuildPermission.Administrator)] + [RequireUserPermission(GuildPermission.ManageRoles)] [Command("add", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Add a role to the whitelist.")] @@ -126,7 +128,7 @@ namespace Geekbot.net.Commands } } - [RequireUserPermission(GuildPermission.Administrator)] + [RequireUserPermission(GuildPermission.ManageRoles)] [Command("remove", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Remove a role from the whitelist.")] @@ -150,5 +152,40 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } + + [RequireUserPermission(GuildPermission.ManageRoles)] + [Remarks(CommandCategories.Admin)] + [Summary("Give a role by clicking on an emoji")] + [Command("listen", RunMode = RunMode.Async)] + public async Task AddListener([Summary("messageID")] string messageId, [Summary("Emoji")] string emoji, [Summary("@role")] IRole role) + { + try + { + var message = (IUserMessage) await Context.Channel.GetMessageAsync(ulong.Parse(messageId)); + IEmote emote; + if (!emoji.StartsWith('<')) + { + var emo = new Emoji(emoji); + emote = (IEmote) emo; + } + else + { + emote = Emote.Parse(emoji); + } + await message.AddReactionAsync(emote); + await _reactionListener.AddRoleToListener(messageId, emote, role); + await Context.Message.DeleteAsync(); + } + catch (HttpException e) + { + await Context.Channel.SendMessageAsync("Custom emojis from other servers are not supported"); + Console.WriteLine(e); + } + catch (Exception e) + { + await Context.Channel.SendMessageAsync("Something went wrong... please try again on a new message"); + Console.WriteLine(e); + } + } } } \ No newline at end of file diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index aa8a154..7ca9390 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -19,8 +19,9 @@ namespace Geekbot.net private readonly IServiceProvider _servicesProvider; private readonly CommandService _commands; private readonly IUserRepository _userRepository; + private readonly IReactionListener _reactionListener; - public Handlers(IDiscordClient client, IGeekbotLogger logger, IDatabase redis, IServiceProvider servicesProvider, CommandService commands, IUserRepository userRepository) + public Handlers(IDiscordClient client, IGeekbotLogger logger, IDatabase redis, IServiceProvider servicesProvider, CommandService commands, IUserRepository userRepository, IReactionListener reactionListener) { _client = client; _logger = logger; @@ -28,6 +29,7 @@ namespace Geekbot.net _servicesProvider = servicesProvider; _commands = commands; _userRepository = userRepository; + _reactionListener = reactionListener; } // @@ -180,5 +182,25 @@ namespace Geekbot.net _logger.Error("Geekbot", "Failed to send delete message...", e); } } + + // + // Reactions + // + + public Task ReactionAdded(Cacheable cacheable, ISocketMessageChannel socketMessageChannel, SocketReaction reaction) + { + if (reaction.User.Value.IsBot) return Task.CompletedTask; + if (!_reactionListener.IsListener(reaction.MessageId)) return Task.CompletedTask; + _reactionListener.GiveRole(socketMessageChannel, reaction); + return Task.CompletedTask; + } + + public Task ReactionRemoved(Cacheable cacheable, ISocketMessageChannel socketMessageChannel, SocketReaction reaction) + { + if (reaction.User.Value.IsBot) return Task.CompletedTask; + if (!_reactionListener.IsListener(reaction.MessageId)) return Task.CompletedTask; + _reactionListener.RemoveRole(socketMessageChannel, reaction); + return Task.CompletedTask; + } } } diff --git a/Geekbot.net/Lib/MtgManaConverter.cs b/Geekbot.net/Lib/MtgManaConverter.cs index 176c1a4..6385fa8 100644 --- a/Geekbot.net/Lib/MtgManaConverter.cs +++ b/Geekbot.net/Lib/MtgManaConverter.cs @@ -40,6 +40,7 @@ namespace Geekbot.net.Lib manaDict.Add("{R}", "<:mtg_red:415216131322806272>"); manaDict.Add("{G}", "<:mtg_green:415216131180331009>"); manaDict.Add("{S}", "<:mtg_s:415216131293446144>"); + manaDict.Add("{T}", "<:mtg_tap:415258392727257088>"); manaDict.Add("{2/W}", "<:mtg_2w:415216130446065664>"); manaDict.Add("{2/U}", "<:mtg_2u:415216130429550592>"); manaDict.Add("{2/B}", "<:mtg_2b:415216130160984065>"); diff --git a/Geekbot.net/Lib/ReactionListener.cs b/Geekbot.net/Lib/ReactionListener.cs new file mode 100644 index 0000000..f0e75a6 --- /dev/null +++ b/Geekbot.net/Lib/ReactionListener.cs @@ -0,0 +1,98 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Discord; +using Discord.WebSocket; +using StackExchange.Redis; + +namespace Geekbot.net.Lib +{ + public class ReactionListener : IReactionListener + { + private readonly IDatabase _database; + private Dictionary> _listener; + + public ReactionListener(IDatabase database) + { + _database = database; + LoadListeners(); + } + + private Task LoadListeners() + { + var ids = _database.SetMembers("MessageIds"); + _listener = new Dictionary>(); + foreach (var id in ids) + { + var reactions = _database.HashGetAll($"Messages:{id}"); + var messageId = id; + var emojiDict = new Dictionary(); + foreach (var r in reactions) + { + IEmote emote; + if (!r.Name.ToString().StartsWith('<')) + { + var emo = new Emoji(r.Name); + emote = (IEmote) emo; + } + else + { + emote = Emote.Parse(r.Name); + } + emojiDict.Add(emote, ulong.Parse(r.Value)); + } + _listener.Add(messageId, emojiDict); + } + + return Task.CompletedTask; + } + + public bool IsListener(ulong id) + { + return _listener.ContainsKey(id.ToString()); + } + + public Task AddRoleToListener(string messageId, IEmote emoji, IRole role) + { + if (_database.SetMembers("MessageIds").All(e => e.ToString() != messageId)) + { + _database.SetAdd("MessageIds", messageId); + } + _database.HashSet($"Messages:{messageId}", new[] {new HashEntry(emoji.ToString(), role.Id.ToString())}); + _database.SetAdd("MessageIds", messageId); + if (_listener.ContainsKey(messageId)) + { + _listener[messageId].Add(emoji, role.Id); + return Task.CompletedTask; + } + var dict = new Dictionary(); + dict.Add(emoji, role.Id); + _listener.Add(messageId, dict); + return Task.CompletedTask; + } + + public async void RemoveRole(ISocketMessageChannel channel, SocketReaction reaction) + { + var roleId = _listener[reaction.MessageId.ToString()][reaction.Emote]; + var guild = (SocketGuildChannel) channel; + var role = guild.Guild.GetRole(roleId); + await ((IGuildUser) reaction.User.Value).RemoveRoleAsync(role); + } + + public async void GiveRole(ISocketMessageChannel channel, SocketReaction reaction) + { + var roleId = _listener[reaction.MessageId.ToString()][reaction.Emote]; + var guild = (SocketGuildChannel) channel; + var role = guild.Guild.GetRole(roleId); + await ((IGuildUser) reaction.User.Value).AddRoleAsync(role); + } + } + + public interface IReactionListener + { + bool IsListener(ulong id); + Task AddRoleToListener(string messageId, IEmote emoji, IRole role); + void RemoveRole(ISocketMessageChannel channel, SocketReaction reaction); + void GiveRole(ISocketMessageChannel message, SocketReaction reaction); + } +} \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 266f562..3f31945 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -135,14 +135,16 @@ namespace Geekbot.net logger.Information("Geekbot", "Registering Stuff"); var translationHandler = new TranslationHandler(client.Guilds, redis, logger); var errorHandler = new ErrorHandler(logger, translationHandler); + var reactionListener = new ReactionListener(redis); await commands.AddModulesAsync(Assembly.GetEntryAssembly()); services.AddSingleton(commands); services.AddSingleton(errorHandler); services.AddSingleton(translationHandler); services.AddSingleton(client); + services.AddSingleton(reactionListener); servicesProvider = services.BuildServiceProvider(); - var handlers = new Handlers(client, logger, redis, servicesProvider, commands, userRepository); + var handlers = new Handlers(client, logger, redis, servicesProvider, commands, userRepository, reactionListener); client.MessageReceived += handlers.RunCommand; client.MessageReceived += handlers.UpdateStats; @@ -150,6 +152,8 @@ namespace Geekbot.net client.UserJoined += handlers.UserJoined; client.UserUpdated += handlers.UserUpdated; client.UserLeft += handlers.UserLeft; + client.ReactionAdded += handlers.ReactionAdded; + client.ReactionRemoved += handlers.ReactionRemoved; if (firstStart || args.Contains("--reset")) { From a616d4254384b0424768025392374c13174b3d1d Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 19 Feb 2018 22:55:22 +0100 Subject: [PATCH 126/553] Add colorless mana to mtg mana converter --- Geekbot.net/Lib/MtgManaConverter.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Geekbot.net/Lib/MtgManaConverter.cs b/Geekbot.net/Lib/MtgManaConverter.cs index 6385fa8..4337e68 100644 --- a/Geekbot.net/Lib/MtgManaConverter.cs +++ b/Geekbot.net/Lib/MtgManaConverter.cs @@ -41,6 +41,7 @@ namespace Geekbot.net.Lib manaDict.Add("{G}", "<:mtg_green:415216131180331009>"); manaDict.Add("{S}", "<:mtg_s:415216131293446144>"); manaDict.Add("{T}", "<:mtg_tap:415258392727257088>"); + manaDict.Add("{C}", "<:mtg_colorless:415216130706374666>"); manaDict.Add("{2/W}", "<:mtg_2w:415216130446065664>"); manaDict.Add("{2/U}", "<:mtg_2u:415216130429550592>"); manaDict.Add("{2/B}", "<:mtg_2b:415216130160984065>"); From e158e2196fdaa900de7c7274cadcf3c0ef066d17 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Tue, 20 Feb 2018 09:34:26 +0100 Subject: [PATCH 127/553] Revert SimpleContextConverter --- Geekbot.net/Lib/SimpleConextConverter.cs | 28 +++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/Geekbot.net/Lib/SimpleConextConverter.cs b/Geekbot.net/Lib/SimpleConextConverter.cs index 2e12e50..3dbc58b 100644 --- a/Geekbot.net/Lib/SimpleConextConverter.cs +++ b/Geekbot.net/Lib/SimpleConextConverter.cs @@ -8,7 +8,33 @@ namespace Geekbot.net.Lib { public static MessageDto ConvertContext(ICommandContext context) { - return ConvertSocketMessage((SocketMessage) context.Message); + return new MessageDto() + { + Message = new MessageDto.MessageContent() + { + Content = context.Message.Content, + Id = context.Message.Id.ToString(), + Attachments = context.Message.Attachments.Count, + ChannelMentions = context.Message.MentionedChannelIds.Count, + UserMentions = context.Message.MentionedUserIds.Count, + RoleMentions = context.Message.MentionedRoleIds.Count + }, + User = new MessageDto.IdAndName() + { + Id = context.User.Id.ToString(), + Name = $"{context.User.Username}#{context.User.Discriminator}" + }, + Guild = new MessageDto.IdAndName() + { + Id = context.Guild.Id.ToString(), + Name = context.Guild.Name + }, + Channel = new MessageDto.IdAndName() + { + Id = context.Channel.Id.ToString(), + Name = context.Channel.Name + } + }; } public static MessageDto ConvertSocketMessage(SocketMessage message) { From 8189d78ceacb5019c26f4c1947eb9f2b3e7f51a4 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Tue, 20 Feb 2018 16:26:56 +0100 Subject: [PATCH 128/553] Optimize dictionary in mtgmanaconverter --- Geekbot.net/Lib/MtgManaConverter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Geekbot.net/Lib/MtgManaConverter.cs b/Geekbot.net/Lib/MtgManaConverter.cs index 4337e68..aeb1c9e 100644 --- a/Geekbot.net/Lib/MtgManaConverter.cs +++ b/Geekbot.net/Lib/MtgManaConverter.cs @@ -70,7 +70,7 @@ namespace Geekbot.net.Lib var rgx = Regex.Matches(mana, "(\\{(.*?)\\})"); foreach (Match manaTypes in rgx) { - var m = _manaDict.FirstOrDefault(x => x.Key == manaTypes.Value).Value; + var m = _manaDict.GetValueOrDefault(manaTypes.Value); if (!string.IsNullOrEmpty(m)) { mana = mana.Replace(manaTypes.Value, m); From 440f3a97c298f5813349ac5f7a1970fe854efed2 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 2 Mar 2018 23:05:14 +0100 Subject: [PATCH 129/553] Revive ping pong --- Geekbot.net/Commands/Admin.cs | 21 +++++++++++++++++++-- Geekbot.net/Handlers.cs | 9 +++++++++ Geekbot.net/Lib/MtgManaConverter.cs | 2 +- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/Geekbot.net/Commands/Admin.cs b/Geekbot.net/Commands/Admin.cs index 0b76b4b..681ff99 100644 --- a/Geekbot.net/Commands/Admin.cs +++ b/Geekbot.net/Commands/Admin.cs @@ -34,8 +34,7 @@ namespace Geekbot.net.Commands { _redis.HashSet($"{Context.Guild.Id}:Settings", new[] {new HashEntry("WelcomeMsg", welcomeMessage)}); var formatedMessage = welcomeMessage.Replace("$user", Context.User.Mention); - await ReplyAsync("Welcome message has been changed\r\nHere is an example of how it would look:\r\n" + - formatedMessage); + await ReplyAsync($"Welcome message has been changed\r\nHere is an example of how it would look:\r\n{formatedMessage}"); } [Command("modchannel", RunMode = RunMode.Async)] @@ -155,5 +154,23 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } + + [Command("ping", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Admin)] + [Summary("Enable the ping reply.")] + public async Task togglePing() + { + try + { + bool.TryParse(_redis.HashGet($"{Context.Guild.Id}:Settings", "ping"), out var current); + _redis.HashSet($"{Context.Guild.Id}:Settings", new[] {new HashEntry("ping", current ? "false" : "true"), }); + await ReplyAsync(!current ? "i will reply to ping now" : "No more pongs..."); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + } } \ No newline at end of file diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index 7ca9390..c1e0ee3 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -49,6 +49,15 @@ namespace Geekbot.net message.Channel.SendMessageAsync("hui!!!"); return Task.CompletedTask; } + if (lowCaseMsg.StartsWith("ping ") || lowCaseMsg.Equals("ping")) + { + bool.TryParse(_redis.HashGet($"{((SocketGuildChannel) message.Channel).Guild.Id}:Settings", "ping"), out var allowPings); + if (allowPings) + { + message.Channel.SendMessageAsync("pong"); + return Task.CompletedTask; + } + } if (!(message.HasCharPrefix('!', ref argPos) || message.HasMentionPrefix(_client.CurrentUser, ref argPos))) return Task.CompletedTask; var context = new CommandContext(_client, message); diff --git a/Geekbot.net/Lib/MtgManaConverter.cs b/Geekbot.net/Lib/MtgManaConverter.cs index aeb1c9e..098542e 100644 --- a/Geekbot.net/Lib/MtgManaConverter.cs +++ b/Geekbot.net/Lib/MtgManaConverter.cs @@ -67,7 +67,7 @@ namespace Geekbot.net.Lib public string ConvertMana(string mana) { - var rgx = Regex.Matches(mana, "(\\{(.*?)\\})"); + var rgx = Regex.Matches(mana, @"(\{(.*?)\})"); foreach (Match manaTypes in rgx) { var m = _manaDict.GetValueOrDefault(manaTypes.Value); From 75cbcfff76adc01655edb8225c8259c760b6ec4d Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 2 Mar 2018 23:35:14 +0100 Subject: [PATCH 130/553] Add a check to help --- Geekbot.net/Commands/Help.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Geekbot.net/Commands/Help.cs b/Geekbot.net/Commands/Help.cs index aa2cc57..83374a8 100644 --- a/Geekbot.net/Commands/Help.cs +++ b/Geekbot.net/Commands/Help.cs @@ -1,6 +1,7 @@ using System; using System.Text; using System.Threading.Tasks; +using Discord; using Discord.Commands; using Geekbot.net.Lib; @@ -28,6 +29,7 @@ namespace Geekbot.net.Commands sb.AppendLine("https://geekbot.pizzaandcoffee.rocks/commands"); var dm = await Context.User.GetOrCreateDMChannelAsync(); await dm.SendMessageAsync(sb.ToString()); + Context.Message.AddReactionAsync(new Emoji("✅")); } catch (Exception e) { From 6bc6fb69afefd5f28dbd0fb08c26c2196f17c411 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 28 Mar 2018 21:28:16 +0200 Subject: [PATCH 131/553] Now with 100% more pinguins --- Geekbot.net/Commands/RandomAnimals.cs | 27 +++++++++++++++++++++----- Geekbot.net/Geekbot.net.csproj | 3 +++ Geekbot.net/Lib/Media/MediaProvider.cs | 15 ++++++++++++++ Geekbot.net/Storage/pinguins | 13 +++++++++++++ 4 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 Geekbot.net/Storage/pinguins diff --git a/Geekbot.net/Commands/RandomAnimals.cs b/Geekbot.net/Commands/RandomAnimals.cs index 29930eb..84f0323 100644 --- a/Geekbot.net/Commands/RandomAnimals.cs +++ b/Geekbot.net/Commands/RandomAnimals.cs @@ -1,4 +1,5 @@ using System.Threading.Tasks; +using Discord; using Discord.Commands; using Geekbot.net.Lib; using Geekbot.net.Lib.Media; @@ -19,7 +20,7 @@ namespace Geekbot.net.Commands [Summary("Get a random panda image")] public async Task panda() { - await ReplyAsync(_mediaProvider.getPanda()); + await ReplyAsync("", false, eb(_mediaProvider.getPanda())); } [Command("croissant", RunMode = RunMode.Async)] @@ -28,7 +29,7 @@ namespace Geekbot.net.Commands [Summary("Get a random croissant image")] public async Task croissant() { - await ReplyAsync(_mediaProvider.getCrossant()); + await ReplyAsync("", false, eb(_mediaProvider.getCrossant())); } [Command("pumpkin", RunMode = RunMode.Async)] @@ -36,7 +37,7 @@ namespace Geekbot.net.Commands [Summary("Get a random pumpkin image")] public async Task pumpkin() { - await ReplyAsync(_mediaProvider.getPumpkin()); + await ReplyAsync("", false, eb(_mediaProvider.getPumpkin())); } [Command("squirrel", RunMode = RunMode.Async)] @@ -44,7 +45,7 @@ namespace Geekbot.net.Commands [Summary("Get a random squirrel image")] public async Task squirrel() { - await ReplyAsync(_mediaProvider.getSquirrel()); + await ReplyAsync("", false, eb(_mediaProvider.getSquirrel())); } [Command("turtle", RunMode = RunMode.Async)] @@ -52,7 +53,23 @@ namespace Geekbot.net.Commands [Summary("Get a random turtle image")] public async Task turtle() { - await ReplyAsync(_mediaProvider.getTurtle()); + await ReplyAsync("", false, eb(_mediaProvider.getTurtle())); + } + + [Command("pinguin", RunMode = RunMode.Async)] + [Alias("pingu")] + [Remarks(CommandCategories.Randomness)] + [Summary("Get a random turtle image")] + public async Task pinguin() + { + await ReplyAsync("", false, eb(_mediaProvider.getPinguin())); + } + + private EmbedBuilder eb(string image) + { + var eb = new EmbedBuilder(); + eb.ImageUrl = image; + return eb; } } } \ No newline at end of file diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 89aab56..0a772d8 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -69,5 +69,8 @@ PreserveNewest + + PreserveNewest + \ No newline at end of file diff --git a/Geekbot.net/Lib/Media/MediaProvider.cs b/Geekbot.net/Lib/Media/MediaProvider.cs index 0a3ff6c..2f0204e 100644 --- a/Geekbot.net/Lib/Media/MediaProvider.cs +++ b/Geekbot.net/Lib/Media/MediaProvider.cs @@ -16,6 +16,7 @@ namespace Geekbot.net.Lib.Media private string[] _squirrelImages; private string[] _pumpkinImages; private string[] _turtlesImages; + private string[] _pinguinImages; public MediaProvider(IGeekbotLogger logger) { @@ -30,6 +31,7 @@ namespace Geekbot.net.Lib.Media LoadSquirrels(); LoadPumpkins(); LoadTurtles(); + LoadPinguins(); } private void LoadCheckem() @@ -74,6 +76,13 @@ namespace Geekbot.net.Lib.Media _logger.Debug("Geekbot", $"Loaded {_turtlesImages.Length} Turtle Images"); } + private void LoadPinguins() + { + var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/pinguins")); + _pinguinImages = rawLinks.Split("\n"); + _logger.Debug("Geekbot", $"Loaded {_pinguinImages.Length} Pinguin Images"); + } + public string getCheckem() { return _checkemImages[_random.Next(0, _checkemImages.Length)]; @@ -103,6 +112,11 @@ namespace Geekbot.net.Lib.Media { return _turtlesImages[_random.Next(0, _turtlesImages.Length)]; } + + public string getPinguin() + { + return _pinguinImages[_random.Next(0, _pinguinImages.Length)]; + } } public interface IMediaProvider @@ -113,5 +127,6 @@ namespace Geekbot.net.Lib.Media string getSquirrel(); string getPumpkin(); string getTurtle(); + string getPinguin(); } } \ No newline at end of file diff --git a/Geekbot.net/Storage/pinguins b/Geekbot.net/Storage/pinguins new file mode 100644 index 0000000..631f9d0 --- /dev/null +++ b/Geekbot.net/Storage/pinguins @@ -0,0 +1,13 @@ +https://i.ytimg.com/vi/Qr6sULJnu2o/maxresdefault.jpg +https://www.apex-expeditions.com/wp-content/uploads/2015/08/newzealandSlider_Macquarie_ElephantSealKingPenguins_GRiehle_1366x601.jpg +https://www.birdlife.org/sites/default/files/styles/1600/public/slide.jpg?itok=HRhQfA1S +http://experimentexchange.com/wp-content/uploads/2016/07/penguins-fact.jpg +http://images.mentalfloss.com/sites/default/files/styles/mf_image_16x9/public/istock-511366776.jpg?itok=cWhdWNZ8&resize=1100x619 +https://www.thevaporplace.ch/media/catalog/product/cache/1/thumbnail/800x800/9df78eab33525d08d6e5fb8d27136e95/a/t/atopack_penguin-15.jpg +https://www.superfastbusiness.com/wp-content/uploads/2015/10/real-time-penguin-algorithm-featured.jpg +http://www.antarctica.gov.au/__data/assets/image/0011/147737/varieties/antarctic.jpg +https://vignette.wikia.nocookie.net/robloxcreepypasta/images/1/11/AAEAAQAAAAAAAAdkAAAAJDc3YzkyYjJhLTYyZjctNDY2Mi04M2VjLTg4NjY4ZjgwYzRmNg.png/revision/latest?cb=20180207200526 +https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3xV0lhpZuhT8Nmm6LaITsppZ7VfWcWXuyu2cPHrlv_dt_M92K5g +http://goboiano.com/wp-content/uploads/2017/04/Penguin-Kemeno-Friends-Waifu.jpg +https://cdn.yoast.com/app/uploads/2015/10/Penguins_1200x628.png +https://images.justwatch.com/backdrop/8611153/s1440/pingu \ No newline at end of file From f127e0c02ba0552abff4847873cc79020c58b861 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 28 Mar 2018 21:29:42 +0200 Subject: [PATCH 132/553] Disable !cat --- Geekbot.net/Commands/Cat.cs | 39 +++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/Geekbot.net/Commands/Cat.cs b/Geekbot.net/Commands/Cat.cs index 2120fe7..e096f20 100644 --- a/Geekbot.net/Commands/Cat.cs +++ b/Geekbot.net/Commands/Cat.cs @@ -24,25 +24,26 @@ namespace Geekbot.net.Commands { try { - using (var client = new HttpClient()) - { - try - { - client.BaseAddress = new Uri("http://random.cat"); - var response = await client.GetAsync("/meow.php"); - response.EnsureSuccessStatusCode(); - - var stringResponse = await response.Content.ReadAsStringAsync(); - var catFile = JsonConvert.DeserializeObject(stringResponse); - var eb = new EmbedBuilder(); - eb.ImageUrl = catFile.file; - await ReplyAsync("", false, eb.Build()); - } - catch (HttpRequestException e) - { - await ReplyAsync($"Seems like the dog cought the cat (error occured)\r\n{e.Message}"); - } - } +// using (var client = new HttpClient()) +// { +// try +// { +// client.BaseAddress = new Uri("http://random.cat"); +// var response = await client.GetAsync("/meow.php"); +// response.EnsureSuccessStatusCode(); +// +// var stringResponse = await response.Content.ReadAsStringAsync(); +// var catFile = JsonConvert.DeserializeObject(stringResponse); +// var eb = new EmbedBuilder(); +// eb.ImageUrl = catFile.file; +// await ReplyAsync("", false, eb.Build()); +// } +// catch (HttpRequestException e) +// { +// await ReplyAsync($"Seems like the dog cought the cat (error occured)\r\n{e.Message}"); +// } +// } + await ReplyAsync("Command disabled for now because http://random.cat is down"); } catch (Exception e) { From 3f02f90d70f1855db303619555078a180cea49b9 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 28 Mar 2018 21:45:29 +0200 Subject: [PATCH 133/553] Enable cat command again --- Geekbot.net/Commands/Cat.cs | 115 ++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 58 deletions(-) diff --git a/Geekbot.net/Commands/Cat.cs b/Geekbot.net/Commands/Cat.cs index e096f20..1f97d5a 100644 --- a/Geekbot.net/Commands/Cat.cs +++ b/Geekbot.net/Commands/Cat.cs @@ -1,59 +1,58 @@ -using System; -using System.Net.Http; -using System.Threading.Tasks; -using Discord; -using Discord.Commands; -using Geekbot.net.Lib; -using Newtonsoft.Json; - -namespace Geekbot.net.Commands -{ - public class Cat : ModuleBase - { - private readonly IErrorHandler _errorHandler; - - public Cat(IErrorHandler errorHandler) - { - _errorHandler = errorHandler; - } - - [Command("cat", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Randomness)] - [Summary("Return a random image of a cat.")] - public async Task Say() - { - try - { -// using (var client = new HttpClient()) -// { -// try -// { -// client.BaseAddress = new Uri("http://random.cat"); -// var response = await client.GetAsync("/meow.php"); -// response.EnsureSuccessStatusCode(); -// -// var stringResponse = await response.Content.ReadAsStringAsync(); -// var catFile = JsonConvert.DeserializeObject(stringResponse); -// var eb = new EmbedBuilder(); -// eb.ImageUrl = catFile.file; -// await ReplyAsync("", false, eb.Build()); -// } -// catch (HttpRequestException e) -// { -// await ReplyAsync($"Seems like the dog cought the cat (error occured)\r\n{e.Message}"); -// } -// } - await ReplyAsync("Command disabled for now because http://random.cat is down"); - } - catch (Exception e) - { - _errorHandler.HandleCommandException(e, Context); - } - } - - private class CatResponse - { - public string file { get; set; } - } - } +using System; +using System.Net.Http; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Geekbot.net.Lib; +using Newtonsoft.Json; + +namespace Geekbot.net.Commands +{ + public class Cat : ModuleBase + { + private readonly IErrorHandler _errorHandler; + + public Cat(IErrorHandler errorHandler) + { + _errorHandler = errorHandler; + } + + [Command("cat", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Randomness)] + [Summary("Return a random image of a cat.")] + public async Task Say() + { + try + { + using (var client = new HttpClient()) + { + try + { + client.BaseAddress = new Uri("https://aws.random.cat"); + var response = await client.GetAsync("/meow"); + response.EnsureSuccessStatusCode(); + + var stringResponse = await response.Content.ReadAsStringAsync(); + var catFile = JsonConvert.DeserializeObject(stringResponse); + var eb = new EmbedBuilder(); + eb.ImageUrl = catFile.file; + await ReplyAsync("", false, eb.Build()); + } + catch + { + await ReplyAsync("Seems like the dog cought the cat (error occured)"); + } + } + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + private class CatResponse + { + public string file { get; set; } + } + } } \ No newline at end of file From 8974d6df7edc3bd369a4013d71ce3adcdb3ff3a4 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 28 Mar 2018 22:14:07 +0200 Subject: [PATCH 134/553] Add in some foxes aswell --- Geekbot.net/Commands/RandomAnimals.cs | 8 +++++++ Geekbot.net/Geekbot.net.csproj | 3 +++ Geekbot.net/Lib/Media/MediaProvider.cs | 15 +++++++++++++ Geekbot.net/Storage/foxes | 29 ++++++++++++++++++++++++++ 4 files changed, 55 insertions(+) create mode 100644 Geekbot.net/Storage/foxes diff --git a/Geekbot.net/Commands/RandomAnimals.cs b/Geekbot.net/Commands/RandomAnimals.cs index 84f0323..f9dead9 100644 --- a/Geekbot.net/Commands/RandomAnimals.cs +++ b/Geekbot.net/Commands/RandomAnimals.cs @@ -64,6 +64,14 @@ namespace Geekbot.net.Commands { await ReplyAsync("", false, eb(_mediaProvider.getPinguin())); } + + [Command("fox", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Randomness)] + [Summary("Get a random turtle image")] + public async Task fox() + { + await ReplyAsync("", false, eb(_mediaProvider.getFox())); + } private EmbedBuilder eb(string image) { diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 0a772d8..1a11cd9 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -72,5 +72,8 @@ PreserveNewest + + PreserveNewest + \ No newline at end of file diff --git a/Geekbot.net/Lib/Media/MediaProvider.cs b/Geekbot.net/Lib/Media/MediaProvider.cs index 2f0204e..b8aeaa3 100644 --- a/Geekbot.net/Lib/Media/MediaProvider.cs +++ b/Geekbot.net/Lib/Media/MediaProvider.cs @@ -17,6 +17,7 @@ namespace Geekbot.net.Lib.Media private string[] _pumpkinImages; private string[] _turtlesImages; private string[] _pinguinImages; + private string[] _foxImages; public MediaProvider(IGeekbotLogger logger) { @@ -32,6 +33,7 @@ namespace Geekbot.net.Lib.Media LoadPumpkins(); LoadTurtles(); LoadPinguins(); + LoadFoxes(); } private void LoadCheckem() @@ -83,6 +85,13 @@ namespace Geekbot.net.Lib.Media _logger.Debug("Geekbot", $"Loaded {_pinguinImages.Length} Pinguin Images"); } + private void LoadFoxes() + { + var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/foxes")); + _foxImages = rawLinks.Split("\n"); + _logger.Debug("Geekbot", $"Loaded {_foxImages.Length} Foxes Images"); + } + public string getCheckem() { return _checkemImages[_random.Next(0, _checkemImages.Length)]; @@ -117,6 +126,11 @@ namespace Geekbot.net.Lib.Media { return _pinguinImages[_random.Next(0, _pinguinImages.Length)]; } + + public string getFox() + { + return _foxImages[_random.Next(0, _foxImages.Length)]; + } } public interface IMediaProvider @@ -128,5 +142,6 @@ namespace Geekbot.net.Lib.Media string getPumpkin(); string getTurtle(); string getPinguin(); + string getFox(); } } \ No newline at end of file diff --git a/Geekbot.net/Storage/foxes b/Geekbot.net/Storage/foxes new file mode 100644 index 0000000..020c1cf --- /dev/null +++ b/Geekbot.net/Storage/foxes @@ -0,0 +1,29 @@ +https://i.ytimg.com/vi/qF6OOGuT_hI/maxresdefault.jpg +https://www.hd-wallpapersdownload.com/script/bulk-upload/desktop-funny-fox-wallpaper.jpg +http://moziru.com/images/drawn-fox-funny-18.jpg +https://static.tumblr.com/bb34d8f163098ad1daafcffbdbb03975/rk23uap/Nwwp0rmi2/tumblr_static_tumblr_static__640.jpg +https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQoHUFOnZ3wJ2kT1skNdztFXXSvpU8bEoGS1alNZiuyLXvGJhcY +http://childrenstorytales.com/wp-content/uploads/2011/03/how-to-draw-a-red-fox-in-the-snow.jpg +https://www.popsci.com/sites/popsci.com/files/styles/1000_1x_/public/import/2013/images/2013/09/redfoxyawn.jpg?itok=yRkSVe8T +https://hdqwalls.com/wallpapers/wild-fox-art.jpg +https://ae01.alicdn.com/kf/HTB1Q9dpLpXXXXbhXpXXq6xXFXXXl/new-cute-fox-toy-lifelike-soft-long-yellow-fox-doll-gift-about-73cm.jpg_640x640.jpg +https://i.imgur.com/ktK9yXX.jpg +https://res.cloudinary.com/teepublic/image/private/s--yTx2ncFA--/t_Preview/b_rgb:c8e0ec,c_limit,f_auto,h_313,q_90,w_313/v1506478249/production/designs/1932607_0 +http://4.bp.blogspot.com/-Hz-o_KYj3Xk/Vlm2mwbztjI/AAAAAAAA8Ss/jbH5ovjmC9A/s1600/ScreenShot5502.jpg +https://i.pinimg.com/originals/1e/d5/2f/1ed52f70873a95ac02fa074e48edfb71.jpg +https://i.imgur.com/2vCrtap.jpg +https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfukWGu_IBaDeJOMBqOhVAwsDfqEPw0BFpCn5_-Iyr_xjd7zi9 +https://cdn.pixabay.com/photo/2017/01/31/18/36/animal-2026297_960_720.png +https://i.pinimg.com/originals/e2/63/67/e26367a0844633b2a697b0a9d69e8cc9.jpg +https://i.ebayimg.com/images/g/BvkAAOSwqxdTqrip/s-l300.jpg +https://res.cloudinary.com/teepublic/image/private/s--1R53bger--/t_Preview/b_rgb:eae0c7,c_limit,f_jpg,h_630,q_90,w_630/v1481013120/production/designs/914528_1.jpg +https://i.pinimg.com/originals/97/fe/69/97fe698462afde7b4209ccefeecbce71.jpg +https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT6G0ch6g-wG1TuDJ6BbkOFelMNnkgFXC6CxOw7qSNjoFkx-BCe +https://wallpaperscraft.com/image/fox_forest_grass_117190_540x960.jpg +https://image.freepik.com/free-vector/cartoon-flat-illustration-funny-cute-fox_6317-1174.jpg +https://orig00.deviantart.net/2feb/f/2013/137/a/f/fox_and_curious_squirrel_by_tamarar-d65ju8d.jpg +https://res.cloudinary.com/teepublic/image/private/s--dICeNmBx--/t_Preview/b_rgb:6e2229,c_limit,f_jpg,h_630,q_90,w_630/v1505243196/production/designs/1890493_1.jpg +https://vignette.wikia.nocookie.net/puppyinmypocketfanon/images/4/49/L-Baby-Fox.jpg/revision/latest?cb=20130421001806 +http://7-themes.com/data_images/out/69/7009194-fox-puppy.jpg +http://www.tehcute.com/pics/201401/little-fox-big.jpg +https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR6QXB1APLdUsyzO39kPvhnC9cOvcwzEtsxown9QjWilWppia2mwg \ No newline at end of file From f4ced55d15abff3ad019c9e69811d7be0856b9a7 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 4 Apr 2018 01:41:37 +0200 Subject: [PATCH 135/553] Disable voice features --- Geekbot.net/Commands/Voice.cs | 204 +++++++++++++++++----------------- 1 file changed, 102 insertions(+), 102 deletions(-) diff --git a/Geekbot.net/Commands/Voice.cs b/Geekbot.net/Commands/Voice.cs index cda1f8b..ca65913 100644 --- a/Geekbot.net/Commands/Voice.cs +++ b/Geekbot.net/Commands/Voice.cs @@ -1,102 +1,102 @@ -using System; -using System.IO; -using System.Threading.Tasks; -using Discord; -using Discord.Commands; -using Geekbot.net.Lib; - -namespace Geekbot.net.Commands -{ - public class Voice : ModuleBase - { - private readonly IAudioUtils _audioUtils; - private readonly IErrorHandler _errorHandler; - - public Voice(IErrorHandler errorHandler, IAudioUtils audioUtils) - { - _errorHandler = errorHandler; - _audioUtils = audioUtils; - } - - [Command("join")] - public async Task JoinChannel() - { - try - { - // Get the audio channel - var channel = (Context.User as IGuildUser)?.VoiceChannel; - if (channel == null) - { - await Context.Channel.SendMessageAsync( - "User must be in a voice channel, or a voice channel must be passed as an argument."); - return; - } - - // For the next step with transmitting audio, you would want to pass this Audio Client in to a service. - var audioClient = await channel.ConnectAsync(); - _audioUtils.StoreAudioClient(Context.Guild.Id, audioClient); - await ReplyAsync($"Connected to {channel.Name}"); - } - catch (Exception e) - { - _errorHandler.HandleCommandException(e, Context); - } - } - - [Command("disconnect")] - public async Task DisconnectChannel() - { - try - { - var audioClient = _audioUtils.GetAudioClient(Context.Guild.Id); - if (audioClient == null) - { - await Context.Channel.SendMessageAsync("I'm not in a voice channel at the moment"); - return; - } - - await audioClient.StopAsync(); - await ReplyAsync("Disconnected from channel!"); - _audioUtils.Cleanup(Context.Guild.Id); - } - catch (Exception e) - { - _errorHandler.HandleCommandException(e, Context); - _audioUtils.Cleanup(Context.Guild.Id); - } - } - - [Command("ytplay")] - public async Task ytplay(string url) - { - try - { - if (!url.Contains("youtube")) - { - await ReplyAsync("I can only play youtube videos"); - return; - } - var audioClient = _audioUtils.GetAudioClient(Context.Guild.Id); - if (audioClient == null) - { - await ReplyAsync("I'm not in a voice channel at the moment"); - return; - } - - var message = await Context.Channel.SendMessageAsync("Just a second, i'm still a bit slow at this"); - var ffmpeg = _audioUtils.CreateStreamFromYoutube(url, Context.Guild.Id); - var output = ffmpeg.StandardOutput.BaseStream; - await message.ModifyAsync(msg => msg.Content = "**Playing!** Please note that this feature is experimental"); - var discord = audioClient.CreatePCMStream(Discord.Audio.AudioApplication.Mixed); - await output.CopyToAsync(discord); - await discord.FlushAsync(); - _audioUtils.Cleanup(Context.Guild.Id); - } - catch (Exception e) - { - _errorHandler.HandleCommandException(e, Context); - _audioUtils.Cleanup(Context.Guild.Id); - } - } - } -} \ No newline at end of file +//using System; +//using System.IO; +//using System.Threading.Tasks; +//using Discord; +//using Discord.Commands; +//using Geekbot.net.Lib; +// +//namespace Geekbot.net.Commands +//{ +// public class Voice : ModuleBase +// { +// private readonly IAudioUtils _audioUtils; +// private readonly IErrorHandler _errorHandler; +// +// public Voice(IErrorHandler errorHandler, IAudioUtils audioUtils) +// { +// _errorHandler = errorHandler; +// _audioUtils = audioUtils; +// } +// +// [Command("join")] +// public async Task JoinChannel() +// { +// try +// { +// // Get the audio channel +// var channel = (Context.User as IGuildUser)?.VoiceChannel; +// if (channel == null) +// { +// await Context.Channel.SendMessageAsync( +// "User must be in a voice channel, or a voice channel must be passed as an argument."); +// return; +// } +// +// // For the next step with transmitting audio, you would want to pass this Audio Client in to a service. +// var audioClient = await channel.ConnectAsync(); +// _audioUtils.StoreAudioClient(Context.Guild.Id, audioClient); +// await ReplyAsync($"Connected to {channel.Name}"); +// } +// catch (Exception e) +// { +// _errorHandler.HandleCommandException(e, Context); +// } +// } +// +// [Command("disconnect")] +// public async Task DisconnectChannel() +// { +// try +// { +// var audioClient = _audioUtils.GetAudioClient(Context.Guild.Id); +// if (audioClient == null) +// { +// await Context.Channel.SendMessageAsync("I'm not in a voice channel at the moment"); +// return; +// } +// +// await audioClient.StopAsync(); +// await ReplyAsync("Disconnected from channel!"); +// _audioUtils.Cleanup(Context.Guild.Id); +// } +// catch (Exception e) +// { +// _errorHandler.HandleCommandException(e, Context); +// _audioUtils.Cleanup(Context.Guild.Id); +// } +// } +// +// [Command("ytplay")] +// public async Task ytplay(string url) +// { +// try +// { +// if (!url.Contains("youtube")) +// { +// await ReplyAsync("I can only play youtube videos"); +// return; +// } +// var audioClient = _audioUtils.GetAudioClient(Context.Guild.Id); +// if (audioClient == null) +// { +// await ReplyAsync("I'm not in a voice channel at the moment"); +// return; +// } +// +// var message = await Context.Channel.SendMessageAsync("Just a second, i'm still a bit slow at this"); +// var ffmpeg = _audioUtils.CreateStreamFromYoutube(url, Context.Guild.Id); +// var output = ffmpeg.StandardOutput.BaseStream; +// await message.ModifyAsync(msg => msg.Content = "**Playing!** Please note that this feature is experimental"); +// var discord = audioClient.CreatePCMStream(Discord.Audio.AudioApplication.Mixed); +// await output.CopyToAsync(discord); +// await discord.FlushAsync(); +// _audioUtils.Cleanup(Context.Guild.Id); +// } +// catch (Exception e) +// { +// _errorHandler.HandleCommandException(e, Context); +// _audioUtils.Cleanup(Context.Guild.Id); +// } +// } +// } +//} \ No newline at end of file From 846c928f5f5dd551963b61e5a4490fd42d3e2353 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 28 Apr 2018 01:01:48 +0200 Subject: [PATCH 136/553] Add wikipedia api client, add wikipedia command, show errors in chat when debugging --- .gitignore | 4 + Geekbot.net.sln | 6 ++ Geekbot.net/Commands/Wikipedia.cs | 94 +++++++++++++++++++ Geekbot.net/Geekbot.net.csproj | 6 +- Geekbot.net/Lib/ErrorHandler.cs | 18 +++- Geekbot.net/Program.cs | 9 +- WikipediaApi/IWikipediaClient.cs | 10 ++ WikipediaApi/Page/PageApiUrls.cs | 14 +++ WikipediaApi/Page/PageContentUrlCollection.cs | 8 ++ WikipediaApi/Page/PageContentUrls.cs | 12 +++ WikipediaApi/Page/PageCoordinates.cs | 8 ++ WikipediaApi/Page/PageImage.cs | 12 +++ WikipediaApi/Page/PageNamespace.cs | 8 ++ WikipediaApi/Page/PagePreview.cs | 68 ++++++++++++++ WikipediaApi/Page/PageTitles.cs | 10 ++ WikipediaApi/Page/PageTypes.cs | 19 ++++ WikipediaApi/WikipediaApi.csproj | 8 ++ WikipediaApi/WikipediaClient.cs | 29 ++++++ 18 files changed, 334 insertions(+), 9 deletions(-) create mode 100644 Geekbot.net/Commands/Wikipedia.cs create mode 100644 WikipediaApi/IWikipediaClient.cs create mode 100644 WikipediaApi/Page/PageApiUrls.cs create mode 100644 WikipediaApi/Page/PageContentUrlCollection.cs create mode 100644 WikipediaApi/Page/PageContentUrls.cs create mode 100644 WikipediaApi/Page/PageCoordinates.cs create mode 100644 WikipediaApi/Page/PageImage.cs create mode 100644 WikipediaApi/Page/PageNamespace.cs create mode 100644 WikipediaApi/Page/PagePreview.cs create mode 100644 WikipediaApi/Page/PageTitles.cs create mode 100644 WikipediaApi/Page/PageTypes.cs create mode 100644 WikipediaApi/WikipediaApi.csproj create mode 100644 WikipediaApi/WikipediaClient.cs diff --git a/.gitignore b/.gitignore index c99d9e6..fe7e3d4 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,7 @@ UpgradeLog.htm .vscode Geekbot.net/Logs/* !/Geekbot.net/Logs/.keep +Geekbot.net.sln.DotSettings.user +Geekbot.net/temp/ +WikipediaApi/bin/ +WikipediaApi/obj/ diff --git a/Geekbot.net.sln b/Geekbot.net.sln index 5011ad4..b542f25 100644 --- a/Geekbot.net.sln +++ b/Geekbot.net.sln @@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Geekbot.net", "Geekbot.net/ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WikipediaApi", "WikipediaApi\WikipediaApi.csproj", "{1084D499-EF94-4834-9E6A-B2AD81B60078}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -21,6 +23,10 @@ Global {4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}.Debug|Any CPU.Build.0 = Debug|Any CPU {4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}.Release|Any CPU.ActiveCfg = Release|Any CPU {4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}.Release|Any CPU.Build.0 = Release|Any CPU + {1084D499-EF94-4834-9E6A-B2AD81B60078}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1084D499-EF94-4834-9E6A-B2AD81B60078}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1084D499-EF94-4834-9E6A-B2AD81B60078}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1084D499-EF94-4834-9E6A-B2AD81B60078}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Geekbot.net/Commands/Wikipedia.cs b/Geekbot.net/Commands/Wikipedia.cs new file mode 100644 index 0000000..d0ea945 --- /dev/null +++ b/Geekbot.net/Commands/Wikipedia.cs @@ -0,0 +1,94 @@ +using System; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Discord.Net; +using Geekbot.net.Lib; +using HtmlAgilityPack; +using WikipediaApi; +using WikipediaApi.Page; + +namespace Geekbot.net.Commands +{ + public class Wikipedia : ModuleBase + { + private readonly IErrorHandler _errorHandler; + private readonly IWikipediaClient _wikipediaClient; + + public Wikipedia(IErrorHandler errorHandler, IWikipediaClient wikipediaClient) + { + _errorHandler = errorHandler; + _wikipediaClient = wikipediaClient; + } + + [Command("wiki", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Helpers)] + [Summary("Get an article from wikipedia.")] + public async Task GetPreview([Remainder] [Summary("Article")] string articleName) + { + try + { + var article = await _wikipediaClient.GetPreview(articleName.Replace(" ", "_")); + + if (article.Type != PageTypes.Standard) + { + switch (article.Type) + { + case PageTypes.Disambiguation: + await ReplyAsync($"**__Disambiguation__**\r\n{DisambiguationExtractor(article.ExtractHtml)}"); + break; + case PageTypes.MainPage: + await ReplyAsync("The main page is not supported"); + break; + case PageTypes.NoExtract: + await ReplyAsync($"This page has no summary, here is the link: {article.ContentUrls.Desktop.Page}"); + break; + case PageTypes.Standard: + break; + default: + await ReplyAsync($"This page type is currently not supported, here is the link: {article.ContentUrls.Desktop.Page}"); + break; + } + return; + } + + var eb = new EmbedBuilder + { + Title = article.Title, + Description = article.Extract, + ImageUrl = article.Thumbnail.Source.ToString(), + Url = article.ContentUrls.Desktop.Page.ToString() + }; + await ReplyAsync("", false, eb.Build()); + } + catch (HttpRequestException e) + { + await ReplyAsync("I couldn't find that article"); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + private string DisambiguationExtractor(string extractHtml) + { + var doc = new HtmlDocument(); + doc.LoadHtml(extractHtml); + var nodes = doc.DocumentNode.SelectNodes("//li"); + var sb = new StringBuilder(); + foreach (var node in nodes) + { + var split = node.InnerText.Split(','); + var title = split.First(); + var desc = string.Join(",", split.Skip(1)); + sb.AppendLine($"**{title}** - {desc}"); + } + + return sb.ToString(); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 1a11cd9..6fb13f9 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -15,6 +15,7 @@ 1.0.2
+ @@ -22,7 +23,7 @@ - + @@ -76,4 +77,7 @@ PreserveNewest + + + \ No newline at end of file diff --git a/Geekbot.net/Lib/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandler.cs index 3410e91..c0c3d95 100644 --- a/Geekbot.net/Lib/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandler.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Diagnostics; using System.Net; using Discord.Commands; using Discord.Net; @@ -12,12 +14,14 @@ namespace Geekbot.net.Lib private readonly IGeekbotLogger _logger; private readonly ITranslationHandler _translation; private readonly IRavenClient _raven; + private readonly bool _errorsInChat; - public ErrorHandler(IGeekbotLogger logger, ITranslationHandler translation) + public ErrorHandler(IGeekbotLogger logger, ITranslationHandler translation, bool errorsInChat) { _logger = logger; _translation = translation; - + _errorsInChat = errorsInChat; + var sentryDsn = Environment.GetEnvironmentVariable("SENTRY"); if (!string.IsNullOrEmpty(sentryDsn)) { @@ -41,7 +45,15 @@ namespace Geekbot.net.Lib _logger.Error("Geekbot", "An error ocured", e, errorObj); if (!string.IsNullOrEmpty(errorMessage)) { - Context.Channel.SendMessageAsync(errorString); + if (_errorsInChat) + { + Context.Channel.SendMessageAsync($"{e.Message}\r\n```\r\n{e.InnerException}\r\n```"); + } + else + { + Context.Channel.SendMessageAsync(errorString); + } + } if (_raven == null) return; diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 3f31945..b805e5f 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -1,10 +1,7 @@ using System; -using System.Collections.Generic; -using System.IO; using System.Linq; using System.Net; using System.Reflection; -using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using Discord; @@ -14,8 +11,8 @@ using Geekbot.net.Lib; using Geekbot.net.Lib.Media; using Microsoft.Extensions.DependencyInjection; using Nancy.Hosting.Self; -using Serilog; using StackExchange.Redis; +using WikipediaApi; namespace Geekbot.net { @@ -101,6 +98,7 @@ namespace Geekbot.net var emojiConverter = new EmojiConverter(); var audioUtils = new AudioUtils(); var mtgManaConverter = new MtgManaConverter(); + var wikipediaClient = new WikipediaClient(); services.AddSingleton(redis); services.AddSingleton(logger); @@ -112,6 +110,7 @@ namespace Geekbot.net services.AddSingleton(mediaProvider); services.AddSingleton(malClient); services.AddSingleton(mtgManaConverter); + services.AddSingleton(wikipediaClient); logger.Information("Geekbot", "Connecting to Discord"); @@ -134,7 +133,7 @@ namespace Geekbot.net logger.Information("Geekbot", "Registering Stuff"); var translationHandler = new TranslationHandler(client.Guilds, redis, logger); - var errorHandler = new ErrorHandler(logger, translationHandler); + var errorHandler = new ErrorHandler(logger, translationHandler, args.Contains("--expose-errors")); var reactionListener = new ReactionListener(redis); await commands.AddModulesAsync(Assembly.GetEntryAssembly()); services.AddSingleton(commands); diff --git a/WikipediaApi/IWikipediaClient.cs b/WikipediaApi/IWikipediaClient.cs new file mode 100644 index 0000000..3fad554 --- /dev/null +++ b/WikipediaApi/IWikipediaClient.cs @@ -0,0 +1,10 @@ +using System.Threading.Tasks; +using WikipediaApi.Page; + +namespace WikipediaApi +{ + public interface IWikipediaClient + { + Task GetPreview(string pageName); + } +} \ No newline at end of file diff --git a/WikipediaApi/Page/PageApiUrls.cs b/WikipediaApi/Page/PageApiUrls.cs new file mode 100644 index 0000000..8a121be --- /dev/null +++ b/WikipediaApi/Page/PageApiUrls.cs @@ -0,0 +1,14 @@ +using System; + +namespace WikipediaApi.Page +{ + public class PageApiUrls + { + public Uri Summary { get; set; } + public Uri Metadata { get; set; } + public Uri References { get; set; } + public Uri Media { get; set; } + public Uri EditHtml { get; set; } + public Uri TalkPageHtml { get; set; } + } +} \ No newline at end of file diff --git a/WikipediaApi/Page/PageContentUrlCollection.cs b/WikipediaApi/Page/PageContentUrlCollection.cs new file mode 100644 index 0000000..f6c680b --- /dev/null +++ b/WikipediaApi/Page/PageContentUrlCollection.cs @@ -0,0 +1,8 @@ +namespace WikipediaApi.Page +{ + public class PageContentUrlCollection + { + public PageContentUrls Desktop { get; set; } + public PageContentUrls Mobile { get; set; } + } +} \ No newline at end of file diff --git a/WikipediaApi/Page/PageContentUrls.cs b/WikipediaApi/Page/PageContentUrls.cs new file mode 100644 index 0000000..64a80dc --- /dev/null +++ b/WikipediaApi/Page/PageContentUrls.cs @@ -0,0 +1,12 @@ +using System; + +namespace WikipediaApi.Page +{ + public class PageContentUrls + { + public Uri Page { get; set; } + public Uri Revisions { get; set; } + public Uri Edit { get; set; } + public Uri Talk { get; set; } + } +} \ No newline at end of file diff --git a/WikipediaApi/Page/PageCoordinates.cs b/WikipediaApi/Page/PageCoordinates.cs new file mode 100644 index 0000000..f86bb09 --- /dev/null +++ b/WikipediaApi/Page/PageCoordinates.cs @@ -0,0 +1,8 @@ +namespace WikipediaApi.Page +{ + public class PageCoordinates + { + public float lat { get; set; } + public float lon { get; set; } + } +} \ No newline at end of file diff --git a/WikipediaApi/Page/PageImage.cs b/WikipediaApi/Page/PageImage.cs new file mode 100644 index 0000000..4a8b28d --- /dev/null +++ b/WikipediaApi/Page/PageImage.cs @@ -0,0 +1,12 @@ +using System; + +namespace WikipediaApi.Page +{ + public class PageImage + { + public Uri Source { get; set; } + public int Width { get; set; } + public int Height { get; set; } + + } +} \ No newline at end of file diff --git a/WikipediaApi/Page/PageNamespace.cs b/WikipediaApi/Page/PageNamespace.cs new file mode 100644 index 0000000..66600b6 --- /dev/null +++ b/WikipediaApi/Page/PageNamespace.cs @@ -0,0 +1,8 @@ +namespace WikipediaApi.Page +{ + public class PageNamespace + { + public ulong Id { get; set; } + public string Text { get; set; } + } +} \ No newline at end of file diff --git a/WikipediaApi/Page/PagePreview.cs b/WikipediaApi/Page/PagePreview.cs new file mode 100644 index 0000000..41ab6f3 --- /dev/null +++ b/WikipediaApi/Page/PagePreview.cs @@ -0,0 +1,68 @@ +using System; +using System.Runtime.Serialization; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; + +namespace WikipediaApi.Page +{ + public class PagePreview + { + [JsonProperty("type")] + [JsonConverter(typeof(StringEnumConverter))] + public PageTypes Type { get; set; } = PageTypes.NoExtract; + + [JsonProperty("title")] + public string Title { get; set; } + + [JsonProperty("displaytitle")] + public string Displaytitle { get; set; } + + [JsonProperty("namespace")] + public PageNamespace @Namespace { get; set; } + + [JsonProperty("titles")] + public PageTitles Titles { get; set; } + + [JsonProperty("pageid")] + public ulong Pageid { get; set; } + + [JsonProperty("thumbnail")] + public PageImage Thumbnail { get; set; } + + [JsonProperty("originalimage")] + public PageImage Originalimage { get; set; } + + [JsonProperty("lang")] + public string Lang { get; set; } + + [JsonProperty("dir")] + public string Dir { get; set; } + + [JsonProperty("revision")] + public ulong Revision { get; set; } + + [JsonProperty("tid")] + public string Tid { get; set; } + + [JsonProperty("timestamp")] + public DateTimeOffset Timestamp { get; set; } + + [JsonProperty("description")] + public string Description { get; set; } + + [JsonProperty("coordinates")] + public PageCoordinates Coordinates { get; set; } + + [JsonProperty("content_urls")] + public PageContentUrlCollection ContentUrls { get; set; } + + [JsonProperty("api_urls")] + public PageApiUrls ApiUrls { get; set; } + + [JsonProperty("extract")] + public string Extract { get; set; } + + [JsonProperty("extract_html")] + public string ExtractHtml { get; set; } + } +} \ No newline at end of file diff --git a/WikipediaApi/Page/PageTitles.cs b/WikipediaApi/Page/PageTitles.cs new file mode 100644 index 0000000..31a55b9 --- /dev/null +++ b/WikipediaApi/Page/PageTitles.cs @@ -0,0 +1,10 @@ +namespace WikipediaApi.Page +{ + public class PageTitles + { + public string Canonical { get; set; } + public string Normalized { get; set; } + public string Display { get; set; } + + } +} \ No newline at end of file diff --git a/WikipediaApi/Page/PageTypes.cs b/WikipediaApi/Page/PageTypes.cs new file mode 100644 index 0000000..a415d75 --- /dev/null +++ b/WikipediaApi/Page/PageTypes.cs @@ -0,0 +1,19 @@ +using System.Runtime.Serialization; + +namespace WikipediaApi.Page +{ + public enum PageTypes + { + [EnumMember(Value = "standard")] + Standard, + + [EnumMember(Value = "disambiguation")] + Disambiguation, + + [EnumMember(Value = "mainpage")] + MainPage, + + [EnumMember(Value = "no-extract")] + NoExtract + } +} \ No newline at end of file diff --git a/WikipediaApi/WikipediaApi.csproj b/WikipediaApi/WikipediaApi.csproj new file mode 100644 index 0000000..f182d90 --- /dev/null +++ b/WikipediaApi/WikipediaApi.csproj @@ -0,0 +1,8 @@ + + + netcoreapp2.0 + + + + + \ No newline at end of file diff --git a/WikipediaApi/WikipediaClient.cs b/WikipediaApi/WikipediaClient.cs new file mode 100644 index 0000000..9bd3059 --- /dev/null +++ b/WikipediaApi/WikipediaClient.cs @@ -0,0 +1,29 @@ +using System; +using System.Net.Http; +using System.Threading.Tasks; +using Newtonsoft.Json; +using WikipediaApi.Page; + +namespace WikipediaApi +{ + public class WikipediaClient : IWikipediaClient + { + private readonly HttpClient _httpClient; + public WikipediaClient() + { + _httpClient = new HttpClient + { + BaseAddress = new Uri("https://en.wikipedia.org") + }; + } + + public async Task GetPreview(string pageName) + { + var response = await _httpClient.GetAsync($"/api/rest_v1/page/summary/{pageName}"); + response.EnsureSuccessStatusCode(); + + var stringResponse = await response.Content.ReadAsStringAsync(); + return JsonConvert.DeserializeObject(stringResponse); + } + } +} \ No newline at end of file From 4548c6083aa5c6cecf0ef511e58c6e0ee35588f6 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 28 Apr 2018 01:28:48 +0200 Subject: [PATCH 137/553] Dependency updates and mtg color fixes --- Geekbot.net/Commands/MagicTheGathering.cs | 12 ++++++------ Geekbot.net/Commands/Overwatch.cs | 2 +- Geekbot.net/Geekbot.net.csproj | 16 ++++++++-------- WikipediaApi/WikipediaClient.cs | 4 ++-- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Geekbot.net/Commands/MagicTheGathering.cs b/Geekbot.net/Commands/MagicTheGathering.cs index e3cc864..044c287 100644 --- a/Geekbot.net/Commands/MagicTheGathering.cs +++ b/Geekbot.net/Commands/MagicTheGathering.cs @@ -74,17 +74,17 @@ namespace Geekbot.net.Commands switch (color) { case "Black": - return new Color(177, 171, 170); + return new Color(203, 194, 191); case "White": - return new Color(255, 252, 214); + return new Color(255, 251, 213); case "Blue": - return new Color(156, 189, 204); + return new Color(170, 224, 250); case "Red": - return new Color(204, 156, 140); + return new Color(250, 170, 143); case "Green": - return new Color(147, 181, 159); + return new Color(155, 211, 174); default: - return new Color(255, 252, 214); + return new Color(204, 194, 212); } } } diff --git a/Geekbot.net/Commands/Overwatch.cs b/Geekbot.net/Commands/Overwatch.cs index 10dc459..fbb9699 100644 --- a/Geekbot.net/Commands/Overwatch.cs +++ b/Geekbot.net/Commands/Overwatch.cs @@ -110,7 +110,7 @@ namespace Geekbot.net.Commands private async Task createProfile(string battletag) { - var owConfig = new OverwatchConfig.Builder().WithRegions(Region.Eu).WithPlatforms(Platform.Pc); + var owConfig = new OverwatchConfig.Builder().WithPlatforms(Platform.Pc); using (var owClient = new OverwatchClient(owConfig)) { var player = await owClient.GetPlayerAsync(battletag); diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 6fb13f9..c91512f 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -14,24 +14,24 @@ 1.0.2 - + - - - - + + + + - + - + - + 1.2.6 diff --git a/WikipediaApi/WikipediaClient.cs b/WikipediaApi/WikipediaClient.cs index 9bd3059..25bf299 100644 --- a/WikipediaApi/WikipediaClient.cs +++ b/WikipediaApi/WikipediaClient.cs @@ -9,11 +9,11 @@ namespace WikipediaApi public class WikipediaClient : IWikipediaClient { private readonly HttpClient _httpClient; - public WikipediaClient() + public WikipediaClient(string language = "en") { _httpClient = new HttpClient { - BaseAddress = new Uri("https://en.wikipedia.org") + BaseAddress = new Uri($"https://{language}.wikipedia.org") }; } From f5fd9ba017d3493730d72e815b58278457399c9a Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 28 Apr 2018 02:46:30 +0200 Subject: [PATCH 138/553] Bug fixes in !wiki and errorHandler --- Geekbot.net/Commands/Help.cs | 2 +- Geekbot.net/Commands/Wikipedia.cs | 5 +++-- Geekbot.net/Lib/ErrorHandler.cs | 5 ++++- WikipediaApi/Page/PagePreview.cs | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Geekbot.net/Commands/Help.cs b/Geekbot.net/Commands/Help.cs index 83374a8..1b3e285 100644 --- a/Geekbot.net/Commands/Help.cs +++ b/Geekbot.net/Commands/Help.cs @@ -29,7 +29,7 @@ namespace Geekbot.net.Commands sb.AppendLine("https://geekbot.pizzaandcoffee.rocks/commands"); var dm = await Context.User.GetOrCreateDMChannelAsync(); await dm.SendMessageAsync(sb.ToString()); - Context.Message.AddReactionAsync(new Emoji("✅")); + await Context.Message.AddReactionAsync(new Emoji("✅")); } catch (Exception e) { diff --git a/Geekbot.net/Commands/Wikipedia.cs b/Geekbot.net/Commands/Wikipedia.cs index d0ea945..e7b36cf 100644 --- a/Geekbot.net/Commands/Wikipedia.cs +++ b/Geekbot.net/Commands/Wikipedia.cs @@ -59,12 +59,12 @@ namespace Geekbot.net.Commands { Title = article.Title, Description = article.Extract, - ImageUrl = article.Thumbnail.Source.ToString(), + ImageUrl = article.Thumbnail?.Source.ToString(), Url = article.ContentUrls.Desktop.Page.ToString() }; await ReplyAsync("", false, eb.Build()); } - catch (HttpRequestException e) + catch (HttpRequestException) { await ReplyAsync("I couldn't find that article"); } @@ -79,6 +79,7 @@ namespace Geekbot.net.Commands var doc = new HtmlDocument(); doc.LoadHtml(extractHtml); var nodes = doc.DocumentNode.SelectNodes("//li"); + if (nodes == null) return "(List is to long to show)"; var sb = new StringBuilder(); foreach (var node in nodes) { diff --git a/Geekbot.net/Lib/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandler.cs index c0c3d95..dc67db2 100644 --- a/Geekbot.net/Lib/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandler.cs @@ -47,7 +47,9 @@ namespace Geekbot.net.Lib { if (_errorsInChat) { - Context.Channel.SendMessageAsync($"{e.Message}\r\n```\r\n{e.InnerException}\r\n```"); + var resStackTrace = string.IsNullOrEmpty(e.InnerException?.ToString()) ? e.StackTrace : e.InnerException.ToString(); + var maxLen = Math.Min(resStackTrace.Length, 1850); + Context.Channel.SendMessageAsync($"{e.Message}\r\n```\r\n{resStackTrace?.Substring(0, maxLen)}\r\n```"); } else { @@ -72,6 +74,7 @@ namespace Geekbot.net.Lib } catch (Exception ex) { + Context.Channel.SendMessageAsync("Something went really really wrong here"); _logger.Error("Geekbot", "Errorception", ex); } } diff --git a/WikipediaApi/Page/PagePreview.cs b/WikipediaApi/Page/PagePreview.cs index 41ab6f3..c1de2d7 100644 --- a/WikipediaApi/Page/PagePreview.cs +++ b/WikipediaApi/Page/PagePreview.cs @@ -9,7 +9,7 @@ namespace WikipediaApi.Page { [JsonProperty("type")] [JsonConverter(typeof(StringEnumConverter))] - public PageTypes Type { get; set; } = PageTypes.NoExtract; + public PageTypes Type { get; set; } [JsonProperty("title")] public string Title { get; set; } From b97fca787ce6262f1a084135757066e12968da2c Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 28 Apr 2018 17:38:45 +0200 Subject: [PATCH 139/553] Ability to change wikipedia instance and make !wiki nicer --- Geekbot.net/Commands/Admin.cs | 18 ++++++++++++++++++ Geekbot.net/Commands/Wikipedia.cs | 31 ++++++++++++++++++++++++------- WikipediaApi/IWikipediaClient.cs | 2 +- WikipediaApi/WikipediaClient.cs | 11 ++++------- 4 files changed, 47 insertions(+), 15 deletions(-) diff --git a/Geekbot.net/Commands/Admin.cs b/Geekbot.net/Commands/Admin.cs index 681ff99..4e94673 100644 --- a/Geekbot.net/Commands/Admin.cs +++ b/Geekbot.net/Commands/Admin.cs @@ -138,6 +138,24 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } + + [Command("wiki", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Admin)] + [Summary("Change the wikipedia instance (use lang code in xx.wikipedia.org)")] + public async Task setWikiLanguage([Summary("language")] string languageRaw) + { + try + { + var language = languageRaw.ToLower(); + _redis.HashSet($"{Context.Guild.Id}:Settings", new[] {new HashEntry("WikiLang", language) }); + + await ReplyAsync($"Now using the {language} wikipedia"); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } [Command("lang", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] diff --git a/Geekbot.net/Commands/Wikipedia.cs b/Geekbot.net/Commands/Wikipedia.cs index e7b36cf..77fb41d 100644 --- a/Geekbot.net/Commands/Wikipedia.cs +++ b/Geekbot.net/Commands/Wikipedia.cs @@ -5,9 +5,9 @@ using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Discord.Net; using Geekbot.net.Lib; using HtmlAgilityPack; +using StackExchange.Redis; using WikipediaApi; using WikipediaApi.Page; @@ -17,11 +17,13 @@ namespace Geekbot.net.Commands { private readonly IErrorHandler _errorHandler; private readonly IWikipediaClient _wikipediaClient; - - public Wikipedia(IErrorHandler errorHandler, IWikipediaClient wikipediaClient) + private readonly IDatabase _redis; + + public Wikipedia(IErrorHandler errorHandler, IWikipediaClient wikipediaClient, IDatabase redis) { _errorHandler = errorHandler; _wikipediaClient = wikipediaClient; + _redis = redis; } [Command("wiki", RunMode = RunMode.Async)] @@ -31,7 +33,12 @@ namespace Geekbot.net.Commands { try { - var article = await _wikipediaClient.GetPreview(articleName.Replace(" ", "_")); + var wikiLang = _redis.HashGet($"{Context.Guild.Id}:Settings", "WikiLang").ToString(); + if (string.IsNullOrEmpty(wikiLang)) + { + wikiLang = "en"; + } + var article = await _wikipediaClient.GetPreview(articleName.Replace(" ", "_"), wikiLang); if (article.Type != PageTypes.Standard) { @@ -58,10 +65,20 @@ namespace Geekbot.net.Commands var eb = new EmbedBuilder { Title = article.Title, - Description = article.Extract, + Description = article.Description, ImageUrl = article.Thumbnail?.Source.ToString(), - Url = article.ContentUrls.Desktop.Page.ToString() + Url = article.ContentUrls.Desktop.Page.ToString(), + Color = new Color(246,246,246), + Timestamp = article.Timestamp, + Footer = new EmbedFooterBuilder + { + Text = "Last Edit", + IconUrl = "http://icons.iconarchive.com/icons/sykonist/popular-sites/256/Wikipedia-icon.png" + } }; + + eb.AddField("Description", article.Extract); + if (article.Coordinates != null) eb.AddField("Coordinates", $"{article.Coordinates.lat} Lat {article.Coordinates.lon} Lon"); await ReplyAsync("", false, eb.Build()); } catch (HttpRequestException) @@ -86,7 +103,7 @@ namespace Geekbot.net.Commands var split = node.InnerText.Split(','); var title = split.First(); var desc = string.Join(",", split.Skip(1)); - sb.AppendLine($"**{title}** - {desc}"); + sb.AppendLine($"• **{title}** -{desc}"); } return sb.ToString(); diff --git a/WikipediaApi/IWikipediaClient.cs b/WikipediaApi/IWikipediaClient.cs index 3fad554..4d1dae9 100644 --- a/WikipediaApi/IWikipediaClient.cs +++ b/WikipediaApi/IWikipediaClient.cs @@ -5,6 +5,6 @@ namespace WikipediaApi { public interface IWikipediaClient { - Task GetPreview(string pageName); + Task GetPreview(string pageName, string language = "en"); } } \ No newline at end of file diff --git a/WikipediaApi/WikipediaClient.cs b/WikipediaApi/WikipediaClient.cs index 25bf299..161cbce 100644 --- a/WikipediaApi/WikipediaClient.cs +++ b/WikipediaApi/WikipediaClient.cs @@ -9,17 +9,14 @@ namespace WikipediaApi public class WikipediaClient : IWikipediaClient { private readonly HttpClient _httpClient; - public WikipediaClient(string language = "en") + public WikipediaClient() { - _httpClient = new HttpClient - { - BaseAddress = new Uri($"https://{language}.wikipedia.org") - }; + _httpClient = new HttpClient(); } - public async Task GetPreview(string pageName) + public async Task GetPreview(string pageName, string language = "en") { - var response = await _httpClient.GetAsync($"/api/rest_v1/page/summary/{pageName}"); + var response = await _httpClient.GetAsync($"https://{language}.wikipedia.org/api/rest_v1/page/summary/{pageName}"); response.EnsureSuccessStatusCode(); var stringResponse = await response.Content.ReadAsStringAsync(); From b81284bfe7adda7a9df2877392ee164740ec3faa Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 28 Apr 2018 19:27:41 +0200 Subject: [PATCH 140/553] Add !chuck and !dad --- Geekbot.net/Commands/ChuckNorrisJokes.cs | 61 ++++++++++++++++++++++++ Geekbot.net/Commands/DadJokes.cs | 60 +++++++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 Geekbot.net/Commands/ChuckNorrisJokes.cs create mode 100644 Geekbot.net/Commands/DadJokes.cs diff --git a/Geekbot.net/Commands/ChuckNorrisJokes.cs b/Geekbot.net/Commands/ChuckNorrisJokes.cs new file mode 100644 index 0000000..1ac6c4d --- /dev/null +++ b/Geekbot.net/Commands/ChuckNorrisJokes.cs @@ -0,0 +1,61 @@ +using System; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Threading.Tasks; +using Discord.Commands; +using Geekbot.net.Lib; +using Newtonsoft.Json; + +namespace Geekbot.net.Commands +{ + public class ChuckNorrisJokes : ModuleBase + { + private readonly IErrorHandler _errorHandler; + + public ChuckNorrisJokes(IErrorHandler errorHandler) + { + _errorHandler = errorHandler; + } + + [Command("chuck", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Randomness)] + [Summary("A random chuck norris joke")] + public async Task Say() + { + try + { + using (var client = new HttpClient()) + { + try + { + client.DefaultRequestHeaders.Accept.Clear(); + client.DefaultRequestHeaders.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); + var response = await client.GetAsync("https://api.chucknorris.io/jokes/random"); + response.EnsureSuccessStatusCode(); + + var stringResponse = await response.Content.ReadAsStringAsync(); + var data = JsonConvert.DeserializeObject(stringResponse); + await ReplyAsync(data.value); + } + catch (HttpRequestException) + { + await ReplyAsync("Api down..."); + } + } + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + private class ChuckNorrisJokeResponse + { + public string category { get; set; } + public string icon_url { get; set; } + public string id { get; set; } + public string url { get; set; } + public string value { get; set; } + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/DadJokes.cs b/Geekbot.net/Commands/DadJokes.cs new file mode 100644 index 0000000..615f3d5 --- /dev/null +++ b/Geekbot.net/Commands/DadJokes.cs @@ -0,0 +1,60 @@ +using System; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Geekbot.net.Lib; +using Newtonsoft.Json; + +namespace Geekbot.net.Commands +{ + public class DadJokes : ModuleBase + { + private readonly IErrorHandler _errorHandler; + + public DadJokes(IErrorHandler errorHandler) + { + _errorHandler = errorHandler; + } + + [Command("dad", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Randomness)] + [Summary("A random dad joke")] + public async Task Say() + { + try + { + using (var client = new HttpClient()) + { + try + { + client.DefaultRequestHeaders.Accept.Clear(); + client.DefaultRequestHeaders.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); + var response = await client.GetAsync("https://icanhazdadjoke.com/"); + response.EnsureSuccessStatusCode(); + + var stringResponse = await response.Content.ReadAsStringAsync(); + var data = JsonConvert.DeserializeObject(stringResponse); + await ReplyAsync(data.joke); + } + catch (HttpRequestException) + { + await ReplyAsync("Api down..."); + } + } + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + private class DadJokeResponse + { + public string id { get; set; } + public string joke { get; set; } + public string status { get; set; } + } + } +} \ No newline at end of file From cdb104cacc7440f9d7b6a414056efd1a7e980916 Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 30 Apr 2018 23:44:19 +0200 Subject: [PATCH 141/553] Resharper suggestions --- Geekbot.net/Commands/Admin.cs | 16 +- Geekbot.net/Commands/AvatarGetter.cs | 2 +- Geekbot.net/Commands/BattleTag.cs | 11 +- Geekbot.net/Commands/Cat.cs | 4 +- Geekbot.net/Commands/Changelog.cs | 22 ++- Geekbot.net/Commands/CheckEm.cs | 2 +- Geekbot.net/Commands/ChuckNorrisJokes.cs | 8 +- Geekbot.net/Commands/DadJokes.cs | 7 +- Geekbot.net/Commands/Dice.cs | 38 ++--- Geekbot.net/Commands/Dog.cs | 4 +- Geekbot.net/Commands/Emojify.cs | 2 +- Geekbot.net/Commands/Gdq.cs | 4 +- Geekbot.net/Commands/Google.cs | 56 ++++--- Geekbot.net/Commands/GuildInfo.cs | 2 +- Geekbot.net/Commands/Karma.cs | 4 +- Geekbot.net/Commands/MagicTheGathering.cs | 3 +- Geekbot.net/Commands/Mod.cs | 4 +- Geekbot.net/Commands/Overwatch.cs | 23 ++- Geekbot.net/Commands/Owner.cs | 6 +- Geekbot.net/Commands/Pokedex.cs | 18 +-- Geekbot.net/Commands/Poll.cs | 8 +- Geekbot.net/Commands/Quote.cs | 68 ++++----- Geekbot.net/Commands/RandomAnimals.cs | 30 ++-- Geekbot.net/Commands/Rank.cs | 3 +- Geekbot.net/Commands/Role.cs | 10 +- Geekbot.net/Commands/Ship.cs | 4 +- Geekbot.net/Commands/Slap.cs | 2 +- Geekbot.net/Commands/UrbanDictionary.cs | 40 +++-- Geekbot.net/Commands/Wikipedia.cs | 2 +- Geekbot.net/Commands/mal.cs | 16 +- Geekbot.net/Handlers.cs | 2 - Geekbot.net/Lib/AudioClientCache.cs | 106 ------------- Geekbot.net/Lib/CommandCategories.cs | 2 +- Geekbot.net/Lib/Constants.cs | 2 +- Geekbot.net/Lib/EmojiConverter.cs | 12 +- Geekbot.net/Lib/ErrorHandler.cs | 24 ++- Geekbot.net/Lib/GeekbotLogger.cs | 4 +- Geekbot.net/Lib/LevelCalc.cs | 1 - Geekbot.net/Lib/LoggerFactory.cs | 3 +- Geekbot.net/Lib/MalClient.cs | 18 +-- Geekbot.net/Lib/Media/FortunesProvider.cs | 11 +- Geekbot.net/Lib/Media/MediaProvider.cs | 35 ++--- Geekbot.net/Lib/MtgManaConverter.cs | 1 - Geekbot.net/Lib/ReactionListener.cs | 2 +- Geekbot.net/Lib/SimpleConextConverter.cs | 25 ++-- Geekbot.net/Lib/TranslationHandler.cs | 6 +- Geekbot.net/Lib/UserRepository.cs | 21 ++- Geekbot.net/Program.cs | 174 +++++++++++----------- Geekbot.net/WebApi/HelpController.cs | 34 ++--- Geekbot.net/WebApi/StatusController.cs | 6 +- Tests/Lib/EmojiConverter.test.cs | 11 +- Tests/Lib/LevelCalc.test.cs | 3 +- WikipediaApi/Page/PageCoordinates.cs | 4 +- WikipediaApi/Page/PagePreview.cs | 3 +- WikipediaApi/WikipediaClient.cs | 3 +- 55 files changed, 382 insertions(+), 550 deletions(-) delete mode 100644 Geekbot.net/Lib/AudioClientCache.cs diff --git a/Geekbot.net/Commands/Admin.cs b/Geekbot.net/Commands/Admin.cs index 4e94673..481eab1 100644 --- a/Geekbot.net/Commands/Admin.cs +++ b/Geekbot.net/Commands/Admin.cs @@ -40,7 +40,7 @@ namespace Geekbot.net.Commands [Command("modchannel", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Set a channel for moderation purposes")] - public async Task selectModChannel([Summary("#Channel")] ISocketMessageChannel channel) + public async Task SelectModChannel([Summary("#Channel")] ISocketMessageChannel channel) { try { @@ -61,7 +61,7 @@ namespace Geekbot.net.Commands [Command("showleave", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Notify modchannel when someone leaves")] - public async Task showLeave([Summary("true/false")] bool enabled) + public async Task ShowLeave([Summary("true/false")] bool enabled) { var modChannelId = ulong.Parse(_redis.HashGet($"{Context.Guild.Id}:Settings", "ModChannel")); try @@ -88,7 +88,7 @@ namespace Geekbot.net.Commands [Command("showdel", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Notify modchannel when someone deletes a message")] - public async Task showDelete([Summary("true/false")] bool enabled) + public async Task ShowDelete([Summary("true/false")] bool enabled) { var modChannelId = ulong.Parse(_redis.HashGet($"{Context.Guild.Id}:Settings", "ModChannel")); try @@ -117,7 +117,7 @@ namespace Geekbot.net.Commands [Command("setlang", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Change the bots language")] - public async Task setLanguage([Summary("language")] string languageRaw) + public async Task SetLanguage([Summary("language")] string languageRaw) { try { @@ -142,7 +142,7 @@ namespace Geekbot.net.Commands [Command("wiki", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Change the wikipedia instance (use lang code in xx.wikipedia.org)")] - public async Task setWikiLanguage([Summary("language")] string languageRaw) + public async Task SetWikiLanguage([Summary("language")] string languageRaw) { try { @@ -160,7 +160,7 @@ namespace Geekbot.net.Commands [Command("lang", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Change the bots language")] - public async Task getLanguage() + public async Task GetLanguage() { try { @@ -176,12 +176,12 @@ namespace Geekbot.net.Commands [Command("ping", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Enable the ping reply.")] - public async Task togglePing() + public async Task TogglePing() { try { bool.TryParse(_redis.HashGet($"{Context.Guild.Id}:Settings", "ping"), out var current); - _redis.HashSet($"{Context.Guild.Id}:Settings", new[] {new HashEntry("ping", current ? "false" : "true"), }); + _redis.HashSet($"{Context.Guild.Id}:Settings", new[] {new HashEntry("ping", current ? "false" : "true") }); await ReplyAsync(!current ? "i will reply to ping now" : "No more pongs..."); } catch (Exception e) diff --git a/Geekbot.net/Commands/AvatarGetter.cs b/Geekbot.net/Commands/AvatarGetter.cs index 9e31b6b..d8a04e9 100644 --- a/Geekbot.net/Commands/AvatarGetter.cs +++ b/Geekbot.net/Commands/AvatarGetter.cs @@ -18,7 +18,7 @@ namespace Geekbot.net.Commands [Command("avatar", RunMode = RunMode.Async)] [Remarks(CommandCategories.Helpers)] [Summary("Get someones avatar")] - public async Task getAvatar([Remainder] [Summary("user")] IUser user = null) + public async Task GetAvatar([Remainder] [Summary("user")] IUser user = null) { try { diff --git a/Geekbot.net/Commands/BattleTag.cs b/Geekbot.net/Commands/BattleTag.cs index cbc5ecc..eb6fca1 100644 --- a/Geekbot.net/Commands/BattleTag.cs +++ b/Geekbot.net/Commands/BattleTag.cs @@ -24,7 +24,7 @@ namespace Geekbot.net.Commands { try { - var tag = _userRepository.getUserSetting(Context.User.Id, "BattleTag"); + var tag = _userRepository.GetUserSetting(Context.User.Id, "BattleTag"); if (!string.IsNullOrEmpty(tag)) await ReplyAsync($"Your BattleTag is {tag}"); else @@ -43,9 +43,9 @@ namespace Geekbot.net.Commands { try { - if (isValidTag(tag)) + if (IsValidTag(tag)) { - _userRepository.saveUserSetting(Context.User.Id, "BattleTag", tag); + _userRepository.SaveUserSetting(Context.User.Id, "BattleTag", tag); await ReplyAsync("Saved!"); } else @@ -59,13 +59,12 @@ namespace Geekbot.net.Commands } } - public static bool isValidTag(string tag) + public static bool IsValidTag(string tag) { var splited = tag.Split("#"); if (splited.Length != 2) return false; if (!int.TryParse(splited[1], out var discriminator)) return false; - if (splited[1].Length == 4 || splited[1].Length == 5) return true; - return false; + return splited[1].Length == 4 || splited[1].Length == 5; } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Cat.cs b/Geekbot.net/Commands/Cat.cs index 1f97d5a..0545894 100644 --- a/Geekbot.net/Commands/Cat.cs +++ b/Geekbot.net/Commands/Cat.cs @@ -35,7 +35,7 @@ namespace Geekbot.net.Commands var stringResponse = await response.Content.ReadAsStringAsync(); var catFile = JsonConvert.DeserializeObject(stringResponse); var eb = new EmbedBuilder(); - eb.ImageUrl = catFile.file; + eb.ImageUrl = catFile.File; await ReplyAsync("", false, eb.Build()); } catch @@ -52,7 +52,7 @@ namespace Geekbot.net.Commands private class CatResponse { - public string file { get; set; } + public string File { get; set; } } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Changelog.cs b/Geekbot.net/Commands/Changelog.cs index e060152..70c4c17 100644 --- a/Geekbot.net/Commands/Changelog.cs +++ b/Geekbot.net/Commands/Changelog.cs @@ -27,7 +27,7 @@ namespace Geekbot.net.Commands [Alias("updates")] [Remarks(CommandCategories.Helpers)] [Summary("Show the latest 5 updates")] - public async Task getChangelog() + public async Task GetChangelog() { try { @@ -40,7 +40,7 @@ namespace Geekbot.net.Commands response.EnsureSuccessStatusCode(); var stringResponse = await response.Content.ReadAsStringAsync(); - var commits = JsonConvert.DeserializeObject>(stringResponse); + var commits = JsonConvert.DeserializeObject>(stringResponse); var eb = new EmbedBuilder(); eb.WithColor(new Color(143, 165, 102)); eb.WithAuthor(new EmbedAuthorBuilder @@ -51,7 +51,7 @@ namespace Geekbot.net.Commands }); var sb = new StringBuilder(); foreach (var commit in commits.Take(10)) - sb.AppendLine($"- {commit.commit.message} ({commit.commit.author.date:yyyy-MM-dd})"); + sb.AppendLine($"- {commit.Commit.Message} ({commit.Commit.Author.Date:yyyy-MM-dd})"); eb.Description = sb.ToString(); eb.WithFooter(new EmbedFooterBuilder { @@ -66,24 +66,20 @@ namespace Geekbot.net.Commands } } - private class Commit + private class CommitDto { - public string sha { get; set; } - public CommitInfo commit { get; set; } - public Uri html_url { get; set; } + public CommitInfo Commit { get; set; } } private class CommitInfo { - public commitAuthor author { get; set; } - public string message { get; set; } + public CommitAuthor Author { get; set; } + public string Message { get; set; } } - private class commitAuthor + private class CommitAuthor { - public string name { get; set; } - public string email { get; set; } - public DateTimeOffset date { get; set; } + public DateTimeOffset Date { get; set; } } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/CheckEm.cs b/Geekbot.net/Commands/CheckEm.cs index 61de091..67df682 100644 --- a/Geekbot.net/Commands/CheckEm.cs +++ b/Geekbot.net/Commands/CheckEm.cs @@ -46,7 +46,7 @@ namespace Geekbot.net.Commands sb.AppendLine($"**{number}**"); if (!string.IsNullOrEmpty(dubtriqua)) sb.AppendLine($":tada: {dubtriqua} :tada:"); - sb.AppendLine(_checkEmImages.getCheckem()); + sb.AppendLine(_checkEmImages.GetCheckem()); await ReplyAsync(sb.ToString()); } diff --git a/Geekbot.net/Commands/ChuckNorrisJokes.cs b/Geekbot.net/Commands/ChuckNorrisJokes.cs index 1ac6c4d..1c3b009 100644 --- a/Geekbot.net/Commands/ChuckNorrisJokes.cs +++ b/Geekbot.net/Commands/ChuckNorrisJokes.cs @@ -35,7 +35,7 @@ namespace Geekbot.net.Commands var stringResponse = await response.Content.ReadAsStringAsync(); var data = JsonConvert.DeserializeObject(stringResponse); - await ReplyAsync(data.value); + await ReplyAsync(data.Value); } catch (HttpRequestException) { @@ -51,11 +51,7 @@ namespace Geekbot.net.Commands private class ChuckNorrisJokeResponse { - public string category { get; set; } - public string icon_url { get; set; } - public string id { get; set; } - public string url { get; set; } - public string value { get; set; } + public string Value { get; set; } } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/DadJokes.cs b/Geekbot.net/Commands/DadJokes.cs index 615f3d5..897c3e0 100644 --- a/Geekbot.net/Commands/DadJokes.cs +++ b/Geekbot.net/Commands/DadJokes.cs @@ -2,7 +2,6 @@ using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; -using Discord; using Discord.Commands; using Geekbot.net.Lib; using Newtonsoft.Json; @@ -36,7 +35,7 @@ namespace Geekbot.net.Commands var stringResponse = await response.Content.ReadAsStringAsync(); var data = JsonConvert.DeserializeObject(stringResponse); - await ReplyAsync(data.joke); + await ReplyAsync(data.Joke); } catch (HttpRequestException) { @@ -52,9 +51,7 @@ namespace Geekbot.net.Commands private class DadJokeResponse { - public string id { get; set; } - public string joke { get; set; } - public string status { get; set; } + public string Joke { get; set; } } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Dice.cs b/Geekbot.net/Commands/Dice.cs index 774f8b9..89b3a11 100644 --- a/Geekbot.net/Commands/Dice.cs +++ b/Geekbot.net/Commands/Dice.cs @@ -20,12 +20,12 @@ namespace Geekbot.net.Commands var mod = 0; foreach (var i in splitedDices) { - var dice = toDice(i); - if (dice.sides != 0 && dice.times != 0) + var dice = ToDice(i); + if (dice.Sides != 0 && dice.Times != 0) { dices.Add(dice); } - else if (dice.mod != 0) + else if (dice.Mod != 0) { if (mod != 0) { @@ -33,7 +33,7 @@ namespace Geekbot.net.Commands return; } - mod = dice.mod; + mod = dice.Mod; } } @@ -45,13 +45,13 @@ namespace Geekbot.net.Commands } - if (dices.Any(d => d.times > 20)) + if (dices.Any(d => d.Times > 20)) { await ReplyAsync("You can't throw more than 20 dices"); return; } - if (dices.Any(d => d.sides > 120)) + if (dices.Any(d => d.Sides > 120)) { await ReplyAsync("A dice can't have more than 120 sides"); return; @@ -66,16 +66,16 @@ namespace Geekbot.net.Commands foreach (var dice in dices) { var results = new List(); - for (var i = 0; i < dice.times; i++) + for (var i = 0; i < dice.Times; i++) { - var roll = new Random().Next(1, dice.sides); + var roll = new Random().Next(1, dice.Sides); total += roll; results.Add(roll); - if (roll == dice.sides) extraText = "**Critical Hit!**"; + if (roll == dice.Sides) extraText = "**Critical Hit!**"; if (roll == 1) extraText = "**Critical Fail!**"; } - resultStrings.Add($"{dice.diceType} ({string.Join(",", results)})"); + resultStrings.Add($"{dice.DiceType} ({string.Join(",", results)})"); } rep.Append(string.Join(" + ", resultStrings)); @@ -91,7 +91,7 @@ namespace Geekbot.net.Commands await ReplyAsync(rep.ToString()); } - private DiceTypeDto toDice(string dice) + private DiceTypeDto ToDice(string dice) { var diceParts = dice.Split('d'); if (diceParts.Length == 2 @@ -99,15 +99,15 @@ namespace Geekbot.net.Commands && int.TryParse(diceParts[1], out var max)) return new DiceTypeDto { - diceType = dice, - times = times, - sides = max + DiceType = dice, + Times = times, + Sides = max }; if (dice.Length == 1 && int.TryParse(diceParts[0], out var mod)) return new DiceTypeDto { - mod = mod + Mod = mod }; return new DiceTypeDto(); } @@ -115,9 +115,9 @@ namespace Geekbot.net.Commands internal class DiceTypeDto { - public string diceType { get; set; } - public int times { get; set; } - public int sides { get; set; } - public int mod { get; set; } + public string DiceType { get; set; } + public int Times { get; set; } + public int Sides { get; set; } + public int Mod { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Dog.cs b/Geekbot.net/Commands/Dog.cs index 485b7f0..30c0301 100644 --- a/Geekbot.net/Commands/Dog.cs +++ b/Geekbot.net/Commands/Dog.cs @@ -35,7 +35,7 @@ namespace Geekbot.net.Commands var stringResponse = await response.Content.ReadAsStringAsync(); var dogFile = JsonConvert.DeserializeObject(stringResponse); var eb = new EmbedBuilder(); - eb.ImageUrl = dogFile.url; + eb.ImageUrl = dogFile.Url; await ReplyAsync("", false, eb.Build()); } catch (HttpRequestException e) @@ -52,7 +52,7 @@ namespace Geekbot.net.Commands private class DogResponse { - public string url { get; set; } + public string Url { get; set; } } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Emojify.cs b/Geekbot.net/Commands/Emojify.cs index 7bdbf8a..739a4dc 100644 --- a/Geekbot.net/Commands/Emojify.cs +++ b/Geekbot.net/Commands/Emojify.cs @@ -23,7 +23,7 @@ namespace Geekbot.net.Commands { try { - var emojis = _emojiConverter.textToEmoji(text); + var emojis = _emojiConverter.TextToEmoji(text); if (emojis.Length > 1999) { await ReplyAsync("I can't take that much at once!"); diff --git a/Geekbot.net/Commands/Gdq.cs b/Geekbot.net/Commands/Gdq.cs index b191d6c..fef1c96 100644 --- a/Geekbot.net/Commands/Gdq.cs +++ b/Geekbot.net/Commands/Gdq.cs @@ -1,8 +1,6 @@ using System; -using System.Linq; using System.Net; using System.Threading.Tasks; -using Discord; using Discord.Commands; using Geekbot.net.Lib; @@ -20,7 +18,7 @@ namespace Geekbot.net.Commands [Command("gdq", RunMode = RunMode.Async)] [Remarks(CommandCategories.Games)] [Summary("Get a quote from the GDQ donation generator.")] - public async Task getQuote() + public async Task GetQuote() { try { diff --git a/Geekbot.net/Commands/Google.cs b/Geekbot.net/Commands/Google.cs index b10bc02..19d3efb 100644 --- a/Geekbot.net/Commands/Google.cs +++ b/Geekbot.net/Commands/Google.cs @@ -2,14 +2,12 @@ using System.Collections.Generic; using System.Linq; using System.Net; -using System.Net.Http; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Discord.Net; using Geekbot.net.Lib; -using Newtonsoft.Json; using StackExchange.Redis; +using Utf8Json; namespace Geekbot.net.Commands { @@ -27,7 +25,7 @@ namespace Geekbot.net.Commands [Command("google", RunMode = RunMode.Async)] [Remarks(CommandCategories.Helpers)] [Summary("Google Something.")] - public async Task askGoogle([Remainder, Summary("SearchText")] string searchText) + public async Task AskGoogle([Remainder, Summary("SearchText")] string searchText) { try { @@ -42,21 +40,21 @@ namespace Geekbot.net.Commands var url = new Uri($"https://kgsearch.googleapis.com/v1/entities:search?languages=en&limit=1&query={searchText}&key={apiKey}"); var responseString = client.DownloadString(url); - var response = Utf8Json.JsonSerializer.Deserialize(responseString); + var response = JsonSerializer.Deserialize(responseString); - if (!response.itemListElement.Any()) + if (!response.ItemListElement.Any()) { await ReplyAsync("No results were found..."); return; } - var data = response.itemListElement.First().result; + var data = response.ItemListElement.First().Result; var eb = new EmbedBuilder(); - eb.Title = data.name; - if(!string.IsNullOrEmpty(data.description)) eb.WithDescription(data.description); - if(!string.IsNullOrEmpty(data.detailedDescription?.url)) eb.WithUrl(data.detailedDescription.url); - if(!string.IsNullOrEmpty(data.detailedDescription?.articleBody)) eb.AddField("Details", data.detailedDescription.articleBody); - if(!string.IsNullOrEmpty(data.image?.contentUrl)) eb.WithThumbnailUrl(data.image.contentUrl); + eb.Title = data.Name; + if(!string.IsNullOrEmpty(data.Description)) eb.WithDescription(data.Description); + if(!string.IsNullOrEmpty(data.DetailedDescription?.Url)) eb.WithUrl(data.DetailedDescription.Url); + if(!string.IsNullOrEmpty(data.DetailedDescription?.ArticleBody)) eb.AddField("Details", data.DetailedDescription.ArticleBody); + if(!string.IsNullOrEmpty(data.Image?.ContentUrl)) eb.WithThumbnailUrl(data.Image.ContentUrl); await ReplyAsync("", false, eb.Build()); } @@ -67,35 +65,35 @@ namespace Geekbot.net.Commands } } - public class GoogleKGApiResponse + public class GoogleKgApiResponse { - public List itemListElement { get; set; } + public List ItemListElement { get; set; } - public class GoogleKGApiElement + public class GoogleKgApiElement { - public GoogleKGApiResult result { get; set; } - public double resultScore { get; set; } + public GoogleKgApiResult Result { get; set; } + public double ResultScore { get; set; } } - public class GoogleKGApiResult + public class GoogleKgApiResult { - public string name { get; set; } - public string description { get; set; } - public GoogleKGApiImage image { get; set; } - public GoogleKGApiDetailed detailedDescription { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public GoogleKgApiImage Image { get; set; } + public GoogleKgApiDetailed DetailedDescription { get; set; } } - public class GoogleKGApiImage + public class GoogleKgApiImage { - public string contentUrl { get; set; } - public string url { get; set; } + public string ContentUrl { get; set; } + public string Url { get; set; } } - public class GoogleKGApiDetailed + public class GoogleKgApiDetailed { - public string articleBody { get; set; } - public string url { get; set; } - public string license { get; set; } + public string ArticleBody { get; set; } + public string Url { get; set; } + public string License { get; set; } } } } diff --git a/Geekbot.net/Commands/GuildInfo.cs b/Geekbot.net/Commands/GuildInfo.cs index 2ca76c6..62e0fd1 100644 --- a/Geekbot.net/Commands/GuildInfo.cs +++ b/Geekbot.net/Commands/GuildInfo.cs @@ -24,7 +24,7 @@ namespace Geekbot.net.Commands [Command("serverstats", RunMode = RunMode.Async)] [Remarks(CommandCategories.Statistics)] [Summary("Show some info about the bot.")] - public async Task getInfo() + public async Task GetInfo() { try { diff --git a/Geekbot.net/Commands/Karma.cs b/Geekbot.net/Commands/Karma.cs index 1affa82..d379b06 100644 --- a/Geekbot.net/Commands/Karma.cs +++ b/Geekbot.net/Commands/Karma.cs @@ -110,9 +110,7 @@ namespace Geekbot.net.Commands private DateTimeOffset ConvertToDateTimeOffset(string dateTimeOffsetString) { - if (string.IsNullOrEmpty(dateTimeOffsetString)) - return DateTimeOffset.Now.Subtract(new TimeSpan(7, 18, 0, 0)); - return DateTimeOffset.Parse(dateTimeOffsetString); + return string.IsNullOrEmpty(dateTimeOffsetString) ? DateTimeOffset.Now.Subtract(new TimeSpan(7, 18, 0, 0)) : DateTimeOffset.Parse(dateTimeOffsetString); } private bool TimeoutFinished(DateTimeOffset lastKarma) diff --git a/Geekbot.net/Commands/MagicTheGathering.cs b/Geekbot.net/Commands/MagicTheGathering.cs index 044c287..9c7379f 100644 --- a/Geekbot.net/Commands/MagicTheGathering.cs +++ b/Geekbot.net/Commands/MagicTheGathering.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text.RegularExpressions; using System.Threading.Tasks; using Discord; using Discord.Commands; @@ -24,7 +23,7 @@ namespace Geekbot.net.Commands [Command("mtg", RunMode = RunMode.Async)] [Remarks(CommandCategories.Games)] [Summary("Find a Magic The Gathering Card.")] - public async Task getCard([Remainder] [Summary("name")] string cardName) + public async Task GetCard([Remainder] [Summary("name")] string cardName) { try { diff --git a/Geekbot.net/Commands/Mod.cs b/Geekbot.net/Commands/Mod.cs index c927b0d..e8751f6 100644 --- a/Geekbot.net/Commands/Mod.cs +++ b/Geekbot.net/Commands/Mod.cs @@ -32,7 +32,7 @@ namespace Geekbot.net.Commands [Command("namehistory", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("See past usernames of an user")] - public async Task usernameHistory([Summary("@user")] IUser user) + public async Task UsernameHistory([Summary("@user")] IUser user) { try { @@ -52,7 +52,7 @@ namespace Geekbot.net.Commands [Command("kick", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Ban a user")] - public async Task kick([Summary("@user")] IUser userNormal, + public async Task Kick([Summary("@user")] IUser userNormal, [Summary("reason")] [Remainder] string reason = "none") { try diff --git a/Geekbot.net/Commands/Overwatch.cs b/Geekbot.net/Commands/Overwatch.cs index fbb9699..0a39662 100644 --- a/Geekbot.net/Commands/Overwatch.cs +++ b/Geekbot.net/Commands/Overwatch.cs @@ -5,7 +5,6 @@ using Discord.Commands; using Geekbot.net.Lib; using OverwatchAPI; using OverwatchAPI.Config; -using Serilog; using StackExchange.Redis; namespace Geekbot.net.Commands @@ -16,7 +15,7 @@ namespace Geekbot.net.Commands private readonly IErrorHandler _errorHandler; private readonly IUserRepository _userRepository; - public Overwatch(IErrorHandler errorHandler, IDatabase redis, IUserRepository userRepository) + public Overwatch(IErrorHandler errorHandler, IUserRepository userRepository) { _errorHandler = errorHandler; _userRepository = userRepository; @@ -25,18 +24,18 @@ namespace Geekbot.net.Commands [Command("profile", RunMode = RunMode.Async)] [Summary("Get someones overwatch profile. EU on PC only. Default battletag is your own (if set).")] [Remarks(CommandCategories.Games)] - public async Task owProfile() + public async Task OwProfile() { try { - var tag = _userRepository.getUserSetting(Context.User.Id, "BattleTag"); + var tag = _userRepository.GetUserSetting(Context.User.Id, "BattleTag"); if (string.IsNullOrEmpty(tag)) { await ReplyAsync("You have no battle Tag saved, use `!battletag`"); return; } - var profile = await createProfile(tag); + var profile = await CreateProfile(tag); if (profile == null) { await ReplyAsync("That player doesn't seem to exist"); @@ -54,17 +53,17 @@ namespace Geekbot.net.Commands [Command("profile", RunMode = RunMode.Async)] [Summary("Get someones overwatch profile. EU on PC only. Default battletag is your own (if set).")] [Remarks(CommandCategories.Games)] - public async Task owProfile([Summary("BattleTag")] string tag) + public async Task OwProfile([Summary("BattleTag")] string tag) { try { - if (!BattleTag.isValidTag(tag)) + if (!BattleTag.IsValidTag(tag)) { await ReplyAsync("That doesn't seem to be a valid battletag..."); return; } - var profile = await createProfile(tag); + var profile = await CreateProfile(tag); if (profile == null) { await ReplyAsync("That player doesn't seem to exist"); @@ -82,18 +81,18 @@ namespace Geekbot.net.Commands [Command("profile", RunMode = RunMode.Async)] [Summary("Get someones overwatch profile. EU on PC only.")] [Remarks(CommandCategories.Games)] - public async Task owProfile([Summary("@someone")] IUser user) + public async Task OwProfile([Summary("@someone")] IUser user) { try { - var tag = _userRepository.getUserSetting(user.Id, "BattleTag"); + var tag = _userRepository.GetUserSetting(user.Id, "BattleTag"); if (string.IsNullOrEmpty(tag)) { await ReplyAsync("This user didn't set a battletag"); return; } - var profile = await createProfile(tag); + var profile = await CreateProfile(tag); if (profile == null) { await ReplyAsync("That player doesn't seem to exist"); @@ -108,7 +107,7 @@ namespace Geekbot.net.Commands } } - private async Task createProfile(string battletag) + private async Task CreateProfile(string battletag) { var owConfig = new OverwatchConfig.Builder().WithPlatforms(Platform.Pc); using (var owClient = new OverwatchClient(owConfig)) diff --git a/Geekbot.net/Commands/Owner.cs b/Geekbot.net/Commands/Owner.cs index c4adb25..b73797f 100644 --- a/Geekbot.net/Commands/Owner.cs +++ b/Geekbot.net/Commands/Owner.cs @@ -4,7 +4,6 @@ using Discord; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Lib; -using Serilog; using StackExchange.Redis; namespace Geekbot.net.Commands @@ -68,7 +67,7 @@ namespace Geekbot.net.Commands [Command("popuserrepo", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Populate user cache")] - public async Task popUserRepoCommand() + public async Task PopUserRepoCommand() { try { @@ -82,8 +81,7 @@ namespace Geekbot.net.Commands } catch (Exception) { - await ReplyAsync( - $"Sorry, only the botowner can do this"); + await ReplyAsync("Sorry, only the botowner can do this"); return; } diff --git a/Geekbot.net/Commands/Pokedex.cs b/Geekbot.net/Commands/Pokedex.cs index 2b43693..fa8746f 100644 --- a/Geekbot.net/Commands/Pokedex.cs +++ b/Geekbot.net/Commands/Pokedex.cs @@ -36,7 +36,7 @@ namespace Geekbot.net.Commands return; } - var embed = await pokemonEmbedBuilder(pokemon); + var embed = await PokemonEmbedBuilder(pokemon); await ReplyAsync("", false, embed.Build()); } catch (Exception e) @@ -45,29 +45,29 @@ namespace Geekbot.net.Commands } } - private async Task pokemonEmbedBuilder(Pokemon pokemon) + private async Task PokemonEmbedBuilder(Pokemon pokemon) { var eb = new EmbedBuilder(); var species = await DataFetcher.GetApiObject(pokemon.ID); - eb.Title = $"#{pokemon.ID} {toUpper(pokemon.Name)}"; + eb.Title = $"#{pokemon.ID} {ToUpper(pokemon.Name)}"; eb.Description = species.FlavorTexts[1].FlavorText; eb.ThumbnailUrl = pokemon.Sprites.FrontMale ?? pokemon.Sprites.FrontFemale; - eb.AddInlineField(getSingularOrPlural(pokemon.Types.Length, "Type"), - string.Join(", ", pokemon.Types.Select(t => toUpper(t.Type.Name)))); - eb.AddInlineField(getSingularOrPlural(pokemon.Abilities.Length, "Ability"), - string.Join(", ", pokemon.Abilities.Select(t => toUpper(t.Ability.Name)))); + eb.AddInlineField(GetSingularOrPlural(pokemon.Types.Length, "Type"), + string.Join(", ", pokemon.Types.Select(t => ToUpper(t.Type.Name)))); + eb.AddInlineField(GetSingularOrPlural(pokemon.Abilities.Length, "Ability"), + string.Join(", ", pokemon.Abilities.Select(t => ToUpper(t.Ability.Name)))); eb.AddInlineField("Height", pokemon.Height); eb.AddInlineField("Weight", pokemon.Mass); return eb; } - private string getSingularOrPlural(int lenght, string word) + private string GetSingularOrPlural(int lenght, string word) { if (lenght == 1) return word; return word.EndsWith("y") ? $"{word.Remove(word.Length - 1)}ies" : $"{word}s"; } - private string toUpper(string s) + private string ToUpper(string s) { if (string.IsNullOrEmpty(s)) return string.Empty; return char.ToUpper(s[0]) + s.Substring(1); diff --git a/Geekbot.net/Commands/Poll.cs b/Geekbot.net/Commands/Poll.cs index 51b6742..cf80835 100644 --- a/Geekbot.net/Commands/Poll.cs +++ b/Geekbot.net/Commands/Poll.cs @@ -82,14 +82,14 @@ namespace Geekbot.net.Commands var i = 1; pollList.ForEach(option => { - eb.AddInlineField($"Option {_emojiConverter.numberToEmoji(i)}", option); + eb.AddInlineField($"Option {_emojiConverter.NumberToEmoji(i)}", option); i++; }); var pollMessage = await ReplyAsync("", false, eb.Build()); i = 1; pollList.ForEach(option => { - pollMessage.AddReactionAsync(new Emoji(_emojiConverter.numberToEmoji(i))); + pollMessage.AddReactionAsync(new Emoji(_emojiConverter.NumberToEmoji(i))); i++; }); var poll = new PollData @@ -123,7 +123,7 @@ namespace Geekbot.net.Commands return; } - var results = await getPollResults(currentPoll); + var results = await GetPollResults(currentPoll); var sb = new StringBuilder(); sb.AppendLine("**Poll Results**"); sb.AppendLine(currentPoll.Question); @@ -152,7 +152,7 @@ namespace Geekbot.net.Commands } } - private async Task> getPollResults(PollData poll) + private async Task> GetPollResults(PollData poll) { var message = (IUserMessage) await Context.Channel.GetMessageAsync(poll.MessageId); var results = new List(); diff --git a/Geekbot.net/Commands/Quote.cs b/Geekbot.net/Commands/Quote.cs index fc4e2ce..4b4cfc3 100644 --- a/Geekbot.net/Commands/Quote.cs +++ b/Geekbot.net/Commands/Quote.cs @@ -24,7 +24,7 @@ namespace Geekbot.net.Commands [Command] [Remarks(CommandCategories.Quotes)] [Summary("Return a random quoute from the database")] - public async Task getRandomQuote() + public async Task GetRandomQuote() { try { @@ -32,7 +32,7 @@ namespace Geekbot.net.Commands var randomNumber = new Random().Next(randomQuotes.Length - 1); var randomQuote = randomQuotes[randomNumber]; var quote = JsonConvert.DeserializeObject(randomQuote); - var embed = quoteBuilder(quote, randomNumber + 1); + var embed = QuoteBuilder(quote, randomNumber + 1); await ReplyAsync("", false, embed.Build()); } catch (Exception e) @@ -44,7 +44,7 @@ namespace Geekbot.net.Commands [Command("save")] [Remarks(CommandCategories.Quotes)] [Summary("Save a quote from the last sent message by @user")] - public async Task saveQuote([Summary("@user")] IUser user) + public async Task SaveQuote([Summary("@user")] IUser user) { try { @@ -60,11 +60,11 @@ namespace Geekbot.net.Commands return; } - var lastMessage = await getLastMessageByUser(user); - var quote = createQuoteObject(lastMessage); + var lastMessage = await GetLastMessageByUser(user); + var quote = CreateQuoteObject(lastMessage); var quoteStore = JsonConvert.SerializeObject(quote); _redis.SetAdd($"{Context.Guild.Id}:Quotes", quoteStore); - var embed = quoteBuilder(quote); + var embed = QuoteBuilder(quote); await ReplyAsync("**Quote Added**", false, embed.Build()); } catch (Exception e) @@ -77,7 +77,7 @@ namespace Geekbot.net.Commands [Command("save")] [Remarks(CommandCategories.Quotes)] [Summary("Save a quote from a message id")] - public async Task saveQuote([Summary("messageId")] ulong messageId) + public async Task SaveQuote([Summary("messageId")] ulong messageId) { try { @@ -94,10 +94,10 @@ namespace Geekbot.net.Commands return; } - var quote = createQuoteObject(message); + var quote = CreateQuoteObject(message); var quoteStore = JsonConvert.SerializeObject(quote); _redis.SetAdd($"{Context.Guild.Id}:Quotes", quoteStore); - var embed = quoteBuilder(quote); + var embed = QuoteBuilder(quote); await ReplyAsync("**Quote Added**", false, embed.Build()); } catch (Exception e) @@ -110,13 +110,13 @@ namespace Geekbot.net.Commands [Command("make")] [Remarks(CommandCategories.Quotes)] [Summary("Create a quote from the last sent message by @user")] - public async Task returnSpecifiedQuote([Summary("@user")] IUser user) + public async Task ReturnSpecifiedQuote([Summary("@user")] IUser user) { try { - var lastMessage = await getLastMessageByUser(user); - var quote = createQuoteObject(lastMessage); - var embed = quoteBuilder(quote); + var lastMessage = await GetLastMessageByUser(user); + var quote = CreateQuoteObject(lastMessage); + var embed = QuoteBuilder(quote); await ReplyAsync("", false, embed.Build()); } catch (Exception e) @@ -129,13 +129,13 @@ namespace Geekbot.net.Commands [Command("make")] [Remarks(CommandCategories.Quotes)] [Summary("Create a quote from a message id")] - public async Task returnSpecifiedQuote([Summary("messageId")] ulong messageId) + public async Task ReturnSpecifiedQuote([Summary("messageId")] ulong messageId) { try { var message = await Context.Channel.GetMessageAsync(messageId); - var quote = createQuoteObject(message); - var embed = quoteBuilder(quote); + var quote = CreateQuoteObject(message); + var embed = QuoteBuilder(quote); await ReplyAsync("", false, embed.Build()); } catch (Exception e) @@ -151,7 +151,7 @@ namespace Geekbot.net.Commands [RequireUserPermission(GuildPermission.ManageRoles)] [Remarks(CommandCategories.Quotes)] [Summary("Remove a quote (required mod permissions)")] - public async Task removeQuote([Summary("quoteId")] int id) + public async Task RemoveQuote([Summary("quoteId")] int id) { try { @@ -160,12 +160,12 @@ namespace Geekbot.net.Commands if (success) { var quote = JsonConvert.DeserializeObject(quotes[id - 1]); - var embed = quoteBuilder(quote); + var embed = QuoteBuilder(quote); await ReplyAsync($"**Removed #{id}**", false, embed.Build()); } else { - await ReplyAsync($"I couldn't find a quote with that id :disappointed:"); + await ReplyAsync("I couldn't find a quote with that id :disappointed:"); } } catch (Exception e) @@ -175,7 +175,7 @@ namespace Geekbot.net.Commands } } - private async Task getLastMessageByUser(IUser user) + private async Task GetLastMessageByUser(IUser user) { var list = Context.Channel.GetMessagesAsync().Flatten(); await list; @@ -186,20 +186,20 @@ namespace Geekbot.net.Commands && !msg.Content.ToLower().StartsWith("!")); } - private EmbedBuilder quoteBuilder(QuoteObject quote, int id = 0) + private EmbedBuilder QuoteBuilder(QuoteObject quote, int id = 0) { - var user = Context.Client.GetUserAsync(quote.userId).Result; + var user = Context.Client.GetUserAsync(quote.UserId).Result; var eb = new EmbedBuilder(); eb.WithColor(new Color(143, 167, 232)); eb.Title = id == 0 ? "" : $"#{id} | "; - eb.Title += $"{user.Username} @ {quote.time.Day}.{quote.time.Month}.{quote.time.Year}"; - eb.Description = quote.quote; + eb.Title += $"{user.Username} @ {quote.Time.Day}.{quote.Time.Month}.{quote.Time.Year}"; + eb.Description = quote.Quote; eb.ThumbnailUrl = user.GetAvatarUrl(); - if (quote.image != null) eb.ImageUrl = quote.image; + if (quote.Image != null) eb.ImageUrl = quote.Image; return eb; } - private QuoteObject createQuoteObject(IMessage message) + private QuoteObject CreateQuoteObject(IMessage message) { string image; try @@ -213,19 +213,19 @@ namespace Geekbot.net.Commands return new QuoteObject { - userId = message.Author.Id, - time = message.Timestamp.DateTime, - quote = message.Content, - image = image + UserId = message.Author.Id, + Time = message.Timestamp.DateTime, + Quote = message.Content, + Image = image }; } } public class QuoteObject { - public ulong userId { get; set; } - public string quote { get; set; } - public DateTime time { get; set; } - public string image { get; set; } + public ulong UserId { get; set; } + public string Quote { get; set; } + public DateTime Time { get; set; } + public string Image { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/RandomAnimals.cs b/Geekbot.net/Commands/RandomAnimals.cs index f9dead9..2101c33 100644 --- a/Geekbot.net/Commands/RandomAnimals.cs +++ b/Geekbot.net/Commands/RandomAnimals.cs @@ -18,62 +18,62 @@ namespace Geekbot.net.Commands [Command("panda", RunMode = RunMode.Async)] [Remarks(CommandCategories.Randomness)] [Summary("Get a random panda image")] - public async Task panda() + public async Task Panda() { - await ReplyAsync("", false, eb(_mediaProvider.getPanda())); + await ReplyAsync("", false, Eb(_mediaProvider.GetPanda())); } [Command("croissant", RunMode = RunMode.Async)] [Alias("gipfeli")] [Remarks(CommandCategories.Randomness)] [Summary("Get a random croissant image")] - public async Task croissant() + public async Task Croissant() { - await ReplyAsync("", false, eb(_mediaProvider.getCrossant())); + await ReplyAsync("", false, Eb(_mediaProvider.GetCrossant())); } [Command("pumpkin", RunMode = RunMode.Async)] [Remarks(CommandCategories.Randomness)] [Summary("Get a random pumpkin image")] - public async Task pumpkin() + public async Task Pumpkin() { - await ReplyAsync("", false, eb(_mediaProvider.getPumpkin())); + await ReplyAsync("", false, Eb(_mediaProvider.GetPumpkin())); } [Command("squirrel", RunMode = RunMode.Async)] [Remarks(CommandCategories.Randomness)] [Summary("Get a random squirrel image")] - public async Task squirrel() + public async Task Squirrel() { - await ReplyAsync("", false, eb(_mediaProvider.getSquirrel())); + await ReplyAsync("", false, Eb(_mediaProvider.GetSquirrel())); } [Command("turtle", RunMode = RunMode.Async)] [Remarks(CommandCategories.Randomness)] [Summary("Get a random turtle image")] - public async Task turtle() + public async Task Turtle() { - await ReplyAsync("", false, eb(_mediaProvider.getTurtle())); + await ReplyAsync("", false, Eb(_mediaProvider.GetTurtle())); } [Command("pinguin", RunMode = RunMode.Async)] [Alias("pingu")] [Remarks(CommandCategories.Randomness)] [Summary("Get a random turtle image")] - public async Task pinguin() + public async Task Pinguin() { - await ReplyAsync("", false, eb(_mediaProvider.getPinguin())); + await ReplyAsync("", false, Eb(_mediaProvider.GetPinguin())); } [Command("fox", RunMode = RunMode.Async)] [Remarks(CommandCategories.Randomness)] [Summary("Get a random turtle image")] - public async Task fox() + public async Task Fox() { - await ReplyAsync("", false, eb(_mediaProvider.getFox())); + await ReplyAsync("", false, Eb(_mediaProvider.GetFox())); } - private EmbedBuilder eb(string image) + private EmbedBuilder Eb(string image) { var eb = new EmbedBuilder(); eb.ImageUrl = image; diff --git a/Geekbot.net/Commands/Rank.cs b/Geekbot.net/Commands/Rank.cs index 8c11171..92f78bd 100644 --- a/Geekbot.net/Commands/Rank.cs +++ b/Geekbot.net/Commands/Rank.cs @@ -6,7 +6,6 @@ using System.Threading.Tasks; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Lib; -using Serilog; using StackExchange.Redis; namespace Geekbot.net.Commands @@ -110,7 +109,7 @@ namespace Geekbot.net.Commands foreach (var user in highscoreUsers) { replyBuilder.Append(highscorePlace < 11 - ? $"{_emojiConverter.numberToEmoji(highscorePlace)} " + ? $"{_emojiConverter.NumberToEmoji(highscorePlace)} " : $"`{highscorePlace}.` "); replyBuilder.Append(user.Key.Username != null diff --git a/Geekbot.net/Commands/Role.cs b/Geekbot.net/Commands/Role.cs index 1de55ab..eb67bbf 100644 --- a/Geekbot.net/Commands/Role.cs +++ b/Geekbot.net/Commands/Role.cs @@ -27,7 +27,7 @@ namespace Geekbot.net.Commands [Command(RunMode = RunMode.Async)] [Remarks(CommandCategories.Helpers)] [Summary("Get a list of all available roles.")] - public async Task getAllRoles() + public async Task GetAllRoles() { try { @@ -53,7 +53,7 @@ namespace Geekbot.net.Commands [Command(RunMode = RunMode.Async)] [Remarks(CommandCategories.Helpers)] [Summary("Get a role by mentioning it.")] - public async Task giveRole([Summary("roleNickname")] string roleNameRaw) + public async Task GiveRole([Summary("roleNickname")] string roleNameRaw) { try { @@ -97,7 +97,7 @@ namespace Geekbot.net.Commands [Command("add", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Add a role to the whitelist.")] - public async Task addRole([Summary("@role")] IRole role, [Summary("alias")] string roleName) + public async Task AddRole([Summary("@role")] IRole role, [Summary("alias")] string roleName) { try { @@ -132,7 +132,7 @@ namespace Geekbot.net.Commands [Command("remove", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Remove a role from the whitelist.")] - public async Task removeRole([Summary("roleNickname")] string roleName) + public async Task RemoveRole([Summary("roleNickname")] string roleName) { try { @@ -166,7 +166,7 @@ namespace Geekbot.net.Commands if (!emoji.StartsWith('<')) { var emo = new Emoji(emoji); - emote = (IEmote) emo; + emote = emo; } else { diff --git a/Geekbot.net/Commands/Ship.cs b/Geekbot.net/Commands/Ship.cs index 4727bc8..d7dfd0e 100644 --- a/Geekbot.net/Commands/Ship.cs +++ b/Geekbot.net/Commands/Ship.cs @@ -64,9 +64,7 @@ namespace Geekbot.net.Commands return "There might be a chance"; if (rate >= 60 && rate < 80) return "Almost a match, but could work"; - if (rate >= 80) - return "It's a match"; - return "a"; + return rate >= 80 ? "It's a match" : "a"; } private string BlockCounter(int rate) diff --git a/Geekbot.net/Commands/Slap.cs b/Geekbot.net/Commands/Slap.cs index 09a6c15..668d33e 100644 --- a/Geekbot.net/Commands/Slap.cs +++ b/Geekbot.net/Commands/Slap.cs @@ -32,7 +32,7 @@ namespace Geekbot.net.Commands return; } - var things = new List() + var things = new List { "thing", "rubber chicken", diff --git a/Geekbot.net/Commands/UrbanDictionary.cs b/Geekbot.net/Commands/UrbanDictionary.cs index 573b289..a951cb8 100644 --- a/Geekbot.net/Commands/UrbanDictionary.cs +++ b/Geekbot.net/Commands/UrbanDictionary.cs @@ -22,7 +22,7 @@ namespace Geekbot.net.Commands [Command("urban", RunMode = RunMode.Async)] [Remarks(CommandCategories.Helpers)] [Summary("Lookup something on urban dictionary")] - public async Task urbanDefine([Remainder] [Summary("word")] string word) + public async Task UrbanDefine([Remainder] [Summary("word")] string word) { try { @@ -34,26 +34,26 @@ namespace Geekbot.net.Commands var stringResponse = await response.Content.ReadAsStringAsync(); var definitions = JsonConvert.DeserializeObject(stringResponse); - if (definitions.list.Count == 0) + if (definitions.List.Count == 0) { await ReplyAsync("That word hasn't been defined..."); return; } - var definition = definitions.list.First(e => !string.IsNullOrWhiteSpace(e.example)); + var definition = definitions.List.First(e => !string.IsNullOrWhiteSpace(e.Example)); var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder { - Name = definition.word, - Url = definition.permalink + Name = definition.Word, + Url = definition.Permalink }); eb.WithColor(new Color(239, 255, 0)); - eb.Description = definition.definition; - eb.AddField("Example", definition.example ?? "(no example given...)"); - eb.AddInlineField("Upvotes", definition.thumbs_up); - eb.AddInlineField("Downvotes", definition.thumbs_down); - if (definitions.tags.Length > 0) eb.AddField("Tags", string.Join(", ", definitions.tags)); + eb.Description = definition.Definition; + eb.AddField("Example", definition.Example ?? "(no example given...)"); + eb.AddInlineField("Upvotes", definition.ThumbsUp); + eb.AddInlineField("Downvotes", definition.ThumbsDown); + if (definitions.Tags.Length > 0) eb.AddField("Tags", string.Join(", ", definitions.Tags)); await ReplyAsync("", false, eb.Build()); } @@ -66,22 +66,18 @@ namespace Geekbot.net.Commands private class UrbanResponse { - public string[] tags { get; set; } - public string result_type { get; set; } - public List list { get; set; } + public string[] Tags { get; set; } + public List List { get; set; } } private class UrbanListItem { - public string definition { get; set; } - public string permalink { get; set; } - public string thumbs_up { get; set; } - public string author { get; set; } - public string word { get; set; } - public string defid { get; set; } - public string current_vote { get; set; } - public string example { get; set; } - public string thumbs_down { get; set; } + public string Definition { get; set; } + public string Permalink { get; set; } + public string ThumbsUp { get; set; } + public string Word { get; set; } + public string Example { get; set; } + public string ThumbsDown { get; set; } } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Wikipedia.cs b/Geekbot.net/Commands/Wikipedia.cs index 77fb41d..05b21a6 100644 --- a/Geekbot.net/Commands/Wikipedia.cs +++ b/Geekbot.net/Commands/Wikipedia.cs @@ -78,7 +78,7 @@ namespace Geekbot.net.Commands }; eb.AddField("Description", article.Extract); - if (article.Coordinates != null) eb.AddField("Coordinates", $"{article.Coordinates.lat} Lat {article.Coordinates.lon} Lon"); + if (article.Coordinates != null) eb.AddField("Coordinates", $"{article.Coordinates.Lat} Lat {article.Coordinates.Lon} Lon"); await ReplyAsync("", false, eb.Build()); } catch (HttpRequestException) diff --git a/Geekbot.net/Commands/mal.cs b/Geekbot.net/Commands/mal.cs index 22b3d4a..8c16936 100644 --- a/Geekbot.net/Commands/mal.cs +++ b/Geekbot.net/Commands/mal.cs @@ -7,12 +7,12 @@ using Geekbot.net.Lib; namespace Geekbot.net.Commands { - public class mal : ModuleBase + public class Mal : ModuleBase { private readonly IErrorHandler _errorHandler; private readonly IMalClient _malClient; - public mal(IMalClient malClient, IErrorHandler errorHandler) + public Mal(IMalClient malClient, IErrorHandler errorHandler) { _malClient = malClient; _errorHandler = errorHandler; @@ -21,13 +21,13 @@ namespace Geekbot.net.Commands [Command("anime", RunMode = RunMode.Async)] [Remarks(CommandCategories.Helpers)] [Summary("Show Info about an Anime.")] - public async Task searchAnime([Remainder] [Summary("AnimeName")] string animeName) + public async Task SearchAnime([Remainder] [Summary("AnimeName")] string animeName) { try { - if (_malClient.isLoggedIn()) + if (_malClient.IsLoggedIn()) { - var anime = await _malClient.getAnime(animeName); + var anime = await _malClient.GetAnime(animeName); if (anime != null) { var eb = new EmbedBuilder(); @@ -70,13 +70,13 @@ namespace Geekbot.net.Commands [Command("manga", RunMode = RunMode.Async)] [Remarks(CommandCategories.Helpers)] [Summary("Show Info about a Manga.")] - public async Task searchManga([Remainder] [Summary("MangaName")] string mangaName) + public async Task SearchManga([Remainder] [Summary("MangaName")] string mangaName) { try { - if (_malClient.isLoggedIn()) + if (_malClient.IsLoggedIn()) { - var manga = await _malClient.getManga(mangaName); + var manga = await _malClient.GetManga(mangaName); if (manga != null) { var eb = new EmbedBuilder(); diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index c1e0ee3..31608b2 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -1,12 +1,10 @@ using System; -using System.Collections; using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Lib; -using Serilog; using StackExchange.Redis; namespace Geekbot.net diff --git a/Geekbot.net/Lib/AudioClientCache.cs b/Geekbot.net/Lib/AudioClientCache.cs deleted file mode 100644 index d43b98a..0000000 --- a/Geekbot.net/Lib/AudioClientCache.cs +++ /dev/null @@ -1,106 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Net; -using System.Security.Cryptography; -using Discord.Audio; -using Discord.Net; - -namespace Geekbot.net.Lib -{ - public class AudioUtils : IAudioUtils - { - private string _tempFolderPath; - private Dictionary _audioClients; - - public AudioUtils() - { - _audioClients = new Dictionary(); - _tempFolderPath = Path.GetFullPath("./tmp/"); - if (Directory.Exists(_tempFolderPath)) - { - Directory.Delete(_tempFolderPath, true); - } - Directory.CreateDirectory(_tempFolderPath); - } - - public IAudioClient GetAudioClient(ulong guildId) - { - return _audioClients[guildId]; - } - - public void StoreAudioClient(ulong guildId, IAudioClient client) - { - _audioClients[guildId] = client; - } - - public Process CreateStreamFromFile(string path) - { - var ffmpeg = new ProcessStartInfo - { - FileName = "ffmpeg", - Arguments = $"-i {path} -ac 2 -f s16le -ar 48000 pipe:1", - UseShellExecute = false, - RedirectStandardOutput = true, - }; - return Process.Start(ffmpeg); - } - - public Process CreateStreamFromYoutube(string url, ulong guildId) - { - var ytdlMediaUrl = GetYoutubeMediaUrl(url); - DownloadMediaUrl(ytdlMediaUrl, guildId); - return CreateStreamFromFile($"{_tempFolderPath}{guildId}"); - } - - public void Cleanup(ulong guildId) - { - File.Delete($"{_tempFolderPath}{guildId}"); - } - - private string GetYoutubeMediaUrl(string url) - { - var ytdl = new ProcessStartInfo() - { - FileName = "youtube-dl", - Arguments = $"-f bestaudio -g {url}", - UseShellExecute = false, - RedirectStandardOutput = true - }; - var output = Process.Start(ytdl).StandardOutput.ReadToEnd(); - if (string.IsNullOrWhiteSpace(output)) - { - throw new Exception("Could not get Youtube Media URL"); - } - return output; - } - - private void DownloadMediaUrl(string url, ulong guildId) - { - using (var web = new WebClient()) - { - web.DownloadFile(url, $"{_tempFolderPath}{guildId}"); - } -// var ffmpeg = new ProcessStartInfo -// { -// FileName = "ffmpeg", -// Arguments = $"-i \"{_tempFolderPath}{guildId}\" -c:a mp3 -b:a 256k {_tempFolderPath}{guildId}.mp3", -// UseShellExecute = false, -// RedirectStandardOutput = true, -// }; -// Process.Start(ffmpeg).WaitForExit(); -// File.Delete($"{_tempFolderPath}{guildId}"); - return; - } - } - - public interface IAudioUtils - { - IAudioClient GetAudioClient(ulong guildId); - void StoreAudioClient(ulong guildId, IAudioClient client); - Process CreateStreamFromFile(string path); - Process CreateStreamFromYoutube(string url, ulong guildId); - void Cleanup(ulong guildId); - } -} \ No newline at end of file diff --git a/Geekbot.net/Lib/CommandCategories.cs b/Geekbot.net/Lib/CommandCategories.cs index ca7ea58..d67123b 100644 --- a/Geekbot.net/Lib/CommandCategories.cs +++ b/Geekbot.net/Lib/CommandCategories.cs @@ -1,6 +1,6 @@ namespace Geekbot.net.Lib { - public class CommandCategories + public static class CommandCategories { public const string Randomness = "Randomness"; public const string Karma = "Karma"; diff --git a/Geekbot.net/Lib/Constants.cs b/Geekbot.net/Lib/Constants.cs index db5c875..d754b5c 100644 --- a/Geekbot.net/Lib/Constants.cs +++ b/Geekbot.net/Lib/Constants.cs @@ -3,7 +3,7 @@ public class Constants { public const string Name = "Geekbot"; - public const double BotVersion = 3.5; + public const double BotVersion = 3.6; public const double ApiVersion = 1; } } \ No newline at end of file diff --git a/Geekbot.net/Lib/EmojiConverter.cs b/Geekbot.net/Lib/EmojiConverter.cs index 7091f0c..b836485 100644 --- a/Geekbot.net/Lib/EmojiConverter.cs +++ b/Geekbot.net/Lib/EmojiConverter.cs @@ -5,13 +5,13 @@ namespace Geekbot.net.Lib { public class EmojiConverter : IEmojiConverter { - public string numberToEmoji(int number) + public string NumberToEmoji(int number) { if (number == 10) { return "🔟"; } - var emojiMap = new string[] + var emojiMap = new[] { ":zero:", ":one:", @@ -22,7 +22,7 @@ namespace Geekbot.net.Lib ":six:", ":seven:", ":eight:", - ":nine:", + ":nine:" }; var numbers = number.ToString().ToCharArray(); var returnString = new StringBuilder(); @@ -33,7 +33,7 @@ namespace Geekbot.net.Lib return returnString.ToString(); } - public string textToEmoji(string text) + public string TextToEmoji(string text) { var emojiMap = new Hashtable { @@ -93,7 +93,7 @@ namespace Geekbot.net.Lib public interface IEmojiConverter { - string numberToEmoji(int number); - string textToEmoji(string text); + string NumberToEmoji(int number); + string TextToEmoji(string text); } } \ No newline at end of file diff --git a/Geekbot.net/Lib/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandler.cs index dc67db2..9bf99f4 100644 --- a/Geekbot.net/Lib/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandler.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Diagnostics; using System.Net; using Discord.Commands; using Discord.Net; @@ -34,12 +32,12 @@ namespace Geekbot.net.Lib } } - public void HandleCommandException(Exception e, ICommandContext Context, string errorMessage = "def") + public void HandleCommandException(Exception e, ICommandContext context, string errorMessage = "def") { try { - var errorString = errorMessage == "def" ? _translation.GetString(Context.Guild.Id, "errorHandler", "SomethingWentWrong") : errorMessage; - var errorObj = SimpleConextConverter.ConvertContext(Context); + var errorString = errorMessage == "def" ? _translation.GetString(context.Guild.Id, "errorHandler", "SomethingWentWrong") : errorMessage; + var errorObj = SimpleConextConverter.ConvertContext(context); if (e.Message.Contains("50007")) return; if (e.Message.Contains("50013")) return; _logger.Error("Geekbot", "An error ocured", e, errorObj); @@ -49,11 +47,11 @@ namespace Geekbot.net.Lib { var resStackTrace = string.IsNullOrEmpty(e.InnerException?.ToString()) ? e.StackTrace : e.InnerException.ToString(); var maxLen = Math.Min(resStackTrace.Length, 1850); - Context.Channel.SendMessageAsync($"{e.Message}\r\n```\r\n{resStackTrace?.Substring(0, maxLen)}\r\n```"); + context.Channel.SendMessageAsync($"{e.Message}\r\n```\r\n{resStackTrace.Substring(0, maxLen)}\r\n```"); } else { - Context.Channel.SendMessageAsync(errorString); + context.Channel.SendMessageAsync(errorString); } } @@ -74,18 +72,18 @@ namespace Geekbot.net.Lib } catch (Exception ex) { - Context.Channel.SendMessageAsync("Something went really really wrong here"); + context.Channel.SendMessageAsync("Something went really really wrong here"); _logger.Error("Geekbot", "Errorception", ex); } } - public async void HandleHttpException(HttpException e, ICommandContext Context) + public async void HandleHttpException(HttpException e, ICommandContext context) { - var errorStrings = _translation.GetDict(Context, "httpErrors"); + var errorStrings = _translation.GetDict(context, "httpErrors"); switch(e.HttpCode) { case HttpStatusCode.Forbidden: - await Context.Channel.SendMessageAsync(errorStrings["403"]); + await context.Channel.SendMessageAsync(errorStrings["403"]); break; } } @@ -95,7 +93,7 @@ namespace Geekbot.net.Lib public interface IErrorHandler { - void HandleCommandException(Exception e, ICommandContext Context, string errorMessage = "def"); - void HandleHttpException(HttpException e, ICommandContext Context); + void HandleCommandException(Exception e, ICommandContext context, string errorMessage = "def"); + void HandleHttpException(HttpException e, ICommandContext context); } } \ No newline at end of file diff --git a/Geekbot.net/Lib/GeekbotLogger.cs b/Geekbot.net/Lib/GeekbotLogger.cs index f2feda7..b5214b0 100644 --- a/Geekbot.net/Lib/GeekbotLogger.cs +++ b/Geekbot.net/Lib/GeekbotLogger.cs @@ -10,7 +10,7 @@ namespace Geekbot.net.Lib private readonly ILogger _serilog; public GeekbotLogger() { - _serilog = LoggerFactory.createLogger(); + _serilog = LoggerFactory.CreateLogger(); //JsonSerializer.SetDefaultResolver(StandardResolver.AllowPrivateExcludeNullSnakeCase); Information("Geekbot", "Using GeekbotLogger"); } @@ -45,7 +45,7 @@ namespace Geekbot.net.Lib private string CreateLogObject(string type, string source, string message, Exception stackTrace = null, object extra = null) { - var logObject = new GeekbotLoggerObject() + var logObject = new GeekbotLoggerObject { Timestamp = DateTime.Now, Type = type, diff --git a/Geekbot.net/Lib/LevelCalc.cs b/Geekbot.net/Lib/LevelCalc.cs index d075754..75df83d 100644 --- a/Geekbot.net/Lib/LevelCalc.cs +++ b/Geekbot.net/Lib/LevelCalc.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; namespace Geekbot.net.Lib { diff --git a/Geekbot.net/Lib/LoggerFactory.cs b/Geekbot.net/Lib/LoggerFactory.cs index 789bdc6..9bff873 100644 --- a/Geekbot.net/Lib/LoggerFactory.cs +++ b/Geekbot.net/Lib/LoggerFactory.cs @@ -1,13 +1,12 @@ using System; using Serilog; -using Serilog.Formatting.Json; using Serilog.Sinks.SumoLogic; namespace Geekbot.net.Lib { public class LoggerFactory { - public static ILogger createLogger() + public static ILogger CreateLogger() { var loggerCreation = new LoggerConfiguration(); var template = "{Message}{NewLine}"; diff --git a/Geekbot.net/Lib/MalClient.cs b/Geekbot.net/Lib/MalClient.cs index bc09036..dcf4fe3 100644 --- a/Geekbot.net/Lib/MalClient.cs +++ b/Geekbot.net/Lib/MalClient.cs @@ -2,7 +2,6 @@ using MyAnimeListSharp.Auth; using MyAnimeListSharp.Core; using MyAnimeListSharp.Facade.Async; -using Serilog; using StackExchange.Redis; namespace Geekbot.net.Lib @@ -19,10 +18,10 @@ namespace Geekbot.net.Lib { _redis = redis; _logger = logger; - reloadClient(); + ReloadClient(); } - public bool reloadClient() + public bool ReloadClient() { var malCredentials = _redis.HashGetAll("malCredentials"); if (malCredentials.Length != 0) @@ -50,18 +49,18 @@ namespace Geekbot.net.Lib } - public bool isLoggedIn() + public bool IsLoggedIn() { return _credentials != null; } - public async Task getAnime(string query) + public async Task GetAnime(string query) { var response = await _animeSearch.SearchDeserializedAsync(query); return response.Entries.Count == 0 ? null : response.Entries[0]; } - public async Task getManga(string query) + public async Task GetManga(string query) { var response = await _mangaSearch.SearchDeserializedAsync(query); return response.Entries.Count == 0 ? null : response.Entries[0]; @@ -70,9 +69,8 @@ namespace Geekbot.net.Lib public interface IMalClient { - bool reloadClient(); - bool isLoggedIn(); - Task getAnime(string query); - Task getManga(string query); + bool IsLoggedIn(); + Task GetAnime(string query); + Task GetManga(string query); } } \ No newline at end of file diff --git a/Geekbot.net/Lib/Media/FortunesProvider.cs b/Geekbot.net/Lib/Media/FortunesProvider.cs index 8a9b6f0..5988660 100644 --- a/Geekbot.net/Lib/Media/FortunesProvider.cs +++ b/Geekbot.net/Lib/Media/FortunesProvider.cs @@ -1,13 +1,12 @@ using System; using System.IO; -using Serilog; namespace Geekbot.net.Lib.Media { internal class FortunesProvider : IFortunesProvider { - private readonly string[] fortuneArray; - private readonly int totalFortunes; + private readonly string[] _fortuneArray; + private readonly int _totalFortunes; public FortunesProvider(IGeekbotLogger logger) { @@ -15,8 +14,8 @@ namespace Geekbot.net.Lib.Media if (File.Exists(path)) { var rawFortunes = File.ReadAllText(path); - fortuneArray = rawFortunes.Split("%"); - totalFortunes = fortuneArray.Length; + _fortuneArray = rawFortunes.Split("%"); + _totalFortunes = _fortuneArray.Length; logger.Debug("Geekbot", "Loaded {totalFortunes} Fortunes"); } else @@ -27,7 +26,7 @@ namespace Geekbot.net.Lib.Media public string GetRandomFortune() { - return fortuneArray[new Random().Next(0, totalFortunes)]; + return _fortuneArray[new Random().Next(0, _totalFortunes)]; } } diff --git a/Geekbot.net/Lib/Media/MediaProvider.cs b/Geekbot.net/Lib/Media/MediaProvider.cs index b8aeaa3..568f67d 100644 --- a/Geekbot.net/Lib/Media/MediaProvider.cs +++ b/Geekbot.net/Lib/Media/MediaProvider.cs @@ -1,8 +1,5 @@ using System; using System.IO; -using System.Runtime.CompilerServices; -using System.Threading.Tasks; -using Serilog; namespace Geekbot.net.Lib.Media { @@ -92,42 +89,42 @@ namespace Geekbot.net.Lib.Media _logger.Debug("Geekbot", $"Loaded {_foxImages.Length} Foxes Images"); } - public string getCheckem() + public string GetCheckem() { return _checkemImages[_random.Next(0, _checkemImages.Length)]; } - public string getPanda() + public string GetPanda() { return _pandaImages[_random.Next(0, _pandaImages.Length)]; } - public string getCrossant() + public string GetCrossant() { return _croissantImages[_random.Next(0, _croissantImages.Length)]; } - public string getSquirrel() + public string GetSquirrel() { return _squirrelImages[_random.Next(0, _squirrelImages.Length)]; } - public string getPumpkin() + public string GetPumpkin() { return _pumpkinImages[_random.Next(0, _pumpkinImages.Length)]; } - public string getTurtle() + public string GetTurtle() { return _turtlesImages[_random.Next(0, _turtlesImages.Length)]; } - public string getPinguin() + public string GetPinguin() { return _pinguinImages[_random.Next(0, _pinguinImages.Length)]; } - public string getFox() + public string GetFox() { return _foxImages[_random.Next(0, _foxImages.Length)]; } @@ -135,13 +132,13 @@ namespace Geekbot.net.Lib.Media public interface IMediaProvider { - string getCheckem(); - string getPanda(); - string getCrossant(); - string getSquirrel(); - string getPumpkin(); - string getTurtle(); - string getPinguin(); - string getFox(); + string GetCheckem(); + string GetPanda(); + string GetCrossant(); + string GetSquirrel(); + string GetPumpkin(); + string GetTurtle(); + string GetPinguin(); + string GetFox(); } } \ No newline at end of file diff --git a/Geekbot.net/Lib/MtgManaConverter.cs b/Geekbot.net/Lib/MtgManaConverter.cs index 098542e..83b6767 100644 --- a/Geekbot.net/Lib/MtgManaConverter.cs +++ b/Geekbot.net/Lib/MtgManaConverter.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; using System.Text.RegularExpressions; namespace Geekbot.net.Lib diff --git a/Geekbot.net/Lib/ReactionListener.cs b/Geekbot.net/Lib/ReactionListener.cs index f0e75a6..f837280 100644 --- a/Geekbot.net/Lib/ReactionListener.cs +++ b/Geekbot.net/Lib/ReactionListener.cs @@ -33,7 +33,7 @@ namespace Geekbot.net.Lib if (!r.Name.ToString().StartsWith('<')) { var emo = new Emoji(r.Name); - emote = (IEmote) emo; + emote = emo; } else { diff --git a/Geekbot.net/Lib/SimpleConextConverter.cs b/Geekbot.net/Lib/SimpleConextConverter.cs index 3dbc58b..ad029c7 100644 --- a/Geekbot.net/Lib/SimpleConextConverter.cs +++ b/Geekbot.net/Lib/SimpleConextConverter.cs @@ -1,5 +1,4 @@ -using System; -using Discord.Commands; +using Discord.Commands; using Discord.WebSocket; namespace Geekbot.net.Lib @@ -8,9 +7,9 @@ namespace Geekbot.net.Lib { public static MessageDto ConvertContext(ICommandContext context) { - return new MessageDto() + return new MessageDto { - Message = new MessageDto.MessageContent() + Message = new MessageDto.MessageContent { Content = context.Message.Content, Id = context.Message.Id.ToString(), @@ -19,17 +18,17 @@ namespace Geekbot.net.Lib UserMentions = context.Message.MentionedUserIds.Count, RoleMentions = context.Message.MentionedRoleIds.Count }, - User = new MessageDto.IdAndName() + User = new MessageDto.IdAndName { Id = context.User.Id.ToString(), Name = $"{context.User.Username}#{context.User.Discriminator}" }, - Guild = new MessageDto.IdAndName() + Guild = new MessageDto.IdAndName { Id = context.Guild.Id.ToString(), Name = context.Guild.Name }, - Channel = new MessageDto.IdAndName() + Channel = new MessageDto.IdAndName { Id = context.Channel.Id.ToString(), Name = context.Channel.Name @@ -39,9 +38,9 @@ namespace Geekbot.net.Lib public static MessageDto ConvertSocketMessage(SocketMessage message) { var channel = (SocketGuildChannel) message.Channel; - return new MessageDto() + return new MessageDto { - Message = new MessageDto.MessageContent() + Message = new MessageDto.MessageContent { Content = message.Content, Id = message.Id.ToString(), @@ -50,21 +49,21 @@ namespace Geekbot.net.Lib UserMentions = message.MentionedUsers.Count, RoleMentions = message.MentionedRoles.Count }, - User = new MessageDto.IdAndName() + User = new MessageDto.IdAndName { Id = message.Author.Id.ToString(), Name = $"{message.Author.Username}#{message.Author.Discriminator}" }, - Guild = new MessageDto.IdAndName() + Guild = new MessageDto.IdAndName { Id = channel.Guild.Id.ToString(), Name = channel.Guild.Name }, - Channel = new MessageDto.IdAndName() + Channel = new MessageDto.IdAndName { Id = channel.Id.ToString(), Name = channel.Name - }, + } }; } diff --git a/Geekbot.net/Lib/TranslationHandler.cs b/Geekbot.net/Lib/TranslationHandler.cs index cdacac8..5324496 100644 --- a/Geekbot.net/Lib/TranslationHandler.cs +++ b/Geekbot.net/Lib/TranslationHandler.cs @@ -4,8 +4,8 @@ using System.IO; using System.Linq; using Discord.Commands; using Discord.WebSocket; -using Serilog; using StackExchange.Redis; +using Utf8Json; namespace Geekbot.net.Lib { @@ -31,7 +31,7 @@ namespace Geekbot.net.Lib try { var translationFile = File.ReadAllText(Path.GetFullPath("./Storage/Translations.json")); - var rawTranslations = Utf8Json.JsonSerializer.Deserialize>>>(translationFile); + var rawTranslations = JsonSerializer.Deserialize>>>(translationFile); var sortedPerLanguage = new Dictionary>>(); foreach (var command in rawTranslations) { @@ -136,7 +136,7 @@ namespace Geekbot.net.Lib try { if (!_supportedLanguages.Contains(language)) return false; - _redis.HashSet($"{guildId}:Settings", new HashEntry[]{ new HashEntry("Language", language), }); + _redis.HashSet($"{guildId}:Settings", new[]{ new HashEntry("Language", language) }); _serverLanguages[guildId] = language; return true; } diff --git a/Geekbot.net/Lib/UserRepository.cs b/Geekbot.net/Lib/UserRepository.cs index b180ef9..28d0541 100644 --- a/Geekbot.net/Lib/UserRepository.cs +++ b/Geekbot.net/Lib/UserRepository.cs @@ -1,10 +1,7 @@ using System; using System.Collections.Generic; -using System.Globalization; -using System.Linq; using System.Threading.Tasks; using Discord.WebSocket; -using Serilog; using StackExchange.Redis; using Utf8Json; @@ -50,7 +47,7 @@ namespace Geekbot.net.Lib private void Store(UserRepositoryUser user) { - _redis.HashSetAsync($"Users:{user.Id.ToString()}", new HashEntry[] + _redis.HashSetAsync($"Users:{user.Id.ToString()}", new[] { new HashEntry("Id", user.Id.ToString()), new HashEntry("Username", user.Username), @@ -58,7 +55,7 @@ namespace Geekbot.net.Lib new HashEntry("AvatarUrl", user.AvatarUrl), new HashEntry("IsBot", user.IsBot), new HashEntry("Joined", user.Joined.ToString()), - new HashEntry("UsedNames", JsonSerializer.Serialize(user.UsedNames)), + new HashEntry("UsedNames", JsonSerializer.Serialize(user.UsedNames)) }); } @@ -67,7 +64,7 @@ namespace Geekbot.net.Lib try { var user = _redis.HashGetAll($"Users:{userId.ToString()}"); - for (int i = 1; i < 11; i++) + for (var i = 1; i < 11; i++) { if (user.Length != 0) break; user = _redis.HashGetAll($"Users:{(userId + (ulong) i).ToString()}"); @@ -88,7 +85,7 @@ namespace Geekbot.net.Lib dto.Discriminator = a.Value.ToString(); break; case "AvatarUrl": - dto.AvatarUrl = (a.Value != "0") ? a.Value.ToString() : null; + dto.AvatarUrl = a.Value != "0" ? a.Value.ToString() : null; break; case "IsBot": dto.IsBot = a.Value == 1; @@ -110,14 +107,14 @@ namespace Geekbot.net.Lib } } - public string getUserSetting(ulong userId, string setting) + public string GetUserSetting(ulong userId, string setting) { return _redis.HashGet($"Users:{userId}", setting); } - public bool saveUserSetting(ulong userId, string setting, string value) + public bool SaveUserSetting(ulong userId, string setting, string value) { - _redis.HashSet($"Users:{userId}", new HashEntry[] + _redis.HashSet($"Users:{userId}", new[] { new HashEntry(setting, value) }); @@ -140,7 +137,7 @@ namespace Geekbot.net.Lib { Task Update(SocketUser user); UserRepositoryUser Get(ulong userId); - string getUserSetting(ulong userId, string setting); - bool saveUserSetting(ulong userId, string setting, string value); + string GetUserSetting(ulong userId, string setting); + bool SaveUserSetting(ulong userId, string setting, string value); } } \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index b805e5f..0a107e9 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -18,16 +18,16 @@ namespace Geekbot.net { internal class Program { - private DiscordSocketClient client; - private CommandService commands; - private IDatabase redis; - private IServiceCollection services; - private IServiceProvider servicesProvider; - private RedisValue token; - private IGeekbotLogger logger; - private IUserRepository userRepository; - private string[] args; - private bool firstStart = false; + private DiscordSocketClient _client; + private CommandService _commands; + private IDatabase _redis; + private IServiceCollection _services; + private IServiceProvider _servicesProvider; + private RedisValue _token; + private IGeekbotLogger _logger; + private IUserRepository _userRepository; + private string[] _args; + private bool _firstStart; private static void Main(string[] args) { @@ -53,23 +53,23 @@ namespace Geekbot.net private async Task MainAsync(string[] args, IGeekbotLogger logger) { - this.logger = logger; - this.args = args; + _logger = logger; + _args = args; logger.Information("Geekbot", "Initing Stuff"); - client = new DiscordSocketClient(new DiscordSocketConfig + _client = new DiscordSocketClient(new DiscordSocketConfig { LogLevel = LogSeverity.Verbose, MessageCacheSize = 1000 }); - client.Log += DiscordLogger; - commands = new CommandService(); + _client.Log += DiscordLogger; + _commands = new CommandService(); try { var redisMultiplexer = ConnectionMultiplexer.Connect("127.0.0.1:6379"); - redis = redisMultiplexer.GetDatabase(6); - logger.Information("Redis", $"Connected to db {redis.Database}"); + _redis = redisMultiplexer.GetDatabase(6); + logger.Information("Redis", $"Connected to db {_redis.Database}"); } catch (Exception e) { @@ -77,40 +77,38 @@ namespace Geekbot.net Environment.Exit(102); } - token = redis.StringGet("discordToken"); - if (token.IsNullOrEmpty) + _token = _redis.StringGet("discordToken"); + if (_token.IsNullOrEmpty) { Console.Write("Your bot Token: "); var newToken = Console.ReadLine(); - redis.StringSet("discordToken", newToken); - redis.StringSet("Game", "Ping Pong"); - token = newToken; - firstStart = true; + _redis.StringSet("discordToken", newToken); + _redis.StringSet("Game", "Ping Pong"); + _token = newToken; + _firstStart = true; } - services = new ServiceCollection(); + _services = new ServiceCollection(); - userRepository = new UserRepository(redis, logger); + _userRepository = new UserRepository(_redis, logger); var fortunes = new FortunesProvider(logger); var mediaProvider = new MediaProvider(logger); - var malClient = new MalClient(redis, logger); + var malClient = new MalClient(_redis, logger); var levelCalc = new LevelCalc(); var emojiConverter = new EmojiConverter(); - var audioUtils = new AudioUtils(); var mtgManaConverter = new MtgManaConverter(); var wikipediaClient = new WikipediaClient(); - services.AddSingleton(redis); - services.AddSingleton(logger); - services.AddSingleton(userRepository); - services.AddSingleton(levelCalc); - services.AddSingleton(emojiConverter); - services.AddSingleton(audioUtils); - services.AddSingleton(fortunes); - services.AddSingleton(mediaProvider); - services.AddSingleton(malClient); - services.AddSingleton(mtgManaConverter); - services.AddSingleton(wikipediaClient); + _services.AddSingleton(_redis); + _services.AddSingleton(logger); + _services.AddSingleton(_userRepository); + _services.AddSingleton(levelCalc); + _services.AddSingleton(emojiConverter); + _services.AddSingleton(fortunes); + _services.AddSingleton(mediaProvider); + _services.AddSingleton(malClient); + _services.AddSingleton(mtgManaConverter); + _services.AddSingleton(wikipediaClient); logger.Information("Geekbot", "Connecting to Discord"); @@ -123,94 +121,94 @@ namespace Geekbot.net { try { - await client.LoginAsync(TokenType.Bot, token); - await client.StartAsync(); - var isConneted = await isConnected(); + await _client.LoginAsync(TokenType.Bot, _token); + await _client.StartAsync(); + var isConneted = await IsConnected(); if (isConneted) { - await client.SetGameAsync(redis.StringGet("Game")); - logger.Information("Geekbot", $"Now Connected as {client.CurrentUser.Username} to {client.Guilds.Count} Servers"); + await _client.SetGameAsync(_redis.StringGet("Game")); + _logger.Information("Geekbot", $"Now Connected as {_client.CurrentUser.Username} to {_client.Guilds.Count} Servers"); - logger.Information("Geekbot", "Registering Stuff"); - var translationHandler = new TranslationHandler(client.Guilds, redis, logger); - var errorHandler = new ErrorHandler(logger, translationHandler, args.Contains("--expose-errors")); - var reactionListener = new ReactionListener(redis); - await commands.AddModulesAsync(Assembly.GetEntryAssembly()); - services.AddSingleton(commands); - services.AddSingleton(errorHandler); - services.AddSingleton(translationHandler); - services.AddSingleton(client); - services.AddSingleton(reactionListener); - servicesProvider = services.BuildServiceProvider(); + _logger.Information("Geekbot", "Registering Stuff"); + var translationHandler = new TranslationHandler(_client.Guilds, _redis, _logger); + var errorHandler = new ErrorHandler(_logger, translationHandler, _args.Contains("--expose-errors")); + var reactionListener = new ReactionListener(_redis); + await _commands.AddModulesAsync(Assembly.GetEntryAssembly()); + _services.AddSingleton(_commands); + _services.AddSingleton(errorHandler); + _services.AddSingleton(translationHandler); + _services.AddSingleton(_client); + _services.AddSingleton(reactionListener); + _servicesProvider = _services.BuildServiceProvider(); - var handlers = new Handlers(client, logger, redis, servicesProvider, commands, userRepository, reactionListener); + var handlers = new Handlers(_client, _logger, _redis, _servicesProvider, _commands, _userRepository, reactionListener); - client.MessageReceived += handlers.RunCommand; - client.MessageReceived += handlers.UpdateStats; - client.MessageDeleted += handlers.MessageDeleted; - client.UserJoined += handlers.UserJoined; - client.UserUpdated += handlers.UserUpdated; - client.UserLeft += handlers.UserLeft; - client.ReactionAdded += handlers.ReactionAdded; - client.ReactionRemoved += handlers.ReactionRemoved; + _client.MessageReceived += handlers.RunCommand; + _client.MessageReceived += handlers.UpdateStats; + _client.MessageDeleted += handlers.MessageDeleted; + _client.UserJoined += handlers.UserJoined; + _client.UserUpdated += handlers.UserUpdated; + _client.UserLeft += handlers.UserLeft; + _client.ReactionAdded += handlers.ReactionAdded; + _client.ReactionRemoved += handlers.ReactionRemoved; - if (firstStart || args.Contains("--reset")) + if (_firstStart || _args.Contains("--reset")) { - logger.Information("Geekbot", "Finishing setup"); + _logger.Information("Geekbot", "Finishing setup"); await FinishSetup(); - logger.Information("Geekbot", "Setup finished"); + _logger.Information("Geekbot", "Setup finished"); } - if (!args.Contains("--disable-api")) + if (!_args.Contains("--disable-api")) { - startWebApi(); + StartWebApi(); } - logger.Information("Geekbot", "Done and ready for use"); + _logger.Information("Geekbot", "Done and ready for use"); } } catch (Exception e) { - logger.Error("Discord", "Could not connect...", e); + _logger.Error("Discord", "Could not connect...", e); Environment.Exit(103); } } - private async Task isConnected() + private async Task IsConnected() { - while (!client.ConnectionState.Equals(ConnectionState.Connected)) + while (!_client.ConnectionState.Equals(ConnectionState.Connected)) await Task.Delay(25); return true; } - private void startWebApi() + private void StartWebApi() { - logger.Information("API", "Starting Webserver"); + _logger.Information("API", "Starting Webserver"); var webApiUrl = new Uri("http://localhost:12995"); new NancyHost(webApiUrl).Start(); - logger.Information("API", $"Webserver now running on {webApiUrl}"); + _logger.Information("API", $"Webserver now running on {webApiUrl}"); } private async Task FinishSetup() { - var appInfo = await client.GetApplicationInfoAsync(); - logger.Information("Setup", $"Just a moment while i setup everything {appInfo.Owner.Username}"); + var appInfo = await _client.GetApplicationInfoAsync(); + _logger.Information("Setup", $"Just a moment while i setup everything {appInfo.Owner.Username}"); try { - redis.StringSet("botOwner", appInfo.Owner.Id); - var req = HttpWebRequest.Create(appInfo.IconUrl); + _redis.StringSet("botOwner", appInfo.Owner.Id); + var req = WebRequest.Create(appInfo.IconUrl); using (var stream = req.GetResponse().GetResponseStream()) { - await client.CurrentUser.ModifyAsync(User => + await _client.CurrentUser.ModifyAsync(user => { - User.Avatar = new Image(stream); - User.Username = appInfo.Name.ToString(); + user.Avatar = new Image(stream); + user.Username = appInfo.Name.ToString(); }); } - logger.Information("Setup", "Everything done, enjoy!"); + _logger.Information("Setup", "Everything done, enjoy!"); } catch (Exception e) { - logger.Warning("Setup", "Oha, it seems like something went wrong while running the setup, geekbot will work never the less though", e); + _logger.Warning("Setup", "Oha, it seems like something went wrong while running the setup, geekbot will work never the less though", e); } return Task.CompletedTask; } @@ -222,19 +220,19 @@ namespace Geekbot.net { case LogSeverity.Verbose: case LogSeverity.Debug: - logger.Debug(message.Source, message.Message); + _logger.Debug(message.Source, message.Message); break; case LogSeverity.Info: - logger.Information(message.Source, message.Message); + _logger.Information(message.Source, message.Message); break; case LogSeverity.Critical: case LogSeverity.Error: case LogSeverity.Warning: if (logMessage.Contains("VOICE_STATE_UPDATE")) break; - logger.Error(message.Source, message.Message, message.Exception); + _logger.Error(message.Source, message.Message, message.Exception); break; default: - logger.Information(message.Source, $"{logMessage} --- {message.Severity}"); + _logger.Information(message.Source, $"{logMessage} --- {message.Severity}"); break; } return Task.CompletedTask; diff --git a/Geekbot.net/WebApi/HelpController.cs b/Geekbot.net/WebApi/HelpController.cs index 6146352..060dea0 100644 --- a/Geekbot.net/WebApi/HelpController.cs +++ b/Geekbot.net/WebApi/HelpController.cs @@ -3,10 +3,9 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Threading.Tasks; -using Discord; using Discord.Commands; -using Nancy; using Geekbot.net.Lib; +using Nancy; namespace Geekbot.net.WebApi { @@ -16,25 +15,18 @@ namespace Geekbot.net.WebApi { Get("/v1/commands", args => { - var commands = getCommands().Result; + var commands = GetCommands().Result; - var commandList = new List(); - foreach (var cmd in commands.Commands) - { - var cmdParamsObj = new List(); - foreach (var cmdParam in cmd.Parameters) - { - var singleParamObj = new CommandParamDto() + var commandList = (from cmd in commands.Commands + let cmdParamsObj = cmd.Parameters.Select(cmdParam => new CommandParamDto { Summary = cmdParam.Summary, - Default = cmdParam?.DefaultValue?.ToString() ?? null, - Type = cmdParam?.Type?.ToString() - }; - cmdParamsObj.Add(singleParamObj); - } - - var param = string.Join(", !", cmd.Aliases); - var cmdObj = new CommandDto() + Default = cmdParam.DefaultValue?.ToString() ?? null, + Type = cmdParam.Type?.ToString() + }) + .ToList() + let param = string.Join(", !", cmd.Aliases) + select new CommandDto { Name = cmd.Name, Summary = cmd.Summary, @@ -42,15 +34,13 @@ namespace Geekbot.net.WebApi IsAdminCommand = (param.Contains("admin")), Aliases = cmd.Aliases.ToArray(), Params = cmdParamsObj - }; - commandList.Add(cmdObj); - } + }).ToList(); return Response.AsJson(commandList); }); } - private async Task getCommands() + private async Task GetCommands() { var commands = new CommandService(); await commands.AddModulesAsync(Assembly.GetEntryAssembly()); diff --git a/Geekbot.net/WebApi/StatusController.cs b/Geekbot.net/WebApi/StatusController.cs index 2fd84f8..b785e07 100644 --- a/Geekbot.net/WebApi/StatusController.cs +++ b/Geekbot.net/WebApi/StatusController.cs @@ -1,5 +1,5 @@ -using Nancy; -using Geekbot.net.Lib; +using Geekbot.net.Lib; +using Nancy; namespace Geekbot.net.WebApi { @@ -9,7 +9,7 @@ namespace Geekbot.net.WebApi { Get("/", args => { - var responseBody = new ApiStatusDto() + var responseBody = new ApiStatusDto { GeekbotVersion = Constants.BotVersion.ToString(), ApiVersion = Constants.ApiVersion.ToString(), diff --git a/Tests/Lib/EmojiConverter.test.cs b/Tests/Lib/EmojiConverter.test.cs index b9e7b4f..4bfcf06 100644 --- a/Tests/Lib/EmojiConverter.test.cs +++ b/Tests/Lib/EmojiConverter.test.cs @@ -1,11 +1,10 @@ using System.Collections.Generic; -using System.Threading.Tasks; using Geekbot.net.Lib; using Xunit; namespace Tests.Lib { - public class EmojiConverter_test + public class EmojiConverterTest { public static IEnumerable NumberToEmojiTestData { @@ -42,11 +41,11 @@ namespace Tests.Lib public void NumberToEmoji(int number, string expectedResult) { var emojiConverter = new EmojiConverter(); - var result = emojiConverter.numberToEmoji(number); + var result = emojiConverter.NumberToEmoji(number); Assert.Equal(result, expectedResult); } - public static IEnumerable textToEmojiTestData + public static IEnumerable TextToEmojiTestData { get { @@ -64,11 +63,11 @@ namespace Tests.Lib } - [Theory, MemberData(nameof(textToEmojiTestData))] + [Theory, MemberData(nameof(TextToEmojiTestData))] public void TextToEmoji(string text, string expectedResult) { var emojiConverter = new EmojiConverter(); - var result = emojiConverter.textToEmoji(text); + var result = emojiConverter.TextToEmoji(text); Assert.Equal(result, expectedResult); } } diff --git a/Tests/Lib/LevelCalc.test.cs b/Tests/Lib/LevelCalc.test.cs index 7c00392..ecca151 100644 --- a/Tests/Lib/LevelCalc.test.cs +++ b/Tests/Lib/LevelCalc.test.cs @@ -1,11 +1,10 @@ using System.Collections.Generic; -using System.Threading.Tasks; using Geekbot.net.Lib; using Xunit; namespace Tests.Lib { - public class LevelCalc_test + public class LevelCalcTest { public static IEnumerable LevelCalcTestData { diff --git a/WikipediaApi/Page/PageCoordinates.cs b/WikipediaApi/Page/PageCoordinates.cs index f86bb09..7fa42ba 100644 --- a/WikipediaApi/Page/PageCoordinates.cs +++ b/WikipediaApi/Page/PageCoordinates.cs @@ -2,7 +2,7 @@ { public class PageCoordinates { - public float lat { get; set; } - public float lon { get; set; } + public float Lat { get; set; } + public float Lon { get; set; } } } \ No newline at end of file diff --git a/WikipediaApi/Page/PagePreview.cs b/WikipediaApi/Page/PagePreview.cs index c1de2d7..8db9dad 100644 --- a/WikipediaApi/Page/PagePreview.cs +++ b/WikipediaApi/Page/PagePreview.cs @@ -1,5 +1,4 @@ using System; -using System.Runtime.Serialization; using Newtonsoft.Json; using Newtonsoft.Json.Converters; @@ -18,7 +17,7 @@ namespace WikipediaApi.Page public string Displaytitle { get; set; } [JsonProperty("namespace")] - public PageNamespace @Namespace { get; set; } + public PageNamespace Namespace { get; set; } [JsonProperty("titles")] public PageTitles Titles { get; set; } diff --git a/WikipediaApi/WikipediaClient.cs b/WikipediaApi/WikipediaClient.cs index 161cbce..6576f3d 100644 --- a/WikipediaApi/WikipediaClient.cs +++ b/WikipediaApi/WikipediaClient.cs @@ -1,5 +1,4 @@ -using System; -using System.Net.Http; +using System.Net.Http; using System.Threading.Tasks; using Newtonsoft.Json; using WikipediaApi.Page; From 276e9bfe8e19a6b5bb4adc4f48e0e2bfeba2bd29 Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 1 May 2018 00:19:03 +0200 Subject: [PATCH 142/553] add null checking in !urban --- Geekbot.net/Commands/UrbanDictionary.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Geekbot.net/Commands/UrbanDictionary.cs b/Geekbot.net/Commands/UrbanDictionary.cs index a951cb8..2af43ba 100644 --- a/Geekbot.net/Commands/UrbanDictionary.cs +++ b/Geekbot.net/Commands/UrbanDictionary.cs @@ -49,10 +49,10 @@ namespace Geekbot.net.Commands Url = definition.Permalink }); eb.WithColor(new Color(239, 255, 0)); - eb.Description = definition.Definition; - eb.AddField("Example", definition.Example ?? "(no example given...)"); - eb.AddInlineField("Upvotes", definition.ThumbsUp); - eb.AddInlineField("Downvotes", definition.ThumbsDown); + if (!string.IsNullOrEmpty(definition.Definition)) eb.Description = definition.Definition; + if (!string.IsNullOrEmpty(definition.Example)) eb.AddField("Example", definition.Example ?? "(no example given...)"); + if (!string.IsNullOrEmpty(definition.ThumbsUp)) eb.AddInlineField("Upvotes", definition.ThumbsUp); + if (!string.IsNullOrEmpty(definition.ThumbsDown)) eb.AddInlineField("Downvotes", definition.ThumbsDown); if (definitions.Tags.Length > 0) eb.AddField("Tags", string.Join(", ", definitions.Tags)); await ReplyAsync("", false, eb.Build()); From fa5797cd22b7c08766a062713f461e54a3637a73 Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 1 May 2018 02:31:54 +0200 Subject: [PATCH 143/553] use newtonsoft in logger --- Geekbot.net/Lib/GeekbotLogger.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Geekbot.net/Lib/GeekbotLogger.cs b/Geekbot.net/Lib/GeekbotLogger.cs index b5214b0..5ae65d6 100644 --- a/Geekbot.net/Lib/GeekbotLogger.cs +++ b/Geekbot.net/Lib/GeekbotLogger.cs @@ -1,7 +1,7 @@ using System; using System.Threading.Tasks; +using Newtonsoft.Json; using Serilog; -using Utf8Json; namespace Geekbot.net.Lib { @@ -11,7 +11,6 @@ namespace Geekbot.net.Lib public GeekbotLogger() { _serilog = LoggerFactory.CreateLogger(); - //JsonSerializer.SetDefaultResolver(StandardResolver.AllowPrivateExcludeNullSnakeCase); Information("Geekbot", "Using GeekbotLogger"); } @@ -54,7 +53,7 @@ namespace Geekbot.net.Lib StackTrace = stackTrace, Extra = extra }; - return JsonSerializer.ToJsonString(logObject); + return JsonConvert.SerializeObject(logObject); } } From f3156176dd1cc6bc1a95f0a19324e26bced11f77 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Tue, 1 May 2018 16:50:48 +0200 Subject: [PATCH 144/553] More explicit logging configuration --- Geekbot.net/Commands/RandomAnimals.cs | 4 ++-- Geekbot.net/Lib/GeekbotLogger.cs | 19 +++++++++++++------ Geekbot.net/Lib/LoggerFactory.cs | 4 ++-- Geekbot.net/Program.cs | 3 ++- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/Geekbot.net/Commands/RandomAnimals.cs b/Geekbot.net/Commands/RandomAnimals.cs index 2101c33..7829b21 100644 --- a/Geekbot.net/Commands/RandomAnimals.cs +++ b/Geekbot.net/Commands/RandomAnimals.cs @@ -59,7 +59,7 @@ namespace Geekbot.net.Commands [Command("pinguin", RunMode = RunMode.Async)] [Alias("pingu")] [Remarks(CommandCategories.Randomness)] - [Summary("Get a random turtle image")] + [Summary("Get a random pinguin image")] public async Task Pinguin() { await ReplyAsync("", false, Eb(_mediaProvider.GetPinguin())); @@ -67,7 +67,7 @@ namespace Geekbot.net.Commands [Command("fox", RunMode = RunMode.Async)] [Remarks(CommandCategories.Randomness)] - [Summary("Get a random turtle image")] + [Summary("Get a random fox image")] public async Task Fox() { await ReplyAsync("", false, Eb(_mediaProvider.GetFox())); diff --git a/Geekbot.net/Lib/GeekbotLogger.cs b/Geekbot.net/Lib/GeekbotLogger.cs index 5ae65d6..a9fb3a1 100644 --- a/Geekbot.net/Lib/GeekbotLogger.cs +++ b/Geekbot.net/Lib/GeekbotLogger.cs @@ -1,5 +1,4 @@ using System; -using System.Threading.Tasks; using Newtonsoft.Json; using Serilog; @@ -8,9 +7,18 @@ namespace Geekbot.net.Lib public class GeekbotLogger : IGeekbotLogger { private readonly ILogger _serilog; - public GeekbotLogger() + private readonly JsonSerializerSettings _serializerSettings; + private readonly Formatting _jsonFormatting; + + public GeekbotLogger(bool sumologicActive) { - _serilog = LoggerFactory.CreateLogger(); + _serilog = LoggerFactory.CreateLogger(sumologicActive); + _serializerSettings = new JsonSerializerSettings + { + ReferenceLoopHandling = ReferenceLoopHandling.Serialize, + NullValueHandling = NullValueHandling.Include + }; + _jsonFormatting = sumologicActive ? Formatting.None : Formatting.Indented; Information("Geekbot", "Using GeekbotLogger"); } @@ -34,12 +42,11 @@ namespace Geekbot.net.Lib HandleLogObject("Error", source, message, stackTrace, extra); } - private Task HandleLogObject(string type, string source, string message, Exception stackTrace = null, object extra = null) + private void HandleLogObject(string type, string source, string message, Exception stackTrace = null, object extra = null) { var logJson = CreateLogObject(type, source, message, stackTrace, extra); // fuck serilog _serilog.Information(logJson + "}"); - return Task.CompletedTask; } private string CreateLogObject(string type, string source, string message, Exception stackTrace = null, object extra = null) @@ -53,7 +60,7 @@ namespace Geekbot.net.Lib StackTrace = stackTrace, Extra = extra }; - return JsonConvert.SerializeObject(logObject); + return JsonConvert.SerializeObject(logObject, _jsonFormatting, _serializerSettings); } } diff --git a/Geekbot.net/Lib/LoggerFactory.cs b/Geekbot.net/Lib/LoggerFactory.cs index 9bff873..24df1ab 100644 --- a/Geekbot.net/Lib/LoggerFactory.cs +++ b/Geekbot.net/Lib/LoggerFactory.cs @@ -6,11 +6,11 @@ namespace Geekbot.net.Lib { public class LoggerFactory { - public static ILogger CreateLogger() + public static ILogger CreateLogger(bool sumologicActive) { var loggerCreation = new LoggerConfiguration(); var template = "{Message}{NewLine}"; - if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("GEEKBOT_SUMO"))) + if (sumologicActive) { Console.WriteLine("Logging Geekbot Logs to Sumologic"); loggerCreation.WriteTo.SumoLogic(Environment.GetEnvironmentVariable("GEEKBOT_SUMO"), diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 0a107e9..10f0dcb 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -39,7 +39,8 @@ namespace Geekbot.net logo.AppendLine(@" \____|_____|_____|_|\_\____/ \___/ |_|"); logo.AppendLine("========================================="); Console.WriteLine(logo.ToString()); - var logger = new GeekbotLogger(); + var sumologicActive = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("GEEKBOT_SUMO")); + var logger = new GeekbotLogger(sumologicActive); logger.Information("Geekbot", "Starting..."); try { From ec084a124bae82a0019baa9b0a882411ca0a9033 Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 1 May 2018 21:07:27 +0200 Subject: [PATCH 145/553] Only format as json when logging to sumologic --- Geekbot.net/Lib/GeekbotLogger.cs | 44 +++++++++++++++++++------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/Geekbot.net/Lib/GeekbotLogger.cs b/Geekbot.net/Lib/GeekbotLogger.cs index a9fb3a1..ec88290 100644 --- a/Geekbot.net/Lib/GeekbotLogger.cs +++ b/Geekbot.net/Lib/GeekbotLogger.cs @@ -6,61 +6,69 @@ namespace Geekbot.net.Lib { public class GeekbotLogger : IGeekbotLogger { + private readonly bool _sumologicActive; private readonly ILogger _serilog; private readonly JsonSerializerSettings _serializerSettings; - private readonly Formatting _jsonFormatting; public GeekbotLogger(bool sumologicActive) { + _sumologicActive = sumologicActive; _serilog = LoggerFactory.CreateLogger(sumologicActive); _serializerSettings = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Serialize, NullValueHandling = NullValueHandling.Include }; - _jsonFormatting = sumologicActive ? Formatting.None : Formatting.Indented; Information("Geekbot", "Using GeekbotLogger"); } public void Debug(string source, string message, object extra = null) { - HandleLogObject("Debug", source, message, null, extra); + _serilog.Debug(CreateLogString("Debug", source, message, null, extra)); } public void Information(string source, string message, object extra = null) { - HandleLogObject("Information", source, message, null, extra); + _serilog.Information(CreateLogString("Information", source, message, null, extra)); } public void Warning(string source, string message, Exception stackTrace = null, object extra = null) { - HandleLogObject("Warning", source, message, stackTrace, extra); + _serilog.Warning(CreateLogString("Warning", source, message, stackTrace, extra)); } public void Error(string source, string message, Exception stackTrace, object extra = null) { - HandleLogObject("Error", source, message, stackTrace, extra); + _serilog.Error(CreateLogString("Error", source, message, stackTrace, extra)); } private void HandleLogObject(string type, string source, string message, Exception stackTrace = null, object extra = null) { - var logJson = CreateLogObject(type, source, message, stackTrace, extra); + var logJson = CreateLogString(type, source, message, stackTrace, extra); // fuck serilog - _serilog.Information(logJson + "}"); + _serilog.Information(logJson, stackTrace + "}"); } - private string CreateLogObject(string type, string source, string message, Exception stackTrace = null, object extra = null) + private string CreateLogString(string type, string source, string message, Exception stackTrace = null, object extra = null) { - var logObject = new GeekbotLoggerObject + if (_sumologicActive) { - Timestamp = DateTime.Now, - Type = type, - Source = source, - Message = message, - StackTrace = stackTrace, - Extra = extra - }; - return JsonConvert.SerializeObject(logObject, _jsonFormatting, _serializerSettings); + var logObject = new GeekbotLoggerObject + { + Timestamp = DateTime.Now, + Type = type, + Source = source, + Message = message, + StackTrace = stackTrace, + Extra = extra + }; + return JsonConvert.SerializeObject(logObject, Formatting.None, _serializerSettings); + } + + if (source != "Message") return $"[{source}] - {message}"; + + var m = (MessageDto) extra; + return $"[{source}] - [{m.Guild.Name} - {m.Channel.Name}] {m.User.Name}: {m.Message.Content}"; } } From d3fcfc8a5c4735b419b5545bacc3416859803d61 Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 1 May 2018 22:55:47 +0200 Subject: [PATCH 146/553] Replace Serilog with NLog --- Geekbot.net/Geekbot.net.csproj | 8 ++-- Geekbot.net/Lib/GeekbotLogger.cs | 20 +++------- Geekbot.net/Lib/LoggerFactory.cs | 63 +++++++++++++++++++++++++++----- 3 files changed, 62 insertions(+), 29 deletions(-) diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index c91512f..d943a8e 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -24,17 +24,15 @@ + + - - - - - 1.2.6 + diff --git a/Geekbot.net/Lib/GeekbotLogger.cs b/Geekbot.net/Lib/GeekbotLogger.cs index ec88290..c4a792b 100644 --- a/Geekbot.net/Lib/GeekbotLogger.cs +++ b/Geekbot.net/Lib/GeekbotLogger.cs @@ -1,19 +1,18 @@ using System; using Newtonsoft.Json; -using Serilog; namespace Geekbot.net.Lib { public class GeekbotLogger : IGeekbotLogger { private readonly bool _sumologicActive; - private readonly ILogger _serilog; + private readonly NLog.Logger _logger; private readonly JsonSerializerSettings _serializerSettings; public GeekbotLogger(bool sumologicActive) { _sumologicActive = sumologicActive; - _serilog = LoggerFactory.CreateLogger(sumologicActive); + _logger = LoggerFactory.CreateNLog(sumologicActive); _serializerSettings = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Serialize, @@ -24,29 +23,22 @@ namespace Geekbot.net.Lib public void Debug(string source, string message, object extra = null) { - _serilog.Debug(CreateLogString("Debug", source, message, null, extra)); + _logger.Debug(CreateLogString("Debug", source, message, null, extra)); } public void Information(string source, string message, object extra = null) { - _serilog.Information(CreateLogString("Information", source, message, null, extra)); + _logger.Info(CreateLogString("Information", source, message, null, extra)); } public void Warning(string source, string message, Exception stackTrace = null, object extra = null) { - _serilog.Warning(CreateLogString("Warning", source, message, stackTrace, extra)); + _logger.Warn(CreateLogString("Warning", source, message, stackTrace, extra)); } public void Error(string source, string message, Exception stackTrace, object extra = null) { - _serilog.Error(CreateLogString("Error", source, message, stackTrace, extra)); - } - - private void HandleLogObject(string type, string source, string message, Exception stackTrace = null, object extra = null) - { - var logJson = CreateLogString(type, source, message, stackTrace, extra); - // fuck serilog - _serilog.Information(logJson, stackTrace + "}"); + _logger.Error(stackTrace, CreateLogString("Error", source, message, stackTrace, extra)); } private string CreateLogString(string type, string source, string message, Exception stackTrace = null, object extra = null) diff --git a/Geekbot.net/Lib/LoggerFactory.cs b/Geekbot.net/Lib/LoggerFactory.cs index 24df1ab..8631c11 100644 --- a/Geekbot.net/Lib/LoggerFactory.cs +++ b/Geekbot.net/Lib/LoggerFactory.cs @@ -1,27 +1,70 @@ using System; -using Serilog; -using Serilog.Sinks.SumoLogic; +using System.Text; +using NLog; +using NLog.Config; +using NLog.Targets; +using SumoLogic.Logging.NLog; namespace Geekbot.net.Lib { public class LoggerFactory { - public static ILogger CreateLogger(bool sumologicActive) + public static Logger CreateNLog(bool sumologicActive) { - var loggerCreation = new LoggerConfiguration(); - var template = "{Message}{NewLine}"; + var config = new LoggingConfiguration(); + if (sumologicActive) { Console.WriteLine("Logging Geekbot Logs to Sumologic"); - loggerCreation.WriteTo.SumoLogic(Environment.GetEnvironmentVariable("GEEKBOT_SUMO"), - outputTemplate: template); + config.LoggingRules.Add( + new LoggingRule("*", LogLevel.Info, LogLevel.Fatal, + new BufferedSumoLogicTarget() + { + Url = Environment.GetEnvironmentVariable("GEEKBOT_SUMO"), + SourceName = "GeekbotLogger", + Layout = "${message}", + UseConsoleLog = false, + MaxQueueSizeBytes = 500000, + FlushingAccuracy = 250, + MaxFlushInterval = 10000, + OptimizeBufferReuse = true, + MessagesPerRequest = 10, + RetryInterval = 5000, + Name = "Geekbot" + }) + ); } else { - loggerCreation.WriteTo.LiterateConsole(outputTemplate: template); - loggerCreation.WriteTo.RollingFile("Logs/geekbot-{Date}.txt", shared: true, outputTemplate: template); + config.LoggingRules.Add( + new LoggingRule("*", LogLevel.Trace, LogLevel.Fatal, + new ColoredConsoleTarget + { + Name = "Console", + Encoding = Encoding.Unicode, + Layout = "[${longdate} ${level:format=FirstCharacter}] ${message} ${exception:format=toString}" + }) + ); + + config.LoggingRules.Add( + new LoggingRule("*", LogLevel.Trace, LogLevel.Fatal, + new FileTarget + { + Name = "File", + Layout = "[${longdate} ${level}] ${message}", + Encoding = Encoding.Unicode, + LineEnding = LineEndingMode.Default, + MaxArchiveFiles = 30, + ArchiveNumbering = ArchiveNumberingMode.Date, + ArchiveEvery = FileArchivePeriod.Day, + ArchiveFileName = "./Logs/Archive/{#####}.log", + FileName = "./Logs/Geekbot.log" + }) + ); } - return loggerCreation.CreateLogger(); + + var loggerConfig = new LogFactory { Configuration = config }; + return loggerConfig.GetCurrentClassLogger(); } } } \ No newline at end of file From 2701f641cf253e0410cdb2f8f7011fc14344260c Mon Sep 17 00:00:00 2001 From: Runebaas Date: Wed, 2 May 2018 20:19:11 +0200 Subject: [PATCH 147/553] Add commandline parser --- Geekbot.net/Geekbot.net.csproj | 1 + Geekbot.net/Lib/GeekbotLogger.cs | 4 ++-- Geekbot.net/Lib/LoggerFactory.cs | 7 ++++--- Geekbot.net/Lib/RunParameters.cs | 23 +++++++++++++++++++++++ Geekbot.net/Program.cs | 22 ++++++++++++++-------- 5 files changed, 44 insertions(+), 13 deletions(-) create mode 100644 Geekbot.net/Lib/RunParameters.cs diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index d943a8e..cf7e5f9 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -11,6 +11,7 @@ NU1701 + 1.0.2 diff --git a/Geekbot.net/Lib/GeekbotLogger.cs b/Geekbot.net/Lib/GeekbotLogger.cs index c4a792b..aae0978 100644 --- a/Geekbot.net/Lib/GeekbotLogger.cs +++ b/Geekbot.net/Lib/GeekbotLogger.cs @@ -9,10 +9,10 @@ namespace Geekbot.net.Lib private readonly NLog.Logger _logger; private readonly JsonSerializerSettings _serializerSettings; - public GeekbotLogger(bool sumologicActive) + public GeekbotLogger(RunParameters runParameters, bool sumologicActive) { _sumologicActive = sumologicActive; - _logger = LoggerFactory.CreateNLog(sumologicActive); + _logger = LoggerFactory.CreateNLog(runParameters, sumologicActive); _serializerSettings = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Serialize, diff --git a/Geekbot.net/Lib/LoggerFactory.cs b/Geekbot.net/Lib/LoggerFactory.cs index 8631c11..b0b5060 100644 --- a/Geekbot.net/Lib/LoggerFactory.cs +++ b/Geekbot.net/Lib/LoggerFactory.cs @@ -9,7 +9,7 @@ namespace Geekbot.net.Lib { public class LoggerFactory { - public static Logger CreateNLog(bool sumologicActive) + public static Logger CreateNLog(RunParameters runParameters, bool sumologicActive) { var config = new LoggingConfiguration(); @@ -36,8 +36,9 @@ namespace Geekbot.net.Lib } else { + var minLevel = runParameters.Verbose ? LogLevel.Trace : LogLevel.Info; config.LoggingRules.Add( - new LoggingRule("*", LogLevel.Trace, LogLevel.Fatal, + new LoggingRule("*", minLevel, LogLevel.Fatal, new ColoredConsoleTarget { Name = "Console", @@ -47,7 +48,7 @@ namespace Geekbot.net.Lib ); config.LoggingRules.Add( - new LoggingRule("*", LogLevel.Trace, LogLevel.Fatal, + new LoggingRule("*", minLevel, LogLevel.Fatal, new FileTarget { Name = "File", diff --git a/Geekbot.net/Lib/RunParameters.cs b/Geekbot.net/Lib/RunParameters.cs new file mode 100644 index 0000000..0549ac5 --- /dev/null +++ b/Geekbot.net/Lib/RunParameters.cs @@ -0,0 +1,23 @@ +using System; +using CommandLine; + +namespace Geekbot.net.Lib +{ + public class RunParameters + { + [Option('V', "verbose", Default = false, HelpText = "Prints all messages to standard output.")] + public bool Verbose { get; set; } + + [Option('r', "reset", Default = false, HelpText = "Resets the bot")] + public bool Reset { get; set; } + + [Option('j', "log-json", Default = false, HelpText = "Logs messages as json")] + public bool LogJson { get; set; } + + [Option("disable-api", Default = false, HelpText = "Disables the web api")] + public bool DisableApi { get; set; } + + [Option('e', "expose-errors", Default = false, HelpText = "Shows internal errors in the chat")] + public bool ExposeErrors { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 10f0dcb..39e5e8b 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -4,6 +4,7 @@ using System.Net; using System.Reflection; using System.Text; using System.Threading.Tasks; +using CommandLine; using Discord; using Discord.Commands; using Discord.WebSocket; @@ -26,11 +27,16 @@ namespace Geekbot.net private RedisValue _token; private IGeekbotLogger _logger; private IUserRepository _userRepository; - private string[] _args; private bool _firstStart; + private RunParameters _runParameters; private static void Main(string[] args) { + RunParameters runParameters = null; + Parser.Default.ParseArguments(args) + .WithParsed(e => runParameters = e) + .WithNotParsed(_ => Environment.Exit(1)); + var logo = new StringBuilder(); logo.AppendLine(@" ____ _____ _____ _ ______ ___ _____"); logo.AppendLine(@" / ___| ____| ____| |/ / __ ) / _ \\_ _|"); @@ -40,11 +46,11 @@ namespace Geekbot.net logo.AppendLine("========================================="); Console.WriteLine(logo.ToString()); var sumologicActive = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("GEEKBOT_SUMO")); - var logger = new GeekbotLogger(sumologicActive); + var logger = new GeekbotLogger(runParameters, sumologicActive); logger.Information("Geekbot", "Starting..."); try { - new Program().MainAsync(args, logger).GetAwaiter().GetResult(); + new Program().MainAsync(runParameters, logger).GetAwaiter().GetResult(); } catch (Exception e) { @@ -52,10 +58,10 @@ namespace Geekbot.net } } - private async Task MainAsync(string[] args, IGeekbotLogger logger) + private async Task MainAsync(RunParameters runParameters, IGeekbotLogger logger) { _logger = logger; - _args = args; + _runParameters = runParameters; logger.Information("Geekbot", "Initing Stuff"); _client = new DiscordSocketClient(new DiscordSocketConfig @@ -132,7 +138,7 @@ namespace Geekbot.net _logger.Information("Geekbot", "Registering Stuff"); var translationHandler = new TranslationHandler(_client.Guilds, _redis, _logger); - var errorHandler = new ErrorHandler(_logger, translationHandler, _args.Contains("--expose-errors")); + var errorHandler = new ErrorHandler(_logger, translationHandler, _runParameters.ExposeErrors); var reactionListener = new ReactionListener(_redis); await _commands.AddModulesAsync(Assembly.GetEntryAssembly()); _services.AddSingleton(_commands); @@ -153,13 +159,13 @@ namespace Geekbot.net _client.ReactionAdded += handlers.ReactionAdded; _client.ReactionRemoved += handlers.ReactionRemoved; - if (_firstStart || _args.Contains("--reset")) + if (_firstStart || _runParameters.Reset) { _logger.Information("Geekbot", "Finishing setup"); await FinishSetup(); _logger.Information("Geekbot", "Setup finished"); } - if (!_args.Contains("--disable-api")) + if (!_runParameters.DisableApi) { StartWebApi(); } From 55e152f4aaae797519e3438419be9b56d7acbea0 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 2 May 2018 23:32:40 +0200 Subject: [PATCH 148/553] Update Readme and add token parameter --- Geekbot.net/Geekbot.net.csproj | 2 +- Geekbot.net/Lib/GeekbotLogger.cs | 6 +++--- Geekbot.net/Lib/RunParameters.cs | 3 +++ Geekbot.net/Program.cs | 3 +-- readme.md | 10 +--------- 5 files changed, 9 insertions(+), 15 deletions(-) diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index cf7e5f9..ba9faed 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -3,7 +3,7 @@ Exe netcoreapp2.0 derp.ico - 1.1.0 + 3.6.0 Pizza and Coffee Studios Pizza and Coffee Studios A Discord bot diff --git a/Geekbot.net/Lib/GeekbotLogger.cs b/Geekbot.net/Lib/GeekbotLogger.cs index aae0978..7093a7c 100644 --- a/Geekbot.net/Lib/GeekbotLogger.cs +++ b/Geekbot.net/Lib/GeekbotLogger.cs @@ -5,13 +5,13 @@ namespace Geekbot.net.Lib { public class GeekbotLogger : IGeekbotLogger { - private readonly bool _sumologicActive; + private readonly bool _logAsJson; private readonly NLog.Logger _logger; private readonly JsonSerializerSettings _serializerSettings; public GeekbotLogger(RunParameters runParameters, bool sumologicActive) { - _sumologicActive = sumologicActive; + _logAsJson = sumologicActive || runParameters.LogJson; _logger = LoggerFactory.CreateNLog(runParameters, sumologicActive); _serializerSettings = new JsonSerializerSettings { @@ -43,7 +43,7 @@ namespace Geekbot.net.Lib private string CreateLogString(string type, string source, string message, Exception stackTrace = null, object extra = null) { - if (_sumologicActive) + if (_logAsJson) { var logObject = new GeekbotLoggerObject { diff --git a/Geekbot.net/Lib/RunParameters.cs b/Geekbot.net/Lib/RunParameters.cs index 0549ac5..35c1a2a 100644 --- a/Geekbot.net/Lib/RunParameters.cs +++ b/Geekbot.net/Lib/RunParameters.cs @@ -19,5 +19,8 @@ namespace Geekbot.net.Lib [Option('e', "expose-errors", Default = false, HelpText = "Shows internal errors in the chat")] public bool ExposeErrors { get; set; } + + [Option("token", Default = null, HelpText = "Set a new bot token")] + public string Token { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 39e5e8b..3c0e5eb 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using System.Net; using System.Reflection; using System.Text; @@ -84,7 +83,7 @@ namespace Geekbot.net Environment.Exit(102); } - _token = _redis.StringGet("discordToken"); + _token = runParameters.Token ??_redis.StringGet("discordToken"); if (_token.IsNullOrEmpty) { Console.Write("Your bot Token: "); diff --git a/readme.md b/readme.md index be5ba0a..7d8544f 100644 --- a/readme.md +++ b/readme.md @@ -11,7 +11,6 @@ You can invite Geekbot to your server with [this link](https://discordapp.com/oa * DotNet Core 2 * Redis * Discord.net -* ffmpeg ## Running @@ -24,14 +23,7 @@ Run these commands On your first run geekbot will ask for your bot token, everything else is taken care of. -### Launch Parameters - -| Parameter | Description | -| --- | --- | -| `--verbose` | Show more log information | -| `--disable-api` | Disables the webapi on startup | -| `--reset` | Resets certain parts of the bot | -| `--migrate` | Migrates the database from V3.1 to the new format from V3.2
(make sure to backup before running this) | +For a list of launch options use `dotnet run -h` ## Contributing From e3adf557429effbe2cac6a6dd8af72e4878dabde Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 3 May 2018 00:56:06 +0200 Subject: [PATCH 149/553] Refaction all files into component based folders --- Geekbot.net/Commands/{ => Admin}/Admin.cs | 4 +- Geekbot.net/Commands/{ => Admin}/Mod.cs | 4 +- Geekbot.net/Commands/{ => Admin}/Owner.cs | 5 +- Geekbot.net/Commands/{ => Admin}/Role.cs | 4 +- Geekbot.net/Commands/{ => Admin}/Say.cs | 3 +- Geekbot.net/Commands/{ => Games}/BattleTag.cs | 4 +- Geekbot.net/Commands/{ => Games}/Overwatch.cs | 5 +- Geekbot.net/Commands/{ => Games}/Pokedex.cs | 3 +- Geekbot.net/Commands/{ => Games}/Roll.cs | 4 +- .../{ => Integrations/Google}/Google.cs | 46 +----- .../Google/GoogleKgApiDetailedDto.cs | 9 ++ .../Google/GoogleKgApiElementDto.cs | 8 + .../Google/GoogleKgApiImageDto.cs | 8 + .../Google/GoogleKgApiResponseDto.cs | 9 ++ .../Google/GoogleKgApiResultDto.cs | 10 ++ .../{ => Integrations}/MagicTheGathering.cs | 4 +- .../Commands/{mal.cs => Integrations/Mal.cs} | 4 +- .../UbranDictionary/UrbanDictListItemDto.cs | 12 ++ .../UbranDictionary/UrbanDictResponseDto.cs | 10 ++ .../UbranDictionary}/UrbanDictionary.cs | 22 +-- .../Commands/{ => Integrations}/Wikipedia.cs | 3 +- .../Commands/{ => Integrations}/Youtube.cs | 3 +- .../Commands/{ => Randomness/Cat}/Cat.cs | 110 +++++++------- .../Commands/Randomness/Cat/CatResponseDto.cs | 7 + .../Commands/{ => Randomness}/CheckEm.cs | 143 +++++++++--------- .../Chuck/ChuckNorrisJokeResponseDto.cs | 7 + .../Chuck}/ChuckNorrisJokes.cs | 10 +- .../Randomness/Dad/DadJokeResponseDto.cs | 7 + .../Commands/{ => Randomness/Dad}/DadJokes.cs | 10 +- .../Commands/{ => Randomness/Dog}/Dog.cs | 10 +- .../Commands/Randomness/Dog/DogResponseDto.cs | 7 + .../Commands/{ => Randomness}/EightBall.cs | 3 +- .../Commands/{ => Randomness}/Fortune.cs | 2 +- Geekbot.net/Commands/{ => Randomness}/Gdq.cs | 3 +- .../{ => Randomness}/RandomAnimals.cs | 2 +- Geekbot.net/Commands/{ => Randomness}/Ship.cs | 3 +- Geekbot.net/Commands/{ => Randomness}/Slap.cs | 3 +- Geekbot.net/Commands/{ => User}/GuildInfo.cs | 11 +- Geekbot.net/Commands/{ => User}/Karma.cs | 4 +- Geekbot.net/Commands/{ => User/Rank}/Rank.cs | 19 +-- .../Commands/User/Rank/RankUserPolyfillDto.cs | 9 ++ Geekbot.net/Commands/{ => User}/Stats.cs | 4 +- .../Commands/{ => Utils}/AvatarGetter.cs | 3 +- .../{ => Utils/Changelog}/Changelog.cs | 21 +-- .../Utils/Changelog/CommitAuthorDto.cs | 9 ++ .../Commands/Utils/Changelog/CommitDto.cs | 7 + .../Commands/Utils/Changelog/CommitInfoDto.cs | 8 + Geekbot.net/Commands/{ => Utils}/Choose.cs | 4 +- Geekbot.net/Commands/{ => Utils/Dice}/Dice.cs | 10 +- .../Commands/Utils/Dice/DiceTypeDto.cs | 10 ++ Geekbot.net/Commands/{ => Utils}/Emojify.cs | 4 +- Geekbot.net/Commands/{ => Utils}/Help.cs | 3 +- Geekbot.net/Commands/{ => Utils}/Info.cs | 3 +- Geekbot.net/Commands/{ => Utils}/Ping.cs | 2 +- Geekbot.net/Commands/{ => Utils/Poll}/Poll.cs | 34 ++--- .../Commands/Utils/Poll/PollDataDto.cs | 13 ++ .../Commands/Utils/Poll/PollResultDto.cs | 8 + .../Commands/{ => Utils/Quote}/Quote.cs | 21 +-- .../Commands/Utils/Quote/QuoteObjectDto.cs | 12 ++ Geekbot.net/Commands/Voice.cs | 102 ------------- Geekbot.net/Geekbot.net.csproj | 9 +- Geekbot.net/Handlers.cs | 5 +- Geekbot.net/Lib/Clients/IMalClient.cs | 12 ++ Geekbot.net/Lib/{ => Clients}/MalClient.cs | 10 +- .../Lib/{ => Converters}/EmojiConverter.cs | 8 +- Geekbot.net/Lib/Converters/IEmojiConverter.cs | 8 + .../Lib/Converters/IMtgManaConverter.cs | 7 + .../Lib/Converters/MtgManaConverter.cs | 33 ++++ Geekbot.net/Lib/Converters/MtgManaEmojis.json | 50 ++++++ .../Lib/{ => ErrorHandling}/ErrorHandler.cs | 10 +- .../Lib/ErrorHandling/IErrorHandler.cs | 12 ++ Geekbot.net/Lib/Levels/ILevelCalc.cs | 7 + Geekbot.net/Lib/{ => Levels}/LevelCalc.cs | 7 +- .../Lib/Localization/ITranslationHandler.cs | 14 ++ .../{ => Localization}/TranslationHandler.cs | 14 +- .../Localization}/Translations.json | 0 Geekbot.net/Lib/Logger/DiscordLogger.cs | 42 +++++ Geekbot.net/Lib/{ => Logger}/GeekbotLogger.cs | 25 +-- Geekbot.net/Lib/Logger/IDiscordLogger.cs | 10 ++ Geekbot.net/Lib/Logger/IGeekbotLogger.cs | 13 ++ Geekbot.net/Lib/Logger/LogDto.cs | 14 ++ Geekbot.net/Lib/{ => Logger}/LoggerFactory.cs | 4 +- Geekbot.net/Lib/Logger/MessageDto.cs | 26 ++++ .../Lib/{ => Logger}/SimpleConextConverter.cs | 27 +--- Geekbot.net/Lib/Media/FortunesProvider.cs | 8 +- Geekbot.net/Lib/Media/IFortunesProvider.cs | 7 + Geekbot.net/Lib/Media/IMediaProvider.cs | 14 ++ Geekbot.net/Lib/Media/MediaProvider.cs | 29 ++-- Geekbot.net/Lib/MtgManaConverter.cs | 86 ----------- .../Lib/ReactionListener/IReactionListener.cs | 14 ++ .../ReactionListener.cs | 10 +- .../Lib/UserRepository/IUserRepository.cs | 13 ++ .../{ => UserRepository}/UserRepository.cs | 22 +-- .../UserRepository/UserRepositoryUserDto.cs | 16 ++ Geekbot.net/Program.cs | 40 ++--- Geekbot.net/WebApi/Help/CommandDto.cs | 15 ++ Geekbot.net/WebApi/Help/CommandParamDto.cs | 9 ++ .../WebApi/{ => Help}/HelpController.cs | 23 +-- Geekbot.net/WebApi/Status/ApiStatusDto.cs | 9 ++ .../WebApi/{ => Status}/StatusController.cs | 9 +- Tests/Lib/EmojiConverter.test.cs | 1 + Tests/Lib/LevelCalc.test.cs | 1 + 102 files changed, 816 insertions(+), 709 deletions(-) rename Geekbot.net/Commands/{ => Admin}/Admin.cs (96%) rename Geekbot.net/Commands/{ => Admin}/Mod.cs (94%) rename Geekbot.net/Commands/{ => Admin}/Owner.cs (94%) rename Geekbot.net/Commands/{ => Admin}/Role.cs (98%) rename Geekbot.net/Commands/{ => Admin}/Say.cs (92%) rename Geekbot.net/Commands/{ => Games}/BattleTag.cs (92%) rename Geekbot.net/Commands/{ => Games}/Overwatch.cs (94%) rename Geekbot.net/Commands/{ => Games}/Pokedex.cs (94%) rename Geekbot.net/Commands/{ => Games}/Roll.cs (95%) rename Geekbot.net/Commands/{ => Integrations/Google}/Google.cs (56%) create mode 100644 Geekbot.net/Commands/Integrations/Google/GoogleKgApiDetailedDto.cs create mode 100644 Geekbot.net/Commands/Integrations/Google/GoogleKgApiElementDto.cs create mode 100644 Geekbot.net/Commands/Integrations/Google/GoogleKgApiImageDto.cs create mode 100644 Geekbot.net/Commands/Integrations/Google/GoogleKgApiResponseDto.cs create mode 100644 Geekbot.net/Commands/Integrations/Google/GoogleKgApiResultDto.cs rename Geekbot.net/Commands/{ => Integrations}/MagicTheGathering.cs (94%) rename Geekbot.net/Commands/{mal.cs => Integrations/Mal.cs} (95%) create mode 100644 Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictListItemDto.cs create mode 100644 Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictResponseDto.cs rename Geekbot.net/Commands/{ => Integrations/UbranDictionary}/UrbanDictionary.cs (78%) rename Geekbot.net/Commands/{ => Integrations}/Wikipedia.cs (95%) rename Geekbot.net/Commands/{ => Integrations}/Youtube.cs (92%) rename Geekbot.net/Commands/{ => Randomness/Cat}/Cat.cs (90%) create mode 100644 Geekbot.net/Commands/Randomness/Cat/CatResponseDto.cs rename Geekbot.net/Commands/{ => Randomness}/CheckEm.cs (93%) create mode 100644 Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokeResponseDto.cs rename Geekbot.net/Commands/{ => Randomness/Chuck}/ChuckNorrisJokes.cs (87%) create mode 100644 Geekbot.net/Commands/Randomness/Dad/DadJokeResponseDto.cs rename Geekbot.net/Commands/{ => Randomness/Dad}/DadJokes.cs (87%) rename Geekbot.net/Commands/{ => Randomness/Dog}/Dog.cs (88%) create mode 100644 Geekbot.net/Commands/Randomness/Dog/DogResponseDto.cs rename Geekbot.net/Commands/{ => Randomness}/EightBall.cs (95%) rename Geekbot.net/Commands/{ => Randomness}/Fortune.cs (89%) rename Geekbot.net/Commands/{ => Randomness}/Gdq.cs (89%) rename Geekbot.net/Commands/{ => Randomness}/RandomAnimals.cs (98%) rename Geekbot.net/Commands/{ => Randomness}/Ship.cs (94%) rename Geekbot.net/Commands/{ => Randomness}/Slap.cs (94%) rename Geekbot.net/Commands/{ => User}/GuildInfo.cs (83%) rename Geekbot.net/Commands/{ => User}/Karma.cs (97%) rename Geekbot.net/Commands/{ => User/Rank}/Rank.cs (93%) create mode 100644 Geekbot.net/Commands/User/Rank/RankUserPolyfillDto.cs rename Geekbot.net/Commands/{ => User}/Stats.cs (96%) rename Geekbot.net/Commands/{ => Utils}/AvatarGetter.cs (89%) rename Geekbot.net/Commands/{ => Utils/Changelog}/Changelog.cs (82%) create mode 100644 Geekbot.net/Commands/Utils/Changelog/CommitAuthorDto.cs create mode 100644 Geekbot.net/Commands/Utils/Changelog/CommitDto.cs create mode 100644 Geekbot.net/Commands/Utils/Changelog/CommitInfoDto.cs rename Geekbot.net/Commands/{ => Utils}/Choose.cs (88%) rename Geekbot.net/Commands/{ => Utils/Dice}/Dice.cs (93%) create mode 100644 Geekbot.net/Commands/Utils/Dice/DiceTypeDto.cs rename Geekbot.net/Commands/{ => Utils}/Emojify.cs (89%) rename Geekbot.net/Commands/{ => Utils}/Help.cs (93%) rename Geekbot.net/Commands/{ => Utils}/Info.cs (94%) rename Geekbot.net/Commands/{ => Utils}/Ping.cs (91%) rename Geekbot.net/Commands/{ => Utils/Poll}/Poll.cs (85%) create mode 100644 Geekbot.net/Commands/Utils/Poll/PollDataDto.cs create mode 100644 Geekbot.net/Commands/Utils/Poll/PollResultDto.cs rename Geekbot.net/Commands/{ => Utils/Quote}/Quote.cs (94%) create mode 100644 Geekbot.net/Commands/Utils/Quote/QuoteObjectDto.cs delete mode 100644 Geekbot.net/Commands/Voice.cs create mode 100644 Geekbot.net/Lib/Clients/IMalClient.cs rename Geekbot.net/Lib/{ => Clients}/MalClient.cs (89%) rename Geekbot.net/Lib/{ => Converters}/EmojiConverter.cs (92%) create mode 100644 Geekbot.net/Lib/Converters/IEmojiConverter.cs create mode 100644 Geekbot.net/Lib/Converters/IMtgManaConverter.cs create mode 100644 Geekbot.net/Lib/Converters/MtgManaConverter.cs create mode 100644 Geekbot.net/Lib/Converters/MtgManaEmojis.json rename Geekbot.net/Lib/{ => ErrorHandling}/ErrorHandler.cs (93%) create mode 100644 Geekbot.net/Lib/ErrorHandling/IErrorHandler.cs create mode 100644 Geekbot.net/Lib/Levels/ILevelCalc.cs rename Geekbot.net/Lib/{ => Levels}/LevelCalc.cs (87%) create mode 100644 Geekbot.net/Lib/Localization/ITranslationHandler.cs rename Geekbot.net/Lib/{ => Localization}/TranslationHandler.cs (90%) rename Geekbot.net/{Storage => Lib/Localization}/Translations.json (100%) create mode 100644 Geekbot.net/Lib/Logger/DiscordLogger.cs rename Geekbot.net/Lib/{ => Logger}/GeekbotLogger.cs (75%) create mode 100644 Geekbot.net/Lib/Logger/IDiscordLogger.cs create mode 100644 Geekbot.net/Lib/Logger/IGeekbotLogger.cs create mode 100644 Geekbot.net/Lib/Logger/LogDto.cs rename Geekbot.net/Lib/{ => Logger}/LoggerFactory.cs (95%) create mode 100644 Geekbot.net/Lib/Logger/MessageDto.cs rename Geekbot.net/Lib/{ => Logger}/SimpleConextConverter.cs (75%) create mode 100644 Geekbot.net/Lib/Media/IFortunesProvider.cs create mode 100644 Geekbot.net/Lib/Media/IMediaProvider.cs delete mode 100644 Geekbot.net/Lib/MtgManaConverter.cs create mode 100644 Geekbot.net/Lib/ReactionListener/IReactionListener.cs rename Geekbot.net/Lib/{ => ReactionListener}/ReactionListener.cs (87%) create mode 100644 Geekbot.net/Lib/UserRepository/IUserRepository.cs rename Geekbot.net/Lib/{ => UserRepository}/UserRepository.cs (84%) create mode 100644 Geekbot.net/Lib/UserRepository/UserRepositoryUserDto.cs create mode 100644 Geekbot.net/WebApi/Help/CommandDto.cs create mode 100644 Geekbot.net/WebApi/Help/CommandParamDto.cs rename Geekbot.net/WebApi/{ => Help}/HelpController.cs (70%) create mode 100644 Geekbot.net/WebApi/Status/ApiStatusDto.cs rename Geekbot.net/WebApi/{ => Status}/StatusController.cs (71%) diff --git a/Geekbot.net/Commands/Admin.cs b/Geekbot.net/Commands/Admin/Admin.cs similarity index 96% rename from Geekbot.net/Commands/Admin.cs rename to Geekbot.net/Commands/Admin/Admin.cs index 481eab1..7d30689 100644 --- a/Geekbot.net/Commands/Admin.cs +++ b/Geekbot.net/Commands/Admin/Admin.cs @@ -5,9 +5,11 @@ using Discord; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Localization; using StackExchange.Redis; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Admin { [Group("admin")] [RequireUserPermission(GuildPermission.Administrator)] diff --git a/Geekbot.net/Commands/Mod.cs b/Geekbot.net/Commands/Admin/Mod.cs similarity index 94% rename from Geekbot.net/Commands/Mod.cs rename to Geekbot.net/Commands/Admin/Mod.cs index e8751f6..2dacee3 100644 --- a/Geekbot.net/Commands/Mod.cs +++ b/Geekbot.net/Commands/Admin/Mod.cs @@ -5,9 +5,11 @@ using Discord; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.UserRepository; using StackExchange.Redis; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Admin { [Group("mod")] [RequireUserPermission(GuildPermission.KickMembers)] diff --git a/Geekbot.net/Commands/Owner.cs b/Geekbot.net/Commands/Admin/Owner.cs similarity index 94% rename from Geekbot.net/Commands/Owner.cs rename to Geekbot.net/Commands/Admin/Owner.cs index b73797f..39ccd8c 100644 --- a/Geekbot.net/Commands/Owner.cs +++ b/Geekbot.net/Commands/Admin/Owner.cs @@ -4,9 +4,12 @@ using Discord; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Logger; +using Geekbot.net.Lib.UserRepository; using StackExchange.Redis; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Admin { [Group("owner")] [RequireUserPermission(GuildPermission.Administrator)] diff --git a/Geekbot.net/Commands/Role.cs b/Geekbot.net/Commands/Admin/Role.cs similarity index 98% rename from Geekbot.net/Commands/Role.cs rename to Geekbot.net/Commands/Admin/Role.cs index eb67bbf..24d19dd 100644 --- a/Geekbot.net/Commands/Role.cs +++ b/Geekbot.net/Commands/Admin/Role.cs @@ -6,9 +6,11 @@ using Discord; using Discord.Commands; using Discord.Net; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.ReactionListener; using StackExchange.Redis; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Admin { [Group("role")] public class Role : ModuleBase diff --git a/Geekbot.net/Commands/Say.cs b/Geekbot.net/Commands/Admin/Say.cs similarity index 92% rename from Geekbot.net/Commands/Say.cs rename to Geekbot.net/Commands/Admin/Say.cs index 4c878c4..97c7a0f 100644 --- a/Geekbot.net/Commands/Say.cs +++ b/Geekbot.net/Commands/Admin/Say.cs @@ -3,8 +3,9 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Admin { public class Say : ModuleBase { diff --git a/Geekbot.net/Commands/BattleTag.cs b/Geekbot.net/Commands/Games/BattleTag.cs similarity index 92% rename from Geekbot.net/Commands/BattleTag.cs rename to Geekbot.net/Commands/Games/BattleTag.cs index eb6fca1..88cc0d8 100644 --- a/Geekbot.net/Commands/BattleTag.cs +++ b/Geekbot.net/Commands/Games/BattleTag.cs @@ -2,8 +2,10 @@ using System.Threading.Tasks; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.UserRepository; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Games { [Group("battletag")] public class BattleTag : ModuleBase diff --git a/Geekbot.net/Commands/Overwatch.cs b/Geekbot.net/Commands/Games/Overwatch.cs similarity index 94% rename from Geekbot.net/Commands/Overwatch.cs rename to Geekbot.net/Commands/Games/Overwatch.cs index 0a39662..73e5858 100644 --- a/Geekbot.net/Commands/Overwatch.cs +++ b/Geekbot.net/Commands/Games/Overwatch.cs @@ -3,11 +3,12 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.UserRepository; using OverwatchAPI; using OverwatchAPI.Config; -using StackExchange.Redis; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Games { [Group("ow")] public class Overwatch : ModuleBase diff --git a/Geekbot.net/Commands/Pokedex.cs b/Geekbot.net/Commands/Games/Pokedex.cs similarity index 94% rename from Geekbot.net/Commands/Pokedex.cs rename to Geekbot.net/Commands/Games/Pokedex.cs index fa8746f..57f842a 100644 --- a/Geekbot.net/Commands/Pokedex.cs +++ b/Geekbot.net/Commands/Games/Pokedex.cs @@ -4,9 +4,10 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; using PokeAPI; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Games { public class Pokedex : ModuleBase { diff --git a/Geekbot.net/Commands/Roll.cs b/Geekbot.net/Commands/Games/Roll.cs similarity index 95% rename from Geekbot.net/Commands/Roll.cs rename to Geekbot.net/Commands/Games/Roll.cs index 8d4854c..30697df 100644 --- a/Geekbot.net/Commands/Roll.cs +++ b/Geekbot.net/Commands/Games/Roll.cs @@ -2,9 +2,11 @@ using System.Threading.Tasks; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Localization; using StackExchange.Redis; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Games { public class Roll : ModuleBase { diff --git a/Geekbot.net/Commands/Google.cs b/Geekbot.net/Commands/Integrations/Google/Google.cs similarity index 56% rename from Geekbot.net/Commands/Google.cs rename to Geekbot.net/Commands/Integrations/Google/Google.cs index 19d3efb..8e880c4 100644 --- a/Geekbot.net/Commands/Google.cs +++ b/Geekbot.net/Commands/Integrations/Google/Google.cs @@ -1,15 +1,15 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Net; using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; using StackExchange.Redis; using Utf8Json; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Integrations.Google { public class Google : ModuleBase { @@ -40,7 +40,7 @@ namespace Geekbot.net.Commands var url = new Uri($"https://kgsearch.googleapis.com/v1/entities:search?languages=en&limit=1&query={searchText}&key={apiKey}"); var responseString = client.DownloadString(url); - var response = JsonSerializer.Deserialize(responseString); + var response = JsonSerializer.Deserialize(responseString); if (!response.ItemListElement.Any()) { @@ -48,13 +48,13 @@ namespace Geekbot.net.Commands return; } - var data = response.ItemListElement.First().Result; + var data = response.ItemListElement.First().ResultDto; var eb = new EmbedBuilder(); eb.Title = data.Name; if(!string.IsNullOrEmpty(data.Description)) eb.WithDescription(data.Description); - if(!string.IsNullOrEmpty(data.DetailedDescription?.Url)) eb.WithUrl(data.DetailedDescription.Url); - if(!string.IsNullOrEmpty(data.DetailedDescription?.ArticleBody)) eb.AddField("Details", data.DetailedDescription.ArticleBody); - if(!string.IsNullOrEmpty(data.Image?.ContentUrl)) eb.WithThumbnailUrl(data.Image.ContentUrl); + if(!string.IsNullOrEmpty(data.DetailedDtoDescription?.Url)) eb.WithUrl(data.DetailedDtoDescription.Url); + if(!string.IsNullOrEmpty(data.DetailedDtoDescription?.ArticleBody)) eb.AddField("Details", data.DetailedDtoDescription.ArticleBody); + if(!string.IsNullOrEmpty(data.ImageDto?.ContentUrl)) eb.WithThumbnailUrl(data.ImageDto.ContentUrl); await ReplyAsync("", false, eb.Build()); } @@ -64,37 +64,5 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } - - public class GoogleKgApiResponse - { - public List ItemListElement { get; set; } - - public class GoogleKgApiElement - { - public GoogleKgApiResult Result { get; set; } - public double ResultScore { get; set; } - } - - public class GoogleKgApiResult - { - public string Name { get; set; } - public string Description { get; set; } - public GoogleKgApiImage Image { get; set; } - public GoogleKgApiDetailed DetailedDescription { get; set; } - } - - public class GoogleKgApiImage - { - public string ContentUrl { get; set; } - public string Url { get; set; } - } - - public class GoogleKgApiDetailed - { - public string ArticleBody { get; set; } - public string Url { get; set; } - public string License { get; set; } - } - } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Integrations/Google/GoogleKgApiDetailedDto.cs b/Geekbot.net/Commands/Integrations/Google/GoogleKgApiDetailedDto.cs new file mode 100644 index 0000000..031d1e7 --- /dev/null +++ b/Geekbot.net/Commands/Integrations/Google/GoogleKgApiDetailedDto.cs @@ -0,0 +1,9 @@ +namespace Geekbot.net.Commands.Integrations.Google +{ + public class GoogleKgApiDetailedDto + { + public string ArticleBody { get; set; } + public string Url { get; set; } + public string License { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Integrations/Google/GoogleKgApiElementDto.cs b/Geekbot.net/Commands/Integrations/Google/GoogleKgApiElementDto.cs new file mode 100644 index 0000000..3c4a130 --- /dev/null +++ b/Geekbot.net/Commands/Integrations/Google/GoogleKgApiElementDto.cs @@ -0,0 +1,8 @@ +namespace Geekbot.net.Commands.Integrations.Google +{ + public class GoogleKgApiElementDto + { + public GoogleKgApiResultDto ResultDto { get; set; } + public double ResultScore { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Integrations/Google/GoogleKgApiImageDto.cs b/Geekbot.net/Commands/Integrations/Google/GoogleKgApiImageDto.cs new file mode 100644 index 0000000..fe7cdaa --- /dev/null +++ b/Geekbot.net/Commands/Integrations/Google/GoogleKgApiImageDto.cs @@ -0,0 +1,8 @@ +namespace Geekbot.net.Commands.Integrations.Google +{ + public class GoogleKgApiImageDto + { + public string ContentUrl { get; set; } + public string Url { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Integrations/Google/GoogleKgApiResponseDto.cs b/Geekbot.net/Commands/Integrations/Google/GoogleKgApiResponseDto.cs new file mode 100644 index 0000000..af337db --- /dev/null +++ b/Geekbot.net/Commands/Integrations/Google/GoogleKgApiResponseDto.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace Geekbot.net.Commands.Integrations.Google +{ + public class GoogleKgApiResponseDto + { + public List ItemListElement { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Integrations/Google/GoogleKgApiResultDto.cs b/Geekbot.net/Commands/Integrations/Google/GoogleKgApiResultDto.cs new file mode 100644 index 0000000..2c348c9 --- /dev/null +++ b/Geekbot.net/Commands/Integrations/Google/GoogleKgApiResultDto.cs @@ -0,0 +1,10 @@ +namespace Geekbot.net.Commands.Integrations.Google +{ + public class GoogleKgApiResultDto + { + public string Name { get; set; } + public string Description { get; set; } + public GoogleKgApiImageDto ImageDto { get; set; } + public GoogleKgApiDetailedDto DetailedDtoDescription { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/MagicTheGathering.cs b/Geekbot.net/Commands/Integrations/MagicTheGathering.cs similarity index 94% rename from Geekbot.net/Commands/MagicTheGathering.cs rename to Geekbot.net/Commands/Integrations/MagicTheGathering.cs index 9c7379f..3074803 100644 --- a/Geekbot.net/Commands/MagicTheGathering.cs +++ b/Geekbot.net/Commands/Integrations/MagicTheGathering.cs @@ -5,9 +5,11 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.Converters; +using Geekbot.net.Lib.ErrorHandling; using MtgApiManager.Lib.Service; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Integrations { public class Magicthegathering : ModuleBase { diff --git a/Geekbot.net/Commands/mal.cs b/Geekbot.net/Commands/Integrations/Mal.cs similarity index 95% rename from Geekbot.net/Commands/mal.cs rename to Geekbot.net/Commands/Integrations/Mal.cs index 8c16936..d70949a 100644 --- a/Geekbot.net/Commands/mal.cs +++ b/Geekbot.net/Commands/Integrations/Mal.cs @@ -4,8 +4,10 @@ using System.Web; using Discord; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.Clients; +using Geekbot.net.Lib.ErrorHandling; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Integrations { public class Mal : ModuleBase { diff --git a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictListItemDto.cs b/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictListItemDto.cs new file mode 100644 index 0000000..e98885b --- /dev/null +++ b/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictListItemDto.cs @@ -0,0 +1,12 @@ +namespace Geekbot.net.Commands.Integrations.UbranDictionary +{ + internal class UrbanListItemDto + { + public string Definition { get; set; } + public string Permalink { get; set; } + public string ThumbsUp { get; set; } + public string Word { get; set; } + public string Example { get; set; } + public string ThumbsDown { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictResponseDto.cs b/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictResponseDto.cs new file mode 100644 index 0000000..2c3e014 --- /dev/null +++ b/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictResponseDto.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace Geekbot.net.Commands.Integrations.UbranDictionary +{ + internal class UrbanResponseDto + { + public string[] Tags { get; set; } + public List List { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/UrbanDictionary.cs b/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs similarity index 78% rename from Geekbot.net/Commands/UrbanDictionary.cs rename to Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs index 2af43ba..44402d0 100644 --- a/Geekbot.net/Commands/UrbanDictionary.cs +++ b/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs @@ -1,14 +1,14 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; using Newtonsoft.Json; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Integrations.UbranDictionary { public class UrbanDictionary : ModuleBase { @@ -33,7 +33,7 @@ namespace Geekbot.net.Commands response.EnsureSuccessStatusCode(); var stringResponse = await response.Content.ReadAsStringAsync(); - var definitions = JsonConvert.DeserializeObject(stringResponse); + var definitions = JsonConvert.DeserializeObject(stringResponse); if (definitions.List.Count == 0) { await ReplyAsync("That word hasn't been defined..."); @@ -63,21 +63,5 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } - - private class UrbanResponse - { - public string[] Tags { get; set; } - public List List { get; set; } - } - - private class UrbanListItem - { - public string Definition { get; set; } - public string Permalink { get; set; } - public string ThumbsUp { get; set; } - public string Word { get; set; } - public string Example { get; set; } - public string ThumbsDown { get; set; } - } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Wikipedia.cs b/Geekbot.net/Commands/Integrations/Wikipedia.cs similarity index 95% rename from Geekbot.net/Commands/Wikipedia.cs rename to Geekbot.net/Commands/Integrations/Wikipedia.cs index 05b21a6..68589f6 100644 --- a/Geekbot.net/Commands/Wikipedia.cs +++ b/Geekbot.net/Commands/Integrations/Wikipedia.cs @@ -6,12 +6,13 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; using HtmlAgilityPack; using StackExchange.Redis; using WikipediaApi; using WikipediaApi.Page; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Integrations { public class Wikipedia : ModuleBase { diff --git a/Geekbot.net/Commands/Youtube.cs b/Geekbot.net/Commands/Integrations/Youtube.cs similarity index 92% rename from Geekbot.net/Commands/Youtube.cs rename to Geekbot.net/Commands/Integrations/Youtube.cs index 305052b..f534bcd 100644 --- a/Geekbot.net/Commands/Youtube.cs +++ b/Geekbot.net/Commands/Integrations/Youtube.cs @@ -2,11 +2,12 @@ using System.Threading.Tasks; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; using Google.Apis.Services; using Google.Apis.YouTube.v3; using StackExchange.Redis; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Integrations { public class Youtube : ModuleBase { diff --git a/Geekbot.net/Commands/Cat.cs b/Geekbot.net/Commands/Randomness/Cat/Cat.cs similarity index 90% rename from Geekbot.net/Commands/Cat.cs rename to Geekbot.net/Commands/Randomness/Cat/Cat.cs index 0545894..88a9ce5 100644 --- a/Geekbot.net/Commands/Cat.cs +++ b/Geekbot.net/Commands/Randomness/Cat/Cat.cs @@ -1,58 +1,54 @@ -using System; -using System.Net.Http; -using System.Threading.Tasks; -using Discord; -using Discord.Commands; -using Geekbot.net.Lib; -using Newtonsoft.Json; - -namespace Geekbot.net.Commands -{ - public class Cat : ModuleBase - { - private readonly IErrorHandler _errorHandler; - - public Cat(IErrorHandler errorHandler) - { - _errorHandler = errorHandler; - } - - [Command("cat", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Randomness)] - [Summary("Return a random image of a cat.")] - public async Task Say() - { - try - { - using (var client = new HttpClient()) - { - try - { - client.BaseAddress = new Uri("https://aws.random.cat"); - var response = await client.GetAsync("/meow"); - response.EnsureSuccessStatusCode(); - - var stringResponse = await response.Content.ReadAsStringAsync(); - var catFile = JsonConvert.DeserializeObject(stringResponse); - var eb = new EmbedBuilder(); - eb.ImageUrl = catFile.File; - await ReplyAsync("", false, eb.Build()); - } - catch - { - await ReplyAsync("Seems like the dog cought the cat (error occured)"); - } - } - } - catch (Exception e) - { - _errorHandler.HandleCommandException(e, Context); - } - } - - private class CatResponse - { - public string File { get; set; } - } - } +using System; +using System.Net.Http; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; +using Newtonsoft.Json; + +namespace Geekbot.net.Commands.Randomness.Cat +{ + public class Cat : ModuleBase + { + private readonly IErrorHandler _errorHandler; + + public Cat(IErrorHandler errorHandler) + { + _errorHandler = errorHandler; + } + + [Command("cat", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Randomness)] + [Summary("Return a random image of a cat.")] + public async Task Say() + { + try + { + using (var client = new HttpClient()) + { + try + { + client.BaseAddress = new Uri("https://aws.random.cat"); + var response = await client.GetAsync("/meow"); + response.EnsureSuccessStatusCode(); + + var stringResponse = await response.Content.ReadAsStringAsync(); + var catFile = JsonConvert.DeserializeObject(stringResponse); + var eb = new EmbedBuilder(); + eb.ImageUrl = catFile.File; + await ReplyAsync("", false, eb.Build()); + } + catch + { + await ReplyAsync("Seems like the dog cought the cat (error occured)"); + } + } + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Randomness/Cat/CatResponseDto.cs b/Geekbot.net/Commands/Randomness/Cat/CatResponseDto.cs new file mode 100644 index 0000000..05ebf2b --- /dev/null +++ b/Geekbot.net/Commands/Randomness/Cat/CatResponseDto.cs @@ -0,0 +1,7 @@ +namespace Geekbot.net.Commands.Randomness.Cat +{ + internal class CatResponseDto + { + public string File { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/CheckEm.cs b/Geekbot.net/Commands/Randomness/CheckEm.cs similarity index 93% rename from Geekbot.net/Commands/CheckEm.cs rename to Geekbot.net/Commands/Randomness/CheckEm.cs index 67df682..fc962cc 100644 --- a/Geekbot.net/Commands/CheckEm.cs +++ b/Geekbot.net/Commands/Randomness/CheckEm.cs @@ -1,72 +1,73 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading.Tasks; -using Discord.Commands; -using Geekbot.net.Lib; -using Geekbot.net.Lib.Media; - -namespace Geekbot.net.Commands -{ - public class CheckEm : ModuleBase - { - private readonly IMediaProvider _checkEmImages; - private readonly IErrorHandler _errorHandler; - - public CheckEm(IMediaProvider mediaProvider, IErrorHandler errorHandler) - { - _checkEmImages = mediaProvider; - _errorHandler = errorHandler; - } - - [Command("checkem", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Randomness)] - [Summary("Check for dubs")] - public async Task MuhDubs() - { - try - { - var number = new Random().Next(10000000, 99999999); - var dubtriqua = ""; - - var ns = GetIntArray(number); - if (ns[7] == ns[6]) - { - dubtriqua = "DUBS"; - if (ns[6] == ns[5]) - { - dubtriqua = "TRIPS"; - if (ns[5] == ns[4]) - dubtriqua = "QUADS"; - } - } - - var sb = new StringBuilder(); - sb.AppendLine($"Check em {Context.User.Mention}"); - sb.AppendLine($"**{number}**"); - if (!string.IsNullOrEmpty(dubtriqua)) - sb.AppendLine($":tada: {dubtriqua} :tada:"); - sb.AppendLine(_checkEmImages.GetCheckem()); - - await ReplyAsync(sb.ToString()); - } - catch (Exception e) - { - _errorHandler.HandleCommandException(e, Context); - } - } - - private int[] GetIntArray(int num) - { - var listOfInts = new List(); - while (num > 0) - { - listOfInts.Add(num % 10); - num = num / 10; - } - - listOfInts.Reverse(); - return listOfInts.ToArray(); - } - } +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Discord.Commands; +using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Media; + +namespace Geekbot.net.Commands.Randomness +{ + public class CheckEm : ModuleBase + { + private readonly IMediaProvider _checkEmImages; + private readonly IErrorHandler _errorHandler; + + public CheckEm(IMediaProvider mediaProvider, IErrorHandler errorHandler) + { + _checkEmImages = mediaProvider; + _errorHandler = errorHandler; + } + + [Command("checkem", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Randomness)] + [Summary("Check for dubs")] + public async Task MuhDubs() + { + try + { + var number = new Random().Next(10000000, 99999999); + var dubtriqua = ""; + + var ns = GetIntArray(number); + if (ns[7] == ns[6]) + { + dubtriqua = "DUBS"; + if (ns[6] == ns[5]) + { + dubtriqua = "TRIPS"; + if (ns[5] == ns[4]) + dubtriqua = "QUADS"; + } + } + + var sb = new StringBuilder(); + sb.AppendLine($"Check em {Context.User.Mention}"); + sb.AppendLine($"**{number}**"); + if (!string.IsNullOrEmpty(dubtriqua)) + sb.AppendLine($":tada: {dubtriqua} :tada:"); + sb.AppendLine(_checkEmImages.GetCheckem()); + + await ReplyAsync(sb.ToString()); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + private int[] GetIntArray(int num) + { + var listOfInts = new List(); + while (num > 0) + { + listOfInts.Add(num % 10); + num = num / 10; + } + + listOfInts.Reverse(); + return listOfInts.ToArray(); + } + } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokeResponseDto.cs b/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokeResponseDto.cs new file mode 100644 index 0000000..8d513b8 --- /dev/null +++ b/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokeResponseDto.cs @@ -0,0 +1,7 @@ +namespace Geekbot.net.Commands.Randomness.Chuck +{ + internal class ChuckNorrisJokeResponseDto + { + public string Value { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/ChuckNorrisJokes.cs b/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs similarity index 87% rename from Geekbot.net/Commands/ChuckNorrisJokes.cs rename to Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs index 1c3b009..6ff2255 100644 --- a/Geekbot.net/Commands/ChuckNorrisJokes.cs +++ b/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs @@ -4,9 +4,10 @@ using System.Net.Http.Headers; using System.Threading.Tasks; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; using Newtonsoft.Json; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Randomness.Chuck { public class ChuckNorrisJokes : ModuleBase { @@ -34,7 +35,7 @@ namespace Geekbot.net.Commands response.EnsureSuccessStatusCode(); var stringResponse = await response.Content.ReadAsStringAsync(); - var data = JsonConvert.DeserializeObject(stringResponse); + var data = JsonConvert.DeserializeObject(stringResponse); await ReplyAsync(data.Value); } catch (HttpRequestException) @@ -48,10 +49,5 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } - - private class ChuckNorrisJokeResponse - { - public string Value { get; set; } - } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Randomness/Dad/DadJokeResponseDto.cs b/Geekbot.net/Commands/Randomness/Dad/DadJokeResponseDto.cs new file mode 100644 index 0000000..262eee9 --- /dev/null +++ b/Geekbot.net/Commands/Randomness/Dad/DadJokeResponseDto.cs @@ -0,0 +1,7 @@ +namespace Geekbot.net.Commands.Randomness.Dad +{ + internal class DadJokeResponseDto + { + public string Joke { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/DadJokes.cs b/Geekbot.net/Commands/Randomness/Dad/DadJokes.cs similarity index 87% rename from Geekbot.net/Commands/DadJokes.cs rename to Geekbot.net/Commands/Randomness/Dad/DadJokes.cs index 897c3e0..e35798c 100644 --- a/Geekbot.net/Commands/DadJokes.cs +++ b/Geekbot.net/Commands/Randomness/Dad/DadJokes.cs @@ -4,9 +4,10 @@ using System.Net.Http.Headers; using System.Threading.Tasks; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; using Newtonsoft.Json; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Randomness.Dad { public class DadJokes : ModuleBase { @@ -34,7 +35,7 @@ namespace Geekbot.net.Commands response.EnsureSuccessStatusCode(); var stringResponse = await response.Content.ReadAsStringAsync(); - var data = JsonConvert.DeserializeObject(stringResponse); + var data = JsonConvert.DeserializeObject(stringResponse); await ReplyAsync(data.Joke); } catch (HttpRequestException) @@ -48,10 +49,5 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } - - private class DadJokeResponse - { - public string Joke { get; set; } - } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Dog.cs b/Geekbot.net/Commands/Randomness/Dog/Dog.cs similarity index 88% rename from Geekbot.net/Commands/Dog.cs rename to Geekbot.net/Commands/Randomness/Dog/Dog.cs index 30c0301..08c1a9b 100644 --- a/Geekbot.net/Commands/Dog.cs +++ b/Geekbot.net/Commands/Randomness/Dog/Dog.cs @@ -4,9 +4,10 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; using Newtonsoft.Json; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Randomness.Dog { public class Dog : ModuleBase { @@ -33,7 +34,7 @@ namespace Geekbot.net.Commands response.EnsureSuccessStatusCode(); var stringResponse = await response.Content.ReadAsStringAsync(); - var dogFile = JsonConvert.DeserializeObject(stringResponse); + var dogFile = JsonConvert.DeserializeObject(stringResponse); var eb = new EmbedBuilder(); eb.ImageUrl = dogFile.Url; await ReplyAsync("", false, eb.Build()); @@ -49,10 +50,5 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } - - private class DogResponse - { - public string Url { get; set; } - } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Randomness/Dog/DogResponseDto.cs b/Geekbot.net/Commands/Randomness/Dog/DogResponseDto.cs new file mode 100644 index 0000000..1fc1a82 --- /dev/null +++ b/Geekbot.net/Commands/Randomness/Dog/DogResponseDto.cs @@ -0,0 +1,7 @@ +namespace Geekbot.net.Commands.Randomness.Dog +{ + internal class DogResponseDto + { + public string Url { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/EightBall.cs b/Geekbot.net/Commands/Randomness/EightBall.cs similarity index 95% rename from Geekbot.net/Commands/EightBall.cs rename to Geekbot.net/Commands/Randomness/EightBall.cs index 94b01a1..79ba6d1 100644 --- a/Geekbot.net/Commands/EightBall.cs +++ b/Geekbot.net/Commands/Randomness/EightBall.cs @@ -3,8 +3,9 @@ using System.Collections.Generic; using System.Threading.Tasks; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Randomness { public class EightBall : ModuleBase { diff --git a/Geekbot.net/Commands/Fortune.cs b/Geekbot.net/Commands/Randomness/Fortune.cs similarity index 89% rename from Geekbot.net/Commands/Fortune.cs rename to Geekbot.net/Commands/Randomness/Fortune.cs index 1335139..abc9ce5 100644 --- a/Geekbot.net/Commands/Fortune.cs +++ b/Geekbot.net/Commands/Randomness/Fortune.cs @@ -3,7 +3,7 @@ using Discord.Commands; using Geekbot.net.Lib; using Geekbot.net.Lib.Media; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Randomness { public class Fortune : ModuleBase { diff --git a/Geekbot.net/Commands/Gdq.cs b/Geekbot.net/Commands/Randomness/Gdq.cs similarity index 89% rename from Geekbot.net/Commands/Gdq.cs rename to Geekbot.net/Commands/Randomness/Gdq.cs index fef1c96..3e17451 100644 --- a/Geekbot.net/Commands/Gdq.cs +++ b/Geekbot.net/Commands/Randomness/Gdq.cs @@ -3,8 +3,9 @@ using System.Net; using System.Threading.Tasks; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Randomness { public class Gdq : ModuleBase { diff --git a/Geekbot.net/Commands/RandomAnimals.cs b/Geekbot.net/Commands/Randomness/RandomAnimals.cs similarity index 98% rename from Geekbot.net/Commands/RandomAnimals.cs rename to Geekbot.net/Commands/Randomness/RandomAnimals.cs index 7829b21..a96aea8 100644 --- a/Geekbot.net/Commands/RandomAnimals.cs +++ b/Geekbot.net/Commands/Randomness/RandomAnimals.cs @@ -4,7 +4,7 @@ using Discord.Commands; using Geekbot.net.Lib; using Geekbot.net.Lib.Media; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Randomness { public class RandomAnimals : ModuleBase { diff --git a/Geekbot.net/Commands/Ship.cs b/Geekbot.net/Commands/Randomness/Ship.cs similarity index 94% rename from Geekbot.net/Commands/Ship.cs rename to Geekbot.net/Commands/Randomness/Ship.cs index d7dfd0e..ffa18b4 100644 --- a/Geekbot.net/Commands/Ship.cs +++ b/Geekbot.net/Commands/Randomness/Ship.cs @@ -3,9 +3,10 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; using StackExchange.Redis; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Randomness { public class Ship : ModuleBase { diff --git a/Geekbot.net/Commands/Slap.cs b/Geekbot.net/Commands/Randomness/Slap.cs similarity index 94% rename from Geekbot.net/Commands/Slap.cs rename to Geekbot.net/Commands/Randomness/Slap.cs index 668d33e..129e89d 100644 --- a/Geekbot.net/Commands/Slap.cs +++ b/Geekbot.net/Commands/Randomness/Slap.cs @@ -4,9 +4,10 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; using StackExchange.Redis; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Randomness { public class Slap : ModuleBase { diff --git a/Geekbot.net/Commands/GuildInfo.cs b/Geekbot.net/Commands/User/GuildInfo.cs similarity index 83% rename from Geekbot.net/Commands/GuildInfo.cs rename to Geekbot.net/Commands/User/GuildInfo.cs index 62e0fd1..6306a76 100644 --- a/Geekbot.net/Commands/GuildInfo.cs +++ b/Geekbot.net/Commands/User/GuildInfo.cs @@ -4,9 +4,11 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Levels; using StackExchange.Redis; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.User { public class GuildInfo : ModuleBase { @@ -51,12 +53,5 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } - - public static string FirstCharToUpper(string input) - { - if (string.IsNullOrEmpty(input)) - throw new ArgumentException("ARGH!"); - return input.First().ToString().ToUpper() + input.Substring(1); - } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Karma.cs b/Geekbot.net/Commands/User/Karma.cs similarity index 97% rename from Geekbot.net/Commands/Karma.cs rename to Geekbot.net/Commands/User/Karma.cs index d379b06..d6244a8 100644 --- a/Geekbot.net/Commands/Karma.cs +++ b/Geekbot.net/Commands/User/Karma.cs @@ -3,9 +3,11 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Localization; using StackExchange.Redis; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.User { public class Karma : ModuleBase { diff --git a/Geekbot.net/Commands/Rank.cs b/Geekbot.net/Commands/User/Rank/Rank.cs similarity index 93% rename from Geekbot.net/Commands/Rank.cs rename to Geekbot.net/Commands/User/Rank/Rank.cs index 92f78bd..774ac5a 100644 --- a/Geekbot.net/Commands/Rank.cs +++ b/Geekbot.net/Commands/User/Rank/Rank.cs @@ -6,9 +6,13 @@ using System.Threading.Tasks; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Lib; +using Geekbot.net.Lib.Converters; +using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Logger; +using Geekbot.net.Lib.UserRepository; using StackExchange.Redis; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.User.Rank { public class Rank : ModuleBase { @@ -69,7 +73,7 @@ namespace Geekbot.net.Commands } if (type == "Messages") sortedList.RemoveAt(0); - var highscoreUsers = new Dictionary(); + var highscoreUsers = new Dictionary(); var listLimiter = 1; var failedToRetrieveUser = false; foreach (var user in sortedList) @@ -80,7 +84,7 @@ namespace Geekbot.net.Commands var guildUser = _userRepository.Get((ulong) user.Name); if (guildUser.Username != null) { - highscoreUsers.Add(new RankUserPolyfill + highscoreUsers.Add(new RankUserPolyfillDto { Username = guildUser.Username, Discriminator = guildUser.Discriminator @@ -88,7 +92,7 @@ namespace Geekbot.net.Commands } else { - highscoreUsers.Add(new RankUserPolyfill + highscoreUsers.Add(new RankUserPolyfillDto { Id = user.Name }, (int) user.Value); @@ -143,11 +147,4 @@ namespace Geekbot.net.Commands } } } - - internal class RankUserPolyfill - { - public string Username { get; set; } - public string Discriminator { get; set; } - public string Id { get; set; } - } } \ No newline at end of file diff --git a/Geekbot.net/Commands/User/Rank/RankUserPolyfillDto.cs b/Geekbot.net/Commands/User/Rank/RankUserPolyfillDto.cs new file mode 100644 index 0000000..f666ffc --- /dev/null +++ b/Geekbot.net/Commands/User/Rank/RankUserPolyfillDto.cs @@ -0,0 +1,9 @@ +namespace Geekbot.net.Commands.User.Rank +{ + internal class RankUserPolyfillDto + { + public string Username { get; set; } + public string Discriminator { get; set; } + public string Id { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Stats.cs b/Geekbot.net/Commands/User/Stats.cs similarity index 96% rename from Geekbot.net/Commands/Stats.cs rename to Geekbot.net/Commands/User/Stats.cs index 67b76b9..19a6aa8 100644 --- a/Geekbot.net/Commands/Stats.cs +++ b/Geekbot.net/Commands/User/Stats.cs @@ -3,9 +3,11 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Levels; using StackExchange.Redis; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.User { public class Stats : ModuleBase { diff --git a/Geekbot.net/Commands/AvatarGetter.cs b/Geekbot.net/Commands/Utils/AvatarGetter.cs similarity index 89% rename from Geekbot.net/Commands/AvatarGetter.cs rename to Geekbot.net/Commands/Utils/AvatarGetter.cs index d8a04e9..d42c779 100644 --- a/Geekbot.net/Commands/AvatarGetter.cs +++ b/Geekbot.net/Commands/Utils/AvatarGetter.cs @@ -3,8 +3,9 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Utils { public class AvatarGetter : ModuleBase { diff --git a/Geekbot.net/Commands/Changelog.cs b/Geekbot.net/Commands/Utils/Changelog/Changelog.cs similarity index 82% rename from Geekbot.net/Commands/Changelog.cs rename to Geekbot.net/Commands/Utils/Changelog/Changelog.cs index 70c4c17..f956d7c 100644 --- a/Geekbot.net/Commands/Changelog.cs +++ b/Geekbot.net/Commands/Utils/Changelog/Changelog.cs @@ -8,9 +8,10 @@ using Discord; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; using Newtonsoft.Json; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Utils.Changelog { public class Changelog : ModuleBase { @@ -51,7 +52,7 @@ namespace Geekbot.net.Commands }); var sb = new StringBuilder(); foreach (var commit in commits.Take(10)) - sb.AppendLine($"- {commit.Commit.Message} ({commit.Commit.Author.Date:yyyy-MM-dd})"); + sb.AppendLine($"- {commit.Commit.Message} ({commit.Commit.AuthorDto.Date:yyyy-MM-dd})"); eb.Description = sb.ToString(); eb.WithFooter(new EmbedFooterBuilder { @@ -65,21 +66,5 @@ namespace Geekbot.net.Commands _errorHandler.HandleCommandException(e, Context); } } - - private class CommitDto - { - public CommitInfo Commit { get; set; } - } - - private class CommitInfo - { - public CommitAuthor Author { get; set; } - public string Message { get; set; } - } - - private class CommitAuthor - { - public DateTimeOffset Date { get; set; } - } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Utils/Changelog/CommitAuthorDto.cs b/Geekbot.net/Commands/Utils/Changelog/CommitAuthorDto.cs new file mode 100644 index 0000000..ad37311 --- /dev/null +++ b/Geekbot.net/Commands/Utils/Changelog/CommitAuthorDto.cs @@ -0,0 +1,9 @@ +using System; + +namespace Geekbot.net.Commands.Utils.Changelog +{ + internal class CommitAuthorDto + { + public DateTimeOffset Date { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Utils/Changelog/CommitDto.cs b/Geekbot.net/Commands/Utils/Changelog/CommitDto.cs new file mode 100644 index 0000000..d5c5bab --- /dev/null +++ b/Geekbot.net/Commands/Utils/Changelog/CommitDto.cs @@ -0,0 +1,7 @@ +namespace Geekbot.net.Commands.Utils.Changelog +{ + internal class CommitDto + { + public CommitInfoDto Commit { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Utils/Changelog/CommitInfoDto.cs b/Geekbot.net/Commands/Utils/Changelog/CommitInfoDto.cs new file mode 100644 index 0000000..102d2cd --- /dev/null +++ b/Geekbot.net/Commands/Utils/Changelog/CommitInfoDto.cs @@ -0,0 +1,8 @@ +namespace Geekbot.net.Commands.Utils.Changelog +{ + internal class CommitInfoDto + { + public CommitAuthorDto AuthorDto { get; set; } + public string Message { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Choose.cs b/Geekbot.net/Commands/Utils/Choose.cs similarity index 88% rename from Geekbot.net/Commands/Choose.cs rename to Geekbot.net/Commands/Utils/Choose.cs index a726741..4d54654 100644 --- a/Geekbot.net/Commands/Choose.cs +++ b/Geekbot.net/Commands/Utils/Choose.cs @@ -2,8 +2,10 @@ using System.Threading.Tasks; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Localization; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Utils { public class Choose : ModuleBase { diff --git a/Geekbot.net/Commands/Dice.cs b/Geekbot.net/Commands/Utils/Dice/Dice.cs similarity index 93% rename from Geekbot.net/Commands/Dice.cs rename to Geekbot.net/Commands/Utils/Dice/Dice.cs index 89b3a11..7fc4f84 100644 --- a/Geekbot.net/Commands/Dice.cs +++ b/Geekbot.net/Commands/Utils/Dice/Dice.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; using Discord.Commands; using Geekbot.net.Lib; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Utils.Dice { public class Dice : ModuleBase { @@ -112,12 +112,4 @@ namespace Geekbot.net.Commands return new DiceTypeDto(); } } - - internal class DiceTypeDto - { - public string DiceType { get; set; } - public int Times { get; set; } - public int Sides { get; set; } - public int Mod { get; set; } - } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Utils/Dice/DiceTypeDto.cs b/Geekbot.net/Commands/Utils/Dice/DiceTypeDto.cs new file mode 100644 index 0000000..5c54792 --- /dev/null +++ b/Geekbot.net/Commands/Utils/Dice/DiceTypeDto.cs @@ -0,0 +1,10 @@ +namespace Geekbot.net.Commands.Utils.Dice +{ + internal class DiceTypeDto + { + public string DiceType { get; set; } + public int Times { get; set; } + public int Sides { get; set; } + public int Mod { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Emojify.cs b/Geekbot.net/Commands/Utils/Emojify.cs similarity index 89% rename from Geekbot.net/Commands/Emojify.cs rename to Geekbot.net/Commands/Utils/Emojify.cs index 739a4dc..57363c2 100644 --- a/Geekbot.net/Commands/Emojify.cs +++ b/Geekbot.net/Commands/Utils/Emojify.cs @@ -2,8 +2,10 @@ using System.Threading.Tasks; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.Converters; +using Geekbot.net.Lib.ErrorHandling; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Utils { public class Emojify : ModuleBase { diff --git a/Geekbot.net/Commands/Help.cs b/Geekbot.net/Commands/Utils/Help.cs similarity index 93% rename from Geekbot.net/Commands/Help.cs rename to Geekbot.net/Commands/Utils/Help.cs index 1b3e285..be9a747 100644 --- a/Geekbot.net/Commands/Help.cs +++ b/Geekbot.net/Commands/Utils/Help.cs @@ -4,8 +4,9 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Utils { public class Help : ModuleBase { diff --git a/Geekbot.net/Commands/Info.cs b/Geekbot.net/Commands/Utils/Info.cs similarity index 94% rename from Geekbot.net/Commands/Info.cs rename to Geekbot.net/Commands/Utils/Info.cs index e8c35dc..446abfe 100644 --- a/Geekbot.net/Commands/Info.cs +++ b/Geekbot.net/Commands/Utils/Info.cs @@ -6,9 +6,10 @@ using Discord; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; using StackExchange.Redis; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Utils { public class Info : ModuleBase { diff --git a/Geekbot.net/Commands/Ping.cs b/Geekbot.net/Commands/Utils/Ping.cs similarity index 91% rename from Geekbot.net/Commands/Ping.cs rename to Geekbot.net/Commands/Utils/Ping.cs index c41700e..226e9a3 100644 --- a/Geekbot.net/Commands/Ping.cs +++ b/Geekbot.net/Commands/Utils/Ping.cs @@ -2,7 +2,7 @@ using Discord.Commands; using Geekbot.net.Lib; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Utils { public class Ping : ModuleBase { diff --git a/Geekbot.net/Commands/Poll.cs b/Geekbot.net/Commands/Utils/Poll/Poll.cs similarity index 85% rename from Geekbot.net/Commands/Poll.cs rename to Geekbot.net/Commands/Utils/Poll/Poll.cs index cf80835..5d18a0f 100644 --- a/Geekbot.net/Commands/Poll.cs +++ b/Geekbot.net/Commands/Utils/Poll/Poll.cs @@ -6,10 +6,13 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.Converters; +using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.UserRepository; using Newtonsoft.Json; using StackExchange.Redis; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Utils.Poll { [Group("poll")] public class Poll : ModuleBase @@ -92,7 +95,7 @@ namespace Geekbot.net.Commands pollMessage.AddReactionAsync(new Emoji(_emojiConverter.NumberToEmoji(i))); i++; }); - var poll = new PollData + var poll = new PollDataDto { Creator = Context.User.Id, MessageId = pollMessage.Id, @@ -139,28 +142,28 @@ namespace Geekbot.net.Commands } } - private PollData GetCurrentPoll() + private PollDataDto GetCurrentPoll() { try { var currentPoll = _redis.HashGet($"{Context.Guild.Id}:Polls", Context.Channel.Id); - return JsonConvert.DeserializeObject(currentPoll.ToString()); + return JsonConvert.DeserializeObject(currentPoll.ToString()); } catch { - return new PollData(); + return new PollDataDto(); } } - private async Task> GetPollResults(PollData poll) + private async Task> GetPollResults(PollDataDto poll) { var message = (IUserMessage) await Context.Channel.GetMessageAsync(poll.MessageId); - var results = new List(); + var results = new List(); foreach (var r in message.Reactions) try { var option = int.Parse(r.Key.Name.ToCharArray()[0].ToString()); - var result = new PollResult + var result = new PollResultDto { Option = poll.Options[option - 1], VoteCount = r.Value.ReactionCount @@ -172,20 +175,5 @@ namespace Geekbot.net.Commands results.Sort((x, y) => y.VoteCount.CompareTo(x.VoteCount)); return results; } - - private class PollData - { - public ulong Creator { get; set; } - public ulong MessageId { get; set; } - public bool IsFinshed { get; set; } - public string Question { get; set; } - public List Options { get; set; } - } - - private class PollResult - { - public string Option { get; set; } - public int VoteCount { get; set; } - } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Utils/Poll/PollDataDto.cs b/Geekbot.net/Commands/Utils/Poll/PollDataDto.cs new file mode 100644 index 0000000..3d21479 --- /dev/null +++ b/Geekbot.net/Commands/Utils/Poll/PollDataDto.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace Geekbot.net.Commands.Utils.Poll +{ + internal class PollDataDto + { + public ulong Creator { get; set; } + public ulong MessageId { get; set; } + public bool IsFinshed { get; set; } + public string Question { get; set; } + public List Options { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Utils/Poll/PollResultDto.cs b/Geekbot.net/Commands/Utils/Poll/PollResultDto.cs new file mode 100644 index 0000000..b4f14a2 --- /dev/null +++ b/Geekbot.net/Commands/Utils/Poll/PollResultDto.cs @@ -0,0 +1,8 @@ +namespace Geekbot.net.Commands.Utils.Poll +{ + internal class PollResultDto + { + public string Option { get; set; } + public int VoteCount { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Quote.cs b/Geekbot.net/Commands/Utils/Quote/Quote.cs similarity index 94% rename from Geekbot.net/Commands/Quote.cs rename to Geekbot.net/Commands/Utils/Quote/Quote.cs index 4b4cfc3..f1941ba 100644 --- a/Geekbot.net/Commands/Quote.cs +++ b/Geekbot.net/Commands/Utils/Quote/Quote.cs @@ -4,10 +4,11 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; using Newtonsoft.Json; using StackExchange.Redis; -namespace Geekbot.net.Commands +namespace Geekbot.net.Commands.Utils.Quote { [Group("quote")] public class Quote : ModuleBase @@ -31,7 +32,7 @@ namespace Geekbot.net.Commands var randomQuotes = _redis.SetMembers($"{Context.Guild.Id}:Quotes"); var randomNumber = new Random().Next(randomQuotes.Length - 1); var randomQuote = randomQuotes[randomNumber]; - var quote = JsonConvert.DeserializeObject(randomQuote); + var quote = JsonConvert.DeserializeObject(randomQuote); var embed = QuoteBuilder(quote, randomNumber + 1); await ReplyAsync("", false, embed.Build()); } @@ -159,7 +160,7 @@ namespace Geekbot.net.Commands var success = _redis.SetRemove($"{Context.Guild.Id}:Quotes", quotes[id - 1]); if (success) { - var quote = JsonConvert.DeserializeObject(quotes[id - 1]); + var quote = JsonConvert.DeserializeObject(quotes[id - 1]); var embed = QuoteBuilder(quote); await ReplyAsync($"**Removed #{id}**", false, embed.Build()); } @@ -186,7 +187,7 @@ namespace Geekbot.net.Commands && !msg.Content.ToLower().StartsWith("!")); } - private EmbedBuilder QuoteBuilder(QuoteObject quote, int id = 0) + private EmbedBuilder QuoteBuilder(QuoteObjectDto quote, int id = 0) { var user = Context.Client.GetUserAsync(quote.UserId).Result; var eb = new EmbedBuilder(); @@ -199,7 +200,7 @@ namespace Geekbot.net.Commands return eb; } - private QuoteObject CreateQuoteObject(IMessage message) + private QuoteObjectDto CreateQuoteObject(IMessage message) { string image; try @@ -211,7 +212,7 @@ namespace Geekbot.net.Commands image = null; } - return new QuoteObject + return new QuoteObjectDto { UserId = message.Author.Id, Time = message.Timestamp.DateTime, @@ -220,12 +221,4 @@ namespace Geekbot.net.Commands }; } } - - public class QuoteObject - { - public ulong UserId { get; set; } - public string Quote { get; set; } - public DateTime Time { get; set; } - public string Image { get; set; } - } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Utils/Quote/QuoteObjectDto.cs b/Geekbot.net/Commands/Utils/Quote/QuoteObjectDto.cs new file mode 100644 index 0000000..a37ff76 --- /dev/null +++ b/Geekbot.net/Commands/Utils/Quote/QuoteObjectDto.cs @@ -0,0 +1,12 @@ +using System; + +namespace Geekbot.net.Commands.Utils.Quote +{ + internal class QuoteObjectDto + { + public ulong UserId { get; set; } + public string Quote { get; set; } + public DateTime Time { get; set; } + public string Image { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Voice.cs b/Geekbot.net/Commands/Voice.cs deleted file mode 100644 index ca65913..0000000 --- a/Geekbot.net/Commands/Voice.cs +++ /dev/null @@ -1,102 +0,0 @@ -//using System; -//using System.IO; -//using System.Threading.Tasks; -//using Discord; -//using Discord.Commands; -//using Geekbot.net.Lib; -// -//namespace Geekbot.net.Commands -//{ -// public class Voice : ModuleBase -// { -// private readonly IAudioUtils _audioUtils; -// private readonly IErrorHandler _errorHandler; -// -// public Voice(IErrorHandler errorHandler, IAudioUtils audioUtils) -// { -// _errorHandler = errorHandler; -// _audioUtils = audioUtils; -// } -// -// [Command("join")] -// public async Task JoinChannel() -// { -// try -// { -// // Get the audio channel -// var channel = (Context.User as IGuildUser)?.VoiceChannel; -// if (channel == null) -// { -// await Context.Channel.SendMessageAsync( -// "User must be in a voice channel, or a voice channel must be passed as an argument."); -// return; -// } -// -// // For the next step with transmitting audio, you would want to pass this Audio Client in to a service. -// var audioClient = await channel.ConnectAsync(); -// _audioUtils.StoreAudioClient(Context.Guild.Id, audioClient); -// await ReplyAsync($"Connected to {channel.Name}"); -// } -// catch (Exception e) -// { -// _errorHandler.HandleCommandException(e, Context); -// } -// } -// -// [Command("disconnect")] -// public async Task DisconnectChannel() -// { -// try -// { -// var audioClient = _audioUtils.GetAudioClient(Context.Guild.Id); -// if (audioClient == null) -// { -// await Context.Channel.SendMessageAsync("I'm not in a voice channel at the moment"); -// return; -// } -// -// await audioClient.StopAsync(); -// await ReplyAsync("Disconnected from channel!"); -// _audioUtils.Cleanup(Context.Guild.Id); -// } -// catch (Exception e) -// { -// _errorHandler.HandleCommandException(e, Context); -// _audioUtils.Cleanup(Context.Guild.Id); -// } -// } -// -// [Command("ytplay")] -// public async Task ytplay(string url) -// { -// try -// { -// if (!url.Contains("youtube")) -// { -// await ReplyAsync("I can only play youtube videos"); -// return; -// } -// var audioClient = _audioUtils.GetAudioClient(Context.Guild.Id); -// if (audioClient == null) -// { -// await ReplyAsync("I'm not in a voice channel at the moment"); -// return; -// } -// -// var message = await Context.Channel.SendMessageAsync("Just a second, i'm still a bit slow at this"); -// var ffmpeg = _audioUtils.CreateStreamFromYoutube(url, Context.Guild.Id); -// var output = ffmpeg.StandardOutput.BaseStream; -// await message.ModifyAsync(msg => msg.Content = "**Playing!** Please note that this feature is experimental"); -// var discord = audioClient.CreatePCMStream(Discord.Audio.AudioApplication.Mixed); -// await output.CopyToAsync(discord); -// await discord.FlushAsync(); -// _audioUtils.Cleanup(Context.Guild.Id); -// } -// catch (Exception e) -// { -// _errorHandler.HandleCommandException(e, Context); -// _audioUtils.Cleanup(Context.Guild.Id); -// } -// } -// } -//} \ No newline at end of file diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index ba9faed..5cba28a 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -63,9 +63,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest @@ -75,6 +72,12 @@ PreserveNewest + + Always + + + Always +
diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index 31608b2..7d1523b 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -4,7 +4,9 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.WebSocket; -using Geekbot.net.Lib; +using Geekbot.net.Lib.Logger; +using Geekbot.net.Lib.ReactionListener; +using Geekbot.net.Lib.UserRepository; using StackExchange.Redis; namespace Geekbot.net @@ -89,7 +91,6 @@ namespace Geekbot.net if (message.Author.IsBot) return Task.CompletedTask; _logger.Information("Message", message.Content, SimpleConextConverter.ConvertSocketMessage(message)); -// _logger.Information($"[Message] {channel.Guild.Name} ({channel.Guild.Id}) - {message.Channel} ({message.Channel.Id}) - {message.Author.Username}#{message.Author.Discriminator} ({message.Author.Id}) - {message.Content}"); } catch (Exception e) { diff --git a/Geekbot.net/Lib/Clients/IMalClient.cs b/Geekbot.net/Lib/Clients/IMalClient.cs new file mode 100644 index 0000000..f59c511 --- /dev/null +++ b/Geekbot.net/Lib/Clients/IMalClient.cs @@ -0,0 +1,12 @@ +using System.Threading.Tasks; +using MyAnimeListSharp.Core; + +namespace Geekbot.net.Lib.Clients +{ + public interface IMalClient + { + bool IsLoggedIn(); + Task GetAnime(string query); + Task GetManga(string query); + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/MalClient.cs b/Geekbot.net/Lib/Clients/MalClient.cs similarity index 89% rename from Geekbot.net/Lib/MalClient.cs rename to Geekbot.net/Lib/Clients/MalClient.cs index dcf4fe3..d8bfe41 100644 --- a/Geekbot.net/Lib/MalClient.cs +++ b/Geekbot.net/Lib/Clients/MalClient.cs @@ -1,10 +1,11 @@ using System.Threading.Tasks; +using Geekbot.net.Lib.Logger; using MyAnimeListSharp.Auth; using MyAnimeListSharp.Core; using MyAnimeListSharp.Facade.Async; using StackExchange.Redis; -namespace Geekbot.net.Lib +namespace Geekbot.net.Lib.Clients { public class MalClient : IMalClient { @@ -66,11 +67,4 @@ namespace Geekbot.net.Lib return response.Entries.Count == 0 ? null : response.Entries[0]; } } - - public interface IMalClient - { - bool IsLoggedIn(); - Task GetAnime(string query); - Task GetManga(string query); - } } \ No newline at end of file diff --git a/Geekbot.net/Lib/EmojiConverter.cs b/Geekbot.net/Lib/Converters/EmojiConverter.cs similarity index 92% rename from Geekbot.net/Lib/EmojiConverter.cs rename to Geekbot.net/Lib/Converters/EmojiConverter.cs index b836485..06f1aa8 100644 --- a/Geekbot.net/Lib/EmojiConverter.cs +++ b/Geekbot.net/Lib/Converters/EmojiConverter.cs @@ -1,7 +1,7 @@ using System.Collections; using System.Text; -namespace Geekbot.net.Lib +namespace Geekbot.net.Lib.Converters { public class EmojiConverter : IEmojiConverter { @@ -90,10 +90,4 @@ namespace Geekbot.net.Lib return returnString.ToString(); } } - - public interface IEmojiConverter - { - string NumberToEmoji(int number); - string TextToEmoji(string text); - } } \ No newline at end of file diff --git a/Geekbot.net/Lib/Converters/IEmojiConverter.cs b/Geekbot.net/Lib/Converters/IEmojiConverter.cs new file mode 100644 index 0000000..b0f666f --- /dev/null +++ b/Geekbot.net/Lib/Converters/IEmojiConverter.cs @@ -0,0 +1,8 @@ +namespace Geekbot.net.Lib.Converters +{ + public interface IEmojiConverter + { + string NumberToEmoji(int number); + string TextToEmoji(string text); + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Converters/IMtgManaConverter.cs b/Geekbot.net/Lib/Converters/IMtgManaConverter.cs new file mode 100644 index 0000000..d558f09 --- /dev/null +++ b/Geekbot.net/Lib/Converters/IMtgManaConverter.cs @@ -0,0 +1,7 @@ +namespace Geekbot.net.Lib.Converters +{ + public interface IMtgManaConverter + { + string ConvertMana(string mana); + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Converters/MtgManaConverter.cs b/Geekbot.net/Lib/Converters/MtgManaConverter.cs new file mode 100644 index 0000000..c29e1e0 --- /dev/null +++ b/Geekbot.net/Lib/Converters/MtgManaConverter.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; +using Utf8Json; + +namespace Geekbot.net.Lib.Converters +{ + public class MtgManaConverter : IMtgManaConverter + { + private Dictionary _manaDict; + + public MtgManaConverter() + { + // these emotes can be found at https://discord.gg/bz8HyA7 + var mtgEmojis = File.ReadAllText(Path.GetFullPath("./Lib/Converters/MtgManaEmojis.json")); + _manaDict = JsonSerializer.Deserialize>(mtgEmojis); + } + + public string ConvertMana(string mana) + { + var rgx = Regex.Matches(mana, @"(\{(.*?)\})"); + foreach (Match manaTypes in rgx) + { + var m = _manaDict.GetValueOrDefault(manaTypes.Value); + if (!string.IsNullOrEmpty(m)) + { + mana = mana.Replace(manaTypes.Value, m); + } + } + return mana; + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Converters/MtgManaEmojis.json b/Geekbot.net/Lib/Converters/MtgManaEmojis.json new file mode 100644 index 0000000..8ebe75b --- /dev/null +++ b/Geekbot.net/Lib/Converters/MtgManaEmojis.json @@ -0,0 +1,50 @@ +{ + "{0}": "<:mtg_0:415216130043412482>", + "{1}": "<:mtg_1:415216130253389835>", + "{2}": "<:mtg_2:415216130031091713>", + "{3}": "<:mtg_3:415216130467037194>", + "{4}": "<:mtg_4:415216130026635295>", + "{5}": "<:mtg_5:415216130492203008>", + "{6}": "<:mtg_6:415216130458779658>", + "{7}": "<:mtg_7:415216130190475265>", + "{8}": "<:mtg_8:415216130517630986>", + "{9}": "<:mtg_9:415216130500722689>", + "{10": "<:mtg_10:415216130450391051>", + "{11}": "<:mtg_11:415216130811101185>", + "{12}": "<:mtg_12:415216130525888532>", + "{13}": "<:mtg_13:415216130517631000>", + "{14}": "<:mtg_14:415216130165178370>", + "{15}": "<:mtg_15:415216130576089108>", + "{16}": "<:mtg_16:415216130358247425>", + "{17}": "<:mtg_17:415216130601517056>", + "{18}": "<:mtg_18:415216130462842891>", + "{19}": "<:mtg_19:415216130614099988>", + "{20}": "<:mtg_20:415216130656043038>", + "{W}": "<:mtg_white:415216131515744256>", + "{U}": "<:mtg_blue:415216130521694209>", + "{B}": "<:mtg_black:415216130873884683>", + "{R}": "<:mtg_red:415216131322806272>", + "{G}": "<:mtg_green:415216131180331009>", + "{S}": "<:mtg_s:415216131293446144>", + "{T}": "<:mtg_tap:415258392727257088>", + "{C}": "<:mtg_colorless:415216130706374666>", + "{2/W}": "<:mtg_2w:415216130446065664>", + "{2/U}": "<:mtg_2u:415216130429550592>", + "{2/B}": "<:mtg_2b:415216130160984065>", + "{2/R}": "<:mtg_2r:415216130454716436>", + "{2/G}": "<:mtg_2g:415216130420899840>", + "{W/U}": "<:mtg_wu:415216130970484736>", + "{W/B}": "<:mtg_wb:415216131222011914>", + "{U/R}": "<:mtg_ur:415216130962096128>", + "{U/B}": "<:mtg_ub:415216130865758218>", + "{R/W}": "<:mtg_rw:415216130878210057>", + "{G/W}": "<:mtg_gw:415216130567962646>", + "{G/U}": "<:mtg_gu:415216130739666945>", + "{B/R}": "<:mtg_br:415216130580283394>", + "{B/G}": "<:mtg_bg:415216130781609994>", + "{U/P}": "<:mtg_up:415216130861432842>", + "{R/P}": "<:mtg_rp:415216130597322783>", + "{G/P}": "<:mtg_gp:415216130760769546>", + "{W/P}": "<:mtg_wp:415216131541041172>", + "{B/P}": "<:mtg_bp:415216130664169482>" +} \ No newline at end of file diff --git a/Geekbot.net/Lib/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs similarity index 93% rename from Geekbot.net/Lib/ErrorHandler.cs rename to Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs index 9bf99f4..3d53242 100644 --- a/Geekbot.net/Lib/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs @@ -2,10 +2,12 @@ using System.Net; using Discord.Commands; using Discord.Net; +using Geekbot.net.Lib.Localization; +using Geekbot.net.Lib.Logger; using SharpRaven; using SharpRaven.Data; -namespace Geekbot.net.Lib +namespace Geekbot.net.Lib.ErrorHandling { public class ErrorHandler : IErrorHandler { @@ -90,10 +92,4 @@ namespace Geekbot.net.Lib } - - public interface IErrorHandler - { - void HandleCommandException(Exception e, ICommandContext context, string errorMessage = "def"); - void HandleHttpException(HttpException e, ICommandContext context); - } } \ No newline at end of file diff --git a/Geekbot.net/Lib/ErrorHandling/IErrorHandler.cs b/Geekbot.net/Lib/ErrorHandling/IErrorHandler.cs new file mode 100644 index 0000000..f2d8dac --- /dev/null +++ b/Geekbot.net/Lib/ErrorHandling/IErrorHandler.cs @@ -0,0 +1,12 @@ +using System; +using Discord.Commands; +using Discord.Net; + +namespace Geekbot.net.Lib.ErrorHandling +{ + public interface IErrorHandler + { + void HandleCommandException(Exception e, ICommandContext context, string errorMessage = "def"); + void HandleHttpException(HttpException e, ICommandContext context); + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Levels/ILevelCalc.cs b/Geekbot.net/Lib/Levels/ILevelCalc.cs new file mode 100644 index 0000000..6353132 --- /dev/null +++ b/Geekbot.net/Lib/Levels/ILevelCalc.cs @@ -0,0 +1,7 @@ +namespace Geekbot.net.Lib.Levels +{ + public interface ILevelCalc + { + int GetLevel(int experience); + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/LevelCalc.cs b/Geekbot.net/Lib/Levels/LevelCalc.cs similarity index 87% rename from Geekbot.net/Lib/LevelCalc.cs rename to Geekbot.net/Lib/Levels/LevelCalc.cs index 75df83d..9ecf803 100644 --- a/Geekbot.net/Lib/LevelCalc.cs +++ b/Geekbot.net/Lib/Levels/LevelCalc.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace Geekbot.net.Lib +namespace Geekbot.net.Lib.Levels { public class LevelCalc : ILevelCalc { @@ -30,9 +30,4 @@ namespace Geekbot.net.Lib return returnVal; } } - - public interface ILevelCalc - { - int GetLevel(int experience); - } } \ No newline at end of file diff --git a/Geekbot.net/Lib/Localization/ITranslationHandler.cs b/Geekbot.net/Lib/Localization/ITranslationHandler.cs new file mode 100644 index 0000000..3cd9549 --- /dev/null +++ b/Geekbot.net/Lib/Localization/ITranslationHandler.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using Discord.Commands; + +namespace Geekbot.net.Lib.Localization +{ + public interface ITranslationHandler + { + string GetString(ulong guildId, string command, string stringName); + Dictionary GetDict(ICommandContext context); + Dictionary GetDict(ICommandContext context, string command); + bool SetLanguage(ulong guildId, string language); + List GetSupportedLanguages(); + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/TranslationHandler.cs b/Geekbot.net/Lib/Localization/TranslationHandler.cs similarity index 90% rename from Geekbot.net/Lib/TranslationHandler.cs rename to Geekbot.net/Lib/Localization/TranslationHandler.cs index 5324496..e57ee8d 100644 --- a/Geekbot.net/Lib/TranslationHandler.cs +++ b/Geekbot.net/Lib/Localization/TranslationHandler.cs @@ -4,10 +4,11 @@ using System.IO; using System.Linq; using Discord.Commands; using Discord.WebSocket; +using Geekbot.net.Lib.Logger; using StackExchange.Redis; using Utf8Json; -namespace Geekbot.net.Lib +namespace Geekbot.net.Lib.Localization { public class TranslationHandler : ITranslationHandler { @@ -30,7 +31,7 @@ namespace Geekbot.net.Lib { try { - var translationFile = File.ReadAllText(Path.GetFullPath("./Storage/Translations.json")); + var translationFile = File.ReadAllText(Path.GetFullPath("./Lib/Localization/Translations.json")); var rawTranslations = JsonSerializer.Deserialize>>>(translationFile); var sortedPerLanguage = new Dictionary>>(); foreach (var command in rawTranslations) @@ -152,13 +153,4 @@ namespace Geekbot.net.Lib return _supportedLanguages; } } - - public interface ITranslationHandler - { - string GetString(ulong guildId, string command, string stringName); - Dictionary GetDict(ICommandContext context); - Dictionary GetDict(ICommandContext context, string command); - bool SetLanguage(ulong guildId, string language); - List GetSupportedLanguages(); - } } \ No newline at end of file diff --git a/Geekbot.net/Storage/Translations.json b/Geekbot.net/Lib/Localization/Translations.json similarity index 100% rename from Geekbot.net/Storage/Translations.json rename to Geekbot.net/Lib/Localization/Translations.json diff --git a/Geekbot.net/Lib/Logger/DiscordLogger.cs b/Geekbot.net/Lib/Logger/DiscordLogger.cs new file mode 100644 index 0000000..fc12201 --- /dev/null +++ b/Geekbot.net/Lib/Logger/DiscordLogger.cs @@ -0,0 +1,42 @@ +using System.Threading.Tasks; +using Discord; + +namespace Geekbot.net.Lib.Logger +{ + public class DiscordLogger : IDiscordLogger + { + private readonly GeekbotLogger _logger; + + public DiscordLogger(GeekbotLogger logger) + { + _logger = logger; + } + + public Task Log(LogMessage message) + { + var logMessage = $"[{message.Source}] {message.Message}"; + switch (message.Severity) + { + case LogSeverity.Verbose: + _logger.Trace(message.Source, message.Message); + break; + case LogSeverity.Debug: + _logger.Debug(message.Source, message.Message); + break; + case LogSeverity.Info: + _logger.Information(message.Source, message.Message); + break; + case LogSeverity.Critical: + case LogSeverity.Error: + case LogSeverity.Warning: + if (logMessage.Contains("VOICE_STATE_UPDATE")) break; + _logger.Error(message.Source, message.Message, message.Exception); + break; + default: + _logger.Information(message.Source, $"{logMessage} --- {message.Severity}"); + break; + } + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/GeekbotLogger.cs b/Geekbot.net/Lib/Logger/GeekbotLogger.cs similarity index 75% rename from Geekbot.net/Lib/GeekbotLogger.cs rename to Geekbot.net/Lib/Logger/GeekbotLogger.cs index 7093a7c..8cefdb4 100644 --- a/Geekbot.net/Lib/GeekbotLogger.cs +++ b/Geekbot.net/Lib/Logger/GeekbotLogger.cs @@ -1,7 +1,7 @@ using System; using Newtonsoft.Json; -namespace Geekbot.net.Lib +namespace Geekbot.net.Lib.Logger { public class GeekbotLogger : IGeekbotLogger { @@ -21,6 +21,11 @@ namespace Geekbot.net.Lib Information("Geekbot", "Using GeekbotLogger"); } + public void Trace(string source, string message, object extra = null) + { + _logger.Trace(CreateLogString("Debug", source, message, null, extra)); + } + public void Debug(string source, string message, object extra = null) { _logger.Debug(CreateLogString("Debug", source, message, null, extra)); @@ -63,22 +68,4 @@ namespace Geekbot.net.Lib return $"[{source}] - [{m.Guild.Name} - {m.Channel.Name}] {m.User.Name}: {m.Message.Content}"; } } - - public class GeekbotLoggerObject - { - public DateTime Timestamp { get; set; } - public string Type { get; set; } - public string Source { get; set; } - public string Message { get; set; } - public Exception StackTrace { get; set; } - public object Extra { get; set; } - } - - public interface IGeekbotLogger - { - void Debug(string source, string message, object extra = null); - void Information(string source, string message, object extra = null); - void Warning(string source, string message, Exception stackTrace = null, object extra = null); - void Error(string source, string message, Exception stackTrace, object extra = null); - } } \ No newline at end of file diff --git a/Geekbot.net/Lib/Logger/IDiscordLogger.cs b/Geekbot.net/Lib/Logger/IDiscordLogger.cs new file mode 100644 index 0000000..fdc8c7f --- /dev/null +++ b/Geekbot.net/Lib/Logger/IDiscordLogger.cs @@ -0,0 +1,10 @@ +using System.Threading.Tasks; +using Discord; + +namespace Geekbot.net.Lib.Logger +{ + public interface IDiscordLogger + { + Task Log(LogMessage message); + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Logger/IGeekbotLogger.cs b/Geekbot.net/Lib/Logger/IGeekbotLogger.cs new file mode 100644 index 0000000..36d456d --- /dev/null +++ b/Geekbot.net/Lib/Logger/IGeekbotLogger.cs @@ -0,0 +1,13 @@ +using System; + +namespace Geekbot.net.Lib.Logger +{ + public interface IGeekbotLogger + { + void Trace(string source, string message, object extra = null); + void Debug(string source, string message, object extra = null); + void Information(string source, string message, object extra = null); + void Warning(string source, string message, Exception stackTrace = null, object extra = null); + void Error(string source, string message, Exception stackTrace, object extra = null); + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Logger/LogDto.cs b/Geekbot.net/Lib/Logger/LogDto.cs new file mode 100644 index 0000000..74695ec --- /dev/null +++ b/Geekbot.net/Lib/Logger/LogDto.cs @@ -0,0 +1,14 @@ +using System; + +namespace Geekbot.net.Lib.Logger +{ + public class GeekbotLoggerObject + { + public DateTime Timestamp { get; set; } + public string Type { get; set; } + public string Source { get; set; } + public string Message { get; set; } + public Exception StackTrace { get; set; } + public object Extra { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/LoggerFactory.cs b/Geekbot.net/Lib/Logger/LoggerFactory.cs similarity index 95% rename from Geekbot.net/Lib/LoggerFactory.cs rename to Geekbot.net/Lib/Logger/LoggerFactory.cs index b0b5060..53325a6 100644 --- a/Geekbot.net/Lib/LoggerFactory.cs +++ b/Geekbot.net/Lib/Logger/LoggerFactory.cs @@ -5,11 +5,11 @@ using NLog.Config; using NLog.Targets; using SumoLogic.Logging.NLog; -namespace Geekbot.net.Lib +namespace Geekbot.net.Lib.Logger { public class LoggerFactory { - public static Logger CreateNLog(RunParameters runParameters, bool sumologicActive) + public static NLog.Logger CreateNLog(RunParameters runParameters, bool sumologicActive) { var config = new LoggingConfiguration(); diff --git a/Geekbot.net/Lib/Logger/MessageDto.cs b/Geekbot.net/Lib/Logger/MessageDto.cs new file mode 100644 index 0000000..011acf3 --- /dev/null +++ b/Geekbot.net/Lib/Logger/MessageDto.cs @@ -0,0 +1,26 @@ +namespace Geekbot.net.Lib.Logger +{ + public class MessageDto + { + public MessageContent Message { get; set; } + public IdAndName User { get; set; } + public IdAndName Guild { get; set; } + public IdAndName Channel { get; set; } + + public class MessageContent + { + public string Content { get; set; } + public string Id { get; set; } + public int Attachments { get; set; } + public int ChannelMentions { get; set; } + public int UserMentions { get; set; } + public int RoleMentions { get; set; } + } + + public class IdAndName + { + public string Id { get; set; } + public string Name { get; set; } + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/SimpleConextConverter.cs b/Geekbot.net/Lib/Logger/SimpleConextConverter.cs similarity index 75% rename from Geekbot.net/Lib/SimpleConextConverter.cs rename to Geekbot.net/Lib/Logger/SimpleConextConverter.cs index ad029c7..4df802d 100644 --- a/Geekbot.net/Lib/SimpleConextConverter.cs +++ b/Geekbot.net/Lib/Logger/SimpleConextConverter.cs @@ -1,7 +1,7 @@ using Discord.Commands; using Discord.WebSocket; -namespace Geekbot.net.Lib +namespace Geekbot.net.Lib.Logger { public class SimpleConextConverter { @@ -68,29 +68,4 @@ namespace Geekbot.net.Lib } } - - - public class MessageDto - { - public MessageContent Message { get; set; } - public IdAndName User { get; set; } - public IdAndName Guild { get; set; } - public IdAndName Channel { get; set; } - - public class MessageContent - { - public string Content { get; set; } - public string Id { get; set; } - public int Attachments { get; set; } - public int ChannelMentions { get; set; } - public int UserMentions { get; set; } - public int RoleMentions { get; set; } - } - - public class IdAndName - { - public string Id { get; set; } - public string Name { get; set; } - } - } } \ No newline at end of file diff --git a/Geekbot.net/Lib/Media/FortunesProvider.cs b/Geekbot.net/Lib/Media/FortunesProvider.cs index 5988660..dc97199 100644 --- a/Geekbot.net/Lib/Media/FortunesProvider.cs +++ b/Geekbot.net/Lib/Media/FortunesProvider.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using Geekbot.net.Lib.Logger; namespace Geekbot.net.Lib.Media { @@ -16,7 +17,7 @@ namespace Geekbot.net.Lib.Media var rawFortunes = File.ReadAllText(path); _fortuneArray = rawFortunes.Split("%"); _totalFortunes = _fortuneArray.Length; - logger.Debug("Geekbot", "Loaded {totalFortunes} Fortunes"); + logger.Trace("Geekbot", $"Loaded {_totalFortunes} Fortunes"); } else { @@ -29,9 +30,4 @@ namespace Geekbot.net.Lib.Media return _fortuneArray[new Random().Next(0, _totalFortunes)]; } } - - public interface IFortunesProvider - { - string GetRandomFortune(); - } } \ No newline at end of file diff --git a/Geekbot.net/Lib/Media/IFortunesProvider.cs b/Geekbot.net/Lib/Media/IFortunesProvider.cs new file mode 100644 index 0000000..c82e45c --- /dev/null +++ b/Geekbot.net/Lib/Media/IFortunesProvider.cs @@ -0,0 +1,7 @@ +namespace Geekbot.net.Lib.Media +{ + public interface IFortunesProvider + { + string GetRandomFortune(); + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Media/IMediaProvider.cs b/Geekbot.net/Lib/Media/IMediaProvider.cs new file mode 100644 index 0000000..79c6c98 --- /dev/null +++ b/Geekbot.net/Lib/Media/IMediaProvider.cs @@ -0,0 +1,14 @@ +namespace Geekbot.net.Lib.Media +{ + public interface IMediaProvider + { + string GetCheckem(); + string GetPanda(); + string GetCrossant(); + string GetSquirrel(); + string GetPumpkin(); + string GetTurtle(); + string GetPinguin(); + string GetFox(); + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Media/MediaProvider.cs b/Geekbot.net/Lib/Media/MediaProvider.cs index 568f67d..8f28d0d 100644 --- a/Geekbot.net/Lib/Media/MediaProvider.cs +++ b/Geekbot.net/Lib/Media/MediaProvider.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using Geekbot.net.Lib.Logger; namespace Geekbot.net.Lib.Media { @@ -37,56 +38,56 @@ namespace Geekbot.net.Lib.Media { var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/checkEmPics")); _checkemImages = rawLinks.Split("\n"); - _logger.Debug("Geekbot", $"Loaded {_checkemImages.Length} CheckEm Images"); + _logger.Trace("Geekbot", $"Loaded {_checkemImages.Length} CheckEm Images"); } private void LoadPandas() { var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/pandas")); _pandaImages = rawLinks.Split("\n"); - _logger.Debug("Geekbot", $"Loaded {_pandaImages.Length} Panda Images"); + _logger.Trace("Geekbot", $"Loaded {_pandaImages.Length} Panda Images"); } private void BakeCroissants() { var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/croissant")); _croissantImages = rawLinks.Split("\n"); - _logger.Debug("Geekbot", $"Loaded {_croissantImages.Length} Croissant Images"); + _logger.Trace("Geekbot", $"Loaded {_croissantImages.Length} Croissant Images"); } private void LoadSquirrels() { var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/squirrel")); _squirrelImages = rawLinks.Split("\n"); - _logger.Debug("Geekbot", $"Loaded {_squirrelImages.Length} Squirrel Images"); + _logger.Trace("Geekbot", $"Loaded {_squirrelImages.Length} Squirrel Images"); } private void LoadPumpkins() { var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/pumpkin")); _pumpkinImages = rawLinks.Split("\n"); - _logger.Debug("Geekbot", $"Loaded {_pumpkinImages.Length} Pumpkin Images"); + _logger.Trace("Geekbot", $"Loaded {_pumpkinImages.Length} Pumpkin Images"); } private void LoadTurtles() { var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/turtles")); _turtlesImages = rawLinks.Split("\n"); - _logger.Debug("Geekbot", $"Loaded {_turtlesImages.Length} Turtle Images"); + _logger.Trace("Geekbot", $"Loaded {_turtlesImages.Length} Turtle Images"); } private void LoadPinguins() { var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/pinguins")); _pinguinImages = rawLinks.Split("\n"); - _logger.Debug("Geekbot", $"Loaded {_pinguinImages.Length} Pinguin Images"); + _logger.Trace("Geekbot", $"Loaded {_pinguinImages.Length} Pinguin Images"); } private void LoadFoxes() { var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/foxes")); _foxImages = rawLinks.Split("\n"); - _logger.Debug("Geekbot", $"Loaded {_foxImages.Length} Foxes Images"); + _logger.Trace("Geekbot", $"Loaded {_foxImages.Length} Foxes Images"); } public string GetCheckem() @@ -129,16 +130,4 @@ namespace Geekbot.net.Lib.Media return _foxImages[_random.Next(0, _foxImages.Length)]; } } - - public interface IMediaProvider - { - string GetCheckem(); - string GetPanda(); - string GetCrossant(); - string GetSquirrel(); - string GetPumpkin(); - string GetTurtle(); - string GetPinguin(); - string GetFox(); - } } \ No newline at end of file diff --git a/Geekbot.net/Lib/MtgManaConverter.cs b/Geekbot.net/Lib/MtgManaConverter.cs deleted file mode 100644 index 83b6767..0000000 --- a/Geekbot.net/Lib/MtgManaConverter.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System.Collections.Generic; -using System.Text.RegularExpressions; - -namespace Geekbot.net.Lib -{ - public class MtgManaConverter : IMtgManaConverter - { - private Dictionary _manaDict; - - public MtgManaConverter() - { - // these emotes can be found at https://discord.gg/bz8HyA7 - - var manaDict = new Dictionary(); - manaDict.Add("{0}", "<:mtg_0:415216130043412482>"); - manaDict.Add("{1}", "<:mtg_1:415216130253389835>"); - manaDict.Add("{2}", "<:mtg_2:415216130031091713>"); - manaDict.Add("{3}", "<:mtg_3:415216130467037194>"); - manaDict.Add("{4}", "<:mtg_4:415216130026635295>"); - manaDict.Add("{5}", "<:mtg_5:415216130492203008>"); - manaDict.Add("{6}", "<:mtg_6:415216130458779658>"); - manaDict.Add("{7}", "<:mtg_7:415216130190475265>"); - manaDict.Add("{8}", "<:mtg_8:415216130517630986>"); - manaDict.Add("{9}", "<:mtg_9:415216130500722689>"); - manaDict.Add("{10", "<:mtg_10:415216130450391051>"); - manaDict.Add("{11}", "<:mtg_11:415216130811101185>"); - manaDict.Add("{12}", "<:mtg_12:415216130525888532>"); - manaDict.Add("{13}", "<:mtg_13:415216130517631000>"); - manaDict.Add("{14}", "<:mtg_14:415216130165178370>"); - manaDict.Add("{15}", "<:mtg_15:415216130576089108>"); - manaDict.Add("{16}", "<:mtg_16:415216130358247425>"); - manaDict.Add("{17}", "<:mtg_17:415216130601517056>"); - manaDict.Add("{18}", "<:mtg_18:415216130462842891>"); - manaDict.Add("{19}", "<:mtg_19:415216130614099988>"); - manaDict.Add("{20}", "<:mtg_20:415216130656043038>"); - manaDict.Add("{W}", "<:mtg_white:415216131515744256>"); - manaDict.Add("{U}", "<:mtg_blue:415216130521694209>"); - manaDict.Add("{B}", "<:mtg_black:415216130873884683>"); - manaDict.Add("{R}", "<:mtg_red:415216131322806272>"); - manaDict.Add("{G}", "<:mtg_green:415216131180331009>"); - manaDict.Add("{S}", "<:mtg_s:415216131293446144>"); - manaDict.Add("{T}", "<:mtg_tap:415258392727257088>"); - manaDict.Add("{C}", "<:mtg_colorless:415216130706374666>"); - manaDict.Add("{2/W}", "<:mtg_2w:415216130446065664>"); - manaDict.Add("{2/U}", "<:mtg_2u:415216130429550592>"); - manaDict.Add("{2/B}", "<:mtg_2b:415216130160984065>"); - manaDict.Add("{2/R}", "<:mtg_2r:415216130454716436>"); - manaDict.Add("{2/G}", "<:mtg_2g:415216130420899840>"); - manaDict.Add("{W/U}", "<:mtg_wu:415216130970484736>"); - manaDict.Add("{W/B}", "<:mtg_wb:415216131222011914>"); - manaDict.Add("{U/R}", "<:mtg_ur:415216130962096128>"); - manaDict.Add("{U/B}", "<:mtg_ub:415216130865758218>"); - manaDict.Add("{R/W}", "<:mtg_rw:415216130878210057>"); - manaDict.Add("{G/W}", "<:mtg_gw:415216130567962646>"); - manaDict.Add("{G/U}", "<:mtg_gu:415216130739666945>"); - manaDict.Add("{B/R}", "<:mtg_br:415216130580283394>"); - manaDict.Add("{B/G}", "<:mtg_bg:415216130781609994>"); - manaDict.Add("{U/P}", "<:mtg_up:415216130861432842>"); - manaDict.Add("{R/P}", "<:mtg_rp:415216130597322783>"); - manaDict.Add("{G/P}", "<:mtg_gp:415216130760769546>"); - manaDict.Add("{W/P}", "<:mtg_wp:415216131541041172>"); - manaDict.Add("{B/P}", "<:mtg_bp:415216130664169482>"); - - _manaDict = manaDict; - } - - public string ConvertMana(string mana) - { - var rgx = Regex.Matches(mana, @"(\{(.*?)\})"); - foreach (Match manaTypes in rgx) - { - var m = _manaDict.GetValueOrDefault(manaTypes.Value); - if (!string.IsNullOrEmpty(m)) - { - mana = mana.Replace(manaTypes.Value, m); - } - } - return mana; - } - } - - public interface IMtgManaConverter - { - string ConvertMana(string mana); - } -} \ No newline at end of file diff --git a/Geekbot.net/Lib/ReactionListener/IReactionListener.cs b/Geekbot.net/Lib/ReactionListener/IReactionListener.cs new file mode 100644 index 0000000..792a516 --- /dev/null +++ b/Geekbot.net/Lib/ReactionListener/IReactionListener.cs @@ -0,0 +1,14 @@ +using System.Threading.Tasks; +using Discord; +using Discord.WebSocket; + +namespace Geekbot.net.Lib.ReactionListener +{ + public interface IReactionListener + { + bool IsListener(ulong id); + Task AddRoleToListener(string messageId, IEmote emoji, IRole role); + void RemoveRole(ISocketMessageChannel channel, SocketReaction reaction); + void GiveRole(ISocketMessageChannel message, SocketReaction reaction); + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/ReactionListener.cs b/Geekbot.net/Lib/ReactionListener/ReactionListener.cs similarity index 87% rename from Geekbot.net/Lib/ReactionListener.cs rename to Geekbot.net/Lib/ReactionListener/ReactionListener.cs index f837280..950edd1 100644 --- a/Geekbot.net/Lib/ReactionListener.cs +++ b/Geekbot.net/Lib/ReactionListener/ReactionListener.cs @@ -5,7 +5,7 @@ using Discord; using Discord.WebSocket; using StackExchange.Redis; -namespace Geekbot.net.Lib +namespace Geekbot.net.Lib.ReactionListener { public class ReactionListener : IReactionListener { @@ -87,12 +87,4 @@ namespace Geekbot.net.Lib await ((IGuildUser) reaction.User.Value).AddRoleAsync(role); } } - - public interface IReactionListener - { - bool IsListener(ulong id); - Task AddRoleToListener(string messageId, IEmote emoji, IRole role); - void RemoveRole(ISocketMessageChannel channel, SocketReaction reaction); - void GiveRole(ISocketMessageChannel message, SocketReaction reaction); - } } \ No newline at end of file diff --git a/Geekbot.net/Lib/UserRepository/IUserRepository.cs b/Geekbot.net/Lib/UserRepository/IUserRepository.cs new file mode 100644 index 0000000..9466621 --- /dev/null +++ b/Geekbot.net/Lib/UserRepository/IUserRepository.cs @@ -0,0 +1,13 @@ +using System.Threading.Tasks; +using Discord.WebSocket; + +namespace Geekbot.net.Lib.UserRepository +{ + public interface IUserRepository + { + Task Update(SocketUser user); + UserRepositoryUser Get(ulong userId); + string GetUserSetting(ulong userId, string setting); + bool SaveUserSetting(ulong userId, string setting, string value); + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/UserRepository.cs b/Geekbot.net/Lib/UserRepository/UserRepository.cs similarity index 84% rename from Geekbot.net/Lib/UserRepository.cs rename to Geekbot.net/Lib/UserRepository/UserRepository.cs index 28d0541..558732e 100644 --- a/Geekbot.net/Lib/UserRepository.cs +++ b/Geekbot.net/Lib/UserRepository/UserRepository.cs @@ -2,10 +2,11 @@ using System.Collections.Generic; using System.Threading.Tasks; using Discord.WebSocket; +using Geekbot.net.Lib.Logger; using StackExchange.Redis; using Utf8Json; -namespace Geekbot.net.Lib +namespace Geekbot.net.Lib.UserRepository { public class UserRepository : IUserRepository { @@ -121,23 +122,4 @@ namespace Geekbot.net.Lib return true; } } - - public class UserRepositoryUser - { - public ulong Id { get; set; } - public string Username { get; set; } - public string Discriminator { get; set; } - public string AvatarUrl { get; set; } - public bool IsBot { get; set; } - public DateTimeOffset Joined { get; set; } - public List UsedNames { get; set; } - } - - public interface IUserRepository - { - Task Update(SocketUser user); - UserRepositoryUser Get(ulong userId); - string GetUserSetting(ulong userId, string setting); - bool SaveUserSetting(ulong userId, string setting, string value); - } } \ No newline at end of file diff --git a/Geekbot.net/Lib/UserRepository/UserRepositoryUserDto.cs b/Geekbot.net/Lib/UserRepository/UserRepositoryUserDto.cs new file mode 100644 index 0000000..4af719b --- /dev/null +++ b/Geekbot.net/Lib/UserRepository/UserRepositoryUserDto.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; + +namespace Geekbot.net.Lib.UserRepository +{ + public class UserRepositoryUser + { + public ulong Id { get; set; } + public string Username { get; set; } + public string Discriminator { get; set; } + public string AvatarUrl { get; set; } + public bool IsBot { get; set; } + public DateTimeOffset Joined { get; set; } + public List UsedNames { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 3c0e5eb..f5f878a 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -8,7 +8,15 @@ using Discord; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Lib; +using Geekbot.net.Lib.Clients; +using Geekbot.net.Lib.Converters; +using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Levels; +using Geekbot.net.Lib.Localization; +using Geekbot.net.Lib.Logger; using Geekbot.net.Lib.Media; +using Geekbot.net.Lib.ReactionListener; +using Geekbot.net.Lib.UserRepository; using Microsoft.Extensions.DependencyInjection; using Nancy.Hosting.Self; using StackExchange.Redis; @@ -24,7 +32,7 @@ namespace Geekbot.net private IServiceCollection _services; private IServiceProvider _servicesProvider; private RedisValue _token; - private IGeekbotLogger _logger; + private GeekbotLogger _logger; private IUserRepository _userRepository; private bool _firstStart; private RunParameters _runParameters; @@ -57,18 +65,19 @@ namespace Geekbot.net } } - private async Task MainAsync(RunParameters runParameters, IGeekbotLogger logger) + private async Task MainAsync(RunParameters runParameters, GeekbotLogger logger) { _logger = logger; _runParameters = runParameters; logger.Information("Geekbot", "Initing Stuff"); + var discordLogger = new DiscordLogger(logger); _client = new DiscordSocketClient(new DiscordSocketConfig { LogLevel = LogSeverity.Verbose, MessageCacheSize = 1000 }); - _client.Log += DiscordLogger; + _client.Log += discordLogger.Log; _commands = new CommandService(); try @@ -218,30 +227,5 @@ namespace Geekbot.net } return Task.CompletedTask; } - - private Task DiscordLogger(LogMessage message) - { - var logMessage = $"[{message.Source}] {message.Message}"; - switch (message.Severity) - { - case LogSeverity.Verbose: - case LogSeverity.Debug: - _logger.Debug(message.Source, message.Message); - break; - case LogSeverity.Info: - _logger.Information(message.Source, message.Message); - break; - case LogSeverity.Critical: - case LogSeverity.Error: - case LogSeverity.Warning: - if (logMessage.Contains("VOICE_STATE_UPDATE")) break; - _logger.Error(message.Source, message.Message, message.Exception); - break; - default: - _logger.Information(message.Source, $"{logMessage} --- {message.Severity}"); - break; - } - return Task.CompletedTask; - } } } \ No newline at end of file diff --git a/Geekbot.net/WebApi/Help/CommandDto.cs b/Geekbot.net/WebApi/Help/CommandDto.cs new file mode 100644 index 0000000..5921fa6 --- /dev/null +++ b/Geekbot.net/WebApi/Help/CommandDto.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; + +namespace Geekbot.net.WebApi.Help +{ + public class CommandDto + { + public string Name { get; set; } + public string Category { get; set; } + public string Summary { get; set; } + public bool IsAdminCommand { get; set; } + public Array Aliases { get; set; } + public List Params { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/WebApi/Help/CommandParamDto.cs b/Geekbot.net/WebApi/Help/CommandParamDto.cs new file mode 100644 index 0000000..f7ce0ea --- /dev/null +++ b/Geekbot.net/WebApi/Help/CommandParamDto.cs @@ -0,0 +1,9 @@ +namespace Geekbot.net.WebApi.Help +{ + public class CommandParamDto + { + public string Summary { get; set; } + public string Default { get; set; } + public string Type { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/WebApi/HelpController.cs b/Geekbot.net/WebApi/Help/HelpController.cs similarity index 70% rename from Geekbot.net/WebApi/HelpController.cs rename to Geekbot.net/WebApi/Help/HelpController.cs index 060dea0..d71d26f 100644 --- a/Geekbot.net/WebApi/HelpController.cs +++ b/Geekbot.net/WebApi/Help/HelpController.cs @@ -1,13 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System.Linq; using System.Reflection; using System.Threading.Tasks; using Discord.Commands; using Geekbot.net.Lib; using Nancy; -namespace Geekbot.net.WebApi +namespace Geekbot.net.WebApi.Help { public class HelpController : NancyModule { @@ -47,21 +45,4 @@ namespace Geekbot.net.WebApi return commands; } } - - public class CommandDto - { - public string Name { get; set; } - public string Category { get; set; } - public string Summary { get; set; } - public bool IsAdminCommand { get; set; } - public Array Aliases { get; set; } - public List Params { get; set; } - } - - public class CommandParamDto - { - public string Summary { get; set; } - public string Default { get; set; } - public string Type { get; set; } - } } \ No newline at end of file diff --git a/Geekbot.net/WebApi/Status/ApiStatusDto.cs b/Geekbot.net/WebApi/Status/ApiStatusDto.cs new file mode 100644 index 0000000..242bf58 --- /dev/null +++ b/Geekbot.net/WebApi/Status/ApiStatusDto.cs @@ -0,0 +1,9 @@ +namespace Geekbot.net.WebApi.Status +{ + public class ApiStatusDto + { + public string GeekbotVersion { get; set; } + public string ApiVersion { get; set; } + public string Status { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/WebApi/StatusController.cs b/Geekbot.net/WebApi/Status/StatusController.cs similarity index 71% rename from Geekbot.net/WebApi/StatusController.cs rename to Geekbot.net/WebApi/Status/StatusController.cs index b785e07..5f995c9 100644 --- a/Geekbot.net/WebApi/StatusController.cs +++ b/Geekbot.net/WebApi/Status/StatusController.cs @@ -1,7 +1,7 @@ using Geekbot.net.Lib; using Nancy; -namespace Geekbot.net.WebApi +namespace Geekbot.net.WebApi.Status { public class StatusController : NancyModule { @@ -19,11 +19,4 @@ namespace Geekbot.net.WebApi }); } } - - public class ApiStatusDto - { - public string GeekbotVersion { get; set; } - public string ApiVersion { get; set; } - public string Status { get; set; } - } } \ No newline at end of file diff --git a/Tests/Lib/EmojiConverter.test.cs b/Tests/Lib/EmojiConverter.test.cs index 4bfcf06..aaaaa8f 100644 --- a/Tests/Lib/EmojiConverter.test.cs +++ b/Tests/Lib/EmojiConverter.test.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Geekbot.net.Lib; +using Geekbot.net.Lib.Converters; using Xunit; namespace Tests.Lib diff --git a/Tests/Lib/LevelCalc.test.cs b/Tests/Lib/LevelCalc.test.cs index ecca151..4b6b095 100644 --- a/Tests/Lib/LevelCalc.test.cs +++ b/Tests/Lib/LevelCalc.test.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Geekbot.net.Lib; +using Geekbot.net.Lib.Levels; using Xunit; namespace Tests.Lib From 0828130ae8d7879409cba3794cea5482cbe5bce7 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 3 May 2018 21:20:49 +0200 Subject: [PATCH 150/553] Fixes --- Geekbot.net/Commands/Integrations/Google/Google.cs | 4 ++-- Geekbot.net/Commands/User/{Rank => Ranking}/Rank.cs | 5 ++--- .../User/{Rank => Ranking}/RankUserPolyfillDto.cs | 2 +- .../Commands/Utils/Changelog/CommitAuthorDto.cs | 2 +- Geekbot.net/Commands/Utils/Changelog/CommitDto.cs | 2 +- .../Commands/Utils/Changelog/CommitInfoDto.cs | 2 +- Geekbot.net/Lib/Logger/GeekbotLogger.cs | 4 ++-- Geekbot.net/Lib/Logger/LoggerFactory.cs | 12 ++++++------ 8 files changed, 16 insertions(+), 17 deletions(-) rename Geekbot.net/Commands/User/{Rank => Ranking}/Rank.cs (95%) rename Geekbot.net/Commands/User/{Rank => Ranking}/RankUserPolyfillDto.cs (77%) diff --git a/Geekbot.net/Commands/Integrations/Google/Google.cs b/Geekbot.net/Commands/Integrations/Google/Google.cs index 8e880c4..631bbe3 100644 --- a/Geekbot.net/Commands/Integrations/Google/Google.cs +++ b/Geekbot.net/Commands/Integrations/Google/Google.cs @@ -6,8 +6,8 @@ using Discord; using Discord.Commands; using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; +using Newtonsoft.Json; using StackExchange.Redis; -using Utf8Json; namespace Geekbot.net.Commands.Integrations.Google { @@ -40,7 +40,7 @@ namespace Geekbot.net.Commands.Integrations.Google var url = new Uri($"https://kgsearch.googleapis.com/v1/entities:search?languages=en&limit=1&query={searchText}&key={apiKey}"); var responseString = client.DownloadString(url); - var response = JsonSerializer.Deserialize(responseString); + var response = JsonConvert.DeserializeObject(responseString); if (!response.ItemListElement.Any()) { diff --git a/Geekbot.net/Commands/User/Rank/Rank.cs b/Geekbot.net/Commands/User/Ranking/Rank.cs similarity index 95% rename from Geekbot.net/Commands/User/Rank/Rank.cs rename to Geekbot.net/Commands/User/Ranking/Rank.cs index 774ac5a..590921e 100644 --- a/Geekbot.net/Commands/User/Rank/Rank.cs +++ b/Geekbot.net/Commands/User/Ranking/Rank.cs @@ -12,7 +12,7 @@ using Geekbot.net.Lib.Logger; using Geekbot.net.Lib.UserRepository; using StackExchange.Redis; -namespace Geekbot.net.Commands.User.Rank +namespace Geekbot.net.Commands.User.Ranking { public class Rank : ModuleBase { @@ -37,8 +37,7 @@ namespace Geekbot.net.Commands.User.Rank [Command("rank", RunMode = RunMode.Async)] [Remarks(CommandCategories.Statistics)] [Summary("get user top 10 in messages or karma")] - public async Task RankCmd([Summary("type")] string typeUnformated = "messages", - [Summary("amount")] int amount = 10) + public async Task RankCmd([Summary("type")] string typeUnformated = "messages", [Summary("amount")] int amount = 10) { try { diff --git a/Geekbot.net/Commands/User/Rank/RankUserPolyfillDto.cs b/Geekbot.net/Commands/User/Ranking/RankUserPolyfillDto.cs similarity index 77% rename from Geekbot.net/Commands/User/Rank/RankUserPolyfillDto.cs rename to Geekbot.net/Commands/User/Ranking/RankUserPolyfillDto.cs index f666ffc..625c326 100644 --- a/Geekbot.net/Commands/User/Rank/RankUserPolyfillDto.cs +++ b/Geekbot.net/Commands/User/Ranking/RankUserPolyfillDto.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Commands.User.Rank +namespace Geekbot.net.Commands.User.Ranking { internal class RankUserPolyfillDto { diff --git a/Geekbot.net/Commands/Utils/Changelog/CommitAuthorDto.cs b/Geekbot.net/Commands/Utils/Changelog/CommitAuthorDto.cs index ad37311..53881d5 100644 --- a/Geekbot.net/Commands/Utils/Changelog/CommitAuthorDto.cs +++ b/Geekbot.net/Commands/Utils/Changelog/CommitAuthorDto.cs @@ -2,7 +2,7 @@ namespace Geekbot.net.Commands.Utils.Changelog { - internal class CommitAuthorDto + public class CommitAuthorDto { public DateTimeOffset Date { get; set; } } diff --git a/Geekbot.net/Commands/Utils/Changelog/CommitDto.cs b/Geekbot.net/Commands/Utils/Changelog/CommitDto.cs index d5c5bab..3379697 100644 --- a/Geekbot.net/Commands/Utils/Changelog/CommitDto.cs +++ b/Geekbot.net/Commands/Utils/Changelog/CommitDto.cs @@ -1,6 +1,6 @@ namespace Geekbot.net.Commands.Utils.Changelog { - internal class CommitDto + public class CommitDto { public CommitInfoDto Commit { get; set; } } diff --git a/Geekbot.net/Commands/Utils/Changelog/CommitInfoDto.cs b/Geekbot.net/Commands/Utils/Changelog/CommitInfoDto.cs index 102d2cd..743ca52 100644 --- a/Geekbot.net/Commands/Utils/Changelog/CommitInfoDto.cs +++ b/Geekbot.net/Commands/Utils/Changelog/CommitInfoDto.cs @@ -1,6 +1,6 @@ namespace Geekbot.net.Commands.Utils.Changelog { - internal class CommitInfoDto + public class CommitInfoDto { public CommitAuthorDto AuthorDto { get; set; } public string Message { get; set; } diff --git a/Geekbot.net/Lib/Logger/GeekbotLogger.cs b/Geekbot.net/Lib/Logger/GeekbotLogger.cs index 8cefdb4..c1ceb38 100644 --- a/Geekbot.net/Lib/Logger/GeekbotLogger.cs +++ b/Geekbot.net/Lib/Logger/GeekbotLogger.cs @@ -23,7 +23,7 @@ namespace Geekbot.net.Lib.Logger public void Trace(string source, string message, object extra = null) { - _logger.Trace(CreateLogString("Debug", source, message, null, extra)); + _logger.Trace(CreateLogString("Trace", source, message, null, extra)); } public void Debug(string source, string message, object extra = null) @@ -65,7 +65,7 @@ namespace Geekbot.net.Lib.Logger if (source != "Message") return $"[{source}] - {message}"; var m = (MessageDto) extra; - return $"[{source}] - [{m.Guild.Name} - {m.Channel.Name}] {m.User.Name}: {m.Message.Content}"; + return $"[{source}] - [{m?.Guild.Name} - {m?.Channel.Name}] {m?.User.Name}: {m?.Message.Content}"; } } } \ No newline at end of file diff --git a/Geekbot.net/Lib/Logger/LoggerFactory.cs b/Geekbot.net/Lib/Logger/LoggerFactory.cs index 53325a6..491197c 100644 --- a/Geekbot.net/Lib/Logger/LoggerFactory.cs +++ b/Geekbot.net/Lib/Logger/LoggerFactory.cs @@ -17,20 +17,20 @@ namespace Geekbot.net.Lib.Logger { Console.WriteLine("Logging Geekbot Logs to Sumologic"); config.LoggingRules.Add( - new LoggingRule("*", LogLevel.Info, LogLevel.Fatal, + new LoggingRule("*", LogLevel.Debug, LogLevel.Fatal, new BufferedSumoLogicTarget() { Url = Environment.GetEnvironmentVariable("GEEKBOT_SUMO"), SourceName = "GeekbotLogger", Layout = "${message}", - UseConsoleLog = false, + UseConsoleLog = true, MaxQueueSizeBytes = 500000, FlushingAccuracy = 250, MaxFlushInterval = 10000, OptimizeBufferReuse = true, MessagesPerRequest = 10, RetryInterval = 5000, - Name = "Geekbot" + Name = "GeekbotBeta" }) ); } @@ -38,11 +38,11 @@ namespace Geekbot.net.Lib.Logger { var minLevel = runParameters.Verbose ? LogLevel.Trace : LogLevel.Info; config.LoggingRules.Add( - new LoggingRule("*", minLevel, LogLevel.Fatal, + new LoggingRule("*", LogLevel.Info, LogLevel.Fatal, new ColoredConsoleTarget { Name = "Console", - Encoding = Encoding.Unicode, + Encoding = Encoding.UTF8, Layout = "[${longdate} ${level:format=FirstCharacter}] ${message} ${exception:format=toString}" }) ); @@ -53,7 +53,7 @@ namespace Geekbot.net.Lib.Logger { Name = "File", Layout = "[${longdate} ${level}] ${message}", - Encoding = Encoding.Unicode, + Encoding = Encoding.UTF8, LineEnding = LineEndingMode.Default, MaxArchiveFiles = 30, ArchiveNumbering = ArchiveNumberingMode.Date, From 8599c815d7743e3817f60793e9555606bea66a61 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 4 May 2018 00:54:01 +0200 Subject: [PATCH 151/553] Add audio stuff back --- Geekbot.net/Commands/Audio/Voice.cs | 103 +++++++++++++++++++++++++++ Geekbot.net/Lib/Audio/AudioUtils.cs | 96 +++++++++++++++++++++++++ Geekbot.net/Lib/Audio/IAudioUtils.cs | 15 ++++ Geekbot.net/Program.cs | 3 + 4 files changed, 217 insertions(+) create mode 100644 Geekbot.net/Commands/Audio/Voice.cs create mode 100644 Geekbot.net/Lib/Audio/AudioUtils.cs create mode 100644 Geekbot.net/Lib/Audio/IAudioUtils.cs diff --git a/Geekbot.net/Commands/Audio/Voice.cs b/Geekbot.net/Commands/Audio/Voice.cs new file mode 100644 index 0000000..e8f3134 --- /dev/null +++ b/Geekbot.net/Commands/Audio/Voice.cs @@ -0,0 +1,103 @@ +using System; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Geekbot.net.Lib.Audio; +using Geekbot.net.Lib.ErrorHandling; + +namespace Geekbot.net.Commands.Audio +{ + public class Voice : ModuleBase + { + private readonly IAudioUtils _audioUtils; + private readonly IErrorHandler _errorHandler; + + public Voice(IErrorHandler errorHandler, IAudioUtils audioUtils) + { + _errorHandler = errorHandler; + _audioUtils = audioUtils; + } + + [Command("join")] + public async Task JoinChannel() + { + try + { + // Get the audio channel + var channel = (Context.User as IGuildUser)?.VoiceChannel; + if (channel == null) + { + await Context.Channel.SendMessageAsync( + "User must be in a voice channel, or a voice channel must be passed as an argument."); + return; + } + + // For the next step with transmitting audio, you would want to pass this Audio Client in to a service. + var audioClient = await channel.ConnectAsync(); + _audioUtils.StoreAudioClient(Context.Guild.Id, audioClient); + await ReplyAsync($"Connected to {channel.Name}"); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + [Command("disconnect")] + public async Task DisconnectChannel() + { + try + { + var audioClient = _audioUtils.GetAudioClient(Context.Guild.Id); + if (audioClient == null) + { + await Context.Channel.SendMessageAsync("I'm not in a voice channel at the moment"); + return; + } + + await audioClient.StopAsync(); + await ReplyAsync("Disconnected from channel!"); + _audioUtils.Cleanup(Context.Guild.Id); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + _audioUtils.Cleanup(Context.Guild.Id); + } + } + + [Command("ytplay")] + public async Task ytplay(string url) + { + try + { + if (!url.Contains("youtube")) + { + await ReplyAsync("I can only play youtube videos"); + return; + } + var audioClient = _audioUtils.GetAudioClient(Context.Guild.Id); + if (audioClient == null) + { + await ReplyAsync("I'm not in a voice channel at the moment"); + return; + } + + var message = await Context.Channel.SendMessageAsync("Just a second, i'm still a bit slow at this"); + var ffmpeg = _audioUtils.CreateStreamFromYoutube(url, Context.Guild.Id); + var output = ffmpeg.StandardOutput.BaseStream; + await message.ModifyAsync(msg => msg.Content = "**Playing!** Please note that this feature is experimental"); + var discord = audioClient.CreatePCMStream(Discord.Audio.AudioApplication.Mixed); + await output.CopyToAsync(discord); + await discord.FlushAsync(); + _audioUtils.Cleanup(Context.Guild.Id); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + _audioUtils.Cleanup(Context.Guild.Id); + } + } + } + +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Audio/AudioUtils.cs b/Geekbot.net/Lib/Audio/AudioUtils.cs new file mode 100644 index 0000000..024019d --- /dev/null +++ b/Geekbot.net/Lib/Audio/AudioUtils.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Net; +using Discord.Audio; + +namespace Geekbot.net.Lib.Audio +{ + public class AudioUtils : IAudioUtils + { + private string _tempFolderPath; + private Dictionary _audioClients; + + public AudioUtils() + { + _audioClients = new Dictionary(); + _tempFolderPath = Path.GetFullPath("./tmp/"); + if (Directory.Exists(_tempFolderPath)) + { + Directory.Delete(_tempFolderPath, true); + } + Directory.CreateDirectory(_tempFolderPath); + } + + public IAudioClient GetAudioClient(ulong guildId) + { + return _audioClients[guildId]; + } + + public void StoreAudioClient(ulong guildId, IAudioClient client) + { + _audioClients[guildId] = client; + } + + public Process CreateStreamFromFile(string path) + { + var ffmpeg = new ProcessStartInfo + { + FileName = "ffmpeg", + Arguments = $"-i {path} -ac 2 -f s16le -ar 48000 pipe:1", + UseShellExecute = false, + RedirectStandardOutput = true, + }; + return Process.Start(ffmpeg); + } + + public Process CreateStreamFromYoutube(string url, ulong guildId) + { + var ytdlMediaUrl = GetYoutubeMediaUrl(url); + DownloadMediaUrl(ytdlMediaUrl, guildId); + return CreateStreamFromFile($"{_tempFolderPath}{guildId}"); + } + + public void Cleanup(ulong guildId) + { + File.Delete($"{_tempFolderPath}{guildId}"); + } + + private string GetYoutubeMediaUrl(string url) + { + var ytdl = new ProcessStartInfo() + { + FileName = "youtube-dl", + Arguments = $"-f bestaudio -g {url}", + UseShellExecute = false, + RedirectStandardOutput = true + }; + var output = Process.Start(ytdl).StandardOutput.ReadToEnd(); + if (string.IsNullOrWhiteSpace(output)) + { + throw new Exception("Could not get Youtube Media URL"); + } + return output; + } + + private void DownloadMediaUrl(string url, ulong guildId) + { + using (var web = new WebClient()) + { + web.DownloadFile(url, $"{_tempFolderPath}{guildId}"); + } +// var ffmpeg = new ProcessStartInfo +// { +// FileName = "ffmpeg", +// Arguments = $"-i \"{_tempFolderPath}{guildId}\" -c:a mp3 -b:a 256k {_tempFolderPath}{guildId}.mp3", +// UseShellExecute = false, +// RedirectStandardOutput = true, +// }; +// Process.Start(ffmpeg).WaitForExit(); +// File.Delete($"{_tempFolderPath}{guildId}"); + return; + } + + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Audio/IAudioUtils.cs b/Geekbot.net/Lib/Audio/IAudioUtils.cs new file mode 100644 index 0000000..4af1293 --- /dev/null +++ b/Geekbot.net/Lib/Audio/IAudioUtils.cs @@ -0,0 +1,15 @@ +using System.Diagnostics; +using Discord.Audio; + +namespace Geekbot.net.Lib.Audio +{ + public interface IAudioUtils + { + IAudioClient GetAudioClient(ulong guildId); + void StoreAudioClient(ulong guildId, IAudioClient client); + Process CreateStreamFromFile(string path); + Process CreateStreamFromYoutube(string url, ulong guildId); + void Cleanup(ulong guildId); + + } +} \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index f5f878a..8268833 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -8,6 +8,7 @@ using Discord; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Lib; +using Geekbot.net.Lib.Audio; using Geekbot.net.Lib.Clients; using Geekbot.net.Lib.Converters; using Geekbot.net.Lib.ErrorHandling; @@ -113,6 +114,7 @@ namespace Geekbot.net var emojiConverter = new EmojiConverter(); var mtgManaConverter = new MtgManaConverter(); var wikipediaClient = new WikipediaClient(); + var audioUtils = new AudioUtils(); _services.AddSingleton(_redis); _services.AddSingleton(logger); @@ -124,6 +126,7 @@ namespace Geekbot.net _services.AddSingleton(malClient); _services.AddSingleton(mtgManaConverter); _services.AddSingleton(wikipediaClient); + _services.AddSingleton(audioUtils); logger.Information("Geekbot", "Connecting to Discord"); From 290b85fdb6ff9b480b0922ef684662056be1f0d3 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 4 May 2018 00:55:32 +0200 Subject: [PATCH 152/553] Fix !changelog, fix bug in logger and typo in !mod namehistory --- Geekbot.net/Commands/Admin/Mod.cs | 2 +- Geekbot.net/Commands/Utils/Changelog/Changelog.cs | 2 +- Geekbot.net/Commands/Utils/Changelog/CommitAuthorDto.cs | 2 ++ Geekbot.net/Commands/Utils/Changelog/CommitInfoDto.cs | 2 +- Geekbot.net/Lib/Logger/GeekbotLogger.cs | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Geekbot.net/Commands/Admin/Mod.cs b/Geekbot.net/Commands/Admin/Mod.cs index 2dacee3..6f79157 100644 --- a/Geekbot.net/Commands/Admin/Mod.cs +++ b/Geekbot.net/Commands/Admin/Mod.cs @@ -47,7 +47,7 @@ namespace Geekbot.net.Commands.Admin catch (Exception e) { _errorHandler.HandleCommandException(e, Context, - $"I don't have enough permissions to give {user.Username} that role"); + $"I don't have enough permissions do that"); } } diff --git a/Geekbot.net/Commands/Utils/Changelog/Changelog.cs b/Geekbot.net/Commands/Utils/Changelog/Changelog.cs index f956d7c..f1752f7 100644 --- a/Geekbot.net/Commands/Utils/Changelog/Changelog.cs +++ b/Geekbot.net/Commands/Utils/Changelog/Changelog.cs @@ -52,7 +52,7 @@ namespace Geekbot.net.Commands.Utils.Changelog }); var sb = new StringBuilder(); foreach (var commit in commits.Take(10)) - sb.AppendLine($"- {commit.Commit.Message} ({commit.Commit.AuthorDto.Date:yyyy-MM-dd})"); + sb.AppendLine($"- {commit.Commit.Message} ({commit.Commit.Author.Date:yyyy-MM-dd})"); eb.Description = sb.ToString(); eb.WithFooter(new EmbedFooterBuilder { diff --git a/Geekbot.net/Commands/Utils/Changelog/CommitAuthorDto.cs b/Geekbot.net/Commands/Utils/Changelog/CommitAuthorDto.cs index 53881d5..8debd77 100644 --- a/Geekbot.net/Commands/Utils/Changelog/CommitAuthorDto.cs +++ b/Geekbot.net/Commands/Utils/Changelog/CommitAuthorDto.cs @@ -4,6 +4,8 @@ namespace Geekbot.net.Commands.Utils.Changelog { public class CommitAuthorDto { + public string Name { get; set; } + public string Email { get; set; } public DateTimeOffset Date { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Utils/Changelog/CommitInfoDto.cs b/Geekbot.net/Commands/Utils/Changelog/CommitInfoDto.cs index 743ca52..9008343 100644 --- a/Geekbot.net/Commands/Utils/Changelog/CommitInfoDto.cs +++ b/Geekbot.net/Commands/Utils/Changelog/CommitInfoDto.cs @@ -2,7 +2,7 @@ { public class CommitInfoDto { - public CommitAuthorDto AuthorDto { get; set; } + public CommitAuthorDto Author { get; set; } public string Message { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Lib/Logger/GeekbotLogger.cs b/Geekbot.net/Lib/Logger/GeekbotLogger.cs index c1ceb38..45d65f5 100644 --- a/Geekbot.net/Lib/Logger/GeekbotLogger.cs +++ b/Geekbot.net/Lib/Logger/GeekbotLogger.cs @@ -43,7 +43,7 @@ namespace Geekbot.net.Lib.Logger public void Error(string source, string message, Exception stackTrace, object extra = null) { - _logger.Error(stackTrace, CreateLogString("Error", source, message, stackTrace, extra)); + _logger.Error(CreateLogString("Error", source, message, stackTrace, extra)); } private string CreateLogString(string type, string source, string message, Exception stackTrace = null, object extra = null) From 0b7303d576980c6c70e496040ea8af3c4ad0602a Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 4 May 2018 00:59:49 +0200 Subject: [PATCH 153/553] fix !google --- Geekbot.net/Commands/Integrations/Google/Google.cs | 4 ++-- .../Commands/Integrations/Google/GoogleKgApiElementDto.cs | 2 +- .../Commands/Integrations/Google/GoogleKgApiResultDto.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Geekbot.net/Commands/Integrations/Google/Google.cs b/Geekbot.net/Commands/Integrations/Google/Google.cs index 631bbe3..7bd3a56 100644 --- a/Geekbot.net/Commands/Integrations/Google/Google.cs +++ b/Geekbot.net/Commands/Integrations/Google/Google.cs @@ -48,13 +48,13 @@ namespace Geekbot.net.Commands.Integrations.Google return; } - var data = response.ItemListElement.First().ResultDto; + var data = response.ItemListElement.First().Result; var eb = new EmbedBuilder(); eb.Title = data.Name; if(!string.IsNullOrEmpty(data.Description)) eb.WithDescription(data.Description); if(!string.IsNullOrEmpty(data.DetailedDtoDescription?.Url)) eb.WithUrl(data.DetailedDtoDescription.Url); if(!string.IsNullOrEmpty(data.DetailedDtoDescription?.ArticleBody)) eb.AddField("Details", data.DetailedDtoDescription.ArticleBody); - if(!string.IsNullOrEmpty(data.ImageDto?.ContentUrl)) eb.WithThumbnailUrl(data.ImageDto.ContentUrl); + if(!string.IsNullOrEmpty(data.Image?.ContentUrl)) eb.WithThumbnailUrl(data.Image.ContentUrl); await ReplyAsync("", false, eb.Build()); } diff --git a/Geekbot.net/Commands/Integrations/Google/GoogleKgApiElementDto.cs b/Geekbot.net/Commands/Integrations/Google/GoogleKgApiElementDto.cs index 3c4a130..a48b184 100644 --- a/Geekbot.net/Commands/Integrations/Google/GoogleKgApiElementDto.cs +++ b/Geekbot.net/Commands/Integrations/Google/GoogleKgApiElementDto.cs @@ -2,7 +2,7 @@ { public class GoogleKgApiElementDto { - public GoogleKgApiResultDto ResultDto { get; set; } + public GoogleKgApiResultDto Result { get; set; } public double ResultScore { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Integrations/Google/GoogleKgApiResultDto.cs b/Geekbot.net/Commands/Integrations/Google/GoogleKgApiResultDto.cs index 2c348c9..465f1d7 100644 --- a/Geekbot.net/Commands/Integrations/Google/GoogleKgApiResultDto.cs +++ b/Geekbot.net/Commands/Integrations/Google/GoogleKgApiResultDto.cs @@ -4,7 +4,7 @@ { public string Name { get; set; } public string Description { get; set; } - public GoogleKgApiImageDto ImageDto { get; set; } + public GoogleKgApiImageDto Image { get; set; } public GoogleKgApiDetailedDto DetailedDtoDescription { get; set; } } } \ No newline at end of file From 7958c87de527d7dbf624412d15a63e2567063feb Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 4 May 2018 01:14:43 +0200 Subject: [PATCH 154/553] Fix every other command that was not working --- Geekbot.net/Program.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 8268833..82016fa 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -116,9 +116,9 @@ namespace Geekbot.net var wikipediaClient = new WikipediaClient(); var audioUtils = new AudioUtils(); - _services.AddSingleton(_redis); - _services.AddSingleton(logger); - _services.AddSingleton(_userRepository); + _services.AddSingleton(_redis); + _services.AddSingleton(_userRepository); + _services.AddSingleton(logger); _services.AddSingleton(levelCalc); _services.AddSingleton(emojiConverter); _services.AddSingleton(fortunes); From 49392703f2a6b539513b62d192c336be2877a63b Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 4 May 2018 23:34:47 +0200 Subject: [PATCH 155/553] Bump version to 3.7 --- Geekbot.net/Commands/Audio/Voice.cs | 10 ++++------ Geekbot.net/Geekbot.net.csproj | 2 +- Geekbot.net/Lib/Constants.cs | 2 +- Geekbot.net/Lib/Logger/LoggerFactory.cs | 2 +- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/Geekbot.net/Commands/Audio/Voice.cs b/Geekbot.net/Commands/Audio/Voice.cs index e8f3134..410d8e2 100644 --- a/Geekbot.net/Commands/Audio/Voice.cs +++ b/Geekbot.net/Commands/Audio/Voice.cs @@ -18,7 +18,7 @@ namespace Geekbot.net.Commands.Audio _audioUtils = audioUtils; } - [Command("join")] +// [Command("join")] public async Task JoinChannel() { try @@ -27,12 +27,10 @@ namespace Geekbot.net.Commands.Audio var channel = (Context.User as IGuildUser)?.VoiceChannel; if (channel == null) { - await Context.Channel.SendMessageAsync( - "User must be in a voice channel, or a voice channel must be passed as an argument."); + await Context.Channel.SendMessageAsync("You must be in a voice channel."); return; } - // For the next step with transmitting audio, you would want to pass this Audio Client in to a service. var audioClient = await channel.ConnectAsync(); _audioUtils.StoreAudioClient(Context.Guild.Id, audioClient); await ReplyAsync($"Connected to {channel.Name}"); @@ -43,7 +41,7 @@ namespace Geekbot.net.Commands.Audio } } - [Command("disconnect")] +// [Command("disconnect")] public async Task DisconnectChannel() { try @@ -66,7 +64,7 @@ namespace Geekbot.net.Commands.Audio } } - [Command("ytplay")] +// [Command("ytplay")] public async Task ytplay(string url) { try diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 5cba28a..861085b 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -3,7 +3,7 @@ Exe netcoreapp2.0 derp.ico - 3.6.0 + 3.7.0 Pizza and Coffee Studios Pizza and Coffee Studios A Discord bot diff --git a/Geekbot.net/Lib/Constants.cs b/Geekbot.net/Lib/Constants.cs index d754b5c..dbba570 100644 --- a/Geekbot.net/Lib/Constants.cs +++ b/Geekbot.net/Lib/Constants.cs @@ -3,7 +3,7 @@ public class Constants { public const string Name = "Geekbot"; - public const double BotVersion = 3.6; + public const double BotVersion = 3.7; public const double ApiVersion = 1; } } \ No newline at end of file diff --git a/Geekbot.net/Lib/Logger/LoggerFactory.cs b/Geekbot.net/Lib/Logger/LoggerFactory.cs index 491197c..d32d80b 100644 --- a/Geekbot.net/Lib/Logger/LoggerFactory.cs +++ b/Geekbot.net/Lib/Logger/LoggerFactory.cs @@ -30,7 +30,7 @@ namespace Geekbot.net.Lib.Logger OptimizeBufferReuse = true, MessagesPerRequest = 10, RetryInterval = 5000, - Name = "GeekbotBeta" + Name = "Geekbot" }) ); } From 0fe273151c61535d54605b6658488f83ef6a117f Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 6 May 2018 00:59:06 +0200 Subject: [PATCH 156/553] Use Owner Attribute instead of manual inline checking --- Geekbot.net/Commands/Admin/Owner.cs | 46 +++++++---------------------- 1 file changed, 11 insertions(+), 35 deletions(-) diff --git a/Geekbot.net/Commands/Admin/Owner.cs b/Geekbot.net/Commands/Admin/Owner.cs index 39ccd8c..4d4f0f2 100644 --- a/Geekbot.net/Commands/Admin/Owner.cs +++ b/Geekbot.net/Commands/Admin/Owner.cs @@ -12,7 +12,7 @@ using StackExchange.Redis; namespace Geekbot.net.Commands.Admin { [Group("owner")] - [RequireUserPermission(GuildPermission.Administrator)] + [RequireOwner] public class Owner : ModuleBase { private readonly DiscordSocketClient _client; @@ -21,8 +21,7 @@ namespace Geekbot.net.Commands.Admin private readonly IDatabase _redis; private readonly IUserRepository _userRepository; - public Owner(IDatabase redis, DiscordSocketClient client, IGeekbotLogger logger, IUserRepository userRepositry, - IErrorHandler errorHandler) + public Owner(IDatabase redis, DiscordSocketClient client, IGeekbotLogger logger, IUserRepository userRepositry, IErrorHandler errorHandler) { _redis = redis; _client = client; @@ -36,14 +35,6 @@ namespace Geekbot.net.Commands.Admin [Summary("Set the youtube api key")] public async Task SetYoutubeKey([Summary("API Key")] string key) { - var botOwner = Context.Guild.GetUserAsync(ulong.Parse(_redis.StringGet("botOwner"))).Result; - if (!Context.User.Id.ToString().Equals(botOwner.Id.ToString())) - { - await ReplyAsync( - $"Sorry, only the botowner can do this ({botOwner.Username}#{botOwner.Discriminator})"); - return; - } - _redis.StringSet("youtubeKey", key); await ReplyAsync("Apikey has been set"); } @@ -53,14 +44,6 @@ namespace Geekbot.net.Commands.Admin [Summary("Set the game that the bot is playing")] public async Task SetGame([Remainder] [Summary("Game")] string key) { - var botOwner = Context.Guild.GetUserAsync(ulong.Parse(_redis.StringGet("botOwner"))).Result; - if (!Context.User.Id.ToString().Equals(botOwner.Id.ToString())) - { - await ReplyAsync( - $"Sorry, only the botowner can do this ({botOwner.Username}#{botOwner.Discriminator})"); - return; - } - _redis.StringSet("Game", key); await _client.SetGameAsync(key); _logger.Information("Geekbot", $"Changed game to {key}"); @@ -72,22 +55,6 @@ namespace Geekbot.net.Commands.Admin [Summary("Populate user cache")] public async Task PopUserRepoCommand() { - try - { - var botOwner = Context.Guild.GetUserAsync(ulong.Parse(_redis.StringGet("botOwner"))).Result; - if (!Context.User.Id.ToString().Equals(botOwner.Id.ToString())) - { - await ReplyAsync( - $"Sorry, only the botowner can do this ({botOwner.Username}#{botOwner.Discriminator})"); - return; - } - } - catch (Exception) - { - await ReplyAsync("Sorry, only the botowner can do this"); - return; - } - var success = 0; var failed = 0; try @@ -114,5 +81,14 @@ namespace Geekbot.net.Commands.Admin "Couldn't complete User Repository, see console for more info"); } } + + [Command("error", RunMode = RunMode.Async)] + [Remarks(CommandCategories.Admin)] + [Summary("Throw an error un purpose")] + public void PurposefulError() + { + var e = new Exception("Error Generated by !owner error"); + _errorHandler.HandleCommandException(e, Context); + } } } \ No newline at end of file From 2b85caeb2979063dae3f225293a615baa916f62c Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 6 May 2018 01:47:13 +0200 Subject: [PATCH 157/553] Use LogSource Enum for logger and improve logging messages --- Geekbot.net/Commands/Admin/Owner.cs | 8 ++-- Geekbot.net/Commands/User/Ranking/Rank.cs | 2 +- Geekbot.net/Handlers.cs | 20 ++++----- Geekbot.net/Lib/Clients/MalClient.cs | 4 +- Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs | 19 +++++--- .../Lib/Localization/TranslationHandler.cs | 12 ++--- Geekbot.net/Lib/Logger/DiscordLogger.cs | 25 ++++++++--- Geekbot.net/Lib/Logger/GeekbotLogger.cs | 19 ++++---- Geekbot.net/Lib/Logger/IGeekbotLogger.cs | 10 ++--- Geekbot.net/Lib/Logger/LogDto.cs | 2 +- Geekbot.net/Lib/Logger/LogSource.cs | 16 +++++++ .../Lib/Logger/SimpleConextConverter.cs | 8 ++-- Geekbot.net/Lib/Media/FortunesProvider.cs | 4 +- Geekbot.net/Lib/Media/MediaProvider.cs | 18 ++++---- .../Lib/UserRepository/UserRepository.cs | 6 +-- Geekbot.net/Program.cs | 44 +++++++------------ 16 files changed, 122 insertions(+), 95 deletions(-) create mode 100644 Geekbot.net/Lib/Logger/LogSource.cs diff --git a/Geekbot.net/Commands/Admin/Owner.cs b/Geekbot.net/Commands/Admin/Owner.cs index 4d4f0f2..2d097e0 100644 --- a/Geekbot.net/Commands/Admin/Owner.cs +++ b/Geekbot.net/Commands/Admin/Owner.cs @@ -46,7 +46,7 @@ namespace Geekbot.net.Commands.Admin { _redis.StringSet("Game", key); await _client.SetGameAsync(key); - _logger.Information("Geekbot", $"Changed game to {key}"); + _logger.Information(LogSource.Geekbot, $"Changed game to {key}"); await ReplyAsync($"Now Playing {key}"); } @@ -59,11 +59,11 @@ namespace Geekbot.net.Commands.Admin var failed = 0; try { - _logger.Warning("UserRepository", "Populating User Repositry"); + _logger.Warning(LogSource.UserRepository, "Populating User Repositry"); await ReplyAsync("Starting Population of User Repository"); foreach (var guild in _client.Guilds) { - _logger.Information("UserRepository", $"Populating users from {guild.Name}"); + _logger.Information(LogSource.UserRepository, $"Populating users from {guild.Name}"); foreach (var user in guild.Users) { var succeded = await _userRepository.Update(user); @@ -71,7 +71,7 @@ namespace Geekbot.net.Commands.Admin } } - _logger.Warning("UserRepository", "Finished Updating User Repositry"); + _logger.Warning(LogSource.UserRepository, "Finished Updating User Repositry"); await ReplyAsync( $"Successfully Populated User Repository with {success} Users in {_client.Guilds.Count} Guilds (Failed: {failed})"); } diff --git a/Geekbot.net/Commands/User/Ranking/Rank.cs b/Geekbot.net/Commands/User/Ranking/Rank.cs index 590921e..08d4d3b 100644 --- a/Geekbot.net/Commands/User/Ranking/Rank.cs +++ b/Geekbot.net/Commands/User/Ranking/Rank.cs @@ -102,7 +102,7 @@ namespace Geekbot.net.Commands.User.Ranking } catch (Exception e) { - _logger.Warning("Geekbot", $"Could not retrieve user {user.Name}", e); + _logger.Warning(LogSource.Geekbot, $"Could not retrieve user {user.Name}", e); } } diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index 7d1523b..f248d5d 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -62,14 +62,14 @@ namespace Geekbot.net message.HasMentionPrefix(_client.CurrentUser, ref argPos))) return Task.CompletedTask; var context = new CommandContext(_client, message); var commandExec = _commands.ExecuteAsync(context, argPos, _servicesProvider); - _logger.Information("Command", + _logger.Information(LogSource.Command, context.Message.Content.Split(" ")[0].Replace("!", ""), SimpleConextConverter.ConvertContext(context)); return Task.CompletedTask; } catch (Exception e) { - _logger.Error("Geekbot", "Failed to run commands", e); + _logger.Error(LogSource.Geekbot, "Failed to Process Message", e); return Task.CompletedTask; } } @@ -81,7 +81,7 @@ namespace Geekbot.net if (message == null) return Task.CompletedTask; if (message.Channel.Name.StartsWith('@')) { - _logger.Information("Message", "DM-Channel - {message.Channel.Name} - {message.Content}"); + _logger.Information(LogSource.Message, $"[DM-Channel] {message.Content}", SimpleConextConverter.ConvertSocketMessage(message)); return Task.CompletedTask; } var channel = (SocketGuildChannel) message.Channel; @@ -90,11 +90,11 @@ namespace Geekbot.net _redis.HashIncrementAsync($"{channel.Guild.Id}:Messages", 0.ToString()); if (message.Author.IsBot) return Task.CompletedTask; - _logger.Information("Message", message.Content, SimpleConextConverter.ConvertSocketMessage(message)); + _logger.Information(LogSource.Message, message.Content, SimpleConextConverter.ConvertSocketMessage(message)); } catch (Exception e) { - _logger.Error("Message", "Could not process message stats", e); + _logger.Error(LogSource.Message, "Could not process message stats", e); } return Task.CompletedTask; } @@ -117,11 +117,11 @@ namespace Geekbot.net } } _userRepository.Update(user); - _logger.Information("Geekbot", $"{user.Username} ({user.Id}) joined {user.Guild.Name} ({user.Guild.Id})"); + _logger.Information(LogSource.Geekbot, $"{user.Username} ({user.Id}) joined {user.Guild.Name} ({user.Guild.Id})"); } catch (Exception e) { - _logger.Error("Geekbot", "Failed to send welcome message", e); + _logger.Error(LogSource.Geekbot, "Failed to send welcome message", e); } return Task.CompletedTask; } @@ -149,9 +149,9 @@ namespace Geekbot.net } catch (Exception e) { - _logger.Error("Geekbot", "Failed to send leave message", e); + _logger.Error(LogSource.Geekbot, "Failed to send leave message", e); } - _logger.Information("Geekbot", $"{user.Username} ({user.Id}) joined {user.Guild.Name} ({user.Guild.Id})"); + _logger.Information(LogSource.Geekbot, $"{user.Username} ({user.Id}) joined {user.Guild.Name} ({user.Guild.Id})"); } // @@ -187,7 +187,7 @@ namespace Geekbot.net } catch (Exception e) { - _logger.Error("Geekbot", "Failed to send delete message...", e); + _logger.Error(LogSource.Geekbot, "Failed to send delete message...", e); } } diff --git a/Geekbot.net/Lib/Clients/MalClient.cs b/Geekbot.net/Lib/Clients/MalClient.cs index d8bfe41..95d7dbd 100644 --- a/Geekbot.net/Lib/Clients/MalClient.cs +++ b/Geekbot.net/Lib/Clients/MalClient.cs @@ -42,10 +42,10 @@ namespace Geekbot.net.Lib.Clients } _animeSearch = new AnimeSearchMethodsAsync(_credentials); _mangaSearch = new MangaSearchMethodsAsync(_credentials); - _logger.Debug("Geekbot", "Logged in to MAL"); + _logger.Debug(LogSource.Geekbot, "Logged in to MAL"); return true; } - _logger.Debug("Geekbot", "No MAL Credentials Set!"); + _logger.Debug(LogSource.Geekbot, "No MAL Credentials Set!"); return false; } diff --git a/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs index 3d53242..382bdda 100644 --- a/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs @@ -26,7 +26,7 @@ namespace Geekbot.net.Lib.ErrorHandling if (!string.IsNullOrEmpty(sentryDsn)) { _raven = new RavenClient(sentryDsn); - _logger.Information("Geekbot", $"Command Errors will be logged to Sentry: {sentryDsn}"); + _logger.Information(LogSource.Geekbot, $"Command Errors will be logged to Sentry: {sentryDsn}"); } else { @@ -42,14 +42,21 @@ namespace Geekbot.net.Lib.ErrorHandling var errorObj = SimpleConextConverter.ConvertContext(context); if (e.Message.Contains("50007")) return; if (e.Message.Contains("50013")) return; - _logger.Error("Geekbot", "An error ocured", e, errorObj); + _logger.Error(LogSource.Geekbot, "An error ocured", e, errorObj); if (!string.IsNullOrEmpty(errorMessage)) { if (_errorsInChat) { - var resStackTrace = string.IsNullOrEmpty(e.InnerException?.ToString()) ? e.StackTrace : e.InnerException.ToString(); - var maxLen = Math.Min(resStackTrace.Length, 1850); - context.Channel.SendMessageAsync($"{e.Message}\r\n```\r\n{resStackTrace.Substring(0, maxLen)}\r\n```"); + var resStackTrace = string.IsNullOrEmpty(e.InnerException?.ToString()) ? e.StackTrace : e.InnerException?.ToString(); + if (!string.IsNullOrEmpty(resStackTrace)) + { + var maxLen = Math.Min(resStackTrace.Length, 1850); + context.Channel.SendMessageAsync($"{e.Message}\r\n```\r\n{resStackTrace.Substring(0, maxLen)}\r\n```"); + } + else + { + context.Channel.SendMessageAsync(e.Message); + } } else { @@ -75,7 +82,7 @@ namespace Geekbot.net.Lib.ErrorHandling catch (Exception ex) { context.Channel.SendMessageAsync("Something went really really wrong here"); - _logger.Error("Geekbot", "Errorception", ex); + _logger.Error(LogSource.Geekbot, "Errorception", ex); } } diff --git a/Geekbot.net/Lib/Localization/TranslationHandler.cs b/Geekbot.net/Lib/Localization/TranslationHandler.cs index e57ee8d..e4af1e0 100644 --- a/Geekbot.net/Lib/Localization/TranslationHandler.cs +++ b/Geekbot.net/Lib/Localization/TranslationHandler.cs @@ -22,7 +22,7 @@ namespace Geekbot.net.Lib.Localization { _logger = logger; _redis = redis; - _logger.Information("Geekbot", "Loading Translations"); + _logger.Information(LogSource.Geekbot, "Loading Translations"); LoadTranslations(); LoadServerLanguages(clientGuilds); } @@ -71,7 +71,7 @@ namespace Geekbot.net.Lib.Localization } catch (Exception e) { - _logger.Error("Geekbot", "Failed to load Translations", e); + _logger.Error(LogSource.Geekbot, "Failed to load Translations", e); Environment.Exit(110); } } @@ -100,7 +100,7 @@ namespace Geekbot.net.Lib.Localization translation = _translations[command][stringName]["EN"]; if (string.IsNullOrWhiteSpace(translation)) { - _logger.Warning("Geekbot", $"No translation found for {command} - {stringName}"); + _logger.Warning(LogSource.Geekbot, $"No translation found for {command} - {stringName}"); } return translation; } @@ -114,7 +114,7 @@ namespace Geekbot.net.Lib.Localization } catch (Exception e) { - _logger.Error("Geekbot", "lol nope", e); + _logger.Error(LogSource.Geekbot, "lol nope", e); return new Dictionary(); } } @@ -127,7 +127,7 @@ namespace Geekbot.net.Lib.Localization } catch (Exception e) { - _logger.Error("Geekbot", "lol nope", e); + _logger.Error(LogSource.Geekbot, "lol nope", e); return new Dictionary(); } } @@ -143,7 +143,7 @@ namespace Geekbot.net.Lib.Localization } catch (Exception e) { - _logger.Error("Geekbot", "Error while changing language", e); + _logger.Error(LogSource.Geekbot, "Error while changing language", e); return false; } } diff --git a/Geekbot.net/Lib/Logger/DiscordLogger.cs b/Geekbot.net/Lib/Logger/DiscordLogger.cs index fc12201..2adcd73 100644 --- a/Geekbot.net/Lib/Logger/DiscordLogger.cs +++ b/Geekbot.net/Lib/Logger/DiscordLogger.cs @@ -1,5 +1,7 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using Discord; +using Geekbot.net.Commands.Randomness.Cat; namespace Geekbot.net.Lib.Logger { @@ -14,26 +16,37 @@ namespace Geekbot.net.Lib.Logger public Task Log(LogMessage message) { + LogSource source; + try + { + source = Enum.Parse(message.Source); + } + catch + { + source = LogSource.Discord; + _logger.Warning(LogSource.Geekbot, $"Could not parse {message.Source} to a LogSource Enum"); + } + var logMessage = $"[{message.Source}] {message.Message}"; switch (message.Severity) { case LogSeverity.Verbose: - _logger.Trace(message.Source, message.Message); + _logger.Trace(source, message.Message); break; case LogSeverity.Debug: - _logger.Debug(message.Source, message.Message); + _logger.Debug(source, message.Message); break; case LogSeverity.Info: - _logger.Information(message.Source, message.Message); + _logger.Information(source, message.Message); break; case LogSeverity.Critical: case LogSeverity.Error: case LogSeverity.Warning: if (logMessage.Contains("VOICE_STATE_UPDATE")) break; - _logger.Error(message.Source, message.Message, message.Exception); + _logger.Error(source, message.Message, message.Exception); break; default: - _logger.Information(message.Source, $"{logMessage} --- {message.Severity}"); + _logger.Information(source, $"{logMessage} --- {message.Severity}"); break; } return Task.CompletedTask; diff --git a/Geekbot.net/Lib/Logger/GeekbotLogger.cs b/Geekbot.net/Lib/Logger/GeekbotLogger.cs index 45d65f5..60628af 100644 --- a/Geekbot.net/Lib/Logger/GeekbotLogger.cs +++ b/Geekbot.net/Lib/Logger/GeekbotLogger.cs @@ -18,35 +18,36 @@ namespace Geekbot.net.Lib.Logger ReferenceLoopHandling = ReferenceLoopHandling.Serialize, NullValueHandling = NullValueHandling.Include }; - Information("Geekbot", "Using GeekbotLogger"); + Information(LogSource.Geekbot, "Using GeekbotLogger"); } - public void Trace(string source, string message, object extra = null) + public void Trace(LogSource source, string message, object extra = null) { _logger.Trace(CreateLogString("Trace", source, message, null, extra)); } - public void Debug(string source, string message, object extra = null) + public void Debug(LogSource source, string message, object extra = null) { _logger.Debug(CreateLogString("Debug", source, message, null, extra)); } - public void Information(string source, string message, object extra = null) + public void Information(LogSource source, string message, object extra = null) { _logger.Info(CreateLogString("Information", source, message, null, extra)); } - public void Warning(string source, string message, Exception stackTrace = null, object extra = null) + public void Warning(LogSource source, string message, Exception stackTrace = null, object extra = null) { _logger.Warn(CreateLogString("Warning", source, message, stackTrace, extra)); } - public void Error(string source, string message, Exception stackTrace, object extra = null) + public void Error(LogSource source, string message, Exception stackTrace, object extra = null) { - _logger.Error(CreateLogString("Error", source, message, stackTrace, extra)); + if (_logAsJson) _logger.Error(CreateLogString("Error", source, message, stackTrace, extra)); + else _logger.Error(stackTrace, CreateLogString("Error", source, message, stackTrace, extra)); } - private string CreateLogString(string type, string source, string message, Exception stackTrace = null, object extra = null) + private string CreateLogString(string type, LogSource source, string message, Exception stackTrace = null, object extra = null) { if (_logAsJson) { @@ -62,7 +63,7 @@ namespace Geekbot.net.Lib.Logger return JsonConvert.SerializeObject(logObject, Formatting.None, _serializerSettings); } - if (source != "Message") return $"[{source}] - {message}"; + if (source != LogSource.Message) return $"[{source}] - {message}"; var m = (MessageDto) extra; return $"[{source}] - [{m?.Guild.Name} - {m?.Channel.Name}] {m?.User.Name}: {m?.Message.Content}"; diff --git a/Geekbot.net/Lib/Logger/IGeekbotLogger.cs b/Geekbot.net/Lib/Logger/IGeekbotLogger.cs index 36d456d..1f76cb0 100644 --- a/Geekbot.net/Lib/Logger/IGeekbotLogger.cs +++ b/Geekbot.net/Lib/Logger/IGeekbotLogger.cs @@ -4,10 +4,10 @@ namespace Geekbot.net.Lib.Logger { public interface IGeekbotLogger { - void Trace(string source, string message, object extra = null); - void Debug(string source, string message, object extra = null); - void Information(string source, string message, object extra = null); - void Warning(string source, string message, Exception stackTrace = null, object extra = null); - void Error(string source, string message, Exception stackTrace, object extra = null); + void Trace(LogSource source, string message, object extra = null); + void Debug(LogSource source, string message, object extra = null); + void Information(LogSource source, string message, object extra = null); + void Warning(LogSource source, string message, Exception stackTrace = null, object extra = null); + void Error(LogSource source, string message, Exception stackTrace, object extra = null); } } \ No newline at end of file diff --git a/Geekbot.net/Lib/Logger/LogDto.cs b/Geekbot.net/Lib/Logger/LogDto.cs index 74695ec..8ccfcdf 100644 --- a/Geekbot.net/Lib/Logger/LogDto.cs +++ b/Geekbot.net/Lib/Logger/LogDto.cs @@ -6,7 +6,7 @@ namespace Geekbot.net.Lib.Logger { public DateTime Timestamp { get; set; } public string Type { get; set; } - public string Source { get; set; } + public LogSource Source { get; set; } public string Message { get; set; } public Exception StackTrace { get; set; } public object Extra { get; set; } diff --git a/Geekbot.net/Lib/Logger/LogSource.cs b/Geekbot.net/Lib/Logger/LogSource.cs new file mode 100644 index 0000000..46b902f --- /dev/null +++ b/Geekbot.net/Lib/Logger/LogSource.cs @@ -0,0 +1,16 @@ +namespace Geekbot.net.Lib.Logger +{ + public enum LogSource + { + Geekbot, + Rest, + Gateway, + Discord, + Redis, + Message, + UserRepository, + Command, + Api, + Other + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Logger/SimpleConextConverter.cs b/Geekbot.net/Lib/Logger/SimpleConextConverter.cs index 4df802d..0845cc1 100644 --- a/Geekbot.net/Lib/Logger/SimpleConextConverter.cs +++ b/Geekbot.net/Lib/Logger/SimpleConextConverter.cs @@ -56,13 +56,13 @@ namespace Geekbot.net.Lib.Logger }, Guild = new MessageDto.IdAndName { - Id = channel.Guild.Id.ToString(), - Name = channel.Guild.Name + Id = channel?.Guild?.Id.ToString(), + Name = channel?.Guild?.Name }, Channel = new MessageDto.IdAndName { - Id = channel.Id.ToString(), - Name = channel.Name + Id = channel?.Id.ToString(), + Name = channel?.Name } }; } diff --git a/Geekbot.net/Lib/Media/FortunesProvider.cs b/Geekbot.net/Lib/Media/FortunesProvider.cs index dc97199..56b5ed6 100644 --- a/Geekbot.net/Lib/Media/FortunesProvider.cs +++ b/Geekbot.net/Lib/Media/FortunesProvider.cs @@ -17,11 +17,11 @@ namespace Geekbot.net.Lib.Media var rawFortunes = File.ReadAllText(path); _fortuneArray = rawFortunes.Split("%"); _totalFortunes = _fortuneArray.Length; - logger.Trace("Geekbot", $"Loaded {_totalFortunes} Fortunes"); + logger.Trace(LogSource.Geekbot, $"Loaded {_totalFortunes} Fortunes"); } else { - logger.Information("Geekbot", $"Fortunes File not found at {path}"); + logger.Information(LogSource.Geekbot, $"Fortunes File not found at {path}"); } } diff --git a/Geekbot.net/Lib/Media/MediaProvider.cs b/Geekbot.net/Lib/Media/MediaProvider.cs index 8f28d0d..7f883ae 100644 --- a/Geekbot.net/Lib/Media/MediaProvider.cs +++ b/Geekbot.net/Lib/Media/MediaProvider.cs @@ -22,7 +22,7 @@ namespace Geekbot.net.Lib.Media _random = new Random(); _logger = logger; - logger.Information("Geekbot", "Loading Media Files"); + logger.Information(LogSource.Geekbot, "Loading Media Files"); LoadCheckem(); LoadPandas(); @@ -38,56 +38,56 @@ namespace Geekbot.net.Lib.Media { var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/checkEmPics")); _checkemImages = rawLinks.Split("\n"); - _logger.Trace("Geekbot", $"Loaded {_checkemImages.Length} CheckEm Images"); + _logger.Trace(LogSource.Geekbot, $"Loaded {_checkemImages.Length} CheckEm Images"); } private void LoadPandas() { var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/pandas")); _pandaImages = rawLinks.Split("\n"); - _logger.Trace("Geekbot", $"Loaded {_pandaImages.Length} Panda Images"); + _logger.Trace(LogSource.Geekbot, $"Loaded {_pandaImages.Length} Panda Images"); } private void BakeCroissants() { var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/croissant")); _croissantImages = rawLinks.Split("\n"); - _logger.Trace("Geekbot", $"Loaded {_croissantImages.Length} Croissant Images"); + _logger.Trace(LogSource.Geekbot, $"Loaded {_croissantImages.Length} Croissant Images"); } private void LoadSquirrels() { var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/squirrel")); _squirrelImages = rawLinks.Split("\n"); - _logger.Trace("Geekbot", $"Loaded {_squirrelImages.Length} Squirrel Images"); + _logger.Trace(LogSource.Geekbot, $"Loaded {_squirrelImages.Length} Squirrel Images"); } private void LoadPumpkins() { var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/pumpkin")); _pumpkinImages = rawLinks.Split("\n"); - _logger.Trace("Geekbot", $"Loaded {_pumpkinImages.Length} Pumpkin Images"); + _logger.Trace(LogSource.Geekbot, $"Loaded {_pumpkinImages.Length} Pumpkin Images"); } private void LoadTurtles() { var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/turtles")); _turtlesImages = rawLinks.Split("\n"); - _logger.Trace("Geekbot", $"Loaded {_turtlesImages.Length} Turtle Images"); + _logger.Trace(LogSource.Geekbot, $"Loaded {_turtlesImages.Length} Turtle Images"); } private void LoadPinguins() { var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/pinguins")); _pinguinImages = rawLinks.Split("\n"); - _logger.Trace("Geekbot", $"Loaded {_pinguinImages.Length} Pinguin Images"); + _logger.Trace(LogSource.Geekbot, $"Loaded {_pinguinImages.Length} Pinguin Images"); } private void LoadFoxes() { var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/foxes")); _foxImages = rawLinks.Split("\n"); - _logger.Trace("Geekbot", $"Loaded {_foxImages.Length} Foxes Images"); + _logger.Trace(LogSource.Geekbot, $"Loaded {_foxImages.Length} Foxes Images"); } public string GetCheckem() diff --git a/Geekbot.net/Lib/UserRepository/UserRepository.cs b/Geekbot.net/Lib/UserRepository/UserRepository.cs index 558732e..3937107 100644 --- a/Geekbot.net/Lib/UserRepository/UserRepository.cs +++ b/Geekbot.net/Lib/UserRepository/UserRepository.cs @@ -36,12 +36,12 @@ namespace Geekbot.net.Lib.UserRepository } Store(savedUser); - _logger.Information("UserRepository", "Updated User", savedUser); + _logger.Information(LogSource.UserRepository, "Updated User", savedUser); return Task.FromResult(true); } catch (Exception e) { - _logger.Warning("UserRepository", $"Failed to update user: {user.Username}#{user.Discriminator} ({user.Id})", e); + _logger.Warning(LogSource.UserRepository, $"Failed to update user: {user.Username}#{user.Discriminator} ({user.Id})", e); return Task.FromResult(false); } } @@ -103,7 +103,7 @@ namespace Geekbot.net.Lib.UserRepository } catch (Exception e) { - _logger.Warning("UserRepository", "Failed to get {userId} from repository", e); + _logger.Warning(LogSource.UserRepository, $"Failed to get {userId} from repository", e); return new UserRepositoryUser(); } } diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 82016fa..bc90b4f 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -55,14 +55,14 @@ namespace Geekbot.net Console.WriteLine(logo.ToString()); var sumologicActive = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("GEEKBOT_SUMO")); var logger = new GeekbotLogger(runParameters, sumologicActive); - logger.Information("Geekbot", "Starting..."); + logger.Information(LogSource.Geekbot, "Starting..."); try { new Program().MainAsync(runParameters, logger).GetAwaiter().GetResult(); } catch (Exception e) { - logger.Error("Geekbot", "RIP", e); + logger.Error(LogSource.Geekbot, "RIP", e); } } @@ -70,7 +70,7 @@ namespace Geekbot.net { _logger = logger; _runParameters = runParameters; - logger.Information("Geekbot", "Initing Stuff"); + logger.Information(LogSource.Geekbot, "Initing Stuff"); var discordLogger = new DiscordLogger(logger); _client = new DiscordSocketClient(new DiscordSocketConfig @@ -85,11 +85,11 @@ namespace Geekbot.net { var redisMultiplexer = ConnectionMultiplexer.Connect("127.0.0.1:6379"); _redis = redisMultiplexer.GetDatabase(6); - logger.Information("Redis", $"Connected to db {_redis.Database}"); + logger.Information(LogSource.Redis, $"Connected to db {_redis.Database}"); } catch (Exception e) { - logger.Error("Redis", "Redis Connection Failed", e); + logger.Error(LogSource.Redis, "Redis Connection Failed", e); Environment.Exit(102); } @@ -128,7 +128,7 @@ namespace Geekbot.net _services.AddSingleton(wikipediaClient); _services.AddSingleton(audioUtils); - logger.Information("Geekbot", "Connecting to Discord"); + logger.Information(LogSource.Geekbot, "Connecting to Discord"); await Login(); @@ -145,9 +145,9 @@ namespace Geekbot.net if (isConneted) { await _client.SetGameAsync(_redis.StringGet("Game")); - _logger.Information("Geekbot", $"Now Connected as {_client.CurrentUser.Username} to {_client.Guilds.Count} Servers"); + _logger.Information(LogSource.Geekbot, $"Now Connected as {_client.CurrentUser.Username} to {_client.Guilds.Count} Servers"); - _logger.Information("Geekbot", "Registering Stuff"); + _logger.Information(LogSource.Geekbot, "Registering Stuff"); var translationHandler = new TranslationHandler(_client.Guilds, _redis, _logger); var errorHandler = new ErrorHandler(_logger, translationHandler, _runParameters.ExposeErrors); var reactionListener = new ReactionListener(_redis); @@ -172,21 +172,21 @@ namespace Geekbot.net if (_firstStart || _runParameters.Reset) { - _logger.Information("Geekbot", "Finishing setup"); + _logger.Information(LogSource.Geekbot, "Finishing setup"); await FinishSetup(); - _logger.Information("Geekbot", "Setup finished"); + _logger.Information(LogSource.Geekbot, "Setup finished"); } if (!_runParameters.DisableApi) { StartWebApi(); } - _logger.Information("Geekbot", "Done and ready for use"); + _logger.Information(LogSource.Geekbot, "Done and ready for use"); } } catch (Exception e) { - _logger.Error("Discord", "Could not connect...", e); + _logger.Error(LogSource.Geekbot, "Could not connect...", e); Environment.Exit(103); } } @@ -200,33 +200,23 @@ namespace Geekbot.net private void StartWebApi() { - _logger.Information("API", "Starting Webserver"); + _logger.Information(LogSource.Api, "Starting Webserver"); var webApiUrl = new Uri("http://localhost:12995"); new NancyHost(webApiUrl).Start(); - _logger.Information("API", $"Webserver now running on {webApiUrl}"); + _logger.Information(LogSource.Api, $"Webserver now running on {webApiUrl}"); } private async Task FinishSetup() { - var appInfo = await _client.GetApplicationInfoAsync(); - _logger.Information("Setup", $"Just a moment while i setup everything {appInfo.Owner.Username}"); try { + // ToDo: Set bot avatar + var appInfo = await _client.GetApplicationInfoAsync(); _redis.StringSet("botOwner", appInfo.Owner.Id); - var req = WebRequest.Create(appInfo.IconUrl); - using (var stream = req.GetResponse().GetResponseStream()) - { - await _client.CurrentUser.ModifyAsync(user => - { - user.Avatar = new Image(stream); - user.Username = appInfo.Name.ToString(); - }); - } - _logger.Information("Setup", "Everything done, enjoy!"); } catch (Exception e) { - _logger.Warning("Setup", "Oha, it seems like something went wrong while running the setup, geekbot will work never the less though", e); + _logger.Warning(LogSource.Geekbot, "Setup Failed, couldn't retrieve discord application data", e); } return Task.CompletedTask; } From fe5e2cb80fbe29b1598bff9fc5fb22eb6677c63c Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 6 May 2018 02:00:45 +0200 Subject: [PATCH 158/553] Create Enum for exit codes --- Geekbot.net/Lib/GeekbotExitCode.cs | 19 +++++++++++++++++++ .../Lib/Localization/TranslationHandler.cs | 8 ++++---- Geekbot.net/Program.cs | 8 ++++---- 3 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 Geekbot.net/Lib/GeekbotExitCode.cs diff --git a/Geekbot.net/Lib/GeekbotExitCode.cs b/Geekbot.net/Lib/GeekbotExitCode.cs new file mode 100644 index 0000000..e9e1210 --- /dev/null +++ b/Geekbot.net/Lib/GeekbotExitCode.cs @@ -0,0 +1,19 @@ +namespace Geekbot.net.Lib +{ + public enum GeekbotExitCode : int + { + // General + Clean = 0, + InvalidArguments = 1, + + // Geekbot Internals + TranslationsFailed = 201, + + // Dependent Services + RedisConnectionFailed = 301, + + // Discord Related + CouldNotLogin = 401 + + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Localization/TranslationHandler.cs b/Geekbot.net/Lib/Localization/TranslationHandler.cs index e4af1e0..550759d 100644 --- a/Geekbot.net/Lib/Localization/TranslationHandler.cs +++ b/Geekbot.net/Lib/Localization/TranslationHandler.cs @@ -72,7 +72,7 @@ namespace Geekbot.net.Lib.Localization catch (Exception e) { _logger.Error(LogSource.Geekbot, "Failed to load Translations", e); - Environment.Exit(110); + Environment.Exit(GeekbotExitCode.TranslationsFailed.GetHashCode()); } } @@ -114,8 +114,8 @@ namespace Geekbot.net.Lib.Localization } catch (Exception e) { - _logger.Error(LogSource.Geekbot, "lol nope", e); - return new Dictionary(); + _logger.Error(LogSource.Geekbot, "No translations for command found", e); + return new Dictionary(); } } @@ -127,7 +127,7 @@ namespace Geekbot.net.Lib.Localization } catch (Exception e) { - _logger.Error(LogSource.Geekbot, "lol nope", e); + _logger.Error(LogSource.Geekbot, "No translations for command found", e); return new Dictionary(); } } diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index bc90b4f..3a35d19 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -43,7 +43,7 @@ namespace Geekbot.net RunParameters runParameters = null; Parser.Default.ParseArguments(args) .WithParsed(e => runParameters = e) - .WithNotParsed(_ => Environment.Exit(1)); + .WithNotParsed(_ => Environment.Exit(GeekbotExitCode.InvalidArguments.GetHashCode())); var logo = new StringBuilder(); logo.AppendLine(@" ____ _____ _____ _ ______ ___ _____"); @@ -90,10 +90,10 @@ namespace Geekbot.net catch (Exception e) { logger.Error(LogSource.Redis, "Redis Connection Failed", e); - Environment.Exit(102); + Environment.Exit(GeekbotExitCode.RedisConnectionFailed.GetHashCode()); } - _token = runParameters.Token ??_redis.StringGet("discordToken"); + _token = runParameters.Token ?? _redis.StringGet("discordToken"); if (_token.IsNullOrEmpty) { Console.Write("Your bot Token: "); @@ -187,7 +187,7 @@ namespace Geekbot.net catch (Exception e) { _logger.Error(LogSource.Geekbot, "Could not connect...", e); - Environment.Exit(103); + Environment.Exit(GeekbotExitCode.CouldNotLogin.GetHashCode()); } } From 7eb62cb267d74da821bd5bbd1a6f6ae9459544d3 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 6 May 2018 02:05:52 +0200 Subject: [PATCH 159/553] Serialize LogSource as string instead of numerical representation --- Geekbot.net/Lib/Logger/LogSource.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Geekbot.net/Lib/Logger/LogSource.cs b/Geekbot.net/Lib/Logger/LogSource.cs index 46b902f..d9a8629 100644 --- a/Geekbot.net/Lib/Logger/LogSource.cs +++ b/Geekbot.net/Lib/Logger/LogSource.cs @@ -1,5 +1,9 @@ -namespace Geekbot.net.Lib.Logger +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; + +namespace Geekbot.net.Lib.Logger { + [JsonConverter(typeof(StringEnumConverter))] public enum LogSource { Geekbot, From 7238e7177d413430aed8b14508278a686b4922a4 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 6 May 2018 02:43:23 +0200 Subject: [PATCH 160/553] Bug fixes in !quote --- Geekbot.net/Commands/Utils/Quote/Quote.cs | 32 +++++++++++++++----- Geekbot.net/Lib/Polyfills/UserPolyfillDto.cs | 31 +++++++++++++++++++ 2 files changed, 55 insertions(+), 8 deletions(-) create mode 100644 Geekbot.net/Lib/Polyfills/UserPolyfillDto.cs diff --git a/Geekbot.net/Commands/Utils/Quote/Quote.cs b/Geekbot.net/Commands/Utils/Quote/Quote.cs index f1941ba..7a25b50 100644 --- a/Geekbot.net/Commands/Utils/Quote/Quote.cs +++ b/Geekbot.net/Commands/Utils/Quote/Quote.cs @@ -5,6 +5,7 @@ using Discord; using Discord.Commands; using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Polyfills; using Newtonsoft.Json; using StackExchange.Redis; @@ -30,6 +31,11 @@ namespace Geekbot.net.Commands.Utils.Quote try { var randomQuotes = _redis.SetMembers($"{Context.Guild.Id}:Quotes"); + if (!randomQuotes.Any()) + { + await ReplyAsync("This server doesn't seem to have any quotes yet. You can add a quote with `!quote save @user` or `!quote save `"); + return; + } var randomNumber = new Random().Next(randomQuotes.Length - 1); var randomQuote = randomQuotes[randomNumber]; var quote = JsonConvert.DeserializeObject(randomQuote); @@ -62,6 +68,7 @@ namespace Geekbot.net.Commands.Utils.Quote } var lastMessage = await GetLastMessageByUser(user); + if (lastMessage == null) return; var quote = CreateQuoteObject(lastMessage); var quoteStore = JsonConvert.SerializeObject(quote); _redis.SetAdd($"{Context.Guild.Id}:Quotes", quoteStore); @@ -116,6 +123,7 @@ namespace Geekbot.net.Commands.Utils.Quote try { var lastMessage = await GetLastMessageByUser(user); + if (lastMessage == null) return; var quote = CreateQuoteObject(lastMessage); var embed = QuoteBuilder(quote); await ReplyAsync("", false, embed.Build()); @@ -178,18 +186,26 @@ namespace Geekbot.net.Commands.Utils.Quote private async Task GetLastMessageByUser(IUser user) { - var list = Context.Channel.GetMessagesAsync().Flatten(); - await list; - return list.Result - .First(msg => msg.Author.Id == user.Id - && msg.Embeds.Count == 0 - && msg.Id != Context.Message.Id - && !msg.Content.ToLower().StartsWith("!")); + try + { + var list = Context.Channel.GetMessagesAsync().Flatten(); + await list; + return list.Result + .First(msg => msg.Author.Id == user.Id + && msg.Embeds.Count == 0 + && msg.Id != Context.Message.Id + && !msg.Content.ToLower().StartsWith("!")); + } + catch + { + await ReplyAsync($"No quoteable message have been sent by {user.Username} in this channel"); + return null; + } } private EmbedBuilder QuoteBuilder(QuoteObjectDto quote, int id = 0) { - var user = Context.Client.GetUserAsync(quote.UserId).Result; + var user = Context.Client.GetUserAsync(quote.UserId).Result ?? new UserPolyfillDto { Username = "Unknown User" }; var eb = new EmbedBuilder(); eb.WithColor(new Color(143, 167, 232)); eb.Title = id == 0 ? "" : $"#{id} | "; diff --git a/Geekbot.net/Lib/Polyfills/UserPolyfillDto.cs b/Geekbot.net/Lib/Polyfills/UserPolyfillDto.cs new file mode 100644 index 0000000..407ae36 --- /dev/null +++ b/Geekbot.net/Lib/Polyfills/UserPolyfillDto.cs @@ -0,0 +1,31 @@ +using System; +using System.Threading.Tasks; +using Discord; + +namespace Geekbot.net.Lib.Polyfills +{ + internal class UserPolyfillDto : IUser + { + public ulong Id { get; set; } + public DateTimeOffset CreatedAt { get; set; } + public string Mention { get; set; } + public Game? Game { get; set; } + public UserStatus Status { get; set; } + public string AvatarId { get; set; } + public string Discriminator { get; set; } + public ushort DiscriminatorValue { get; set; } + public bool IsBot { get; set; } + public bool IsWebhook { get; set; } + public string Username { get; set; } + + public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) + { + return "https://discordapp.com/assets/6debd47ed13483642cf09e832ed0bc1b.png"; + } + + public Task GetOrCreateDMChannelAsync(RequestOptions options = null) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file From 59ee6b289acb6101ceb9525c563e77059500281a Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 6 May 2018 03:24:09 +0200 Subject: [PATCH 161/553] Include git sha in binary --- .gitlab-ci.yml | 2 +- Geekbot.net/Commands/Utils/Info.cs | 2 +- Geekbot.net/Geekbot.net.csproj | 2 ++ Geekbot.net/Lib/Constants.cs | 11 +++++++++-- Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs | 2 +- Geekbot.net/WebApi/Status/StatusController.cs | 2 +- 6 files changed, 15 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3928542..98eb9ba 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,7 +22,7 @@ build: script: - dotnet restore - dotnet test Tests - - dotnet publish --configuration Release -o Binaries ./ + - dotnet publish --version-suffix ${CI_COMMIT_SHA:0:8} --configuration Release -o Binaries ./ deploy: stage: deploy diff --git a/Geekbot.net/Commands/Utils/Info.cs b/Geekbot.net/Commands/Utils/Info.cs index 446abfe..de34e89 100644 --- a/Geekbot.net/Commands/Utils/Info.cs +++ b/Geekbot.net/Commands/Utils/Info.cs @@ -37,7 +37,7 @@ namespace Geekbot.net.Commands.Utils eb.WithAuthor(new EmbedAuthorBuilder() .WithIconUrl(_client.CurrentUser.GetAvatarUrl()) - .WithName($"{Constants.Name} V{Constants.BotVersion}")); + .WithName($"{Constants.Name} V{Constants.BotVersion()}")); var botOwner = await Context.Guild.GetUserAsync(ulong.Parse(_redis.StringGet("botOwner"))); var uptime = DateTime.Now.Subtract(Process.GetCurrentProcess().StartTime); diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 861085b..90ff896 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -4,6 +4,8 @@ netcoreapp2.0 derp.ico 3.7.0 + $(VersionSuffix) + $(Version)-$(VersionSuffix) Pizza and Coffee Studios Pizza and Coffee Studios A Discord bot diff --git a/Geekbot.net/Lib/Constants.cs b/Geekbot.net/Lib/Constants.cs index dbba570..240cfce 100644 --- a/Geekbot.net/Lib/Constants.cs +++ b/Geekbot.net/Lib/Constants.cs @@ -1,9 +1,16 @@ -namespace Geekbot.net.Lib +using System.Reflection; + +namespace Geekbot.net.Lib { public class Constants { public const string Name = "Geekbot"; - public const double BotVersion = 3.7; + + public static string BotVersion() + { + return typeof(Program).Assembly.GetCustomAttribute().InformationalVersion; + } + public const double ApiVersion = 1; } } \ No newline at end of file diff --git a/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs index 382bdda..99d1e8b 100644 --- a/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs @@ -25,7 +25,7 @@ namespace Geekbot.net.Lib.ErrorHandling var sentryDsn = Environment.GetEnvironmentVariable("SENTRY"); if (!string.IsNullOrEmpty(sentryDsn)) { - _raven = new RavenClient(sentryDsn); + _raven = new RavenClient(sentryDsn) { Release = Constants.BotVersion() }; _logger.Information(LogSource.Geekbot, $"Command Errors will be logged to Sentry: {sentryDsn}"); } else diff --git a/Geekbot.net/WebApi/Status/StatusController.cs b/Geekbot.net/WebApi/Status/StatusController.cs index 5f995c9..05196a2 100644 --- a/Geekbot.net/WebApi/Status/StatusController.cs +++ b/Geekbot.net/WebApi/Status/StatusController.cs @@ -11,7 +11,7 @@ namespace Geekbot.net.WebApi.Status { var responseBody = new ApiStatusDto { - GeekbotVersion = Constants.BotVersion.ToString(), + GeekbotVersion = Constants.BotVersion(), ApiVersion = Constants.ApiVersion.ToString(), Status = "Online" }; From 4d39850373244a966c27f87d5845afa6d2c1d885 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 6 May 2018 23:08:04 +0200 Subject: [PATCH 162/553] A dice can now have 144 sides instead of 120 --- Geekbot.net/Commands/Utils/Dice/Dice.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Geekbot.net/Commands/Utils/Dice/Dice.cs b/Geekbot.net/Commands/Utils/Dice/Dice.cs index 7fc4f84..9c169c7 100644 --- a/Geekbot.net/Commands/Utils/Dice/Dice.cs +++ b/Geekbot.net/Commands/Utils/Dice/Dice.cs @@ -51,9 +51,9 @@ namespace Geekbot.net.Commands.Utils.Dice return; } - if (dices.Any(d => d.Sides > 120)) + if (dices.Any(d => d.Sides > 144)) { - await ReplyAsync("A dice can't have more than 120 sides"); + await ReplyAsync("A dice can't have more than 144 sides"); return; } From d671817b0da09266633395959640779d50f1b7c1 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 6 May 2018 23:28:44 +0200 Subject: [PATCH 163/553] Make constants static and use non buffered sumologic client --- Geekbot.net/Lib/Constants.cs | 2 +- Geekbot.net/Lib/Logger/LoggerFactory.cs | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/Geekbot.net/Lib/Constants.cs b/Geekbot.net/Lib/Constants.cs index 240cfce..f80f182 100644 --- a/Geekbot.net/Lib/Constants.cs +++ b/Geekbot.net/Lib/Constants.cs @@ -2,7 +2,7 @@ namespace Geekbot.net.Lib { - public class Constants + public static class Constants { public const string Name = "Geekbot"; diff --git a/Geekbot.net/Lib/Logger/LoggerFactory.cs b/Geekbot.net/Lib/Logger/LoggerFactory.cs index d32d80b..4095d00 100644 --- a/Geekbot.net/Lib/Logger/LoggerFactory.cs +++ b/Geekbot.net/Lib/Logger/LoggerFactory.cs @@ -18,19 +18,15 @@ namespace Geekbot.net.Lib.Logger Console.WriteLine("Logging Geekbot Logs to Sumologic"); config.LoggingRules.Add( new LoggingRule("*", LogLevel.Debug, LogLevel.Fatal, - new BufferedSumoLogicTarget() + new SumoLogicTarget() { Url = Environment.GetEnvironmentVariable("GEEKBOT_SUMO"), SourceName = "GeekbotLogger", Layout = "${message}", - UseConsoleLog = true, - MaxQueueSizeBytes = 500000, - FlushingAccuracy = 250, - MaxFlushInterval = 10000, + UseConsoleLog = false, OptimizeBufferReuse = true, - MessagesPerRequest = 10, - RetryInterval = 5000, - Name = "Geekbot" + Name = "Geekbot", + AppendException = false }) ); } From 83f3c61661077c69a973e877fc03c322f22ad736 Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 8 May 2018 00:22:14 +0200 Subject: [PATCH 164/553] Log errors as info when logging to sumologic --- Geekbot.net/Lib/Logger/GeekbotLogger.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Geekbot.net/Lib/Logger/GeekbotLogger.cs b/Geekbot.net/Lib/Logger/GeekbotLogger.cs index 60628af..b2bb677 100644 --- a/Geekbot.net/Lib/Logger/GeekbotLogger.cs +++ b/Geekbot.net/Lib/Logger/GeekbotLogger.cs @@ -28,7 +28,8 @@ namespace Geekbot.net.Lib.Logger public void Debug(LogSource source, string message, object extra = null) { - _logger.Debug(CreateLogString("Debug", source, message, null, extra)); + if (_logAsJson) _logger.Info(CreateLogString("Debug", source, message, null, extra)); + else _logger.Debug(CreateLogString("Debug", source, message, null, extra)); } public void Information(LogSource source, string message, object extra = null) @@ -38,12 +39,13 @@ namespace Geekbot.net.Lib.Logger public void Warning(LogSource source, string message, Exception stackTrace = null, object extra = null) { - _logger.Warn(CreateLogString("Warning", source, message, stackTrace, extra)); + if (_logAsJson) _logger.Info(CreateLogString("Warning", source, message, stackTrace, extra)); + else _logger.Warn(CreateLogString("Warning", source, message, stackTrace, extra)); } public void Error(LogSource source, string message, Exception stackTrace, object extra = null) { - if (_logAsJson) _logger.Error(CreateLogString("Error", source, message, stackTrace, extra)); + if (_logAsJson) _logger.Info(CreateLogString("Error", source, message, stackTrace, extra)); else _logger.Error(stackTrace, CreateLogString("Error", source, message, stackTrace, extra)); } From 510b030fecca6981d78a4fcec948c3bd146ba99a Mon Sep 17 00:00:00 2001 From: Runebaas Date: Wed, 9 May 2018 01:21:39 +0200 Subject: [PATCH 165/553] Begining of implementing the entity framework --- Geekbot.net/Commands/Utils/Quote/Quote.cs | 94 ++++++++++++----------- Geekbot.net/Database/DatabaseContext.cs | 15 ++++ Geekbot.net/Database/QuoteModel.cs | 17 ++++ Geekbot.net/Geekbot.net.csproj | 5 ++ Geekbot.net/Lib/GeekbotExitCode.cs | 1 + Geekbot.net/Lib/RunParameters.cs | 3 + Geekbot.net/Program.cs | 16 ++++ 7 files changed, 108 insertions(+), 43 deletions(-) create mode 100644 Geekbot.net/Database/DatabaseContext.cs create mode 100644 Geekbot.net/Database/QuoteModel.cs diff --git a/Geekbot.net/Commands/Utils/Quote/Quote.cs b/Geekbot.net/Commands/Utils/Quote/Quote.cs index 7a25b50..0310182 100644 --- a/Geekbot.net/Commands/Utils/Quote/Quote.cs +++ b/Geekbot.net/Commands/Utils/Quote/Quote.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.net.Database; using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Polyfills; @@ -15,12 +16,14 @@ namespace Geekbot.net.Commands.Utils.Quote public class Quote : ModuleBase { private readonly IErrorHandler _errorHandler; + private readonly DatabaseContext _database; private readonly IDatabase _redis; - public Quote(IDatabase redis, IErrorHandler errorHandler) + public Quote(IDatabase redis, IErrorHandler errorHandler, DatabaseContext database) { _redis = redis; _errorHandler = errorHandler; + _database = database; } [Command] @@ -30,16 +33,18 @@ namespace Geekbot.net.Commands.Utils.Quote { try { - var randomQuotes = _redis.SetMembers($"{Context.Guild.Id}:Quotes"); - if (!randomQuotes.Any()) + var s = _database.Quotes.Where(e => e.GuildId.Equals(Context.Guild.Id)); + var totalQuotes = s.Count(); + + if (totalQuotes > 0) { await ReplyAsync("This server doesn't seem to have any quotes yet. You can add a quote with `!quote save @user` or `!quote save `"); return; } - var randomNumber = new Random().Next(randomQuotes.Length - 1); - var randomQuote = randomQuotes[randomNumber]; - var quote = JsonConvert.DeserializeObject(randomQuote); - var embed = QuoteBuilder(quote, randomNumber + 1); + var quote = s.Where(e => e.Id.Equals(new Random().Next(totalQuotes)))?.FirstOrDefault(); + + + var embed = QuoteBuilder(quote, 2); await ReplyAsync("", false, embed.Build()); } catch (Exception e) @@ -69,9 +74,10 @@ namespace Geekbot.net.Commands.Utils.Quote var lastMessage = await GetLastMessageByUser(user); if (lastMessage == null) return; + var quote = CreateQuoteObject(lastMessage); - var quoteStore = JsonConvert.SerializeObject(quote); - _redis.SetAdd($"{Context.Guild.Id}:Quotes", quoteStore); + await _database.Quotes.AddAsync(quote); + var embed = QuoteBuilder(quote); await ReplyAsync("**Quote Added**", false, embed.Build()); } @@ -103,8 +109,8 @@ namespace Geekbot.net.Commands.Utils.Quote } var quote = CreateQuoteObject(message); - var quoteStore = JsonConvert.SerializeObject(quote); - _redis.SetAdd($"{Context.Guild.Id}:Quotes", quoteStore); + await _database.Quotes.AddAsync(quote); + var embed = QuoteBuilder(quote); await ReplyAsync("**Quote Added**", false, embed.Build()); } @@ -154,35 +160,36 @@ namespace Geekbot.net.Commands.Utils.Quote } } - [Command("remove")] - [RequireUserPermission(GuildPermission.KickMembers)] - [RequireUserPermission(GuildPermission.ManageMessages)] - [RequireUserPermission(GuildPermission.ManageRoles)] - [Remarks(CommandCategories.Quotes)] - [Summary("Remove a quote (required mod permissions)")] - public async Task RemoveQuote([Summary("quoteId")] int id) - { - try - { - var quotes = _redis.SetMembers($"{Context.Guild.Id}:Quotes"); - var success = _redis.SetRemove($"{Context.Guild.Id}:Quotes", quotes[id - 1]); - if (success) - { - var quote = JsonConvert.DeserializeObject(quotes[id - 1]); - var embed = QuoteBuilder(quote); - await ReplyAsync($"**Removed #{id}**", false, embed.Build()); - } - else - { - await ReplyAsync("I couldn't find a quote with that id :disappointed:"); - } - } - catch (Exception e) - { - _errorHandler.HandleCommandException(e, Context, - "I couldn't find a quote with that id :disappointed:"); - } - } + [Command("remove")] + [RequireUserPermission(GuildPermission.KickMembers)] + [RequireUserPermission(GuildPermission.ManageMessages)] + [RequireUserPermission(GuildPermission.ManageRoles)] + [Remarks(CommandCategories.Quotes)] + [Summary("Remove a quote (required mod permissions)")] + public async Task RemoveQuote([Summary("quoteId")] int id) + { + await ReplyAsync("Command currently Disabled"); + // try + // { + // var quotes = _redis.SetMembers($"{Context.Guild.Id}:Quotes"); + // var success = _redis.SetRemove($"{Context.Guild.Id}:Quotes", quotes[id - 1]); + // if (success) + // { + // var quote = JsonConvert.DeserializeObject(quotes[id - 1]); + // var embed = QuoteBuilder(quote); + // await ReplyAsync($"**Removed #{id}**", false, embed.Build()); + // } + // else + // { + // await ReplyAsync("I couldn't find a quote with that id :disappointed:"); + // } + // } + // catch (Exception e) + // { + // _errorHandler.HandleCommandException(e, Context, + // "I couldn't find a quote with that id :disappointed:"); + // } + } private async Task GetLastMessageByUser(IUser user) { @@ -203,7 +210,7 @@ namespace Geekbot.net.Commands.Utils.Quote } } - private EmbedBuilder QuoteBuilder(QuoteObjectDto quote, int id = 0) + private EmbedBuilder QuoteBuilder(QuoteModel quote, int id = 0) { var user = Context.Client.GetUserAsync(quote.UserId).Result ?? new UserPolyfillDto { Username = "Unknown User" }; var eb = new EmbedBuilder(); @@ -216,7 +223,7 @@ namespace Geekbot.net.Commands.Utils.Quote return eb; } - private QuoteObjectDto CreateQuoteObject(IMessage message) + private QuoteModel CreateQuoteObject(IMessage message) { string image; try @@ -228,8 +235,9 @@ namespace Geekbot.net.Commands.Utils.Quote image = null; } - return new QuoteObjectDto + return new QuoteModel() { + GuildId = Context.Guild.Id, UserId = message.Author.Id, Time = message.Timestamp.DateTime, Quote = message.Content, diff --git a/Geekbot.net/Database/DatabaseContext.cs b/Geekbot.net/Database/DatabaseContext.cs new file mode 100644 index 0000000..d2645a1 --- /dev/null +++ b/Geekbot.net/Database/DatabaseContext.cs @@ -0,0 +1,15 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; + +namespace Geekbot.net.Database +{ + public class DatabaseContext : DbContext + { + public DbSet Quotes { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + => optionsBuilder.UseLoggerFactory(new LoggerFactory().AddConsole()) +// .UseInMemoryDatabase(databaseName: "Geekbot"); + .UseMySql(@"Server=localhost;database=geekbot;uid=geekbot;"); + } +} \ No newline at end of file diff --git a/Geekbot.net/Database/QuoteModel.cs b/Geekbot.net/Database/QuoteModel.cs new file mode 100644 index 0000000..ea42e93 --- /dev/null +++ b/Geekbot.net/Database/QuoteModel.cs @@ -0,0 +1,17 @@ +using System; +using System.ComponentModel.DataAnnotations; +using Microsoft.EntityFrameworkCore.Scaffolding.Metadata; + +namespace Geekbot.net.Database +{ + public class QuoteModel + { + [Key] + public int Id { get; set; } + public ulong GuildId { get; set; } + public ulong UserId { get; set; } + public string Quote { get; set; } + public DateTime Time { get; set; } + public string Image { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 90ff896..f8554c9 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -19,6 +19,9 @@
+ + + @@ -31,6 +34,8 @@ + + 1.2.6 diff --git a/Geekbot.net/Lib/GeekbotExitCode.cs b/Geekbot.net/Lib/GeekbotExitCode.cs index e9e1210..d68aa4a 100644 --- a/Geekbot.net/Lib/GeekbotExitCode.cs +++ b/Geekbot.net/Lib/GeekbotExitCode.cs @@ -11,6 +11,7 @@ // Dependent Services RedisConnectionFailed = 301, + DatabaseConnectionFailed = 302, // Discord Related CouldNotLogin = 401 diff --git a/Geekbot.net/Lib/RunParameters.cs b/Geekbot.net/Lib/RunParameters.cs index 35c1a2a..1e1048b 100644 --- a/Geekbot.net/Lib/RunParameters.cs +++ b/Geekbot.net/Lib/RunParameters.cs @@ -22,5 +22,8 @@ namespace Geekbot.net.Lib [Option("token", Default = null, HelpText = "Set a new bot token")] public string Token { get; set; } + + [Option("in-memory", Default = false, HelpText = "Disables the web api")] + public bool InMemory { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 3a35d19..f1982c0 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Net; using System.Reflection; using System.Text; @@ -7,6 +8,7 @@ using CommandLine; using Discord; using Discord.Commands; using Discord.WebSocket; +using Geekbot.net.Database; using Geekbot.net.Lib; using Geekbot.net.Lib.Audio; using Geekbot.net.Lib.Clients; @@ -18,6 +20,7 @@ using Geekbot.net.Lib.Logger; using Geekbot.net.Lib.Media; using Geekbot.net.Lib.ReactionListener; using Geekbot.net.Lib.UserRepository; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Nancy.Hosting.Self; using StackExchange.Redis; @@ -104,6 +107,18 @@ namespace Geekbot.net _firstStart = true; } + DatabaseContext database = null; + try + { + database = new DatabaseContext(); + database.Database.EnsureCreated(); + } + catch (Exception e) + { + logger.Error(LogSource.Geekbot, "Could not Connect to datbase", e); + Environment.Exit(GeekbotExitCode.DatabaseConnectionFailed.GetHashCode()); + } + _services = new ServiceCollection(); _userRepository = new UserRepository(_redis, logger); @@ -127,6 +142,7 @@ namespace Geekbot.net _services.AddSingleton(mtgManaConverter); _services.AddSingleton(wikipediaClient); _services.AddSingleton(audioUtils); + _services.AddSingleton(database); logger.Information(LogSource.Geekbot, "Connecting to Discord"); From 177942f7fe08295213625b1beef2d35bf0107c74 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 9 May 2018 02:12:58 +0200 Subject: [PATCH 166/553] Save quotes to the database after adding them --- Geekbot.net/Commands/Utils/Quote/Quote.cs | 65 ++++++++++++----------- Geekbot.net/Database/QuoteModel.cs | 14 ++++- 2 files changed, 46 insertions(+), 33 deletions(-) diff --git a/Geekbot.net/Commands/Utils/Quote/Quote.cs b/Geekbot.net/Commands/Utils/Quote/Quote.cs index 0310182..8186f56 100644 --- a/Geekbot.net/Commands/Utils/Quote/Quote.cs +++ b/Geekbot.net/Commands/Utils/Quote/Quote.cs @@ -33,18 +33,18 @@ namespace Geekbot.net.Commands.Utils.Quote { try { - var s = _database.Quotes.Where(e => e.GuildId.Equals(Context.Guild.Id)); - var totalQuotes = s.Count(); + var s = _database.Quotes.OrderBy(e => e.GuildId).Where(e => e.GuildId.Equals(Context.Guild.Id)).ToList(); - if (totalQuotes > 0) + if (!s.Any()) { await ReplyAsync("This server doesn't seem to have any quotes yet. You can add a quote with `!quote save @user` or `!quote save `"); return; } - var quote = s.Where(e => e.Id.Equals(new Random().Next(totalQuotes)))?.FirstOrDefault(); + + var random = new Random().Next(1, s.Count()); + var quote = s[random - 1]; - - var embed = QuoteBuilder(quote, 2); + var embed = QuoteBuilder(quote); await ReplyAsync("", false, embed.Build()); } catch (Exception e) @@ -76,7 +76,8 @@ namespace Geekbot.net.Commands.Utils.Quote if (lastMessage == null) return; var quote = CreateQuoteObject(lastMessage); - await _database.Quotes.AddAsync(quote); + _database.Quotes.Add(quote); + _database.SaveChanges(); var embed = QuoteBuilder(quote); await ReplyAsync("**Quote Added**", false, embed.Build()); @@ -109,7 +110,8 @@ namespace Geekbot.net.Commands.Utils.Quote } var quote = CreateQuoteObject(message); - await _database.Quotes.AddAsync(quote); + _database.Quotes.Add(quote); + _database.SaveChanges(); var embed = QuoteBuilder(quote); await ReplyAsync("**Quote Added**", false, embed.Build()); @@ -168,27 +170,25 @@ namespace Geekbot.net.Commands.Utils.Quote [Summary("Remove a quote (required mod permissions)")] public async Task RemoveQuote([Summary("quoteId")] int id) { - await ReplyAsync("Command currently Disabled"); - // try - // { - // var quotes = _redis.SetMembers($"{Context.Guild.Id}:Quotes"); - // var success = _redis.SetRemove($"{Context.Guild.Id}:Quotes", quotes[id - 1]); - // if (success) - // { - // var quote = JsonConvert.DeserializeObject(quotes[id - 1]); - // var embed = QuoteBuilder(quote); - // await ReplyAsync($"**Removed #{id}**", false, embed.Build()); - // } - // else - // { - // await ReplyAsync("I couldn't find a quote with that id :disappointed:"); - // } - // } - // catch (Exception e) - // { - // _errorHandler.HandleCommandException(e, Context, - // "I couldn't find a quote with that id :disappointed:"); - // } + try + { + var quote = _database.Quotes.Where(e => e.GuildId == Context.Guild.Id && e.InternalId == id)?.FirstOrDefault(); + if (quote != null) + { + _database.Quotes.Remove(quote); + _database.SaveChanges(); + var embed = QuoteBuilder(quote); + await ReplyAsync($"**Removed #{id}**", false, embed.Build()); + } + else + { + await ReplyAsync("I couldn't find a quote with that id :disappointed:"); + } + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context, "I couldn't find a quote with that id :disappointed:"); + } } private async Task GetLastMessageByUser(IUser user) @@ -210,13 +210,12 @@ namespace Geekbot.net.Commands.Utils.Quote } } - private EmbedBuilder QuoteBuilder(QuoteModel quote, int id = 0) + private EmbedBuilder QuoteBuilder(QuoteModel quote) { var user = Context.Client.GetUserAsync(quote.UserId).Result ?? new UserPolyfillDto { Username = "Unknown User" }; var eb = new EmbedBuilder(); eb.WithColor(new Color(143, 167, 232)); - eb.Title = id == 0 ? "" : $"#{id} | "; - eb.Title += $"{user.Username} @ {quote.Time.Day}.{quote.Time.Month}.{quote.Time.Year}"; + eb.Title = $"#{quote.InternalId} | {user.Username} @ {quote.Time.Day}.{quote.Time.Month}.{quote.Time.Year}"; eb.Description = quote.Quote; eb.ThumbnailUrl = user.GetAvatarUrl(); if (quote.Image != null) eb.ImageUrl = quote.Image; @@ -235,8 +234,10 @@ namespace Geekbot.net.Commands.Utils.Quote image = null; } + var internalId = _database.Quotes.Count(e => e.GuildId == Context.Guild.Id); return new QuoteModel() { + InternalId = internalId, GuildId = Context.Guild.Id, UserId = message.Author.Id, Time = message.Timestamp.DateTime, diff --git a/Geekbot.net/Database/QuoteModel.cs b/Geekbot.net/Database/QuoteModel.cs index ea42e93..37d4a37 100644 --- a/Geekbot.net/Database/QuoteModel.cs +++ b/Geekbot.net/Database/QuoteModel.cs @@ -8,10 +8,22 @@ namespace Geekbot.net.Database { [Key] public int Id { get; set; } + + [Required] + public int InternalId { get; set; } + + [Required] public ulong GuildId { get; set; } + + [Required] public ulong UserId { get; set; } - public string Quote { get; set; } + + [Required] + [DataType(DataType.DateTime)] public DateTime Time { get; set; } + + public string Quote { get; set; } + public string Image { get; set; } } } \ No newline at end of file From 3425896c0b7e4ac27465b15fecff586f00cc47be Mon Sep 17 00:00:00 2001 From: Runebaas Date: Wed, 9 May 2018 18:51:53 +0200 Subject: [PATCH 167/553] Add database Initializer --- Geekbot.net/Database/DatabaseInitializer.cs | 43 +++++++++++++++++++++ Geekbot.net/Database/InMemoryDatabase.cs | 19 +++++++++ Geekbot.net/Database/SqlConnectionString.cs | 16 ++++++++ Geekbot.net/Database/SqlDatabase.cs | 19 +++++++++ Geekbot.net/Program.cs | 12 +----- 5 files changed, 98 insertions(+), 11 deletions(-) create mode 100644 Geekbot.net/Database/DatabaseInitializer.cs create mode 100644 Geekbot.net/Database/InMemoryDatabase.cs create mode 100644 Geekbot.net/Database/SqlConnectionString.cs create mode 100644 Geekbot.net/Database/SqlDatabase.cs diff --git a/Geekbot.net/Database/DatabaseInitializer.cs b/Geekbot.net/Database/DatabaseInitializer.cs new file mode 100644 index 0000000..838eb48 --- /dev/null +++ b/Geekbot.net/Database/DatabaseInitializer.cs @@ -0,0 +1,43 @@ +using System; +using Geekbot.net.Lib; +using Geekbot.net.Lib.Logger; + +namespace Geekbot.net.Database +{ + public class DatabaseInitializer + { + private readonly RunParameters _runParameters; + private readonly GeekbotLogger _logger; + + public DatabaseInitializer(RunParameters runParameters, GeekbotLogger logger) + { + _runParameters = runParameters; + _logger = logger; + } + + public DatabaseContext Initzialize() + { + DatabaseContext database = null; + try + { + if (_runParameters.InMemory) + { + database = new InMemoryDatabase("geekbot"); + } + else + { + database = new SqlDatabase(new SqlConnectionString()); + } + + database.Database.EnsureCreated(); + } + catch (Exception e) + { + _logger.Error(LogSource.Geekbot, "Could not Connect to datbase", e); + Environment.Exit(GeekbotExitCode.DatabaseConnectionFailed.GetHashCode()); + } + + return database; + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Database/InMemoryDatabase.cs b/Geekbot.net/Database/InMemoryDatabase.cs new file mode 100644 index 0000000..cfef816 --- /dev/null +++ b/Geekbot.net/Database/InMemoryDatabase.cs @@ -0,0 +1,19 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; + +namespace Geekbot.net.Database +{ + public class InMemoryDatabase : DatabaseContext + { + private readonly string _name; + + public InMemoryDatabase(string name) + { + _name = name; + } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + => optionsBuilder.UseLoggerFactory(new LoggerFactory().AddConsole()) + .UseInMemoryDatabase(databaseName: _name); + } +} \ No newline at end of file diff --git a/Geekbot.net/Database/SqlConnectionString.cs b/Geekbot.net/Database/SqlConnectionString.cs new file mode 100644 index 0000000..1dcfabb --- /dev/null +++ b/Geekbot.net/Database/SqlConnectionString.cs @@ -0,0 +1,16 @@ +namespace Geekbot.net.Database +{ + public class SqlConnectionString + { + public string Server { get; set; } = "localhost"; + public string Port { get; set; } = "3306"; + public string Database { get; set; } = "geekbot"; + public string Username { get; set; } = "geekbot"; + public string Password { get; set; } = ""; + + public override string ToString() + { + return $"Server={Server};Port={Port};Database={Database};Uid={Username};Pwd={Password};"; + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Database/SqlDatabase.cs b/Geekbot.net/Database/SqlDatabase.cs new file mode 100644 index 0000000..0d9cd8f --- /dev/null +++ b/Geekbot.net/Database/SqlDatabase.cs @@ -0,0 +1,19 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; + +namespace Geekbot.net.Database +{ + public class SqlDatabase : DatabaseContext + { + private readonly SqlConnectionString _connectionString; + + public SqlDatabase(SqlConnectionString connectionString) + { + _connectionString = connectionString; + } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + => optionsBuilder.UseLoggerFactory(new LoggerFactory().AddConsole()) + .UseMySql(_connectionString.ToString()); + } +} \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index f1982c0..4fa763d 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -107,17 +107,7 @@ namespace Geekbot.net _firstStart = true; } - DatabaseContext database = null; - try - { - database = new DatabaseContext(); - database.Database.EnsureCreated(); - } - catch (Exception e) - { - logger.Error(LogSource.Geekbot, "Could not Connect to datbase", e); - Environment.Exit(GeekbotExitCode.DatabaseConnectionFailed.GetHashCode()); - } + var database = new DatabaseInitializer(runParameters, logger).Initzialize(); _services = new ServiceCollection(); From d2f31d07308d3c6c84fb832fb7841f444f451de0 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 10 May 2018 00:00:51 +0200 Subject: [PATCH 168/553] Use Postgresql, add db run params, npgsql logging adapter and empty models --- Geekbot.net/Commands/Utils/Quote/Quote.cs | 22 +++--- Geekbot.net/Database/DatabaseContext.cs | 16 ++-- Geekbot.net/Database/DatabaseInitializer.cs | 16 +++- Geekbot.net/Database/InMemoryDatabase.cs | 3 +- .../LoggingAdapter/NpgsqlLoggingAdapter.cs | 73 +++++++++++++++++++ .../NpgsqlLoggingProviderAdapter.cs | 20 +++++ .../Database/Models/GuildSettingsModel.cs | 7 ++ Geekbot.net/Database/Models/GuildsModel.cs | 7 ++ Geekbot.net/Database/Models/KarmaModel.cs | 7 ++ .../Database/{ => Models}/QuoteModel.cs | 7 +- .../Database/Models/RoleSelfServiceModel.cs | 7 ++ Geekbot.net/Database/Models/ShipsModel.cs | 7 ++ Geekbot.net/Database/Models/SlapsModel.cs | 7 ++ Geekbot.net/Database/Models/UserModel.cs | 7 ++ Geekbot.net/Database/SqlConnectionString.cs | 12 +-- Geekbot.net/Database/SqlDatabase.cs | 4 +- Geekbot.net/Geekbot.net.csproj | 6 +- Geekbot.net/Lib/Extensions/LongExtensions.cs | 12 +++ Geekbot.net/Lib/Extensions/UlongExtensions.cs | 12 +++ Geekbot.net/Lib/Logger/GeekbotLogger.cs | 10 +++ Geekbot.net/Lib/Logger/IGeekbotLogger.cs | 2 + Geekbot.net/Lib/Logger/LogSource.cs | 1 + Geekbot.net/Lib/Logger/LoggerFactory.cs | 2 +- Geekbot.net/Lib/RunParameters.cs | 24 +++++- 24 files changed, 252 insertions(+), 39 deletions(-) create mode 100644 Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingAdapter.cs create mode 100644 Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingProviderAdapter.cs create mode 100644 Geekbot.net/Database/Models/GuildSettingsModel.cs create mode 100644 Geekbot.net/Database/Models/GuildsModel.cs create mode 100644 Geekbot.net/Database/Models/KarmaModel.cs rename Geekbot.net/Database/{ => Models}/QuoteModel.cs (73%) create mode 100644 Geekbot.net/Database/Models/RoleSelfServiceModel.cs create mode 100644 Geekbot.net/Database/Models/ShipsModel.cs create mode 100644 Geekbot.net/Database/Models/SlapsModel.cs create mode 100644 Geekbot.net/Database/Models/UserModel.cs create mode 100644 Geekbot.net/Lib/Extensions/LongExtensions.cs create mode 100644 Geekbot.net/Lib/Extensions/UlongExtensions.cs diff --git a/Geekbot.net/Commands/Utils/Quote/Quote.cs b/Geekbot.net/Commands/Utils/Quote/Quote.cs index 8186f56..18eab22 100644 --- a/Geekbot.net/Commands/Utils/Quote/Quote.cs +++ b/Geekbot.net/Commands/Utils/Quote/Quote.cs @@ -4,10 +4,11 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Database; +using Geekbot.net.Database.Models; using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Polyfills; -using Newtonsoft.Json; using StackExchange.Redis; namespace Geekbot.net.Commands.Utils.Quote @@ -33,7 +34,7 @@ namespace Geekbot.net.Commands.Utils.Quote { try { - var s = _database.Quotes.OrderBy(e => e.GuildId).Where(e => e.GuildId.Equals(Context.Guild.Id)).ToList(); + var s = _database.Quotes.Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())).ToList(); if (!s.Any()) { @@ -41,8 +42,8 @@ namespace Geekbot.net.Commands.Utils.Quote return; } - var random = new Random().Next(1, s.Count()); - var quote = s[random - 1]; + var random = new Random().Next(s.Count()); + var quote = s[random]; var embed = QuoteBuilder(quote); await ReplyAsync("", false, embed.Build()); @@ -172,7 +173,7 @@ namespace Geekbot.net.Commands.Utils.Quote { try { - var quote = _database.Quotes.Where(e => e.GuildId == Context.Guild.Id && e.InternalId == id)?.FirstOrDefault(); + var quote = _database.Quotes.Where(e => e.GuildId == Context.Guild.Id.AsLong() && e.InternalId == id)?.FirstOrDefault(); if (quote != null) { _database.Quotes.Remove(quote); @@ -212,7 +213,7 @@ namespace Geekbot.net.Commands.Utils.Quote private EmbedBuilder QuoteBuilder(QuoteModel quote) { - var user = Context.Client.GetUserAsync(quote.UserId).Result ?? new UserPolyfillDto { Username = "Unknown User" }; + var user = Context.Client.GetUserAsync(quote.UserId.AsUlong()).Result ?? new UserPolyfillDto { Username = "Unknown User" }; var eb = new EmbedBuilder(); eb.WithColor(new Color(143, 167, 232)); eb.Title = $"#{quote.InternalId} | {user.Username} @ {quote.Time.Day}.{quote.Time.Month}.{quote.Time.Year}"; @@ -234,12 +235,15 @@ namespace Geekbot.net.Commands.Utils.Quote image = null; } - var internalId = _database.Quotes.Count(e => e.GuildId == Context.Guild.Id); + var last = _database.Quotes.Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())) + .OrderByDescending(e => e.InternalId).FirstOrDefault(); + int internalId = 1; + if (last != null) internalId = last.InternalId + 1; return new QuoteModel() { InternalId = internalId, - GuildId = Context.Guild.Id, - UserId = message.Author.Id, + GuildId = Context.Guild.Id.AsLong(), + UserId = message.Author.Id.AsLong(), Time = message.Timestamp.DateTime, Quote = message.Content, Image = image diff --git a/Geekbot.net/Database/DatabaseContext.cs b/Geekbot.net/Database/DatabaseContext.cs index d2645a1..4426c8d 100644 --- a/Geekbot.net/Database/DatabaseContext.cs +++ b/Geekbot.net/Database/DatabaseContext.cs @@ -1,15 +1,17 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Logging; +using Geekbot.net.Database.Models; +using Microsoft.EntityFrameworkCore; namespace Geekbot.net.Database { public class DatabaseContext : DbContext { public DbSet Quotes { get; set; } - - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - => optionsBuilder.UseLoggerFactory(new LoggerFactory().AddConsole()) -// .UseInMemoryDatabase(databaseName: "Geekbot"); - .UseMySql(@"Server=localhost;database=geekbot;uid=geekbot;"); +// public DbSet Users { get; set; } +// public DbSet Guilds { get; set; } +// public DbSet GuildSettings { get; set; } +// public DbSet Karma { get; set; } +// public DbSet Ships { get; set; } +// public DbSet RoleSelfService { get; set; } +// public DbSet SlapsModels { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Database/DatabaseInitializer.cs b/Geekbot.net/Database/DatabaseInitializer.cs index 838eb48..f4bb8f1 100644 --- a/Geekbot.net/Database/DatabaseInitializer.cs +++ b/Geekbot.net/Database/DatabaseInitializer.cs @@ -1,6 +1,8 @@ using System; +using Geekbot.net.Database.LoggingAdapter; using Geekbot.net.Lib; using Geekbot.net.Lib.Logger; +using Npgsql.Logging; namespace Geekbot.net.Database { @@ -26,9 +28,16 @@ namespace Geekbot.net.Database } else { - database = new SqlDatabase(new SqlConnectionString()); + NpgsqlLogManager.Provider = new NpgsqlLoggingProviderAdapter(_logger); + database = new SqlDatabase(new SqlConnectionString + { + Host = _runParameters.DbHost, + Port = _runParameters.DbPort, + Database = _runParameters.DbDatabase, + Username = _runParameters.DbUser, + Password = _runParameters.DbPassword + }); } - database.Database.EnsureCreated(); } catch (Exception e) @@ -36,7 +45,8 @@ namespace Geekbot.net.Database _logger.Error(LogSource.Geekbot, "Could not Connect to datbase", e); Environment.Exit(GeekbotExitCode.DatabaseConnectionFailed.GetHashCode()); } - + + _logger.Information(LogSource.Database, $"Connected with {database.Database.ProviderName}"); return database; } } diff --git a/Geekbot.net/Database/InMemoryDatabase.cs b/Geekbot.net/Database/InMemoryDatabase.cs index cfef816..178c0e3 100644 --- a/Geekbot.net/Database/InMemoryDatabase.cs +++ b/Geekbot.net/Database/InMemoryDatabase.cs @@ -13,7 +13,6 @@ namespace Geekbot.net.Database } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - => optionsBuilder.UseLoggerFactory(new LoggerFactory().AddConsole()) - .UseInMemoryDatabase(databaseName: _name); + => optionsBuilder.UseInMemoryDatabase(databaseName: _name); } } \ No newline at end of file diff --git a/Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingAdapter.cs b/Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingAdapter.cs new file mode 100644 index 0000000..80d60b3 --- /dev/null +++ b/Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingAdapter.cs @@ -0,0 +1,73 @@ +using System; +using Geekbot.net.Lib.Logger; +using Npgsql.Logging; +using LogLevel = NLog.LogLevel; + +namespace Geekbot.net.Database.LoggingAdapter +{ + public class NpgsqlLoggingAdapter : NpgsqlLogger + { + private readonly string _name; + private readonly IGeekbotLogger _geekbotLogger; + + public NpgsqlLoggingAdapter(string name, IGeekbotLogger geekbotLogger) + { + _name = name.Substring(7); + _geekbotLogger = geekbotLogger; + geekbotLogger.Trace(LogSource.Database, $"Loaded Npgsql logging adapter: {name}"); + } + + public override bool IsEnabled(NpgsqlLogLevel level) + { + return !_geekbotLogger.LogAsJson() && _geekbotLogger.GetNLogger().IsEnabled(ToGeekbotLogLevel(level)); + } + + public override void Log(NpgsqlLogLevel level, int connectorId, string msg, Exception exception = null) + { + var nameAndMessage = $"{_name}: {msg}"; + switch (level) + { + case NpgsqlLogLevel.Trace: + _geekbotLogger.Trace(LogSource.Database, nameAndMessage); + break; + case NpgsqlLogLevel.Debug: + _geekbotLogger.Debug(LogSource.Database, nameAndMessage); + break; + case NpgsqlLogLevel.Info: + _geekbotLogger.Information(LogSource.Database, nameAndMessage); + break; + case NpgsqlLogLevel.Warn: + _geekbotLogger.Warning(LogSource.Database, nameAndMessage, exception); + break; + case NpgsqlLogLevel.Error: + case NpgsqlLogLevel.Fatal: + _geekbotLogger.Error(LogSource.Database, nameAndMessage, exception); + break; + default: + _geekbotLogger.Information(LogSource.Database, nameAndMessage); + break; + } + } + + private static LogLevel ToGeekbotLogLevel(NpgsqlLogLevel level) + { + switch (level) + { + case NpgsqlLogLevel.Trace: + return LogLevel.Trace; + case NpgsqlLogLevel.Debug: + return LogLevel.Debug; + case NpgsqlLogLevel.Info: + return LogLevel.Info; + case NpgsqlLogLevel.Warn: + return LogLevel.Warn; + case NpgsqlLogLevel.Error: + return LogLevel.Error; + case NpgsqlLogLevel.Fatal: + return LogLevel.Fatal; + default: + throw new ArgumentOutOfRangeException(nameof(level)); + } + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingProviderAdapter.cs b/Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingProviderAdapter.cs new file mode 100644 index 0000000..0888111 --- /dev/null +++ b/Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingProviderAdapter.cs @@ -0,0 +1,20 @@ +using Geekbot.net.Lib.Logger; +using Npgsql.Logging; + +namespace Geekbot.net.Database.LoggingAdapter +{ + public class NpgsqlLoggingProviderAdapter : INpgsqlLoggingProvider + { + private readonly GeekbotLogger _geekbotLogger; + + public NpgsqlLoggingProviderAdapter(GeekbotLogger geekbotLogger) + { + _geekbotLogger = geekbotLogger; + } + + public NpgsqlLogger CreateLogger(string name) + { + return new NpgsqlLoggingAdapter(name, _geekbotLogger); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Database/Models/GuildSettingsModel.cs b/Geekbot.net/Database/Models/GuildSettingsModel.cs new file mode 100644 index 0000000..b8ae300 --- /dev/null +++ b/Geekbot.net/Database/Models/GuildSettingsModel.cs @@ -0,0 +1,7 @@ +namespace Geekbot.net.Database.Models +{ + public class GuildSettingsModel + { + + } +} \ No newline at end of file diff --git a/Geekbot.net/Database/Models/GuildsModel.cs b/Geekbot.net/Database/Models/GuildsModel.cs new file mode 100644 index 0000000..0b8ec3c --- /dev/null +++ b/Geekbot.net/Database/Models/GuildsModel.cs @@ -0,0 +1,7 @@ +namespace Geekbot.net.Database.Models +{ + public class GuildsModel + { + + } +} \ No newline at end of file diff --git a/Geekbot.net/Database/Models/KarmaModel.cs b/Geekbot.net/Database/Models/KarmaModel.cs new file mode 100644 index 0000000..d29f313 --- /dev/null +++ b/Geekbot.net/Database/Models/KarmaModel.cs @@ -0,0 +1,7 @@ +namespace Geekbot.net.Database.Models +{ + public class KarmaModel + { + + } +} \ No newline at end of file diff --git a/Geekbot.net/Database/QuoteModel.cs b/Geekbot.net/Database/Models/QuoteModel.cs similarity index 73% rename from Geekbot.net/Database/QuoteModel.cs rename to Geekbot.net/Database/Models/QuoteModel.cs index 37d4a37..98e8b21 100644 --- a/Geekbot.net/Database/QuoteModel.cs +++ b/Geekbot.net/Database/Models/QuoteModel.cs @@ -1,8 +1,7 @@ using System; using System.ComponentModel.DataAnnotations; -using Microsoft.EntityFrameworkCore.Scaffolding.Metadata; -namespace Geekbot.net.Database +namespace Geekbot.net.Database.Models { public class QuoteModel { @@ -13,10 +12,10 @@ namespace Geekbot.net.Database public int InternalId { get; set; } [Required] - public ulong GuildId { get; set; } + public long GuildId { get; set; } [Required] - public ulong UserId { get; set; } + public long UserId { get; set; } [Required] [DataType(DataType.DateTime)] diff --git a/Geekbot.net/Database/Models/RoleSelfServiceModel.cs b/Geekbot.net/Database/Models/RoleSelfServiceModel.cs new file mode 100644 index 0000000..4bb7f01 --- /dev/null +++ b/Geekbot.net/Database/Models/RoleSelfServiceModel.cs @@ -0,0 +1,7 @@ +namespace Geekbot.net.Database.Models +{ + public class RoleSelfServiceModel + { + + } +} \ No newline at end of file diff --git a/Geekbot.net/Database/Models/ShipsModel.cs b/Geekbot.net/Database/Models/ShipsModel.cs new file mode 100644 index 0000000..6eda191 --- /dev/null +++ b/Geekbot.net/Database/Models/ShipsModel.cs @@ -0,0 +1,7 @@ +namespace Geekbot.net.Database.Models +{ + public class ShipsModel + { + + } +} \ No newline at end of file diff --git a/Geekbot.net/Database/Models/SlapsModel.cs b/Geekbot.net/Database/Models/SlapsModel.cs new file mode 100644 index 0000000..80ee199 --- /dev/null +++ b/Geekbot.net/Database/Models/SlapsModel.cs @@ -0,0 +1,7 @@ +namespace Geekbot.net.Database.Models +{ + public class SlapsModel + { + + } +} \ No newline at end of file diff --git a/Geekbot.net/Database/Models/UserModel.cs b/Geekbot.net/Database/Models/UserModel.cs new file mode 100644 index 0000000..d68f178 --- /dev/null +++ b/Geekbot.net/Database/Models/UserModel.cs @@ -0,0 +1,7 @@ +namespace Geekbot.net.Database.Models +{ + public class UserModel + { + + } +} \ No newline at end of file diff --git a/Geekbot.net/Database/SqlConnectionString.cs b/Geekbot.net/Database/SqlConnectionString.cs index 1dcfabb..3228a05 100644 --- a/Geekbot.net/Database/SqlConnectionString.cs +++ b/Geekbot.net/Database/SqlConnectionString.cs @@ -2,15 +2,15 @@ { public class SqlConnectionString { - public string Server { get; set; } = "localhost"; - public string Port { get; set; } = "3306"; - public string Database { get; set; } = "geekbot"; - public string Username { get; set; } = "geekbot"; - public string Password { get; set; } = ""; + public string Host { get; set; } + public string Port { get; set; } + public string Database { get; set; } + public string Username { get; set; } + public string Password { get; set; } public override string ToString() { - return $"Server={Server};Port={Port};Database={Database};Uid={Username};Pwd={Password};"; + return $"Server={Host};Port={Port};Database={Database};Uid={Username};Pwd={Password};"; } } } \ No newline at end of file diff --git a/Geekbot.net/Database/SqlDatabase.cs b/Geekbot.net/Database/SqlDatabase.cs index 0d9cd8f..e6d03d4 100644 --- a/Geekbot.net/Database/SqlDatabase.cs +++ b/Geekbot.net/Database/SqlDatabase.cs @@ -1,5 +1,4 @@ using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Logging; namespace Geekbot.net.Database { @@ -13,7 +12,6 @@ namespace Geekbot.net.Database } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - => optionsBuilder.UseLoggerFactory(new LoggerFactory().AddConsole()) - .UseMySql(_connectionString.ToString()); + => optionsBuilder.UseNpgsql(_connectionString.ToString()); } } \ No newline at end of file diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index f8554c9..8e01709 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -32,15 +32,15 @@ + + - - 1.2.6 - + diff --git a/Geekbot.net/Lib/Extensions/LongExtensions.cs b/Geekbot.net/Lib/Extensions/LongExtensions.cs new file mode 100644 index 0000000..1bcdd9b --- /dev/null +++ b/Geekbot.net/Lib/Extensions/LongExtensions.cs @@ -0,0 +1,12 @@ +using System; + +namespace Geekbot.net.Lib.Extensions +{ + public static class LongExtensions + { + public static ulong AsUlong(this long thing) + { + return Convert.ToUInt64(thing); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Extensions/UlongExtensions.cs b/Geekbot.net/Lib/Extensions/UlongExtensions.cs new file mode 100644 index 0000000..8fa2a67 --- /dev/null +++ b/Geekbot.net/Lib/Extensions/UlongExtensions.cs @@ -0,0 +1,12 @@ +using System; + +namespace Geekbot.net.Lib.Extensions +{ + public static class UlongExtensions + { + public static long AsLong(this ulong thing) + { + return Convert.ToInt64(thing); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Logger/GeekbotLogger.cs b/Geekbot.net/Lib/Logger/GeekbotLogger.cs index b2bb677..09a3ecb 100644 --- a/Geekbot.net/Lib/Logger/GeekbotLogger.cs +++ b/Geekbot.net/Lib/Logger/GeekbotLogger.cs @@ -49,6 +49,16 @@ namespace Geekbot.net.Lib.Logger else _logger.Error(stackTrace, CreateLogString("Error", source, message, stackTrace, extra)); } + public NLog.Logger GetNLogger() + { + return _logger; + } + + public bool LogAsJson() + { + return _logAsJson; + } + private string CreateLogString(string type, LogSource source, string message, Exception stackTrace = null, object extra = null) { if (_logAsJson) diff --git a/Geekbot.net/Lib/Logger/IGeekbotLogger.cs b/Geekbot.net/Lib/Logger/IGeekbotLogger.cs index 1f76cb0..944524a 100644 --- a/Geekbot.net/Lib/Logger/IGeekbotLogger.cs +++ b/Geekbot.net/Lib/Logger/IGeekbotLogger.cs @@ -9,5 +9,7 @@ namespace Geekbot.net.Lib.Logger void Information(LogSource source, string message, object extra = null); void Warning(LogSource source, string message, Exception stackTrace = null, object extra = null); void Error(LogSource source, string message, Exception stackTrace, object extra = null); + NLog.Logger GetNLogger(); + bool LogAsJson(); } } \ No newline at end of file diff --git a/Geekbot.net/Lib/Logger/LogSource.cs b/Geekbot.net/Lib/Logger/LogSource.cs index d9a8629..cccc930 100644 --- a/Geekbot.net/Lib/Logger/LogSource.cs +++ b/Geekbot.net/Lib/Logger/LogSource.cs @@ -11,6 +11,7 @@ namespace Geekbot.net.Lib.Logger Gateway, Discord, Redis, + Database, Message, UserRepository, Command, diff --git a/Geekbot.net/Lib/Logger/LoggerFactory.cs b/Geekbot.net/Lib/Logger/LoggerFactory.cs index 4095d00..9c5f759 100644 --- a/Geekbot.net/Lib/Logger/LoggerFactory.cs +++ b/Geekbot.net/Lib/Logger/LoggerFactory.cs @@ -34,7 +34,7 @@ namespace Geekbot.net.Lib.Logger { var minLevel = runParameters.Verbose ? LogLevel.Trace : LogLevel.Info; config.LoggingRules.Add( - new LoggingRule("*", LogLevel.Info, LogLevel.Fatal, + new LoggingRule("*", minLevel, LogLevel.Fatal, new ColoredConsoleTarget { Name = "Console", diff --git a/Geekbot.net/Lib/RunParameters.cs b/Geekbot.net/Lib/RunParameters.cs index 1e1048b..5485533 100644 --- a/Geekbot.net/Lib/RunParameters.cs +++ b/Geekbot.net/Lib/RunParameters.cs @@ -5,6 +5,9 @@ namespace Geekbot.net.Lib { public class RunParameters { + /** + * General Parameters + */ [Option('V', "verbose", Default = false, HelpText = "Prints all messages to standard output.")] public bool Verbose { get; set; } @@ -23,7 +26,26 @@ namespace Geekbot.net.Lib [Option("token", Default = null, HelpText = "Set a new bot token")] public string Token { get; set; } - [Option("in-memory", Default = false, HelpText = "Disables the web api")] + /** + * Database Stuff + */ + [Option("in-memory", Default = false, HelpText = "Uses the in-memory database instead of postgresql")] public bool InMemory { get; set; } + + // Postresql connection + [Option("database", Default = false, HelpText = "Select a postgresql database")] + public string DbDatabase { get; set; } = "geekbot"; + + [Option("db-host", Default = false, HelpText = "Set a postgresql host (e.g. 127.0.0.1)")] + public string DbHost { get; set; } = "localhost"; + + [Option("db-port", Default = false, HelpText = "Set a postgresql host (e.g. 5432)")] + public string DbPort { get; set; } = "5432"; + + [Option("db-user", Default = false, HelpText = "Set a postgresql user")] + public string DbUser { get; set; } = "geekbot"; + + [Option("db-password", Default = false, HelpText = "Set a posgresql password")] + public string DbPassword { get; set; } = ""; } } \ No newline at end of file From 15034d63a33dbf00daedf50a2ae2f8fbed9ed27f Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 10 May 2018 02:00:26 +0200 Subject: [PATCH 169/553] Port UserRepository and remove OW stuff --- Geekbot.net/Commands/Admin/Owner.cs | 5 +- Geekbot.net/Commands/Games/BattleTag.cs | 72 ---------- Geekbot.net/Commands/Games/Overwatch.cs | 131 ------------------ Geekbot.net/Commands/User/Ranking/Rank.cs | 2 +- Geekbot.net/Commands/Utils/Quote/Quote.cs | 4 +- Geekbot.net/Database/DatabaseContext.cs | 13 +- Geekbot.net/Database/DatabaseInitializer.cs | 2 + .../Database/Models/GuildSettingsModel.cs | 24 +++- Geekbot.net/Database/Models/GuildsModel.cs | 17 ++- Geekbot.net/Database/Models/KarmaModel.cs | 16 ++- Geekbot.net/Database/Models/ShipsModel.cs | 11 +- Geekbot.net/Database/Models/SlapsModel.cs | 15 +- Geekbot.net/Database/Models/UserModel.cs | 25 +++- .../Database/Models/UserSettingsModel.cs | 15 ++ Geekbot.net/Geekbot.net.csproj | 1 - Geekbot.net/Handlers.cs | 12 +- .../Lib/UserRepository/IUserRepository.cs | 5 +- .../Lib/UserRepository/UserRepository.cs | 116 +++++----------- .../UserRepository/UserRepositoryUserDto.cs | 16 --- Geekbot.net/Program.cs | 2 +- 20 files changed, 176 insertions(+), 328 deletions(-) delete mode 100644 Geekbot.net/Commands/Games/BattleTag.cs delete mode 100644 Geekbot.net/Commands/Games/Overwatch.cs create mode 100644 Geekbot.net/Database/Models/UserSettingsModel.cs delete mode 100644 Geekbot.net/Lib/UserRepository/UserRepositoryUserDto.cs diff --git a/Geekbot.net/Commands/Admin/Owner.cs b/Geekbot.net/Commands/Admin/Owner.cs index 2d097e0..10cbfd7 100644 --- a/Geekbot.net/Commands/Admin/Owner.cs +++ b/Geekbot.net/Commands/Admin/Owner.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.WebSocket; +using Geekbot.net.Database; using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Logger; @@ -17,17 +18,19 @@ namespace Geekbot.net.Commands.Admin { private readonly DiscordSocketClient _client; private readonly IErrorHandler _errorHandler; + private readonly DatabaseContext _database; private readonly IGeekbotLogger _logger; private readonly IDatabase _redis; private readonly IUserRepository _userRepository; - public Owner(IDatabase redis, DiscordSocketClient client, IGeekbotLogger logger, IUserRepository userRepositry, IErrorHandler errorHandler) + public Owner(IDatabase redis, DiscordSocketClient client, IGeekbotLogger logger, IUserRepository userRepositry, IErrorHandler errorHandler, DatabaseContext database) { _redis = redis; _client = client; _logger = logger; _userRepository = userRepositry; _errorHandler = errorHandler; + _database = database; } [Command("youtubekey", RunMode = RunMode.Async)] diff --git a/Geekbot.net/Commands/Games/BattleTag.cs b/Geekbot.net/Commands/Games/BattleTag.cs deleted file mode 100644 index 88cc0d8..0000000 --- a/Geekbot.net/Commands/Games/BattleTag.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -using System.Threading.Tasks; -using Discord.Commands; -using Geekbot.net.Lib; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.UserRepository; - -namespace Geekbot.net.Commands.Games -{ - [Group("battletag")] - public class BattleTag : ModuleBase - { - private readonly IErrorHandler _errorHandler; - private readonly IUserRepository _userRepository; - - public BattleTag(IErrorHandler errorHandler, IUserRepository userRepository) - { - _errorHandler = errorHandler; - _userRepository = userRepository; - } - - [Command(RunMode = RunMode.Async)] - [Remarks(CommandCategories.Games)] - [Summary("Get your battletag")] - public async Task BattleTagCmd() - { - try - { - var tag = _userRepository.GetUserSetting(Context.User.Id, "BattleTag"); - if (!string.IsNullOrEmpty(tag)) - await ReplyAsync($"Your BattleTag is {tag}"); - else - await ReplyAsync("You haven't set your BattleTag, set it with `!battletag user#1234`"); - } - catch (Exception e) - { - _errorHandler.HandleCommandException(e, Context); - } - } - - [Command(RunMode = RunMode.Async)] - [Remarks(CommandCategories.Games)] - [Summary("Save your battletag")] - public async Task BattleTagCmd([Summary("Battletag")] string tag) - { - try - { - if (IsValidTag(tag)) - { - _userRepository.SaveUserSetting(Context.User.Id, "BattleTag", tag); - await ReplyAsync("Saved!"); - } - else - { - await ReplyAsync("That doesn't seem to be a valid battletag"); - } - } - catch (Exception e) - { - _errorHandler.HandleCommandException(e, Context); - } - } - - public static bool IsValidTag(string tag) - { - var splited = tag.Split("#"); - if (splited.Length != 2) return false; - if (!int.TryParse(splited[1], out var discriminator)) return false; - return splited[1].Length == 4 || splited[1].Length == 5; - } - } -} \ No newline at end of file diff --git a/Geekbot.net/Commands/Games/Overwatch.cs b/Geekbot.net/Commands/Games/Overwatch.cs deleted file mode 100644 index 73e5858..0000000 --- a/Geekbot.net/Commands/Games/Overwatch.cs +++ /dev/null @@ -1,131 +0,0 @@ -using System; -using System.Threading.Tasks; -using Discord; -using Discord.Commands; -using Geekbot.net.Lib; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.UserRepository; -using OverwatchAPI; -using OverwatchAPI.Config; - -namespace Geekbot.net.Commands.Games -{ - [Group("ow")] - public class Overwatch : ModuleBase - { - private readonly IErrorHandler _errorHandler; - private readonly IUserRepository _userRepository; - - public Overwatch(IErrorHandler errorHandler, IUserRepository userRepository) - { - _errorHandler = errorHandler; - _userRepository = userRepository; - } - - [Command("profile", RunMode = RunMode.Async)] - [Summary("Get someones overwatch profile. EU on PC only. Default battletag is your own (if set).")] - [Remarks(CommandCategories.Games)] - public async Task OwProfile() - { - try - { - var tag = _userRepository.GetUserSetting(Context.User.Id, "BattleTag"); - if (string.IsNullOrEmpty(tag)) - { - await ReplyAsync("You have no battle Tag saved, use `!battletag`"); - return; - } - - var profile = await CreateProfile(tag); - if (profile == null) - { - await ReplyAsync("That player doesn't seem to exist"); - return; - } - - await ReplyAsync("", false, profile.Build()); - } - catch (Exception e) - { - _errorHandler.HandleCommandException(e, Context); - } - } - - [Command("profile", RunMode = RunMode.Async)] - [Summary("Get someones overwatch profile. EU on PC only. Default battletag is your own (if set).")] - [Remarks(CommandCategories.Games)] - public async Task OwProfile([Summary("BattleTag")] string tag) - { - try - { - if (!BattleTag.IsValidTag(tag)) - { - await ReplyAsync("That doesn't seem to be a valid battletag..."); - return; - } - - var profile = await CreateProfile(tag); - if (profile == null) - { - await ReplyAsync("That player doesn't seem to exist"); - return; - } - - await ReplyAsync("", false, profile.Build()); - } - catch (Exception e) - { - _errorHandler.HandleCommandException(e, Context); - } - } - - [Command("profile", RunMode = RunMode.Async)] - [Summary("Get someones overwatch profile. EU on PC only.")] - [Remarks(CommandCategories.Games)] - public async Task OwProfile([Summary("@someone")] IUser user) - { - try - { - var tag = _userRepository.GetUserSetting(user.Id, "BattleTag"); - if (string.IsNullOrEmpty(tag)) - { - await ReplyAsync("This user didn't set a battletag"); - return; - } - - var profile = await CreateProfile(tag); - if (profile == null) - { - await ReplyAsync("That player doesn't seem to exist"); - return; - } - - await ReplyAsync("", false, profile.Build()); - } - catch (Exception e) - { - _errorHandler.HandleCommandException(e, Context); - } - } - - private async Task CreateProfile(string battletag) - { - var owConfig = new OverwatchConfig.Builder().WithPlatforms(Platform.Pc); - using (var owClient = new OverwatchClient(owConfig)) - { - var player = await owClient.GetPlayerAsync(battletag); - if (player.Username == null) return null; - var eb = new EmbedBuilder(); - eb.WithAuthor(new EmbedAuthorBuilder() - .WithIconUrl(player.ProfilePortraitUrl) - .WithName(player.Username)); - eb.Url = player.ProfileUrl; - eb.AddInlineField("Level", player.PlayerLevel); - eb.AddInlineField("Current Rank", - player.CompetitiveRank > 0 ? player.CompetitiveRank.ToString() : "Unranked"); - - return eb; - } - } - } -} \ No newline at end of file diff --git a/Geekbot.net/Commands/User/Ranking/Rank.cs b/Geekbot.net/Commands/User/Ranking/Rank.cs index 08d4d3b..e0fbfa0 100644 --- a/Geekbot.net/Commands/User/Ranking/Rank.cs +++ b/Geekbot.net/Commands/User/Ranking/Rank.cs @@ -81,7 +81,7 @@ namespace Geekbot.net.Commands.User.Ranking try { var guildUser = _userRepository.Get((ulong) user.Name); - if (guildUser.Username != null) + if (guildUser?.Username != null) { highscoreUsers.Add(new RankUserPolyfillDto { diff --git a/Geekbot.net/Commands/Utils/Quote/Quote.cs b/Geekbot.net/Commands/Utils/Quote/Quote.cs index 18eab22..71c4089 100644 --- a/Geekbot.net/Commands/Utils/Quote/Quote.cs +++ b/Geekbot.net/Commands/Utils/Quote/Quote.cs @@ -18,11 +18,9 @@ namespace Geekbot.net.Commands.Utils.Quote { private readonly IErrorHandler _errorHandler; private readonly DatabaseContext _database; - private readonly IDatabase _redis; - public Quote(IDatabase redis, IErrorHandler errorHandler, DatabaseContext database) + public Quote(IErrorHandler errorHandler, DatabaseContext database) { - _redis = redis; _errorHandler = errorHandler; _database = database; } diff --git a/Geekbot.net/Database/DatabaseContext.cs b/Geekbot.net/Database/DatabaseContext.cs index 4426c8d..028a4f5 100644 --- a/Geekbot.net/Database/DatabaseContext.cs +++ b/Geekbot.net/Database/DatabaseContext.cs @@ -6,12 +6,13 @@ namespace Geekbot.net.Database public class DatabaseContext : DbContext { public DbSet Quotes { get; set; } -// public DbSet Users { get; set; } -// public DbSet Guilds { get; set; } -// public DbSet GuildSettings { get; set; } -// public DbSet Karma { get; set; } -// public DbSet Ships { get; set; } + public DbSet Users { get; set; } + public DbSet Guilds { get; set; } + public DbSet GuildSettings { get; set; } + public DbSet Karma { get; set; } + public DbSet Ships { get; set; } + public DbSet SlapsModels { get; set; } +// public DbSet UserSettings { get; set; } // public DbSet RoleSelfService { get; set; } -// public DbSet SlapsModels { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Database/DatabaseInitializer.cs b/Geekbot.net/Database/DatabaseInitializer.cs index f4bb8f1..83660bb 100644 --- a/Geekbot.net/Database/DatabaseInitializer.cs +++ b/Geekbot.net/Database/DatabaseInitializer.cs @@ -2,6 +2,7 @@ using Geekbot.net.Database.LoggingAdapter; using Geekbot.net.Lib; using Geekbot.net.Lib.Logger; +using Microsoft.EntityFrameworkCore; using Npgsql.Logging; namespace Geekbot.net.Database @@ -39,6 +40,7 @@ namespace Geekbot.net.Database }); } database.Database.EnsureCreated(); + database.Database.Migrate(); } catch (Exception e) { diff --git a/Geekbot.net/Database/Models/GuildSettingsModel.cs b/Geekbot.net/Database/Models/GuildSettingsModel.cs index b8ae300..a71aac1 100644 --- a/Geekbot.net/Database/Models/GuildSettingsModel.cs +++ b/Geekbot.net/Database/Models/GuildSettingsModel.cs @@ -1,7 +1,29 @@ -namespace Geekbot.net.Database.Models +using System.ComponentModel.DataAnnotations; + +namespace Geekbot.net.Database.Models { public class GuildSettingsModel { + [Key] + public int Id { get; set; } + [Required] + public long GuildId { get; set; } + + public bool Ping { get; set; } + + public bool Hui { get; set; } + + public long ModChannel { get; set; } + + public string WelcomeMessage { get; set; } + + public bool ShowDelete { get; set; } + + public bool ShowLeave { get; set; } + + public string WikiLang { get; set; } + + public string Language { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Database/Models/GuildsModel.cs b/Geekbot.net/Database/Models/GuildsModel.cs index 0b8ec3c..515231a 100644 --- a/Geekbot.net/Database/Models/GuildsModel.cs +++ b/Geekbot.net/Database/Models/GuildsModel.cs @@ -1,7 +1,22 @@ -namespace Geekbot.net.Database.Models +using System.ComponentModel.DataAnnotations; + +namespace Geekbot.net.Database.Models { public class GuildsModel { + [Key] + public int Id { get; set; } + [Required] + public long GuildId { get; set; } + + [Required] + public string Name { get; set; } + + [Required] + public string Owner { get; set; } + + [Required] + public string IconUrl { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Database/Models/KarmaModel.cs b/Geekbot.net/Database/Models/KarmaModel.cs index d29f313..7d5f533 100644 --- a/Geekbot.net/Database/Models/KarmaModel.cs +++ b/Geekbot.net/Database/Models/KarmaModel.cs @@ -1,7 +1,21 @@ -namespace Geekbot.net.Database.Models +using System; +using System.ComponentModel.DataAnnotations; + +namespace Geekbot.net.Database.Models { public class KarmaModel { + [Key] + public int Id { get; set; } + [Required] + public long GuildId { get; set; } + + [Required] + public long UserId { get; set; } + + public int Karma { get; set; } + + public DateTimeOffset TimeOut { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Database/Models/ShipsModel.cs b/Geekbot.net/Database/Models/ShipsModel.cs index 6eda191..d8156b0 100644 --- a/Geekbot.net/Database/Models/ShipsModel.cs +++ b/Geekbot.net/Database/Models/ShipsModel.cs @@ -1,7 +1,16 @@ -namespace Geekbot.net.Database.Models +using System.ComponentModel.DataAnnotations; + +namespace Geekbot.net.Database.Models { public class ShipsModel { + [Key] + public int Id { get; set; } + public long FirstUserId { get; set; } + + public long SecondUserId { get; set; } + + public int Strength { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Database/Models/SlapsModel.cs b/Geekbot.net/Database/Models/SlapsModel.cs index 80ee199..6c402aa 100644 --- a/Geekbot.net/Database/Models/SlapsModel.cs +++ b/Geekbot.net/Database/Models/SlapsModel.cs @@ -1,7 +1,20 @@ -namespace Geekbot.net.Database.Models +using System.ComponentModel.DataAnnotations; + +namespace Geekbot.net.Database.Models { public class SlapsModel { + [Key] + public int Id { get; set; } + [Required] + public long GuildId { get; set; } + + [Required] + public long UserId { get; set; } + + public int Given { get; set; } + + public int Recieved { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Database/Models/UserModel.cs b/Geekbot.net/Database/Models/UserModel.cs index d68f178..0083ada 100644 --- a/Geekbot.net/Database/Models/UserModel.cs +++ b/Geekbot.net/Database/Models/UserModel.cs @@ -1,7 +1,30 @@ -namespace Geekbot.net.Database.Models +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace Geekbot.net.Database.Models { public class UserModel { + [Key] + public int Id { get; set; } + [Required] + public long UserId { get; set; } + + [Required] + public string Username { get; set; } + + [Required] + public string Discriminator { get; set; } + + public string AvatarUrl { get; set; } + + [Required] + public bool IsBot { get; set; } + + public DateTimeOffset Joined { get; set; } + + public string[] UsedNames { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Database/Models/UserSettingsModel.cs b/Geekbot.net/Database/Models/UserSettingsModel.cs new file mode 100644 index 0000000..659ef1d --- /dev/null +++ b/Geekbot.net/Database/Models/UserSettingsModel.cs @@ -0,0 +1,15 @@ +using System.ComponentModel.DataAnnotations; + +namespace Geekbot.net.Database.Models +{ + public class UserSettingsModel + { + [Key] + public int Id { get; set; } + + [Required] + public long UserId { get; set; } + + // stuff to be added in the future + } +} \ No newline at end of file diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 8e01709..9141772 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -34,7 +34,6 @@ - diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index f248d5d..1515920 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -103,7 +103,7 @@ namespace Geekbot.net // User Stuff // - public Task UserJoined(SocketGuildUser user) + public async Task UserJoined(SocketGuildUser user) { try { @@ -113,23 +113,21 @@ namespace Geekbot.net if (!message.IsNullOrEmpty) { message = message.ToString().Replace("$user", user.Mention); - user.Guild.DefaultChannel.SendMessageAsync(message); + await user.Guild.DefaultChannel.SendMessageAsync(message); } } - _userRepository.Update(user); + await _userRepository.Update(user); _logger.Information(LogSource.Geekbot, $"{user.Username} ({user.Id}) joined {user.Guild.Name} ({user.Guild.Id})"); } catch (Exception e) { _logger.Error(LogSource.Geekbot, "Failed to send welcome message", e); } - return Task.CompletedTask; } - public Task UserUpdated(SocketUser oldUser, SocketUser newUser) + public async Task UserUpdated(SocketUser oldUser, SocketUser newUser) { - _userRepository.Update(newUser); - return Task.CompletedTask; + await _userRepository.Update(newUser); } public async Task UserLeft(SocketGuildUser user) diff --git a/Geekbot.net/Lib/UserRepository/IUserRepository.cs b/Geekbot.net/Lib/UserRepository/IUserRepository.cs index 9466621..b2f9a1f 100644 --- a/Geekbot.net/Lib/UserRepository/IUserRepository.cs +++ b/Geekbot.net/Lib/UserRepository/IUserRepository.cs @@ -1,13 +1,12 @@ using System.Threading.Tasks; using Discord.WebSocket; +using Geekbot.net.Database.Models; namespace Geekbot.net.Lib.UserRepository { public interface IUserRepository { Task Update(SocketUser user); - UserRepositoryUser Get(ulong userId); - string GetUserSetting(ulong userId, string setting); - bool SaveUserSetting(ulong userId, string setting, string value); + UserModel Get(ulong userId); } } \ No newline at end of file diff --git a/Geekbot.net/Lib/UserRepository/UserRepository.cs b/Geekbot.net/Lib/UserRepository/UserRepository.cs index 3937107..0125ee5 100644 --- a/Geekbot.net/Lib/UserRepository/UserRepository.cs +++ b/Geekbot.net/Lib/UserRepository/UserRepository.cs @@ -1,125 +1,81 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Discord.WebSocket; +using Geekbot.net.Database; +using Geekbot.net.Database.Models; +using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Logger; -using StackExchange.Redis; -using Utf8Json; namespace Geekbot.net.Lib.UserRepository { public class UserRepository : IUserRepository { - private readonly IDatabase _redis; + private readonly DatabaseContext _database; private readonly IGeekbotLogger _logger; - public UserRepository(IDatabase redis, IGeekbotLogger logger) + public UserRepository(DatabaseContext database, IGeekbotLogger logger) { - _redis = redis; + _database = database; _logger = logger; } - public Task Update(SocketUser user) + public async Task Update(SocketUser user) { try { var savedUser = Get(user.Id); - savedUser.Id = user.Id; + var isNew = false; + if (savedUser == null) + { + savedUser = new UserModel(); + isNew = true; + } + savedUser.UserId = user.Id.AsLong(); savedUser.Username = user.Username; savedUser.Discriminator = user.Discriminator; - savedUser.AvatarUrl = user.GetAvatarUrl() ?? "0"; + savedUser.AvatarUrl = user.GetAvatarUrl() ?? ""; savedUser.IsBot = user.IsBot; savedUser.Joined = user.CreatedAt; - if(savedUser.UsedNames == null) savedUser.UsedNames = new List(); + if (savedUser.UsedNames == null) savedUser.UsedNames = Enumerable.Empty().ToArray(); if (!savedUser.UsedNames.Contains(user.Username)) { - savedUser.UsedNames.Add(user.Username); + savedUser.UsedNames = savedUser.UsedNames.Concat(new[] {user.Username}).ToArray(); } - Store(savedUser); - + + if (isNew) + { + await _database.Users.AddAsync(savedUser); + } + else + { + _database.Users.Update(savedUser); + } + + await _database.SaveChangesAsync(); + _logger.Information(LogSource.UserRepository, "Updated User", savedUser); - return Task.FromResult(true); + await Task.Delay(500); + return true; } catch (Exception e) { _logger.Warning(LogSource.UserRepository, $"Failed to update user: {user.Username}#{user.Discriminator} ({user.Id})", e); - return Task.FromResult(false); + return false; } } - private void Store(UserRepositoryUser user) - { - _redis.HashSetAsync($"Users:{user.Id.ToString()}", new[] - { - new HashEntry("Id", user.Id.ToString()), - new HashEntry("Username", user.Username), - new HashEntry("Discriminator", user.Discriminator), - new HashEntry("AvatarUrl", user.AvatarUrl), - new HashEntry("IsBot", user.IsBot), - new HashEntry("Joined", user.Joined.ToString()), - new HashEntry("UsedNames", JsonSerializer.Serialize(user.UsedNames)) - }); - } - - public UserRepositoryUser Get(ulong userId) + public UserModel Get(ulong userId) { try { - var user = _redis.HashGetAll($"Users:{userId.ToString()}"); - for (var i = 1; i < 11; i++) - { - if (user.Length != 0) break; - user = _redis.HashGetAll($"Users:{(userId + (ulong) i).ToString()}"); - - } - var dto = new UserRepositoryUser(); - foreach (var a in user.ToDictionary()) - { - switch (a.Key) - { - case "Id": - dto.Id = ulong.Parse(a.Value); - break; - case "Username": - dto.Username = a.Value.ToString(); - break; - case "Discriminator": - dto.Discriminator = a.Value.ToString(); - break; - case "AvatarUrl": - dto.AvatarUrl = a.Value != "0" ? a.Value.ToString() : null; - break; - case "IsBot": - dto.IsBot = a.Value == 1; - break; - case "Joined": - dto.Joined = DateTimeOffset.Parse(a.Value.ToString()); - break; - case "UsedNames": - dto.UsedNames = JsonSerializer.Deserialize>(a.Value.ToString()) ?? new List(); - break; - } - } - return dto; + return _database.Users.FirstOrDefault(u => u.UserId.Equals(userId.AsLong())); } catch (Exception e) { _logger.Warning(LogSource.UserRepository, $"Failed to get {userId} from repository", e); - return new UserRepositoryUser(); + return null; } } - - public string GetUserSetting(ulong userId, string setting) - { - return _redis.HashGet($"Users:{userId}", setting); - } - - public bool SaveUserSetting(ulong userId, string setting, string value) - { - _redis.HashSet($"Users:{userId}", new[] - { - new HashEntry(setting, value) - }); - return true; - } } } \ No newline at end of file diff --git a/Geekbot.net/Lib/UserRepository/UserRepositoryUserDto.cs b/Geekbot.net/Lib/UserRepository/UserRepositoryUserDto.cs deleted file mode 100644 index 4af719b..0000000 --- a/Geekbot.net/Lib/UserRepository/UserRepositoryUserDto.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Geekbot.net.Lib.UserRepository -{ - public class UserRepositoryUser - { - public ulong Id { get; set; } - public string Username { get; set; } - public string Discriminator { get; set; } - public string AvatarUrl { get; set; } - public bool IsBot { get; set; } - public DateTimeOffset Joined { get; set; } - public List UsedNames { get; set; } - } -} \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 4fa763d..ee05a12 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -111,7 +111,7 @@ namespace Geekbot.net _services = new ServiceCollection(); - _userRepository = new UserRepository(_redis, logger); + _userRepository = new UserRepository(database, logger); var fortunes = new FortunesProvider(logger); var mediaProvider = new MediaProvider(logger); var malClient = new MalClient(_redis, logger); From 5117e7609f6115b287444bafd472b5cd699f8a0b Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 10 May 2018 02:33:10 +0200 Subject: [PATCH 170/553] Port !karma --- Geekbot.net/Commands/User/Karma.cs | 82 +++++++++++++++++++++--------- Geekbot.net/Geekbot.net.csproj | 2 +- 2 files changed, 58 insertions(+), 26 deletions(-) diff --git a/Geekbot.net/Commands/User/Karma.cs b/Geekbot.net/Commands/User/Karma.cs index d6244a8..b63951e 100644 --- a/Geekbot.net/Commands/User/Karma.cs +++ b/Geekbot.net/Commands/User/Karma.cs @@ -1,23 +1,26 @@ using System; +using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.net.Database; +using Geekbot.net.Database.Models; using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Localization; -using StackExchange.Redis; namespace Geekbot.net.Commands.User { public class Karma : ModuleBase { private readonly IErrorHandler _errorHandler; - private readonly IDatabase _redis; + private readonly DatabaseContext _database; private readonly ITranslationHandler _translation; - public Karma(IDatabase redis, IErrorHandler errorHandler, ITranslationHandler translation) + public Karma(DatabaseContext database, IErrorHandler errorHandler, ITranslationHandler translation) { - _redis = redis; + _database = database; _errorHandler = errorHandler; _translation = translation; } @@ -30,22 +33,26 @@ namespace Geekbot.net.Commands.User try { var transDict = _translation.GetDict(Context); - var lastKarmaFromRedis = _redis.HashGet($"{Context.Guild.Id}:KarmaTimeout", Context.User.Id.ToString()); - var lastKarma = ConvertToDateTimeOffset(lastKarmaFromRedis.ToString()); + var actor = GetUser(Context.User.Id); if (user.Id == Context.User.Id) { await ReplyAsync(string.Format(transDict["CannotChangeOwn"], Context.User.Username)); } - else if (TimeoutFinished(lastKarma)) + else if (TimeoutFinished(actor.TimeOut)) { await ReplyAsync(string.Format(transDict["WaitUntill"], Context.User.Username, - GetTimeLeft(lastKarma))); + GetTimeLeft(actor.TimeOut))); } else { - var newKarma = _redis.HashIncrement($"{Context.Guild.Id}:Karma", user.Id.ToString()); - _redis.HashSet($"{Context.Guild.Id}:KarmaTimeout", - new[] {new HashEntry(Context.User.Id.ToString(), DateTimeOffset.Now.ToString("u"))}); + var target = GetUser(user.Id); + target.Karma = target.Karma + 1; + SetUser(target); + + actor.TimeOut = DateTimeOffset.Now; + SetUser(actor); + + _database.SaveChanges(); var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder() @@ -56,7 +63,7 @@ namespace Geekbot.net.Commands.User eb.Title = transDict["Increased"]; eb.AddInlineField(transDict["By"], Context.User.Username); eb.AddInlineField(transDict["Amount"], "+1"); - eb.AddInlineField(transDict["Current"], newKarma); + eb.AddInlineField(transDict["Current"], target.Karma); await ReplyAsync("", false, eb.Build()); } } @@ -74,22 +81,26 @@ namespace Geekbot.net.Commands.User try { var transDict = _translation.GetDict(Context); - var lastKarmaFromRedis = _redis.HashGet($"{Context.Guild.Id}:KarmaTimeout", Context.User.Id.ToString()); - var lastKarma = ConvertToDateTimeOffset(lastKarmaFromRedis.ToString()); + var actor = GetUser(Context.User.Id); if (user.Id == Context.User.Id) { await ReplyAsync(string.Format(transDict["CannotChangeOwn"], Context.User.Username)); } - else if (TimeoutFinished(lastKarma)) + else if (TimeoutFinished(actor.TimeOut)) { await ReplyAsync(string.Format(transDict["WaitUntill"], Context.User.Username, - GetTimeLeft(lastKarma))); + GetTimeLeft(actor.TimeOut))); } else { - var newKarma = _redis.HashDecrement($"{Context.Guild.Id}:Karma", user.Id.ToString()); - _redis.HashSet($"{Context.Guild.Id}:KarmaTimeout", - new[] {new HashEntry(Context.User.Id.ToString(), DateTimeOffset.Now.ToString())}); + var target = GetUser(user.Id); + target.Karma = target.Karma - 1; + SetUser(target); + + actor.TimeOut = DateTimeOffset.Now; + SetUser(actor); + + _database.SaveChanges(); var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder() @@ -100,7 +111,7 @@ namespace Geekbot.net.Commands.User eb.Title = transDict["Decreased"]; eb.AddInlineField(transDict["By"], Context.User.Username); eb.AddInlineField(transDict["Amount"], "-1"); - eb.AddInlineField(transDict["Current"], newKarma); + eb.AddInlineField(transDict["Current"], target.Karma); await ReplyAsync("", false, eb.Build()); } } @@ -110,11 +121,6 @@ namespace Geekbot.net.Commands.User } } - private DateTimeOffset ConvertToDateTimeOffset(string dateTimeOffsetString) - { - return string.IsNullOrEmpty(dateTimeOffsetString) ? DateTimeOffset.Now.Subtract(new TimeSpan(7, 18, 0, 0)) : DateTimeOffset.Parse(dateTimeOffsetString); - } - private bool TimeoutFinished(DateTimeOffset lastKarma) { return lastKarma.AddMinutes(3) > DateTimeOffset.Now; @@ -125,5 +131,31 @@ namespace Geekbot.net.Commands.User var dt = lastKarma.AddMinutes(3).Subtract(DateTimeOffset.Now); return $"{dt.Minutes} Minutes and {dt.Seconds} Seconds"; } + + private KarmaModel GetUser(ulong userId) + { + var user = _database.Karma.FirstOrDefault(u =>u.GuildId.Equals(Context.Guild.Id.AsLong()) && u.UserId.Equals(userId.AsLong())) ?? CreateNewRow(userId); + return user; + } + + private bool SetUser(KarmaModel user) + { + _database.Karma.Update(user); + return true; + } + + private KarmaModel CreateNewRow(ulong userId) + { + var user = new KarmaModel() + { + GuildId = Context.Guild.Id.AsLong(), + UserId = userId.AsLong(), + Karma = 0, + TimeOut = DateTimeOffset.MinValue + }; + var newUser = _database.Karma.Add(user).Entity; + _database.SaveChanges(); + return newUser; + } } } \ No newline at end of file diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 9141772..425eb9f 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -3,7 +3,7 @@ Exe netcoreapp2.0 derp.ico - 3.7.0 + 4.0.0 $(VersionSuffix) $(Version)-$(VersionSuffix) Pizza and Coffee Studios From 54bcd541d3dbe91c9215b0142fd2f7c088cbd559 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 10 May 2018 03:29:11 +0200 Subject: [PATCH 171/553] Fix run params --- Geekbot.net/Geekbot.net.csproj | 7 ++++++- Geekbot.net/Lib/RunParameters.cs | 22 +++++++++++----------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 425eb9f..33a1663 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -11,6 +11,11 @@ A Discord bot https://github.com/pizzaandcoffee/Geekbot.net NU1701 + git + https://geekbot.pizzaandcoffee.rocks + + + true @@ -88,4 +93,4 @@ - \ No newline at end of file + diff --git a/Geekbot.net/Lib/RunParameters.cs b/Geekbot.net/Lib/RunParameters.cs index 5485533..eb3ca37 100644 --- a/Geekbot.net/Lib/RunParameters.cs +++ b/Geekbot.net/Lib/RunParameters.cs @@ -17,7 +17,7 @@ namespace Geekbot.net.Lib [Option('j', "log-json", Default = false, HelpText = "Logs messages as json")] public bool LogJson { get; set; } - [Option("disable-api", Default = false, HelpText = "Disables the web api")] + [Option('a', "disable-api", Default = false, HelpText = "Disables the web api")] public bool DisableApi { get; set; } [Option('e', "expose-errors", Default = false, HelpText = "Shows internal errors in the chat")] @@ -33,19 +33,19 @@ namespace Geekbot.net.Lib public bool InMemory { get; set; } // Postresql connection - [Option("database", Default = false, HelpText = "Select a postgresql database")] - public string DbDatabase { get; set; } = "geekbot"; + [Option("database", Default = "geekbot", HelpText = "Select a postgresql database")] + public string DbDatabase { get; set; } - [Option("db-host", Default = false, HelpText = "Set a postgresql host (e.g. 127.0.0.1)")] - public string DbHost { get; set; } = "localhost"; + [Option("db-host", Default = "localhost", HelpText = "Set a postgresql host (e.g. 127.0.0.1)")] + public string DbHost { get; set; } - [Option("db-port", Default = false, HelpText = "Set a postgresql host (e.g. 5432)")] - public string DbPort { get; set; } = "5432"; + [Option("db-port", Default = "5432", HelpText = "Set a postgresql host (e.g. 5432)")] + public string DbPort { get; set; } - [Option("db-user", Default = false, HelpText = "Set a postgresql user")] - public string DbUser { get; set; } = "geekbot"; + [Option("db-user", Default = "geekbot", HelpText = "Set a postgresql user")] + public string DbUser { get; set; } - [Option("db-password", Default = false, HelpText = "Set a posgresql password")] - public string DbPassword { get; set; } = ""; + [Option("db-password", Default = "", HelpText = "Set a posgresql password")] + public string DbPassword { get; set; } } } \ No newline at end of file From b54b7cd7869b06c3f1e208fe7e8bcaee8950263a Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 10 May 2018 17:56:43 +0200 Subject: [PATCH 172/553] port !rank --- Geekbot.net/Commands/User/Ranking/Rank.cs | 141 ++++++++++++------ Geekbot.net/Commands/User/Ranking/RankType.cs | 9 ++ ...{RankUserPolyfillDto.cs => RankUserDto.cs} | 2 +- Geekbot.net/Database/DatabaseContext.cs | 2 + Geekbot.net/Database/Models/GuildsModel.cs | 5 +- Geekbot.net/Database/Models/MessagesModel.cs | 18 +++ Geekbot.net/Database/Models/RollsModel.cs | 18 +++ Geekbot.net/Geekbot.net.csproj | 2 +- 8 files changed, 145 insertions(+), 52 deletions(-) create mode 100644 Geekbot.net/Commands/User/Ranking/RankType.cs rename Geekbot.net/Commands/User/Ranking/{RankUserPolyfillDto.cs => RankUserDto.cs} (80%) create mode 100644 Geekbot.net/Database/Models/MessagesModel.cs create mode 100644 Geekbot.net/Database/Models/RollsModel.cs diff --git a/Geekbot.net/Commands/User/Ranking/Rank.cs b/Geekbot.net/Commands/User/Ranking/Rank.cs index e0fbfa0..9b1b32f 100644 --- a/Geekbot.net/Commands/User/Ranking/Rank.cs +++ b/Geekbot.net/Commands/User/Ranking/Rank.cs @@ -5,12 +5,13 @@ using System.Text; using System.Threading.Tasks; using Discord.Commands; using Discord.WebSocket; +using Geekbot.net.Database; using Geekbot.net.Lib; using Geekbot.net.Lib.Converters; using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Logger; using Geekbot.net.Lib.UserRepository; -using StackExchange.Redis; namespace Geekbot.net.Commands.User.Ranking { @@ -19,14 +20,14 @@ namespace Geekbot.net.Commands.User.Ranking private readonly IEmojiConverter _emojiConverter; private readonly IErrorHandler _errorHandler; private readonly IGeekbotLogger _logger; - private readonly IDatabase _redis; + private readonly DatabaseContext _database; private readonly IUserRepository _userRepository; private readonly DiscordSocketClient _client; - public Rank(IDatabase redis, IErrorHandler errorHandler, IGeekbotLogger logger, IUserRepository userRepository, + public Rank(DatabaseContext database, IErrorHandler errorHandler, IGeekbotLogger logger, IUserRepository userRepository, IEmojiConverter emojiConverter, DiscordSocketClient client) { - _redis = redis; + _database = database; _errorHandler = errorHandler; _logger = logger; _userRepository = userRepository; @@ -41,68 +42,76 @@ namespace Geekbot.net.Commands.User.Ranking { try { - var type = typeUnformated.ToCharArray().First().ToString().ToUpper() + typeUnformated.Substring(1); - - if (!type.Equals("Messages") && !type.Equals("Karma") && !type.Equals("Rolls")) + RankType type; + try + { + type = Enum.Parse(typeUnformated.ToLower()); + } + catch { await ReplyAsync("Valid types are '`messages`' '`karma`', '`rolls`'"); return; } + var replyBuilder = new StringBuilder(); - if (amount > 20) { - replyBuilder.AppendLine(":warning: Limiting to 20"); + replyBuilder.AppendLine(":warning: Limiting to 20\n"); amount = 20; } + + Dictionary list; - var messageList = _redis.HashGetAll($"{Context.Guild.Id}:{type}"); - if (messageList.Length == 0) + switch (type) { - await ReplyAsync($"No {type.ToLowerInvariant()} found on this server"); + case RankType.messages: + list = GetMessageList(amount); + break; + case RankType.karma: + list = GetKarmaList(amount); + break; + case RankType.rolls: + list = GetRollsList(amount); + break; + default: + list = new Dictionary(); + break; + } + + if (!list.Any()) + { + await ReplyAsync($"No {type} found on this server"); return; } - var sortedList = messageList.OrderByDescending(e => e.Value).ToList(); - var guildMessages = (int) sortedList.First().Value; - var theBot = sortedList.FirstOrDefault(e => e.Name.ToString().Equals(_client.CurrentUser.Id.ToString())); - if (!string.IsNullOrEmpty(theBot.Name)) - { - sortedList.Remove(theBot); - } - if (type == "Messages") sortedList.RemoveAt(0); - var highscoreUsers = new Dictionary(); - var listLimiter = 1; + var highscoreUsers = new Dictionary(); var failedToRetrieveUser = false; - foreach (var user in sortedList) + foreach (var user in list) { - if (listLimiter > amount) break; try { - var guildUser = _userRepository.Get((ulong) user.Name); + var guildUser = _userRepository.Get(user.Key); if (guildUser?.Username != null) { - highscoreUsers.Add(new RankUserPolyfillDto + highscoreUsers.Add(new RankUserDto { Username = guildUser.Username, Discriminator = guildUser.Discriminator - }, (int) user.Value); + }, user.Value); } else { - highscoreUsers.Add(new RankUserPolyfillDto + highscoreUsers.Add(new RankUserDto { - Id = user.Name - }, (int) user.Value); + Id = user.Key.ToString() + }, user.Value); failedToRetrieveUser = true; } - - listLimiter++; } - catch (Exception e) + catch { - _logger.Warning(LogSource.Geekbot, $"Could not retrieve user {user.Name}", e); + // ignore } } @@ -119,21 +128,7 @@ namespace Geekbot.net.Commands.User.Ranking ? $"**{user.Key.Username}#{user.Key.Discriminator}**" : $"**{user.Key.Id}**"); - switch (type) - { - case "Messages": - var percent = Math.Round((double) (100 * user.Value) / guildMessages, 2); - replyBuilder.Append($" - {percent}% of total - {user.Value} messages"); - break; - case "Karma": - replyBuilder.Append($" - {user.Value} Karma"); - break; - case "Rolls": - replyBuilder.Append($" - {user.Value} Guessed"); - break; - } - - replyBuilder.Append("\n"); + replyBuilder.Append($" - {user.Value} {type}\n"); highscorePlace++; } @@ -145,5 +140,53 @@ namespace Geekbot.net.Commands.User.Ranking _errorHandler.HandleCommandException(e, Context); } } + + private Dictionary GetMessageList(int amount) + { + var data = _database.Messages + .Where(k => k.GuildId.Equals(Context.Guild.Id.AsLong())) + .OrderByDescending(o => o.MessageCount) + .Take(amount); + + var dict = new Dictionary(); + foreach (var user in data) + { + dict.Add(user.UserId.AsUlong(), user.MessageCount); + } + + return dict; + } + + private Dictionary GetKarmaList(int amount) + { + var data = _database.Karma + .Where(k => k.GuildId.Equals(Context.Guild.Id.AsLong())) + .OrderByDescending(o => o.Karma) + .Take(amount); + + var dict = new Dictionary(); + foreach (var user in data) + { + dict.Add(user.UserId.AsUlong(), user.Karma); + } + + return dict; + } + + private Dictionary GetRollsList(int amount) + { + var data = _database.Rolls + .Where(k => k.GuildId.Equals(Context.Guild.Id.AsLong())) + .OrderByDescending(o => o.Rolls) + .Take(amount); + + var dict = new Dictionary(); + foreach (var user in data) + { + dict.Add(user.UserId.AsUlong(), user.Rolls); + } + + return dict; + } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/User/Ranking/RankType.cs b/Geekbot.net/Commands/User/Ranking/RankType.cs new file mode 100644 index 0000000..1e88ef0 --- /dev/null +++ b/Geekbot.net/Commands/User/Ranking/RankType.cs @@ -0,0 +1,9 @@ +namespace Geekbot.net.Commands.User.Ranking +{ + public enum RankType + { + messages, + karma, + rolls + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/User/Ranking/RankUserPolyfillDto.cs b/Geekbot.net/Commands/User/Ranking/RankUserDto.cs similarity index 80% rename from Geekbot.net/Commands/User/Ranking/RankUserPolyfillDto.cs rename to Geekbot.net/Commands/User/Ranking/RankUserDto.cs index 625c326..2ec518e 100644 --- a/Geekbot.net/Commands/User/Ranking/RankUserPolyfillDto.cs +++ b/Geekbot.net/Commands/User/Ranking/RankUserDto.cs @@ -1,6 +1,6 @@ namespace Geekbot.net.Commands.User.Ranking { - internal class RankUserPolyfillDto + internal class RankUserDto { public string Username { get; set; } public string Discriminator { get; set; } diff --git a/Geekbot.net/Database/DatabaseContext.cs b/Geekbot.net/Database/DatabaseContext.cs index 028a4f5..2768e2e 100644 --- a/Geekbot.net/Database/DatabaseContext.cs +++ b/Geekbot.net/Database/DatabaseContext.cs @@ -11,6 +11,8 @@ namespace Geekbot.net.Database public DbSet GuildSettings { get; set; } public DbSet Karma { get; set; } public DbSet Ships { get; set; } + public DbSet Rolls { get; set; } + public DbSet Messages { get; set; } public DbSet SlapsModels { get; set; } // public DbSet UserSettings { get; set; } // public DbSet RoleSelfService { get; set; } diff --git a/Geekbot.net/Database/Models/GuildsModel.cs b/Geekbot.net/Database/Models/GuildsModel.cs index 515231a..371bfd7 100644 --- a/Geekbot.net/Database/Models/GuildsModel.cs +++ b/Geekbot.net/Database/Models/GuildsModel.cs @@ -1,4 +1,5 @@ -using System.ComponentModel.DataAnnotations; +using System; +using System.ComponentModel.DataAnnotations; namespace Geekbot.net.Database.Models { @@ -18,5 +19,7 @@ namespace Geekbot.net.Database.Models [Required] public string IconUrl { get; set; } + + public DateTimeOffset CreatedAt { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Database/Models/MessagesModel.cs b/Geekbot.net/Database/Models/MessagesModel.cs new file mode 100644 index 0000000..31332e8 --- /dev/null +++ b/Geekbot.net/Database/Models/MessagesModel.cs @@ -0,0 +1,18 @@ +using System.ComponentModel.DataAnnotations; + +namespace Geekbot.net.Database.Models +{ + public class MessagesModel + { + [Key] + public int Id { get; set; } + + [Required] + public long GuildId { get; set; } + + [Required] + public long UserId { get; set; } + + public int MessageCount { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Database/Models/RollsModel.cs b/Geekbot.net/Database/Models/RollsModel.cs new file mode 100644 index 0000000..de9b82e --- /dev/null +++ b/Geekbot.net/Database/Models/RollsModel.cs @@ -0,0 +1,18 @@ +using System.ComponentModel.DataAnnotations; + +namespace Geekbot.net.Database.Models +{ + public class RollsModel + { + [Key] + public int Id { get; set; } + + [Required] + public long GuildId { get; set; } + + [Required] + public long UserId { get; set; } + + public int Rolls { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 33a1663..ff230b6 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -93,4 +93,4 @@ - + \ No newline at end of file From 9ecc224ae167dd89f308bfa64705f99f37d729b6 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 10 May 2018 20:12:31 +0200 Subject: [PATCH 173/553] Add ef cli tools --- Geekbot.net/Geekbot.net.csproj | 14 ++++++++++---- Tests/Tests.csproj | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index ff230b6..3c59bc7 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -22,14 +22,16 @@ 1.0.2 - + + - - - + + + + @@ -55,6 +57,10 @@ + + + PreserveNewest diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index c838db0..776acf6 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -5,7 +5,7 @@ NU1701 - + From 32ae82ca8d492943242b1c745fcfa36e0ce913ec Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 11 May 2018 00:36:29 +0200 Subject: [PATCH 174/553] Add simple migration script --- Geekbot.net/Commands/Admin/Owner.cs | 28 +- Geekbot.net/Commands/User/GuildInfo.cs | 13 +- Geekbot.net/Database/DatabaseContext.cs | 2 +- Geekbot.net/Database/Models/GuildsModel.cs | 3 +- Geekbot.net/Database/RedisMigration.cs | 304 +++++++++++++++++++++ Geekbot.net/Geekbot.net.csproj | 3 +- 6 files changed, 341 insertions(+), 12 deletions(-) create mode 100644 Geekbot.net/Database/RedisMigration.cs diff --git a/Geekbot.net/Commands/Admin/Owner.cs b/Geekbot.net/Commands/Admin/Owner.cs index 10cbfd7..a1a98d6 100644 --- a/Geekbot.net/Commands/Admin/Owner.cs +++ b/Geekbot.net/Commands/Admin/Owner.cs @@ -33,6 +33,24 @@ namespace Geekbot.net.Commands.Admin _database = database; } + [Command("migrate", RunMode = RunMode.Async)] + public async Task Migrate() + { + await ReplyAsync("starting migration"); + + try + { + var redisMigration = new RedisMigration(_database, _redis, _logger, _client); + await redisMigration.Migrate(); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + + await ReplyAsync("done"); + } + [Command("youtubekey", RunMode = RunMode.Async)] [Remarks(CommandCategories.Admin)] [Summary("Set the youtube api key")] @@ -90,8 +108,14 @@ namespace Geekbot.net.Commands.Admin [Summary("Throw an error un purpose")] public void PurposefulError() { - var e = new Exception("Error Generated by !owner error"); - _errorHandler.HandleCommandException(e, Context); + try + { + throw new Exception("Error Generated by !owner error"); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/User/GuildInfo.cs b/Geekbot.net/Commands/User/GuildInfo.cs index 6306a76..dabe005 100644 --- a/Geekbot.net/Commands/User/GuildInfo.cs +++ b/Geekbot.net/Commands/User/GuildInfo.cs @@ -3,22 +3,23 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.net.Database; using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Levels; -using StackExchange.Redis; namespace Geekbot.net.Commands.User { public class GuildInfo : ModuleBase { private readonly IErrorHandler _errorHandler; + private readonly DatabaseContext _database; private readonly ILevelCalc _levelCalc; - private readonly IDatabase _redis; - public GuildInfo(IDatabase redis, ILevelCalc levelCalc, IErrorHandler errorHandler) + public GuildInfo(DatabaseContext database, ILevelCalc levelCalc, IErrorHandler errorHandler) { - _redis = redis; + _database = database; _levelCalc = levelCalc; _errorHandler = errorHandler; } @@ -39,7 +40,9 @@ namespace Geekbot.net.Commands.User var created = Context.Guild.CreatedAt; var age = Math.Floor((DateTime.Now - created).TotalDays); - var messages = _redis.HashGet($"{Context.Guild.Id}:Messages", 0.ToString()); + var messages = _database.Messages + .Where(e => e.GuildId == Context.Guild.Id.AsLong()) + .Sum(e => e.MessageCount); var level = _levelCalc.GetLevel((int) messages); eb.AddField("Server Age", $"{created.Day}/{created.Month}/{created.Year} ({age} days)"); diff --git a/Geekbot.net/Database/DatabaseContext.cs b/Geekbot.net/Database/DatabaseContext.cs index 2768e2e..78701b8 100644 --- a/Geekbot.net/Database/DatabaseContext.cs +++ b/Geekbot.net/Database/DatabaseContext.cs @@ -13,7 +13,7 @@ namespace Geekbot.net.Database public DbSet Ships { get; set; } public DbSet Rolls { get; set; } public DbSet Messages { get; set; } - public DbSet SlapsModels { get; set; } + public DbSet Slaps { get; set; } // public DbSet UserSettings { get; set; } // public DbSet RoleSelfService { get; set; } } diff --git a/Geekbot.net/Database/Models/GuildsModel.cs b/Geekbot.net/Database/Models/GuildsModel.cs index 371bfd7..b6347a6 100644 --- a/Geekbot.net/Database/Models/GuildsModel.cs +++ b/Geekbot.net/Database/Models/GuildsModel.cs @@ -15,9 +15,8 @@ namespace Geekbot.net.Database.Models public string Name { get; set; } [Required] - public string Owner { get; set; } + public long Owner { get; set; } - [Required] public string IconUrl { get; set; } public DateTimeOffset CreatedAt { get; set; } diff --git a/Geekbot.net/Database/RedisMigration.cs b/Geekbot.net/Database/RedisMigration.cs new file mode 100644 index 0000000..6c8e0d0 --- /dev/null +++ b/Geekbot.net/Database/RedisMigration.cs @@ -0,0 +1,304 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Discord; +using Discord.WebSocket; +using Geekbot.net.Commands.Utils.Quote; +using Geekbot.net.Database.Models; +using Geekbot.net.Lib.Extensions; +using Geekbot.net.Lib.Logger; +using Newtonsoft.Json; +using StackExchange.Redis; + +namespace Geekbot.net.Database +{ + public class RedisMigration + { + private readonly DatabaseContext _database; + private readonly IDatabase _redis; + private readonly IGeekbotLogger _logger; + private readonly DiscordSocketClient _client; + + public RedisMigration(DatabaseContext database, IDatabase redis, IGeekbotLogger logger, DiscordSocketClient client) + { + _database = database; + _redis = redis; + _logger = logger; + _client = client; + } + + public async Task Migrate() + { + _logger.Information(LogSource.Geekbot, "Starting migration process"); + foreach (var guild in _client.Guilds) + { + _logger.Information(LogSource.Geekbot, $"Start Migration for {guild.Name}"); + #region Quotes + /** + * Quotes + */ + try + { + var data = _redis.SetScan($"{guild.Id}:Quotes"); + foreach (var q in data) + { + try + { + var qd = JsonConvert.DeserializeObject(q); + var quote = CreateQuoteObject(guild.Id, qd); + _database.Quotes.Add(quote); + _database.SaveChanges(); + } + catch + { + _logger.Warning(LogSource.Geekbot, $"quote failed: {q}"); + } + } + } + catch + { + _logger.Warning(LogSource.Geekbot, "quote migration failed"); + } + #endregion + + #region Karma + /** + * Karma + */ + try + { + var data = _redis.HashGetAll($"{guild.Id}:Karma"); + foreach (var q in data) + { + try + { + var user = new KarmaModel() + { + GuildId = guild.Id.AsLong(), + UserId = ulong.Parse(q.Name).AsLong(), + Karma = int.Parse(q.Value), + TimeOut = DateTimeOffset.MinValue + }; + _database.Karma.Add(user); + _database.SaveChanges(); + } + catch + { + _logger.Warning(LogSource.Geekbot, $"karma failed for: {q.Name}"); + } + } + } + catch + { + _logger.Warning(LogSource.Geekbot, "karma migration failed"); + } + #endregion + + #region Rolls + /** + * Rolls + */ + try + { + var data = _redis.HashGetAll($"{guild.Id}:Rolls"); + foreach (var q in data) + { + try + { + var user = new RollsModel() + { + GuildId = guild.Id.AsLong(), + UserId = ulong.Parse(q.Name).AsLong(), + Rolls = int.Parse(q.Value) + }; + _database.Rolls.Add(user); + _database.SaveChanges(); + } + catch + { + _logger.Warning(LogSource.Geekbot, $"Rolls failed for: {q.Name}"); + } + } + } + catch + { + _logger.Warning(LogSource.Geekbot, "rolls migration failed"); + } + #endregion + + #region Slaps + /** + * Slaps + */ + try + { + var given = _redis.HashGetAll($"{guild.Id}:SlapsGiven"); + var gotten = _redis.HashGetAll($"{guild.Id}:SlapsGiven"); + foreach (var q in given) + { + try + { + var user = new SlapsModel() + { + GuildId = guild.Id.AsLong(), + UserId = ulong.Parse(q.Name).AsLong(), + Given = int.Parse(q.Value), + Recieved= int.Parse(gotten[int.Parse(q.Name)].Value) + }; + _database.Slaps.Add(user); + _database.SaveChanges(); + } + catch + { + _logger.Warning(LogSource.Geekbot, $"Slaps failed for: {q.Name}"); + } + } + } + catch + { + _logger.Warning(LogSource.Geekbot, "Slaps migration failed"); + } + #endregion + + #region Messages + /** + * Messages + */ + try + { + var data = _redis.HashGetAll($"{guild.Id}:Messages"); + foreach (var q in data) + { + try + { + // drop the guild qounter + if(q.Name.ToString() != "0") continue; + var user = new MessagesModel() + { + GuildId = guild.Id.AsLong(), + UserId = ulong.Parse(q.Name).AsLong(), + MessageCount= int.Parse(q.Value) + }; + _database.Messages.Add(user); + _database.SaveChanges(); + } + catch + { + _logger.Warning(LogSource.Geekbot, $"Messages failed for: {q.Name}"); + } + } + } + catch + { + _logger.Warning(LogSource.Geekbot, "Messages migration failed"); + } + #endregion + + #region Ships + /** + * Ships + */ + try + { + var data = _redis.HashGetAll($"{guild.Id}:Ships"); + var done = new List(); + foreach (var q in data) + { + try + { + if (done.Contains(q.Name)) continue; + var split = q.Name.ToString().Split('-'); + var user = new ShipsModel() + { + FirstUserId = ulong.Parse(split[0]).AsLong(), + SecondUserId = ulong.Parse(split[1]).AsLong(), + Strength = int.Parse(q.Value) + }; + _database.Ships.Add(user); + _database.SaveChanges(); + done.Add(q.Name); + } + catch + { + _logger.Warning(LogSource.Geekbot, $"Ships failed for: {q.Name}"); + } + } + } + catch + { + _logger.Warning(LogSource.Geekbot, "Ships migration failed"); + } + #endregion + + #region Users + /** + * Users + */ + try + { + var data = guild.Users; + foreach (var user in data) + { + try + { + _database.Users.Add(new UserModel() + { + UserId = user.Id.AsLong(), + Username = user.Username, + Discriminator = user.Discriminator, + AvatarUrl = user.GetAvatarUrl(ImageFormat.Auto, 1024), + IsBot = user.IsBot, + Joined = user.CreatedAt, + UsedNames = new [] {user.Username} + }); + _database.SaveChanges(); + } + catch + { + _logger.Warning(LogSource.Geekbot, $"User failed: {user.Username}"); + } + } + } + catch + { + _logger.Warning(LogSource.Geekbot, "User migration failed"); + } + #endregion + + #region Guilds + + _database.Guilds.Add(new GuildsModel + { + CreatedAt = guild.CreatedAt, + GuildId = guild.Id.AsLong(), + IconUrl = guild.IconUrl, + Name = guild.Name, + Owner = guild.Owner.Id.AsLong() + }); + _database.SaveChanges(); + + #endregion + _logger.Information(LogSource.Geekbot, $"Finished Migration for {guild.Name}"); + } + _logger.Information(LogSource.Geekbot, "Finished migration process"); + } + + private QuoteModel CreateQuoteObject(ulong guild, QuoteObjectDto quote) + { + var last = _database.Quotes.Where(e => e.GuildId.Equals(guild.AsLong())) + .OrderByDescending(e => e.InternalId).FirstOrDefault(); + int internalId = 1; + if (last != null) internalId = last.InternalId + 1; + return new QuoteModel() + { + InternalId = internalId, + GuildId = guild.AsLong(), + UserId = quote.UserId.AsLong(), + Time = quote.Time, + Quote = quote.Quote, + Image = quote.Image + }; + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 3c59bc7..27e5dad 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -58,8 +58,7 @@ - + From 3fa4115502455c1174bff2306cf0680a02c392c0 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 13 May 2018 14:14:50 +0200 Subject: [PATCH 175/553] Improve migration Script --- Geekbot.net/Database/DatabaseContext.cs | 6 +++-- Geekbot.net/Database/Models/GlobalsModel.cs | 18 +++++++++++++ Geekbot.net/Database/RedisMigration.cs | 25 ++++++++++--------- Geekbot.net/Lib/Extensions/DbSetExtensions.cs | 17 +++++++++++++ 4 files changed, 52 insertions(+), 14 deletions(-) create mode 100644 Geekbot.net/Database/Models/GlobalsModel.cs create mode 100644 Geekbot.net/Lib/Extensions/DbSetExtensions.cs diff --git a/Geekbot.net/Database/DatabaseContext.cs b/Geekbot.net/Database/DatabaseContext.cs index 78701b8..e4fab28 100644 --- a/Geekbot.net/Database/DatabaseContext.cs +++ b/Geekbot.net/Database/DatabaseContext.cs @@ -14,7 +14,9 @@ namespace Geekbot.net.Database public DbSet Rolls { get; set; } public DbSet Messages { get; set; } public DbSet Slaps { get; set; } -// public DbSet UserSettings { get; set; } -// public DbSet RoleSelfService { get; set; } + public DbSet Globals { get; set; } + + // public DbSet UserSettings { get; set; } + // public DbSet RoleSelfService { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Database/Models/GlobalsModel.cs b/Geekbot.net/Database/Models/GlobalsModel.cs new file mode 100644 index 0000000..63261fc --- /dev/null +++ b/Geekbot.net/Database/Models/GlobalsModel.cs @@ -0,0 +1,18 @@ +using System.ComponentModel.DataAnnotations; + +namespace Geekbot.net.Database.Models +{ + public class GlobalsModel + { + [Key] + public int Id { get; set; } + + [Required] + public string Name { get; set; } + + [Required] + public string Value { get; set; } + + public string Meta { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Database/RedisMigration.cs b/Geekbot.net/Database/RedisMigration.cs index 6c8e0d0..1cd73b0 100644 --- a/Geekbot.net/Database/RedisMigration.cs +++ b/Geekbot.net/Database/RedisMigration.cs @@ -8,6 +8,7 @@ using Geekbot.net.Commands.Utils.Quote; using Geekbot.net.Database.Models; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Logger; +using MtgApiManager.Lib.Model; using Newtonsoft.Json; using StackExchange.Redis; @@ -172,8 +173,6 @@ namespace Geekbot.net.Database { try { - // drop the guild qounter - if(q.Name.ToString() != "0") continue; var user = new MessagesModel() { GuildId = guild.Id.AsLong(), @@ -242,16 +241,18 @@ namespace Geekbot.net.Database { try { - _database.Users.Add(new UserModel() - { - UserId = user.Id.AsLong(), - Username = user.Username, - Discriminator = user.Discriminator, - AvatarUrl = user.GetAvatarUrl(ImageFormat.Auto, 1024), - IsBot = user.IsBot, - Joined = user.CreatedAt, - UsedNames = new [] {user.Username} - }); + var namesSerialized = _redis.HashGet($"User:{user.Id}", "UsedNames").ToString(); + var names = Utf8Json.JsonSerializer.Deserialize(namesSerialized); + _database.Users.AddIfNotExists(new UserModel() + { + UserId = user.Id.AsLong(), + Username = user.Username, + Discriminator = user.Discriminator, + AvatarUrl = user.GetAvatarUrl(ImageFormat.Auto, 1024), + IsBot = user.IsBot, + Joined = user.CreatedAt, + UsedNames = names + }, model => model.UserId.Equals(user.Id.AsLong())); _database.SaveChanges(); } catch diff --git a/Geekbot.net/Lib/Extensions/DbSetExtensions.cs b/Geekbot.net/Lib/Extensions/DbSetExtensions.cs new file mode 100644 index 0000000..c731fc0 --- /dev/null +++ b/Geekbot.net/Lib/Extensions/DbSetExtensions.cs @@ -0,0 +1,17 @@ +using System; +using System.Linq; +using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.ChangeTracking; + +namespace Geekbot.net.Lib.Extensions +{ + public static class DbSetExtensions + { + public static EntityEntry AddIfNotExists(this DbSet dbSet, T entity, Expression> predicate = null) where T : class, new() + { + var exists = predicate != null ? dbSet.Any(predicate) : dbSet.Any(); + return !exists ? dbSet.Add(entity) : null; + } + } +} \ No newline at end of file From 37ac7f56a84d98740cbb522aef296ba7a56ab1d5 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 13 May 2018 15:55:57 +0200 Subject: [PATCH 176/553] Remove command categories --- Geekbot.net/Commands/Admin/Admin.cs | 8 -------- Geekbot.net/Commands/Admin/Mod.cs | 2 -- Geekbot.net/Commands/Admin/Owner.cs | 4 ---- Geekbot.net/Commands/Admin/Role.cs | 5 ----- Geekbot.net/Commands/Admin/Say.cs | 1 - Geekbot.net/Commands/Games/Pokedex.cs | 1 - Geekbot.net/Commands/Games/Roll.cs | 1 - .../Commands/Integrations/Google/Google.cs | 1 - .../Commands/Integrations/MagicTheGathering.cs | 1 - Geekbot.net/Commands/Integrations/Mal.cs | 2 -- .../UbranDictionary/UrbanDictionary.cs | 1 - Geekbot.net/Commands/Integrations/Wikipedia.cs | 1 - Geekbot.net/Commands/Integrations/Youtube.cs | 1 - Geekbot.net/Commands/Randomness/Cat/Cat.cs | 1 - Geekbot.net/Commands/Randomness/CheckEm.cs | 1 - .../Commands/Randomness/Chuck/ChuckNorrisJokes.cs | 1 - Geekbot.net/Commands/Randomness/Dad/DadJokes.cs | 1 - Geekbot.net/Commands/Randomness/Dog/Dog.cs | 1 - Geekbot.net/Commands/Randomness/EightBall.cs | 1 - Geekbot.net/Commands/Randomness/Fortune.cs | 1 - Geekbot.net/Commands/Randomness/Gdq.cs | 1 - Geekbot.net/Commands/Randomness/RandomAnimals.cs | 7 ------- Geekbot.net/Commands/Randomness/Ship.cs | 1 - Geekbot.net/Commands/Randomness/Slap.cs | 1 - Geekbot.net/Commands/User/GuildInfo.cs | 1 - Geekbot.net/Commands/User/Karma.cs | 2 -- Geekbot.net/Commands/User/Ranking/Rank.cs | 1 - Geekbot.net/Commands/User/Stats.cs | 1 - Geekbot.net/Commands/Utils/AvatarGetter.cs | 1 - Geekbot.net/Commands/Utils/Changelog/Changelog.cs | 4 +--- Geekbot.net/Commands/Utils/Choose.cs | 1 - Geekbot.net/Commands/Utils/Dice/Dice.cs | 1 - Geekbot.net/Commands/Utils/Emojify.cs | 1 - Geekbot.net/Commands/Utils/Help.cs | 1 - Geekbot.net/Commands/Utils/Info.cs | 2 -- Geekbot.net/Commands/Utils/Ping.cs | 1 - Geekbot.net/Commands/Utils/Poll/Poll.cs | 3 --- Geekbot.net/Commands/Utils/Quote/Quote.cs | 6 ------ Geekbot.net/Lib/CommandCategories.cs | 15 --------------- Geekbot.net/WebApi/Help/HelpController.cs | 1 - 40 files changed, 1 insertion(+), 87 deletions(-) delete mode 100644 Geekbot.net/Lib/CommandCategories.cs diff --git a/Geekbot.net/Commands/Admin/Admin.cs b/Geekbot.net/Commands/Admin/Admin.cs index 7d30689..7b5198d 100644 --- a/Geekbot.net/Commands/Admin/Admin.cs +++ b/Geekbot.net/Commands/Admin/Admin.cs @@ -30,7 +30,6 @@ namespace Geekbot.net.Commands.Admin } [Command("welcome", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Admin)] [Summary("Set a Welcome Message (use '$user' to mention the new joined user).")] public async Task SetWelcomeMessage([Remainder] [Summary("message")] string welcomeMessage) { @@ -40,7 +39,6 @@ namespace Geekbot.net.Commands.Admin } [Command("modchannel", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Admin)] [Summary("Set a channel for moderation purposes")] public async Task SelectModChannel([Summary("#Channel")] ISocketMessageChannel channel) { @@ -61,7 +59,6 @@ namespace Geekbot.net.Commands.Admin } [Command("showleave", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Admin)] [Summary("Notify modchannel when someone leaves")] public async Task ShowLeave([Summary("true/false")] bool enabled) { @@ -88,7 +85,6 @@ namespace Geekbot.net.Commands.Admin } [Command("showdel", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Admin)] [Summary("Notify modchannel when someone deletes a message")] public async Task ShowDelete([Summary("true/false")] bool enabled) { @@ -117,7 +113,6 @@ namespace Geekbot.net.Commands.Admin } [Command("setlang", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Admin)] [Summary("Change the bots language")] public async Task SetLanguage([Summary("language")] string languageRaw) { @@ -142,7 +137,6 @@ namespace Geekbot.net.Commands.Admin } [Command("wiki", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Admin)] [Summary("Change the wikipedia instance (use lang code in xx.wikipedia.org)")] public async Task SetWikiLanguage([Summary("language")] string languageRaw) { @@ -160,7 +154,6 @@ namespace Geekbot.net.Commands.Admin } [Command("lang", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Admin)] [Summary("Change the bots language")] public async Task GetLanguage() { @@ -176,7 +169,6 @@ namespace Geekbot.net.Commands.Admin } [Command("ping", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Admin)] [Summary("Enable the ping reply.")] public async Task TogglePing() { diff --git a/Geekbot.net/Commands/Admin/Mod.cs b/Geekbot.net/Commands/Admin/Mod.cs index 6f79157..b34b328 100644 --- a/Geekbot.net/Commands/Admin/Mod.cs +++ b/Geekbot.net/Commands/Admin/Mod.cs @@ -32,7 +32,6 @@ namespace Geekbot.net.Commands.Admin } [Command("namehistory", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Admin)] [Summary("See past usernames of an user")] public async Task UsernameHistory([Summary("@user")] IUser user) { @@ -52,7 +51,6 @@ namespace Geekbot.net.Commands.Admin } [Command("kick", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Admin)] [Summary("Ban a user")] public async Task Kick([Summary("@user")] IUser userNormal, [Summary("reason")] [Remainder] string reason = "none") diff --git a/Geekbot.net/Commands/Admin/Owner.cs b/Geekbot.net/Commands/Admin/Owner.cs index a1a98d6..2f4e3ab 100644 --- a/Geekbot.net/Commands/Admin/Owner.cs +++ b/Geekbot.net/Commands/Admin/Owner.cs @@ -52,7 +52,6 @@ namespace Geekbot.net.Commands.Admin } [Command("youtubekey", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Admin)] [Summary("Set the youtube api key")] public async Task SetYoutubeKey([Summary("API Key")] string key) { @@ -61,7 +60,6 @@ namespace Geekbot.net.Commands.Admin } [Command("game", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Admin)] [Summary("Set the game that the bot is playing")] public async Task SetGame([Remainder] [Summary("Game")] string key) { @@ -72,7 +70,6 @@ namespace Geekbot.net.Commands.Admin } [Command("popuserrepo", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Admin)] [Summary("Populate user cache")] public async Task PopUserRepoCommand() { @@ -104,7 +101,6 @@ namespace Geekbot.net.Commands.Admin } [Command("error", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Admin)] [Summary("Throw an error un purpose")] public void PurposefulError() { diff --git a/Geekbot.net/Commands/Admin/Role.cs b/Geekbot.net/Commands/Admin/Role.cs index 24d19dd..8624e66 100644 --- a/Geekbot.net/Commands/Admin/Role.cs +++ b/Geekbot.net/Commands/Admin/Role.cs @@ -27,7 +27,6 @@ namespace Geekbot.net.Commands.Admin } [Command(RunMode = RunMode.Async)] - [Remarks(CommandCategories.Helpers)] [Summary("Get a list of all available roles.")] public async Task GetAllRoles() { @@ -53,7 +52,6 @@ namespace Geekbot.net.Commands.Admin } [Command(RunMode = RunMode.Async)] - [Remarks(CommandCategories.Helpers)] [Summary("Get a role by mentioning it.")] public async Task GiveRole([Summary("roleNickname")] string roleNameRaw) { @@ -97,7 +95,6 @@ namespace Geekbot.net.Commands.Admin [RequireUserPermission(GuildPermission.ManageRoles)] [Command("add", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Admin)] [Summary("Add a role to the whitelist.")] public async Task AddRole([Summary("@role")] IRole role, [Summary("alias")] string roleName) { @@ -132,7 +129,6 @@ namespace Geekbot.net.Commands.Admin [RequireUserPermission(GuildPermission.ManageRoles)] [Command("remove", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Admin)] [Summary("Remove a role from the whitelist.")] public async Task RemoveRole([Summary("roleNickname")] string roleName) { @@ -156,7 +152,6 @@ namespace Geekbot.net.Commands.Admin } [RequireUserPermission(GuildPermission.ManageRoles)] - [Remarks(CommandCategories.Admin)] [Summary("Give a role by clicking on an emoji")] [Command("listen", RunMode = RunMode.Async)] public async Task AddListener([Summary("messageID")] string messageId, [Summary("Emoji")] string emoji, [Summary("@role")] IRole role) diff --git a/Geekbot.net/Commands/Admin/Say.cs b/Geekbot.net/Commands/Admin/Say.cs index 97c7a0f..f8708cd 100644 --- a/Geekbot.net/Commands/Admin/Say.cs +++ b/Geekbot.net/Commands/Admin/Say.cs @@ -18,7 +18,6 @@ namespace Geekbot.net.Commands.Admin [RequireUserPermission(GuildPermission.Administrator)] [Command("say", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Admin)] [Summary("Say Something.")] public async Task Echo([Remainder] [Summary("What?")] string echo) { diff --git a/Geekbot.net/Commands/Games/Pokedex.cs b/Geekbot.net/Commands/Games/Pokedex.cs index 57f842a..d4cbc0e 100644 --- a/Geekbot.net/Commands/Games/Pokedex.cs +++ b/Geekbot.net/Commands/Games/Pokedex.cs @@ -19,7 +19,6 @@ namespace Geekbot.net.Commands.Games } [Command("pokedex", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Helpers)] [Summary("A Pokedex Tool")] public async Task GetPokemon([Summary("pokemonName")] string pokemonName) { diff --git a/Geekbot.net/Commands/Games/Roll.cs b/Geekbot.net/Commands/Games/Roll.cs index 30697df..59a3c27 100644 --- a/Geekbot.net/Commands/Games/Roll.cs +++ b/Geekbot.net/Commands/Games/Roll.cs @@ -22,7 +22,6 @@ namespace Geekbot.net.Commands.Games } [Command("roll", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Fun)] [Summary("Guess which number the bot will roll (1-100")] public async Task RollCommand([Remainder] [Summary("guess")] string stuff = "noGuess") { diff --git a/Geekbot.net/Commands/Integrations/Google/Google.cs b/Geekbot.net/Commands/Integrations/Google/Google.cs index 7bd3a56..4c86de3 100644 --- a/Geekbot.net/Commands/Integrations/Google/Google.cs +++ b/Geekbot.net/Commands/Integrations/Google/Google.cs @@ -23,7 +23,6 @@ namespace Geekbot.net.Commands.Integrations.Google } [Command("google", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Helpers)] [Summary("Google Something.")] public async Task AskGoogle([Remainder, Summary("SearchText")] string searchText) { diff --git a/Geekbot.net/Commands/Integrations/MagicTheGathering.cs b/Geekbot.net/Commands/Integrations/MagicTheGathering.cs index 3074803..842c9de 100644 --- a/Geekbot.net/Commands/Integrations/MagicTheGathering.cs +++ b/Geekbot.net/Commands/Integrations/MagicTheGathering.cs @@ -23,7 +23,6 @@ namespace Geekbot.net.Commands.Integrations } [Command("mtg", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Games)] [Summary("Find a Magic The Gathering Card.")] public async Task GetCard([Remainder] [Summary("name")] string cardName) { diff --git a/Geekbot.net/Commands/Integrations/Mal.cs b/Geekbot.net/Commands/Integrations/Mal.cs index d70949a..36c6457 100644 --- a/Geekbot.net/Commands/Integrations/Mal.cs +++ b/Geekbot.net/Commands/Integrations/Mal.cs @@ -21,7 +21,6 @@ namespace Geekbot.net.Commands.Integrations } [Command("anime", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Helpers)] [Summary("Show Info about an Anime.")] public async Task SearchAnime([Remainder] [Summary("AnimeName")] string animeName) { @@ -70,7 +69,6 @@ namespace Geekbot.net.Commands.Integrations } [Command("manga", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Helpers)] [Summary("Show Info about a Manga.")] public async Task SearchManga([Remainder] [Summary("MangaName")] string mangaName) { diff --git a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs b/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs index 44402d0..3ad37f3 100644 --- a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs +++ b/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs @@ -20,7 +20,6 @@ namespace Geekbot.net.Commands.Integrations.UbranDictionary } [Command("urban", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Helpers)] [Summary("Lookup something on urban dictionary")] public async Task UrbanDefine([Remainder] [Summary("word")] string word) { diff --git a/Geekbot.net/Commands/Integrations/Wikipedia.cs b/Geekbot.net/Commands/Integrations/Wikipedia.cs index 68589f6..e2e8928 100644 --- a/Geekbot.net/Commands/Integrations/Wikipedia.cs +++ b/Geekbot.net/Commands/Integrations/Wikipedia.cs @@ -28,7 +28,6 @@ namespace Geekbot.net.Commands.Integrations } [Command("wiki", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Helpers)] [Summary("Get an article from wikipedia.")] public async Task GetPreview([Remainder] [Summary("Article")] string articleName) { diff --git a/Geekbot.net/Commands/Integrations/Youtube.cs b/Geekbot.net/Commands/Integrations/Youtube.cs index f534bcd..a5d681e 100644 --- a/Geekbot.net/Commands/Integrations/Youtube.cs +++ b/Geekbot.net/Commands/Integrations/Youtube.cs @@ -21,7 +21,6 @@ namespace Geekbot.net.Commands.Integrations } [Command("yt", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Helpers)] [Summary("Search for something on youtube.")] public async Task Yt([Remainder] [Summary("Title")] string searchQuery) { diff --git a/Geekbot.net/Commands/Randomness/Cat/Cat.cs b/Geekbot.net/Commands/Randomness/Cat/Cat.cs index 88a9ce5..a79eb37 100644 --- a/Geekbot.net/Commands/Randomness/Cat/Cat.cs +++ b/Geekbot.net/Commands/Randomness/Cat/Cat.cs @@ -19,7 +19,6 @@ namespace Geekbot.net.Commands.Randomness.Cat } [Command("cat", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Randomness)] [Summary("Return a random image of a cat.")] public async Task Say() { diff --git a/Geekbot.net/Commands/Randomness/CheckEm.cs b/Geekbot.net/Commands/Randomness/CheckEm.cs index fc962cc..325d7cc 100644 --- a/Geekbot.net/Commands/Randomness/CheckEm.cs +++ b/Geekbot.net/Commands/Randomness/CheckEm.cs @@ -21,7 +21,6 @@ namespace Geekbot.net.Commands.Randomness } [Command("checkem", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Randomness)] [Summary("Check for dubs")] public async Task MuhDubs() { diff --git a/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs b/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs index 6ff2255..8e8a369 100644 --- a/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs +++ b/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs @@ -19,7 +19,6 @@ namespace Geekbot.net.Commands.Randomness.Chuck } [Command("chuck", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Randomness)] [Summary("A random chuck norris joke")] public async Task Say() { diff --git a/Geekbot.net/Commands/Randomness/Dad/DadJokes.cs b/Geekbot.net/Commands/Randomness/Dad/DadJokes.cs index e35798c..a14a098 100644 --- a/Geekbot.net/Commands/Randomness/Dad/DadJokes.cs +++ b/Geekbot.net/Commands/Randomness/Dad/DadJokes.cs @@ -19,7 +19,6 @@ namespace Geekbot.net.Commands.Randomness.Dad } [Command("dad", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Randomness)] [Summary("A random dad joke")] public async Task Say() { diff --git a/Geekbot.net/Commands/Randomness/Dog/Dog.cs b/Geekbot.net/Commands/Randomness/Dog/Dog.cs index 08c1a9b..83d7a2e 100644 --- a/Geekbot.net/Commands/Randomness/Dog/Dog.cs +++ b/Geekbot.net/Commands/Randomness/Dog/Dog.cs @@ -19,7 +19,6 @@ namespace Geekbot.net.Commands.Randomness.Dog } [Command("dog", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Randomness)] [Summary("Return a random image of a dog.")] public async Task Say() { diff --git a/Geekbot.net/Commands/Randomness/EightBall.cs b/Geekbot.net/Commands/Randomness/EightBall.cs index 79ba6d1..cf59431 100644 --- a/Geekbot.net/Commands/Randomness/EightBall.cs +++ b/Geekbot.net/Commands/Randomness/EightBall.cs @@ -17,7 +17,6 @@ namespace Geekbot.net.Commands.Randomness } [Command("8ball", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Randomness)] [Summary("Ask 8Ball a Question.")] public async Task Ball([Remainder] [Summary("Question")] string echo) { diff --git a/Geekbot.net/Commands/Randomness/Fortune.cs b/Geekbot.net/Commands/Randomness/Fortune.cs index abc9ce5..498085a 100644 --- a/Geekbot.net/Commands/Randomness/Fortune.cs +++ b/Geekbot.net/Commands/Randomness/Fortune.cs @@ -15,7 +15,6 @@ namespace Geekbot.net.Commands.Randomness } [Command("fortune", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Randomness)] [Summary("Get a random fortune")] public async Task GetAFortune() { diff --git a/Geekbot.net/Commands/Randomness/Gdq.cs b/Geekbot.net/Commands/Randomness/Gdq.cs index 3e17451..8d0472c 100644 --- a/Geekbot.net/Commands/Randomness/Gdq.cs +++ b/Geekbot.net/Commands/Randomness/Gdq.cs @@ -17,7 +17,6 @@ namespace Geekbot.net.Commands.Randomness } [Command("gdq", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Games)] [Summary("Get a quote from the GDQ donation generator.")] public async Task GetQuote() { diff --git a/Geekbot.net/Commands/Randomness/RandomAnimals.cs b/Geekbot.net/Commands/Randomness/RandomAnimals.cs index a96aea8..608b52d 100644 --- a/Geekbot.net/Commands/Randomness/RandomAnimals.cs +++ b/Geekbot.net/Commands/Randomness/RandomAnimals.cs @@ -16,7 +16,6 @@ namespace Geekbot.net.Commands.Randomness } [Command("panda", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Randomness)] [Summary("Get a random panda image")] public async Task Panda() { @@ -25,7 +24,6 @@ namespace Geekbot.net.Commands.Randomness [Command("croissant", RunMode = RunMode.Async)] [Alias("gipfeli")] - [Remarks(CommandCategories.Randomness)] [Summary("Get a random croissant image")] public async Task Croissant() { @@ -33,7 +31,6 @@ namespace Geekbot.net.Commands.Randomness } [Command("pumpkin", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Randomness)] [Summary("Get a random pumpkin image")] public async Task Pumpkin() { @@ -41,7 +38,6 @@ namespace Geekbot.net.Commands.Randomness } [Command("squirrel", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Randomness)] [Summary("Get a random squirrel image")] public async Task Squirrel() { @@ -49,7 +45,6 @@ namespace Geekbot.net.Commands.Randomness } [Command("turtle", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Randomness)] [Summary("Get a random turtle image")] public async Task Turtle() { @@ -58,7 +53,6 @@ namespace Geekbot.net.Commands.Randomness [Command("pinguin", RunMode = RunMode.Async)] [Alias("pingu")] - [Remarks(CommandCategories.Randomness)] [Summary("Get a random pinguin image")] public async Task Pinguin() { @@ -66,7 +60,6 @@ namespace Geekbot.net.Commands.Randomness } [Command("fox", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Randomness)] [Summary("Get a random fox image")] public async Task Fox() { diff --git a/Geekbot.net/Commands/Randomness/Ship.cs b/Geekbot.net/Commands/Randomness/Ship.cs index ffa18b4..735bd51 100644 --- a/Geekbot.net/Commands/Randomness/Ship.cs +++ b/Geekbot.net/Commands/Randomness/Ship.cs @@ -20,7 +20,6 @@ namespace Geekbot.net.Commands.Randomness } [Command("Ship", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Fun)] [Summary("Ask the Shipping meter")] public async Task Command([Summary("@User1")] IUser user1, [Summary("@User2")] IUser user2) { diff --git a/Geekbot.net/Commands/Randomness/Slap.cs b/Geekbot.net/Commands/Randomness/Slap.cs index 129e89d..2cac9d2 100644 --- a/Geekbot.net/Commands/Randomness/Slap.cs +++ b/Geekbot.net/Commands/Randomness/Slap.cs @@ -21,7 +21,6 @@ namespace Geekbot.net.Commands.Randomness } [Command("slap", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Fun)] [Summary("slap someone")] public async Task Slapper([Summary("@user")] IUser user) { diff --git a/Geekbot.net/Commands/User/GuildInfo.cs b/Geekbot.net/Commands/User/GuildInfo.cs index dabe005..c475d99 100644 --- a/Geekbot.net/Commands/User/GuildInfo.cs +++ b/Geekbot.net/Commands/User/GuildInfo.cs @@ -25,7 +25,6 @@ namespace Geekbot.net.Commands.User } [Command("serverstats", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Statistics)] [Summary("Show some info about the bot.")] public async Task GetInfo() { diff --git a/Geekbot.net/Commands/User/Karma.cs b/Geekbot.net/Commands/User/Karma.cs index b63951e..2f427c8 100644 --- a/Geekbot.net/Commands/User/Karma.cs +++ b/Geekbot.net/Commands/User/Karma.cs @@ -26,7 +26,6 @@ namespace Geekbot.net.Commands.User } [Command("good", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Karma)] [Summary("Increase Someones Karma")] public async Task Good([Summary("@someone")] IUser user) { @@ -74,7 +73,6 @@ namespace Geekbot.net.Commands.User } [Command("bad", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Karma)] [Summary("Decrease Someones Karma")] public async Task Bad([Summary("@someone")] IUser user) { diff --git a/Geekbot.net/Commands/User/Ranking/Rank.cs b/Geekbot.net/Commands/User/Ranking/Rank.cs index 9b1b32f..dd1d026 100644 --- a/Geekbot.net/Commands/User/Ranking/Rank.cs +++ b/Geekbot.net/Commands/User/Ranking/Rank.cs @@ -36,7 +36,6 @@ namespace Geekbot.net.Commands.User.Ranking } [Command("rank", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Statistics)] [Summary("get user top 10 in messages or karma")] public async Task RankCmd([Summary("type")] string typeUnformated = "messages", [Summary("amount")] int amount = 10) { diff --git a/Geekbot.net/Commands/User/Stats.cs b/Geekbot.net/Commands/User/Stats.cs index 19a6aa8..93bddef 100644 --- a/Geekbot.net/Commands/User/Stats.cs +++ b/Geekbot.net/Commands/User/Stats.cs @@ -23,7 +23,6 @@ namespace Geekbot.net.Commands.User } [Command("stats", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Statistics)] [Summary("Get information about this user")] public async Task User([Summary("@someone")] IUser user = null) { diff --git a/Geekbot.net/Commands/Utils/AvatarGetter.cs b/Geekbot.net/Commands/Utils/AvatarGetter.cs index d42c779..cf34ca3 100644 --- a/Geekbot.net/Commands/Utils/AvatarGetter.cs +++ b/Geekbot.net/Commands/Utils/AvatarGetter.cs @@ -17,7 +17,6 @@ namespace Geekbot.net.Commands.Utils } [Command("avatar", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Helpers)] [Summary("Get someones avatar")] public async Task GetAvatar([Remainder] [Summary("user")] IUser user = null) { diff --git a/Geekbot.net/Commands/Utils/Changelog/Changelog.cs b/Geekbot.net/Commands/Utils/Changelog/Changelog.cs index f1752f7..c218c66 100644 --- a/Geekbot.net/Commands/Utils/Changelog/Changelog.cs +++ b/Geekbot.net/Commands/Utils/Changelog/Changelog.cs @@ -25,9 +25,7 @@ namespace Geekbot.net.Commands.Utils.Changelog } [Command("changelog", RunMode = RunMode.Async)] - [Alias("updates")] - [Remarks(CommandCategories.Helpers)] - [Summary("Show the latest 5 updates")] + [Summary("Show the latest 10 updates")] public async Task GetChangelog() { try diff --git a/Geekbot.net/Commands/Utils/Choose.cs b/Geekbot.net/Commands/Utils/Choose.cs index 4d54654..2b9ff19 100644 --- a/Geekbot.net/Commands/Utils/Choose.cs +++ b/Geekbot.net/Commands/Utils/Choose.cs @@ -19,7 +19,6 @@ namespace Geekbot.net.Commands.Utils } [Command("choose", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Helpers)] [Summary("Let the bot choose for you, seperate options with a semicolon.")] public async Task Command([Remainder] [Summary("option1;option2")] string choices) diff --git a/Geekbot.net/Commands/Utils/Dice/Dice.cs b/Geekbot.net/Commands/Utils/Dice/Dice.cs index 9c169c7..c8e31f5 100644 --- a/Geekbot.net/Commands/Utils/Dice/Dice.cs +++ b/Geekbot.net/Commands/Utils/Dice/Dice.cs @@ -11,7 +11,6 @@ namespace Geekbot.net.Commands.Utils.Dice public class Dice : ModuleBase { [Command("dice", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Randomness)] [Summary("Roll a dice.")] public async Task RollCommand([Remainder] [Summary("diceType")] string diceType = "1d20") { diff --git a/Geekbot.net/Commands/Utils/Emojify.cs b/Geekbot.net/Commands/Utils/Emojify.cs index 57363c2..07adadb 100644 --- a/Geekbot.net/Commands/Utils/Emojify.cs +++ b/Geekbot.net/Commands/Utils/Emojify.cs @@ -19,7 +19,6 @@ namespace Geekbot.net.Commands.Utils } [Command("emojify", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Helpers)] [Summary("Emojify text")] public async Task Dflt([Remainder] [Summary("text")] string text) { diff --git a/Geekbot.net/Commands/Utils/Help.cs b/Geekbot.net/Commands/Utils/Help.cs index be9a747..4372692 100644 --- a/Geekbot.net/Commands/Utils/Help.cs +++ b/Geekbot.net/Commands/Utils/Help.cs @@ -18,7 +18,6 @@ namespace Geekbot.net.Commands.Utils } [Command("help", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Helpers)] [Summary("List all Commands")] public async Task GetHelp() { diff --git a/Geekbot.net/Commands/Utils/Info.cs b/Geekbot.net/Commands/Utils/Info.cs index de34e89..55615ea 100644 --- a/Geekbot.net/Commands/Utils/Info.cs +++ b/Geekbot.net/Commands/Utils/Info.cs @@ -27,7 +27,6 @@ namespace Geekbot.net.Commands.Utils } [Command("info", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Helpers)] [Summary("Get Information about the bot")] public async Task BotInfo() { @@ -59,7 +58,6 @@ namespace Geekbot.net.Commands.Utils } [Command("uptime", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Helpers)] [Summary("Get the Bot Uptime")] public async Task BotUptime() { diff --git a/Geekbot.net/Commands/Utils/Ping.cs b/Geekbot.net/Commands/Utils/Ping.cs index 226e9a3..653a46f 100644 --- a/Geekbot.net/Commands/Utils/Ping.cs +++ b/Geekbot.net/Commands/Utils/Ping.cs @@ -8,7 +8,6 @@ namespace Geekbot.net.Commands.Utils { [Command("👀", RunMode = RunMode.Async)] [Summary("Look at the bot.")] - [Remarks(CommandCategories.Fun)] public async Task Eyes() { await ReplyAsync("S... Stop looking at me... baka!"); diff --git a/Geekbot.net/Commands/Utils/Poll/Poll.cs b/Geekbot.net/Commands/Utils/Poll/Poll.cs index 5d18a0f..e94e6d4 100644 --- a/Geekbot.net/Commands/Utils/Poll/Poll.cs +++ b/Geekbot.net/Commands/Utils/Poll/Poll.cs @@ -32,7 +32,6 @@ namespace Geekbot.net.Commands.Utils.Poll } [Command(RunMode = RunMode.Async)] - [Remarks(CommandCategories.Helpers)] [Summary("Check status of the current poll")] public async Task Dflt() { @@ -55,7 +54,6 @@ namespace Geekbot.net.Commands.Utils.Poll } [Command("create", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Helpers)] [Summary("Create a poll")] public async Task Create([Remainder] [Summary("question;option1;option2")] string rawPollString) @@ -113,7 +111,6 @@ namespace Geekbot.net.Commands.Utils.Poll } [Command("end", RunMode = RunMode.Async)] - [Remarks(CommandCategories.Helpers)] [Summary("End the current poll")] public async Task End() { diff --git a/Geekbot.net/Commands/Utils/Quote/Quote.cs b/Geekbot.net/Commands/Utils/Quote/Quote.cs index 71c4089..ef0cbc8 100644 --- a/Geekbot.net/Commands/Utils/Quote/Quote.cs +++ b/Geekbot.net/Commands/Utils/Quote/Quote.cs @@ -26,7 +26,6 @@ namespace Geekbot.net.Commands.Utils.Quote } [Command] - [Remarks(CommandCategories.Quotes)] [Summary("Return a random quoute from the database")] public async Task GetRandomQuote() { @@ -53,7 +52,6 @@ namespace Geekbot.net.Commands.Utils.Quote } [Command("save")] - [Remarks(CommandCategories.Quotes)] [Summary("Save a quote from the last sent message by @user")] public async Task SaveQuote([Summary("@user")] IUser user) { @@ -89,7 +87,6 @@ namespace Geekbot.net.Commands.Utils.Quote } [Command("save")] - [Remarks(CommandCategories.Quotes)] [Summary("Save a quote from a message id")] public async Task SaveQuote([Summary("messageId")] ulong messageId) { @@ -123,7 +120,6 @@ namespace Geekbot.net.Commands.Utils.Quote } [Command("make")] - [Remarks(CommandCategories.Quotes)] [Summary("Create a quote from the last sent message by @user")] public async Task ReturnSpecifiedQuote([Summary("@user")] IUser user) { @@ -143,7 +139,6 @@ namespace Geekbot.net.Commands.Utils.Quote } [Command("make")] - [Remarks(CommandCategories.Quotes)] [Summary("Create a quote from a message id")] public async Task ReturnSpecifiedQuote([Summary("messageId")] ulong messageId) { @@ -165,7 +160,6 @@ namespace Geekbot.net.Commands.Utils.Quote [RequireUserPermission(GuildPermission.KickMembers)] [RequireUserPermission(GuildPermission.ManageMessages)] [RequireUserPermission(GuildPermission.ManageRoles)] - [Remarks(CommandCategories.Quotes)] [Summary("Remove a quote (required mod permissions)")] public async Task RemoveQuote([Summary("quoteId")] int id) { diff --git a/Geekbot.net/Lib/CommandCategories.cs b/Geekbot.net/Lib/CommandCategories.cs deleted file mode 100644 index d67123b..0000000 --- a/Geekbot.net/Lib/CommandCategories.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Geekbot.net.Lib -{ - public static class CommandCategories - { - public const string Randomness = "Randomness"; - public const string Karma = "Karma"; - public const string Quotes = "Quotes"; - public const string Fun = "Fun"; - public const string Statistics = "Statistics"; - public const string Helpers = "Helpers"; - public const string Games = "Games"; - public const string Admin = "Admin"; - public const string Uncategorized = "Uncategorized"; - } -} \ No newline at end of file diff --git a/Geekbot.net/WebApi/Help/HelpController.cs b/Geekbot.net/WebApi/Help/HelpController.cs index d71d26f..015c7d8 100644 --- a/Geekbot.net/WebApi/Help/HelpController.cs +++ b/Geekbot.net/WebApi/Help/HelpController.cs @@ -28,7 +28,6 @@ namespace Geekbot.net.WebApi.Help { Name = cmd.Name, Summary = cmd.Summary, - Category = cmd.Remarks ?? CommandCategories.Uncategorized, IsAdminCommand = (param.Contains("admin")), Aliases = cmd.Aliases.ToArray(), Params = cmdParamsObj From bb8aee1eda8e0923587631555293ca2dffc69446 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 13 May 2018 17:49:13 +0200 Subject: [PATCH 177/553] Port !owner, !admin, !mod, handlers (partial) and add globals to the db --- Geekbot.net/Commands/Admin/Admin.cs | 183 ++++++++++++------ Geekbot.net/Commands/Admin/Mod.cs | 41 +--- Geekbot.net/Commands/Admin/Owner.cs | 11 +- .../Commands/Integrations/Google/Google.cs | 21 +- Geekbot.net/Commands/Integrations/Youtube.cs | 15 +- Geekbot.net/Commands/Utils/Info.cs | 7 +- Geekbot.net/Handlers.cs | 77 ++++---- .../Lib/GlobalSettings/GlobalSettings.cs | 55 ++++++ .../Lib/GlobalSettings/IGlobalSettings.cs | 11 ++ Geekbot.net/Program.cs | 18 +- 10 files changed, 265 insertions(+), 174 deletions(-) create mode 100644 Geekbot.net/Lib/GlobalSettings/GlobalSettings.cs create mode 100644 Geekbot.net/Lib/GlobalSettings/IGlobalSettings.cs diff --git a/Geekbot.net/Commands/Admin/Admin.cs b/Geekbot.net/Commands/Admin/Admin.cs index 7b5198d..f3366a6 100644 --- a/Geekbot.net/Commands/Admin/Admin.cs +++ b/Geekbot.net/Commands/Admin/Admin.cs @@ -1,11 +1,14 @@ using System; +using System.Linq; using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.WebSocket; -using Geekbot.net.Lib; +using Geekbot.net.Database; +using Geekbot.net.Database.Models; using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Localization; using StackExchange.Redis; @@ -17,13 +20,13 @@ namespace Geekbot.net.Commands.Admin { private readonly DiscordSocketClient _client; private readonly IErrorHandler _errorHandler; - private readonly IDatabase _redis; + private readonly DatabaseContext _database; private readonly ITranslationHandler _translation; - public Admin(IDatabase redis, DiscordSocketClient client, IErrorHandler errorHandler, + public Admin(DatabaseContext database, DiscordSocketClient client, IErrorHandler errorHandler, ITranslationHandler translationHandler) { - _redis = redis; + _database = database; _client = client; _errorHandler = errorHandler; _translation = translationHandler; @@ -33,7 +36,11 @@ namespace Geekbot.net.Commands.Admin [Summary("Set a Welcome Message (use '$user' to mention the new joined user).")] public async Task SetWelcomeMessage([Remainder] [Summary("message")] string welcomeMessage) { - _redis.HashSet($"{Context.Guild.Id}:Settings", new[] {new HashEntry("WelcomeMsg", welcomeMessage)}); + var guild = GetGuildSettings(Context.Guild.Id); + guild.WelcomeMessage = welcomeMessage; + _database.GuildSettings.Update(guild); + _database.SaveChanges(); + var formatedMessage = welcomeMessage.Replace("$user", Context.User.Mention); await ReplyAsync($"Welcome message has been changed\r\nHere is an example of how it would look:\r\n{formatedMessage}"); } @@ -44,13 +51,18 @@ namespace Geekbot.net.Commands.Admin { try { + var m = await channel.SendMessageAsync("verifying..."); + + var guild = GetGuildSettings(Context.Guild.Id); + guild.ModChannel = channel.Id.AsLong(); + _database.GuildSettings.Update(guild); + _database.SaveChanges(); + var sb = new StringBuilder(); sb.AppendLine("Successfully saved mod channel, you can now do the following"); - sb.AppendLine("- `!admin showleave true` - send message to mod channel when someone leaves"); - sb.AppendLine("- `!admin showdel true` - send message to mod channel when someone deletes a message"); - await channel.SendMessageAsync(sb.ToString()); - _redis.HashSet($"{Context.Guild.Id}:Settings", - new[] {new HashEntry("ModChannel", channel.Id.ToString())}); + sb.AppendLine("- `!admin showleave` - send message to mod channel when someone leaves"); + sb.AppendLine("- `!admin showdel` - send message to mod channel when someone deletes a message"); + await m.ModifyAsync(e => e.Content = sb.ToString()); } catch (Exception e) { @@ -59,56 +71,50 @@ namespace Geekbot.net.Commands.Admin } [Command("showleave", RunMode = RunMode.Async)] - [Summary("Notify modchannel when someone leaves")] - public async Task ShowLeave([Summary("true/false")] bool enabled) + [Summary("Toggle - notify modchannel when someone leaves")] + public async Task ShowLeave() { - var modChannelId = ulong.Parse(_redis.HashGet($"{Context.Guild.Id}:Settings", "ModChannel")); try { - var modChannel = (ISocketMessageChannel) _client.GetChannel(modChannelId); - if (enabled) - { - await modChannel.SendMessageAsync("Saved - now sending messages here when someone leaves"); - _redis.HashSet($"{Context.Guild.Id}:Settings", new[] {new HashEntry("ShowLeave", true)}); - } - else - { - await modChannel.SendMessageAsync("Saved - stopping sending messages here when someone leaves"); - _redis.HashSet($"{Context.Guild.Id}:Settings", new[] {new HashEntry("ShowLeave", false)}); - } + var guild = GetGuildSettings(Context.Guild.Id); + var modChannel = await GetModChannel(guild.ModChannel.AsUlong()); + if (modChannel == null) return; + + guild.ShowLeave = !guild.ShowLeave; + _database.GuildSettings.Update(guild); + _database.SaveChanges(); + await modChannel.SendMessageAsync(guild.ShowLeave + ? "Saved - now sending messages here when someone leaves" + : "Saved - stopping sending messages here when someone leaves" + ); } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context, - "Modchannel doesn't seem to exist, please set one with `!admin modchannel [channelId]`"); + _errorHandler.HandleCommandException(e, Context); } } [Command("showdel", RunMode = RunMode.Async)] - [Summary("Notify modchannel when someone deletes a message")] - public async Task ShowDelete([Summary("true/false")] bool enabled) + [Summary("Toggle - notify modchannel when someone deletes a message")] + public async Task ShowDelete() { - var modChannelId = ulong.Parse(_redis.HashGet($"{Context.Guild.Id}:Settings", "ModChannel")); try { - var modChannel = (ISocketMessageChannel) _client.GetChannel(modChannelId); - if (enabled) - { - await modChannel.SendMessageAsync( - "Saved - now sending messages here when someone deletes a message"); - _redis.HashSet($"{Context.Guild.Id}:Settings", new[] {new HashEntry("ShowDelete", true)}); - } - else - { - await modChannel.SendMessageAsync( - "Saved - stopping sending messages here when someone deletes a message"); - _redis.HashSet($"{Context.Guild.Id}:Settings", new[] {new HashEntry("ShowDelete", false)}); - } + var guild = GetGuildSettings(Context.Guild.Id); + var modChannel = await GetModChannel(guild.ModChannel.AsUlong()); + if (modChannel == null) return; + + guild.ShowDelete = !guild.ShowDelete; + _database.GuildSettings.Update(guild); + _database.SaveChanges(); + await modChannel.SendMessageAsync(guild.ShowDelete + ? "Saved - now sending messages here when someone deletes a message" + : "Saved - stopping sending messages here when someone deletes a message" + ); } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context, - "Modchannel doesn't seem to exist, please set one with `!admin modchannel [channelId]`"); + _errorHandler.HandleCommandException(e, Context); } } @@ -122,6 +128,11 @@ namespace Geekbot.net.Commands.Admin var success = _translation.SetLanguage(Context.Guild.Id, language); if (success) { + var guild = GetGuildSettings(Context.Guild.Id); + guild.Language = language; + _database.GuildSettings.Update(guild); + _database.SaveChanges(); + var trans = _translation.GetDict(Context); await ReplyAsync(trans["NewLanguageSet"]); return; @@ -143,8 +154,11 @@ namespace Geekbot.net.Commands.Admin try { var language = languageRaw.ToLower(); - _redis.HashSet($"{Context.Guild.Id}:Settings", new[] {new HashEntry("WikiLang", language) }); - + var guild = GetGuildSettings(Context.Guild.Id); + guild.WikiLang = language; + _database.GuildSettings.Update(guild); + _database.SaveChanges(); + await ReplyAsync($"Now using the {language} wikipedia"); } catch (Exception e) @@ -152,21 +166,6 @@ namespace Geekbot.net.Commands.Admin _errorHandler.HandleCommandException(e, Context); } } - - [Command("lang", RunMode = RunMode.Async)] - [Summary("Change the bots language")] - public async Task GetLanguage() - { - try - { - var trans = _translation.GetDict(Context); - await ReplyAsync(trans["GetLanguage"]); - } - catch (Exception e) - { - _errorHandler.HandleCommandException(e, Context); - } - } [Command("ping", RunMode = RunMode.Async)] [Summary("Enable the ping reply.")] @@ -174,9 +173,11 @@ namespace Geekbot.net.Commands.Admin { try { - bool.TryParse(_redis.HashGet($"{Context.Guild.Id}:Settings", "ping"), out var current); - _redis.HashSet($"{Context.Guild.Id}:Settings", new[] {new HashEntry("ping", current ? "false" : "true") }); - await ReplyAsync(!current ? "i will reply to ping now" : "No more pongs..."); + var guild = GetGuildSettings(Context.Guild.Id); + guild.Ping = !guild.Ping; + _database.GuildSettings.Update(guild); + _database.SaveChanges(); + await ReplyAsync(guild.Ping ? "i will reply to ping now" : "No more pongs..."); } catch (Exception e) { @@ -184,5 +185,59 @@ namespace Geekbot.net.Commands.Admin } } + [Command("hui", RunMode = RunMode.Async)] + [Summary("Enable the ping reply.")] + public async Task ToggleHui() + { + try + { + var guild = GetGuildSettings(Context.Guild.Id); + guild.Hui = !guild.Hui; + _database.GuildSettings.Update(guild); + _database.SaveChanges(); + await ReplyAsync(guild.Hui ? "i will reply to hui now" : "No more hui's..."); + } + catch (Exception e) + { + _errorHandler.HandleCommandException(e, Context); + } + } + + private GuildSettingsModel GetGuildSettings(ulong guildId) + { + var guild = _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(guildId.AsLong())); + if (guild != null) return guild; + Console.WriteLine("Adding non-exist Guild Settings to database"); + _database.GuildSettings.Add(new GuildSettingsModel() + { + GuildId = guildId.AsLong(), + Hui = false, + Ping = false, + Language = "en", + ShowDelete = false, + ShowLeave = false, + WikiLang = "en" + }); + _database.SaveChanges(); + return _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(guildId.AsLong())); + } + + private async Task GetModChannel(ulong channelId) + { + try + { + if(channelId == ulong.MinValue) throw new Exception(); + var modChannel = (ISocketMessageChannel) _client.GetChannel(channelId); + if(modChannel == null) throw new Exception(); + return modChannel; + } + catch + { + await ReplyAsync( + "Modchannel doesn't seem to exist, please set one with `!admin modchannel [channelId]`"); + return null; + } + } + } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Admin/Mod.cs b/Geekbot.net/Commands/Admin/Mod.cs index b34b328..2e4ad24 100644 --- a/Geekbot.net/Commands/Admin/Mod.cs +++ b/Geekbot.net/Commands/Admin/Mod.cs @@ -4,10 +4,8 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.WebSocket; -using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.UserRepository; -using StackExchange.Redis; namespace Geekbot.net.Commands.Admin { @@ -19,15 +17,12 @@ namespace Geekbot.net.Commands.Admin { private readonly DiscordSocketClient _client; private readonly IErrorHandler _errorHandler; - private readonly IDatabase _redis; private readonly IUserRepository _userRepository; - public Mod(IUserRepository userRepositry, IErrorHandler errorHandler, IDatabase redis, - DiscordSocketClient client) + public Mod(IUserRepository userRepositry, IErrorHandler errorHandler, DiscordSocketClient client) { _userRepository = userRepositry; _errorHandler = errorHandler; - _redis = redis; _client = client; } @@ -49,39 +44,5 @@ namespace Geekbot.net.Commands.Admin $"I don't have enough permissions do that"); } } - - [Command("kick", RunMode = RunMode.Async)] - [Summary("Ban a user")] - public async Task Kick([Summary("@user")] IUser userNormal, - [Summary("reason")] [Remainder] string reason = "none") - { - try - { - var user = (IGuildUser) userNormal; - if (reason == "none") reason = "No reason provided"; - await user.GetOrCreateDMChannelAsync().Result.SendMessageAsync( - $"You have been kicked from {Context.Guild.Name} for the following reason: \"{reason}\""); - await user.KickAsync(); - try - { - var modChannelId = ulong.Parse(_redis.HashGet($"{Context.Guild.Id}:Settings", "ModChannel")); - var modChannel = (ISocketMessageChannel) _client.GetChannel(modChannelId); - var eb = new EmbedBuilder(); - eb.Title = ":x: User Kicked"; - eb.AddInlineField("User", user.Username); - eb.AddInlineField("By Mod", Context.User.Username); - eb.AddField("Reason", reason); - await modChannel.SendMessageAsync("", false, eb.Build()); - } - catch - { - await ReplyAsync($"{user.Username} was kicked for the following reason: \"{reason}\""); - } - } - catch (Exception e) - { - _errorHandler.HandleCommandException(e, Context, "I don't have enough permissions to kick someone"); - } - } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Admin/Owner.cs b/Geekbot.net/Commands/Admin/Owner.cs index 2f4e3ab..c02c7fb 100644 --- a/Geekbot.net/Commands/Admin/Owner.cs +++ b/Geekbot.net/Commands/Admin/Owner.cs @@ -1,11 +1,10 @@ using System; using System.Threading.Tasks; -using Discord; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Database; -using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.GlobalSettings; using Geekbot.net.Lib.Logger; using Geekbot.net.Lib.UserRepository; using StackExchange.Redis; @@ -19,11 +18,12 @@ namespace Geekbot.net.Commands.Admin private readonly DiscordSocketClient _client; private readonly IErrorHandler _errorHandler; private readonly DatabaseContext _database; + private readonly IGlobalSettings _globalSettings; private readonly IGeekbotLogger _logger; private readonly IDatabase _redis; private readonly IUserRepository _userRepository; - public Owner(IDatabase redis, DiscordSocketClient client, IGeekbotLogger logger, IUserRepository userRepositry, IErrorHandler errorHandler, DatabaseContext database) + public Owner(IDatabase redis, DiscordSocketClient client, IGeekbotLogger logger, IUserRepository userRepositry, IErrorHandler errorHandler, DatabaseContext database, IGlobalSettings globalSettings) { _redis = redis; _client = client; @@ -31,6 +31,7 @@ namespace Geekbot.net.Commands.Admin _userRepository = userRepositry; _errorHandler = errorHandler; _database = database; + _globalSettings = globalSettings; } [Command("migrate", RunMode = RunMode.Async)] @@ -55,7 +56,7 @@ namespace Geekbot.net.Commands.Admin [Summary("Set the youtube api key")] public async Task SetYoutubeKey([Summary("API Key")] string key) { - _redis.StringSet("youtubeKey", key); + _globalSettings.SetKey("YoutubeKey", key); await ReplyAsync("Apikey has been set"); } @@ -63,7 +64,7 @@ namespace Geekbot.net.Commands.Admin [Summary("Set the game that the bot is playing")] public async Task SetGame([Remainder] [Summary("Game")] string key) { - _redis.StringSet("Game", key); + _globalSettings.SetKey("Game", key); await _client.SetGameAsync(key); _logger.Information(LogSource.Geekbot, $"Changed game to {key}"); await ReplyAsync($"Now Playing {key}"); diff --git a/Geekbot.net/Commands/Integrations/Google/Google.cs b/Geekbot.net/Commands/Integrations/Google/Google.cs index 4c86de3..1ad7c8e 100644 --- a/Geekbot.net/Commands/Integrations/Google/Google.cs +++ b/Geekbot.net/Commands/Integrations/Google/Google.cs @@ -4,22 +4,21 @@ using System.Net; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.GlobalSettings; using Newtonsoft.Json; -using StackExchange.Redis; namespace Geekbot.net.Commands.Integrations.Google { public class Google : ModuleBase { private readonly IErrorHandler _errorHandler; - private readonly IDatabase _redis; + private readonly IGlobalSettings _globalSettings; - public Google(IErrorHandler errorHandler, IDatabase redis) + public Google(IErrorHandler errorHandler, IGlobalSettings globalSettings) { _errorHandler = errorHandler; - _redis = redis; + _globalSettings = globalSettings; } [Command("google", RunMode = RunMode.Async)] @@ -30,12 +29,12 @@ namespace Geekbot.net.Commands.Integrations.Google { using (var client = new WebClient()) { - var apiKey = _redis.StringGet("googleGraphKey"); - if (!apiKey.HasValue) + var apiKey = _globalSettings.GetKey("GoogleGraphKey"); + if (string.IsNullOrEmpty(apiKey)) { await ReplyAsync("No Google API key has been set, please contact my owner"); return; - } + } var url = new Uri($"https://kgsearch.googleapis.com/v1/entities:search?languages=en&limit=1&query={searchText}&key={apiKey}"); var responseString = client.DownloadString(url); @@ -48,8 +47,10 @@ namespace Geekbot.net.Commands.Integrations.Google } var data = response.ItemListElement.First().Result; - var eb = new EmbedBuilder(); - eb.Title = data.Name; + var eb = new EmbedBuilder + { + Title = data.Name + }; if(!string.IsNullOrEmpty(data.Description)) eb.WithDescription(data.Description); if(!string.IsNullOrEmpty(data.DetailedDtoDescription?.Url)) eb.WithUrl(data.DetailedDtoDescription.Url); if(!string.IsNullOrEmpty(data.DetailedDtoDescription?.ArticleBody)) eb.AddField("Details", data.DetailedDtoDescription.ArticleBody); diff --git a/Geekbot.net/Commands/Integrations/Youtube.cs b/Geekbot.net/Commands/Integrations/Youtube.cs index a5d681e..2e9fce0 100644 --- a/Geekbot.net/Commands/Integrations/Youtube.cs +++ b/Geekbot.net/Commands/Integrations/Youtube.cs @@ -1,22 +1,21 @@ using System; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.GlobalSettings; using Google.Apis.Services; using Google.Apis.YouTube.v3; -using StackExchange.Redis; namespace Geekbot.net.Commands.Integrations { public class Youtube : ModuleBase { + private readonly IGlobalSettings _globalSettings; private readonly IErrorHandler _errorHandler; - private readonly IDatabase _redis; - public Youtube(IDatabase redis, IErrorHandler errorHandler) + public Youtube(IGlobalSettings globalSettings, IErrorHandler errorHandler) { - _redis = redis; + _globalSettings = globalSettings; _errorHandler = errorHandler; } @@ -24,8 +23,8 @@ namespace Geekbot.net.Commands.Integrations [Summary("Search for something on youtube.")] public async Task Yt([Remainder] [Summary("Title")] string searchQuery) { - var key = _redis.StringGet("youtubeKey"); - if (key.IsNullOrEmpty) + var key = _globalSettings.GetKey("YoutubeKey"); + if (string.IsNullOrEmpty(key)) { await ReplyAsync("No youtube key set, please tell my senpai to set one"); return; @@ -35,7 +34,7 @@ namespace Geekbot.net.Commands.Integrations { var youtubeService = new YouTubeService(new BaseClientService.Initializer { - ApiKey = key.ToString(), + ApiKey = key, ApplicationName = GetType().ToString() }); diff --git a/Geekbot.net/Commands/Utils/Info.cs b/Geekbot.net/Commands/Utils/Info.cs index 55615ea..e7b104f 100644 --- a/Geekbot.net/Commands/Utils/Info.cs +++ b/Geekbot.net/Commands/Utils/Info.cs @@ -7,7 +7,6 @@ using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; -using StackExchange.Redis; namespace Geekbot.net.Commands.Utils { @@ -16,11 +15,9 @@ namespace Geekbot.net.Commands.Utils private readonly DiscordSocketClient _client; private readonly CommandService _commands; private readonly IErrorHandler _errorHandler; - private readonly IDatabase _redis; - public Info(IDatabase redis, IErrorHandler errorHandler, DiscordSocketClient client, CommandService commands) + public Info(IErrorHandler errorHandler, DiscordSocketClient client, CommandService commands) { - _redis = redis; _errorHandler = errorHandler; _client = client; _commands = commands; @@ -37,7 +34,7 @@ namespace Geekbot.net.Commands.Utils eb.WithAuthor(new EmbedAuthorBuilder() .WithIconUrl(_client.CurrentUser.GetAvatarUrl()) .WithName($"{Constants.Name} V{Constants.BotVersion()}")); - var botOwner = await Context.Guild.GetUserAsync(ulong.Parse(_redis.StringGet("botOwner"))); + var botOwner = (await _client.GetApplicationInfoAsync()).Owner; var uptime = DateTime.Now.Subtract(Process.GetCurrentProcess().StartTime); eb.AddInlineField("Bot Name", _client.CurrentUser.Username); diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index 1515920..b901c1f 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -1,9 +1,12 @@ using System; +using System.Linq; using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.WebSocket; +using Geekbot.net.Database; +using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Logger; using Geekbot.net.Lib.ReactionListener; using Geekbot.net.Lib.UserRepository; @@ -13,6 +16,7 @@ namespace Geekbot.net { public class Handlers { + private readonly DatabaseContext _database; private readonly IDiscordClient _client; private readonly IGeekbotLogger _logger; private readonly IDatabase _redis; @@ -21,8 +25,9 @@ namespace Geekbot.net private readonly IUserRepository _userRepository; private readonly IReactionListener _reactionListener; - public Handlers(IDiscordClient client, IGeekbotLogger logger, IDatabase redis, IServiceProvider servicesProvider, CommandService commands, IUserRepository userRepository, IReactionListener reactionListener) + public Handlers(DatabaseContext database, IDiscordClient client, IGeekbotLogger logger, IDatabase redis, IServiceProvider servicesProvider, CommandService commands, IUserRepository userRepository, IReactionListener reactionListener) { + _database = database; _client = client; _logger = logger; _redis = redis; @@ -46,13 +51,21 @@ namespace Geekbot.net var lowCaseMsg = message.ToString().ToLower(); if (lowCaseMsg.StartsWith("hui")) { - message.Channel.SendMessageAsync("hui!!!"); - return Task.CompletedTask; + var hasPing = _database.GuildSettings.FirstOrDefault(guild => + guild.GuildId.Equals(((SocketGuildChannel) message.Channel).Guild.Id.AsLong())) + ?.Hui ?? false; + if (hasPing) + { + message.Channel.SendMessageAsync("hui!!!"); + return Task.CompletedTask; + } } if (lowCaseMsg.StartsWith("ping ") || lowCaseMsg.Equals("ping")) { - bool.TryParse(_redis.HashGet($"{((SocketGuildChannel) message.Channel).Guild.Id}:Settings", "ping"), out var allowPings); - if (allowPings) + var hasPing = _database.GuildSettings.FirstOrDefault(guild => + guild.GuildId.Equals(((SocketGuildChannel) message.Channel).Guild.Id.AsLong())) + ?.Ping ?? false; + if (hasPing) { message.Channel.SendMessageAsync("pong"); return Task.CompletedTask; @@ -109,10 +122,12 @@ namespace Geekbot.net { if (!user.IsBot) { - var message = _redis.HashGet($"{user.Guild.Id}:Settings", "WelcomeMsg"); - if (!message.IsNullOrEmpty) + var message = _database.GuildSettings.FirstOrDefault(guild => + guild.GuildId.Equals(user.Guild.Id.AsLong())) + ?.WelcomeMessage; + if (!string.IsNullOrEmpty(message)) { - message = message.ToString().Replace("$user", user.Mention); + message = message.Replace("$user", user.Mention); await user.Guild.DefaultChannel.SendMessageAsync(message); } } @@ -134,15 +149,12 @@ namespace Geekbot.net { try { - var sendLeftEnabled = _redis.HashGet($"{user.Guild.Id}:Settings", "ShowLeave"); - if (sendLeftEnabled.ToString() == "1") + var guild = _database.GuildSettings.FirstOrDefault(g => + g.GuildId.Equals(user.Guild.Id.AsLong())); + if (guild?.ShowLeave ?? false) { - var modChannel = ulong.Parse(_redis.HashGet($"{user.Guild.Id}:Settings", "ModChannel")); - if (!string.IsNullOrEmpty(modChannel.ToString())) - { - var modChannelSocket = (ISocketMessageChannel) await _client.GetChannelAsync(modChannel); - await modChannelSocket.SendMessageAsync($"{user.Username}#{user.Discriminator} left the server"); - } + var modChannelSocket = (ISocketMessageChannel) await _client.GetChannelAsync(guild.ModChannel.AsUlong()); + await modChannelSocket.SendMessageAsync($"{user.Username}#{user.Discriminator} left the server"); } } catch (Exception e) @@ -160,27 +172,24 @@ namespace Geekbot.net { try { - var guild = ((IGuildChannel) channel).Guild; - var sendLeftEnabled = _redis.HashGet($"{guild.Id}:Settings", "ShowDelete"); - if (sendLeftEnabled.ToString() == "1") + var guildSocketData = ((IGuildChannel) channel).Guild; + var guild = _database.GuildSettings.FirstOrDefault(g => + g.GuildId.Equals(guildSocketData.Id.AsLong())); + if (guild?.ShowDelete ?? false) { - var modChannel = ulong.Parse(_redis.HashGet($"{guild.Id}:Settings", "ModChannel")); - if (!string.IsNullOrEmpty(modChannel.ToString()) && modChannel != channel.Id) + var modChannelSocket = (ISocketMessageChannel) await _client.GetChannelAsync(guild.ModChannel.AsUlong()); + var sb = new StringBuilder(); + if (message.Value != null) { - var modChannelSocket = (ISocketMessageChannel) await _client.GetChannelAsync(modChannel); - var sb = new StringBuilder(); - if (message.Value != null) - { - sb.AppendLine( - $"The following message from {message.Value.Author.Username}#{message.Value.Author.Discriminator} was deleted in <#{channel.Id}>"); - sb.AppendLine(message.Value.Content); - } - else - { - sb.AppendLine("Someone deleted a message, the message was not cached..."); - } - await modChannelSocket.SendMessageAsync(sb.ToString()); + sb.AppendLine( + $"The following message from {message.Value.Author.Username}#{message.Value.Author.Discriminator} was deleted in <#{channel.Id}>"); + sb.AppendLine(message.Value.Content); } + else + { + sb.AppendLine("Someone deleted a message, the message was not cached..."); + } + await modChannelSocket.SendMessageAsync(sb.ToString()); } } catch (Exception e) diff --git a/Geekbot.net/Lib/GlobalSettings/GlobalSettings.cs b/Geekbot.net/Lib/GlobalSettings/GlobalSettings.cs new file mode 100644 index 0000000..1234b34 --- /dev/null +++ b/Geekbot.net/Lib/GlobalSettings/GlobalSettings.cs @@ -0,0 +1,55 @@ +using System.Linq; +using Geekbot.net.Database; +using Geekbot.net.Database.Models; + +namespace Geekbot.net.Lib.GlobalSettings +{ + public class GlobalSettings : IGlobalSettings + { + private readonly DatabaseContext _database; + + public GlobalSettings(DatabaseContext database) + { + _database = database; + } + + public bool SetKey(string keyName, string value) + { + try + { + var key = GetKeyFull(keyName); + if (key == null) + { + _database.Globals.Add(new GlobalsModel() + { + Name = keyName, + Value = value + }); + _database.SaveChanges(); + return true; + } + + key.Value = value; + _database.Globals.Update(key); + _database.SaveChanges(); + return true; + } + catch + { + return false; + } + } + + public string GetKey(string keyName) + { + var key = _database.Globals.FirstOrDefault(k => k.Name.Equals(keyName)); + return key?.Value ?? string.Empty; + } + + public GlobalsModel GetKeyFull(string keyName) + { + var key = _database.Globals.FirstOrDefault(k => k.Name.Equals(keyName)); + return key; + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/GlobalSettings/IGlobalSettings.cs b/Geekbot.net/Lib/GlobalSettings/IGlobalSettings.cs new file mode 100644 index 0000000..1919b50 --- /dev/null +++ b/Geekbot.net/Lib/GlobalSettings/IGlobalSettings.cs @@ -0,0 +1,11 @@ +using Geekbot.net.Database.Models; + +namespace Geekbot.net.Lib.GlobalSettings +{ + public interface IGlobalSettings + { + bool SetKey(string keyName, string value); + string GetKey(string keyName); + GlobalsModel GetKeyFull(string keyName); + } +} \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index ee05a12..42dc856 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -1,6 +1,4 @@ using System; -using System.Linq; -using System.Net; using System.Reflection; using System.Text; using System.Threading.Tasks; @@ -14,13 +12,13 @@ using Geekbot.net.Lib.Audio; using Geekbot.net.Lib.Clients; using Geekbot.net.Lib.Converters; using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.GlobalSettings; using Geekbot.net.Lib.Levels; using Geekbot.net.Lib.Localization; using Geekbot.net.Lib.Logger; using Geekbot.net.Lib.Media; using Geekbot.net.Lib.ReactionListener; using Geekbot.net.Lib.UserRepository; -using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Nancy.Hosting.Self; using StackExchange.Redis; @@ -33,6 +31,8 @@ namespace Geekbot.net private DiscordSocketClient _client; private CommandService _commands; private IDatabase _redis; + private DatabaseContext _database; + private IGlobalSettings _globalSettings; private IServiceCollection _services; private IServiceProvider _servicesProvider; private RedisValue _token; @@ -107,11 +107,12 @@ namespace Geekbot.net _firstStart = true; } - var database = new DatabaseInitializer(runParameters, logger).Initzialize(); + _database = new DatabaseInitializer(runParameters, logger).Initzialize(); + _globalSettings = new GlobalSettings(_database); _services = new ServiceCollection(); - _userRepository = new UserRepository(database, logger); + _userRepository = new UserRepository(_database, logger); var fortunes = new FortunesProvider(logger); var mediaProvider = new MediaProvider(logger); var malClient = new MalClient(_redis, logger); @@ -132,7 +133,8 @@ namespace Geekbot.net _services.AddSingleton(mtgManaConverter); _services.AddSingleton(wikipediaClient); _services.AddSingleton(audioUtils); - _services.AddSingleton(database); + _services.AddSingleton(_database); + _services.AddSingleton(_globalSettings); logger.Information(LogSource.Geekbot, "Connecting to Discord"); @@ -150,7 +152,7 @@ namespace Geekbot.net var isConneted = await IsConnected(); if (isConneted) { - await _client.SetGameAsync(_redis.StringGet("Game")); + await _client.SetGameAsync(_globalSettings.GetKey("Game")); _logger.Information(LogSource.Geekbot, $"Now Connected as {_client.CurrentUser.Username} to {_client.Guilds.Count} Servers"); _logger.Information(LogSource.Geekbot, "Registering Stuff"); @@ -165,7 +167,7 @@ namespace Geekbot.net _services.AddSingleton(reactionListener); _servicesProvider = _services.BuildServiceProvider(); - var handlers = new Handlers(_client, _logger, _redis, _servicesProvider, _commands, _userRepository, reactionListener); + var handlers = new Handlers(_database, _client, _logger, _redis, _servicesProvider, _commands, _userRepository, reactionListener); _client.MessageReceived += handlers.RunCommand; _client.MessageReceived += handlers.UpdateStats; From a1b5bd1955e50185f20404849c1a5051686b009f Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 13 May 2018 18:47:01 +0200 Subject: [PATCH 178/553] Add more run parameters, remove first launch stuff, store token in globals --- Geekbot.net/Database/RedisMigration.cs | 4 +- .../Lib/ReactionListener/ReactionListener.cs | 18 +++---- Geekbot.net/Lib/RunParameters.cs | 47 ++++++++++++++----- Geekbot.net/Program.cs | 43 ++++------------- 4 files changed, 56 insertions(+), 56 deletions(-) diff --git a/Geekbot.net/Database/RedisMigration.cs b/Geekbot.net/Database/RedisMigration.cs index 1cd73b0..237ce60 100644 --- a/Geekbot.net/Database/RedisMigration.cs +++ b/Geekbot.net/Database/RedisMigration.cs @@ -29,7 +29,7 @@ namespace Geekbot.net.Database _client = client; } - public async Task Migrate() + public Task Migrate() { _logger.Information(LogSource.Geekbot, "Starting migration process"); foreach (var guild in _client.Guilds) @@ -283,6 +283,8 @@ namespace Geekbot.net.Database _logger.Information(LogSource.Geekbot, $"Finished Migration for {guild.Name}"); } _logger.Information(LogSource.Geekbot, "Finished migration process"); + + return Task.CompletedTask;; } private QuoteModel CreateQuoteObject(ulong guild, QuoteObjectDto quote) diff --git a/Geekbot.net/Lib/ReactionListener/ReactionListener.cs b/Geekbot.net/Lib/ReactionListener/ReactionListener.cs index 950edd1..18490db 100644 --- a/Geekbot.net/Lib/ReactionListener/ReactionListener.cs +++ b/Geekbot.net/Lib/ReactionListener/ReactionListener.cs @@ -9,22 +9,22 @@ namespace Geekbot.net.Lib.ReactionListener { public class ReactionListener : IReactionListener { - private readonly IDatabase _database; + private readonly IDatabase _redis; private Dictionary> _listener; - public ReactionListener(IDatabase database) + public ReactionListener(IDatabase redis) { - _database = database; + _redis = redis; LoadListeners(); } private Task LoadListeners() { - var ids = _database.SetMembers("MessageIds"); + var ids = _redis.SetMembers("MessageIds"); _listener = new Dictionary>(); foreach (var id in ids) { - var reactions = _database.HashGetAll($"Messages:{id}"); + var reactions = _redis.HashGetAll($"Messages:{id}"); var messageId = id; var emojiDict = new Dictionary(); foreach (var r in reactions) @@ -54,12 +54,12 @@ namespace Geekbot.net.Lib.ReactionListener public Task AddRoleToListener(string messageId, IEmote emoji, IRole role) { - if (_database.SetMembers("MessageIds").All(e => e.ToString() != messageId)) + if (_redis.SetMembers("MessageIds").All(e => e.ToString() != messageId)) { - _database.SetAdd("MessageIds", messageId); + _redis.SetAdd("MessageIds", messageId); } - _database.HashSet($"Messages:{messageId}", new[] {new HashEntry(emoji.ToString(), role.Id.ToString())}); - _database.SetAdd("MessageIds", messageId); + _redis.HashSet($"Messages:{messageId}", new[] {new HashEntry(emoji.ToString(), role.Id.ToString())}); + _redis.SetAdd("MessageIds", messageId); if (_listener.ContainsKey(messageId)) { _listener[messageId].Add(emoji, role.Id); diff --git a/Geekbot.net/Lib/RunParameters.cs b/Geekbot.net/Lib/RunParameters.cs index eb3ca37..7942b76 100644 --- a/Geekbot.net/Lib/RunParameters.cs +++ b/Geekbot.net/Lib/RunParameters.cs @@ -1,20 +1,17 @@ -using System; -using CommandLine; +using CommandLine; namespace Geekbot.net.Lib { public class RunParameters { - /** - * General Parameters - */ - [Option('V', "verbose", Default = false, HelpText = "Prints all messages to standard output.")] + /************************************ + * General * + ************************************/ + + [Option('V', "verbose", Default = false, HelpText = "Logs everything.")] public bool Verbose { get; set; } - [Option('r', "reset", Default = false, HelpText = "Resets the bot")] - public bool Reset { get; set; } - - [Option('j', "log-json", Default = false, HelpText = "Logs messages as json")] + [Option('j', "log-json", Default = false, HelpText = "Logger outputs json")] public bool LogJson { get; set; } [Option('a', "disable-api", Default = false, HelpText = "Disables the web api")] @@ -26,9 +23,10 @@ namespace Geekbot.net.Lib [Option("token", Default = null, HelpText = "Set a new bot token")] public string Token { get; set; } - /** - * Database Stuff - */ + /************************************ + * Database * + ************************************/ + [Option("in-memory", Default = false, HelpText = "Uses the in-memory database instead of postgresql")] public bool InMemory { get; set; } @@ -47,5 +45,28 @@ namespace Geekbot.net.Lib [Option("db-password", Default = "", HelpText = "Set a posgresql password")] public string DbPassword { get; set; } + + /************************************ + * Redis * + ************************************/ + + [Option("redis-host", Default = "127.0.0.1", HelpText = "Set a redis host")] + public string RedisHost { get; set; } + + [Option("redis-port", Default = "6379", HelpText = "Set a redis port")] + public string RedisPort { get; set; } + + [Option("redis-database", Default = "6", HelpText = "Select a redis database (1-15)")] + public string RedisDatabase { get; set; } + + /************************************ + * WebApi * + ************************************/ + + [Option("api-host", Default = "127.0.0.1", HelpText = "Host on which the WebApi listens")] + public string ApiHost { get; set; } + + [Option("api-port", Default = "12995", HelpText = "Port on which the WebApi listens")] + public string ApiPort { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 42dc856..8084127 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -38,7 +38,6 @@ namespace Geekbot.net private RedisValue _token; private GeekbotLogger _logger; private IUserRepository _userRepository; - private bool _firstStart; private RunParameters _runParameters; private static void Main(string[] args) @@ -84,10 +83,13 @@ namespace Geekbot.net _client.Log += discordLogger.Log; _commands = new CommandService(); + _database = new DatabaseInitializer(runParameters, logger).Initzialize(); + _globalSettings = new GlobalSettings(_database); + try { - var redisMultiplexer = ConnectionMultiplexer.Connect("127.0.0.1:6379"); - _redis = redisMultiplexer.GetDatabase(6); + var redisMultiplexer = ConnectionMultiplexer.Connect($"{runParameters.RedisHost}:{runParameters.RedisPort}"); + _redis = redisMultiplexer.GetDatabase(int.Parse(runParameters.RedisDatabase)); logger.Information(LogSource.Redis, $"Connected to db {_redis.Database}"); } catch (Exception e) @@ -96,20 +98,16 @@ namespace Geekbot.net Environment.Exit(GeekbotExitCode.RedisConnectionFailed.GetHashCode()); } - _token = runParameters.Token ?? _redis.StringGet("discordToken"); + _token = runParameters.Token ?? _globalSettings.GetKey("DiscordToken"); if (_token.IsNullOrEmpty) { Console.Write("Your bot Token: "); var newToken = Console.ReadLine(); - _redis.StringSet("discordToken", newToken); - _redis.StringSet("Game", "Ping Pong"); + _globalSettings.SetKey("DiscordToken", newToken); + _globalSettings.SetKey("Game", "Ping Pong"); _token = newToken; - _firstStart = true; } - _database = new DatabaseInitializer(runParameters, logger).Initzialize(); - _globalSettings = new GlobalSettings(_database); - _services = new ServiceCollection(); _userRepository = new UserRepository(_database, logger); @@ -177,13 +175,7 @@ namespace Geekbot.net _client.UserLeft += handlers.UserLeft; _client.ReactionAdded += handlers.ReactionAdded; _client.ReactionRemoved += handlers.ReactionRemoved; - - if (_firstStart || _runParameters.Reset) - { - _logger.Information(LogSource.Geekbot, "Finishing setup"); - await FinishSetup(); - _logger.Information(LogSource.Geekbot, "Setup finished"); - } + if (!_runParameters.DisableApi) { StartWebApi(); @@ -209,24 +201,9 @@ namespace Geekbot.net private void StartWebApi() { _logger.Information(LogSource.Api, "Starting Webserver"); - var webApiUrl = new Uri("http://localhost:12995"); + var webApiUrl = new Uri($"http://{_runParameters.ApiHost}:{_runParameters.ApiPort}"); new NancyHost(webApiUrl).Start(); _logger.Information(LogSource.Api, $"Webserver now running on {webApiUrl}"); } - - private async Task FinishSetup() - { - try - { - // ToDo: Set bot avatar - var appInfo = await _client.GetApplicationInfoAsync(); - _redis.StringSet("botOwner", appInfo.Owner.Id); - } - catch (Exception e) - { - _logger.Warning(LogSource.Geekbot, "Setup Failed, couldn't retrieve discord application data", e); - } - return Task.CompletedTask; - } } } \ No newline at end of file From 08015c61023fb57c37812eb57c34f7ecd7631185 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 13 May 2018 21:06:41 +0200 Subject: [PATCH 179/553] Port !stats, !role, !wiki and !slap, fix messages in rank, add roleselfservicemodel to db --- Geekbot.net/Commands/Admin/Role.cs | 48 +++++++++------- .../Commands/Integrations/Wikipedia.cs | 12 ++-- Geekbot.net/Commands/Randomness/Ship.cs | 37 +++++++----- Geekbot.net/Commands/Randomness/Slap.cs | 57 ++++++++++++++++--- Geekbot.net/Commands/User/Ranking/Rank.cs | 24 +++----- Geekbot.net/Commands/User/Stats.cs | 21 ++++--- Geekbot.net/Database/DatabaseContext.cs | 4 +- .../Database/Models/RoleSelfServiceModel.cs | 12 +++- 8 files changed, 141 insertions(+), 74 deletions(-) diff --git a/Geekbot.net/Commands/Admin/Role.cs b/Geekbot.net/Commands/Admin/Role.cs index 8624e66..a3a649e 100644 --- a/Geekbot.net/Commands/Admin/Role.cs +++ b/Geekbot.net/Commands/Admin/Role.cs @@ -5,24 +5,25 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.Net; -using Geekbot.net.Lib; +using Geekbot.net.Database; +using Geekbot.net.Database.Models; using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.ReactionListener; -using StackExchange.Redis; namespace Geekbot.net.Commands.Admin { [Group("role")] public class Role : ModuleBase { + private readonly DatabaseContext _database; private readonly IErrorHandler _errorHandler; - private readonly IDatabase _redis; private readonly IReactionListener _reactionListener; - public Role(IErrorHandler errorHandler, IDatabase redis, IReactionListener reactionListener) + public Role(DatabaseContext database, IErrorHandler errorHandler, IReactionListener reactionListener) { + _database = database; _errorHandler = errorHandler; - _redis = redis; _reactionListener = reactionListener; } @@ -32,8 +33,8 @@ namespace Geekbot.net.Commands.Admin { try { - var roles = _redis.HashGetAll($"{Context.Guild.Id}:RoleWhitelist"); - if (roles.Length == 0) + var roles = _database.RoleSelfService.Where(g => g.GuildId.Equals(Context.Guild.Id.AsLong())).ToList(); + if (roles.Count == 0) { await ReplyAsync("There are no roles configured for this server"); return; @@ -42,7 +43,7 @@ namespace Geekbot.net.Commands.Admin var sb = new StringBuilder(); sb.AppendLine($"**Self Service Roles on {Context.Guild.Name}**"); sb.AppendLine("To get a role, use `!role name`"); - foreach (var role in roles) sb.AppendLine($"- {role.Name}"); + foreach (var role in roles) sb.AppendLine($"- {role.WhiteListName}"); await ReplyAsync(sb.ToString()); } catch (Exception e) @@ -58,18 +59,19 @@ namespace Geekbot.net.Commands.Admin try { var roleName = roleNameRaw.ToLower(); - if (_redis.HashExists($"{Context.Guild.Id}:RoleWhitelist", roleName)) + var roleFromDb = _database.RoleSelfService.FirstOrDefault(e => + e.GuildId.Equals(Context.Guild.Id.AsLong()) && e.WhiteListName.Equals(roleName)); + if (roleFromDb != null) { var guildUser = (IGuildUser) Context.User; - var roleId = ulong.Parse(_redis.HashGet($"{Context.Guild.Id}:RoleWhitelist", roleName)); - var role = Context.Guild.Roles.First(r => r.Id == roleId); + var role = Context.Guild.Roles.First(r => r.Id == roleFromDb.RoleId.AsUlong()); if (role == null) { await ReplyAsync("That role doesn't seem to exist"); return; } - if (guildUser.RoleIds.Contains(roleId)) + if (guildUser.RoleIds.Contains(role.Id)) { await guildUser.RemoveRoleAsync(role); await ReplyAsync($"Removed you from {role.Name}"); @@ -113,12 +115,17 @@ namespace Geekbot.net.Commands.Admin || role.Permissions.KickMembers) { await ReplyAsync( - "Woah, i don't think you want to add that role to self service as it contains some dangerous permissions"); + "You cannot add that role to self service because it contains one or more dangerous permissions"); return; } - _redis.HashSet($"{Context.Guild.Id}:RoleWhitelist", - new[] {new HashEntry(roleName.ToLower(), role.Id.ToString())}); + _database.RoleSelfService.Add(new RoleSelfServiceModel + { + GuildId = Context.Guild.Id.AsLong(), + RoleId = role.Id.AsLong(), + WhiteListName = roleName + }); + _database.SaveChanges(); await ReplyAsync($"Added {role.Name} to the whitelist"); } catch (Exception e) @@ -134,16 +141,17 @@ namespace Geekbot.net.Commands.Admin { try { - - var success = _redis.HashDelete($"{Context.Guild.Id}:RoleWhitelist", roleName.ToLower()); - if (success) + var roleFromDb = _database.RoleSelfService.FirstOrDefault(e => + e.GuildId.Equals(Context.Guild.Id.AsLong()) && e.WhiteListName.Equals(roleName)); + if (roleFromDb != null) { + _database.RoleSelfService.Remove(roleFromDb); + _database.SaveChanges(); await ReplyAsync($"Removed {roleName} from the whitelist"); return; } - await ReplyAsync("There is not whitelisted role with that name..."); - + await ReplyAsync("There is not whitelisted role with that name"); } catch (Exception e) { diff --git a/Geekbot.net/Commands/Integrations/Wikipedia.cs b/Geekbot.net/Commands/Integrations/Wikipedia.cs index e2e8928..069ba8c 100644 --- a/Geekbot.net/Commands/Integrations/Wikipedia.cs +++ b/Geekbot.net/Commands/Integrations/Wikipedia.cs @@ -5,10 +5,10 @@ using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib; +using Geekbot.net.Database; using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Extensions; using HtmlAgilityPack; -using StackExchange.Redis; using WikipediaApi; using WikipediaApi.Page; @@ -18,13 +18,13 @@ namespace Geekbot.net.Commands.Integrations { private readonly IErrorHandler _errorHandler; private readonly IWikipediaClient _wikipediaClient; - private readonly IDatabase _redis; + private readonly DatabaseContext _database; - public Wikipedia(IErrorHandler errorHandler, IWikipediaClient wikipediaClient, IDatabase redis) + public Wikipedia(IErrorHandler errorHandler, IWikipediaClient wikipediaClient, DatabaseContext database) { _errorHandler = errorHandler; _wikipediaClient = wikipediaClient; - _redis = redis; + _database = database; } [Command("wiki", RunMode = RunMode.Async)] @@ -33,7 +33,7 @@ namespace Geekbot.net.Commands.Integrations { try { - var wikiLang = _redis.HashGet($"{Context.Guild.Id}:Settings", "WikiLang").ToString(); + var wikiLang = _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(Context.Guild.Id.AsLong()))?.WikiLang; if (string.IsNullOrEmpty(wikiLang)) { wikiLang = "en"; diff --git a/Geekbot.net/Commands/Randomness/Ship.cs b/Geekbot.net/Commands/Randomness/Ship.cs index 735bd51..2e3588d 100644 --- a/Geekbot.net/Commands/Randomness/Ship.cs +++ b/Geekbot.net/Commands/Randomness/Ship.cs @@ -1,21 +1,23 @@ using System; +using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib; +using Geekbot.net.Database; +using Geekbot.net.Database.Models; using Geekbot.net.Lib.ErrorHandling; -using StackExchange.Redis; +using Geekbot.net.Lib.Extensions; namespace Geekbot.net.Commands.Randomness { public class Ship : ModuleBase { private readonly IErrorHandler _errorHandler; - private readonly IDatabase _redis; + private readonly DatabaseContext _database; - public Ship(IDatabase redis, IErrorHandler errorHandler) + public Ship(DatabaseContext database, IErrorHandler errorHandler) { - _redis = redis; + _database = database; _errorHandler = errorHandler; } @@ -25,22 +27,29 @@ namespace Geekbot.net.Commands.Randomness { try { - var dbstring = ""; - if (user1.Id > user2.Id) - dbstring = $"{user1.Id}-{user2.Id}"; - else - dbstring = $"{user2.Id}-{user1.Id}"; + var userKeys = user1.Id < user2.Id + ? new Tuple(user1.Id.AsLong(), user2.Id.AsLong()) + : new Tuple(user2.Id.AsLong(), user1.Id.AsLong()); - var dbval = _redis.HashGet($"{Context.Guild.Id}:Ships", dbstring); + var dbval = _database.Ships.FirstOrDefault(s => + s.FirstUserId.Equals(userKeys.Item1) && + s.SecondUserId.Equals(userKeys.Item2)); + var shippingRate = 0; - if (dbval.IsNullOrEmpty) + if (dbval == null) { shippingRate = new Random().Next(1, 100); - _redis.HashSet($"{Context.Guild.Id}:Ships", dbstring, shippingRate); + _database.Ships.Add(new ShipsModel() + { + FirstUserId = userKeys.Item1, + SecondUserId = userKeys.Item2, + Strength = shippingRate + }); + _database.SaveChanges(); } else { - shippingRate = int.Parse(dbval.ToString()); + shippingRate = dbval.Strength; } var reply = ":heartpulse: **Matchmaking** :heartpulse:\r\n"; diff --git a/Geekbot.net/Commands/Randomness/Slap.cs b/Geekbot.net/Commands/Randomness/Slap.cs index 2cac9d2..b37742b 100644 --- a/Geekbot.net/Commands/Randomness/Slap.cs +++ b/Geekbot.net/Commands/Randomness/Slap.cs @@ -1,23 +1,25 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib; +using Geekbot.net.Database; +using Geekbot.net.Database.Models; using Geekbot.net.Lib.ErrorHandling; -using StackExchange.Redis; +using Geekbot.net.Lib.Extensions; namespace Geekbot.net.Commands.Randomness { public class Slap : ModuleBase { private readonly IErrorHandler _errorHandler; - private readonly IDatabase _redis; + private readonly DatabaseContext _database; - public Slap(IErrorHandler errorHandler, IDatabase redis) + public Slap(IErrorHandler errorHandler, DatabaseContext database) { _errorHandler = errorHandler; - _redis = redis; + _database = database; } [Command("slap", RunMode = RunMode.Async)] @@ -76,16 +78,53 @@ namespace Geekbot.net.Commands.Randomness "dictionary", "powerless banhammer" }; - - _redis.HashIncrement($"{Context.Guild.Id}:SlapsRecieved", user.Id.ToString()); - _redis.HashIncrement($"{Context.Guild.Id}:SlapsGiven", Context.User.Id.ToString()); - + await ReplyAsync($"{Context.User.Username} slapped {user.Username} with a {things[new Random().Next(things.Count - 1)]}"); + + UpdateRecieved(user.Id); + UpdateGiven(Context.User.Id); + _database.SaveChanges(); } catch (Exception e) { _errorHandler.HandleCommandException(e, Context); } } + + private void UpdateGiven(ulong userId) + { + var user = GetUser(userId); + user.Given++; + _database.Slaps.Update(user); + } + + private void UpdateRecieved(ulong userId) + { + var user = GetUser(userId); + user.Recieved++; + _database.Slaps.Update(user); + } + + private SlapsModel GetUser(ulong userId) + { + var user = _database.Slaps.FirstOrDefault(e => + e.GuildId.Equals(Context.Guild.Id.AsLong()) && + e.UserId.Equals(userId.AsLong()) + ); + + if (user != null) return user; + + _database.Slaps.Add(new SlapsModel + { + GuildId = Context.Guild.Id.AsLong(), + UserId = userId.AsLong(), + Recieved = 0, + Given = 0 + }); + _database.SaveChanges(); + return _database.Slaps.FirstOrDefault(e => + e.GuildId.Equals(Context.Guild.Id.AsLong()) && + e.UserId.Equals(userId.AsLong())); + } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/User/Ranking/Rank.cs b/Geekbot.net/Commands/User/Ranking/Rank.cs index dd1d026..027f41f 100644 --- a/Geekbot.net/Commands/User/Ranking/Rank.cs +++ b/Geekbot.net/Commands/User/Ranking/Rank.cs @@ -6,12 +6,12 @@ using System.Threading.Tasks; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Database; -using Geekbot.net.Lib; using Geekbot.net.Lib.Converters; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Logger; using Geekbot.net.Lib.UserRepository; +using StackExchange.Redis; namespace Geekbot.net.Commands.User.Ranking { @@ -23,9 +23,10 @@ namespace Geekbot.net.Commands.User.Ranking private readonly DatabaseContext _database; private readonly IUserRepository _userRepository; private readonly DiscordSocketClient _client; + private readonly IDatabase _redis; public Rank(DatabaseContext database, IErrorHandler errorHandler, IGeekbotLogger logger, IUserRepository userRepository, - IEmojiConverter emojiConverter, DiscordSocketClient client) + IEmojiConverter emojiConverter, DiscordSocketClient client, IDatabase redis) { _database = database; _errorHandler = errorHandler; @@ -33,6 +34,7 @@ namespace Geekbot.net.Commands.User.Ranking _userRepository = userRepository; _emojiConverter = emojiConverter; _client = client; + _redis = redis; } [Command("rank", RunMode = RunMode.Async)] @@ -74,8 +76,8 @@ namespace Geekbot.net.Commands.User.Ranking list = GetRollsList(amount); break; default: - list = new Dictionary(); - break; + await ReplyAsync("Valid types are '`messages`' '`karma`', '`rolls`'"); + return; } if (!list.Any()) @@ -142,18 +144,10 @@ namespace Geekbot.net.Commands.User.Ranking private Dictionary GetMessageList(int amount) { - var data = _database.Messages - .Where(k => k.GuildId.Equals(Context.Guild.Id.AsLong())) - .OrderByDescending(o => o.MessageCount) - .Take(amount); - - var dict = new Dictionary(); - foreach (var user in data) - { - dict.Add(user.UserId.AsUlong(), user.MessageCount); - } - return dict; + var data = _redis.HashGetAll($"{Context.Guild.Id}:Messages").ToDictionary().Take(amount + 1); + + return data.Where(user => !user.Key.Equals(0)).ToDictionary(user => ulong.Parse(user.Key), user => int.Parse(user.Value)); } private Dictionary GetKarmaList(int amount) diff --git a/Geekbot.net/Commands/User/Stats.cs b/Geekbot.net/Commands/User/Stats.cs index 93bddef..01d169e 100644 --- a/Geekbot.net/Commands/User/Stats.cs +++ b/Geekbot.net/Commands/User/Stats.cs @@ -1,9 +1,11 @@ using System; +using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib; +using Geekbot.net.Database; using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Levels; using StackExchange.Redis; @@ -14,10 +16,12 @@ namespace Geekbot.net.Commands.User private readonly IErrorHandler _errorHandler; private readonly ILevelCalc _levelCalc; private readonly IDatabase _redis; + private readonly DatabaseContext _database; - public Stats(IDatabase redis, IErrorHandler errorHandler, ILevelCalc levelCalc) + public Stats(IDatabase redis, DatabaseContext database, IErrorHandler errorHandler, ILevelCalc levelCalc) { _redis = redis; + _database = database; _errorHandler = errorHandler; _levelCalc = levelCalc; } @@ -47,20 +51,23 @@ namespace Geekbot.net.Commands.User .WithName(userInfo.Username)); eb.WithColor(new Color(221, 255, 119)); - var karma = _redis.HashGet($"{Context.Guild.Id}:Karma", userInfo.Id.ToString()); - var correctRolls = _redis.HashGet($"{Context.Guild.Id}:Rolls", userInfo.Id.ToString()); + var karma = _database.Karma.FirstOrDefault(e => + e.GuildId.Equals(Context.Guild.Id.AsLong()) && + e.UserId.Equals(userInfo.Id.AsLong())); + var correctRolls = _database.Rolls.FirstOrDefault(e => + e.GuildId.Equals(Context.Guild.Id.AsLong()) && + e.UserId.Equals(userInfo.Id.AsLong())); eb.AddInlineField("Discordian Since", $"{createdAt.Day}.{createdAt.Month}.{createdAt.Year} ({age} days)") .AddInlineField("Joined Server", $"{joinedAt.Day}.{joinedAt.Month}.{joinedAt.Year} ({joinedDayAgo} days)") - .AddInlineField("Karma", karma.ToString() ?? "0") + .AddInlineField("Karma", karma?.Karma ?? 0) .AddInlineField("Level", level) .AddInlineField("Messages Sent", messages) .AddInlineField("Server Total", $"{percent}%"); - if (!correctRolls.IsNullOrEmpty) - eb.AddInlineField("Guessed Rolls", correctRolls); + if (correctRolls != null) eb.AddInlineField("Guessed Rolls", correctRolls.Rolls); await ReplyAsync("", false, eb.Build()); } diff --git a/Geekbot.net/Database/DatabaseContext.cs b/Geekbot.net/Database/DatabaseContext.cs index e4fab28..e9de32c 100644 --- a/Geekbot.net/Database/DatabaseContext.cs +++ b/Geekbot.net/Database/DatabaseContext.cs @@ -15,8 +15,8 @@ namespace Geekbot.net.Database public DbSet Messages { get; set; } public DbSet Slaps { get; set; } public DbSet Globals { get; set; } - + public DbSet RoleSelfService { get; set; } + // public DbSet UserSettings { get; set; } - // public DbSet RoleSelfService { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Database/Models/RoleSelfServiceModel.cs b/Geekbot.net/Database/Models/RoleSelfServiceModel.cs index 4bb7f01..de8c341 100644 --- a/Geekbot.net/Database/Models/RoleSelfServiceModel.cs +++ b/Geekbot.net/Database/Models/RoleSelfServiceModel.cs @@ -1,7 +1,17 @@ -namespace Geekbot.net.Database.Models +using System.ComponentModel.DataAnnotations; + +namespace Geekbot.net.Database.Models { public class RoleSelfServiceModel { + [Key] + public int Id { get; set; } + [Required] + public long GuildId { get; set; } + + public long RoleId { get; set; } + + public string WhiteListName { get; set; } } } \ No newline at end of file From 4a11ce62077ff2e0b40bb5066fa2653497646648 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 13 May 2018 21:33:48 +0200 Subject: [PATCH 180/553] Add Guild Settings to redis migration --- Geekbot.net/Commands/User/Ranking/Rank.cs | 44 +++++------------- Geekbot.net/Database/RedisMigration.cs | 56 +++++++++++++++++++++++ 2 files changed, 68 insertions(+), 32 deletions(-) diff --git a/Geekbot.net/Commands/User/Ranking/Rank.cs b/Geekbot.net/Commands/User/Ranking/Rank.cs index 027f41f..6e3a1d8 100644 --- a/Geekbot.net/Commands/User/Ranking/Rank.cs +++ b/Geekbot.net/Commands/User/Ranking/Rank.cs @@ -4,12 +4,10 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Discord.Commands; -using Discord.WebSocket; using Geekbot.net.Database; using Geekbot.net.Lib.Converters; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; -using Geekbot.net.Lib.Logger; using Geekbot.net.Lib.UserRepository; using StackExchange.Redis; @@ -19,21 +17,17 @@ namespace Geekbot.net.Commands.User.Ranking { private readonly IEmojiConverter _emojiConverter; private readonly IErrorHandler _errorHandler; - private readonly IGeekbotLogger _logger; private readonly DatabaseContext _database; private readonly IUserRepository _userRepository; - private readonly DiscordSocketClient _client; private readonly IDatabase _redis; - public Rank(DatabaseContext database, IErrorHandler errorHandler, IGeekbotLogger logger, IUserRepository userRepository, - IEmojiConverter emojiConverter, DiscordSocketClient client, IDatabase redis) + public Rank(DatabaseContext database, IErrorHandler errorHandler, IUserRepository userRepository, + IEmojiConverter emojiConverter, IDatabase redis) { _database = database; _errorHandler = errorHandler; - _logger = logger; _userRepository = userRepository; _emojiConverter = emojiConverter; - _client = client; _redis = redis; } @@ -144,42 +138,28 @@ namespace Geekbot.net.Commands.User.Ranking private Dictionary GetMessageList(int amount) { - - var data = _redis.HashGetAll($"{Context.Guild.Id}:Messages").ToDictionary().Take(amount + 1); - - return data.Where(user => !user.Key.Equals(0)).ToDictionary(user => ulong.Parse(user.Key), user => int.Parse(user.Value)); + return _redis + .HashGetAll($"{Context.Guild.Id}:Messages").ToDictionary().Take(amount + 1) + .Where(user => !user.Key.Equals(0)) + .ToDictionary(user => ulong.Parse(user.Key), user => int.Parse(user.Value)); } private Dictionary GetKarmaList(int amount) { - var data = _database.Karma + return _database.Karma .Where(k => k.GuildId.Equals(Context.Guild.Id.AsLong())) .OrderByDescending(o => o.Karma) - .Take(amount); - - var dict = new Dictionary(); - foreach (var user in data) - { - dict.Add(user.UserId.AsUlong(), user.Karma); - } - - return dict; + .Take(amount) + .ToDictionary(key => key.UserId.AsUlong(), key => key.Karma); } private Dictionary GetRollsList(int amount) { - var data = _database.Rolls + return _database.Rolls .Where(k => k.GuildId.Equals(Context.Guild.Id.AsLong())) .OrderByDescending(o => o.Rolls) - .Take(amount); - - var dict = new Dictionary(); - foreach (var user in data) - { - dict.Add(user.UserId.AsUlong(), user.Rolls); - } - - return dict; + .Take(amount) + .ToDictionary(key => key.UserId.AsUlong(), key => key.Rolls); } } } \ No newline at end of file diff --git a/Geekbot.net/Database/RedisMigration.cs b/Geekbot.net/Database/RedisMigration.cs index 237ce60..25a7ee5 100644 --- a/Geekbot.net/Database/RedisMigration.cs +++ b/Geekbot.net/Database/RedisMigration.cs @@ -230,6 +230,62 @@ namespace Geekbot.net.Database } #endregion + #region GuildSettings + /** + * Users + */ + try + { + var data = _redis.HashGetAll($"{guild.Id}:Settings"); + var settings = new GuildSettingsModel() + { + GuildId = guild.Id.AsLong(), + Hui = true + }; + foreach (var setting in data) + { + try + { + switch (setting.Name) + { + case "ShowLeave": + settings.ShowLeave = setting.Value.ToString() == "1"; + break; + case "WikiDel": + settings.ShowDelete = setting.Value.ToString() == "1"; + break; + case "WikiLang": + settings.WikiLang = setting.Value.ToString(); + break; + case "Language": + settings.Language = setting.Value.ToString(); + break; + case "WelcomeMsg": + settings.WelcomeMessage = setting.Value.ToString(); + break; + case "ping": + settings.Ping = bool.Parse(setting.Value.ToString()); + break; + case "ModChannel": + settings.ModChannel = long.Parse(setting.Value); + break; + default: + throw new NotImplementedException(); + } + } + catch + { + _logger.Warning(LogSource.Geekbot, $"Setting failed: {setting.Name} - {guild.Id}"); + } + } + } + catch + { + _logger.Warning(LogSource.Geekbot, "Settings migration failed"); + } + + #endregion + #region Users /** * Users From 3004b192098e6290326454d7ce1af655e5616887 Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 14 May 2018 00:41:05 +0200 Subject: [PATCH 181/553] Small tweaks to the web api --- Geekbot.net/Lib/RunParameters.cs | 2 +- Geekbot.net/Program.cs | 4 +++- Geekbot.net/WebApi/Help/HelpController.cs | 7 ++----- Geekbot.net/WebApi/Status/StatusController.cs | 2 +- Geekbot.net/WebApi/WebConfig.cs | 20 +++++++++++++++++-- 5 files changed, 25 insertions(+), 10 deletions(-) diff --git a/Geekbot.net/Lib/RunParameters.cs b/Geekbot.net/Lib/RunParameters.cs index 7942b76..7f2dd3d 100644 --- a/Geekbot.net/Lib/RunParameters.cs +++ b/Geekbot.net/Lib/RunParameters.cs @@ -63,7 +63,7 @@ namespace Geekbot.net.Lib * WebApi * ************************************/ - [Option("api-host", Default = "127.0.0.1", HelpText = "Host on which the WebApi listens")] + [Option("api-host", Default = "localhost", HelpText = "Host on which the WebApi listens")] public string ApiHost { get; set; } [Option("api-port", Default = "12995", HelpText = "Port on which the WebApi listens")] diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 8084127..e5b3f59 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -19,6 +19,7 @@ using Geekbot.net.Lib.Logger; using Geekbot.net.Lib.Media; using Geekbot.net.Lib.ReactionListener; using Geekbot.net.Lib.UserRepository; +using Geekbot.net.WebApi; using Microsoft.Extensions.DependencyInjection; using Nancy.Hosting.Self; using StackExchange.Redis; @@ -202,7 +203,8 @@ namespace Geekbot.net { _logger.Information(LogSource.Api, "Starting Webserver"); var webApiUrl = new Uri($"http://{_runParameters.ApiHost}:{_runParameters.ApiPort}"); - new NancyHost(webApiUrl).Start(); + var webConfig = new WebConfig(_logger, _commands); + new NancyHost(webConfig, webApiUrl).Start(); _logger.Information(LogSource.Api, $"Webserver now running on {webApiUrl}"); } } diff --git a/Geekbot.net/WebApi/Help/HelpController.cs b/Geekbot.net/WebApi/Help/HelpController.cs index 015c7d8..8aaed12 100644 --- a/Geekbot.net/WebApi/Help/HelpController.cs +++ b/Geekbot.net/WebApi/Help/HelpController.cs @@ -2,19 +2,16 @@ using System.Reflection; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib; using Nancy; namespace Geekbot.net.WebApi.Help { - public class HelpController : NancyModule + public sealed class HelpController : NancyModule { - public HelpController() + public HelpController(CommandService commands) { Get("/v1/commands", args => { - var commands = GetCommands().Result; - var commandList = (from cmd in commands.Commands let cmdParamsObj = cmd.Parameters.Select(cmdParam => new CommandParamDto { diff --git a/Geekbot.net/WebApi/Status/StatusController.cs b/Geekbot.net/WebApi/Status/StatusController.cs index 05196a2..a2c692c 100644 --- a/Geekbot.net/WebApi/Status/StatusController.cs +++ b/Geekbot.net/WebApi/Status/StatusController.cs @@ -3,7 +3,7 @@ using Nancy; namespace Geekbot.net.WebApi.Status { - public class StatusController : NancyModule + public sealed class StatusController : NancyModule { public StatusController() { diff --git a/Geekbot.net/WebApi/WebConfig.cs b/Geekbot.net/WebApi/WebConfig.cs index f0b9ca3..6c5a70c 100644 --- a/Geekbot.net/WebApi/WebConfig.cs +++ b/Geekbot.net/WebApi/WebConfig.cs @@ -1,4 +1,6 @@ using System.Diagnostics; +using Discord.Commands; +using Geekbot.net.Lib.Logger; using Nancy; using Nancy.Bootstrapper; using Nancy.TinyIoc; @@ -7,12 +9,26 @@ namespace Geekbot.net.WebApi { public class WebConfig : DefaultNancyBootstrapper { + private readonly GeekbotLogger _logger; + private readonly CommandService _commands; + + public WebConfig(GeekbotLogger logger, CommandService commands) + { + _logger = logger; + _commands = commands; + } + protected override void RequestStartup(TinyIoCContainer container, IPipelines pipelines, NancyContext context) { - - //CORS Enable + // Register Dependencies + container.Register(_logger); + container.Register(_commands); + + // Enable CORS pipelines.AfterRequest.AddItemToEndOfPipeline(ctx => { + _logger.Information(LogSource.Api, ctx.Request.Path.ToString()); + ctx.Response.WithHeader("Access-Control-Allow-Origin", "*") .WithHeader("Access-Control-Allow-Methods", "GET") .WithHeader("Access-Control-Allow-Headers", "Accept, Origin, Content-type") From 8c107de92e29e11db7f971725ebfb774741fd798 Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 14 May 2018 02:33:49 +0200 Subject: [PATCH 182/553] Replace nancy with kestrel --- Geekbot.net/Geekbot.net.csproj | 6 +- Geekbot.net/Program.cs | 5 +- .../Commands}/CommandDto.cs | 2 +- .../Commands}/CommandParamDto.cs | 2 +- .../Controllers/Commands/HelpController.cs | 41 ++++++++++ .../{ => Controllers}/Status/ApiStatusDto.cs | 2 +- .../Controllers/Status/StatusController.cs | 22 ++++++ Geekbot.net/WebApi/Help/HelpController.cs | 44 ----------- Geekbot.net/WebApi/Logging/AspLogProvider.cs | 29 +++++++ Geekbot.net/WebApi/Logging/AspLogger.cs | 75 +++++++++++++++++++ Geekbot.net/WebApi/Status/StatusController.cs | 22 ------ Geekbot.net/WebApi/WebApiStartup.cs | 50 +++++++++++++ Geekbot.net/WebApi/WebConfig.cs | 39 ---------- 13 files changed, 222 insertions(+), 117 deletions(-) rename Geekbot.net/WebApi/{Help => Controllers/Commands}/CommandDto.cs (85%) rename Geekbot.net/WebApi/{Help => Controllers/Commands}/CommandParamDto.cs (74%) create mode 100644 Geekbot.net/WebApi/Controllers/Commands/HelpController.cs rename Geekbot.net/WebApi/{ => Controllers}/Status/ApiStatusDto.cs (75%) create mode 100644 Geekbot.net/WebApi/Controllers/Status/StatusController.cs delete mode 100644 Geekbot.net/WebApi/Help/HelpController.cs create mode 100644 Geekbot.net/WebApi/Logging/AspLogProvider.cs create mode 100644 Geekbot.net/WebApi/Logging/AspLogger.cs delete mode 100644 Geekbot.net/WebApi/Status/StatusController.cs create mode 100644 Geekbot.net/WebApi/WebApiStartup.cs delete mode 100644 Geekbot.net/WebApi/WebConfig.cs diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 27e5dad..83a37d9 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -24,6 +24,7 @@ + @@ -34,8 +35,6 @@ - - @@ -43,9 +42,6 @@ - - 1.2.6 - diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index e5b3f59..c9b53b3 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -19,9 +19,7 @@ using Geekbot.net.Lib.Logger; using Geekbot.net.Lib.Media; using Geekbot.net.Lib.ReactionListener; using Geekbot.net.Lib.UserRepository; -using Geekbot.net.WebApi; using Microsoft.Extensions.DependencyInjection; -using Nancy.Hosting.Self; using StackExchange.Redis; using WikipediaApi; @@ -203,8 +201,7 @@ namespace Geekbot.net { _logger.Information(LogSource.Api, "Starting Webserver"); var webApiUrl = new Uri($"http://{_runParameters.ApiHost}:{_runParameters.ApiPort}"); - var webConfig = new WebConfig(_logger, _commands); - new NancyHost(webConfig, webApiUrl).Start(); + WebApi.WebApiStartup.StartWebApi(_logger, _runParameters, _commands); _logger.Information(LogSource.Api, $"Webserver now running on {webApiUrl}"); } } diff --git a/Geekbot.net/WebApi/Help/CommandDto.cs b/Geekbot.net/WebApi/Controllers/Commands/CommandDto.cs similarity index 85% rename from Geekbot.net/WebApi/Help/CommandDto.cs rename to Geekbot.net/WebApi/Controllers/Commands/CommandDto.cs index 5921fa6..50f7872 100644 --- a/Geekbot.net/WebApi/Help/CommandDto.cs +++ b/Geekbot.net/WebApi/Controllers/Commands/CommandDto.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace Geekbot.net.WebApi.Help +namespace Geekbot.net.WebApi.Controllers.Commands { public class CommandDto { diff --git a/Geekbot.net/WebApi/Help/CommandParamDto.cs b/Geekbot.net/WebApi/Controllers/Commands/CommandParamDto.cs similarity index 74% rename from Geekbot.net/WebApi/Help/CommandParamDto.cs rename to Geekbot.net/WebApi/Controllers/Commands/CommandParamDto.cs index f7ce0ea..5f7519d 100644 --- a/Geekbot.net/WebApi/Help/CommandParamDto.cs +++ b/Geekbot.net/WebApi/Controllers/Commands/CommandParamDto.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.WebApi.Help +namespace Geekbot.net.WebApi.Controllers.Commands { public class CommandParamDto { diff --git a/Geekbot.net/WebApi/Controllers/Commands/HelpController.cs b/Geekbot.net/WebApi/Controllers/Commands/HelpController.cs new file mode 100644 index 0000000..9105706 --- /dev/null +++ b/Geekbot.net/WebApi/Controllers/Commands/HelpController.cs @@ -0,0 +1,41 @@ +using System.Linq; +using Discord.Commands; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; + +namespace Geekbot.net.WebApi.Controllers.Commands +{ + [EnableCors("AllowSpecificOrigin")] + public class HelpController : Controller + { + private readonly CommandService _commands; + + public HelpController(CommandService commands) + { + _commands = commands; + } + + [Route("/v1/commands")] + public IActionResult GetCommands() + { + var commandList = (from cmd in _commands.Commands + let cmdParamsObj = cmd.Parameters.Select(cmdParam => new CommandParamDto + { + Summary = cmdParam.Summary, + Default = cmdParam.DefaultValue?.ToString() ?? null, + Type = cmdParam.Type?.ToString() + }) + .ToList() + let param = string.Join(", !", cmd.Aliases) + select new CommandDto + { + Name = cmd.Name, + Summary = cmd.Summary, + IsAdminCommand = (param.Contains("admin")), + Aliases = cmd.Aliases.ToArray(), + Params = cmdParamsObj + }).ToList(); + return Ok(commandList); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/WebApi/Status/ApiStatusDto.cs b/Geekbot.net/WebApi/Controllers/Status/ApiStatusDto.cs similarity index 75% rename from Geekbot.net/WebApi/Status/ApiStatusDto.cs rename to Geekbot.net/WebApi/Controllers/Status/ApiStatusDto.cs index 242bf58..0d5e6ad 100644 --- a/Geekbot.net/WebApi/Status/ApiStatusDto.cs +++ b/Geekbot.net/WebApi/Controllers/Status/ApiStatusDto.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.WebApi.Status +namespace Geekbot.net.WebApi.Controllers.Status { public class ApiStatusDto { diff --git a/Geekbot.net/WebApi/Controllers/Status/StatusController.cs b/Geekbot.net/WebApi/Controllers/Status/StatusController.cs new file mode 100644 index 0000000..e9af6bb --- /dev/null +++ b/Geekbot.net/WebApi/Controllers/Status/StatusController.cs @@ -0,0 +1,22 @@ +using Geekbot.net.Lib; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; + +namespace Geekbot.net.WebApi.Controllers.Status +{ + [EnableCors("AllowSpecificOrigin")] + public class StatusController : Controller + { + [Route("/")] + public IActionResult GetCommands() + { + var responseBody = new ApiStatusDto + { + GeekbotVersion = Constants.BotVersion(), + ApiVersion = Constants.ApiVersion.ToString(), + Status = "Online" + }; + return Ok(responseBody); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/WebApi/Help/HelpController.cs b/Geekbot.net/WebApi/Help/HelpController.cs deleted file mode 100644 index 8aaed12..0000000 --- a/Geekbot.net/WebApi/Help/HelpController.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.Linq; -using System.Reflection; -using System.Threading.Tasks; -using Discord.Commands; -using Nancy; - -namespace Geekbot.net.WebApi.Help -{ - public sealed class HelpController : NancyModule - { - public HelpController(CommandService commands) - { - Get("/v1/commands", args => - { - var commandList = (from cmd in commands.Commands - let cmdParamsObj = cmd.Parameters.Select(cmdParam => new CommandParamDto - { - Summary = cmdParam.Summary, - Default = cmdParam.DefaultValue?.ToString() ?? null, - Type = cmdParam.Type?.ToString() - }) - .ToList() - let param = string.Join(", !", cmd.Aliases) - select new CommandDto - { - Name = cmd.Name, - Summary = cmd.Summary, - IsAdminCommand = (param.Contains("admin")), - Aliases = cmd.Aliases.ToArray(), - Params = cmdParamsObj - }).ToList(); - return Response.AsJson(commandList); - - }); - } - - private async Task GetCommands() - { - var commands = new CommandService(); - await commands.AddModulesAsync(Assembly.GetEntryAssembly()); - return commands; - } - } -} \ No newline at end of file diff --git a/Geekbot.net/WebApi/Logging/AspLogProvider.cs b/Geekbot.net/WebApi/Logging/AspLogProvider.cs new file mode 100644 index 0000000..9a1599a --- /dev/null +++ b/Geekbot.net/WebApi/Logging/AspLogProvider.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Concurrent; +using Geekbot.net.Lib.Logger; +using Microsoft.Extensions.Logging; + +namespace Geekbot.net.WebApi.Logging +{ + public class AspLogProvider : ILoggerProvider + { + private readonly IGeekbotLogger _geekbotLogger; + + private readonly ConcurrentDictionary _loggers = new ConcurrentDictionary(); + + public AspLogProvider(IGeekbotLogger geekbotLogger) + { + _geekbotLogger = geekbotLogger; + } + + public void Dispose() + { + _loggers.Clear(); + } + + public ILogger CreateLogger(string categoryName) + { + return _loggers.GetOrAdd(categoryName, name => new AspLogger(categoryName, _geekbotLogger)); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/WebApi/Logging/AspLogger.cs b/Geekbot.net/WebApi/Logging/AspLogger.cs new file mode 100644 index 0000000..37c9de1 --- /dev/null +++ b/Geekbot.net/WebApi/Logging/AspLogger.cs @@ -0,0 +1,75 @@ +using System; +using Geekbot.net.Lib.Logger; +using Microsoft.Extensions.Logging; + +namespace Geekbot.net.WebApi.Logging +{ + public class AspLogger : ILogger + { + private readonly string _categoryName; + private readonly IGeekbotLogger _geekbotLogger; + + public AspLogger(string categoryName, IGeekbotLogger geekbotLogger) + { + geekbotLogger.Trace(LogSource.Api, $"Adding {categoryName}"); + _categoryName = categoryName; + _geekbotLogger = geekbotLogger; + } + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + { + switch (logLevel) + { + case LogLevel.Trace: + _geekbotLogger.Trace(LogSource.Api, $"{eventId.Id} - {_categoryName} - {state}"); + break; + case LogLevel.Debug: + _geekbotLogger.Debug(LogSource.Api, $"{eventId.Id} - {_categoryName} - {state}"); + break; + case LogLevel.Information: + _geekbotLogger.Information(LogSource.Api, $"{eventId.Id} - {_categoryName} - {state}"); + break; + case LogLevel.Warning: + _geekbotLogger.Warning(LogSource.Api, $"{eventId.Id} - {_categoryName} - {state}", exception); + break; + case LogLevel.Error: + case LogLevel.Critical: + _geekbotLogger.Error(LogSource.Api, $"{eventId.Id} - {_categoryName} - {state}", exception); + break; + default: + throw new ArgumentOutOfRangeException(nameof(logLevel)); + } + } + + public bool IsEnabled(LogLevel logLevel) + { + return !_geekbotLogger.LogAsJson() && _geekbotLogger.GetNLogger().IsEnabled(ToGeekbotLogLevel(logLevel)); + } + + public IDisposable BeginScope(TState state) + { + return null; + } + + private static NLog.LogLevel ToGeekbotLogLevel(LogLevel level) + { + switch (level) + { + case LogLevel.Trace: + return NLog.LogLevel.Trace; + case LogLevel.Debug: + return NLog.LogLevel.Debug; + case LogLevel.Information: + return NLog.LogLevel.Info; + case LogLevel.Warning: + return NLog.LogLevel.Warn; + case LogLevel.Error: + return NLog.LogLevel.Error; + case LogLevel.Critical: + return NLog.LogLevel.Fatal; + default: + throw new ArgumentOutOfRangeException(nameof(level)); + } + } + } +} \ No newline at end of file diff --git a/Geekbot.net/WebApi/Status/StatusController.cs b/Geekbot.net/WebApi/Status/StatusController.cs deleted file mode 100644 index a2c692c..0000000 --- a/Geekbot.net/WebApi/Status/StatusController.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Geekbot.net.Lib; -using Nancy; - -namespace Geekbot.net.WebApi.Status -{ - public sealed class StatusController : NancyModule - { - public StatusController() - { - Get("/", args => - { - var responseBody = new ApiStatusDto - { - GeekbotVersion = Constants.BotVersion(), - ApiVersion = Constants.ApiVersion.ToString(), - Status = "Online" - }; - return Response.AsJson(responseBody); - }); - } - } -} \ No newline at end of file diff --git a/Geekbot.net/WebApi/WebApiStartup.cs b/Geekbot.net/WebApi/WebApiStartup.cs new file mode 100644 index 0000000..675ba1b --- /dev/null +++ b/Geekbot.net/WebApi/WebApiStartup.cs @@ -0,0 +1,50 @@ +using System; +using System.Net; +using System.Reflection; +using Discord.Commands; +using Geekbot.net.Lib; +using Geekbot.net.Lib.Logger; +using Geekbot.net.WebApi.Logging; +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace Geekbot.net.WebApi +{ + public class WebApiStartup + { + public static void StartWebApi(IGeekbotLogger logger, RunParameters runParameters, CommandService commandService) + { + WebHost.CreateDefaultBuilder() + .UseKestrel(options => + { + options.Listen(IPAddress.Any, int.Parse(runParameters.ApiPort)); + }) + .ConfigureServices(services => + { + services.AddMvc(); + services.AddSingleton(commandService); + services.AddCors(options => + { + options.AddPolicy("AllowSpecificOrigin", + builder => builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()); + }); + }) + .Configure(app => + { + app.UseMvc(); + app.UseCors(builder => builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod().Build()); + }) + .ConfigureLogging(logging => + { + logging.ClearProviders(); + logging.SetMinimumLevel(LogLevel.Debug); + logging.AddProvider(new AspLogProvider(logger)); + }) + .UseSetting(WebHostDefaults.ApplicationKey, typeof(Program).GetTypeInfo().Assembly.FullName) + .Build().Run(); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/WebApi/WebConfig.cs b/Geekbot.net/WebApi/WebConfig.cs deleted file mode 100644 index 6c5a70c..0000000 --- a/Geekbot.net/WebApi/WebConfig.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Diagnostics; -using Discord.Commands; -using Geekbot.net.Lib.Logger; -using Nancy; -using Nancy.Bootstrapper; -using Nancy.TinyIoc; - -namespace Geekbot.net.WebApi -{ - public class WebConfig : DefaultNancyBootstrapper - { - private readonly GeekbotLogger _logger; - private readonly CommandService _commands; - - public WebConfig(GeekbotLogger logger, CommandService commands) - { - _logger = logger; - _commands = commands; - } - - protected override void RequestStartup(TinyIoCContainer container, IPipelines pipelines, NancyContext context) - { - // Register Dependencies - container.Register(_logger); - container.Register(_commands); - - // Enable CORS - pipelines.AfterRequest.AddItemToEndOfPipeline(ctx => - { - _logger.Information(LogSource.Api, ctx.Request.Path.ToString()); - - ctx.Response.WithHeader("Access-Control-Allow-Origin", "*") - .WithHeader("Access-Control-Allow-Methods", "GET") - .WithHeader("Access-Control-Allow-Headers", "Accept, Origin, Content-type") - .WithHeader("Last-Modified", Process.GetCurrentProcess().StartTime.ToString()); - }); - } - } -} \ No newline at end of file From e0d6a97dca2102b8a755edb26ec688acf6296d58 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Mon, 14 May 2018 18:57:07 +0200 Subject: [PATCH 183/553] make database saves async --- Geekbot.net/Commands/Admin/Admin.cs | 16 ++++++++-------- Geekbot.net/Commands/Admin/Role.cs | 4 ++-- Geekbot.net/Commands/Randomness/Ship.cs | 2 +- Geekbot.net/Commands/Randomness/Slap.cs | 2 +- Geekbot.net/Commands/User/Karma.cs | 4 ++-- Geekbot.net/Commands/Utils/Quote/Quote.cs | 6 +++--- Geekbot.net/Database/RedisMigration.cs | 20 +++++++++----------- 7 files changed, 26 insertions(+), 28 deletions(-) diff --git a/Geekbot.net/Commands/Admin/Admin.cs b/Geekbot.net/Commands/Admin/Admin.cs index f3366a6..fc0c231 100644 --- a/Geekbot.net/Commands/Admin/Admin.cs +++ b/Geekbot.net/Commands/Admin/Admin.cs @@ -39,7 +39,7 @@ namespace Geekbot.net.Commands.Admin var guild = GetGuildSettings(Context.Guild.Id); guild.WelcomeMessage = welcomeMessage; _database.GuildSettings.Update(guild); - _database.SaveChanges(); + await _database.SaveChangesAsync(); var formatedMessage = welcomeMessage.Replace("$user", Context.User.Mention); await ReplyAsync($"Welcome message has been changed\r\nHere is an example of how it would look:\r\n{formatedMessage}"); @@ -56,7 +56,7 @@ namespace Geekbot.net.Commands.Admin var guild = GetGuildSettings(Context.Guild.Id); guild.ModChannel = channel.Id.AsLong(); _database.GuildSettings.Update(guild); - _database.SaveChanges(); + await _database.SaveChangesAsync(); var sb = new StringBuilder(); sb.AppendLine("Successfully saved mod channel, you can now do the following"); @@ -82,7 +82,7 @@ namespace Geekbot.net.Commands.Admin guild.ShowLeave = !guild.ShowLeave; _database.GuildSettings.Update(guild); - _database.SaveChanges(); + await _database.SaveChangesAsync(); await modChannel.SendMessageAsync(guild.ShowLeave ? "Saved - now sending messages here when someone leaves" : "Saved - stopping sending messages here when someone leaves" @@ -106,7 +106,7 @@ namespace Geekbot.net.Commands.Admin guild.ShowDelete = !guild.ShowDelete; _database.GuildSettings.Update(guild); - _database.SaveChanges(); + await _database.SaveChangesAsync(); await modChannel.SendMessageAsync(guild.ShowDelete ? "Saved - now sending messages here when someone deletes a message" : "Saved - stopping sending messages here when someone deletes a message" @@ -131,7 +131,7 @@ namespace Geekbot.net.Commands.Admin var guild = GetGuildSettings(Context.Guild.Id); guild.Language = language; _database.GuildSettings.Update(guild); - _database.SaveChanges(); + await _database.SaveChangesAsync(); var trans = _translation.GetDict(Context); await ReplyAsync(trans["NewLanguageSet"]); @@ -157,7 +157,7 @@ namespace Geekbot.net.Commands.Admin var guild = GetGuildSettings(Context.Guild.Id); guild.WikiLang = language; _database.GuildSettings.Update(guild); - _database.SaveChanges(); + await _database.SaveChangesAsync(); await ReplyAsync($"Now using the {language} wikipedia"); } @@ -176,7 +176,7 @@ namespace Geekbot.net.Commands.Admin var guild = GetGuildSettings(Context.Guild.Id); guild.Ping = !guild.Ping; _database.GuildSettings.Update(guild); - _database.SaveChanges(); + await _database.SaveChangesAsync(); await ReplyAsync(guild.Ping ? "i will reply to ping now" : "No more pongs..."); } catch (Exception e) @@ -194,7 +194,7 @@ namespace Geekbot.net.Commands.Admin var guild = GetGuildSettings(Context.Guild.Id); guild.Hui = !guild.Hui; _database.GuildSettings.Update(guild); - _database.SaveChanges(); + await _database.SaveChangesAsync(); await ReplyAsync(guild.Hui ? "i will reply to hui now" : "No more hui's..."); } catch (Exception e) diff --git a/Geekbot.net/Commands/Admin/Role.cs b/Geekbot.net/Commands/Admin/Role.cs index a3a649e..c4d2362 100644 --- a/Geekbot.net/Commands/Admin/Role.cs +++ b/Geekbot.net/Commands/Admin/Role.cs @@ -125,7 +125,7 @@ namespace Geekbot.net.Commands.Admin RoleId = role.Id.AsLong(), WhiteListName = roleName }); - _database.SaveChanges(); + await _database.SaveChangesAsync(); await ReplyAsync($"Added {role.Name} to the whitelist"); } catch (Exception e) @@ -146,7 +146,7 @@ namespace Geekbot.net.Commands.Admin if (roleFromDb != null) { _database.RoleSelfService.Remove(roleFromDb); - _database.SaveChanges(); + await _database.SaveChangesAsync(); await ReplyAsync($"Removed {roleName} from the whitelist"); return; } diff --git a/Geekbot.net/Commands/Randomness/Ship.cs b/Geekbot.net/Commands/Randomness/Ship.cs index 2e3588d..0f33da5 100644 --- a/Geekbot.net/Commands/Randomness/Ship.cs +++ b/Geekbot.net/Commands/Randomness/Ship.cs @@ -45,7 +45,7 @@ namespace Geekbot.net.Commands.Randomness SecondUserId = userKeys.Item2, Strength = shippingRate }); - _database.SaveChanges(); + await _database.SaveChangesAsync(); } else { diff --git a/Geekbot.net/Commands/Randomness/Slap.cs b/Geekbot.net/Commands/Randomness/Slap.cs index b37742b..fea5991 100644 --- a/Geekbot.net/Commands/Randomness/Slap.cs +++ b/Geekbot.net/Commands/Randomness/Slap.cs @@ -83,7 +83,7 @@ namespace Geekbot.net.Commands.Randomness UpdateRecieved(user.Id); UpdateGiven(Context.User.Id); - _database.SaveChanges(); + await _database.SaveChangesAsync(); } catch (Exception e) { diff --git a/Geekbot.net/Commands/User/Karma.cs b/Geekbot.net/Commands/User/Karma.cs index 2f427c8..bf2511f 100644 --- a/Geekbot.net/Commands/User/Karma.cs +++ b/Geekbot.net/Commands/User/Karma.cs @@ -51,7 +51,7 @@ namespace Geekbot.net.Commands.User actor.TimeOut = DateTimeOffset.Now; SetUser(actor); - _database.SaveChanges(); + await _database.SaveChangesAsync(); var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder() @@ -98,7 +98,7 @@ namespace Geekbot.net.Commands.User actor.TimeOut = DateTimeOffset.Now; SetUser(actor); - _database.SaveChanges(); + await _database.SaveChangesAsync(); var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder() diff --git a/Geekbot.net/Commands/Utils/Quote/Quote.cs b/Geekbot.net/Commands/Utils/Quote/Quote.cs index ef0cbc8..dab31a0 100644 --- a/Geekbot.net/Commands/Utils/Quote/Quote.cs +++ b/Geekbot.net/Commands/Utils/Quote/Quote.cs @@ -74,7 +74,7 @@ namespace Geekbot.net.Commands.Utils.Quote var quote = CreateQuoteObject(lastMessage); _database.Quotes.Add(quote); - _database.SaveChanges(); + await _database.SaveChangesAsync(); var embed = QuoteBuilder(quote); await ReplyAsync("**Quote Added**", false, embed.Build()); @@ -107,7 +107,7 @@ namespace Geekbot.net.Commands.Utils.Quote var quote = CreateQuoteObject(message); _database.Quotes.Add(quote); - _database.SaveChanges(); + await _database.SaveChangesAsync(); var embed = QuoteBuilder(quote); await ReplyAsync("**Quote Added**", false, embed.Build()); @@ -169,7 +169,7 @@ namespace Geekbot.net.Commands.Utils.Quote if (quote != null) { _database.Quotes.Remove(quote); - _database.SaveChanges(); + await _database.SaveChangesAsync(); var embed = QuoteBuilder(quote); await ReplyAsync($"**Removed #{id}**", false, embed.Build()); } diff --git a/Geekbot.net/Database/RedisMigration.cs b/Geekbot.net/Database/RedisMigration.cs index 25a7ee5..c7dd881 100644 --- a/Geekbot.net/Database/RedisMigration.cs +++ b/Geekbot.net/Database/RedisMigration.cs @@ -29,7 +29,7 @@ namespace Geekbot.net.Database _client = client; } - public Task Migrate() + public async Task Migrate() { _logger.Information(LogSource.Geekbot, "Starting migration process"); foreach (var guild in _client.Guilds) @@ -49,7 +49,7 @@ namespace Geekbot.net.Database var qd = JsonConvert.DeserializeObject(q); var quote = CreateQuoteObject(guild.Id, qd); _database.Quotes.Add(quote); - _database.SaveChanges(); + await _database.SaveChangesAsync(); } catch { @@ -82,7 +82,7 @@ namespace Geekbot.net.Database TimeOut = DateTimeOffset.MinValue }; _database.Karma.Add(user); - _database.SaveChanges(); + await _database.SaveChangesAsync(); } catch { @@ -114,7 +114,7 @@ namespace Geekbot.net.Database Rolls = int.Parse(q.Value) }; _database.Rolls.Add(user); - _database.SaveChanges(); + await _database.SaveChangesAsync(); } catch { @@ -148,7 +148,7 @@ namespace Geekbot.net.Database Recieved= int.Parse(gotten[int.Parse(q.Name)].Value) }; _database.Slaps.Add(user); - _database.SaveChanges(); + await _database.SaveChangesAsync(); } catch { @@ -180,7 +180,7 @@ namespace Geekbot.net.Database MessageCount= int.Parse(q.Value) }; _database.Messages.Add(user); - _database.SaveChanges(); + await _database.SaveChangesAsync(); } catch { @@ -215,7 +215,7 @@ namespace Geekbot.net.Database Strength = int.Parse(q.Value) }; _database.Ships.Add(user); - _database.SaveChanges(); + await _database.SaveChangesAsync(); done.Add(q.Name); } catch @@ -309,7 +309,7 @@ namespace Geekbot.net.Database Joined = user.CreatedAt, UsedNames = names }, model => model.UserId.Equals(user.Id.AsLong())); - _database.SaveChanges(); + await _database.SaveChangesAsync(); } catch { @@ -333,14 +333,12 @@ namespace Geekbot.net.Database Name = guild.Name, Owner = guild.Owner.Id.AsLong() }); - _database.SaveChanges(); + await _database.SaveChangesAsync(); #endregion _logger.Information(LogSource.Geekbot, $"Finished Migration for {guild.Name}"); } _logger.Information(LogSource.Geekbot, "Finished migration process"); - - return Task.CompletedTask;; } private QuoteModel CreateQuoteObject(ulong guild, QuoteObjectDto quote) From acb2b25e099b383301115f5cba88c57001ff387a Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 15 May 2018 01:18:26 +0200 Subject: [PATCH 184/553] Resharper cleanup and fixes and remove useless asp overhead --- Geekbot.net/Commands/Admin/Admin.cs | 1 - Geekbot.net/Commands/Admin/Say.cs | 1 - Geekbot.net/Commands/Audio/Voice.cs | 2 +- Geekbot.net/Commands/Games/Pokedex.cs | 1 - Geekbot.net/Commands/Games/Roll.cs | 1 - .../Integrations/MagicTheGathering.cs | 1 - Geekbot.net/Commands/Integrations/Mal.cs | 1 - .../UbranDictionary/UrbanDictionary.cs | 1 - Geekbot.net/Commands/Randomness/Cat/Cat.cs | 1 - Geekbot.net/Commands/Randomness/CheckEm.cs | 1 - .../Randomness/Chuck/ChuckNorrisJokes.cs | 1 - .../Commands/Randomness/Dad/DadJokes.cs | 1 - Geekbot.net/Commands/Randomness/Dog/Dog.cs | 1 - Geekbot.net/Commands/Randomness/EightBall.cs | 1 - Geekbot.net/Commands/Randomness/Fortune.cs | 1 - Geekbot.net/Commands/Randomness/Gdq.cs | 1 - .../Commands/Randomness/RandomAnimals.cs | 1 - Geekbot.net/Commands/User/GuildInfo.cs | 3 +- Geekbot.net/Commands/User/Karma.cs | 1 - Geekbot.net/Commands/Utils/AvatarGetter.cs | 1 - .../Commands/Utils/Changelog/Changelog.cs | 1 - Geekbot.net/Commands/Utils/Choose.cs | 1 - Geekbot.net/Commands/Utils/Dice/Dice.cs | 1 - Geekbot.net/Commands/Utils/Emojify.cs | 1 - Geekbot.net/Commands/Utils/Help.cs | 1 - Geekbot.net/Commands/Utils/Ping.cs | 1 - Geekbot.net/Commands/Utils/Poll/Poll.cs | 6 ++-- Geekbot.net/Commands/Utils/Quote/Quote.cs | 2 -- Geekbot.net/Database/InMemoryDatabase.cs | 3 +- Geekbot.net/Database/Models/UserModel.cs | 1 - Geekbot.net/Database/RedisMigration.cs | 1 - Geekbot.net/Geekbot.net.csproj | 6 +++- Geekbot.net/Handlers.cs | 4 ++- Geekbot.net/Lib/Clients/MalClient.cs | 29 +++++++------------ Geekbot.net/Lib/Logger/DiscordLogger.cs | 1 - .../Lib/UserRepository/UserRepository.cs | 1 - Geekbot.net/Program.cs | 19 ++++++------ ...HelpController.cs => CommandController.cs} | 8 ++--- .../Controllers/Status/StatusController.cs | 5 ++-- Geekbot.net/WebApi/Logging/AspLogProvider.cs | 3 +- Geekbot.net/WebApi/Logging/AspLogger.cs | 5 ++++ Geekbot.net/WebApi/WebApiStartup.cs | 10 ++++--- Tests/Lib/EmojiConverter.test.cs | 1 - Tests/Lib/LevelCalc.test.cs | 1 - 44 files changed, 54 insertions(+), 81 deletions(-) rename Geekbot.net/WebApi/Controllers/Commands/{HelpController.cs => CommandController.cs} (83%) diff --git a/Geekbot.net/Commands/Admin/Admin.cs b/Geekbot.net/Commands/Admin/Admin.cs index fc0c231..0925e54 100644 --- a/Geekbot.net/Commands/Admin/Admin.cs +++ b/Geekbot.net/Commands/Admin/Admin.cs @@ -10,7 +10,6 @@ using Geekbot.net.Database.Models; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Localization; -using StackExchange.Redis; namespace Geekbot.net.Commands.Admin { diff --git a/Geekbot.net/Commands/Admin/Say.cs b/Geekbot.net/Commands/Admin/Say.cs index f8708cd..f3db09b 100644 --- a/Geekbot.net/Commands/Admin/Say.cs +++ b/Geekbot.net/Commands/Admin/Say.cs @@ -2,7 +2,6 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; namespace Geekbot.net.Commands.Admin diff --git a/Geekbot.net/Commands/Audio/Voice.cs b/Geekbot.net/Commands/Audio/Voice.cs index 410d8e2..169f298 100644 --- a/Geekbot.net/Commands/Audio/Voice.cs +++ b/Geekbot.net/Commands/Audio/Voice.cs @@ -65,7 +65,7 @@ namespace Geekbot.net.Commands.Audio } // [Command("ytplay")] - public async Task ytplay(string url) + public async Task Ytplay(string url) { try { diff --git a/Geekbot.net/Commands/Games/Pokedex.cs b/Geekbot.net/Commands/Games/Pokedex.cs index d4cbc0e..25f4c88 100644 --- a/Geekbot.net/Commands/Games/Pokedex.cs +++ b/Geekbot.net/Commands/Games/Pokedex.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; using PokeAPI; diff --git a/Geekbot.net/Commands/Games/Roll.cs b/Geekbot.net/Commands/Games/Roll.cs index 59a3c27..1d2ab4f 100644 --- a/Geekbot.net/Commands/Games/Roll.cs +++ b/Geekbot.net/Commands/Games/Roll.cs @@ -1,7 +1,6 @@ using System; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Localization; using StackExchange.Redis; diff --git a/Geekbot.net/Commands/Integrations/MagicTheGathering.cs b/Geekbot.net/Commands/Integrations/MagicTheGathering.cs index 842c9de..968c558 100644 --- a/Geekbot.net/Commands/Integrations/MagicTheGathering.cs +++ b/Geekbot.net/Commands/Integrations/MagicTheGathering.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib; using Geekbot.net.Lib.Converters; using Geekbot.net.Lib.ErrorHandling; using MtgApiManager.Lib.Service; diff --git a/Geekbot.net/Commands/Integrations/Mal.cs b/Geekbot.net/Commands/Integrations/Mal.cs index 36c6457..b617b44 100644 --- a/Geekbot.net/Commands/Integrations/Mal.cs +++ b/Geekbot.net/Commands/Integrations/Mal.cs @@ -3,7 +3,6 @@ using System.Threading.Tasks; using System.Web; using Discord; using Discord.Commands; -using Geekbot.net.Lib; using Geekbot.net.Lib.Clients; using Geekbot.net.Lib.ErrorHandling; diff --git a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs b/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs index 3ad37f3..36d70b1 100644 --- a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs +++ b/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs @@ -4,7 +4,6 @@ using System.Net.Http; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; using Newtonsoft.Json; diff --git a/Geekbot.net/Commands/Randomness/Cat/Cat.cs b/Geekbot.net/Commands/Randomness/Cat/Cat.cs index a79eb37..f46ed25 100644 --- a/Geekbot.net/Commands/Randomness/Cat/Cat.cs +++ b/Geekbot.net/Commands/Randomness/Cat/Cat.cs @@ -3,7 +3,6 @@ using System.Net.Http; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; using Newtonsoft.Json; diff --git a/Geekbot.net/Commands/Randomness/CheckEm.cs b/Geekbot.net/Commands/Randomness/CheckEm.cs index 325d7cc..94a895a 100644 --- a/Geekbot.net/Commands/Randomness/CheckEm.cs +++ b/Geekbot.net/Commands/Randomness/CheckEm.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Media; diff --git a/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs b/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs index 8e8a369..b9d906e 100644 --- a/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs +++ b/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs @@ -3,7 +3,6 @@ using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; using Newtonsoft.Json; diff --git a/Geekbot.net/Commands/Randomness/Dad/DadJokes.cs b/Geekbot.net/Commands/Randomness/Dad/DadJokes.cs index a14a098..3945609 100644 --- a/Geekbot.net/Commands/Randomness/Dad/DadJokes.cs +++ b/Geekbot.net/Commands/Randomness/Dad/DadJokes.cs @@ -3,7 +3,6 @@ using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; using Newtonsoft.Json; diff --git a/Geekbot.net/Commands/Randomness/Dog/Dog.cs b/Geekbot.net/Commands/Randomness/Dog/Dog.cs index 83d7a2e..6606ef5 100644 --- a/Geekbot.net/Commands/Randomness/Dog/Dog.cs +++ b/Geekbot.net/Commands/Randomness/Dog/Dog.cs @@ -3,7 +3,6 @@ using System.Net.Http; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; using Newtonsoft.Json; diff --git a/Geekbot.net/Commands/Randomness/EightBall.cs b/Geekbot.net/Commands/Randomness/EightBall.cs index cf59431..b6f37d3 100644 --- a/Geekbot.net/Commands/Randomness/EightBall.cs +++ b/Geekbot.net/Commands/Randomness/EightBall.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; namespace Geekbot.net.Commands.Randomness diff --git a/Geekbot.net/Commands/Randomness/Fortune.cs b/Geekbot.net/Commands/Randomness/Fortune.cs index 498085a..d4f6b5f 100644 --- a/Geekbot.net/Commands/Randomness/Fortune.cs +++ b/Geekbot.net/Commands/Randomness/Fortune.cs @@ -1,6 +1,5 @@ using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib; using Geekbot.net.Lib.Media; namespace Geekbot.net.Commands.Randomness diff --git a/Geekbot.net/Commands/Randomness/Gdq.cs b/Geekbot.net/Commands/Randomness/Gdq.cs index 8d0472c..c723c6f 100644 --- a/Geekbot.net/Commands/Randomness/Gdq.cs +++ b/Geekbot.net/Commands/Randomness/Gdq.cs @@ -2,7 +2,6 @@ using System.Net; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; namespace Geekbot.net.Commands.Randomness diff --git a/Geekbot.net/Commands/Randomness/RandomAnimals.cs b/Geekbot.net/Commands/Randomness/RandomAnimals.cs index 608b52d..90138af 100644 --- a/Geekbot.net/Commands/Randomness/RandomAnimals.cs +++ b/Geekbot.net/Commands/Randomness/RandomAnimals.cs @@ -1,7 +1,6 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib; using Geekbot.net.Lib.Media; namespace Geekbot.net.Commands.Randomness diff --git a/Geekbot.net/Commands/User/GuildInfo.cs b/Geekbot.net/Commands/User/GuildInfo.cs index c475d99..6f602b1 100644 --- a/Geekbot.net/Commands/User/GuildInfo.cs +++ b/Geekbot.net/Commands/User/GuildInfo.cs @@ -4,7 +4,6 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Database; -using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Levels; @@ -42,7 +41,7 @@ namespace Geekbot.net.Commands.User var messages = _database.Messages .Where(e => e.GuildId == Context.Guild.Id.AsLong()) .Sum(e => e.MessageCount); - var level = _levelCalc.GetLevel((int) messages); + var level = _levelCalc.GetLevel(messages); eb.AddField("Server Age", $"{created.Day}/{created.Month}/{created.Year} ({age} days)"); eb.AddInlineField("Level", level) diff --git a/Geekbot.net/Commands/User/Karma.cs b/Geekbot.net/Commands/User/Karma.cs index bf2511f..8a9189d 100644 --- a/Geekbot.net/Commands/User/Karma.cs +++ b/Geekbot.net/Commands/User/Karma.cs @@ -5,7 +5,6 @@ using Discord; using Discord.Commands; using Geekbot.net.Database; using Geekbot.net.Database.Models; -using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Localization; diff --git a/Geekbot.net/Commands/Utils/AvatarGetter.cs b/Geekbot.net/Commands/Utils/AvatarGetter.cs index cf34ca3..3f74770 100644 --- a/Geekbot.net/Commands/Utils/AvatarGetter.cs +++ b/Geekbot.net/Commands/Utils/AvatarGetter.cs @@ -2,7 +2,6 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; namespace Geekbot.net.Commands.Utils diff --git a/Geekbot.net/Commands/Utils/Changelog/Changelog.cs b/Geekbot.net/Commands/Utils/Changelog/Changelog.cs index c218c66..5d47c08 100644 --- a/Geekbot.net/Commands/Utils/Changelog/Changelog.cs +++ b/Geekbot.net/Commands/Utils/Changelog/Changelog.cs @@ -7,7 +7,6 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.WebSocket; -using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; using Newtonsoft.Json; diff --git a/Geekbot.net/Commands/Utils/Choose.cs b/Geekbot.net/Commands/Utils/Choose.cs index 2b9ff19..411802a 100644 --- a/Geekbot.net/Commands/Utils/Choose.cs +++ b/Geekbot.net/Commands/Utils/Choose.cs @@ -1,7 +1,6 @@ using System; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Localization; diff --git a/Geekbot.net/Commands/Utils/Dice/Dice.cs b/Geekbot.net/Commands/Utils/Dice/Dice.cs index c8e31f5..7733476 100644 --- a/Geekbot.net/Commands/Utils/Dice/Dice.cs +++ b/Geekbot.net/Commands/Utils/Dice/Dice.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib; namespace Geekbot.net.Commands.Utils.Dice { diff --git a/Geekbot.net/Commands/Utils/Emojify.cs b/Geekbot.net/Commands/Utils/Emojify.cs index 07adadb..f0e172e 100644 --- a/Geekbot.net/Commands/Utils/Emojify.cs +++ b/Geekbot.net/Commands/Utils/Emojify.cs @@ -1,7 +1,6 @@ using System; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib; using Geekbot.net.Lib.Converters; using Geekbot.net.Lib.ErrorHandling; diff --git a/Geekbot.net/Commands/Utils/Help.cs b/Geekbot.net/Commands/Utils/Help.cs index 4372692..ace5087 100644 --- a/Geekbot.net/Commands/Utils/Help.cs +++ b/Geekbot.net/Commands/Utils/Help.cs @@ -3,7 +3,6 @@ using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; namespace Geekbot.net.Commands.Utils diff --git a/Geekbot.net/Commands/Utils/Ping.cs b/Geekbot.net/Commands/Utils/Ping.cs index 653a46f..18cf9cb 100644 --- a/Geekbot.net/Commands/Utils/Ping.cs +++ b/Geekbot.net/Commands/Utils/Ping.cs @@ -1,6 +1,5 @@ using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib; namespace Geekbot.net.Commands.Utils { diff --git a/Geekbot.net/Commands/Utils/Poll/Poll.cs b/Geekbot.net/Commands/Utils/Poll/Poll.cs index e94e6d4..ba4e49f 100644 --- a/Geekbot.net/Commands/Utils/Poll/Poll.cs +++ b/Geekbot.net/Commands/Utils/Poll/Poll.cs @@ -5,7 +5,6 @@ using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib; using Geekbot.net.Lib.Converters; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.UserRepository; @@ -167,7 +166,10 @@ namespace Geekbot.net.Commands.Utils.Poll }; results.Add(result); } - catch {} + catch + { + // ignored + } results.Sort((x, y) => y.VoteCount.CompareTo(x.VoteCount)); return results; diff --git a/Geekbot.net/Commands/Utils/Quote/Quote.cs b/Geekbot.net/Commands/Utils/Quote/Quote.cs index dab31a0..949350b 100644 --- a/Geekbot.net/Commands/Utils/Quote/Quote.cs +++ b/Geekbot.net/Commands/Utils/Quote/Quote.cs @@ -5,11 +5,9 @@ using Discord; using Discord.Commands; using Geekbot.net.Database; using Geekbot.net.Database.Models; -using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Polyfills; -using StackExchange.Redis; namespace Geekbot.net.Commands.Utils.Quote { diff --git a/Geekbot.net/Database/InMemoryDatabase.cs b/Geekbot.net/Database/InMemoryDatabase.cs index 178c0e3..2b2cfd0 100644 --- a/Geekbot.net/Database/InMemoryDatabase.cs +++ b/Geekbot.net/Database/InMemoryDatabase.cs @@ -1,5 +1,4 @@ using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Logging; namespace Geekbot.net.Database { @@ -13,6 +12,6 @@ namespace Geekbot.net.Database } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - => optionsBuilder.UseInMemoryDatabase(databaseName: _name); + => optionsBuilder.UseInMemoryDatabase(_name); } } \ No newline at end of file diff --git a/Geekbot.net/Database/Models/UserModel.cs b/Geekbot.net/Database/Models/UserModel.cs index 0083ada..f14ed61 100644 --- a/Geekbot.net/Database/Models/UserModel.cs +++ b/Geekbot.net/Database/Models/UserModel.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.ComponentModel.DataAnnotations; namespace Geekbot.net.Database.Models diff --git a/Geekbot.net/Database/RedisMigration.cs b/Geekbot.net/Database/RedisMigration.cs index c7dd881..005aa69 100644 --- a/Geekbot.net/Database/RedisMigration.cs +++ b/Geekbot.net/Database/RedisMigration.cs @@ -8,7 +8,6 @@ using Geekbot.net.Commands.Utils.Quote; using Geekbot.net.Database.Models; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Logger; -using MtgApiManager.Lib.Model; using Newtonsoft.Json; using StackExchange.Redis; diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 83a37d9..124dd6d 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -24,7 +24,11 @@ - + + + + + diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index b901c1f..f9fbc62 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -25,7 +25,9 @@ namespace Geekbot.net private readonly IUserRepository _userRepository; private readonly IReactionListener _reactionListener; - public Handlers(DatabaseContext database, IDiscordClient client, IGeekbotLogger logger, IDatabase redis, IServiceProvider servicesProvider, CommandService commands, IUserRepository userRepository, IReactionListener reactionListener) + public Handlers(DatabaseContext database, IDiscordClient client, IGeekbotLogger logger, IDatabase redis, + IServiceProvider servicesProvider, CommandService commands, IUserRepository userRepository, + IReactionListener reactionListener) { _database = database; _client = client; diff --git a/Geekbot.net/Lib/Clients/MalClient.cs b/Geekbot.net/Lib/Clients/MalClient.cs index 95d7dbd..a014cf1 100644 --- a/Geekbot.net/Lib/Clients/MalClient.cs +++ b/Geekbot.net/Lib/Clients/MalClient.cs @@ -1,45 +1,38 @@ using System.Threading.Tasks; +using Geekbot.net.Lib.GlobalSettings; using Geekbot.net.Lib.Logger; using MyAnimeListSharp.Auth; using MyAnimeListSharp.Core; using MyAnimeListSharp.Facade.Async; -using StackExchange.Redis; namespace Geekbot.net.Lib.Clients { public class MalClient : IMalClient { - private readonly IDatabase _redis; + private readonly IGlobalSettings _globalSettings; private readonly IGeekbotLogger _logger; private ICredentialContext _credentials; private AnimeSearchMethodsAsync _animeSearch; private MangaSearchMethodsAsync _mangaSearch; - public MalClient(IDatabase redis, IGeekbotLogger logger) + public MalClient(IGlobalSettings globalSettings, IGeekbotLogger logger) { - _redis = redis; + _globalSettings = globalSettings; _logger = logger; ReloadClient(); } public bool ReloadClient() { - var malCredentials = _redis.HashGetAll("malCredentials"); - if (malCredentials.Length != 0) + var malCredentials = _globalSettings.GetKey("MalCredentials"); + if (!string.IsNullOrEmpty(malCredentials)) { - _credentials = new CredentialContext(); - foreach (var c in malCredentials) + var credSplit = malCredentials.Split('|'); + _credentials = new CredentialContext() { - switch (c.Name) - { - case "Username": - _credentials.UserName = c.Value; - break; - case "Password": - _credentials.Password = c.Value; - break; - } - } + UserName = credSplit[0], + Password = credSplit[1] + }; _animeSearch = new AnimeSearchMethodsAsync(_credentials); _mangaSearch = new MangaSearchMethodsAsync(_credentials); _logger.Debug(LogSource.Geekbot, "Logged in to MAL"); diff --git a/Geekbot.net/Lib/Logger/DiscordLogger.cs b/Geekbot.net/Lib/Logger/DiscordLogger.cs index 2adcd73..688e26b 100644 --- a/Geekbot.net/Lib/Logger/DiscordLogger.cs +++ b/Geekbot.net/Lib/Logger/DiscordLogger.cs @@ -1,7 +1,6 @@ using System; using System.Threading.Tasks; using Discord; -using Geekbot.net.Commands.Randomness.Cat; namespace Geekbot.net.Lib.Logger { diff --git a/Geekbot.net/Lib/UserRepository/UserRepository.cs b/Geekbot.net/Lib/UserRepository/UserRepository.cs index 0125ee5..263a2f3 100644 --- a/Geekbot.net/Lib/UserRepository/UserRepository.cs +++ b/Geekbot.net/Lib/UserRepository/UserRepository.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Discord.WebSocket; diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index c9b53b3..f94a785 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -53,6 +53,7 @@ namespace Geekbot.net logo.AppendLine(@"| |_| | |___| |___| . \| |_) | |_| || |"); logo.AppendLine(@" \____|_____|_____|_|\_\____/ \___/ |_|"); logo.AppendLine("========================================="); + logo.AppendLine($"Version {Constants.BotVersion()}"); Console.WriteLine(logo.ToString()); var sumologicActive = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("GEEKBOT_SUMO")); var logger = new GeekbotLogger(runParameters, sumologicActive); @@ -112,7 +113,7 @@ namespace Geekbot.net _userRepository = new UserRepository(_database, logger); var fortunes = new FortunesProvider(logger); var mediaProvider = new MediaProvider(logger); - var malClient = new MalClient(_redis, logger); + var malClient = new MalClient(_globalSettings, logger); var levelCalc = new LevelCalc(); var emojiConverter = new EmojiConverter(); var mtgManaConverter = new MtgManaConverter(); @@ -174,13 +175,12 @@ namespace Geekbot.net _client.UserLeft += handlers.UserLeft; _client.ReactionAdded += handlers.ReactionAdded; _client.ReactionRemoved += handlers.ReactionRemoved; - - if (!_runParameters.DisableApi) - { - StartWebApi(); - } + + var webserver = _runParameters.DisableApi ? Task.Delay(10) : StartWebApi(); _logger.Information(LogSource.Geekbot, "Done and ready for use"); + + await webserver; } } catch (Exception e) @@ -197,12 +197,11 @@ namespace Geekbot.net return true; } - private void StartWebApi() + private Task StartWebApi() { _logger.Information(LogSource.Api, "Starting Webserver"); - var webApiUrl = new Uri($"http://{_runParameters.ApiHost}:{_runParameters.ApiPort}"); - WebApi.WebApiStartup.StartWebApi(_logger, _runParameters, _commands); - _logger.Information(LogSource.Api, $"Webserver now running on {webApiUrl}"); + WebApi.WebApiStartup.StartWebApi(_logger, _runParameters, _commands, _database); + return Task.CompletedTask; } } } \ No newline at end of file diff --git a/Geekbot.net/WebApi/Controllers/Commands/HelpController.cs b/Geekbot.net/WebApi/Controllers/Commands/CommandController.cs similarity index 83% rename from Geekbot.net/WebApi/Controllers/Commands/HelpController.cs rename to Geekbot.net/WebApi/Controllers/Commands/CommandController.cs index 9105706..04caaae 100644 --- a/Geekbot.net/WebApi/Controllers/Commands/HelpController.cs +++ b/Geekbot.net/WebApi/Controllers/Commands/CommandController.cs @@ -6,11 +6,11 @@ using Microsoft.AspNetCore.Mvc; namespace Geekbot.net.WebApi.Controllers.Commands { [EnableCors("AllowSpecificOrigin")] - public class HelpController : Controller + public class CommandController : Controller { private readonly CommandService _commands; - public HelpController(CommandService commands) + public CommandController(CommandService commands) { _commands = commands; } @@ -22,7 +22,7 @@ namespace Geekbot.net.WebApi.Controllers.Commands let cmdParamsObj = cmd.Parameters.Select(cmdParam => new CommandParamDto { Summary = cmdParam.Summary, - Default = cmdParam.DefaultValue?.ToString() ?? null, + Default = cmdParam.DefaultValue?.ToString(), Type = cmdParam.Type?.ToString() }) .ToList() @@ -31,7 +31,7 @@ namespace Geekbot.net.WebApi.Controllers.Commands { Name = cmd.Name, Summary = cmd.Summary, - IsAdminCommand = (param.Contains("admin")), + IsAdminCommand = param.Contains("admin") || param.Contains("owner"), Aliases = cmd.Aliases.ToArray(), Params = cmdParamsObj }).ToList(); diff --git a/Geekbot.net/WebApi/Controllers/Status/StatusController.cs b/Geekbot.net/WebApi/Controllers/Status/StatusController.cs index e9af6bb..c437e64 100644 --- a/Geekbot.net/WebApi/Controllers/Status/StatusController.cs +++ b/Geekbot.net/WebApi/Controllers/Status/StatusController.cs @@ -1,4 +1,5 @@ -using Geekbot.net.Lib; +using System.Globalization; +using Geekbot.net.Lib; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; @@ -13,7 +14,7 @@ namespace Geekbot.net.WebApi.Controllers.Status var responseBody = new ApiStatusDto { GeekbotVersion = Constants.BotVersion(), - ApiVersion = Constants.ApiVersion.ToString(), + ApiVersion = Constants.ApiVersion.ToString(CultureInfo.InvariantCulture), Status = "Online" }; return Ok(responseBody); diff --git a/Geekbot.net/WebApi/Logging/AspLogProvider.cs b/Geekbot.net/WebApi/Logging/AspLogProvider.cs index 9a1599a..d35872d 100644 --- a/Geekbot.net/WebApi/Logging/AspLogProvider.cs +++ b/Geekbot.net/WebApi/Logging/AspLogProvider.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Concurrent; +using System.Collections.Concurrent; using Geekbot.net.Lib.Logger; using Microsoft.Extensions.Logging; diff --git a/Geekbot.net/WebApi/Logging/AspLogger.cs b/Geekbot.net/WebApi/Logging/AspLogger.cs index 37c9de1..85dd619 100644 --- a/Geekbot.net/WebApi/Logging/AspLogger.cs +++ b/Geekbot.net/WebApi/Logging/AspLogger.cs @@ -36,6 +36,8 @@ namespace Geekbot.net.WebApi.Logging case LogLevel.Critical: _geekbotLogger.Error(LogSource.Api, $"{eventId.Id} - {_categoryName} - {state}", exception); break; + case LogLevel.None: + break; default: throw new ArgumentOutOfRangeException(nameof(logLevel)); } @@ -67,6 +69,9 @@ namespace Geekbot.net.WebApi.Logging return NLog.LogLevel.Error; case LogLevel.Critical: return NLog.LogLevel.Fatal; + case LogLevel.None: + return NLog.LogLevel.Off; + break; default: throw new ArgumentOutOfRangeException(nameof(level)); } diff --git a/Geekbot.net/WebApi/WebApiStartup.cs b/Geekbot.net/WebApi/WebApiStartup.cs index 675ba1b..e91ff9f 100644 --- a/Geekbot.net/WebApi/WebApiStartup.cs +++ b/Geekbot.net/WebApi/WebApiStartup.cs @@ -1,7 +1,7 @@ -using System; -using System.Net; +using System.Net; using System.Reflection; using Discord.Commands; +using Geekbot.net.Database; using Geekbot.net.Lib; using Geekbot.net.Lib.Logger; using Geekbot.net.WebApi.Logging; @@ -13,9 +13,10 @@ using Microsoft.Extensions.Logging; namespace Geekbot.net.WebApi { - public class WebApiStartup + public static class WebApiStartup { - public static void StartWebApi(IGeekbotLogger logger, RunParameters runParameters, CommandService commandService) + public static void StartWebApi(IGeekbotLogger logger, RunParameters runParameters, CommandService commandService, + DatabaseContext databaseContext) { WebHost.CreateDefaultBuilder() .UseKestrel(options => @@ -26,6 +27,7 @@ namespace Geekbot.net.WebApi { services.AddMvc(); services.AddSingleton(commandService); + services.AddSingleton(databaseContext); services.AddCors(options => { options.AddPolicy("AllowSpecificOrigin", diff --git a/Tests/Lib/EmojiConverter.test.cs b/Tests/Lib/EmojiConverter.test.cs index aaaaa8f..170d521 100644 --- a/Tests/Lib/EmojiConverter.test.cs +++ b/Tests/Lib/EmojiConverter.test.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using Geekbot.net.Lib; using Geekbot.net.Lib.Converters; using Xunit; diff --git a/Tests/Lib/LevelCalc.test.cs b/Tests/Lib/LevelCalc.test.cs index 4b6b095..5ac5fd3 100644 --- a/Tests/Lib/LevelCalc.test.cs +++ b/Tests/Lib/LevelCalc.test.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using Geekbot.net.Lib; using Geekbot.net.Lib.Levels; using Xunit; From 4e4ef3584ee8d7db33ce3816d6bc41da2d52b3b4 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 17 May 2018 22:06:58 +0200 Subject: [PATCH 185/553] Upgrade to discord.net 2.0 --- Geekbot.net/Commands/Games/Pokedex.cs | 1 + .../Commands/Integrations/MagicTheGathering.cs | 5 +++-- Geekbot.net/Commands/Integrations/Mal.cs | 1 + .../Integrations/UbranDictionary/UrbanDictionary.cs | 1 + Geekbot.net/Commands/Randomness/RandomAnimals.cs | 6 ++---- Geekbot.net/Commands/Utils/Info.cs | 1 + Geekbot.net/Commands/Utils/Poll/Poll.cs | 1 + Geekbot.net/Commands/Utils/Quote/Quote.cs | 11 +++++------ Geekbot.net/Geekbot.net.csproj | 12 ++++++------ Geekbot.net/Lib/Extensions/EmbedBuilderExtensions.cs | 12 ++++++++++++ Geekbot.net/Lib/Polyfills/UserPolyfillDto.cs | 2 +- Tests/Tests.csproj | 2 +- 12 files changed, 35 insertions(+), 20 deletions(-) create mode 100644 Geekbot.net/Lib/Extensions/EmbedBuilderExtensions.cs diff --git a/Geekbot.net/Commands/Games/Pokedex.cs b/Geekbot.net/Commands/Games/Pokedex.cs index 25f4c88..aea442b 100644 --- a/Geekbot.net/Commands/Games/Pokedex.cs +++ b/Geekbot.net/Commands/Games/Pokedex.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Extensions; using PokeAPI; namespace Geekbot.net.Commands.Games diff --git a/Geekbot.net/Commands/Integrations/MagicTheGathering.cs b/Geekbot.net/Commands/Integrations/MagicTheGathering.cs index 968c558..2284646 100644 --- a/Geekbot.net/Commands/Integrations/MagicTheGathering.cs +++ b/Geekbot.net/Commands/Integrations/MagicTheGathering.cs @@ -6,16 +6,17 @@ using Discord; using Discord.Commands; using Geekbot.net.Lib.Converters; using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Extensions; using MtgApiManager.Lib.Service; namespace Geekbot.net.Commands.Integrations { - public class Magicthegathering : ModuleBase + public class MagicTheGathering : ModuleBase { private readonly IErrorHandler _errorHandler; private readonly IMtgManaConverter _manaConverter; - public Magicthegathering(IErrorHandler errorHandler, IMtgManaConverter manaConverter) + public MagicTheGathering(IErrorHandler errorHandler, IMtgManaConverter manaConverter) { _errorHandler = errorHandler; _manaConverter = manaConverter; diff --git a/Geekbot.net/Commands/Integrations/Mal.cs b/Geekbot.net/Commands/Integrations/Mal.cs index b617b44..da03ead 100644 --- a/Geekbot.net/Commands/Integrations/Mal.cs +++ b/Geekbot.net/Commands/Integrations/Mal.cs @@ -5,6 +5,7 @@ using Discord; using Discord.Commands; using Geekbot.net.Lib.Clients; using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Extensions; namespace Geekbot.net.Commands.Integrations { diff --git a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs b/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs index 36d70b1..928dfe2 100644 --- a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs +++ b/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Extensions; using Newtonsoft.Json; namespace Geekbot.net.Commands.Integrations.UbranDictionary diff --git a/Geekbot.net/Commands/Randomness/RandomAnimals.cs b/Geekbot.net/Commands/Randomness/RandomAnimals.cs index 90138af..38061b1 100644 --- a/Geekbot.net/Commands/Randomness/RandomAnimals.cs +++ b/Geekbot.net/Commands/Randomness/RandomAnimals.cs @@ -65,11 +65,9 @@ namespace Geekbot.net.Commands.Randomness await ReplyAsync("", false, Eb(_mediaProvider.GetFox())); } - private EmbedBuilder Eb(string image) + private static Embed Eb(string image) { - var eb = new EmbedBuilder(); - eb.ImageUrl = image; - return eb; + return new EmbedBuilder {ImageUrl = image}.Build(); } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Utils/Info.cs b/Geekbot.net/Commands/Utils/Info.cs index e7b104f..f0900fa 100644 --- a/Geekbot.net/Commands/Utils/Info.cs +++ b/Geekbot.net/Commands/Utils/Info.cs @@ -7,6 +7,7 @@ using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Extensions; namespace Geekbot.net.Commands.Utils { diff --git a/Geekbot.net/Commands/Utils/Poll/Poll.cs b/Geekbot.net/Commands/Utils/Poll/Poll.cs index ba4e49f..aad6eee 100644 --- a/Geekbot.net/Commands/Utils/Poll/Poll.cs +++ b/Geekbot.net/Commands/Utils/Poll/Poll.cs @@ -7,6 +7,7 @@ using Discord; using Discord.Commands; using Geekbot.net.Lib.Converters; using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.UserRepository; using Newtonsoft.Json; using StackExchange.Redis; diff --git a/Geekbot.net/Commands/Utils/Quote/Quote.cs b/Geekbot.net/Commands/Utils/Quote/Quote.cs index 949350b..6af74d7 100644 --- a/Geekbot.net/Commands/Utils/Quote/Quote.cs +++ b/Geekbot.net/Commands/Utils/Quote/Quote.cs @@ -187,12 +187,11 @@ namespace Geekbot.net.Commands.Utils.Quote try { var list = Context.Channel.GetMessagesAsync().Flatten(); - await list; - return list.Result - .First(msg => msg.Author.Id == user.Id - && msg.Embeds.Count == 0 - && msg.Id != Context.Message.Id - && !msg.Content.ToLower().StartsWith("!")); + return await list.FirstOrDefault(msg => + msg.Author.Id == user.Id && + msg.Embeds.Count == 0 && + msg.Id != Context.Message.Id && + !msg.Content.ToLower().StartsWith("!")); } catch { diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 124dd6d..9b0fac6 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -20,10 +20,10 @@ - 1.0.2 + 2.0.0-beta - - + + @@ -40,12 +40,12 @@ - - + + - + diff --git a/Geekbot.net/Lib/Extensions/EmbedBuilderExtensions.cs b/Geekbot.net/Lib/Extensions/EmbedBuilderExtensions.cs new file mode 100644 index 0000000..246be44 --- /dev/null +++ b/Geekbot.net/Lib/Extensions/EmbedBuilderExtensions.cs @@ -0,0 +1,12 @@ +using Discord; + +namespace Geekbot.net.Lib.Extensions +{ + public static class EmbedBuilderExtensions + { + public static EmbedBuilder AddInlineField(this EmbedBuilder builder, string name, object value) + { + return builder.AddField(new EmbedFieldBuilder().WithIsInline(true).WithName(name).WithValue(value)); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Polyfills/UserPolyfillDto.cs b/Geekbot.net/Lib/Polyfills/UserPolyfillDto.cs index 407ae36..568bdd7 100644 --- a/Geekbot.net/Lib/Polyfills/UserPolyfillDto.cs +++ b/Geekbot.net/Lib/Polyfills/UserPolyfillDto.cs @@ -9,7 +9,7 @@ namespace Geekbot.net.Lib.Polyfills public ulong Id { get; set; } public DateTimeOffset CreatedAt { get; set; } public string Mention { get; set; } - public Game? Game { get; set; } + public IActivity Activity { get; } public UserStatus Status { get; set; } public string AvatarId { get; set; } public string Discriminator { get; set; } diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 776acf6..4713b2b 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -5,7 +5,7 @@ NU1701 - + From 6d708627f1f16f809b7faf98885ad001634245b8 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Thu, 17 May 2018 23:55:44 +0200 Subject: [PATCH 186/553] Add Dockerfile --- Dockerfile | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..7594bec --- /dev/null +++ b/Dockerfile @@ -0,0 +1,7 @@ +FROM microsoft/dotnet:2.1-aspnetcore-runtime + +COPY Geekbot.net/Binaries /app/ + +EXPOSE 12995/tcp +WORKDIR /app +ENTRYPOINT ./run.sh From 74793c8ef76d3f15bbf77b51ce0cc08d49b796ce Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 18 May 2018 00:34:45 +0200 Subject: [PATCH 187/553] Dynamically get discord.net version in !info --- Geekbot.net/Commands/Utils/Info.cs | 10 +++++----- Geekbot.net/Lib/Constants.cs | 5 +++++ Geekbot.net/WebApi/Logging/AspLogger.cs | 1 - 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Geekbot.net/Commands/Utils/Info.cs b/Geekbot.net/Commands/Utils/Info.cs index f0900fa..aca4dcd 100644 --- a/Geekbot.net/Commands/Utils/Info.cs +++ b/Geekbot.net/Commands/Utils/Info.cs @@ -32,19 +32,19 @@ namespace Geekbot.net.Commands.Utils { var eb = new EmbedBuilder(); + var appInfo = await _client.GetApplicationInfoAsync(); + eb.WithAuthor(new EmbedAuthorBuilder() - .WithIconUrl(_client.CurrentUser.GetAvatarUrl()) + .WithIconUrl(appInfo.IconUrl) .WithName($"{Constants.Name} V{Constants.BotVersion()}")); - var botOwner = (await _client.GetApplicationInfoAsync()).Owner; var uptime = DateTime.Now.Subtract(Process.GetCurrentProcess().StartTime); eb.AddInlineField("Bot Name", _client.CurrentUser.Username); - eb.AddInlineField("Bot Owner", $"{botOwner.Username}#{botOwner.Discriminator}"); - eb.AddInlineField("Library", "Discord.NET V1.0.2"); + eb.AddInlineField("Bot Owner", $"{appInfo.Owner.Username}#{appInfo.Owner.Discriminator}"); + eb.AddInlineField("Library", $"Discord.NET {Constants.LibraryVersion()}"); eb.AddInlineField("Uptime", $"{uptime.Days}D {uptime.Hours}H {uptime.Minutes}M {uptime.Seconds}S"); eb.AddInlineField("Servers", Context.Client.GetGuildsAsync().Result.Count); eb.AddInlineField("Total Commands", _commands.Commands.Count()); - eb.AddField("Website", "https://geekbot.pizzaandcoffee.rocks/"); await ReplyAsync("", false, eb.Build()); diff --git a/Geekbot.net/Lib/Constants.cs b/Geekbot.net/Lib/Constants.cs index f80f182..4abee4e 100644 --- a/Geekbot.net/Lib/Constants.cs +++ b/Geekbot.net/Lib/Constants.cs @@ -11,6 +11,11 @@ namespace Geekbot.net.Lib return typeof(Program).Assembly.GetCustomAttribute().InformationalVersion; } + public static string LibraryVersion() + { + return typeof(Discord.WebSocket.DiscordSocketClient).Assembly.GetCustomAttribute().InformationalVersion; + } + public const double ApiVersion = 1; } } \ No newline at end of file diff --git a/Geekbot.net/WebApi/Logging/AspLogger.cs b/Geekbot.net/WebApi/Logging/AspLogger.cs index 85dd619..3316150 100644 --- a/Geekbot.net/WebApi/Logging/AspLogger.cs +++ b/Geekbot.net/WebApi/Logging/AspLogger.cs @@ -71,7 +71,6 @@ namespace Geekbot.net.WebApi.Logging return NLog.LogLevel.Fatal; case LogLevel.None: return NLog.LogLevel.Off; - break; default: throw new ArgumentOutOfRangeException(nameof(level)); } From 9354e5f83e62cdf18c7f6578f608ecba84551f60 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 19 May 2018 10:49:01 +0200 Subject: [PATCH 188/553] Change User Model and Add poll model, port !poll but ended up disabling it --- Geekbot.net/Commands/Admin/Mod.cs | 2 +- Geekbot.net/Commands/Utils/{Poll => }/Poll.cs | 103 +++++++++++------- .../Commands/Utils/Poll/PollDataDto.cs | 13 --- .../Commands/Utils/Poll/PollResultDto.cs | 8 -- Geekbot.net/Database/DatabaseContext.cs | 3 +- Geekbot.net/Database/DatabaseInitializer.cs | 2 +- Geekbot.net/Database/Models/PollModel.cs | 27 +++++ .../Database/Models/PollQuestionModel.cs | 16 +++ Geekbot.net/Database/Models/UserModel.cs | 3 +- .../Database/Models/UserSettingsModel.cs | 15 --- .../Database/Models/UserUsedNamesModel.cs | 15 +++ Geekbot.net/Database/RedisMigration.cs | 16 +-- .../Lib/UserRepository/UserRepository.cs | 7 +- 13 files changed, 138 insertions(+), 92 deletions(-) rename Geekbot.net/Commands/Utils/{Poll => }/Poll.cs (63%) delete mode 100644 Geekbot.net/Commands/Utils/Poll/PollDataDto.cs delete mode 100644 Geekbot.net/Commands/Utils/Poll/PollResultDto.cs create mode 100644 Geekbot.net/Database/Models/PollModel.cs create mode 100644 Geekbot.net/Database/Models/PollQuestionModel.cs delete mode 100644 Geekbot.net/Database/Models/UserSettingsModel.cs create mode 100644 Geekbot.net/Database/Models/UserUsedNamesModel.cs diff --git a/Geekbot.net/Commands/Admin/Mod.cs b/Geekbot.net/Commands/Admin/Mod.cs index 2e4ad24..a200cac 100644 --- a/Geekbot.net/Commands/Admin/Mod.cs +++ b/Geekbot.net/Commands/Admin/Mod.cs @@ -35,7 +35,7 @@ namespace Geekbot.net.Commands.Admin var userRepo = _userRepository.Get(user.Id); var sb = new StringBuilder(); sb.AppendLine($":bust_in_silhouette: {user.Username} has been known as:"); - foreach (var name in userRepo.UsedNames) sb.AppendLine($"- `{name}`"); + foreach (var name in userRepo.UsedNames) sb.AppendLine($"- `{name.Name}`"); await ReplyAsync(sb.ToString()); } catch (Exception e) diff --git a/Geekbot.net/Commands/Utils/Poll/Poll.cs b/Geekbot.net/Commands/Utils/Poll.cs similarity index 63% rename from Geekbot.net/Commands/Utils/Poll/Poll.cs rename to Geekbot.net/Commands/Utils/Poll.cs index aad6eee..585c1fb 100644 --- a/Geekbot.net/Commands/Utils/Poll/Poll.cs +++ b/Geekbot.net/Commands/Utils/Poll.cs @@ -5,28 +5,27 @@ using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.net.Database; +using Geekbot.net.Database.Models; using Geekbot.net.Lib.Converters; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.UserRepository; -using Newtonsoft.Json; -using StackExchange.Redis; -namespace Geekbot.net.Commands.Utils.Poll +namespace Geekbot.net.Commands.Utils { [Group("poll")] public class Poll : ModuleBase { private readonly IEmojiConverter _emojiConverter; private readonly IErrorHandler _errorHandler; - private readonly IDatabase _redis; + private readonly DatabaseContext _database; private readonly IUserRepository _userRepository; - public Poll(IErrorHandler errorHandler, IDatabase redis, IEmojiConverter emojiConverter, - IUserRepository userRepository) + public Poll(IErrorHandler errorHandler, DatabaseContext database, IEmojiConverter emojiConverter, IUserRepository userRepository) { _errorHandler = errorHandler; - _redis = redis; + _database = database; _emojiConverter = emojiConverter; _userRepository = userRepository; } @@ -38,7 +37,7 @@ namespace Geekbot.net.Commands.Utils.Poll try { var currentPoll = GetCurrentPoll(); - if (currentPoll.Question == null || currentPoll.IsFinshed) + if (currentPoll.Question == null) { await ReplyAsync( "There is no poll in this channel ongoing at the moment\r\nYou can create one with `!poll create question;option1;option2;option3`"); @@ -60,6 +59,9 @@ namespace Geekbot.net.Commands.Utils.Poll { try { + await ReplyAsync("Poll creation currently disabled"); + return; + var currentPoll = GetCurrentPoll(); if (currentPoll.Question != null && !currentPoll.IsFinshed) { @@ -75,34 +77,46 @@ namespace Geekbot.net.Commands.Utils.Poll return; } - var eb = new EmbedBuilder(); - eb.Title = $"Poll by {Context.User.Username}"; var question = pollList[0]; - eb.Description = question; pollList.RemoveAt(0); + + var eb = new EmbedBuilder + { + Title = $"Poll by {Context.User.Username}", + Description = question + }; + + var options = new List(); var i = 1; pollList.ForEach(option => { + options.Add(new PollQuestionModel() + { + OptionId = i, + OptionText = option + }); eb.AddInlineField($"Option {_emojiConverter.NumberToEmoji(i)}", option); i++; }); var pollMessage = await ReplyAsync("", false, eb.Build()); + + var poll = new PollModel() + { + Creator = Context.User.Id.AsLong(), + MessageId = pollMessage.Id.AsLong(), + IsFinshed = false, + Question = question, + Options = options + }; + _database.Polls.Add(poll); + i = 1; pollList.ForEach(option => { pollMessage.AddReactionAsync(new Emoji(_emojiConverter.NumberToEmoji(i))); + Task.Delay(500); i++; }); - var poll = new PollDataDto - { - Creator = Context.User.Id, - MessageId = pollMessage.Id, - IsFinshed = false, - Question = question, - Options = pollList - }; - var pollJson = JsonConvert.SerializeObject(poll); - _redis.HashSet($"{Context.Guild.Id}:Polls", new[] {new HashEntry(Context.Channel.Id, pollJson)}); } catch (Exception e) { @@ -123,15 +137,14 @@ namespace Geekbot.net.Commands.Utils.Poll return; } - var results = await GetPollResults(currentPoll); + currentPoll = await GetPollResults(currentPoll); var sb = new StringBuilder(); sb.AppendLine("**Poll Results**"); sb.AppendLine(currentPoll.Question); - foreach (var result in results) sb.AppendLine($"{result.VoteCount} - {result.Option}"); + foreach (var result in currentPoll.Options) sb.AppendLine($"{result.Votes} - {result.OptionText}"); await ReplyAsync(sb.ToString()); currentPoll.IsFinshed = true; - var pollJson = JsonConvert.SerializeObject(currentPoll); - _redis.HashSet($"{Context.Guild.Id}:Polls", new[] {new HashEntry(Context.Channel.Id, pollJson)}); + _database.Polls.Update(currentPoll); } catch (Exception e) { @@ -139,41 +152,49 @@ namespace Geekbot.net.Commands.Utils.Poll } } - private PollDataDto GetCurrentPoll() + private PollModel GetCurrentPoll() { try { - var currentPoll = _redis.HashGet($"{Context.Guild.Id}:Polls", Context.Channel.Id); - return JsonConvert.DeserializeObject(currentPoll.ToString()); + var currentPoll = _database.Polls.FirstOrDefault(poll => + poll.ChannelId.Equals(Context.Channel.Id.AsLong()) && + poll.GuildId.Equals(Context.Guild.Id.AsLong()) + ); + return currentPoll ?? new PollModel(); + } catch { - return new PollDataDto(); + return new PollModel(); } } - private async Task> GetPollResults(PollDataDto poll) + private async Task GetPollResults(PollModel poll) { - var message = (IUserMessage) await Context.Channel.GetMessageAsync(poll.MessageId); - var results = new List(); + var message = (IUserMessage) await Context.Channel.GetMessageAsync(poll.MessageId.AsUlong()); + + var results = new Dictionary(); foreach (var r in message.Reactions) + { try { - var option = int.Parse(r.Key.Name.ToCharArray()[0].ToString()); - var result = new PollResultDto - { - Option = poll.Options[option - 1], - VoteCount = r.Value.ReactionCount - }; - results.Add(result); + results.Add(r.Key.Name.ToCharArray()[0], r.Value.ReactionCount); } catch { // ignored } + } + + foreach (var q in poll.Options) + { + q.Votes = results.FirstOrDefault(e => e.Key.Equals(q.OptionId)).Value; + } - results.Sort((x, y) => y.VoteCount.CompareTo(x.VoteCount)); - return results; + return poll; + +// var sortedValues = results.OrderBy(e => e.Value); +// return sortedValues; } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Utils/Poll/PollDataDto.cs b/Geekbot.net/Commands/Utils/Poll/PollDataDto.cs deleted file mode 100644 index 3d21479..0000000 --- a/Geekbot.net/Commands/Utils/Poll/PollDataDto.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Collections.Generic; - -namespace Geekbot.net.Commands.Utils.Poll -{ - internal class PollDataDto - { - public ulong Creator { get; set; } - public ulong MessageId { get; set; } - public bool IsFinshed { get; set; } - public string Question { get; set; } - public List Options { get; set; } - } -} \ No newline at end of file diff --git a/Geekbot.net/Commands/Utils/Poll/PollResultDto.cs b/Geekbot.net/Commands/Utils/Poll/PollResultDto.cs deleted file mode 100644 index b4f14a2..0000000 --- a/Geekbot.net/Commands/Utils/Poll/PollResultDto.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Geekbot.net.Commands.Utils.Poll -{ - internal class PollResultDto - { - public string Option { get; set; } - public int VoteCount { get; set; } - } -} \ No newline at end of file diff --git a/Geekbot.net/Database/DatabaseContext.cs b/Geekbot.net/Database/DatabaseContext.cs index e9de32c..ab786b1 100644 --- a/Geekbot.net/Database/DatabaseContext.cs +++ b/Geekbot.net/Database/DatabaseContext.cs @@ -16,7 +16,6 @@ namespace Geekbot.net.Database public DbSet Slaps { get; set; } public DbSet Globals { get; set; } public DbSet RoleSelfService { get; set; } - - // public DbSet UserSettings { get; set; } + public DbSet Polls { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Database/DatabaseInitializer.cs b/Geekbot.net/Database/DatabaseInitializer.cs index 83660bb..7ae6cc7 100644 --- a/Geekbot.net/Database/DatabaseInitializer.cs +++ b/Geekbot.net/Database/DatabaseInitializer.cs @@ -40,7 +40,7 @@ namespace Geekbot.net.Database }); } database.Database.EnsureCreated(); - database.Database.Migrate(); + if(!_runParameters.InMemory) database.Database.Migrate(); } catch (Exception e) { diff --git a/Geekbot.net/Database/Models/PollModel.cs b/Geekbot.net/Database/Models/PollModel.cs new file mode 100644 index 0000000..3b12410 --- /dev/null +++ b/Geekbot.net/Database/Models/PollModel.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace Geekbot.net.Database.Models +{ + public class PollModel + { + [Key] + public int Id { get; set; } + + [Required] + public long GuildId { get; set; } + + [Required] + public long ChannelId { get; set; } + + public string Question { get; set; } + + public long Creator { get; set; } + + public long MessageId { get; set; } + + public List Options { get; set; } + + public bool IsFinshed { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Database/Models/PollQuestionModel.cs b/Geekbot.net/Database/Models/PollQuestionModel.cs new file mode 100644 index 0000000..e251fe2 --- /dev/null +++ b/Geekbot.net/Database/Models/PollQuestionModel.cs @@ -0,0 +1,16 @@ +using System.ComponentModel.DataAnnotations; + +namespace Geekbot.net.Database.Models +{ + public class PollQuestionModel + { + [Key] + public int Id { get; set; } + + public int OptionId { get; set; } + + public string OptionText { get; set; } + + public int Votes { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Database/Models/UserModel.cs b/Geekbot.net/Database/Models/UserModel.cs index f14ed61..b9c60ca 100644 --- a/Geekbot.net/Database/Models/UserModel.cs +++ b/Geekbot.net/Database/Models/UserModel.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; namespace Geekbot.net.Database.Models @@ -24,6 +25,6 @@ namespace Geekbot.net.Database.Models public DateTimeOffset Joined { get; set; } - public string[] UsedNames { get; set; } + public List UsedNames { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Database/Models/UserSettingsModel.cs b/Geekbot.net/Database/Models/UserSettingsModel.cs deleted file mode 100644 index 659ef1d..0000000 --- a/Geekbot.net/Database/Models/UserSettingsModel.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace Geekbot.net.Database.Models -{ - public class UserSettingsModel - { - [Key] - public int Id { get; set; } - - [Required] - public long UserId { get; set; } - - // stuff to be added in the future - } -} \ No newline at end of file diff --git a/Geekbot.net/Database/Models/UserUsedNamesModel.cs b/Geekbot.net/Database/Models/UserUsedNamesModel.cs new file mode 100644 index 0000000..48ba873 --- /dev/null +++ b/Geekbot.net/Database/Models/UserUsedNamesModel.cs @@ -0,0 +1,15 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace Geekbot.net.Database.Models +{ + public class UserUsedNamesModel + { + [Key] + public int Id { get; set; } + + public string Name { get; set; } + + public DateTimeOffset FirstSeen { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Database/RedisMigration.cs b/Geekbot.net/Database/RedisMigration.cs index 005aa69..df2e90b 100644 --- a/Geekbot.net/Database/RedisMigration.cs +++ b/Geekbot.net/Database/RedisMigration.cs @@ -250,7 +250,7 @@ namespace Geekbot.net.Database case "ShowLeave": settings.ShowLeave = setting.Value.ToString() == "1"; break; - case "WikiDel": + case "ShowDelete": settings.ShowDelete = setting.Value.ToString() == "1"; break; case "WikiLang": @@ -272,9 +272,9 @@ namespace Geekbot.net.Database throw new NotImplementedException(); } } - catch + catch (Exception e) { - _logger.Warning(LogSource.Geekbot, $"Setting failed: {setting.Name} - {guild.Id}"); + _logger.Warning(LogSource.Geekbot, $"Setting failed: {setting.Name} - {guild.Id}", e); } } } @@ -297,7 +297,9 @@ namespace Geekbot.net.Database try { var namesSerialized = _redis.HashGet($"User:{user.Id}", "UsedNames").ToString(); - var names = Utf8Json.JsonSerializer.Deserialize(namesSerialized); + var names = namesSerialized != null + ? Utf8Json.JsonSerializer.Deserialize(namesSerialized) + : new string[] {user.Username}; _database.Users.AddIfNotExists(new UserModel() { UserId = user.Id.AsLong(), @@ -306,13 +308,13 @@ namespace Geekbot.net.Database AvatarUrl = user.GetAvatarUrl(ImageFormat.Auto, 1024), IsBot = user.IsBot, Joined = user.CreatedAt, - UsedNames = names + UsedNames = names.Select(name => new UserUsedNamesModel() {Name = name, FirstSeen = DateTimeOffset.Now}).ToList() }, model => model.UserId.Equals(user.Id.AsLong())); await _database.SaveChangesAsync(); } - catch + catch (Exception e) { - _logger.Warning(LogSource.Geekbot, $"User failed: {user.Username}"); + _logger.Warning(LogSource.Geekbot, $"User failed: {user.Username}", e); } } } diff --git a/Geekbot.net/Lib/UserRepository/UserRepository.cs b/Geekbot.net/Lib/UserRepository/UserRepository.cs index 263a2f3..b27a0a2 100644 --- a/Geekbot.net/Lib/UserRepository/UserRepository.cs +++ b/Geekbot.net/Lib/UserRepository/UserRepository.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Discord.WebSocket; @@ -36,10 +37,10 @@ namespace Geekbot.net.Lib.UserRepository savedUser.AvatarUrl = user.GetAvatarUrl() ?? ""; savedUser.IsBot = user.IsBot; savedUser.Joined = user.CreatedAt; - if (savedUser.UsedNames == null) savedUser.UsedNames = Enumerable.Empty().ToArray(); - if (!savedUser.UsedNames.Contains(user.Username)) + if (savedUser.UsedNames == null) savedUser.UsedNames = new List(); + if (!savedUser.UsedNames.Any(e => e.Name.Equals(user.Username))) { - savedUser.UsedNames = savedUser.UsedNames.Concat(new[] {user.Username}).ToArray(); + savedUser.UsedNames.Add(new UserUsedNamesModel { Name = user.Username, FirstSeen = DateTimeOffset.Now }); } if (isNew) From f53258e348988873dfcd30cc2f87990fbd58fe0b Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 23 May 2018 23:50:11 +0200 Subject: [PATCH 189/553] Log errors with stacktrace in migration, skip 10k+ guilds, prevent migration from running twice by accident --- Geekbot.net/Commands/Admin/Owner.cs | 19 ++++- Geekbot.net/Database/RedisMigration.cs | 99 +++++++++++++++----------- Geekbot.net/Handlers.cs | 4 ++ 3 files changed, 78 insertions(+), 44 deletions(-) diff --git a/Geekbot.net/Commands/Admin/Owner.cs b/Geekbot.net/Commands/Admin/Owner.cs index c02c7fb..e4aa2a8 100644 --- a/Geekbot.net/Commands/Admin/Owner.cs +++ b/Geekbot.net/Commands/Admin/Owner.cs @@ -35,14 +35,27 @@ namespace Geekbot.net.Commands.Admin } [Command("migrate", RunMode = RunMode.Async)] - public async Task Migrate() + public async Task Migrate(string force = "") { - await ReplyAsync("starting migration"); - try { + var status = _globalSettings.GetKey("MigrationStatus"); + if (status.Equals("Running")) + { + await ReplyAsync("Migration already running"); + return; + } + if (status.Equals("Done") && !force.Equals("force")) + { + await ReplyAsync("Migration already ran, write `!owner migrate force` to run again"); + return; + } + + await ReplyAsync("starting migration"); + _globalSettings.SetKey("MigrationStatus", "Running"); var redisMigration = new RedisMigration(_database, _redis, _logger, _client); await redisMigration.Migrate(); + _globalSettings.SetKey("MigrationStatus", "Done"); } catch (Exception e) { diff --git a/Geekbot.net/Database/RedisMigration.cs b/Geekbot.net/Database/RedisMigration.cs index df2e90b..2f005e3 100644 --- a/Geekbot.net/Database/RedisMigration.cs +++ b/Geekbot.net/Database/RedisMigration.cs @@ -33,6 +33,12 @@ namespace Geekbot.net.Database _logger.Information(LogSource.Geekbot, "Starting migration process"); foreach (var guild in _client.Guilds) { + if (guild.MemberCount > 10000) + { + _logger.Information(LogSource.Geekbot, $"Skipping {guild.Name} because server size is to big ({guild.MemberCount})"); + break; + } + _logger.Information(LogSource.Geekbot, $"Start Migration for {guild.Name}"); #region Quotes /** @@ -50,15 +56,15 @@ namespace Geekbot.net.Database _database.Quotes.Add(quote); await _database.SaveChangesAsync(); } - catch + catch (Exception e) { - _logger.Warning(LogSource.Geekbot, $"quote failed: {q}"); + _logger.Error(LogSource.Geekbot, $"quote failed: {q}", e); } } } - catch + catch (Exception e) { - _logger.Warning(LogSource.Geekbot, "quote migration failed"); + _logger.Error(LogSource.Geekbot, "quote migration failed", e); } #endregion @@ -83,15 +89,15 @@ namespace Geekbot.net.Database _database.Karma.Add(user); await _database.SaveChangesAsync(); } - catch + catch (Exception e) { - _logger.Warning(LogSource.Geekbot, $"karma failed for: {q.Name}"); + _logger.Error(LogSource.Geekbot, $"karma failed for: {q.Name}", e); } } } - catch + catch (Exception e) { - _logger.Warning(LogSource.Geekbot, "karma migration failed"); + _logger.Error(LogSource.Geekbot, "karma migration failed", e); } #endregion @@ -115,15 +121,15 @@ namespace Geekbot.net.Database _database.Rolls.Add(user); await _database.SaveChangesAsync(); } - catch + catch (Exception e) { - _logger.Warning(LogSource.Geekbot, $"Rolls failed for: {q.Name}"); + _logger.Error(LogSource.Geekbot, $"Rolls failed for: {q.Name}", e); } } } - catch + catch (Exception e) { - _logger.Warning(LogSource.Geekbot, "rolls migration failed"); + _logger.Error(LogSource.Geekbot, "rolls migration failed", e); } #endregion @@ -144,20 +150,20 @@ namespace Geekbot.net.Database GuildId = guild.Id.AsLong(), UserId = ulong.Parse(q.Name).AsLong(), Given = int.Parse(q.Value), - Recieved= int.Parse(gotten[int.Parse(q.Name)].Value) + Recieved= int.Parse(gotten[long.Parse(q.Name)].Value) }; _database.Slaps.Add(user); await _database.SaveChangesAsync(); } - catch + catch (Exception e) { - _logger.Warning(LogSource.Geekbot, $"Slaps failed for: {q.Name}"); + _logger.Error(LogSource.Geekbot, $"Slaps failed for: {q.Name}", e); } } } - catch + catch (Exception e) { - _logger.Warning(LogSource.Geekbot, "Slaps migration failed"); + _logger.Error(LogSource.Geekbot, "Slaps migration failed", e); } #endregion @@ -181,15 +187,15 @@ namespace Geekbot.net.Database _database.Messages.Add(user); await _database.SaveChangesAsync(); } - catch + catch (Exception e) { - _logger.Warning(LogSource.Geekbot, $"Messages failed for: {q.Name}"); + _logger.Error(LogSource.Geekbot, $"Messages failed for: {q.Name}", e); } } } - catch + catch (Exception e) { - _logger.Warning(LogSource.Geekbot, "Messages migration failed"); + _logger.Error(LogSource.Geekbot, "Messages migration failed", e); } #endregion @@ -217,15 +223,15 @@ namespace Geekbot.net.Database await _database.SaveChangesAsync(); done.Add(q.Name); } - catch + catch (Exception e) { - _logger.Warning(LogSource.Geekbot, $"Ships failed for: {q.Name}"); + _logger.Error(LogSource.Geekbot, $"Ships failed for: {q.Name}", e); } } } - catch + catch (Exception e) { - _logger.Warning(LogSource.Geekbot, "Ships migration failed"); + _logger.Error(LogSource.Geekbot, "Ships migration failed", e); } #endregion @@ -268,19 +274,17 @@ namespace Geekbot.net.Database case "ModChannel": settings.ModChannel = long.Parse(setting.Value); break; - default: - throw new NotImplementedException(); } } catch (Exception e) { - _logger.Warning(LogSource.Geekbot, $"Setting failed: {setting.Name} - {guild.Id}", e); + _logger.Error(LogSource.Geekbot, $"Setting failed: {setting.Name} - {guild.Id}", e); } } } - catch + catch (Exception e) { - _logger.Warning(LogSource.Geekbot, "Settings migration failed"); + _logger.Error(LogSource.Geekbot, "Settings migration failed", e); } #endregion @@ -296,6 +300,11 @@ namespace Geekbot.net.Database { try { + if (user.Username == null) + { + await Task.Delay(100); + if (user.Username == null) break; + } var namesSerialized = _redis.HashGet($"User:{user.Id}", "UsedNames").ToString(); var names = namesSerialized != null ? Utf8Json.JsonSerializer.Deserialize(namesSerialized) @@ -314,30 +323,38 @@ namespace Geekbot.net.Database } catch (Exception e) { - _logger.Warning(LogSource.Geekbot, $"User failed: {user.Username}", e); + _logger.Error(LogSource.Geekbot, $"User failed: {user.Username}", e); } } } - catch + catch (Exception e) { - _logger.Warning(LogSource.Geekbot, "User migration failed"); + _logger.Error(LogSource.Geekbot, "User migration failed", e); } #endregion #region Guilds - _database.Guilds.Add(new GuildsModel + try { - CreatedAt = guild.CreatedAt, - GuildId = guild.Id.AsLong(), - IconUrl = guild.IconUrl, - Name = guild.Name, - Owner = guild.Owner.Id.AsLong() - }); - await _database.SaveChangesAsync(); + _database.Guilds.Add(new GuildsModel + { + CreatedAt = guild.CreatedAt, + GuildId = guild.Id.AsLong(), + IconUrl = guild?.IconUrl, + Name = guild.Name, + Owner = guild.Owner.Id.AsLong() + }); + await _database.SaveChangesAsync(); + } + catch (Exception e) + { + _logger.Error(LogSource.Geekbot, $"Guild migration failed: {guild.Name}", e); + } #endregion _logger.Information(LogSource.Geekbot, $"Finished Migration for {guild.Name}"); + await Task.Delay(1000); } _logger.Information(LogSource.Geekbot, "Finished migration process"); } diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index f9fbc62..52dbfc8 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -50,6 +50,10 @@ namespace Geekbot.net if (!(messageParam is SocketUserMessage message)) return Task.CompletedTask; if (message.Author.IsBot) return Task.CompletedTask; var argPos = 0; + + // ToDo: remove +// if (!message.Author.Id.Equals(93061333972455424)) return Task.CompletedTask; + var lowCaseMsg = message.ToString().ToLower(); if (lowCaseMsg.StartsWith("hui")) { From 35f0a5c8f8277df197ca4d110b4e3faf798f212c Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sat, 26 May 2018 02:33:45 +0200 Subject: [PATCH 190/553] Abstract away redis even more with AlmostRedis.cs --- Geekbot.net/Commands/Admin/Owner.cs | 6 +- Geekbot.net/Commands/Games/Roll.cs | 11 +-- Geekbot.net/Commands/User/Ranking/Rank.cs | 7 +- Geekbot.net/Commands/User/Stats.cs | 10 +-- Geekbot.net/Database/RedisMigration.cs | 74 +++++++++---------- Geekbot.net/Handlers.cs | 10 +-- Geekbot.net/Lib/AlmostRedis/AlmostRedis.cs | 44 +++++++++++ Geekbot.net/Lib/AlmostRedis/IAlmostRedis.cs | 13 ++++ .../Lib/Localization/TranslationHandler.cs | 32 ++++++-- Geekbot.net/Program.cs | 24 +++--- 10 files changed, 153 insertions(+), 78 deletions(-) create mode 100644 Geekbot.net/Lib/AlmostRedis/AlmostRedis.cs create mode 100644 Geekbot.net/Lib/AlmostRedis/IAlmostRedis.cs diff --git a/Geekbot.net/Commands/Admin/Owner.cs b/Geekbot.net/Commands/Admin/Owner.cs index e4aa2a8..a05bd8e 100644 --- a/Geekbot.net/Commands/Admin/Owner.cs +++ b/Geekbot.net/Commands/Admin/Owner.cs @@ -3,11 +3,11 @@ using System.Threading.Tasks; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Database; +using Geekbot.net.Lib.AlmostRedis; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.GlobalSettings; using Geekbot.net.Lib.Logger; using Geekbot.net.Lib.UserRepository; -using StackExchange.Redis; namespace Geekbot.net.Commands.Admin { @@ -20,10 +20,10 @@ namespace Geekbot.net.Commands.Admin private readonly DatabaseContext _database; private readonly IGlobalSettings _globalSettings; private readonly IGeekbotLogger _logger; - private readonly IDatabase _redis; + private readonly IAlmostRedis _redis; private readonly IUserRepository _userRepository; - public Owner(IDatabase redis, DiscordSocketClient client, IGeekbotLogger logger, IUserRepository userRepositry, IErrorHandler errorHandler, DatabaseContext database, IGlobalSettings globalSettings) + public Owner(IAlmostRedis redis, DiscordSocketClient client, IGeekbotLogger logger, IUserRepository userRepositry, IErrorHandler errorHandler, DatabaseContext database, IGlobalSettings globalSettings) { _redis = redis; _client = client; diff --git a/Geekbot.net/Commands/Games/Roll.cs b/Geekbot.net/Commands/Games/Roll.cs index 1d2ab4f..488488f 100644 --- a/Geekbot.net/Commands/Games/Roll.cs +++ b/Geekbot.net/Commands/Games/Roll.cs @@ -1,6 +1,7 @@ using System; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.net.Lib.AlmostRedis; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Localization; using StackExchange.Redis; @@ -10,10 +11,10 @@ namespace Geekbot.net.Commands.Games public class Roll : ModuleBase { private readonly IErrorHandler _errorHandler; - private readonly IDatabase _redis; + private readonly IAlmostRedis _redis; private readonly ITranslationHandler _translation; - public Roll(IDatabase redis, IErrorHandler errorHandler, ITranslationHandler translation) + public Roll(IAlmostRedis redis, IErrorHandler errorHandler, ITranslationHandler translation) { _redis = redis; _translation = translation; @@ -32,20 +33,20 @@ namespace Geekbot.net.Commands.Games var transDict = _translation.GetDict(Context); if (guess <= 100 && guess > 0) { - var prevRoll = _redis.HashGet($"{Context.Guild.Id}:RollsPrevious", Context.Message.Author.Id); + var prevRoll = _redis.Db.HashGet($"{Context.Guild.Id}:RollsPrevious", Context.Message.Author.Id); if (!prevRoll.IsNullOrEmpty && prevRoll.ToString() == guess.ToString()) { await ReplyAsync(string.Format(transDict["NoPrevGuess"], Context.Message.Author.Mention)); return; } - _redis.HashSet($"{Context.Guild.Id}:RollsPrevious", + _redis.Db.HashSet($"{Context.Guild.Id}:RollsPrevious", new[] {new HashEntry(Context.Message.Author.Id, guess)}); await ReplyAsync(string.Format(transDict["Rolled"], Context.Message.Author.Mention, number, guess)); if (guess == number) { await ReplyAsync(string.Format(transDict["Gratz"], Context.Message.Author)); - _redis.HashIncrement($"{Context.Guild.Id}:Rolls", Context.User.Id.ToString()); + _redis.Db.HashIncrement($"{Context.Guild.Id}:Rolls", Context.User.Id.ToString()); } } else diff --git a/Geekbot.net/Commands/User/Ranking/Rank.cs b/Geekbot.net/Commands/User/Ranking/Rank.cs index 6e3a1d8..f404b58 100644 --- a/Geekbot.net/Commands/User/Ranking/Rank.cs +++ b/Geekbot.net/Commands/User/Ranking/Rank.cs @@ -5,6 +5,7 @@ using System.Text; using System.Threading.Tasks; using Discord.Commands; using Geekbot.net.Database; +using Geekbot.net.Lib.AlmostRedis; using Geekbot.net.Lib.Converters; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; @@ -19,10 +20,10 @@ namespace Geekbot.net.Commands.User.Ranking private readonly IErrorHandler _errorHandler; private readonly DatabaseContext _database; private readonly IUserRepository _userRepository; - private readonly IDatabase _redis; + private readonly IAlmostRedis _redis; public Rank(DatabaseContext database, IErrorHandler errorHandler, IUserRepository userRepository, - IEmojiConverter emojiConverter, IDatabase redis) + IEmojiConverter emojiConverter, IAlmostRedis redis) { _database = database; _errorHandler = errorHandler; @@ -138,7 +139,7 @@ namespace Geekbot.net.Commands.User.Ranking private Dictionary GetMessageList(int amount) { - return _redis + return _redis.Db .HashGetAll($"{Context.Guild.Id}:Messages").ToDictionary().Take(amount + 1) .Where(user => !user.Key.Equals(0)) .ToDictionary(user => ulong.Parse(user.Key), user => int.Parse(user.Value)); diff --git a/Geekbot.net/Commands/User/Stats.cs b/Geekbot.net/Commands/User/Stats.cs index 01d169e..4a82a89 100644 --- a/Geekbot.net/Commands/User/Stats.cs +++ b/Geekbot.net/Commands/User/Stats.cs @@ -4,10 +4,10 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Database; +using Geekbot.net.Lib.AlmostRedis; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Levels; -using StackExchange.Redis; namespace Geekbot.net.Commands.User { @@ -15,10 +15,10 @@ namespace Geekbot.net.Commands.User { private readonly IErrorHandler _errorHandler; private readonly ILevelCalc _levelCalc; - private readonly IDatabase _redis; + private readonly IAlmostRedis _redis; private readonly DatabaseContext _database; - public Stats(IDatabase redis, DatabaseContext database, IErrorHandler errorHandler, ILevelCalc levelCalc) + public Stats(IAlmostRedis redis, DatabaseContext database, IErrorHandler errorHandler, ILevelCalc levelCalc) { _redis = redis; _database = database; @@ -39,8 +39,8 @@ namespace Geekbot.net.Commands.User var age = Math.Floor((DateTime.Now - createdAt).TotalDays); var joinedDayAgo = Math.Floor((DateTime.Now - joinedAt).TotalDays); - var messages = (int) _redis.HashGet($"{Context.Guild.Id}:Messages", userInfo.Id.ToString()); - var guildMessages = (int) _redis.HashGet($"{Context.Guild.Id}:Messages", 0.ToString()); + var messages = (int) _redis.Db.HashGet($"{Context.Guild.Id}:Messages", userInfo.Id.ToString()); + var guildMessages = (int) _redis.Db.HashGet($"{Context.Guild.Id}:Messages", 0.ToString()); var level = _levelCalc.GetLevel(messages); var percent = Math.Round((double) (100 * messages) / guildMessages, 2); diff --git a/Geekbot.net/Database/RedisMigration.cs b/Geekbot.net/Database/RedisMigration.cs index 2f005e3..80965d1 100644 --- a/Geekbot.net/Database/RedisMigration.cs +++ b/Geekbot.net/Database/RedisMigration.cs @@ -6,21 +6,21 @@ using Discord; using Discord.WebSocket; using Geekbot.net.Commands.Utils.Quote; using Geekbot.net.Database.Models; +using Geekbot.net.Lib.AlmostRedis; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Logger; using Newtonsoft.Json; -using StackExchange.Redis; namespace Geekbot.net.Database { public class RedisMigration { private readonly DatabaseContext _database; - private readonly IDatabase _redis; + private readonly IAlmostRedis _redis; private readonly IGeekbotLogger _logger; private readonly DiscordSocketClient _client; - public RedisMigration(DatabaseContext database, IDatabase redis, IGeekbotLogger logger, DiscordSocketClient client) + public RedisMigration(DatabaseContext database, IAlmostRedis redis, IGeekbotLogger logger, DiscordSocketClient client) { _database = database; _redis = redis; @@ -46,7 +46,7 @@ namespace Geekbot.net.Database */ try { - var data = _redis.SetScan($"{guild.Id}:Quotes"); + var data = _redis.Db.SetScan($"{guild.Id}:Quotes"); foreach (var q in data) { try @@ -74,7 +74,7 @@ namespace Geekbot.net.Database */ try { - var data = _redis.HashGetAll($"{guild.Id}:Karma"); + var data = _redis.Db.HashGetAll($"{guild.Id}:Karma"); foreach (var q in data) { try @@ -107,7 +107,7 @@ namespace Geekbot.net.Database */ try { - var data = _redis.HashGetAll($"{guild.Id}:Rolls"); + var data = _redis.Db.HashGetAll($"{guild.Id}:Rolls"); foreach (var q in data) { try @@ -139,8 +139,8 @@ namespace Geekbot.net.Database */ try { - var given = _redis.HashGetAll($"{guild.Id}:SlapsGiven"); - var gotten = _redis.HashGetAll($"{guild.Id}:SlapsGiven"); + var given = _redis.Db.HashGetAll($"{guild.Id}:SlapsGiven"); + var gotten = _redis.Db.HashGetAll($"{guild.Id}:SlapsGiven"); foreach (var q in given) { try @@ -171,32 +171,32 @@ namespace Geekbot.net.Database /** * Messages */ - try - { - var data = _redis.HashGetAll($"{guild.Id}:Messages"); - foreach (var q in data) - { - try - { - var user = new MessagesModel() - { - GuildId = guild.Id.AsLong(), - UserId = ulong.Parse(q.Name).AsLong(), - MessageCount= int.Parse(q.Value) - }; - _database.Messages.Add(user); - await _database.SaveChangesAsync(); - } - catch (Exception e) - { - _logger.Error(LogSource.Geekbot, $"Messages failed for: {q.Name}", e); - } - } - } - catch (Exception e) - { - _logger.Error(LogSource.Geekbot, "Messages migration failed", e); - } +// try +// { +// var data = _redis.Db.HashGetAll($"{guild.Id}:Messages"); +// foreach (var q in data) +// { +// try +// { +// var user = new MessagesModel() +// { +// GuildId = guild.Id.AsLong(), +// UserId = ulong.Parse(q.Name).AsLong(), +// MessageCount= int.Parse(q.Value) +// }; +// _database.Messages.Add(user); +// await _database.SaveChangesAsync(); +// } +// catch (Exception e) +// { +// _logger.Error(LogSource.Geekbot, $"Messages failed for: {q.Name}", e); +// } +// } +// } +// catch (Exception e) +// { +// _logger.Error(LogSource.Geekbot, "Messages migration failed", e); +// } #endregion #region Ships @@ -205,7 +205,7 @@ namespace Geekbot.net.Database */ try { - var data = _redis.HashGetAll($"{guild.Id}:Ships"); + var data = _redis.Db.HashGetAll($"{guild.Id}:Ships"); var done = new List(); foreach (var q in data) { @@ -241,7 +241,7 @@ namespace Geekbot.net.Database */ try { - var data = _redis.HashGetAll($"{guild.Id}:Settings"); + var data = _redis.Db.HashGetAll($"{guild.Id}:Settings"); var settings = new GuildSettingsModel() { GuildId = guild.Id.AsLong(), @@ -305,7 +305,7 @@ namespace Geekbot.net.Database await Task.Delay(100); if (user.Username == null) break; } - var namesSerialized = _redis.HashGet($"User:{user.Id}", "UsedNames").ToString(); + var namesSerialized = _redis.Db.HashGet($"User:{user.Id}", "UsedNames").ToString(); var names = namesSerialized != null ? Utf8Json.JsonSerializer.Deserialize(namesSerialized) : new string[] {user.Username}; diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index 52dbfc8..0aab944 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -6,11 +6,11 @@ using Discord; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Database; +using Geekbot.net.Lib.AlmostRedis; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Logger; using Geekbot.net.Lib.ReactionListener; using Geekbot.net.Lib.UserRepository; -using StackExchange.Redis; namespace Geekbot.net { @@ -19,13 +19,13 @@ namespace Geekbot.net private readonly DatabaseContext _database; private readonly IDiscordClient _client; private readonly IGeekbotLogger _logger; - private readonly IDatabase _redis; + private readonly IAlmostRedis _redis; private readonly IServiceProvider _servicesProvider; private readonly CommandService _commands; private readonly IUserRepository _userRepository; private readonly IReactionListener _reactionListener; - public Handlers(DatabaseContext database, IDiscordClient client, IGeekbotLogger logger, IDatabase redis, + public Handlers(DatabaseContext database, IDiscordClient client, IGeekbotLogger logger, IAlmostRedis redis, IServiceProvider servicesProvider, CommandService commands, IUserRepository userRepository, IReactionListener reactionListener) { @@ -105,8 +105,8 @@ namespace Geekbot.net } var channel = (SocketGuildChannel) message.Channel; - _redis.HashIncrementAsync($"{channel.Guild.Id}:Messages", message.Author.Id.ToString()); - _redis.HashIncrementAsync($"{channel.Guild.Id}:Messages", 0.ToString()); + _redis.Db.HashIncrementAsync($"{channel.Guild.Id}:Messages", message.Author.Id.ToString()); + _redis.Db.HashIncrementAsync($"{channel.Guild.Id}:Messages", 0.ToString()); if (message.Author.IsBot) return Task.CompletedTask; _logger.Information(LogSource.Message, message.Content, SimpleConextConverter.ConvertSocketMessage(message)); diff --git a/Geekbot.net/Lib/AlmostRedis/AlmostRedis.cs b/Geekbot.net/Lib/AlmostRedis/AlmostRedis.cs new file mode 100644 index 0000000..031b266 --- /dev/null +++ b/Geekbot.net/Lib/AlmostRedis/AlmostRedis.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; +using Geekbot.net.Lib.Logger; +using StackExchange.Redis; + +namespace Geekbot.net.Lib.AlmostRedis +{ + // if anyone ever sees this, please come up with a better fucking name, i'd appriciate it + public class AlmostRedis : IAlmostRedis + { + private readonly GeekbotLogger _logger; + private readonly RunParameters _runParameters; + private IDatabase _database; + private ConnectionMultiplexer _connection; + private IAlmostRedis _almostRedisImplementation; + + public AlmostRedis(GeekbotLogger logger, RunParameters runParameters) + { + _logger = logger; + _runParameters = runParameters; + } + + public void Connect() + { + _connection = ConnectionMultiplexer.Connect($"{_runParameters.RedisHost}:{_runParameters.RedisPort}"); + _database = _connection.GetDatabase(int.Parse(_runParameters.RedisDatabase)); + _logger.Information(LogSource.Redis, $"Connected to Redis on {_connection.Configuration} at {_database.Database}"); + } + + public IDatabase Db + { + get { return _database; } + } + + public ConnectionMultiplexer Connection + { + get { return _connection; } + } + + public IEnumerable GetAllKeys() + { + return _connection.GetServer($"{_runParameters.RedisHost}:{_runParameters.RedisPort}", int.Parse(_runParameters.RedisDatabase)).Keys(); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/AlmostRedis/IAlmostRedis.cs b/Geekbot.net/Lib/AlmostRedis/IAlmostRedis.cs new file mode 100644 index 0000000..549c49e --- /dev/null +++ b/Geekbot.net/Lib/AlmostRedis/IAlmostRedis.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using StackExchange.Redis; + +namespace Geekbot.net.Lib.AlmostRedis +{ + public interface IAlmostRedis + { + void Connect(); + IDatabase Db { get; } + ConnectionMultiplexer Connection { get; } + IEnumerable GetAllKeys(); + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Localization/TranslationHandler.cs b/Geekbot.net/Lib/Localization/TranslationHandler.cs index 550759d..afcd439 100644 --- a/Geekbot.net/Lib/Localization/TranslationHandler.cs +++ b/Geekbot.net/Lib/Localization/TranslationHandler.cs @@ -4,24 +4,26 @@ using System.IO; using System.Linq; using Discord.Commands; using Discord.WebSocket; +using Geekbot.net.Database; +using Geekbot.net.Database.Models; +using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Logger; -using StackExchange.Redis; using Utf8Json; namespace Geekbot.net.Lib.Localization { public class TranslationHandler : ITranslationHandler { + private readonly DatabaseContext _database; private readonly IGeekbotLogger _logger; - private readonly IDatabase _redis; private Dictionary>> _translations; private Dictionary _serverLanguages; private List _supportedLanguages; - public TranslationHandler(IReadOnlyCollection clientGuilds, IDatabase redis, IGeekbotLogger logger) + public TranslationHandler(IReadOnlyCollection clientGuilds, DatabaseContext database, IGeekbotLogger logger) { + _database = database; _logger = logger; - _redis = redis; _logger.Information(LogSource.Geekbot, "Loading Translations"); LoadTranslations(); LoadServerLanguages(clientGuilds); @@ -81,14 +83,16 @@ namespace Geekbot.net.Lib.Localization _serverLanguages = new Dictionary(); foreach (var guild in clientGuilds) { - var language = _redis.HashGet($"{guild.Id}:Settings", "Language"); + var language = _database.GuildSettings + .FirstOrDefault(g => g.GuildId.Equals(guild.Id.AsLong())) + ?.Language ?? "EN"; if (string.IsNullOrEmpty(language) || !_supportedLanguages.Contains(language)) { _serverLanguages[guild.Id] = "EN"; } else { - _serverLanguages[guild.Id] = language.ToString(); + _serverLanguages[guild.Id] = language; } } } @@ -137,7 +141,9 @@ namespace Geekbot.net.Lib.Localization try { if (!_supportedLanguages.Contains(language)) return false; - _redis.HashSet($"{guildId}:Settings", new[]{ new HashEntry("Language", language) }); + var guild = GetGuild(guildId); + guild.Language = language; + _database.GuildSettings.Update(guild); _serverLanguages[guildId] = language; return true; } @@ -152,5 +158,17 @@ namespace Geekbot.net.Lib.Localization { return _supportedLanguages; } + + private GuildSettingsModel GetGuild(ulong guildId) + { + var guild = _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(guildId.AsLong())); + if (guild != null) return guild; + _database.GuildSettings.Add(new GuildSettingsModel + { + GuildId = guildId.AsLong() + }); + _database.SaveChanges(); + return _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(guildId.AsLong())); + } } } \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index f94a785..f818802 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -8,6 +8,7 @@ using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Database; using Geekbot.net.Lib; +using Geekbot.net.Lib.AlmostRedis; using Geekbot.net.Lib.Audio; using Geekbot.net.Lib.Clients; using Geekbot.net.Lib.Converters; @@ -20,7 +21,6 @@ using Geekbot.net.Lib.Media; using Geekbot.net.Lib.ReactionListener; using Geekbot.net.Lib.UserRepository; using Microsoft.Extensions.DependencyInjection; -using StackExchange.Redis; using WikipediaApi; namespace Geekbot.net @@ -29,15 +29,15 @@ namespace Geekbot.net { private DiscordSocketClient _client; private CommandService _commands; - private IDatabase _redis; private DatabaseContext _database; private IGlobalSettings _globalSettings; private IServiceCollection _services; private IServiceProvider _servicesProvider; - private RedisValue _token; + private string _token; private GeekbotLogger _logger; private IUserRepository _userRepository; private RunParameters _runParameters; + private IAlmostRedis _redis; private static void Main(string[] args) { @@ -52,8 +52,7 @@ namespace Geekbot.net logo.AppendLine(@"| | _| _| | _| | ' /| _ \| | | || |"); logo.AppendLine(@"| |_| | |___| |___| . \| |_) | |_| || |"); logo.AppendLine(@" \____|_____|_____|_|\_\____/ \___/ |_|"); - logo.AppendLine("========================================="); - logo.AppendLine($"Version {Constants.BotVersion()}"); + logo.AppendLine($"Version {Constants.BotVersion()} ".PadRight(41, '=')); Console.WriteLine(logo.ToString()); var sumologicActive = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("GEEKBOT_SUMO")); var logger = new GeekbotLogger(runParameters, sumologicActive); @@ -88,9 +87,8 @@ namespace Geekbot.net try { - var redisMultiplexer = ConnectionMultiplexer.Connect($"{runParameters.RedisHost}:{runParameters.RedisPort}"); - _redis = redisMultiplexer.GetDatabase(int.Parse(runParameters.RedisDatabase)); - logger.Information(LogSource.Redis, $"Connected to db {_redis.Database}"); + _redis = new AlmostRedis(logger, runParameters); + _redis.Connect(); } catch (Exception e) { @@ -99,7 +97,7 @@ namespace Geekbot.net } _token = runParameters.Token ?? _globalSettings.GetKey("DiscordToken"); - if (_token.IsNullOrEmpty) + if (string.IsNullOrEmpty(_token)) { Console.Write("Your bot Token: "); var newToken = Console.ReadLine(); @@ -120,7 +118,7 @@ namespace Geekbot.net var wikipediaClient = new WikipediaClient(); var audioUtils = new AudioUtils(); - _services.AddSingleton(_redis); + _services.AddSingleton(_redis); _services.AddSingleton(_userRepository); _services.AddSingleton(logger); _services.AddSingleton(levelCalc); @@ -154,9 +152,9 @@ namespace Geekbot.net _logger.Information(LogSource.Geekbot, $"Now Connected as {_client.CurrentUser.Username} to {_client.Guilds.Count} Servers"); _logger.Information(LogSource.Geekbot, "Registering Stuff"); - var translationHandler = new TranslationHandler(_client.Guilds, _redis, _logger); + var translationHandler = new TranslationHandler(_client.Guilds, _database, _logger); var errorHandler = new ErrorHandler(_logger, translationHandler, _runParameters.ExposeErrors); - var reactionListener = new ReactionListener(_redis); + var reactionListener = new ReactionListener(_redis.Db); await _commands.AddModulesAsync(Assembly.GetEntryAssembly()); _services.AddSingleton(_commands); _services.AddSingleton(errorHandler); @@ -185,7 +183,7 @@ namespace Geekbot.net } catch (Exception e) { - _logger.Error(LogSource.Geekbot, "Could not connect...", e); + _logger.Error(LogSource.Geekbot, "Could not connect to Discord", e); Environment.Exit(GeekbotExitCode.CouldNotLogin.GetHashCode()); } } From 80c2bd8500342a6411c7a63746c1af8284c29317 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sat, 26 May 2018 02:55:18 +0200 Subject: [PATCH 191/553] Lazyload server language setting in translationHandler --- Geekbot.net/Commands/Admin/Admin.cs | 2 +- Geekbot.net/Lib/AlmostRedis/AlmostRedis.cs | 23 +++------- .../Lib/Localization/ITranslationHandler.cs | 2 +- .../Lib/Localization/TranslationHandler.cs | 46 +++++++++++-------- Geekbot.net/Program.cs | 2 +- 5 files changed, 36 insertions(+), 39 deletions(-) diff --git a/Geekbot.net/Commands/Admin/Admin.cs b/Geekbot.net/Commands/Admin/Admin.cs index 0925e54..ba31f3f 100644 --- a/Geekbot.net/Commands/Admin/Admin.cs +++ b/Geekbot.net/Commands/Admin/Admin.cs @@ -138,7 +138,7 @@ namespace Geekbot.net.Commands.Admin } await ReplyAsync( - $"That doesn't seem to be a supported language\r\nSupported Languages are {string.Join(", ", _translation.GetSupportedLanguages())}"); + $"That doesn't seem to be a supported language\r\nSupported Languages are {string.Join(", ", _translation.SupportedLanguages)}"); } catch (Exception e) { diff --git a/Geekbot.net/Lib/AlmostRedis/AlmostRedis.cs b/Geekbot.net/Lib/AlmostRedis/AlmostRedis.cs index 031b266..5e010f9 100644 --- a/Geekbot.net/Lib/AlmostRedis/AlmostRedis.cs +++ b/Geekbot.net/Lib/AlmostRedis/AlmostRedis.cs @@ -9,9 +9,6 @@ namespace Geekbot.net.Lib.AlmostRedis { private readonly GeekbotLogger _logger; private readonly RunParameters _runParameters; - private IDatabase _database; - private ConnectionMultiplexer _connection; - private IAlmostRedis _almostRedisImplementation; public AlmostRedis(GeekbotLogger logger, RunParameters runParameters) { @@ -21,24 +18,18 @@ namespace Geekbot.net.Lib.AlmostRedis public void Connect() { - _connection = ConnectionMultiplexer.Connect($"{_runParameters.RedisHost}:{_runParameters.RedisPort}"); - _database = _connection.GetDatabase(int.Parse(_runParameters.RedisDatabase)); - _logger.Information(LogSource.Redis, $"Connected to Redis on {_connection.Configuration} at {_database.Database}"); + Connection = ConnectionMultiplexer.Connect($"{_runParameters.RedisHost}:{_runParameters.RedisPort}"); + Db = Connection.GetDatabase(int.Parse(_runParameters.RedisDatabase)); + _logger.Information(LogSource.Redis, $"Connected to Redis on {Connection.Configuration} at {Db.Database}"); } - public IDatabase Db - { - get { return _database; } - } + public IDatabase Db { get; private set; } + + public ConnectionMultiplexer Connection { get; private set; } - public ConnectionMultiplexer Connection - { - get { return _connection; } - } - public IEnumerable GetAllKeys() { - return _connection.GetServer($"{_runParameters.RedisHost}:{_runParameters.RedisPort}", int.Parse(_runParameters.RedisDatabase)).Keys(); + return Connection.GetServer($"{_runParameters.RedisHost}:{_runParameters.RedisPort}", int.Parse(_runParameters.RedisDatabase)).Keys(); } } } \ No newline at end of file diff --git a/Geekbot.net/Lib/Localization/ITranslationHandler.cs b/Geekbot.net/Lib/Localization/ITranslationHandler.cs index 3cd9549..df4d707 100644 --- a/Geekbot.net/Lib/Localization/ITranslationHandler.cs +++ b/Geekbot.net/Lib/Localization/ITranslationHandler.cs @@ -9,6 +9,6 @@ namespace Geekbot.net.Lib.Localization Dictionary GetDict(ICommandContext context); Dictionary GetDict(ICommandContext context, string command); bool SetLanguage(ulong guildId, string language); - List GetSupportedLanguages(); + List SupportedLanguages { get; } } } \ No newline at end of file diff --git a/Geekbot.net/Lib/Localization/TranslationHandler.cs b/Geekbot.net/Lib/Localization/TranslationHandler.cs index afcd439..f8e2d88 100644 --- a/Geekbot.net/Lib/Localization/TranslationHandler.cs +++ b/Geekbot.net/Lib/Localization/TranslationHandler.cs @@ -16,17 +16,17 @@ namespace Geekbot.net.Lib.Localization { private readonly DatabaseContext _database; private readonly IGeekbotLogger _logger; + private readonly Dictionary _serverLanguages; private Dictionary>> _translations; - private Dictionary _serverLanguages; private List _supportedLanguages; - public TranslationHandler(IReadOnlyCollection clientGuilds, DatabaseContext database, IGeekbotLogger logger) + public TranslationHandler(DatabaseContext database, IGeekbotLogger logger) { _database = database; _logger = logger; _logger.Information(LogSource.Geekbot, "Loading Translations"); LoadTranslations(); - LoadServerLanguages(clientGuilds); + _serverLanguages = new Dictionary(); } private void LoadTranslations() @@ -78,28 +78,37 @@ namespace Geekbot.net.Lib.Localization } } - private void LoadServerLanguages(IReadOnlyCollection clientGuilds) + private string GetServerLanguage(ulong guildId) { - _serverLanguages = new Dictionary(); - foreach (var guild in clientGuilds) + try { - var language = _database.GuildSettings - .FirstOrDefault(g => g.GuildId.Equals(guild.Id.AsLong())) - ?.Language ?? "EN"; - if (string.IsNullOrEmpty(language) || !_supportedLanguages.Contains(language)) + string lang; + try { - _serverLanguages[guild.Id] = "EN"; + lang = _serverLanguages[guildId]; + if (!string.IsNullOrEmpty(lang)) + { + return lang; + } + throw new Exception(); } - else + catch { - _serverLanguages[guild.Id] = language; + lang = GetGuild(guildId).Language ?? "EN"; + _serverLanguages[guildId] = lang; + return lang; } } + catch (Exception e) + { + _logger.Error(LogSource.Geekbot, "Could not get guild langage", e); + return "EN"; + } } public string GetString(ulong guildId, string command, string stringName) { - var translation = _translations[_serverLanguages[guildId]][command][stringName]; + var translation = _translations[GetServerLanguage(guildId)][command][stringName]; if (!string.IsNullOrWhiteSpace(translation)) return translation; translation = _translations[command][stringName]["EN"]; if (string.IsNullOrWhiteSpace(translation)) @@ -114,7 +123,7 @@ namespace Geekbot.net.Lib.Localization try { var command = context.Message.Content.Split(' ').First().TrimStart('!').ToLower(); - return _translations[_serverLanguages[context.Guild.Id]][command]; + return _translations[GetServerLanguage(context.Guild.Id)][command]; } catch (Exception e) { @@ -127,7 +136,7 @@ namespace Geekbot.net.Lib.Localization { try { - return _translations[_serverLanguages[context.Guild.Id]][command]; + return _translations[GetServerLanguage(context.Guild.Id)][command]; } catch (Exception e) { @@ -154,10 +163,7 @@ namespace Geekbot.net.Lib.Localization } } - public List GetSupportedLanguages() - { - return _supportedLanguages; - } + public List SupportedLanguages => _supportedLanguages; private GuildSettingsModel GetGuild(ulong guildId) { diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index f818802..86a3507 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -152,7 +152,7 @@ namespace Geekbot.net _logger.Information(LogSource.Geekbot, $"Now Connected as {_client.CurrentUser.Username} to {_client.Guilds.Count} Servers"); _logger.Information(LogSource.Geekbot, "Registering Stuff"); - var translationHandler = new TranslationHandler(_client.Guilds, _database, _logger); + var translationHandler = new TranslationHandler(_database, _logger); var errorHandler = new ErrorHandler(_logger, translationHandler, _runParameters.ExposeErrors); var reactionListener = new ReactionListener(_redis.Db); await _commands.AddModulesAsync(Assembly.GetEntryAssembly()); From f438914c19306938121b42f9bd2dafc995b8552b Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 30 May 2018 23:54:00 +0200 Subject: [PATCH 192/553] Upgrade to dotnet 2.1 --- Geekbot.net/Geekbot.net.csproj | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 9b0fac6..336787a 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -22,26 +22,26 @@ 2.0.0-beta - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - + + From 8b5e52c8e0ca0d468b0e3525988093ac7abb70dd Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 1 Jun 2018 18:10:22 +0200 Subject: [PATCH 193/553] Actually upgrade to dotnet 2.1 --- .gitlab-ci.yml | 2 +- Geekbot.net/Geekbot.net.csproj | 8 +++----- Tests/Tests.csproj | 2 +- WikipediaApi/WikipediaApi.csproj | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 98eb9ba..b40a5e5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,7 +9,7 @@ before_script: build: stage: build - image: microsoft/dotnet:2.0.3-sdk-stretch + image: microsoft/dotnet:2.1.300-sdk-stretch variables: NUGET_PACKAGES: "${CI_PROJECT_DIR}/.nugetcache" cache: diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 336787a..9019d87 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -1,7 +1,8 @@  Exe - netcoreapp2.0 + netcoreapp2.1 + win-x64;linux-x64 derp.ico 4.0.0 $(VersionSuffix) @@ -42,7 +43,7 @@ - + @@ -57,9 +58,6 @@ - - - PreserveNewest diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 4713b2b..96c170b 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -1,6 +1,6 @@  - netcoreapp2.0 + netcoreapp2.1 false NU1701 diff --git a/WikipediaApi/WikipediaApi.csproj b/WikipediaApi/WikipediaApi.csproj index f182d90..9a86577 100644 --- a/WikipediaApi/WikipediaApi.csproj +++ b/WikipediaApi/WikipediaApi.csproj @@ -1,6 +1,6 @@  - netcoreapp2.0 + netcoreapp2.1 From 926a632641a9908f4d7e5ae0aabec3f850242efb Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sat, 2 Jun 2018 00:16:32 +0200 Subject: [PATCH 194/553] Get guilds from existing redis keys instead of the client --- Geekbot.net/Database/RedisMigration.cs | 22 +++++++++++++++++++++- Geekbot.net/Lib/AlmostRedis/AlmostRedis.cs | 2 +- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Geekbot.net/Database/RedisMigration.cs b/Geekbot.net/Database/RedisMigration.cs index 80965d1..3097a88 100644 --- a/Geekbot.net/Database/RedisMigration.cs +++ b/Geekbot.net/Database/RedisMigration.cs @@ -31,7 +31,27 @@ namespace Geekbot.net.Database public async Task Migrate() { _logger.Information(LogSource.Geekbot, "Starting migration process"); - foreach (var guild in _client.Guilds) + + var keys = _redis.GetAllKeys().Where(e => e.ToString().EndsWith("Messages")); + var guilds = new List(); + + foreach (var key in keys) + { + try + { + var g = _client.GetGuild(ulong.Parse(key.ToString().Split(':').First())); + Console.WriteLine(g.Name); + guilds.Add(g); + } + catch (Exception e) + { + // ignore + } + } + + _logger.Information(LogSource.Geekbot, $"Found {guilds.Count} guilds in redis"); + + foreach (var guild in guilds) { if (guild.MemberCount > 10000) { diff --git a/Geekbot.net/Lib/AlmostRedis/AlmostRedis.cs b/Geekbot.net/Lib/AlmostRedis/AlmostRedis.cs index 5e010f9..c6faf52 100644 --- a/Geekbot.net/Lib/AlmostRedis/AlmostRedis.cs +++ b/Geekbot.net/Lib/AlmostRedis/AlmostRedis.cs @@ -29,7 +29,7 @@ namespace Geekbot.net.Lib.AlmostRedis public IEnumerable GetAllKeys() { - return Connection.GetServer($"{_runParameters.RedisHost}:{_runParameters.RedisPort}", int.Parse(_runParameters.RedisDatabase)).Keys(); + return Connection.GetServer($"{_runParameters.RedisHost}:{_runParameters.RedisPort}").Keys(int.Parse(_runParameters.RedisDatabase)); } } } \ No newline at end of file From 95618b1f8b67af10568a98fff24e3740606cb2e4 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 13 Jun 2018 22:18:57 +0200 Subject: [PATCH 195/553] Make errorhandler and languagehandler async, await all database actions --- Geekbot.net/Commands/Admin/Admin.cs | 40 +++++++++---------- Geekbot.net/Commands/Admin/Mod.cs | 2 +- Geekbot.net/Commands/Admin/Owner.cs | 16 ++++---- Geekbot.net/Commands/Admin/Role.cs | 10 ++--- Geekbot.net/Commands/Admin/Say.cs | 2 +- Geekbot.net/Commands/Audio/Voice.cs | 4 +- Geekbot.net/Commands/Games/Pokedex.cs | 2 +- Geekbot.net/Commands/Games/Roll.cs | 2 +- .../Commands/Integrations/Google/Google.cs | 2 +- .../Integrations/MagicTheGathering.cs | 2 +- Geekbot.net/Commands/Integrations/Mal.cs | 2 +- .../UbranDictionary/UrbanDictionary.cs | 2 +- .../Commands/Integrations/Wikipedia.cs | 2 +- Geekbot.net/Commands/Integrations/Youtube.cs | 2 +- Geekbot.net/Commands/Randomness/Cat/Cat.cs | 2 +- Geekbot.net/Commands/Randomness/CheckEm.cs | 2 +- .../Randomness/Chuck/ChuckNorrisJokes.cs | 2 +- .../Commands/Randomness/Dad/DadJokes.cs | 2 +- Geekbot.net/Commands/Randomness/Dog/Dog.cs | 2 +- Geekbot.net/Commands/Randomness/EightBall.cs | 2 +- Geekbot.net/Commands/Randomness/Gdq.cs | 2 +- Geekbot.net/Commands/Randomness/Ship.cs | 2 +- Geekbot.net/Commands/Randomness/Slap.cs | 16 ++++---- Geekbot.net/Commands/User/GuildInfo.cs | 2 +- Geekbot.net/Commands/User/Karma.cs | 23 +++++------ Geekbot.net/Commands/User/Ranking/Rank.cs | 24 +++++++++-- Geekbot.net/Commands/User/Stats.cs | 13 ++++-- Geekbot.net/Commands/Utils/AvatarGetter.cs | 2 +- .../Commands/Utils/Changelog/Changelog.cs | 2 +- Geekbot.net/Commands/Utils/Choose.cs | 4 +- Geekbot.net/Commands/Utils/Emojify.cs | 2 +- Geekbot.net/Commands/Utils/Help.cs | 2 +- Geekbot.net/Commands/Utils/Info.cs | 4 +- Geekbot.net/Commands/Utils/Poll.cs | 6 +-- Geekbot.net/Commands/Utils/Quote/Quote.cs | 12 +++--- Geekbot.net/Geekbot.net.csproj | 2 +- Geekbot.net/Handlers.cs | 21 ++++++---- Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs | 9 +++-- .../Lib/ErrorHandling/IErrorHandler.cs | 5 ++- .../Lib/Extensions/StringExtensions.cs | 12 ++++++ .../Lib/GlobalSettings/GlobalSettings.cs | 7 ++-- .../Lib/GlobalSettings/IGlobalSettings.cs | 5 ++- Geekbot.net/Lib/Levels/ILevelCalc.cs | 2 +- Geekbot.net/Lib/Levels/LevelCalc.cs | 2 +- .../Lib/Localization/ITranslationHandler.cs | 9 +++-- .../Lib/Localization/TranslationHandler.cs | 26 ++++++------ 46 files changed, 181 insertions(+), 137 deletions(-) create mode 100644 Geekbot.net/Lib/Extensions/StringExtensions.cs diff --git a/Geekbot.net/Commands/Admin/Admin.cs b/Geekbot.net/Commands/Admin/Admin.cs index ba31f3f..fd7bbc6 100644 --- a/Geekbot.net/Commands/Admin/Admin.cs +++ b/Geekbot.net/Commands/Admin/Admin.cs @@ -35,7 +35,7 @@ namespace Geekbot.net.Commands.Admin [Summary("Set a Welcome Message (use '$user' to mention the new joined user).")] public async Task SetWelcomeMessage([Remainder] [Summary("message")] string welcomeMessage) { - var guild = GetGuildSettings(Context.Guild.Id); + var guild = await GetGuildSettings(Context.Guild.Id); guild.WelcomeMessage = welcomeMessage; _database.GuildSettings.Update(guild); await _database.SaveChangesAsync(); @@ -52,7 +52,7 @@ namespace Geekbot.net.Commands.Admin { var m = await channel.SendMessageAsync("verifying..."); - var guild = GetGuildSettings(Context.Guild.Id); + var guild = await GetGuildSettings(Context.Guild.Id); guild.ModChannel = channel.Id.AsLong(); _database.GuildSettings.Update(guild); await _database.SaveChangesAsync(); @@ -65,7 +65,7 @@ namespace Geekbot.net.Commands.Admin } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context, "That channel doesn't seem to be valid"); + await _errorHandler.HandleCommandException(e, Context, "That channel doesn't seem to be valid"); } } @@ -75,7 +75,7 @@ namespace Geekbot.net.Commands.Admin { try { - var guild = GetGuildSettings(Context.Guild.Id); + var guild = await GetGuildSettings(Context.Guild.Id); var modChannel = await GetModChannel(guild.ModChannel.AsUlong()); if (modChannel == null) return; @@ -89,7 +89,7 @@ namespace Geekbot.net.Commands.Admin } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } @@ -99,7 +99,7 @@ namespace Geekbot.net.Commands.Admin { try { - var guild = GetGuildSettings(Context.Guild.Id); + var guild = await GetGuildSettings(Context.Guild.Id); var modChannel = await GetModChannel(guild.ModChannel.AsUlong()); if (modChannel == null) return; @@ -113,7 +113,7 @@ namespace Geekbot.net.Commands.Admin } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } @@ -124,15 +124,15 @@ namespace Geekbot.net.Commands.Admin try { var language = languageRaw.ToUpper(); - var success = _translation.SetLanguage(Context.Guild.Id, language); + var success = await _translation.SetLanguage(Context.Guild.Id, language); if (success) { - var guild = GetGuildSettings(Context.Guild.Id); + var guild = await GetGuildSettings(Context.Guild.Id); guild.Language = language; _database.GuildSettings.Update(guild); await _database.SaveChangesAsync(); - var trans = _translation.GetDict(Context); + var trans = await _translation.GetDict(Context); await ReplyAsync(trans["NewLanguageSet"]); return; } @@ -142,7 +142,7 @@ namespace Geekbot.net.Commands.Admin } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } @@ -153,7 +153,7 @@ namespace Geekbot.net.Commands.Admin try { var language = languageRaw.ToLower(); - var guild = GetGuildSettings(Context.Guild.Id); + var guild = await GetGuildSettings(Context.Guild.Id); guild.WikiLang = language; _database.GuildSettings.Update(guild); await _database.SaveChangesAsync(); @@ -162,7 +162,7 @@ namespace Geekbot.net.Commands.Admin } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } @@ -172,7 +172,7 @@ namespace Geekbot.net.Commands.Admin { try { - var guild = GetGuildSettings(Context.Guild.Id); + var guild = await GetGuildSettings(Context.Guild.Id); guild.Ping = !guild.Ping; _database.GuildSettings.Update(guild); await _database.SaveChangesAsync(); @@ -180,7 +180,7 @@ namespace Geekbot.net.Commands.Admin } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } @@ -190,7 +190,7 @@ namespace Geekbot.net.Commands.Admin { try { - var guild = GetGuildSettings(Context.Guild.Id); + var guild = await GetGuildSettings(Context.Guild.Id); guild.Hui = !guild.Hui; _database.GuildSettings.Update(guild); await _database.SaveChangesAsync(); @@ -198,11 +198,11 @@ namespace Geekbot.net.Commands.Admin } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } - private GuildSettingsModel GetGuildSettings(ulong guildId) + private async Task GetGuildSettings(ulong guildId) { var guild = _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(guildId.AsLong())); if (guild != null) return guild; @@ -212,12 +212,12 @@ namespace Geekbot.net.Commands.Admin GuildId = guildId.AsLong(), Hui = false, Ping = false, - Language = "en", + Language = "EN", ShowDelete = false, ShowLeave = false, WikiLang = "en" }); - _database.SaveChanges(); + await _database.SaveChangesAsync(); return _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(guildId.AsLong())); } diff --git a/Geekbot.net/Commands/Admin/Mod.cs b/Geekbot.net/Commands/Admin/Mod.cs index a200cac..b014e53 100644 --- a/Geekbot.net/Commands/Admin/Mod.cs +++ b/Geekbot.net/Commands/Admin/Mod.cs @@ -40,7 +40,7 @@ namespace Geekbot.net.Commands.Admin } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context, + await _errorHandler.HandleCommandException(e, Context, $"I don't have enough permissions do that"); } } diff --git a/Geekbot.net/Commands/Admin/Owner.cs b/Geekbot.net/Commands/Admin/Owner.cs index a05bd8e..7cc194b 100644 --- a/Geekbot.net/Commands/Admin/Owner.cs +++ b/Geekbot.net/Commands/Admin/Owner.cs @@ -52,14 +52,14 @@ namespace Geekbot.net.Commands.Admin } await ReplyAsync("starting migration"); - _globalSettings.SetKey("MigrationStatus", "Running"); + await _globalSettings.SetKey("MigrationStatus", "Running"); var redisMigration = new RedisMigration(_database, _redis, _logger, _client); await redisMigration.Migrate(); - _globalSettings.SetKey("MigrationStatus", "Done"); + await _globalSettings.SetKey("MigrationStatus", "Done"); } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } await ReplyAsync("done"); @@ -69,7 +69,7 @@ namespace Geekbot.net.Commands.Admin [Summary("Set the youtube api key")] public async Task SetYoutubeKey([Summary("API Key")] string key) { - _globalSettings.SetKey("YoutubeKey", key); + await _globalSettings.SetKey("YoutubeKey", key); await ReplyAsync("Apikey has been set"); } @@ -77,7 +77,7 @@ namespace Geekbot.net.Commands.Admin [Summary("Set the game that the bot is playing")] public async Task SetGame([Remainder] [Summary("Game")] string key) { - _globalSettings.SetKey("Game", key); + await _globalSettings.SetKey("Game", key); await _client.SetGameAsync(key); _logger.Information(LogSource.Geekbot, $"Changed game to {key}"); await ReplyAsync($"Now Playing {key}"); @@ -109,14 +109,14 @@ namespace Geekbot.net.Commands.Admin } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context, + await _errorHandler.HandleCommandException(e, Context, "Couldn't complete User Repository, see console for more info"); } } [Command("error", RunMode = RunMode.Async)] [Summary("Throw an error un purpose")] - public void PurposefulError() + public async Task PurposefulError() { try { @@ -124,7 +124,7 @@ namespace Geekbot.net.Commands.Admin } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Commands/Admin/Role.cs b/Geekbot.net/Commands/Admin/Role.cs index c4d2362..a76c9d5 100644 --- a/Geekbot.net/Commands/Admin/Role.cs +++ b/Geekbot.net/Commands/Admin/Role.cs @@ -48,7 +48,7 @@ namespace Geekbot.net.Commands.Admin } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } @@ -87,11 +87,11 @@ namespace Geekbot.net.Commands.Admin } catch (HttpException e) { - _errorHandler.HandleHttpException(e, Context); + await _errorHandler.HandleHttpException(e, Context); } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } @@ -130,7 +130,7 @@ namespace Geekbot.net.Commands.Admin } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } @@ -155,7 +155,7 @@ namespace Geekbot.net.Commands.Admin } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } diff --git a/Geekbot.net/Commands/Admin/Say.cs b/Geekbot.net/Commands/Admin/Say.cs index f3db09b..910d700 100644 --- a/Geekbot.net/Commands/Admin/Say.cs +++ b/Geekbot.net/Commands/Admin/Say.cs @@ -27,7 +27,7 @@ namespace Geekbot.net.Commands.Admin } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Commands/Audio/Voice.cs b/Geekbot.net/Commands/Audio/Voice.cs index 169f298..aa406cc 100644 --- a/Geekbot.net/Commands/Audio/Voice.cs +++ b/Geekbot.net/Commands/Audio/Voice.cs @@ -59,7 +59,7 @@ namespace Geekbot.net.Commands.Audio } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); _audioUtils.Cleanup(Context.Guild.Id); } } @@ -92,7 +92,7 @@ namespace Geekbot.net.Commands.Audio } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); _audioUtils.Cleanup(Context.Guild.Id); } } diff --git a/Geekbot.net/Commands/Games/Pokedex.cs b/Geekbot.net/Commands/Games/Pokedex.cs index aea442b..fbfb568 100644 --- a/Geekbot.net/Commands/Games/Pokedex.cs +++ b/Geekbot.net/Commands/Games/Pokedex.cs @@ -41,7 +41,7 @@ namespace Geekbot.net.Commands.Games } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } diff --git a/Geekbot.net/Commands/Games/Roll.cs b/Geekbot.net/Commands/Games/Roll.cs index 488488f..e8d2d56 100644 --- a/Geekbot.net/Commands/Games/Roll.cs +++ b/Geekbot.net/Commands/Games/Roll.cs @@ -30,7 +30,7 @@ namespace Geekbot.net.Commands.Games var number = new Random().Next(1, 100); var guess = 1000; int.TryParse(stuff, out guess); - var transDict = _translation.GetDict(Context); + var transDict = await _translation.GetDict(Context); if (guess <= 100 && guess > 0) { var prevRoll = _redis.Db.HashGet($"{Context.Guild.Id}:RollsPrevious", Context.Message.Author.Id); diff --git a/Geekbot.net/Commands/Integrations/Google/Google.cs b/Geekbot.net/Commands/Integrations/Google/Google.cs index 1ad7c8e..6ff926d 100644 --- a/Geekbot.net/Commands/Integrations/Google/Google.cs +++ b/Geekbot.net/Commands/Integrations/Google/Google.cs @@ -61,7 +61,7 @@ namespace Geekbot.net.Commands.Integrations.Google } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Commands/Integrations/MagicTheGathering.cs b/Geekbot.net/Commands/Integrations/MagicTheGathering.cs index 2284646..2d3e7c6 100644 --- a/Geekbot.net/Commands/Integrations/MagicTheGathering.cs +++ b/Geekbot.net/Commands/Integrations/MagicTheGathering.cs @@ -64,7 +64,7 @@ namespace Geekbot.net.Commands.Integrations } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } diff --git a/Geekbot.net/Commands/Integrations/Mal.cs b/Geekbot.net/Commands/Integrations/Mal.cs index da03ead..7c79861 100644 --- a/Geekbot.net/Commands/Integrations/Mal.cs +++ b/Geekbot.net/Commands/Integrations/Mal.cs @@ -64,7 +64,7 @@ namespace Geekbot.net.Commands.Integrations } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } diff --git a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs b/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs index 928dfe2..25ab732 100644 --- a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs +++ b/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs @@ -59,7 +59,7 @@ namespace Geekbot.net.Commands.Integrations.UbranDictionary } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Commands/Integrations/Wikipedia.cs b/Geekbot.net/Commands/Integrations/Wikipedia.cs index 069ba8c..e1f6092 100644 --- a/Geekbot.net/Commands/Integrations/Wikipedia.cs +++ b/Geekbot.net/Commands/Integrations/Wikipedia.cs @@ -87,7 +87,7 @@ namespace Geekbot.net.Commands.Integrations } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } diff --git a/Geekbot.net/Commands/Integrations/Youtube.cs b/Geekbot.net/Commands/Integrations/Youtube.cs index 2e9fce0..ed630ee 100644 --- a/Geekbot.net/Commands/Integrations/Youtube.cs +++ b/Geekbot.net/Commands/Integrations/Youtube.cs @@ -51,7 +51,7 @@ namespace Geekbot.net.Commands.Integrations } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Commands/Randomness/Cat/Cat.cs b/Geekbot.net/Commands/Randomness/Cat/Cat.cs index f46ed25..4d43a4c 100644 --- a/Geekbot.net/Commands/Randomness/Cat/Cat.cs +++ b/Geekbot.net/Commands/Randomness/Cat/Cat.cs @@ -45,7 +45,7 @@ namespace Geekbot.net.Commands.Randomness.Cat } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Commands/Randomness/CheckEm.cs b/Geekbot.net/Commands/Randomness/CheckEm.cs index 94a895a..f8191ad 100644 --- a/Geekbot.net/Commands/Randomness/CheckEm.cs +++ b/Geekbot.net/Commands/Randomness/CheckEm.cs @@ -51,7 +51,7 @@ namespace Geekbot.net.Commands.Randomness } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } diff --git a/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs b/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs index b9d906e..07ea41f 100644 --- a/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs +++ b/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs @@ -44,7 +44,7 @@ namespace Geekbot.net.Commands.Randomness.Chuck } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Commands/Randomness/Dad/DadJokes.cs b/Geekbot.net/Commands/Randomness/Dad/DadJokes.cs index 3945609..2c51781 100644 --- a/Geekbot.net/Commands/Randomness/Dad/DadJokes.cs +++ b/Geekbot.net/Commands/Randomness/Dad/DadJokes.cs @@ -44,7 +44,7 @@ namespace Geekbot.net.Commands.Randomness.Dad } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Commands/Randomness/Dog/Dog.cs b/Geekbot.net/Commands/Randomness/Dog/Dog.cs index 6606ef5..176cbad 100644 --- a/Geekbot.net/Commands/Randomness/Dog/Dog.cs +++ b/Geekbot.net/Commands/Randomness/Dog/Dog.cs @@ -45,7 +45,7 @@ namespace Geekbot.net.Commands.Randomness.Dog } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Commands/Randomness/EightBall.cs b/Geekbot.net/Commands/Randomness/EightBall.cs index b6f37d3..7b3bb1f 100644 --- a/Geekbot.net/Commands/Randomness/EightBall.cs +++ b/Geekbot.net/Commands/Randomness/EightBall.cs @@ -50,7 +50,7 @@ namespace Geekbot.net.Commands.Randomness } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Commands/Randomness/Gdq.cs b/Geekbot.net/Commands/Randomness/Gdq.cs index c723c6f..2685b33 100644 --- a/Geekbot.net/Commands/Randomness/Gdq.cs +++ b/Geekbot.net/Commands/Randomness/Gdq.cs @@ -31,7 +31,7 @@ namespace Geekbot.net.Commands.Randomness } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Commands/Randomness/Ship.cs b/Geekbot.net/Commands/Randomness/Ship.cs index 0f33da5..45956b6 100644 --- a/Geekbot.net/Commands/Randomness/Ship.cs +++ b/Geekbot.net/Commands/Randomness/Ship.cs @@ -59,7 +59,7 @@ namespace Geekbot.net.Commands.Randomness } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } diff --git a/Geekbot.net/Commands/Randomness/Slap.cs b/Geekbot.net/Commands/Randomness/Slap.cs index fea5991..412b20c 100644 --- a/Geekbot.net/Commands/Randomness/Slap.cs +++ b/Geekbot.net/Commands/Randomness/Slap.cs @@ -81,8 +81,8 @@ namespace Geekbot.net.Commands.Randomness await ReplyAsync($"{Context.User.Username} slapped {user.Username} with a {things[new Random().Next(things.Count - 1)]}"); - UpdateRecieved(user.Id); - UpdateGiven(Context.User.Id); + await UpdateRecieved(user.Id); + await UpdateGiven(Context.User.Id); await _database.SaveChangesAsync(); } catch (Exception e) @@ -91,21 +91,21 @@ namespace Geekbot.net.Commands.Randomness } } - private void UpdateGiven(ulong userId) + private async Task UpdateGiven(ulong userId) { - var user = GetUser(userId); + var user = await GetUser(userId); user.Given++; _database.Slaps.Update(user); } - private void UpdateRecieved(ulong userId) + private async Task UpdateRecieved(ulong userId) { - var user = GetUser(userId); + var user = await GetUser(userId); user.Recieved++; _database.Slaps.Update(user); } - private SlapsModel GetUser(ulong userId) + private async Task GetUser(ulong userId) { var user = _database.Slaps.FirstOrDefault(e => e.GuildId.Equals(Context.Guild.Id.AsLong()) && @@ -121,7 +121,7 @@ namespace Geekbot.net.Commands.Randomness Recieved = 0, Given = 0 }); - _database.SaveChanges(); + await _database.SaveChangesAsync(); return _database.Slaps.FirstOrDefault(e => e.GuildId.Equals(Context.Guild.Id.AsLong()) && e.UserId.Equals(userId.AsLong())); diff --git a/Geekbot.net/Commands/User/GuildInfo.cs b/Geekbot.net/Commands/User/GuildInfo.cs index 6f602b1..342f80f 100644 --- a/Geekbot.net/Commands/User/GuildInfo.cs +++ b/Geekbot.net/Commands/User/GuildInfo.cs @@ -51,7 +51,7 @@ namespace Geekbot.net.Commands.User } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Commands/User/Karma.cs b/Geekbot.net/Commands/User/Karma.cs index 8a9189d..beb1334 100644 --- a/Geekbot.net/Commands/User/Karma.cs +++ b/Geekbot.net/Commands/User/Karma.cs @@ -30,8 +30,8 @@ namespace Geekbot.net.Commands.User { try { - var transDict = _translation.GetDict(Context); - var actor = GetUser(Context.User.Id); + var transDict = await _translation.GetDict(Context); + var actor = await GetUser(Context.User.Id); if (user.Id == Context.User.Id) { await ReplyAsync(string.Format(transDict["CannotChangeOwn"], Context.User.Username)); @@ -43,7 +43,7 @@ namespace Geekbot.net.Commands.User } else { - var target = GetUser(user.Id); + var target = await GetUser(user.Id); target.Karma = target.Karma + 1; SetUser(target); @@ -77,8 +77,8 @@ namespace Geekbot.net.Commands.User { try { - var transDict = _translation.GetDict(Context); - var actor = GetUser(Context.User.Id); + var transDict = await _translation.GetDict(Context); + var actor = await GetUser(Context.User.Id); if (user.Id == Context.User.Id) { await ReplyAsync(string.Format(transDict["CannotChangeOwn"], Context.User.Username)); @@ -90,7 +90,7 @@ namespace Geekbot.net.Commands.User } else { - var target = GetUser(user.Id); + var target = await GetUser(user.Id); target.Karma = target.Karma - 1; SetUser(target); @@ -129,19 +129,18 @@ namespace Geekbot.net.Commands.User return $"{dt.Minutes} Minutes and {dt.Seconds} Seconds"; } - private KarmaModel GetUser(ulong userId) + private async Task GetUser(ulong userId) { - var user = _database.Karma.FirstOrDefault(u =>u.GuildId.Equals(Context.Guild.Id.AsLong()) && u.UserId.Equals(userId.AsLong())) ?? CreateNewRow(userId); + var user = _database.Karma.FirstOrDefault(u =>u.GuildId.Equals(Context.Guild.Id.AsLong()) && u.UserId.Equals(userId.AsLong())) ?? await CreateNewRow(userId); return user; } - private bool SetUser(KarmaModel user) + private void SetUser(KarmaModel user) { _database.Karma.Update(user); - return true; } - private KarmaModel CreateNewRow(ulong userId) + private async Task CreateNewRow(ulong userId) { var user = new KarmaModel() { @@ -151,7 +150,7 @@ namespace Geekbot.net.Commands.User TimeOut = DateTimeOffset.MinValue }; var newUser = _database.Karma.Add(user).Entity; - _database.SaveChanges(); + await _database.SaveChangesAsync(); return newUser; } } diff --git a/Geekbot.net/Commands/User/Ranking/Rank.cs b/Geekbot.net/Commands/User/Ranking/Rank.cs index f404b58..a2e9891 100644 --- a/Geekbot.net/Commands/User/Ranking/Rank.cs +++ b/Geekbot.net/Commands/User/Ranking/Rank.cs @@ -81,6 +81,15 @@ namespace Geekbot.net.Commands.User.Ranking return; } + int guildMessages = 0; + if (type == RankType.messages) + { + guildMessages = _database.Messages + .Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())) + .Select(e => e.MessageCount) + .Sum(); + } + var highscoreUsers = new Dictionary(); var failedToRetrieveUser = false; foreach (var user in list) @@ -112,7 +121,7 @@ namespace Geekbot.net.Commands.User.Ranking } if (failedToRetrieveUser) replyBuilder.AppendLine(":warning: Couldn't get all userdata\n"); - replyBuilder.AppendLine($":bar_chart: **{type} Highscore for {Context.Guild.Name}**"); + replyBuilder.AppendLine($":bar_chart: **{type.ToString().CapitalizeFirst()} Highscore for {Context.Guild.Name}**"); var highscorePlace = 1; foreach (var user in highscoreUsers) { @@ -123,8 +132,10 @@ namespace Geekbot.net.Commands.User.Ranking replyBuilder.Append(user.Key.Username != null ? $"**{user.Key.Username}#{user.Key.Discriminator}**" : $"**{user.Key.Id}**"); - - replyBuilder.Append($" - {user.Value} {type}\n"); + + replyBuilder.Append(type == RankType.messages + ? $" - {user.Value} {type} - {Math.Round((double) (100 * user.Value) / guildMessages, digits: 2)}%\n" + : $" - {user.Value} {type}\n"); highscorePlace++; } @@ -133,12 +144,17 @@ namespace Geekbot.net.Commands.User.Ranking } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } private Dictionary GetMessageList(int amount) { +// return _database.Messages +// .Where(k => k.GuildId.Equals(Context.Guild.Id.AsLong())) +// .OrderByDescending(o => o.MessageCount) +// .Take(amount) +// .ToDictionary(key => key.UserId.AsUlong(), key => key.MessageCount); return _redis.Db .HashGetAll($"{Context.Guild.Id}:Messages").ToDictionary().Take(amount + 1) .Where(user => !user.Key.Equals(0)) diff --git a/Geekbot.net/Commands/User/Stats.cs b/Geekbot.net/Commands/User/Stats.cs index 4a82a89..990b229 100644 --- a/Geekbot.net/Commands/User/Stats.cs +++ b/Geekbot.net/Commands/User/Stats.cs @@ -39,11 +39,18 @@ namespace Geekbot.net.Commands.User var age = Math.Floor((DateTime.Now - createdAt).TotalDays); var joinedDayAgo = Math.Floor((DateTime.Now - joinedAt).TotalDays); - var messages = (int) _redis.Db.HashGet($"{Context.Guild.Id}:Messages", userInfo.Id.ToString()); - var guildMessages = (int) _redis.Db.HashGet($"{Context.Guild.Id}:Messages", 0.ToString()); + var messages = _database.Messages.FirstOrDefault(e => + e.GuildId.Equals(Context.Guild.Id.AsLong()) && + e.UserId.Equals(userInfo.Id.AsLong()))?.MessageCount; + + var guildMessages = _database.Messages + .Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())) + .Select(e => e.MessageCount) + .Sum(); + var level = _levelCalc.GetLevel(messages); - var percent = Math.Round((double) (100 * messages) / guildMessages, 2); + var percent = Math.Round((double) (100 * messages) / guildMessages, digits: 2); var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder() diff --git a/Geekbot.net/Commands/Utils/AvatarGetter.cs b/Geekbot.net/Commands/Utils/AvatarGetter.cs index 3f74770..e329ad4 100644 --- a/Geekbot.net/Commands/Utils/AvatarGetter.cs +++ b/Geekbot.net/Commands/Utils/AvatarGetter.cs @@ -27,7 +27,7 @@ namespace Geekbot.net.Commands.Utils } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Commands/Utils/Changelog/Changelog.cs b/Geekbot.net/Commands/Utils/Changelog/Changelog.cs index 5d47c08..adcc9a3 100644 --- a/Geekbot.net/Commands/Utils/Changelog/Changelog.cs +++ b/Geekbot.net/Commands/Utils/Changelog/Changelog.cs @@ -60,7 +60,7 @@ namespace Geekbot.net.Commands.Utils.Changelog } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Commands/Utils/Choose.cs b/Geekbot.net/Commands/Utils/Choose.cs index 411802a..ee2bf0d 100644 --- a/Geekbot.net/Commands/Utils/Choose.cs +++ b/Geekbot.net/Commands/Utils/Choose.cs @@ -24,14 +24,14 @@ namespace Geekbot.net.Commands.Utils { try { - var transDict = _translation.GetDict(Context); + var transDict = await _translation.GetDict(Context); var choicesArray = choices.Split(';'); var choice = new Random().Next(choicesArray.Length); await ReplyAsync(string.Format(transDict["Choice"], choicesArray[choice])); } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Commands/Utils/Emojify.cs b/Geekbot.net/Commands/Utils/Emojify.cs index f0e172e..5355aff 100644 --- a/Geekbot.net/Commands/Utils/Emojify.cs +++ b/Geekbot.net/Commands/Utils/Emojify.cs @@ -35,7 +35,7 @@ namespace Geekbot.net.Commands.Utils } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Commands/Utils/Help.cs b/Geekbot.net/Commands/Utils/Help.cs index ace5087..a6f0084 100644 --- a/Geekbot.net/Commands/Utils/Help.cs +++ b/Geekbot.net/Commands/Utils/Help.cs @@ -32,7 +32,7 @@ namespace Geekbot.net.Commands.Utils } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Commands/Utils/Info.cs b/Geekbot.net/Commands/Utils/Info.cs index aca4dcd..b1d5403 100644 --- a/Geekbot.net/Commands/Utils/Info.cs +++ b/Geekbot.net/Commands/Utils/Info.cs @@ -51,7 +51,7 @@ namespace Geekbot.net.Commands.Utils } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } @@ -66,7 +66,7 @@ namespace Geekbot.net.Commands.Utils } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Commands/Utils/Poll.cs b/Geekbot.net/Commands/Utils/Poll.cs index 585c1fb..c5a0119 100644 --- a/Geekbot.net/Commands/Utils/Poll.cs +++ b/Geekbot.net/Commands/Utils/Poll.cs @@ -48,7 +48,7 @@ namespace Geekbot.net.Commands.Utils } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } @@ -120,7 +120,7 @@ namespace Geekbot.net.Commands.Utils } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } @@ -148,7 +148,7 @@ namespace Geekbot.net.Commands.Utils } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } diff --git a/Geekbot.net/Commands/Utils/Quote/Quote.cs b/Geekbot.net/Commands/Utils/Quote/Quote.cs index 6af74d7..9a1d072 100644 --- a/Geekbot.net/Commands/Utils/Quote/Quote.cs +++ b/Geekbot.net/Commands/Utils/Quote/Quote.cs @@ -45,7 +45,7 @@ namespace Geekbot.net.Commands.Utils.Quote } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context, "Whoops, seems like the quote was to edgy to return"); + await _errorHandler.HandleCommandException(e, Context, "Whoops, seems like the quote was to edgy to return"); } } @@ -79,7 +79,7 @@ namespace Geekbot.net.Commands.Utils.Quote } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context, + await _errorHandler.HandleCommandException(e, Context, "I counldn't find a quote from that user :disappointed:"); } } @@ -112,7 +112,7 @@ namespace Geekbot.net.Commands.Utils.Quote } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context, + await _errorHandler.HandleCommandException(e, Context, "I couldn't find a message with that id :disappointed:"); } } @@ -131,7 +131,7 @@ namespace Geekbot.net.Commands.Utils.Quote } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context, + await _errorHandler.HandleCommandException(e, Context, "I counldn't find a quote from that user :disappointed:"); } } @@ -149,7 +149,7 @@ namespace Geekbot.net.Commands.Utils.Quote } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context, + await _errorHandler.HandleCommandException(e, Context, "I couldn't find a message with that id :disappointed:"); } } @@ -178,7 +178,7 @@ namespace Geekbot.net.Commands.Utils.Quote } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context, "I couldn't find a quote with that id :disappointed:"); + await _errorHandler.HandleCommandException(e, Context, "I couldn't find a quote with that id :disappointed:"); } } diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 9019d87..6e857bf 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -44,7 +44,7 @@ - + diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index 0aab944..0331ca9 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -11,6 +11,7 @@ using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Logger; using Geekbot.net.Lib.ReactionListener; using Geekbot.net.Lib.UserRepository; +using Microsoft.EntityFrameworkCore; namespace Geekbot.net { @@ -93,29 +94,33 @@ namespace Geekbot.net } } - public Task UpdateStats(SocketMessage message) + public async Task UpdateStats(SocketMessage message) { try { - if (message == null) return Task.CompletedTask; + if (message == null) return; if (message.Channel.Name.StartsWith('@')) { _logger.Information(LogSource.Message, $"[DM-Channel] {message.Content}", SimpleConextConverter.ConvertSocketMessage(message)); - return Task.CompletedTask; + return; } var channel = (SocketGuildChannel) message.Channel; + +// await _database.Database.ExecuteSqlCommandAsync("UPDATE \"Messages\" " + +// $"SET \"MessageCount\" = \"MessageCount\" + {1} " + +// $"WHERE \"GuildId\" = '{channel.Guild.Id.AsLong()}' " + +// $"AND \"UserId\" = '{message.Author.Id.AsLong()}'"); +// + await _redis.Db.HashIncrementAsync($"{channel.Guild.Id}:Messages", message.Author.Id.ToString()); + await _redis.Db.HashIncrementAsync($"{channel.Guild.Id}:Messages", 0.ToString()); - _redis.Db.HashIncrementAsync($"{channel.Guild.Id}:Messages", message.Author.Id.ToString()); - _redis.Db.HashIncrementAsync($"{channel.Guild.Id}:Messages", 0.ToString()); - - if (message.Author.IsBot) return Task.CompletedTask; + if (message.Author.IsBot) return; _logger.Information(LogSource.Message, message.Content, SimpleConextConverter.ConvertSocketMessage(message)); } catch (Exception e) { _logger.Error(LogSource.Message, "Could not process message stats", e); } - return Task.CompletedTask; } // diff --git a/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs index 99d1e8b..9556b84 100644 --- a/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs @@ -1,5 +1,6 @@ using System; using System.Net; +using System.Threading.Tasks; using Discord.Commands; using Discord.Net; using Geekbot.net.Lib.Localization; @@ -34,11 +35,11 @@ namespace Geekbot.net.Lib.ErrorHandling } } - public void HandleCommandException(Exception e, ICommandContext context, string errorMessage = "def") + public async Task HandleCommandException(Exception e, ICommandContext context, string errorMessage = "def") { try { - var errorString = errorMessage == "def" ? _translation.GetString(context.Guild.Id, "errorHandler", "SomethingWentWrong") : errorMessage; + var errorString = errorMessage == "def" ? await _translation.GetString(context.Guild.Id, "errorHandler", "SomethingWentWrong") : errorMessage; var errorObj = SimpleConextConverter.ConvertContext(context); if (e.Message.Contains("50007")) return; if (e.Message.Contains("50013")) return; @@ -86,9 +87,9 @@ namespace Geekbot.net.Lib.ErrorHandling } } - public async void HandleHttpException(HttpException e, ICommandContext context) + public async Task HandleHttpException(HttpException e, ICommandContext context) { - var errorStrings = _translation.GetDict(context, "httpErrors"); + var errorStrings = await _translation.GetDict(context, "httpErrors"); switch(e.HttpCode) { case HttpStatusCode.Forbidden: diff --git a/Geekbot.net/Lib/ErrorHandling/IErrorHandler.cs b/Geekbot.net/Lib/ErrorHandling/IErrorHandler.cs index f2d8dac..05e0d8e 100644 --- a/Geekbot.net/Lib/ErrorHandling/IErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandling/IErrorHandler.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using Discord.Commands; using Discord.Net; @@ -6,7 +7,7 @@ namespace Geekbot.net.Lib.ErrorHandling { public interface IErrorHandler { - void HandleCommandException(Exception e, ICommandContext context, string errorMessage = "def"); - void HandleHttpException(HttpException e, ICommandContext context); + Task HandleCommandException(Exception e, ICommandContext context, string errorMessage = "def"); + Task HandleHttpException(HttpException e, ICommandContext context); } } \ No newline at end of file diff --git a/Geekbot.net/Lib/Extensions/StringExtensions.cs b/Geekbot.net/Lib/Extensions/StringExtensions.cs new file mode 100644 index 0000000..9ec1dfe --- /dev/null +++ b/Geekbot.net/Lib/Extensions/StringExtensions.cs @@ -0,0 +1,12 @@ +using System.Linq; + +namespace Geekbot.net.Lib.Extensions +{ + public static class StringExtensions + { + public static string CapitalizeFirst(this string source) + { + return source.First().ToString().ToUpper() + source.Substring(1); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/GlobalSettings/GlobalSettings.cs b/Geekbot.net/Lib/GlobalSettings/GlobalSettings.cs index 1234b34..8a1d0e4 100644 --- a/Geekbot.net/Lib/GlobalSettings/GlobalSettings.cs +++ b/Geekbot.net/Lib/GlobalSettings/GlobalSettings.cs @@ -1,4 +1,5 @@ using System.Linq; +using System.Threading.Tasks; using Geekbot.net.Database; using Geekbot.net.Database.Models; @@ -13,7 +14,7 @@ namespace Geekbot.net.Lib.GlobalSettings _database = database; } - public bool SetKey(string keyName, string value) + public async Task SetKey(string keyName, string value) { try { @@ -25,13 +26,13 @@ namespace Geekbot.net.Lib.GlobalSettings Name = keyName, Value = value }); - _database.SaveChanges(); + await _database.SaveChangesAsync(); return true; } key.Value = value; _database.Globals.Update(key); - _database.SaveChanges(); + await _database.SaveChangesAsync(); return true; } catch diff --git a/Geekbot.net/Lib/GlobalSettings/IGlobalSettings.cs b/Geekbot.net/Lib/GlobalSettings/IGlobalSettings.cs index 1919b50..4833215 100644 --- a/Geekbot.net/Lib/GlobalSettings/IGlobalSettings.cs +++ b/Geekbot.net/Lib/GlobalSettings/IGlobalSettings.cs @@ -1,10 +1,11 @@ -using Geekbot.net.Database.Models; +using System.Threading.Tasks; +using Geekbot.net.Database.Models; namespace Geekbot.net.Lib.GlobalSettings { public interface IGlobalSettings { - bool SetKey(string keyName, string value); + Task SetKey(string keyName, string value); string GetKey(string keyName); GlobalsModel GetKeyFull(string keyName); } diff --git a/Geekbot.net/Lib/Levels/ILevelCalc.cs b/Geekbot.net/Lib/Levels/ILevelCalc.cs index 6353132..cc488e7 100644 --- a/Geekbot.net/Lib/Levels/ILevelCalc.cs +++ b/Geekbot.net/Lib/Levels/ILevelCalc.cs @@ -2,6 +2,6 @@ { public interface ILevelCalc { - int GetLevel(int experience); + int GetLevel(int? experience); } } \ No newline at end of file diff --git a/Geekbot.net/Lib/Levels/LevelCalc.cs b/Geekbot.net/Lib/Levels/LevelCalc.cs index 9ecf803..f5b6b80 100644 --- a/Geekbot.net/Lib/Levels/LevelCalc.cs +++ b/Geekbot.net/Lib/Levels/LevelCalc.cs @@ -19,7 +19,7 @@ namespace Geekbot.net.Lib.Levels _levels = levels.ToArray(); } - public int GetLevel(int messages) + public int GetLevel(int? messages) { var returnVal = 1; foreach (var level in _levels) diff --git a/Geekbot.net/Lib/Localization/ITranslationHandler.cs b/Geekbot.net/Lib/Localization/ITranslationHandler.cs index df4d707..2124d4e 100644 --- a/Geekbot.net/Lib/Localization/ITranslationHandler.cs +++ b/Geekbot.net/Lib/Localization/ITranslationHandler.cs @@ -1,14 +1,15 @@ using System.Collections.Generic; +using System.Threading.Tasks; using Discord.Commands; namespace Geekbot.net.Lib.Localization { public interface ITranslationHandler { - string GetString(ulong guildId, string command, string stringName); - Dictionary GetDict(ICommandContext context); - Dictionary GetDict(ICommandContext context, string command); - bool SetLanguage(ulong guildId, string language); + Task GetString(ulong guildId, string command, string stringName); + Task> GetDict(ICommandContext context); + Task> GetDict(ICommandContext context, string command); + Task SetLanguage(ulong guildId, string language); List SupportedLanguages { get; } } } \ No newline at end of file diff --git a/Geekbot.net/Lib/Localization/TranslationHandler.cs b/Geekbot.net/Lib/Localization/TranslationHandler.cs index f8e2d88..88e518e 100644 --- a/Geekbot.net/Lib/Localization/TranslationHandler.cs +++ b/Geekbot.net/Lib/Localization/TranslationHandler.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading.Tasks; using Discord.Commands; -using Discord.WebSocket; using Geekbot.net.Database; using Geekbot.net.Database.Models; using Geekbot.net.Lib.Extensions; @@ -78,7 +78,7 @@ namespace Geekbot.net.Lib.Localization } } - private string GetServerLanguage(ulong guildId) + private async Task GetServerLanguage(ulong guildId) { try { @@ -94,7 +94,7 @@ namespace Geekbot.net.Lib.Localization } catch { - lang = GetGuild(guildId).Language ?? "EN"; + lang = (await GetGuild(guildId)).Language ?? "EN"; _serverLanguages[guildId] = lang; return lang; } @@ -106,9 +106,9 @@ namespace Geekbot.net.Lib.Localization } } - public string GetString(ulong guildId, string command, string stringName) + public async Task GetString(ulong guildId, string command, string stringName) { - var translation = _translations[GetServerLanguage(guildId)][command][stringName]; + var translation = _translations[await GetServerLanguage(guildId)][command][stringName]; if (!string.IsNullOrWhiteSpace(translation)) return translation; translation = _translations[command][stringName]["EN"]; if (string.IsNullOrWhiteSpace(translation)) @@ -118,12 +118,12 @@ namespace Geekbot.net.Lib.Localization return translation; } - public Dictionary GetDict(ICommandContext context) + public async Task> GetDict(ICommandContext context) { try { var command = context.Message.Content.Split(' ').First().TrimStart('!').ToLower(); - return _translations[GetServerLanguage(context.Guild.Id)][command]; + return _translations[await GetServerLanguage(context.Guild.Id)][command]; } catch (Exception e) { @@ -132,11 +132,11 @@ namespace Geekbot.net.Lib.Localization } } - public Dictionary GetDict(ICommandContext context, string command) + public async Task> GetDict(ICommandContext context, string command) { try { - return _translations[GetServerLanguage(context.Guild.Id)][command]; + return _translations[await GetServerLanguage(context.Guild.Id)][command]; } catch (Exception e) { @@ -145,12 +145,12 @@ namespace Geekbot.net.Lib.Localization } } - public bool SetLanguage(ulong guildId, string language) + public async Task SetLanguage(ulong guildId, string language) { try { if (!_supportedLanguages.Contains(language)) return false; - var guild = GetGuild(guildId); + var guild = await GetGuild(guildId); guild.Language = language; _database.GuildSettings.Update(guild); _serverLanguages[guildId] = language; @@ -165,7 +165,7 @@ namespace Geekbot.net.Lib.Localization public List SupportedLanguages => _supportedLanguages; - private GuildSettingsModel GetGuild(ulong guildId) + private async Task GetGuild(ulong guildId) { var guild = _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(guildId.AsLong())); if (guild != null) return guild; @@ -173,7 +173,7 @@ namespace Geekbot.net.Lib.Localization { GuildId = guildId.AsLong() }); - _database.SaveChanges(); + await _database.SaveChangesAsync(); return _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(guildId.AsLong())); } } From 18b3436d66aff23814b16f39c3efa39ef42140d3 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 28 Jul 2018 16:31:18 +0200 Subject: [PATCH 196/553] add more awaits and update !roll --- Geekbot.net.sln.DotSettings | 11 ++++ Geekbot.net/Commands/Audio/Voice.cs | 2 +- Geekbot.net/Commands/Games/Roll.cs | 17 ++++--- Geekbot.net/Commands/Integrations/Mal.cs | 2 +- Geekbot.net/Commands/Randomness/Slap.cs | 2 +- Geekbot.net/Commands/User/Karma.cs | 4 +- Geekbot.net/Commands/User/Stats.cs | 2 +- Geekbot.net/Geekbot.net.csproj | 2 +- Geekbot.net/Handlers.cs | 51 +++++++++---------- Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs | 8 +-- Geekbot.net/Program.cs | 4 +- Tests/Tests.csproj | 2 +- 12 files changed, 60 insertions(+), 47 deletions(-) create mode 100644 Geekbot.net.sln.DotSettings diff --git a/Geekbot.net.sln.DotSettings b/Geekbot.net.sln.DotSettings new file mode 100644 index 0000000..7fa04b3 --- /dev/null +++ b/Geekbot.net.sln.DotSettings @@ -0,0 +1,11 @@ + + NEVER + 200 + True + True + True + True + True + True + True + True \ No newline at end of file diff --git a/Geekbot.net/Commands/Audio/Voice.cs b/Geekbot.net/Commands/Audio/Voice.cs index aa406cc..b12d6e2 100644 --- a/Geekbot.net/Commands/Audio/Voice.cs +++ b/Geekbot.net/Commands/Audio/Voice.cs @@ -37,7 +37,7 @@ namespace Geekbot.net.Commands.Audio } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } diff --git a/Geekbot.net/Commands/Games/Roll.cs b/Geekbot.net/Commands/Games/Roll.cs index e8d2d56..c629ed8 100644 --- a/Geekbot.net/Commands/Games/Roll.cs +++ b/Geekbot.net/Commands/Games/Roll.cs @@ -33,15 +33,18 @@ namespace Geekbot.net.Commands.Games var transDict = await _translation.GetDict(Context); if (guess <= 100 && guess > 0) { - var prevRoll = _redis.Db.HashGet($"{Context.Guild.Id}:RollsPrevious", Context.Message.Author.Id); - if (!prevRoll.IsNullOrEmpty && prevRoll.ToString() == guess.ToString()) + var prevRoll = _redis.Db.HashGet($"{Context.Guild.Id}:RollsPrevious2", Context.Message.Author.Id).ToString()?.Split('|'); + if (prevRoll?.Length == 2) { - await ReplyAsync(string.Format(transDict["NoPrevGuess"], Context.Message.Author.Mention)); - return; + if (prevRoll[0] == guess.ToString() && DateTime.Parse(prevRoll[1]) > DateTime.Now.AddDays(-1)) + { + await ReplyAsync(string.Format(transDict["NoPrevGuess"], Context.Message.Author.Mention)); + return; + } } - _redis.Db.HashSet($"{Context.Guild.Id}:RollsPrevious", - new[] {new HashEntry(Context.Message.Author.Id, guess)}); + _redis.Db.HashSet($"{Context.Guild.Id}:RollsPrevious2", new[] {new HashEntry(Context.Message.Author.Id, $"{guess}|{DateTime.Now}")}); + await ReplyAsync(string.Format(transDict["Rolled"], Context.Message.Author.Mention, number, guess)); if (guess == number) { @@ -56,7 +59,7 @@ namespace Geekbot.net.Commands.Games } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Commands/Integrations/Mal.cs b/Geekbot.net/Commands/Integrations/Mal.cs index 7c79861..88f500e 100644 --- a/Geekbot.net/Commands/Integrations/Mal.cs +++ b/Geekbot.net/Commands/Integrations/Mal.cs @@ -112,7 +112,7 @@ namespace Geekbot.net.Commands.Integrations } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Commands/Randomness/Slap.cs b/Geekbot.net/Commands/Randomness/Slap.cs index 412b20c..13cd22a 100644 --- a/Geekbot.net/Commands/Randomness/Slap.cs +++ b/Geekbot.net/Commands/Randomness/Slap.cs @@ -87,7 +87,7 @@ namespace Geekbot.net.Commands.Randomness } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } diff --git a/Geekbot.net/Commands/User/Karma.cs b/Geekbot.net/Commands/User/Karma.cs index beb1334..39b05be 100644 --- a/Geekbot.net/Commands/User/Karma.cs +++ b/Geekbot.net/Commands/User/Karma.cs @@ -67,7 +67,7 @@ namespace Geekbot.net.Commands.User } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } @@ -114,7 +114,7 @@ namespace Geekbot.net.Commands.User } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } diff --git a/Geekbot.net/Commands/User/Stats.cs b/Geekbot.net/Commands/User/Stats.cs index 990b229..4d4d800 100644 --- a/Geekbot.net/Commands/User/Stats.cs +++ b/Geekbot.net/Commands/User/Stats.cs @@ -80,7 +80,7 @@ namespace Geekbot.net.Commands.User } catch (Exception e) { - _errorHandler.HandleCommandException(e, Context); + await _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 6e857bf..68a1870 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -38,7 +38,7 @@ - + diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index 0331ca9..9811432 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -25,8 +25,8 @@ namespace Geekbot.net private readonly CommandService _commands; private readonly IUserRepository _userRepository; private readonly IReactionListener _reactionListener; - - public Handlers(DatabaseContext database, IDiscordClient client, IGeekbotLogger logger, IAlmostRedis redis, + + public Handlers(DatabaseContext database, IDiscordClient client, IGeekbotLogger logger, IAlmostRedis redis, IServiceProvider servicesProvider, CommandService commands, IUserRepository userRepository, IReactionListener reactionListener) { @@ -39,11 +39,11 @@ namespace Geekbot.net _userRepository = userRepository; _reactionListener = reactionListener; } - + // // Incoming Messages // - + public Task RunCommand(SocketMessage messageParam) { try @@ -51,33 +51,31 @@ namespace Geekbot.net if (!(messageParam is SocketUserMessage message)) return Task.CompletedTask; if (message.Author.IsBot) return Task.CompletedTask; var argPos = 0; - + // ToDo: remove // if (!message.Author.Id.Equals(93061333972455424)) return Task.CompletedTask; - + var lowCaseMsg = message.ToString().ToLower(); if (lowCaseMsg.StartsWith("hui")) { - var hasPing = _database.GuildSettings.FirstOrDefault(guild => - guild.GuildId.Equals(((SocketGuildChannel) message.Channel).Guild.Id.AsLong())) - ?.Hui ?? false; + var hasPing = _database.GuildSettings.FirstOrDefault(guild => guild.GuildId.Equals(((SocketGuildChannel) message.Channel).Guild.Id.AsLong()))?.Hui ?? false; if (hasPing) { message.Channel.SendMessageAsync("hui!!!"); return Task.CompletedTask; } } + if (lowCaseMsg.StartsWith("ping ") || lowCaseMsg.Equals("ping")) { - var hasPing = _database.GuildSettings.FirstOrDefault(guild => - guild.GuildId.Equals(((SocketGuildChannel) message.Channel).Guild.Id.AsLong())) - ?.Ping ?? false; + var hasPing = _database.GuildSettings.FirstOrDefault(guild => guild.GuildId.Equals(((SocketGuildChannel) message.Channel).Guild.Id.AsLong()))?.Ping ?? false; if (hasPing) { message.Channel.SendMessageAsync("pong"); - return Task.CompletedTask; + return Task.CompletedTask; } } + if (!(message.HasCharPrefix('!', ref argPos) || message.HasMentionPrefix(_client.CurrentUser, ref argPos))) return Task.CompletedTask; var context = new CommandContext(_client, message); @@ -104,8 +102,9 @@ namespace Geekbot.net _logger.Information(LogSource.Message, $"[DM-Channel] {message.Content}", SimpleConextConverter.ConvertSocketMessage(message)); return; } + var channel = (SocketGuildChannel) message.Channel; - + // await _database.Database.ExecuteSqlCommandAsync("UPDATE \"Messages\" " + // $"SET \"MessageCount\" = \"MessageCount\" + {1} " + // $"WHERE \"GuildId\" = '{channel.Guild.Id.AsLong()}' " + @@ -122,26 +121,25 @@ namespace Geekbot.net _logger.Error(LogSource.Message, "Could not process message stats", e); } } - + // // User Stuff // - + public async Task UserJoined(SocketGuildUser user) { try { if (!user.IsBot) { - var message = _database.GuildSettings.FirstOrDefault(guild => - guild.GuildId.Equals(user.Guild.Id.AsLong())) - ?.WelcomeMessage; + var message = _database.GuildSettings.FirstOrDefault(guild => guild.GuildId.Equals(user.Guild.Id.AsLong()))?.WelcomeMessage; if (!string.IsNullOrEmpty(message)) { message = message.Replace("$user", user.Mention); await user.Guild.DefaultChannel.SendMessageAsync(message); } } + await _userRepository.Update(user); _logger.Information(LogSource.Geekbot, $"{user.Username} ({user.Id}) joined {user.Guild.Name} ({user.Guild.Id})"); } @@ -172,13 +170,14 @@ namespace Geekbot.net { _logger.Error(LogSource.Geekbot, "Failed to send leave message", e); } + _logger.Information(LogSource.Geekbot, $"{user.Username} ({user.Id}) joined {user.Guild.Name} ({user.Guild.Id})"); } - + // // Message Stuff // - + public async Task MessageDeleted(Cacheable message, ISocketMessageChannel channel) { try @@ -192,14 +191,14 @@ namespace Geekbot.net var sb = new StringBuilder(); if (message.Value != null) { - sb.AppendLine( - $"The following message from {message.Value.Author.Username}#{message.Value.Author.Discriminator} was deleted in <#{channel.Id}>"); + sb.AppendLine($"The following message from {message.Value.Author.Username}#{message.Value.Author.Discriminator} was deleted in <#{channel.Id}>"); sb.AppendLine(message.Value.Content); } else { sb.AppendLine("Someone deleted a message, the message was not cached..."); } + await modChannelSocket.SendMessageAsync(sb.ToString()); } } @@ -208,11 +207,11 @@ namespace Geekbot.net _logger.Error(LogSource.Geekbot, "Failed to send delete message...", e); } } - + // // Reactions // - + public Task ReactionAdded(Cacheable cacheable, ISocketMessageChannel socketMessageChannel, SocketReaction reaction) { if (reaction.User.Value.IsBot) return Task.CompletedTask; @@ -229,4 +228,4 @@ namespace Geekbot.net return Task.CompletedTask; } } -} +} \ No newline at end of file diff --git a/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs index 9556b84..e9ff92c 100644 --- a/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs @@ -52,16 +52,16 @@ namespace Geekbot.net.Lib.ErrorHandling if (!string.IsNullOrEmpty(resStackTrace)) { var maxLen = Math.Min(resStackTrace.Length, 1850); - context.Channel.SendMessageAsync($"{e.Message}\r\n```\r\n{resStackTrace.Substring(0, maxLen)}\r\n```"); + await context.Channel.SendMessageAsync($"{e.Message}\r\n```\r\n{resStackTrace.Substring(0, maxLen)}\r\n```"); } else { - context.Channel.SendMessageAsync(e.Message); + await context.Channel.SendMessageAsync(e.Message); } } else { - context.Channel.SendMessageAsync(errorString); + await context.Channel.SendMessageAsync(errorString); } } @@ -82,7 +82,7 @@ namespace Geekbot.net.Lib.ErrorHandling } catch (Exception ex) { - context.Channel.SendMessageAsync("Something went really really wrong here"); + await context.Channel.SendMessageAsync("Something went really really wrong here"); _logger.Error(LogSource.Geekbot, "Errorception", ex); } } diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 86a3507..3be93c5 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -101,8 +101,8 @@ namespace Geekbot.net { Console.Write("Your bot Token: "); var newToken = Console.ReadLine(); - _globalSettings.SetKey("DiscordToken", newToken); - _globalSettings.SetKey("Game", "Ping Pong"); + await _globalSettings.SetKey("DiscordToken", newToken); + await _globalSettings.SetKey("Game", "Ping Pong"); _token = newToken; } diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 96c170b..58fbfc6 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -7,7 +7,7 @@ - + From 28052a5ba9b5a88ea90028c055878bfde785e29b Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 28 Jul 2018 19:12:50 +0200 Subject: [PATCH 197/553] Update logsource in redis migration --- Geekbot.net/Database/RedisMigration.cs | 94 +++++++++++++------------- Geekbot.net/Lib/Logger/LogSource.cs | 1 + 2 files changed, 48 insertions(+), 47 deletions(-) diff --git a/Geekbot.net/Database/RedisMigration.cs b/Geekbot.net/Database/RedisMigration.cs index 3097a88..07b13b4 100644 --- a/Geekbot.net/Database/RedisMigration.cs +++ b/Geekbot.net/Database/RedisMigration.cs @@ -30,7 +30,7 @@ namespace Geekbot.net.Database public async Task Migrate() { - _logger.Information(LogSource.Geekbot, "Starting migration process"); + _logger.Information(LogSource.Migration, "Starting migration process"); var keys = _redis.GetAllKeys().Where(e => e.ToString().EndsWith("Messages")); var guilds = new List(); @@ -49,17 +49,17 @@ namespace Geekbot.net.Database } } - _logger.Information(LogSource.Geekbot, $"Found {guilds.Count} guilds in redis"); + _logger.Information(LogSource.Migration, $"Found {guilds.Count} guilds in redis"); foreach (var guild in guilds) { if (guild.MemberCount > 10000) { - _logger.Information(LogSource.Geekbot, $"Skipping {guild.Name} because server size is to big ({guild.MemberCount})"); + _logger.Information(LogSource.Migration, $"Skipping {guild.Name} because server size is to big ({guild.MemberCount})"); break; } - _logger.Information(LogSource.Geekbot, $"Start Migration for {guild.Name}"); + _logger.Information(LogSource.Migration, $"Start Migration for {guild.Name}"); #region Quotes /** * Quotes @@ -78,13 +78,13 @@ namespace Geekbot.net.Database } catch (Exception e) { - _logger.Error(LogSource.Geekbot, $"quote failed: {q}", e); + _logger.Error(LogSource.Migration, $"quote failed: {q}", e); } } } catch (Exception e) { - _logger.Error(LogSource.Geekbot, "quote migration failed", e); + _logger.Error(LogSource.Migration, "quote migration failed", e); } #endregion @@ -111,13 +111,13 @@ namespace Geekbot.net.Database } catch (Exception e) { - _logger.Error(LogSource.Geekbot, $"karma failed for: {q.Name}", e); + _logger.Error(LogSource.Migration, $"karma failed for: {q.Name}", e); } } } catch (Exception e) { - _logger.Error(LogSource.Geekbot, "karma migration failed", e); + _logger.Error(LogSource.Migration, "karma migration failed", e); } #endregion @@ -143,13 +143,13 @@ namespace Geekbot.net.Database } catch (Exception e) { - _logger.Error(LogSource.Geekbot, $"Rolls failed for: {q.Name}", e); + _logger.Error(LogSource.Migration, $"Rolls failed for: {q.Name}", e); } } } catch (Exception e) { - _logger.Error(LogSource.Geekbot, "rolls migration failed", e); + _logger.Error(LogSource.Migration, "rolls migration failed", e); } #endregion @@ -177,13 +177,13 @@ namespace Geekbot.net.Database } catch (Exception e) { - _logger.Error(LogSource.Geekbot, $"Slaps failed for: {q.Name}", e); + _logger.Error(LogSource.Migration, $"Slaps failed for: {q.Name}", e); } } } catch (Exception e) { - _logger.Error(LogSource.Geekbot, "Slaps migration failed", e); + _logger.Error(LogSource.Migration, "Slaps migration failed", e); } #endregion @@ -191,32 +191,32 @@ namespace Geekbot.net.Database /** * Messages */ -// try -// { -// var data = _redis.Db.HashGetAll($"{guild.Id}:Messages"); -// foreach (var q in data) -// { -// try -// { -// var user = new MessagesModel() -// { -// GuildId = guild.Id.AsLong(), -// UserId = ulong.Parse(q.Name).AsLong(), -// MessageCount= int.Parse(q.Value) -// }; -// _database.Messages.Add(user); -// await _database.SaveChangesAsync(); -// } -// catch (Exception e) -// { -// _logger.Error(LogSource.Geekbot, $"Messages failed for: {q.Name}", e); -// } -// } -// } -// catch (Exception e) -// { -// _logger.Error(LogSource.Geekbot, "Messages migration failed", e); -// } + /*try + { + var data = _redis.Db.HashGetAll($"{guild.Id}:Messages"); + foreach (var q in data) + { + try + { + var user = new MessagesModel() + { + GuildId = guild.Id.AsLong(), + UserId = ulong.Parse(q.Name).AsLong(), + MessageCount= int.Parse(q.Value) + }; + _database.Messages.Add(user); + await _database.SaveChangesAsync(); + } + catch (Exception e) + { + _logger.Error(LogSource.Migration, $"Messages failed for: {q.Name}", e); + } + } + } + catch (Exception e) + { + _logger.Error(LogSource.Migration, "Messages migration failed", e); + }*/ #endregion #region Ships @@ -245,13 +245,13 @@ namespace Geekbot.net.Database } catch (Exception e) { - _logger.Error(LogSource.Geekbot, $"Ships failed for: {q.Name}", e); + _logger.Error(LogSource.Migration, $"Ships failed for: {q.Name}", e); } } } catch (Exception e) { - _logger.Error(LogSource.Geekbot, "Ships migration failed", e); + _logger.Error(LogSource.Migration, "Ships migration failed", e); } #endregion @@ -298,13 +298,13 @@ namespace Geekbot.net.Database } catch (Exception e) { - _logger.Error(LogSource.Geekbot, $"Setting failed: {setting.Name} - {guild.Id}", e); + _logger.Error(LogSource.Migration, $"Setting failed: {setting.Name} - {guild.Id}", e); } } } catch (Exception e) { - _logger.Error(LogSource.Geekbot, "Settings migration failed", e); + _logger.Error(LogSource.Migration, "Settings migration failed", e); } #endregion @@ -343,13 +343,13 @@ namespace Geekbot.net.Database } catch (Exception e) { - _logger.Error(LogSource.Geekbot, $"User failed: {user.Username}", e); + _logger.Error(LogSource.Migration, $"User failed: {user.Username}", e); } } } catch (Exception e) { - _logger.Error(LogSource.Geekbot, "User migration failed", e); + _logger.Error(LogSource.Migration, "User migration failed", e); } #endregion @@ -369,14 +369,14 @@ namespace Geekbot.net.Database } catch (Exception e) { - _logger.Error(LogSource.Geekbot, $"Guild migration failed: {guild.Name}", e); + _logger.Error(LogSource.Migration, $"Guild migration failed: {guild.Name}", e); } #endregion - _logger.Information(LogSource.Geekbot, $"Finished Migration for {guild.Name}"); + _logger.Information(LogSource.Migration, $"Finished Migration for {guild.Name}"); await Task.Delay(1000); } - _logger.Information(LogSource.Geekbot, "Finished migration process"); + _logger.Information(LogSource.Migration, "Finished migration process"); } private QuoteModel CreateQuoteObject(ulong guild, QuoteObjectDto quote) diff --git a/Geekbot.net/Lib/Logger/LogSource.cs b/Geekbot.net/Lib/Logger/LogSource.cs index cccc930..42c1877 100644 --- a/Geekbot.net/Lib/Logger/LogSource.cs +++ b/Geekbot.net/Lib/Logger/LogSource.cs @@ -16,6 +16,7 @@ namespace Geekbot.net.Lib.Logger UserRepository, Command, Api, + Migration, Other } } \ No newline at end of file From 5b56c1822fcec4f3acdf0582e5033521b9ac4661 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 25 Aug 2018 21:30:33 +0200 Subject: [PATCH 198/553] Updates to language handler --- .../Lib/Localization/TranslationHandler.cs | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/Geekbot.net/Lib/Localization/TranslationHandler.cs b/Geekbot.net/Lib/Localization/TranslationHandler.cs index 88e518e..b1f6e53 100644 --- a/Geekbot.net/Lib/Localization/TranslationHandler.cs +++ b/Geekbot.net/Lib/Localization/TranslationHandler.cs @@ -18,8 +18,7 @@ namespace Geekbot.net.Lib.Localization private readonly IGeekbotLogger _logger; private readonly Dictionary _serverLanguages; private Dictionary>> _translations; - private List _supportedLanguages; - + public TranslationHandler(DatabaseContext database, IGeekbotLogger logger) { _database = database; @@ -45,30 +44,27 @@ namespace Geekbot.net.Lib.Localization if (!sortedPerLanguage.ContainsKey(lang.Key)) { var commandDict = new Dictionary>(); - var strDict = new Dictionary(); - strDict.Add(str.Key, lang.Value); + var strDict = new Dictionary {{str.Key, lang.Value}}; commandDict.Add(command.Key, strDict); sortedPerLanguage.Add(lang.Key, commandDict); + break; } if (!sortedPerLanguage[lang.Key].ContainsKey(command.Key)) { - var strDict = new Dictionary(); - strDict.Add(str.Key, lang.Value); + var strDict = new Dictionary {{str.Key, lang.Value}}; sortedPerLanguage[lang.Key].Add(command.Key, strDict); + break; } - if (!sortedPerLanguage[lang.Key][command.Key].ContainsKey(str.Key)) - { - sortedPerLanguage[lang.Key][command.Key].Add(str.Key, lang.Value); - } + sortedPerLanguage[lang.Key][command.Key].Add(str.Key, lang.Value); } } } _translations = sortedPerLanguage; - _supportedLanguages = new List(); + SupportedLanguages = new List(); foreach (var lang in sortedPerLanguage) { - _supportedLanguages.Add(lang.Key); + SupportedLanguages.Add(lang.Key); } } catch (Exception e) @@ -101,7 +97,7 @@ namespace Geekbot.net.Lib.Localization } catch (Exception e) { - _logger.Error(LogSource.Geekbot, "Could not get guild langage", e); + _logger.Error(LogSource.Geekbot, "Could not get guild language", e); return "EN"; } } @@ -149,7 +145,7 @@ namespace Geekbot.net.Lib.Localization { try { - if (!_supportedLanguages.Contains(language)) return false; + if (!SupportedLanguages.Contains(language)) return false; var guild = await GetGuild(guildId); guild.Language = language; _database.GuildSettings.Update(guild); @@ -163,7 +159,7 @@ namespace Geekbot.net.Lib.Localization } } - public List SupportedLanguages => _supportedLanguages; + public List SupportedLanguages { get; private set; } private async Task GetGuild(ulong guildId) { From 8a62f94e01e7530d8247fbe683843c48f19cb6ad Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 25 Aug 2018 22:40:02 +0200 Subject: [PATCH 199/553] Revert !stats us pull message count from redis --- Geekbot.net/Commands/User/Stats.cs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/Geekbot.net/Commands/User/Stats.cs b/Geekbot.net/Commands/User/Stats.cs index 4d4d800..baacb36 100644 --- a/Geekbot.net/Commands/User/Stats.cs +++ b/Geekbot.net/Commands/User/Stats.cs @@ -39,18 +39,11 @@ namespace Geekbot.net.Commands.User var age = Math.Floor((DateTime.Now - createdAt).TotalDays); var joinedDayAgo = Math.Floor((DateTime.Now - joinedAt).TotalDays); - var messages = _database.Messages.FirstOrDefault(e => - e.GuildId.Equals(Context.Guild.Id.AsLong()) && - e.UserId.Equals(userInfo.Id.AsLong()))?.MessageCount; - - var guildMessages = _database.Messages - .Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())) - .Select(e => e.MessageCount) - .Sum(); - + var messages = (int) _redis.Db.HashGet($"{Context.Guild.Id}:Messages", userInfo.Id.ToString()); + var guildMessages = (int) _redis.Db.HashGet($"{Context.Guild.Id}:Messages", 0.ToString()); var level = _levelCalc.GetLevel(messages); - var percent = Math.Round((double) (100 * messages) / guildMessages, digits: 2); + var percent = Math.Round((double) (100 * messages) / guildMessages, 2); var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder() From e18a512a9b85feb10872de9da04e6bb8e795bfae Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 25 Aug 2018 23:26:46 +0200 Subject: [PATCH 200/553] Update Migration Script --- Geekbot.net/Database/RedisMigration.cs | 17 +++++++---------- Geekbot.net/Handlers.cs | 3 +-- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/Geekbot.net/Database/RedisMigration.cs b/Geekbot.net/Database/RedisMigration.cs index 07b13b4..92ee555 100644 --- a/Geekbot.net/Database/RedisMigration.cs +++ b/Geekbot.net/Database/RedisMigration.cs @@ -33,7 +33,7 @@ namespace Geekbot.net.Database _logger.Information(LogSource.Migration, "Starting migration process"); var keys = _redis.GetAllKeys().Where(e => e.ToString().EndsWith("Messages")); - var guilds = new List(); + var allGuilds = new List(); foreach (var key in keys) { @@ -41,7 +41,7 @@ namespace Geekbot.net.Database { var g = _client.GetGuild(ulong.Parse(key.ToString().Split(':').First())); Console.WriteLine(g.Name); - guilds.Add(g); + allGuilds.Add(g); } catch (Exception e) { @@ -49,16 +49,12 @@ namespace Geekbot.net.Database } } - _logger.Information(LogSource.Migration, $"Found {guilds.Count} guilds in redis"); + _logger.Information(LogSource.Migration, $"Found {allGuilds.Count} guilds in redis"); + var guilds = allGuilds.FindAll(e => e.MemberCount < 10000); + foreach (var guild in guilds) { - if (guild.MemberCount > 10000) - { - _logger.Information(LogSource.Migration, $"Skipping {guild.Name} because server size is to big ({guild.MemberCount})"); - break; - } - _logger.Information(LogSource.Migration, $"Start Migration for {guild.Name}"); #region Quotes /** @@ -315,7 +311,7 @@ namespace Geekbot.net.Database */ try { - var data = guild.Users; + var data = guild.Users.ToList().FindAll(e => !e.IsBot); foreach (var user in data) { try @@ -325,6 +321,7 @@ namespace Geekbot.net.Database await Task.Delay(100); if (user.Username == null) break; } + var namesSerialized = _redis.Db.HashGet($"User:{user.Id}", "UsedNames").ToString(); var names = namesSerialized != null ? Utf8Json.JsonSerializer.Deserialize(namesSerialized) diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index 9811432..64b3a15 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -183,8 +183,7 @@ namespace Geekbot.net try { var guildSocketData = ((IGuildChannel) channel).Guild; - var guild = _database.GuildSettings.FirstOrDefault(g => - g.GuildId.Equals(guildSocketData.Id.AsLong())); + var guild = _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(guildSocketData.Id.AsLong())); if (guild?.ShowDelete ?? false) { var modChannelSocket = (ISocketMessageChannel) await _client.GetChannelAsync(guild.ModChannel.AsUlong()); From 954de7f8db700a697a9f1baeb0a2297091c82696 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 25 Aug 2018 23:27:44 +0200 Subject: [PATCH 201/553] Revert "Updates to language handler" This reverts commit 5b56c18 --- .../Lib/Localization/TranslationHandler.cs | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/Geekbot.net/Lib/Localization/TranslationHandler.cs b/Geekbot.net/Lib/Localization/TranslationHandler.cs index b1f6e53..88e518e 100644 --- a/Geekbot.net/Lib/Localization/TranslationHandler.cs +++ b/Geekbot.net/Lib/Localization/TranslationHandler.cs @@ -18,7 +18,8 @@ namespace Geekbot.net.Lib.Localization private readonly IGeekbotLogger _logger; private readonly Dictionary _serverLanguages; private Dictionary>> _translations; - + private List _supportedLanguages; + public TranslationHandler(DatabaseContext database, IGeekbotLogger logger) { _database = database; @@ -44,27 +45,30 @@ namespace Geekbot.net.Lib.Localization if (!sortedPerLanguage.ContainsKey(lang.Key)) { var commandDict = new Dictionary>(); - var strDict = new Dictionary {{str.Key, lang.Value}}; + var strDict = new Dictionary(); + strDict.Add(str.Key, lang.Value); commandDict.Add(command.Key, strDict); sortedPerLanguage.Add(lang.Key, commandDict); - break; } if (!sortedPerLanguage[lang.Key].ContainsKey(command.Key)) { - var strDict = new Dictionary {{str.Key, lang.Value}}; + var strDict = new Dictionary(); + strDict.Add(str.Key, lang.Value); sortedPerLanguage[lang.Key].Add(command.Key, strDict); - break; } - sortedPerLanguage[lang.Key][command.Key].Add(str.Key, lang.Value); + if (!sortedPerLanguage[lang.Key][command.Key].ContainsKey(str.Key)) + { + sortedPerLanguage[lang.Key][command.Key].Add(str.Key, lang.Value); + } } } } _translations = sortedPerLanguage; - SupportedLanguages = new List(); + _supportedLanguages = new List(); foreach (var lang in sortedPerLanguage) { - SupportedLanguages.Add(lang.Key); + _supportedLanguages.Add(lang.Key); } } catch (Exception e) @@ -97,7 +101,7 @@ namespace Geekbot.net.Lib.Localization } catch (Exception e) { - _logger.Error(LogSource.Geekbot, "Could not get guild language", e); + _logger.Error(LogSource.Geekbot, "Could not get guild langage", e); return "EN"; } } @@ -145,7 +149,7 @@ namespace Geekbot.net.Lib.Localization { try { - if (!SupportedLanguages.Contains(language)) return false; + if (!_supportedLanguages.Contains(language)) return false; var guild = await GetGuild(guildId); guild.Language = language; _database.GuildSettings.Update(guild); @@ -159,7 +163,7 @@ namespace Geekbot.net.Lib.Localization } } - public List SupportedLanguages { get; private set; } + public List SupportedLanguages => _supportedLanguages; private async Task GetGuild(ulong guildId) { From adb1614177254ba56862ba57967241d1606d0bac Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 26 Aug 2018 00:10:19 +0200 Subject: [PATCH 202/553] Update Deployment Script --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b40a5e5..243ea77 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -41,8 +41,8 @@ deploy: - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null - chmod 700 ~/.ssh script: - - rsync -rav -e "ssh -p 65432" ./Geekbot.net/Binaries/* www-data@31.220.42.224:$DEPPATH - - ssh -p 65432 www-data@31.220.42.224 "sudo systemctl restart geekbot.service" + - rsync -rav -e "ssh -p 65432" ./Geekbot.net/Binaries/* geekbot@172.104.156.220:$DEPPATH + - ssh -p 65432 geekbot@172.104.156.220 "sudo systemctl restart geekbot.service" mirror: stage: deploy From cbe88a1721e20515052c10bad925363d5a6aa053 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 26 Aug 2018 00:31:59 +0200 Subject: [PATCH 203/553] Fix !rank --- Geekbot.net/Commands/User/Ranking/Rank.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Geekbot.net/Commands/User/Ranking/Rank.cs b/Geekbot.net/Commands/User/Ranking/Rank.cs index a2e9891..50ccd51 100644 --- a/Geekbot.net/Commands/User/Ranking/Rank.cs +++ b/Geekbot.net/Commands/User/Ranking/Rank.cs @@ -84,10 +84,11 @@ namespace Geekbot.net.Commands.User.Ranking int guildMessages = 0; if (type == RankType.messages) { - guildMessages = _database.Messages - .Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())) - .Select(e => e.MessageCount) - .Sum(); +// guildMessages = _database.Messages +// .Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())) +// .Select(e => e.MessageCount) +// .Sum(); + guildMessages = (int) _redis.Db.HashGet($"{Context.Guild.Id}:Messages", 0.ToString()); } var highscoreUsers = new Dictionary(); @@ -158,6 +159,7 @@ namespace Geekbot.net.Commands.User.Ranking return _redis.Db .HashGetAll($"{Context.Guild.Id}:Messages").ToDictionary().Take(amount + 1) .Where(user => !user.Key.Equals(0)) + .OrderByDescending(s => s.Value) .ToDictionary(user => ulong.Parse(user.Key), user => int.Parse(user.Value)); } From 707be4abe20d8933dac4fbe326fb125648d99a23 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 26 Aug 2018 12:33:04 +0200 Subject: [PATCH 204/553] Trying to fix !rank again --- Geekbot.net/Commands/User/Ranking/Rank.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Geekbot.net/Commands/User/Ranking/Rank.cs b/Geekbot.net/Commands/User/Ranking/Rank.cs index 50ccd51..8e40f06 100644 --- a/Geekbot.net/Commands/User/Ranking/Rank.cs +++ b/Geekbot.net/Commands/User/Ranking/Rank.cs @@ -157,9 +157,10 @@ namespace Geekbot.net.Commands.User.Ranking // .Take(amount) // .ToDictionary(key => key.UserId.AsUlong(), key => key.MessageCount); return _redis.Db - .HashGetAll($"{Context.Guild.Id}:Messages").ToDictionary().Take(amount + 1) + .HashGetAll($"{Context.Guild.Id}:Messages") .Where(user => !user.Key.Equals(0)) .OrderByDescending(s => s.Value) + .Take(amount) .ToDictionary(user => ulong.Parse(user.Key), user => int.Parse(user.Value)); } From 9dda829cf9824180d096008018aa73c53a79fe79 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 26 Aug 2018 12:43:18 +0200 Subject: [PATCH 205/553] remove nuget caching during CI --- .gitlab-ci.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 243ea77..cd67b30 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,11 +10,6 @@ before_script: build: stage: build image: microsoft/dotnet:2.1.300-sdk-stretch - variables: - NUGET_PACKAGES: "${CI_PROJECT_DIR}/.nugetcache" - cache: - paths: - - .nugetcache artifacts: expire_in: 1h paths: From 00da991dae13abe693897fd652cf14278265e766 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 26 Aug 2018 17:39:01 +0200 Subject: [PATCH 206/553] Update !rank error message --- Geekbot.net/Commands/User/Ranking/Rank.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Geekbot.net/Commands/User/Ranking/Rank.cs b/Geekbot.net/Commands/User/Ranking/Rank.cs index 8e40f06..ce74de3 100644 --- a/Geekbot.net/Commands/User/Ranking/Rank.cs +++ b/Geekbot.net/Commands/User/Ranking/Rank.cs @@ -121,7 +121,7 @@ namespace Geekbot.net.Commands.User.Ranking } } - if (failedToRetrieveUser) replyBuilder.AppendLine(":warning: Couldn't get all userdata\n"); + if (failedToRetrieveUser) replyBuilder.AppendLine(":warning: I couldn't find all usernames. Maybe they left the server?\n"); replyBuilder.AppendLine($":bar_chart: **{type.ToString().CapitalizeFirst()} Highscore for {Context.Guild.Name}**"); var highscorePlace = 1; foreach (var user in highscoreUsers) From 74619a4434051eb319fc76e41dc8f7e082b14007 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 26 Aug 2018 17:54:26 +0200 Subject: [PATCH 207/553] Solve casting issue --- Geekbot.net/Handlers.cs | 2 +- Geekbot.net/Lib/Logger/SimpleConextConverter.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index 64b3a15..0e57d55 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -99,7 +99,7 @@ namespace Geekbot.net if (message == null) return; if (message.Channel.Name.StartsWith('@')) { - _logger.Information(LogSource.Message, $"[DM-Channel] {message.Content}", SimpleConextConverter.ConvertSocketMessage(message)); + _logger.Information(LogSource.Message, $"[DM-Channel] {message.Content}", SimpleConextConverter.ConvertSocketMessage(message, true)); return; } diff --git a/Geekbot.net/Lib/Logger/SimpleConextConverter.cs b/Geekbot.net/Lib/Logger/SimpleConextConverter.cs index 0845cc1..5659896 100644 --- a/Geekbot.net/Lib/Logger/SimpleConextConverter.cs +++ b/Geekbot.net/Lib/Logger/SimpleConextConverter.cs @@ -35,9 +35,9 @@ namespace Geekbot.net.Lib.Logger } }; } - public static MessageDto ConvertSocketMessage(SocketMessage message) + public static MessageDto ConvertSocketMessage(SocketMessage message, bool isPrivate = false) { - var channel = (SocketGuildChannel) message.Channel; + SocketGuildChannel channel = isPrivate ? null : (SocketGuildChannel) message.Channel; return new MessageDto { Message = new MessageDto.MessageContent From d1e9992a8c73e497428226f4c7636969b00a57f2 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 26 Aug 2018 18:05:50 +0200 Subject: [PATCH 208/553] Add default values to guildsettings model --- .../Database/Models/GuildSettingsModel.cs | 28 +++++++++---------- Geekbot.net/Handlers.cs | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Geekbot.net/Database/Models/GuildSettingsModel.cs b/Geekbot.net/Database/Models/GuildSettingsModel.cs index a71aac1..6bc98b1 100644 --- a/Geekbot.net/Database/Models/GuildSettingsModel.cs +++ b/Geekbot.net/Database/Models/GuildSettingsModel.cs @@ -9,21 +9,21 @@ namespace Geekbot.net.Database.Models [Required] public long GuildId { get; set; } - - public bool Ping { get; set; } - - public bool Hui { get; set; } - - public long ModChannel { get; set; } + + public bool Ping { get; set; } = false; + + public bool Hui { get; set; } = false; + + public long ModChannel { get; set; } = 0; public string WelcomeMessage { get; set; } - - public bool ShowDelete { get; set; } - - public bool ShowLeave { get; set; } - - public string WikiLang { get; set; } - - public string Language { get; set; } + + public bool ShowDelete { get; set; } = false; + + public bool ShowLeave { get; set; } = false; + + public string WikiLang { get; set; } = "en"; + + public string Language { get; set; } = "EN"; } } \ No newline at end of file diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index 0e57d55..65a04f4 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -184,7 +184,7 @@ namespace Geekbot.net { var guildSocketData = ((IGuildChannel) channel).Guild; var guild = _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(guildSocketData.Id.AsLong())); - if (guild?.ShowDelete ?? false) + if ((guild?.ShowDelete ?? false) && guild?.ModChannel != 0) { var modChannelSocket = (ISocketMessageChannel) await _client.GetChannelAsync(guild.ModChannel.AsUlong()); var sb = new StringBuilder(); From b0758eb119d0356da7b8e43ba806d02374201d01 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 29 Aug 2018 21:16:01 +0200 Subject: [PATCH 209/553] Create multiple database contexts instead of one --- Geekbot.net/Commands/User/Ranking/Rank.cs | 4 +-- Geekbot.net/Commands/User/Stats.cs | 7 +++++ Geekbot.net/Database/DatabaseInitializer.cs | 6 ++-- Geekbot.net/Handlers.cs | 32 ++++++++++++++------- Geekbot.net/Program.cs | 22 ++++++++------ 5 files changed, 47 insertions(+), 24 deletions(-) diff --git a/Geekbot.net/Commands/User/Ranking/Rank.cs b/Geekbot.net/Commands/User/Ranking/Rank.cs index ce74de3..1bb9f95 100644 --- a/Geekbot.net/Commands/User/Ranking/Rank.cs +++ b/Geekbot.net/Commands/User/Ranking/Rank.cs @@ -158,10 +158,10 @@ namespace Geekbot.net.Commands.User.Ranking // .ToDictionary(key => key.UserId.AsUlong(), key => key.MessageCount); return _redis.Db .HashGetAll($"{Context.Guild.Id}:Messages") - .Where(user => !user.Key.Equals(0)) + .Where(user => !user.Name.Equals(0)) .OrderByDescending(s => s.Value) .Take(amount) - .ToDictionary(user => ulong.Parse(user.Key), user => int.Parse(user.Value)); + .ToDictionary(user => ulong.Parse(user.Name), user => int.Parse(user.Value)); } private Dictionary GetKarmaList(int amount) diff --git a/Geekbot.net/Commands/User/Stats.cs b/Geekbot.net/Commands/User/Stats.cs index baacb36..4ec2148 100644 --- a/Geekbot.net/Commands/User/Stats.cs +++ b/Geekbot.net/Commands/User/Stats.cs @@ -39,6 +39,13 @@ namespace Geekbot.net.Commands.User var age = Math.Floor((DateTime.Now - createdAt).TotalDays); var joinedDayAgo = Math.Floor((DateTime.Now - joinedAt).TotalDays); +// var messages = _database.Messages +// .First(e => e.GuildId.Equals(Context.Guild.Id.AsLong()) && e.UserId.Equals(Context.User.Id.AsLong())) +// .MessageCount; +// var guildMessages = _database.Messages +// .Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())) +// .Select(e => e.MessageCount) +// .Sum(); var messages = (int) _redis.Db.HashGet($"{Context.Guild.Id}:Messages", userInfo.Id.ToString()); var guildMessages = (int) _redis.Db.HashGet($"{Context.Guild.Id}:Messages", 0.ToString()); var level = _levelCalc.GetLevel(messages); diff --git a/Geekbot.net/Database/DatabaseInitializer.cs b/Geekbot.net/Database/DatabaseInitializer.cs index 7ae6cc7..7eff2c6 100644 --- a/Geekbot.net/Database/DatabaseInitializer.cs +++ b/Geekbot.net/Database/DatabaseInitializer.cs @@ -16,9 +16,10 @@ namespace Geekbot.net.Database { _runParameters = runParameters; _logger = logger; + NpgsqlLogManager.Provider = new NpgsqlLoggingProviderAdapter(_logger); } - public DatabaseContext Initzialize() + public DatabaseContext Initialize() { DatabaseContext database = null; try @@ -29,7 +30,6 @@ namespace Geekbot.net.Database } else { - NpgsqlLogManager.Provider = new NpgsqlLoggingProviderAdapter(_logger); database = new SqlDatabase(new SqlConnectionString { Host = _runParameters.DbHost, @@ -39,8 +39,6 @@ namespace Geekbot.net.Database Password = _runParameters.DbPassword }); } - database.Database.EnsureCreated(); - if(!_runParameters.InMemory) database.Database.Migrate(); } catch (Exception e) { diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index 65a04f4..d2e065d 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -6,6 +6,7 @@ using Discord; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Database; +using Geekbot.net.Database.Models; using Geekbot.net.Lib.AlmostRedis; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Logger; @@ -25,12 +26,14 @@ namespace Geekbot.net private readonly CommandService _commands; private readonly IUserRepository _userRepository; private readonly IReactionListener _reactionListener; + private readonly DatabaseContext _messageCounterDatabaseContext; - public Handlers(DatabaseContext database, IDiscordClient client, IGeekbotLogger logger, IAlmostRedis redis, + public Handlers(DatabaseInitializer databaseInitializer, IDiscordClient client, IGeekbotLogger logger, IAlmostRedis redis, IServiceProvider servicesProvider, CommandService commands, IUserRepository userRepository, IReactionListener reactionListener) { - _database = database; + _database = databaseInitializer.Initialize(); + _messageCounterDatabaseContext = databaseInitializer.Initialize(); _client = client; _logger = logger; _redis = redis; @@ -52,9 +55,6 @@ namespace Geekbot.net if (message.Author.IsBot) return Task.CompletedTask; var argPos = 0; - // ToDo: remove -// if (!message.Author.Id.Equals(93061333972455424)) return Task.CompletedTask; - var lowCaseMsg = message.ToString().ToLower(); if (lowCaseMsg.StartsWith("hui")) { @@ -105,11 +105,23 @@ namespace Geekbot.net var channel = (SocketGuildChannel) message.Channel; -// await _database.Database.ExecuteSqlCommandAsync("UPDATE \"Messages\" " + -// $"SET \"MessageCount\" = \"MessageCount\" + {1} " + -// $"WHERE \"GuildId\" = '{channel.Guild.Id.AsLong()}' " + -// $"AND \"UserId\" = '{message.Author.Id.AsLong()}'"); -// +// var rowId = await _messageCounterDatabaseContext.Database.ExecuteSqlCommandAsync( +// "UPDATE \"Messages\" SET \"MessageCount\" = \"MessageCount\" + 1 WHERE \"GuildId\" = {0} AND \"UserId\" = {1}", +// channel.Guild.Id.AsLong(), +// message.Author.Id.AsLong() +// ); +// +// if (rowId == 0) +// { +// _messageCounterDatabaseContext.Messages.Add(new MessagesModel +// { +// UserId = message.Author.Id.AsLong(), +// GuildId = channel.Guild.Id.AsLong(), +// MessageCount = 1 +// }); +// _messageCounterDatabaseContext.SaveChanges(); +// } + await _redis.Db.HashIncrementAsync($"{channel.Guild.Id}:Messages", message.Author.Id.ToString()); await _redis.Db.HashIncrementAsync($"{channel.Guild.Id}:Messages", 0.ToString()); diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 3be93c5..875821f 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -7,6 +7,7 @@ using Discord; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Database; +using Geekbot.net.Database.LoggingAdapter; using Geekbot.net.Lib; using Geekbot.net.Lib.AlmostRedis; using Geekbot.net.Lib.Audio; @@ -20,6 +21,7 @@ using Geekbot.net.Lib.Logger; using Geekbot.net.Lib.Media; using Geekbot.net.Lib.ReactionListener; using Geekbot.net.Lib.UserRepository; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using WikipediaApi; @@ -29,7 +31,7 @@ namespace Geekbot.net { private DiscordSocketClient _client; private CommandService _commands; - private DatabaseContext _database; + private DatabaseInitializer _databaseInitializer; private IGlobalSettings _globalSettings; private IServiceCollection _services; private IServiceProvider _servicesProvider; @@ -82,8 +84,12 @@ namespace Geekbot.net _client.Log += discordLogger.Log; _commands = new CommandService(); - _database = new DatabaseInitializer(runParameters, logger).Initzialize(); - _globalSettings = new GlobalSettings(_database); + _databaseInitializer = new DatabaseInitializer(runParameters, logger); + var database = _databaseInitializer.Initialize(); + database.Database.EnsureCreated(); + if(!_runParameters.InMemory) database.Database.Migrate(); + + _globalSettings = new GlobalSettings(database); try { @@ -108,7 +114,7 @@ namespace Geekbot.net _services = new ServiceCollection(); - _userRepository = new UserRepository(_database, logger); + _userRepository = new UserRepository(_databaseInitializer.Initialize(), logger); var fortunes = new FortunesProvider(logger); var mediaProvider = new MediaProvider(logger); var malClient = new MalClient(_globalSettings, logger); @@ -129,8 +135,8 @@ namespace Geekbot.net _services.AddSingleton(mtgManaConverter); _services.AddSingleton(wikipediaClient); _services.AddSingleton(audioUtils); - _services.AddSingleton(_database); _services.AddSingleton(_globalSettings); + _services.AddTransient((e) => _databaseInitializer.Initialize()); logger.Information(LogSource.Geekbot, "Connecting to Discord"); @@ -152,7 +158,7 @@ namespace Geekbot.net _logger.Information(LogSource.Geekbot, $"Now Connected as {_client.CurrentUser.Username} to {_client.Guilds.Count} Servers"); _logger.Information(LogSource.Geekbot, "Registering Stuff"); - var translationHandler = new TranslationHandler(_database, _logger); + var translationHandler = new TranslationHandler(_databaseInitializer.Initialize(), _logger); var errorHandler = new ErrorHandler(_logger, translationHandler, _runParameters.ExposeErrors); var reactionListener = new ReactionListener(_redis.Db); await _commands.AddModulesAsync(Assembly.GetEntryAssembly()); @@ -163,7 +169,7 @@ namespace Geekbot.net _services.AddSingleton(reactionListener); _servicesProvider = _services.BuildServiceProvider(); - var handlers = new Handlers(_database, _client, _logger, _redis, _servicesProvider, _commands, _userRepository, reactionListener); + var handlers = new Handlers(_databaseInitializer, _client, _logger, _redis, _servicesProvider, _commands, _userRepository, reactionListener); _client.MessageReceived += handlers.RunCommand; _client.MessageReceived += handlers.UpdateStats; @@ -198,7 +204,7 @@ namespace Geekbot.net private Task StartWebApi() { _logger.Information(LogSource.Api, "Starting Webserver"); - WebApi.WebApiStartup.StartWebApi(_logger, _runParameters, _commands, _database); + WebApi.WebApiStartup.StartWebApi(_logger, _runParameters, _commands, _databaseInitializer.Initialize()); return Task.CompletedTask; } } From 5db3187f0d9db435188fb9e6c6eadf4bbd986e2c Mon Sep 17 00:00:00 2001 From: Daan Date: Tue, 28 Aug 2018 20:32:24 +0000 Subject: [PATCH 210/553] Change deployment IP --- .gitlab-ci.yml | 96 +++++++++++++++++++++++++------------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cd67b30..93afe34 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,49 +1,49 @@ -stages: - - build - - deploy - -before_script: - - set -e - - set -u - - set -o pipefail - -build: - stage: build - image: microsoft/dotnet:2.1.300-sdk-stretch - artifacts: - expire_in: 1h - paths: - - Geekbot.net/Binaries/ - script: - - dotnet restore - - dotnet test Tests - - dotnet publish --version-suffix ${CI_COMMIT_SHA:0:8} --configuration Release -o Binaries ./ - -deploy: - stage: deploy - image: instrumentisto/rsync-ssh - only: - - master - dependencies: - - build - environment: - name: Production - url: https://discordapp.com/oauth2/authorize?client_id=171249478546882561&scope=bot&permissions=1416834054 - before_script: - - eval $(ssh-agent -s) - - mkdir -p ~/.ssh - - '[[ -f /.dockerenv ]] && echo -e "Host *\n StrictHostKeyChecking no" > ~/.ssh/config' - - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null - - chmod 700 ~/.ssh - script: - - rsync -rav -e "ssh -p 65432" ./Geekbot.net/Binaries/* geekbot@172.104.156.220:$DEPPATH - - ssh -p 65432 geekbot@172.104.156.220 "sudo systemctl restart geekbot.service" - -mirror: - stage: deploy - image: bravissimolabs/alpine-git:latest - only: - - master - script: - - git push https://runebaas:$TOKEN@github.com/pizzaandcoffee/Geekbot.net.git origin/master:master -f +stages: + - build + - deploy + +before_script: + - set -e + - set -u + - set -o pipefail + +build: + stage: build + image: microsoft/dotnet:2.1.300-sdk-stretch + artifacts: + expire_in: 1h + paths: + - Geekbot.net/Binaries/ + script: + - dotnet restore + - dotnet test Tests + - dotnet publish --version-suffix ${CI_COMMIT_SHA:0:8} --configuration Release -o Binaries ./ + +deploy: + stage: deploy + image: instrumentisto/rsync-ssh + only: + - master + dependencies: + - build + environment: + name: Production + url: https://discordapp.com/oauth2/authorize?client_id=171249478546882561&scope=bot&permissions=1416834054 + before_script: + - eval $(ssh-agent -s) + - mkdir -p ~/.ssh + - '[[ -f /.dockerenv ]] && echo -e "Host *\n StrictHostKeyChecking no" > ~/.ssh/config' + - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null + - chmod 700 ~/.ssh + script: + - rsync -rav -e "ssh -p 65432" ./Geekbot.net/Binaries/* geekbot@192.168.156.175:$DEPPATH + - ssh -p 65432 geekbot@192.168.156.175 "sudo systemctl restart geekbot.service" + +mirror: + stage: deploy + image: bravissimolabs/alpine-git:latest + only: + - master + script: + - git push https://runebaas:$TOKEN@github.com/pizzaandcoffee/Geekbot.net.git origin/master:master -f \ No newline at end of file From 0e06e8544751bf96dbbb65b7b8c0ffa45db24b67 Mon Sep 17 00:00:00 2001 From: Date: Wed, 29 Aug 2018 22:04:27 +0200 Subject: [PATCH 211/553] Change the discord.net release branch --- Geekbot.net/Geekbot.net.csproj | 2 +- Geekbot.net/Lib/Polyfills/UserPolyfillDto.cs | 5 +++++ Geekbot.net/Program.cs | 5 ++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 68a1870..46c1eff 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -21,7 +21,7 @@ - 2.0.0-beta + 2.0.0-beta2-00984 diff --git a/Geekbot.net/Lib/Polyfills/UserPolyfillDto.cs b/Geekbot.net/Lib/Polyfills/UserPolyfillDto.cs index 568bdd7..6d81581 100644 --- a/Geekbot.net/Lib/Polyfills/UserPolyfillDto.cs +++ b/Geekbot.net/Lib/Polyfills/UserPolyfillDto.cs @@ -23,6 +23,11 @@ namespace Geekbot.net.Lib.Polyfills return "https://discordapp.com/assets/6debd47ed13483642cf09e832ed0bc1b.png"; } + public string GetDefaultAvatarUrl() + { + throw new NotImplementedException(); + } + public Task GetOrCreateDMChannelAsync(RequestOptions options = null) { throw new NotImplementedException(); diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 875821f..e2f81b2 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -161,14 +161,13 @@ namespace Geekbot.net var translationHandler = new TranslationHandler(_databaseInitializer.Initialize(), _logger); var errorHandler = new ErrorHandler(_logger, translationHandler, _runParameters.ExposeErrors); var reactionListener = new ReactionListener(_redis.Db); - await _commands.AddModulesAsync(Assembly.GetEntryAssembly()); - _services.AddSingleton(_commands); _services.AddSingleton(errorHandler); _services.AddSingleton(translationHandler); _services.AddSingleton(_client); _services.AddSingleton(reactionListener); _servicesProvider = _services.BuildServiceProvider(); - + await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _servicesProvider); + var handlers = new Handlers(_databaseInitializer, _client, _logger, _redis, _servicesProvider, _commands, _userRepository, reactionListener); _client.MessageReceived += handlers.RunCommand; From 0d0f0550a5937d29402419c001e3adf0ddded170 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 29 Aug 2018 22:20:04 +0200 Subject: [PATCH 212/553] Add source to dotnet restore in ci file --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 93afe34..c5b5573 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -15,7 +15,7 @@ build: paths: - Geekbot.net/Binaries/ script: - - dotnet restore + - dotnet restore -s https://api.nuget.org/v3/index.json -s https://www.myget.org/F/discord-net/api/v3/index.json - dotnet test Tests - dotnet publish --version-suffix ${CI_COMMIT_SHA:0:8} --configuration Release -o Binaries ./ From 449e1e0adceff9fe72379c88634e65adb78bd537 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 29 Aug 2018 22:49:13 +0200 Subject: [PATCH 213/553] Update images in ci file --- .gitlab-ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c5b5573..1a55164 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,7 +9,7 @@ before_script: build: stage: build - image: microsoft/dotnet:2.1.300-sdk-stretch + image: microsoft/dotnet:2.1.401-sdk-stretch artifacts: expire_in: 1h paths: @@ -21,7 +21,7 @@ build: deploy: stage: deploy - image: instrumentisto/rsync-ssh + image: runebaas/rsync-ssh-git only: - master dependencies: @@ -41,7 +41,7 @@ deploy: mirror: stage: deploy - image: bravissimolabs/alpine-git:latest + image: runebaas/rsync-ssh-git only: - master script: From 6a163366ea50b1fcf76024a035e57096c4855c60 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 29 Aug 2018 23:01:10 +0200 Subject: [PATCH 214/553] Start counting messages in postgres --- Geekbot.net/Handlers.cs | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index d2e065d..6dd53d0 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -105,23 +105,24 @@ namespace Geekbot.net var channel = (SocketGuildChannel) message.Channel; -// var rowId = await _messageCounterDatabaseContext.Database.ExecuteSqlCommandAsync( -// "UPDATE \"Messages\" SET \"MessageCount\" = \"MessageCount\" + 1 WHERE \"GuildId\" = {0} AND \"UserId\" = {1}", -// channel.Guild.Id.AsLong(), -// message.Author.Id.AsLong() -// ); -// -// if (rowId == 0) -// { -// _messageCounterDatabaseContext.Messages.Add(new MessagesModel -// { -// UserId = message.Author.Id.AsLong(), -// GuildId = channel.Guild.Id.AsLong(), -// MessageCount = 1 -// }); -// _messageCounterDatabaseContext.SaveChanges(); -// } - + // just testing, redis will remain the source of truth for now + var rowId = await _messageCounterDatabaseContext.Database.ExecuteSqlCommandAsync( + "UPDATE \"Messages\" SET \"MessageCount\" = \"MessageCount\" + 1 WHERE \"GuildId\" = {0} AND \"UserId\" = {1}", + channel.Guild.Id.AsLong(), + message.Author.Id.AsLong() + ); + + if (rowId == 0) + { + _messageCounterDatabaseContext.Messages.Add(new MessagesModel + { + UserId = message.Author.Id.AsLong(), + GuildId = channel.Guild.Id.AsLong(), + MessageCount = 1 + }); + _messageCounterDatabaseContext.SaveChanges(); + } + await _redis.Db.HashIncrementAsync($"{channel.Guild.Id}:Messages", message.Author.Id.ToString()); await _redis.Db.HashIncrementAsync($"{channel.Guild.Id}:Messages", 0.ToString()); From 5a4e710ef9e443091ab95a6e43b912f69cc3d44f Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 2 Sep 2018 21:58:16 +0200 Subject: [PATCH 215/553] NRE fixes in simpleMessageConverter, !urban and errorHandler --- .../Integrations/UbranDictionary/UrbanDictionary.cs | 2 +- Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs | 2 +- Geekbot.net/Lib/Logger/SimpleConextConverter.cs | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs b/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs index 25ab732..4f29f10 100644 --- a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs +++ b/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs @@ -52,7 +52,7 @@ namespace Geekbot.net.Commands.Integrations.UbranDictionary if (!string.IsNullOrEmpty(definition.Example)) eb.AddField("Example", definition.Example ?? "(no example given...)"); if (!string.IsNullOrEmpty(definition.ThumbsUp)) eb.AddInlineField("Upvotes", definition.ThumbsUp); if (!string.IsNullOrEmpty(definition.ThumbsDown)) eb.AddInlineField("Downvotes", definition.ThumbsDown); - if (definitions.Tags.Length > 0) eb.AddField("Tags", string.Join(", ", definitions.Tags)); + if (definitions.Tags?.Length > 0) eb.AddField("Tags", string.Join(", ", definitions.Tags)); await ReplyAsync("", false, eb.Build()); } diff --git a/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs index e9ff92c..8ebee2e 100644 --- a/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs @@ -39,7 +39,7 @@ namespace Geekbot.net.Lib.ErrorHandling { try { - var errorString = errorMessage == "def" ? await _translation.GetString(context.Guild.Id, "errorHandler", "SomethingWentWrong") : errorMessage; + var errorString = errorMessage == "def" ? await _translation.GetString(context.Guild?.Id ?? 0, "errorHandler", "SomethingWentWrong") : errorMessage; var errorObj = SimpleConextConverter.ConvertContext(context); if (e.Message.Contains("50007")) return; if (e.Message.Contains("50013")) return; diff --git a/Geekbot.net/Lib/Logger/SimpleConextConverter.cs b/Geekbot.net/Lib/Logger/SimpleConextConverter.cs index 5659896..8b8b0ed 100644 --- a/Geekbot.net/Lib/Logger/SimpleConextConverter.cs +++ b/Geekbot.net/Lib/Logger/SimpleConextConverter.cs @@ -25,13 +25,13 @@ namespace Geekbot.net.Lib.Logger }, Guild = new MessageDto.IdAndName { - Id = context.Guild.Id.ToString(), - Name = context.Guild.Name + Id = context.Guild?.Id.ToString(), + Name = context.Guild?.Name }, Channel = new MessageDto.IdAndName { - Id = context.Channel.Id.ToString(), - Name = context.Channel.Name + Id = context.Channel?.Id.ToString() ?? context.User.Id.ToString(), + Name = context.Channel?.Name ?? "DM-Channel" } }; } @@ -61,8 +61,8 @@ namespace Geekbot.net.Lib.Logger }, Channel = new MessageDto.IdAndName { - Id = channel?.Id.ToString(), - Name = channel?.Name + Id = channel?.Id.ToString() ?? message.Author.Id.ToString(), + Name = channel?.Name ?? "DM-Channel" } }; } From 0d8c82f8aa501ec7df2552b2e0bcea74614967a4 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 2 Sep 2018 22:42:13 +0200 Subject: [PATCH 216/553] Add Caching to GlobalSettings --- .../Lib/GlobalSettings/GlobalSettings.cs | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/Geekbot.net/Lib/GlobalSettings/GlobalSettings.cs b/Geekbot.net/Lib/GlobalSettings/GlobalSettings.cs index 8a1d0e4..a53bc98 100644 --- a/Geekbot.net/Lib/GlobalSettings/GlobalSettings.cs +++ b/Geekbot.net/Lib/GlobalSettings/GlobalSettings.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Geekbot.net.Database; using Geekbot.net.Database.Models; @@ -8,10 +9,12 @@ namespace Geekbot.net.Lib.GlobalSettings public class GlobalSettings : IGlobalSettings { private readonly DatabaseContext _database; + private Dictionary _cache; public GlobalSettings(DatabaseContext database) { _database = database; + _cache = new Dictionary(); } public async Task SetKey(string keyName, string value) @@ -29,9 +32,9 @@ namespace Geekbot.net.Lib.GlobalSettings await _database.SaveChangesAsync(); return true; } - key.Value = value; _database.Globals.Update(key); + _cache[keyName] = value; await _database.SaveChangesAsync(); return true; } @@ -43,8 +46,17 @@ namespace Geekbot.net.Lib.GlobalSettings public string GetKey(string keyName) { - var key = _database.Globals.FirstOrDefault(k => k.Name.Equals(keyName)); - return key?.Value ?? string.Empty; + var keyValue = ""; + if (string.IsNullOrEmpty(_cache[keyName])) + { + keyValue = _database.Globals.FirstOrDefault(k => k.Name.Equals(keyName))?.Value ?? string.Empty; + _cache[keyName] = keyValue; + } + else + { + keyValue = _cache[keyName]; + } + return keyValue ; } public GlobalsModel GetKeyFull(string keyName) From d4c0899ba9be9e0945f8c8de228877e26551b193 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 2 Sep 2018 23:59:26 +0200 Subject: [PATCH 217/553] Fix dict lookup in globalSettings.cs --- Geekbot.net/Lib/GlobalSettings/GlobalSettings.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Geekbot.net/Lib/GlobalSettings/GlobalSettings.cs b/Geekbot.net/Lib/GlobalSettings/GlobalSettings.cs index a53bc98..685a1e5 100644 --- a/Geekbot.net/Lib/GlobalSettings/GlobalSettings.cs +++ b/Geekbot.net/Lib/GlobalSettings/GlobalSettings.cs @@ -9,7 +9,7 @@ namespace Geekbot.net.Lib.GlobalSettings public class GlobalSettings : IGlobalSettings { private readonly DatabaseContext _database; - private Dictionary _cache; + private readonly Dictionary _cache; public GlobalSettings(DatabaseContext database) { @@ -47,7 +47,7 @@ namespace Geekbot.net.Lib.GlobalSettings public string GetKey(string keyName) { var keyValue = ""; - if (string.IsNullOrEmpty(_cache[keyName])) + if (string.IsNullOrEmpty(_cache.GetValueOrDefault(keyName))) { keyValue = _database.Globals.FirstOrDefault(k => k.Name.Equals(keyName))?.Value ?? string.Empty; _cache[keyName] = keyValue; From 6d3fc46e3450cb95ea81aa2ccb649b26b660715b Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 2 Sep 2018 23:59:41 +0200 Subject: [PATCH 218/553] Add Callback Endpoint to API --- Geekbot.net/Program.cs | 2 +- .../Callback/CallbackController.cs | 55 +++++++++++++++++++ .../Callback/CallbackTokenResponseDto.cs | 11 ++++ Geekbot.net/WebApi/WebApiStartup.cs | 6 +- 4 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 Geekbot.net/WebApi/Controllers/Callback/CallbackController.cs create mode 100644 Geekbot.net/WebApi/Controllers/Callback/CallbackTokenResponseDto.cs diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index e2f81b2..f2a6291 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -203,7 +203,7 @@ namespace Geekbot.net private Task StartWebApi() { _logger.Information(LogSource.Api, "Starting Webserver"); - WebApi.WebApiStartup.StartWebApi(_logger, _runParameters, _commands, _databaseInitializer.Initialize()); + WebApi.WebApiStartup.StartWebApi(_logger, _runParameters, _commands, _databaseInitializer.Initialize(), _client, _globalSettings); return Task.CompletedTask; } } diff --git a/Geekbot.net/WebApi/Controllers/Callback/CallbackController.cs b/Geekbot.net/WebApi/Controllers/Callback/CallbackController.cs new file mode 100644 index 0000000..58bdb83 --- /dev/null +++ b/Geekbot.net/WebApi/Controllers/Callback/CallbackController.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Threading.Tasks; +using Discord.WebSocket; +using Geekbot.net.Lib.GlobalSettings; +using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json; + +namespace Geekbot.net.WebApi.Controllers.Callback +{ + public class CallbackController : Controller + { + private readonly DiscordSocketClient _client; + private readonly IGlobalSettings _globalSettings; + + public CallbackController(DiscordSocketClient client, IGlobalSettings globalSettings) + { + _client = client; + _globalSettings = globalSettings; + } + + [Route("/callback")] + public async Task DoCallback([FromQuery] string code) + { + var token = ""; + using (var client = new HttpClient()) + { + client.BaseAddress = new Uri("https://discordapp.com"); + var appInfo = await _client.GetApplicationInfoAsync(); + var accessToken = _globalSettings.GetKey("OAuthToken"); + var callbackUrl = _globalSettings.GetKey("OAuthCallbackUrl"); + + var form = new Dictionary(); + form.Add("client_id", appInfo.Id.ToString()); + form.Add("client_secret", accessToken); + form.Add("grant_type", "authorization_code"); + form.Add("code", code); + form.Add("scope", "identify email guilds"); + form.Add("redirect_uri", callbackUrl); + + client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded")); + var result = await client.PostAsync("/api/oauth2/token", new FormUrlEncodedContent(form)); + result.EnsureSuccessStatusCode(); + + var stringResponse = await result.Content.ReadAsStringAsync(); + var responseData = JsonConvert.DeserializeObject(stringResponse); + token = responseData.access_token; + } + + return new RedirectResult($"https://geekbot.pizzaandcoffee.rocks/login?token={token}", false); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/WebApi/Controllers/Callback/CallbackTokenResponseDto.cs b/Geekbot.net/WebApi/Controllers/Callback/CallbackTokenResponseDto.cs new file mode 100644 index 0000000..3c81592 --- /dev/null +++ b/Geekbot.net/WebApi/Controllers/Callback/CallbackTokenResponseDto.cs @@ -0,0 +1,11 @@ +namespace Geekbot.net.WebApi.Controllers.Callback +{ + public class CallbackTokenResponseDto + { + public string access_token { get; set; } + public string token_type { get; set; } + public int expires_in { get; set; } + public string refresh_token { get; set; } + public string scope { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/WebApi/WebApiStartup.cs b/Geekbot.net/WebApi/WebApiStartup.cs index e91ff9f..e93a8d5 100644 --- a/Geekbot.net/WebApi/WebApiStartup.cs +++ b/Geekbot.net/WebApi/WebApiStartup.cs @@ -1,8 +1,10 @@ using System.Net; using System.Reflection; using Discord.Commands; +using Discord.WebSocket; using Geekbot.net.Database; using Geekbot.net.Lib; +using Geekbot.net.Lib.GlobalSettings; using Geekbot.net.Lib.Logger; using Geekbot.net.WebApi.Logging; using Microsoft.AspNetCore; @@ -16,7 +18,7 @@ namespace Geekbot.net.WebApi public static class WebApiStartup { public static void StartWebApi(IGeekbotLogger logger, RunParameters runParameters, CommandService commandService, - DatabaseContext databaseContext) + DatabaseContext databaseContext, DiscordSocketClient client, IGlobalSettings globalSettings) { WebHost.CreateDefaultBuilder() .UseKestrel(options => @@ -28,6 +30,8 @@ namespace Geekbot.net.WebApi services.AddMvc(); services.AddSingleton(commandService); services.AddSingleton(databaseContext); + services.AddSingleton(client); + services.AddSingleton(globalSettings); services.AddCors(options => { options.AddPolicy("AllowSpecificOrigin", From a8c91c03723ee78f83a287d5c658c130203c8702 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 5 Sep 2018 21:13:43 +0200 Subject: [PATCH 219/553] Hide owner commands from command endpoint --- Geekbot.net/WebApi/Controllers/Commands/CommandController.cs | 4 ++-- Geekbot.net/WebApi/Controllers/Commands/CommandDto.cs | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Geekbot.net/WebApi/Controllers/Commands/CommandController.cs b/Geekbot.net/WebApi/Controllers/Commands/CommandController.cs index 04caaae..74f6e3c 100644 --- a/Geekbot.net/WebApi/Controllers/Commands/CommandController.cs +++ b/Geekbot.net/WebApi/Controllers/Commands/CommandController.cs @@ -32,10 +32,10 @@ namespace Geekbot.net.WebApi.Controllers.Commands Name = cmd.Name, Summary = cmd.Summary, IsAdminCommand = param.Contains("admin") || param.Contains("owner"), - Aliases = cmd.Aliases.ToArray(), + Aliases = cmd.Aliases.ToList(), Params = cmdParamsObj }).ToList(); - return Ok(commandList); + return Ok(commandList.FindAll(e => !e.Aliases[0].StartsWith("owner"))); } } } \ No newline at end of file diff --git a/Geekbot.net/WebApi/Controllers/Commands/CommandDto.cs b/Geekbot.net/WebApi/Controllers/Commands/CommandDto.cs index 50f7872..68c4e74 100644 --- a/Geekbot.net/WebApi/Controllers/Commands/CommandDto.cs +++ b/Geekbot.net/WebApi/Controllers/Commands/CommandDto.cs @@ -6,10 +6,9 @@ namespace Geekbot.net.WebApi.Controllers.Commands public class CommandDto { public string Name { get; set; } - public string Category { get; set; } public string Summary { get; set; } public bool IsAdminCommand { get; set; } - public Array Aliases { get; set; } + public List Aliases { get; set; } public List Params { get; set; } } } \ No newline at end of file From fce6be56e29422263c7a113236e0f5f4f1158914 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 5 Sep 2018 21:15:13 +0200 Subject: [PATCH 220/553] Add Message migration script --- .../Commands/Admin/Owner/MigrationMethods.cs | 8 ++ .../Commands/Admin/{ => Owner}/Owner.cs | 49 ++++++++----- Geekbot.net/Commands/User/Ranking/Rank.cs | 20 ++--- Geekbot.net/Commands/User/Stats.cs | 18 ++--- Geekbot.net/Database/MessageMigration.cs | 73 +++++++++++++++++++ 5 files changed, 132 insertions(+), 36 deletions(-) create mode 100644 Geekbot.net/Commands/Admin/Owner/MigrationMethods.cs rename Geekbot.net/Commands/Admin/{ => Owner}/Owner.cs (68%) create mode 100644 Geekbot.net/Database/MessageMigration.cs diff --git a/Geekbot.net/Commands/Admin/Owner/MigrationMethods.cs b/Geekbot.net/Commands/Admin/Owner/MigrationMethods.cs new file mode 100644 index 0000000..6f50257 --- /dev/null +++ b/Geekbot.net/Commands/Admin/Owner/MigrationMethods.cs @@ -0,0 +1,8 @@ +namespace Geekbot.net.Commands.Admin.Owner +{ + public enum MigrationMethods + { + redis, + messages + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Admin/Owner.cs b/Geekbot.net/Commands/Admin/Owner/Owner.cs similarity index 68% rename from Geekbot.net/Commands/Admin/Owner.cs rename to Geekbot.net/Commands/Admin/Owner/Owner.cs index 7cc194b..b02ee47 100644 --- a/Geekbot.net/Commands/Admin/Owner.cs +++ b/Geekbot.net/Commands/Admin/Owner/Owner.cs @@ -9,7 +9,7 @@ using Geekbot.net.Lib.GlobalSettings; using Geekbot.net.Lib.Logger; using Geekbot.net.Lib.UserRepository; -namespace Geekbot.net.Commands.Admin +namespace Geekbot.net.Commands.Admin.Owner { [Group("owner")] [RequireOwner] @@ -35,27 +35,42 @@ namespace Geekbot.net.Commands.Admin } [Command("migrate", RunMode = RunMode.Async)] - public async Task Migrate(string force = "") + public async Task Migrate(MigrationMethods method, string force = "") { try { - var status = _globalSettings.GetKey("MigrationStatus"); - if (status.Equals("Running")) + switch (method) { - await ReplyAsync("Migration already running"); - return; - } - if (status.Equals("Done") && !force.Equals("force")) - { - await ReplyAsync("Migration already ran, write `!owner migrate force` to run again"); - return; - } + case MigrationMethods.redis: + var status = _globalSettings.GetKey("MigrationStatus"); + if (status.Equals("Running")) + { + await ReplyAsync("Migration already running"); + return; + } + if (status.Equals("Done") && !force.Equals("force")) + { + await ReplyAsync("Migration already ran, write `!owner migrate redis force` to run again"); + return; + } - await ReplyAsync("starting migration"); - await _globalSettings.SetKey("MigrationStatus", "Running"); - var redisMigration = new RedisMigration(_database, _redis, _logger, _client); - await redisMigration.Migrate(); - await _globalSettings.SetKey("MigrationStatus", "Done"); + await ReplyAsync("starting migration"); + await _globalSettings.SetKey("MigrationStatus", "Running"); + var redisMigration = new RedisMigration(_database, _redis, _logger, _client); + await redisMigration.Migrate(); + await _globalSettings.SetKey("MigrationStatus", "Done"); + break; + + case MigrationMethods.messages: + await ReplyAsync("Migrating Messages to postgres..."); + var messageMigration = new MessageMigration(_database, _redis, _logger); + await messageMigration.Migrate(); + break; + + default: + await ReplyAsync("No Migration Method specified..."); + break; + } } catch (Exception e) { diff --git a/Geekbot.net/Commands/User/Ranking/Rank.cs b/Geekbot.net/Commands/User/Ranking/Rank.cs index 1bb9f95..08fd384 100644 --- a/Geekbot.net/Commands/User/Ranking/Rank.cs +++ b/Geekbot.net/Commands/User/Ranking/Rank.cs @@ -151,17 +151,17 @@ namespace Geekbot.net.Commands.User.Ranking private Dictionary GetMessageList(int amount) { -// return _database.Messages -// .Where(k => k.GuildId.Equals(Context.Guild.Id.AsLong())) -// .OrderByDescending(o => o.MessageCount) -// .Take(amount) -// .ToDictionary(key => key.UserId.AsUlong(), key => key.MessageCount); - return _redis.Db - .HashGetAll($"{Context.Guild.Id}:Messages") - .Where(user => !user.Name.Equals(0)) - .OrderByDescending(s => s.Value) + return _database.Messages + .Where(k => k.GuildId.Equals(Context.Guild.Id.AsLong())) + .OrderByDescending(o => o.MessageCount) .Take(amount) - .ToDictionary(user => ulong.Parse(user.Name), user => int.Parse(user.Value)); + .ToDictionary(key => key.UserId.AsUlong(), key => key.MessageCount); +// return _redis.Db +// .HashGetAll($"{Context.Guild.Id}:Messages") +// .Where(user => !user.Name.Equals(0)) +// .OrderByDescending(s => s.Value) +// .Take(amount) +// .ToDictionary(user => ulong.Parse(user.Name), user => int.Parse(user.Value)); } private Dictionary GetKarmaList(int amount) diff --git a/Geekbot.net/Commands/User/Stats.cs b/Geekbot.net/Commands/User/Stats.cs index 4ec2148..4468b21 100644 --- a/Geekbot.net/Commands/User/Stats.cs +++ b/Geekbot.net/Commands/User/Stats.cs @@ -39,15 +39,15 @@ namespace Geekbot.net.Commands.User var age = Math.Floor((DateTime.Now - createdAt).TotalDays); var joinedDayAgo = Math.Floor((DateTime.Now - joinedAt).TotalDays); -// var messages = _database.Messages -// .First(e => e.GuildId.Equals(Context.Guild.Id.AsLong()) && e.UserId.Equals(Context.User.Id.AsLong())) -// .MessageCount; -// var guildMessages = _database.Messages -// .Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())) -// .Select(e => e.MessageCount) -// .Sum(); - var messages = (int) _redis.Db.HashGet($"{Context.Guild.Id}:Messages", userInfo.Id.ToString()); - var guildMessages = (int) _redis.Db.HashGet($"{Context.Guild.Id}:Messages", 0.ToString()); + var messages = _database.Messages + .First(e => e.GuildId.Equals(Context.Guild.Id.AsLong()) && e.UserId.Equals(Context.User.Id.AsLong())) + .MessageCount; + var guildMessages = _database.Messages + .Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())) + .Select(e => e.MessageCount) + .Sum(); +// var messages = (int) _redis.Db.HashGet($"{Context.Guild.Id}:Messages", userInfo.Id.ToString()); +// var guildMessages = (int) _redis.Db.HashGet($"{Context.Guild.Id}:Messages", 0.ToString()); var level = _levelCalc.GetLevel(messages); var percent = Math.Round((double) (100 * messages) / guildMessages, 2); diff --git a/Geekbot.net/Database/MessageMigration.cs b/Geekbot.net/Database/MessageMigration.cs new file mode 100644 index 0000000..ed07072 --- /dev/null +++ b/Geekbot.net/Database/MessageMigration.cs @@ -0,0 +1,73 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Geekbot.net.Database.Models; +using Geekbot.net.Lib.AlmostRedis; +using Geekbot.net.Lib.Extensions; +using Geekbot.net.Lib.Logger; + +namespace Geekbot.net.Database +{ + public class MessageMigration + { + private readonly DatabaseContext _database; + private readonly IAlmostRedis _redis; + private readonly IGeekbotLogger _logger; + + public MessageMigration(DatabaseContext database, IAlmostRedis redis, IGeekbotLogger logger) + { + _database = database; + _redis = redis; + _logger = logger; + } + + public async Task Migrate() + { + _logger.Warning(LogSource.Migration, "Starting message migration"); + try + { + var messageKeys = _redis.GetAllKeys().Where(e => e.ToString().EndsWith("Messages")); + foreach (var keyName in messageKeys) + { + try + { + var guildId = ulong.Parse(keyName.ToString().Split(':').FirstOrDefault()); + var guildUsers = _redis.Db.HashGetAll(keyName); + foreach (var user in guildUsers) + { + try + { + var userId = ulong.Parse(user.Name); + if (userId != 0) + { + var userMessages = int.Parse(user.Value); + _database.Messages.Add(new MessagesModel + { + UserId = userId.AsLong(), + GuildId = guildId.AsLong(), + MessageCount = userMessages + }); + } + } + catch (Exception e) + { + _logger.Error(LogSource.Migration, $"Failed to add record for a user in {guildId}", e); + } + } + + await _database.SaveChangesAsync(); + } + catch (Exception e) + { + _logger.Error(LogSource.Migration, "Failed to determinate guild", e); + } + } + _logger.Warning(LogSource.Migration, "Successfully finished message migration"); + } + catch (Exception e) + { + _logger.Error(LogSource.Migration, "Message migration failed", e); + } + } + } +} \ No newline at end of file From f0814ba6853b539d2c33e877b953dc0a426c7e4c Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 5 Sep 2018 21:15:46 +0200 Subject: [PATCH 221/553] Temporally disable message counting --- Geekbot.net/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index f2a6291..2c2e6ce 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -171,7 +171,7 @@ namespace Geekbot.net var handlers = new Handlers(_databaseInitializer, _client, _logger, _redis, _servicesProvider, _commands, _userRepository, reactionListener); _client.MessageReceived += handlers.RunCommand; - _client.MessageReceived += handlers.UpdateStats; +// _client.MessageReceived += handlers.UpdateStats; _client.MessageDeleted += handlers.MessageDeleted; _client.UserJoined += handlers.UserJoined; _client.UserUpdated += handlers.UserUpdated; From a5c70859a432431d4246525f27d8bcc809ef32e1 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 5 Sep 2018 21:22:56 +0200 Subject: [PATCH 222/553] Reenable Stats Counting --- Geekbot.net/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 2c2e6ce..f2a6291 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -171,7 +171,7 @@ namespace Geekbot.net var handlers = new Handlers(_databaseInitializer, _client, _logger, _redis, _servicesProvider, _commands, _userRepository, reactionListener); _client.MessageReceived += handlers.RunCommand; -// _client.MessageReceived += handlers.UpdateStats; + _client.MessageReceived += handlers.UpdateStats; _client.MessageDeleted += handlers.MessageDeleted; _client.UserJoined += handlers.UserJoined; _client.UserUpdated += handlers.UserUpdated; From 99245b9ead0add5fd861216e6c2a5d5925f4984d Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 5 Sep 2018 22:55:45 +0200 Subject: [PATCH 223/553] Refactor !rank, add HighscoreManager and add /v1/highscore to the api --- Geekbot.net/Commands/User/Ranking/Rank.cs | 112 +++--------------- Geekbot.net/Commands/User/Ranking/RankType.cs | 9 -- Geekbot.net/Database/RedisMigration.cs | 2 +- .../Highscores/HighscoreListEmptyException.cs | 13 ++ .../Lib/Highscores/HighscoreManager.cs | 106 +++++++++++++++++ Geekbot.net/Lib/Highscores/HighscoreTypes.cs | 9 ++ .../Highscores/HighscoreUserDto.cs} | 5 +- .../Lib/Highscores/IHighscoreManager.cs | 12 ++ Geekbot.net/Lib/Logger/LogSource.cs | 1 + Geekbot.net/Program.cs | 7 +- Geekbot.net/WebApi/ApiError.cs | 7 ++ .../Highscores/HighscoreController.cs | 56 +++++++++ .../HighscoreControllerPostBodyDto.cs | 16 +++ .../HighscoreControllerReponseBody.cs | 11 ++ Geekbot.net/WebApi/WebApiStartup.cs | 4 +- 15 files changed, 261 insertions(+), 109 deletions(-) delete mode 100644 Geekbot.net/Commands/User/Ranking/RankType.cs create mode 100644 Geekbot.net/Lib/Highscores/HighscoreListEmptyException.cs create mode 100644 Geekbot.net/Lib/Highscores/HighscoreManager.cs create mode 100644 Geekbot.net/Lib/Highscores/HighscoreTypes.cs rename Geekbot.net/{Commands/User/Ranking/RankUserDto.cs => Lib/Highscores/HighscoreUserDto.cs} (54%) create mode 100644 Geekbot.net/Lib/Highscores/IHighscoreManager.cs create mode 100644 Geekbot.net/WebApi/ApiError.cs create mode 100644 Geekbot.net/WebApi/Controllers/Highscores/HighscoreController.cs create mode 100644 Geekbot.net/WebApi/Controllers/Highscores/HighscoreControllerPostBodyDto.cs create mode 100644 Geekbot.net/WebApi/Controllers/Highscores/HighscoreControllerReponseBody.cs diff --git a/Geekbot.net/Commands/User/Ranking/Rank.cs b/Geekbot.net/Commands/User/Ranking/Rank.cs index 08fd384..9c37a4a 100644 --- a/Geekbot.net/Commands/User/Ranking/Rank.cs +++ b/Geekbot.net/Commands/User/Ranking/Rank.cs @@ -5,31 +5,30 @@ using System.Text; using System.Threading.Tasks; using Discord.Commands; using Geekbot.net.Database; -using Geekbot.net.Lib.AlmostRedis; using Geekbot.net.Lib.Converters; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; +using Geekbot.net.Lib.Highscores; using Geekbot.net.Lib.UserRepository; -using StackExchange.Redis; namespace Geekbot.net.Commands.User.Ranking { public class Rank : ModuleBase { private readonly IEmojiConverter _emojiConverter; + private readonly IHighscoreManager _highscoreManager; private readonly IErrorHandler _errorHandler; private readonly DatabaseContext _database; private readonly IUserRepository _userRepository; - private readonly IAlmostRedis _redis; public Rank(DatabaseContext database, IErrorHandler errorHandler, IUserRepository userRepository, - IEmojiConverter emojiConverter, IAlmostRedis redis) + IEmojiConverter emojiConverter, IHighscoreManager highscoreManager) { _database = database; _errorHandler = errorHandler; _userRepository = userRepository; _emojiConverter = emojiConverter; - _redis = redis; + _highscoreManager = highscoreManager; } [Command("rank", RunMode = RunMode.Async)] @@ -38,10 +37,10 @@ namespace Geekbot.net.Commands.User.Ranking { try { - RankType type; + HighscoreTypes type; try { - type = Enum.Parse(typeUnformated.ToLower()); + type = Enum.Parse(typeUnformated.ToLower()); } catch { @@ -49,7 +48,6 @@ namespace Geekbot.net.Commands.User.Ranking return; } - var replyBuilder = new StringBuilder(); if (amount > 20) { @@ -57,69 +55,28 @@ namespace Geekbot.net.Commands.User.Ranking amount = 20; } - Dictionary list; - - switch (type) + var guildId = Context.Guild.Id; + Dictionary highscoreUsers; + try { - case RankType.messages: - list = GetMessageList(amount); - break; - case RankType.karma: - list = GetKarmaList(amount); - break; - case RankType.rolls: - list = GetRollsList(amount); - break; - default: - await ReplyAsync("Valid types are '`messages`' '`karma`', '`rolls`'"); - return; + highscoreUsers = _highscoreManager.GetHighscoresWithUserData(type, guildId, amount); } - - if (!list.Any()) + catch (HighscoreListEmptyException) { await ReplyAsync($"No {type} found on this server"); return; } int guildMessages = 0; - if (type == RankType.messages) + if (type == HighscoreTypes.messages) { -// guildMessages = _database.Messages -// .Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())) -// .Select(e => e.MessageCount) -// .Sum(); - guildMessages = (int) _redis.Db.HashGet($"{Context.Guild.Id}:Messages", 0.ToString()); + guildMessages = _database.Messages + .Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())) + .Select(e => e.MessageCount) + .Sum(); } - var highscoreUsers = new Dictionary(); - var failedToRetrieveUser = false; - foreach (var user in list) - { - try - { - var guildUser = _userRepository.Get(user.Key); - if (guildUser?.Username != null) - { - highscoreUsers.Add(new RankUserDto - { - Username = guildUser.Username, - Discriminator = guildUser.Discriminator - }, user.Value); - } - else - { - highscoreUsers.Add(new RankUserDto - { - Id = user.Key.ToString() - }, user.Value); - failedToRetrieveUser = true; - } - } - catch - { - // ignore - } - } + var failedToRetrieveUser = highscoreUsers.Any(e => string.IsNullOrEmpty(e.Key.Username)); if (failedToRetrieveUser) replyBuilder.AppendLine(":warning: I couldn't find all usernames. Maybe they left the server?\n"); replyBuilder.AppendLine($":bar_chart: **{type.ToString().CapitalizeFirst()} Highscore for {Context.Guild.Name}**"); @@ -134,7 +91,7 @@ namespace Geekbot.net.Commands.User.Ranking ? $"**{user.Key.Username}#{user.Key.Discriminator}**" : $"**{user.Key.Id}**"); - replyBuilder.Append(type == RankType.messages + replyBuilder.Append(type == HighscoreTypes.messages ? $" - {user.Value} {type} - {Math.Round((double) (100 * user.Value) / guildMessages, digits: 2)}%\n" : $" - {user.Value} {type}\n"); @@ -148,38 +105,5 @@ namespace Geekbot.net.Commands.User.Ranking await _errorHandler.HandleCommandException(e, Context); } } - - private Dictionary GetMessageList(int amount) - { - return _database.Messages - .Where(k => k.GuildId.Equals(Context.Guild.Id.AsLong())) - .OrderByDescending(o => o.MessageCount) - .Take(amount) - .ToDictionary(key => key.UserId.AsUlong(), key => key.MessageCount); -// return _redis.Db -// .HashGetAll($"{Context.Guild.Id}:Messages") -// .Where(user => !user.Name.Equals(0)) -// .OrderByDescending(s => s.Value) -// .Take(amount) -// .ToDictionary(user => ulong.Parse(user.Name), user => int.Parse(user.Value)); - } - - private Dictionary GetKarmaList(int amount) - { - return _database.Karma - .Where(k => k.GuildId.Equals(Context.Guild.Id.AsLong())) - .OrderByDescending(o => o.Karma) - .Take(amount) - .ToDictionary(key => key.UserId.AsUlong(), key => key.Karma); - } - - private Dictionary GetRollsList(int amount) - { - return _database.Rolls - .Where(k => k.GuildId.Equals(Context.Guild.Id.AsLong())) - .OrderByDescending(o => o.Rolls) - .Take(amount) - .ToDictionary(key => key.UserId.AsUlong(), key => key.Rolls); - } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/User/Ranking/RankType.cs b/Geekbot.net/Commands/User/Ranking/RankType.cs deleted file mode 100644 index 1e88ef0..0000000 --- a/Geekbot.net/Commands/User/Ranking/RankType.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Geekbot.net.Commands.User.Ranking -{ - public enum RankType - { - messages, - karma, - rolls - } -} \ No newline at end of file diff --git a/Geekbot.net/Database/RedisMigration.cs b/Geekbot.net/Database/RedisMigration.cs index 92ee555..74d97d2 100644 --- a/Geekbot.net/Database/RedisMigration.cs +++ b/Geekbot.net/Database/RedisMigration.cs @@ -43,7 +43,7 @@ namespace Geekbot.net.Database Console.WriteLine(g.Name); allGuilds.Add(g); } - catch (Exception e) + catch (Exception) { // ignore } diff --git a/Geekbot.net/Lib/Highscores/HighscoreListEmptyException.cs b/Geekbot.net/Lib/Highscores/HighscoreListEmptyException.cs new file mode 100644 index 0000000..8c05ca9 --- /dev/null +++ b/Geekbot.net/Lib/Highscores/HighscoreListEmptyException.cs @@ -0,0 +1,13 @@ +using System; + +namespace Geekbot.net.Lib.Highscores +{ + public class HighscoreListEmptyException : Exception + { + public HighscoreListEmptyException() {} + + public HighscoreListEmptyException(string message) : base(message) {} + + public HighscoreListEmptyException(string message, Exception inner) : base(message, inner) {} + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Highscores/HighscoreManager.cs b/Geekbot.net/Lib/Highscores/HighscoreManager.cs new file mode 100644 index 0000000..c684254 --- /dev/null +++ b/Geekbot.net/Lib/Highscores/HighscoreManager.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Geekbot.net.Database; +using Geekbot.net.Lib.Extensions; +using Geekbot.net.Lib.Logger; +using Geekbot.net.Lib.UserRepository; + +namespace Geekbot.net.Lib.Highscores +{ + public class HighscoreManager : IHighscoreManager + { + private readonly DatabaseContext _database; + private readonly IUserRepository _userRepository; + + public HighscoreManager(DatabaseContext databaseContext, IUserRepository userRepository) + { + _database = databaseContext; + _userRepository = userRepository; + + } + + public Dictionary GetHighscoresWithUserData(HighscoreTypes type, ulong guildId, int amount) + { + Dictionary list; + switch (type) + { + case HighscoreTypes.messages: + list = GetMessageList(guildId, amount); + break; + case HighscoreTypes.karma: + list = GetKarmaList(guildId, amount); + break; + case HighscoreTypes.rolls: + list = GetRollsList(guildId, amount); + break; + default: + list = new Dictionary(); + break; + } + + if (!list.Any()) + { + throw new HighscoreListEmptyException($"No {type} found for guild {guildId}"); + } + + var highscoreUsers = new Dictionary(); + foreach (var user in list) + { + try + { + var guildUser = _userRepository.Get(user.Key); + if (guildUser?.Username != null) + { + highscoreUsers.Add(new HighscoreUserDto + { + Username = guildUser.Username, + Discriminator = guildUser.Discriminator, + Avatar = guildUser.AvatarUrl + }, user.Value); + } + else + { + highscoreUsers.Add(new HighscoreUserDto + { + Id = user.Key.ToString() + }, user.Value); + } + } + catch + { + // ignore + } + } + + return highscoreUsers; + } + + public Dictionary GetMessageList(ulong guildId, int amount) + { + return _database.Messages + .Where(k => k.GuildId.Equals(guildId.AsLong())) + .OrderByDescending(o => o.MessageCount) + .Take(amount) + .ToDictionary(key => key.UserId.AsUlong(), key => key.MessageCount); + } + + public Dictionary GetKarmaList(ulong guildId, int amount) + { + return _database.Karma + .Where(k => k.GuildId.Equals(guildId.AsLong())) + .OrderByDescending(o => o.Karma) + .Take(amount) + .ToDictionary(key => key.UserId.AsUlong(), key => key.Karma); + } + + public Dictionary GetRollsList(ulong guildId, int amount) + { + return _database.Rolls + .Where(k => k.GuildId.Equals(guildId.AsLong())) + .OrderByDescending(o => o.Rolls) + .Take(amount) + .ToDictionary(key => key.UserId.AsUlong(), key => key.Rolls); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Highscores/HighscoreTypes.cs b/Geekbot.net/Lib/Highscores/HighscoreTypes.cs new file mode 100644 index 0000000..492d08d --- /dev/null +++ b/Geekbot.net/Lib/Highscores/HighscoreTypes.cs @@ -0,0 +1,9 @@ +namespace Geekbot.net.Lib.Highscores +{ + public enum HighscoreTypes + { + messages, + karma, + rolls + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/User/Ranking/RankUserDto.cs b/Geekbot.net/Lib/Highscores/HighscoreUserDto.cs similarity index 54% rename from Geekbot.net/Commands/User/Ranking/RankUserDto.cs rename to Geekbot.net/Lib/Highscores/HighscoreUserDto.cs index 2ec518e..7abb352 100644 --- a/Geekbot.net/Commands/User/Ranking/RankUserDto.cs +++ b/Geekbot.net/Lib/Highscores/HighscoreUserDto.cs @@ -1,8 +1,9 @@ -namespace Geekbot.net.Commands.User.Ranking +namespace Geekbot.net.Lib.Highscores { - internal class RankUserDto + public class HighscoreUserDto { public string Username { get; set; } + public string Avatar { get; set; } public string Discriminator { get; set; } public string Id { get; set; } } diff --git a/Geekbot.net/Lib/Highscores/IHighscoreManager.cs b/Geekbot.net/Lib/Highscores/IHighscoreManager.cs new file mode 100644 index 0000000..a09b07e --- /dev/null +++ b/Geekbot.net/Lib/Highscores/IHighscoreManager.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; + +namespace Geekbot.net.Lib.Highscores +{ + public interface IHighscoreManager + { + Dictionary GetHighscoresWithUserData(HighscoreTypes type, ulong guildId, int amount); + Dictionary GetMessageList(ulong guildId, int amount); + Dictionary GetKarmaList(ulong guildId, int amount); + Dictionary GetRollsList(ulong guildId, int amount); + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Logger/LogSource.cs b/Geekbot.net/Lib/Logger/LogSource.cs index 42c1877..7cd92ff 100644 --- a/Geekbot.net/Lib/Logger/LogSource.cs +++ b/Geekbot.net/Lib/Logger/LogSource.cs @@ -17,6 +17,7 @@ namespace Geekbot.net.Lib.Logger Command, Api, Migration, + HighscoreManager, Other } } \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index f2a6291..9af8879 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -7,7 +7,6 @@ using Discord; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Database; -using Geekbot.net.Database.LoggingAdapter; using Geekbot.net.Lib; using Geekbot.net.Lib.AlmostRedis; using Geekbot.net.Lib.Audio; @@ -15,6 +14,7 @@ using Geekbot.net.Lib.Clients; using Geekbot.net.Lib.Converters; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.GlobalSettings; +using Geekbot.net.Lib.Highscores; using Geekbot.net.Lib.Levels; using Geekbot.net.Lib.Localization; using Geekbot.net.Lib.Logger; @@ -40,6 +40,7 @@ namespace Geekbot.net private IUserRepository _userRepository; private RunParameters _runParameters; private IAlmostRedis _redis; + private IHighscoreManager _highscoreManager; private static void Main(string[] args) { @@ -123,6 +124,7 @@ namespace Geekbot.net var mtgManaConverter = new MtgManaConverter(); var wikipediaClient = new WikipediaClient(); var audioUtils = new AudioUtils(); + _highscoreManager = new HighscoreManager(_databaseInitializer.Initialize(), _userRepository); _services.AddSingleton(_redis); _services.AddSingleton(_userRepository); @@ -135,6 +137,7 @@ namespace Geekbot.net _services.AddSingleton(mtgManaConverter); _services.AddSingleton(wikipediaClient); _services.AddSingleton(audioUtils); + _services.AddSingleton(_highscoreManager); _services.AddSingleton(_globalSettings); _services.AddTransient((e) => _databaseInitializer.Initialize()); @@ -203,7 +206,7 @@ namespace Geekbot.net private Task StartWebApi() { _logger.Information(LogSource.Api, "Starting Webserver"); - WebApi.WebApiStartup.StartWebApi(_logger, _runParameters, _commands, _databaseInitializer.Initialize(), _client, _globalSettings); + WebApi.WebApiStartup.StartWebApi(_logger, _runParameters, _commands, _databaseInitializer.Initialize(), _client, _globalSettings, _highscoreManager); return Task.CompletedTask; } } diff --git a/Geekbot.net/WebApi/ApiError.cs b/Geekbot.net/WebApi/ApiError.cs new file mode 100644 index 0000000..182518e --- /dev/null +++ b/Geekbot.net/WebApi/ApiError.cs @@ -0,0 +1,7 @@ +namespace Geekbot.net.WebApi +{ + public class ApiError + { + public string Message { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/WebApi/Controllers/Highscores/HighscoreController.cs b/Geekbot.net/WebApi/Controllers/Highscores/HighscoreController.cs new file mode 100644 index 0000000..3cccb0e --- /dev/null +++ b/Geekbot.net/WebApi/Controllers/Highscores/HighscoreController.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using Geekbot.net.Lib.Highscores; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; + +namespace Geekbot.net.WebApi.Controllers.Highscores +{ + [EnableCors("AllowSpecificOrigin")] + public class HighscoreController : Controller + { + private readonly IHighscoreManager _highscoreManager; + + public HighscoreController(IHighscoreManager highscoreManager) + { + _highscoreManager = highscoreManager; + } + + [HttpPost] + [Route("/v1/highscore")] + public IActionResult GetHighscores([FromBody] HighscoreControllerPostBodyDto body) + { + if (!ModelState.IsValid || body == null) + { + var error = new SerializableError(ModelState); + return BadRequest(error); + } + + Dictionary list; + try + { + list = _highscoreManager.GetHighscoresWithUserData(body.Type, body.GuildId, body.Amount); + } + catch (HighscoreListEmptyException) + { + return NotFound(new ApiError + { + Message = $"No {body.Type} found on this server" + }); + } + + var response = new List(); + var counter = 1; + foreach (var item in list) + { + response.Add(new HighscoreControllerReponseBody + { + count = item.Value, + rank = counter, + user = item.Key + }); + counter++; + } + return Ok(response); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/WebApi/Controllers/Highscores/HighscoreControllerPostBodyDto.cs b/Geekbot.net/WebApi/Controllers/Highscores/HighscoreControllerPostBodyDto.cs new file mode 100644 index 0000000..22da3c7 --- /dev/null +++ b/Geekbot.net/WebApi/Controllers/Highscores/HighscoreControllerPostBodyDto.cs @@ -0,0 +1,16 @@ +using System.ComponentModel.DataAnnotations; +using Geekbot.net.Lib.Highscores; + +namespace Geekbot.net.WebApi.Controllers.Highscores +{ + public class HighscoreControllerPostBodyDto + { + [Required] + public ulong GuildId { get; set; } + + public HighscoreTypes Type { get; set; } = HighscoreTypes.messages; + + [Range(1, 150)] + public int Amount { get; set; } = 50; + } +} \ No newline at end of file diff --git a/Geekbot.net/WebApi/Controllers/Highscores/HighscoreControllerReponseBody.cs b/Geekbot.net/WebApi/Controllers/Highscores/HighscoreControllerReponseBody.cs new file mode 100644 index 0000000..0e59880 --- /dev/null +++ b/Geekbot.net/WebApi/Controllers/Highscores/HighscoreControllerReponseBody.cs @@ -0,0 +1,11 @@ +using Geekbot.net.Lib.Highscores; + +namespace Geekbot.net.WebApi.Controllers.Highscores +{ + public class HighscoreControllerReponseBody + { + public int rank { get; set; } + public HighscoreUserDto user { get; set; } + public int count { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/WebApi/WebApiStartup.cs b/Geekbot.net/WebApi/WebApiStartup.cs index e93a8d5..2459362 100644 --- a/Geekbot.net/WebApi/WebApiStartup.cs +++ b/Geekbot.net/WebApi/WebApiStartup.cs @@ -5,6 +5,7 @@ using Discord.WebSocket; using Geekbot.net.Database; using Geekbot.net.Lib; using Geekbot.net.Lib.GlobalSettings; +using Geekbot.net.Lib.Highscores; using Geekbot.net.Lib.Logger; using Geekbot.net.WebApi.Logging; using Microsoft.AspNetCore; @@ -18,7 +19,7 @@ namespace Geekbot.net.WebApi public static class WebApiStartup { public static void StartWebApi(IGeekbotLogger logger, RunParameters runParameters, CommandService commandService, - DatabaseContext databaseContext, DiscordSocketClient client, IGlobalSettings globalSettings) + DatabaseContext databaseContext, DiscordSocketClient client, IGlobalSettings globalSettings, IHighscoreManager highscoreManager) { WebHost.CreateDefaultBuilder() .UseKestrel(options => @@ -32,6 +33,7 @@ namespace Geekbot.net.WebApi services.AddSingleton(databaseContext); services.AddSingleton(client); services.AddSingleton(globalSettings); + services.AddSingleton(highscoreManager); services.AddCors(options => { options.AddPolicy("AllowSpecificOrigin", From 863fcd5e9df78d2a19c5031e0899a919203edf03 Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 11 Sep 2018 00:13:54 +0200 Subject: [PATCH 224/553] Add bugsnag --- Geekbot.net/Geekbot.net.csproj | 2 + Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs | 83 +++++++++++++++---- Geekbot.net/Program.cs | 2 +- 3 files changed, 70 insertions(+), 17 deletions(-) diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 46c1eff..052199d 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -19,6 +19,8 @@ true + + 2.0.0-beta2-00984 diff --git a/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs index 8ebee2e..7d5deec 100644 --- a/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs @@ -1,12 +1,17 @@ using System; +using System.Collections.Generic; using System.Net; using System.Threading.Tasks; +using Bugsnag; +using Bugsnag.Payload; using Discord.Commands; using Discord.Net; +using Geekbot.net.Lib.GlobalSettings; using Geekbot.net.Lib.Localization; using Geekbot.net.Lib.Logger; using SharpRaven; using SharpRaven.Data; +using Exception = System.Exception; namespace Geekbot.net.Lib.ErrorHandling { @@ -16,8 +21,9 @@ namespace Geekbot.net.Lib.ErrorHandling private readonly ITranslationHandler _translation; private readonly IRavenClient _raven; private readonly bool _errorsInChat; + private readonly IClient _bugsnag; - public ErrorHandler(IGeekbotLogger logger, ITranslationHandler translation, bool errorsInChat) + public ErrorHandler(IGeekbotLogger logger, ITranslationHandler translation, IGlobalSettings globalSettings, bool errorsInChat) { _logger = logger; _translation = translation; @@ -33,6 +39,21 @@ namespace Geekbot.net.Lib.ErrorHandling { _raven = null; } + + var bugsnagApiKey = globalSettings.GetKey("BugsnagApiKey"); + if (!string.IsNullOrEmpty(bugsnagApiKey)) + { + _bugsnag = new Bugsnag.Client(new Bugsnag.Configuration + { + ApiKey = bugsnagApiKey, + AppVersion = Constants.BotVersion() + }); + _logger.Information(LogSource.Geekbot, "Command Errors will be logged to Bugsnag"); + } + else + { + _bugsnag = null; + } } public async Task HandleCommandException(Exception e, ICommandContext context, string errorMessage = "def") @@ -65,20 +86,8 @@ namespace Geekbot.net.Lib.ErrorHandling } } - - if (_raven == null) return; - - var sentryEvent = new SentryEvent(e) - { - Tags = - { - ["discord_server"] = errorObj.Guild.Name, - ["discord_user"] = errorObj.User.Name - }, - Message = errorObj.Message.Content, - Extra = errorObj - }; - _raven.Capture(sentryEvent); + + ReportExternal(e, errorObj); } catch (Exception ex) { @@ -98,6 +107,48 @@ namespace Geekbot.net.Lib.ErrorHandling } } - + private void ReportExternal(Exception e, MessageDto errorObj) + { + if (_raven != null) + { + var sentryEvent = new SentryEvent(e) + { + Tags = + { + ["discord_server"] = errorObj.Guild.Name, + ["discord_user"] = errorObj.User.Name + }, + Message = errorObj.Message.Content, + Extra = errorObj + }; + _raven.Capture(sentryEvent); + } + + _bugsnag?.Notify(e, (report) => + { + report.Event.Metadata.Add("Discord Location", new Dictionary + { + {"Guild Name", errorObj.Guild.Name}, + {"Guild Id", errorObj.Guild.Id}, + {"Channel Name", errorObj.Channel.Name}, + {"Channel Id", errorObj.Channel.Id} + }); + report.Event.Metadata.Add("Message Info", new Dictionary + { + {"Content", errorObj.Message.Content}, + {"Id", errorObj.Message.Id}, + {"Attachments", errorObj.Message.Attachments.ToString()}, + {"ChannelMentions", errorObj.Message.ChannelMentions.ToString()}, + {"UserMentions", errorObj.Message.UserMentions.ToString()}, + {"RoleMentions", errorObj.Message.RoleMentions.ToString()}, + }); + report.Event.Severity = Severity.Error; + report.Event.User = new User + { + Id = errorObj.User.Id, + Name = errorObj.User.Name + }; + }); + } } } \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 9af8879..e2cff4f 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -162,7 +162,7 @@ namespace Geekbot.net _logger.Information(LogSource.Geekbot, "Registering Stuff"); var translationHandler = new TranslationHandler(_databaseInitializer.Initialize(), _logger); - var errorHandler = new ErrorHandler(_logger, translationHandler, _runParameters.ExposeErrors); + var errorHandler = new ErrorHandler(_logger, translationHandler, _globalSettings, _runParameters.ExposeErrors); var reactionListener = new ReactionListener(_redis.Db); _services.AddSingleton(errorHandler); _services.AddSingleton(translationHandler); From 458268bd41e0db5a49ef96a73aa602c0470b2c61 Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 8 Oct 2018 22:15:07 +0200 Subject: [PATCH 225/553] Fix bug in stats where the requestor would always see his own message count --- Geekbot.net/Commands/User/Stats.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Geekbot.net/Commands/User/Stats.cs b/Geekbot.net/Commands/User/Stats.cs index 4468b21..a230456 100644 --- a/Geekbot.net/Commands/User/Stats.cs +++ b/Geekbot.net/Commands/User/Stats.cs @@ -40,7 +40,7 @@ namespace Geekbot.net.Commands.User var joinedDayAgo = Math.Floor((DateTime.Now - joinedAt).TotalDays); var messages = _database.Messages - .First(e => e.GuildId.Equals(Context.Guild.Id.AsLong()) && e.UserId.Equals(Context.User.Id.AsLong())) + .First(e => e.GuildId.Equals(Context.Guild.Id.AsLong()) && e.UserId.Equals(userInfo.Id.AsLong())) .MessageCount; var guildMessages = _database.Messages .Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())) From e8546f37f2040991b7cc6e9ebaff8dd17a194876 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Tue, 30 Oct 2018 19:53:50 +0900 Subject: [PATCH 226/553] Disable the say command --- Geekbot.net/Commands/Admin/Say.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Geekbot.net/Commands/Admin/Say.cs b/Geekbot.net/Commands/Admin/Say.cs index 910d700..2a6f80e 100644 --- a/Geekbot.net/Commands/Admin/Say.cs +++ b/Geekbot.net/Commands/Admin/Say.cs @@ -22,8 +22,7 @@ namespace Geekbot.net.Commands.Admin { try { - await Context.Message.DeleteAsync(); - await ReplyAsync(echo); + await Context.User.SendMessageAsync("the `!say` command has been disabled since 2018/10/30"); } catch (Exception e) { From 26da438efeb462126e1c4ac12eb3f41d51bb6392 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 29 Nov 2018 18:14:22 +0100 Subject: [PATCH 227/553] Fix namehistory command --- Geekbot.net/Commands/Admin/Mod.cs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Geekbot.net/Commands/Admin/Mod.cs b/Geekbot.net/Commands/Admin/Mod.cs index b014e53..e1653e9 100644 --- a/Geekbot.net/Commands/Admin/Mod.cs +++ b/Geekbot.net/Commands/Admin/Mod.cs @@ -33,10 +33,17 @@ namespace Geekbot.net.Commands.Admin try { var userRepo = _userRepository.Get(user.Id); - var sb = new StringBuilder(); - sb.AppendLine($":bust_in_silhouette: {user.Username} has been known as:"); - foreach (var name in userRepo.UsedNames) sb.AppendLine($"- `{name.Name}`"); - await ReplyAsync(sb.ToString()); + if (userRepo != null && userRepo.UsedNames != null) + { + var sb = new StringBuilder(); + sb.AppendLine($":bust_in_silhouette: {user.Username} has been known as:"); + foreach (var name in userRepo.UsedNames) sb.AppendLine($"- `{name.Name}`"); + await ReplyAsync(sb.ToString()); + } + else + { + await ReplyAsync($"No name changes found for {user.Username}"); + } } catch (Exception e) { From 2c6b61b7e6f5f444974b5bce54646dfa93d810ef Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sun, 27 Jan 2019 22:08:49 +0100 Subject: [PATCH 228/553] Add parameter to enable db logging, disabled by default --- Geekbot.net.sln.DotSettings | 1 + Geekbot.net/Database/DatabaseInitializer.cs | 10 +++++++--- .../Database/LoggingAdapter/NpgsqlLoggingAdapter.cs | 7 +++++-- .../LoggingAdapter/NpgsqlLoggingProviderAdapter.cs | 9 ++++++--- Geekbot.net/Lib/RunParameters.cs | 4 ++++ 5 files changed, 23 insertions(+), 8 deletions(-) diff --git a/Geekbot.net.sln.DotSettings b/Geekbot.net.sln.DotSettings index 7fa04b3..6d439b8 100644 --- a/Geekbot.net.sln.DotSettings +++ b/Geekbot.net.sln.DotSettings @@ -5,6 +5,7 @@ True True True + True True True True diff --git a/Geekbot.net/Database/DatabaseInitializer.cs b/Geekbot.net/Database/DatabaseInitializer.cs index 7eff2c6..6adff44 100644 --- a/Geekbot.net/Database/DatabaseInitializer.cs +++ b/Geekbot.net/Database/DatabaseInitializer.cs @@ -16,7 +16,7 @@ namespace Geekbot.net.Database { _runParameters = runParameters; _logger = logger; - NpgsqlLogManager.Provider = new NpgsqlLoggingProviderAdapter(_logger); + NpgsqlLogManager.Provider = new NpgsqlLoggingProviderAdapter(logger, runParameters); } public DatabaseContext Initialize() @@ -45,8 +45,12 @@ namespace Geekbot.net.Database _logger.Error(LogSource.Geekbot, "Could not Connect to datbase", e); Environment.Exit(GeekbotExitCode.DatabaseConnectionFailed.GetHashCode()); } - - _logger.Information(LogSource.Database, $"Connected with {database.Database.ProviderName}"); + + if (_runParameters.DbLogging) + { + _logger.Information(LogSource.Database, $"Connected with {database.Database.ProviderName}"); + } + return database; } } diff --git a/Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingAdapter.cs b/Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingAdapter.cs index 80d60b3..e8850cd 100644 --- a/Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingAdapter.cs +++ b/Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingAdapter.cs @@ -1,4 +1,5 @@ using System; +using Geekbot.net.Lib; using Geekbot.net.Lib.Logger; using Npgsql.Logging; using LogLevel = NLog.LogLevel; @@ -9,17 +10,19 @@ namespace Geekbot.net.Database.LoggingAdapter { private readonly string _name; private readonly IGeekbotLogger _geekbotLogger; + private readonly RunParameters _runParameters; - public NpgsqlLoggingAdapter(string name, IGeekbotLogger geekbotLogger) + public NpgsqlLoggingAdapter(string name, IGeekbotLogger geekbotLogger, RunParameters runParameters) { _name = name.Substring(7); _geekbotLogger = geekbotLogger; + _runParameters = runParameters; geekbotLogger.Trace(LogSource.Database, $"Loaded Npgsql logging adapter: {name}"); } public override bool IsEnabled(NpgsqlLogLevel level) { - return !_geekbotLogger.LogAsJson() && _geekbotLogger.GetNLogger().IsEnabled(ToGeekbotLogLevel(level)); + return (_runParameters.DbLogging && _geekbotLogger.GetNLogger().IsEnabled(ToGeekbotLogLevel(level))); } public override void Log(NpgsqlLogLevel level, int connectorId, string msg, Exception exception = null) diff --git a/Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingProviderAdapter.cs b/Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingProviderAdapter.cs index 0888111..efe82a3 100644 --- a/Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingProviderAdapter.cs +++ b/Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingProviderAdapter.cs @@ -1,4 +1,5 @@ -using Geekbot.net.Lib.Logger; +using Geekbot.net.Lib; +using Geekbot.net.Lib.Logger; using Npgsql.Logging; namespace Geekbot.net.Database.LoggingAdapter @@ -6,15 +7,17 @@ namespace Geekbot.net.Database.LoggingAdapter public class NpgsqlLoggingProviderAdapter : INpgsqlLoggingProvider { private readonly GeekbotLogger _geekbotLogger; + private readonly RunParameters _runParameters; - public NpgsqlLoggingProviderAdapter(GeekbotLogger geekbotLogger) + public NpgsqlLoggingProviderAdapter(GeekbotLogger geekbotLogger, RunParameters runParameters) { _geekbotLogger = geekbotLogger; + _runParameters = runParameters; } public NpgsqlLogger CreateLogger(string name) { - return new NpgsqlLoggingAdapter(name, _geekbotLogger); + return new NpgsqlLoggingAdapter(name, _geekbotLogger, _runParameters); } } } \ No newline at end of file diff --git a/Geekbot.net/Lib/RunParameters.cs b/Geekbot.net/Lib/RunParameters.cs index 7f2dd3d..444a60f 100644 --- a/Geekbot.net/Lib/RunParameters.cs +++ b/Geekbot.net/Lib/RunParameters.cs @@ -45,6 +45,10 @@ namespace Geekbot.net.Lib [Option("db-password", Default = "", HelpText = "Set a posgresql password")] public string DbPassword { get; set; } + + // Logging + [Option("db-logging", Default = false, HelpText = "Enable database logging")] + public bool DbLogging { get; set; } /************************************ * Redis * From 8059f033049692a3d45c38f5148ede87dbfa8cdb Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sun, 27 Jan 2019 22:32:13 +0100 Subject: [PATCH 229/553] Remove !say completly --- Geekbot.net/Commands/Admin/Say.cs | 33 ------------------------------- 1 file changed, 33 deletions(-) delete mode 100644 Geekbot.net/Commands/Admin/Say.cs diff --git a/Geekbot.net/Commands/Admin/Say.cs b/Geekbot.net/Commands/Admin/Say.cs deleted file mode 100644 index 2a6f80e..0000000 --- a/Geekbot.net/Commands/Admin/Say.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Threading.Tasks; -using Discord; -using Discord.Commands; -using Geekbot.net.Lib.ErrorHandling; - -namespace Geekbot.net.Commands.Admin -{ - public class Say : ModuleBase - { - private readonly IErrorHandler _errorHandler; - - public Say(IErrorHandler errorHandler) - { - _errorHandler = errorHandler; - } - - [RequireUserPermission(GuildPermission.Administrator)] - [Command("say", RunMode = RunMode.Async)] - [Summary("Say Something.")] - public async Task Echo([Remainder] [Summary("What?")] string echo) - { - try - { - await Context.User.SendMessageAsync("the `!say` command has been disabled since 2018/10/30"); - } - catch (Exception e) - { - await _errorHandler.HandleCommandException(e, Context); - } - } - } -} \ No newline at end of file From 4de8447c97158bd5a10a34a636b282cd575c9faa Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 13 Feb 2019 00:50:31 +0100 Subject: [PATCH 230/553] Fix roll command to write successful writes to the database instead of redis --- Geekbot.net/Commands/Games/Roll.cs | 31 +++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/Geekbot.net/Commands/Games/Roll.cs b/Geekbot.net/Commands/Games/Roll.cs index c629ed8..8db295c 100644 --- a/Geekbot.net/Commands/Games/Roll.cs +++ b/Geekbot.net/Commands/Games/Roll.cs @@ -1,8 +1,12 @@ using System; +using System.Linq; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.net.Database; +using Geekbot.net.Database.Models; using Geekbot.net.Lib.AlmostRedis; using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Localization; using StackExchange.Redis; @@ -13,11 +17,13 @@ namespace Geekbot.net.Commands.Games private readonly IErrorHandler _errorHandler; private readonly IAlmostRedis _redis; private readonly ITranslationHandler _translation; + private readonly DatabaseContext _database; - public Roll(IAlmostRedis redis, IErrorHandler errorHandler, ITranslationHandler translation) + public Roll(IAlmostRedis redis, IErrorHandler errorHandler, ITranslationHandler translation, DatabaseContext database) { _redis = redis; _translation = translation; + _database = database; _errorHandler = errorHandler; } @@ -50,6 +56,10 @@ namespace Geekbot.net.Commands.Games { await ReplyAsync(string.Format(transDict["Gratz"], Context.Message.Author)); _redis.Db.HashIncrement($"{Context.Guild.Id}:Rolls", Context.User.Id.ToString()); + var user = await GetUser(Context.User.Id); + user.Rolls += 1; + _database.Rolls.Update(user); + await _database.SaveChangesAsync(); } } else @@ -62,5 +72,24 @@ namespace Geekbot.net.Commands.Games await _errorHandler.HandleCommandException(e, Context); } } + + private async Task GetUser(ulong userId) + { + var user = _database.Rolls.FirstOrDefault(u =>u.GuildId.Equals(Context.Guild.Id.AsLong()) && u.UserId.Equals(userId.AsLong())) ?? await CreateNewRow(userId); + return user; + } + + private async Task CreateNewRow(ulong userId) + { + var user = new RollsModel() + { + GuildId = Context.Guild.Id.AsLong(), + UserId = userId.AsLong(), + Rolls = 0 + }; + var newUser = _database.Rolls.Add(user).Entity; + await _database.SaveChangesAsync(); + return newUser; + } } } \ No newline at end of file From 4e4f2e88d5e4c6dead62bb4cf2ef710695a90d34 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 13 Feb 2019 01:06:05 +0100 Subject: [PATCH 231/553] Fix deployment --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1a55164..1ba3063 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -36,8 +36,8 @@ deploy: - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null - chmod 700 ~/.ssh script: - - rsync -rav -e "ssh -p 65432" ./Geekbot.net/Binaries/* geekbot@192.168.156.175:$DEPPATH - - ssh -p 65432 geekbot@192.168.156.175 "sudo systemctl restart geekbot.service" + - rsync -rav -e "ssh -p 65432" ./Geekbot.net/Binaries/* geekbot@$DEPIP:$DEPPATH + - ssh -p 65432 geekbot@$DEPIP "sudo systemctl restart geekbot.service" mirror: stage: deploy From aa059b5558a49e992289e6c1593165e89a1b15c1 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sat, 2 Mar 2019 00:12:35 -0500 Subject: [PATCH 232/553] Update Discord.net --- Geekbot.net/Geekbot.net.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 052199d..554950c 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -23,7 +23,7 @@ - 2.0.0-beta2-00984 + 2.0.1 From ff15e21b5af76878ae5da79d426b326d65b9bd9e Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sat, 2 Mar 2019 00:32:59 -0500 Subject: [PATCH 233/553] Upgrade Gatherer Client and fix bug where card legalities could be an empty collection and throwing and exception as a result --- Geekbot.net/Commands/Integrations/MagicTheGathering.cs | 2 +- Geekbot.net/Geekbot.net.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Geekbot.net/Commands/Integrations/MagicTheGathering.cs b/Geekbot.net/Commands/Integrations/MagicTheGathering.cs index 2d3e7c6..bb95eb7 100644 --- a/Geekbot.net/Commands/Integrations/MagicTheGathering.cs +++ b/Geekbot.net/Commands/Integrations/MagicTheGathering.cs @@ -57,7 +57,7 @@ namespace Geekbot.net.Commands.Integrations if (!string.IsNullOrEmpty(card.ManaCost)) eb.AddInlineField("Cost", _manaConverter.ConvertMana(card.ManaCost)); if (!string.IsNullOrEmpty(card.Rarity)) eb.AddInlineField("Rarity", card.Rarity); - if (card.Legalities != null) + if (card.Legalities != null && card.Legalities.Count > 0) eb.AddField("Legality", string.Join(", ", card.Legalities.Select(e => e.Format))); await ReplyAsync("", false, eb.Build()); diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 554950c..b0a92d9 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -40,7 +40,7 @@ - + From 16f70d52ced95596ab72531ddb0d8193e9113d23 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sat, 2 Mar 2019 00:48:16 -0500 Subject: [PATCH 234/553] Some Upgrades --- Geekbot.net/Geekbot.net.csproj | 16 ++++++++-------- Tests/Tests.csproj | 4 ++-- WikipediaApi/WikipediaApi.csproj | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index b0a92d9..0ed34e8 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -21,12 +21,12 @@ - + 2.0.1 - - + + @@ -42,14 +42,14 @@ - - - + + + - + - + diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 58fbfc6..094bf84 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -6,8 +6,8 @@ - - + + diff --git a/WikipediaApi/WikipediaApi.csproj b/WikipediaApi/WikipediaApi.csproj index 9a86577..8198ca2 100644 --- a/WikipediaApi/WikipediaApi.csproj +++ b/WikipediaApi/WikipediaApi.csproj @@ -3,6 +3,6 @@ netcoreapp2.1 - + \ No newline at end of file From 2b90358ca52ba06a1e16963400bf4b56dac5fc70 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sat, 2 Mar 2019 00:50:54 -0500 Subject: [PATCH 235/553] Remove Bugsnag --- Geekbot.net/Geekbot.net.csproj | 2 - Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs | 67 +++---------------- 2 files changed, 10 insertions(+), 59 deletions(-) diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 0ed34e8..9e98f9b 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -19,8 +19,6 @@ true - - 2.0.1 diff --git a/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs index 7d5deec..c6e1f8d 100644 --- a/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs @@ -1,9 +1,6 @@ using System; -using System.Collections.Generic; using System.Net; using System.Threading.Tasks; -using Bugsnag; -using Bugsnag.Payload; using Discord.Commands; using Discord.Net; using Geekbot.net.Lib.GlobalSettings; @@ -21,7 +18,6 @@ namespace Geekbot.net.Lib.ErrorHandling private readonly ITranslationHandler _translation; private readonly IRavenClient _raven; private readonly bool _errorsInChat; - private readonly IClient _bugsnag; public ErrorHandler(IGeekbotLogger logger, ITranslationHandler translation, IGlobalSettings globalSettings, bool errorsInChat) { @@ -39,21 +35,6 @@ namespace Geekbot.net.Lib.ErrorHandling { _raven = null; } - - var bugsnagApiKey = globalSettings.GetKey("BugsnagApiKey"); - if (!string.IsNullOrEmpty(bugsnagApiKey)) - { - _bugsnag = new Bugsnag.Client(new Bugsnag.Configuration - { - ApiKey = bugsnagApiKey, - AppVersion = Constants.BotVersion() - }); - _logger.Information(LogSource.Geekbot, "Command Errors will be logged to Bugsnag"); - } - else - { - _bugsnag = null; - } } public async Task HandleCommandException(Exception e, ICommandContext context, string errorMessage = "def") @@ -109,46 +90,18 @@ namespace Geekbot.net.Lib.ErrorHandling private void ReportExternal(Exception e, MessageDto errorObj) { - if (_raven != null) + if (_raven == null) return; + var sentryEvent = new SentryEvent(e) { - var sentryEvent = new SentryEvent(e) + Tags = { - Tags = - { - ["discord_server"] = errorObj.Guild.Name, - ["discord_user"] = errorObj.User.Name - }, - Message = errorObj.Message.Content, - Extra = errorObj - }; - _raven.Capture(sentryEvent); - } - - _bugsnag?.Notify(e, (report) => - { - report.Event.Metadata.Add("Discord Location", new Dictionary - { - {"Guild Name", errorObj.Guild.Name}, - {"Guild Id", errorObj.Guild.Id}, - {"Channel Name", errorObj.Channel.Name}, - {"Channel Id", errorObj.Channel.Id} - }); - report.Event.Metadata.Add("Message Info", new Dictionary - { - {"Content", errorObj.Message.Content}, - {"Id", errorObj.Message.Id}, - {"Attachments", errorObj.Message.Attachments.ToString()}, - {"ChannelMentions", errorObj.Message.ChannelMentions.ToString()}, - {"UserMentions", errorObj.Message.UserMentions.ToString()}, - {"RoleMentions", errorObj.Message.RoleMentions.ToString()}, - }); - report.Event.Severity = Severity.Error; - report.Event.User = new User - { - Id = errorObj.User.Id, - Name = errorObj.User.Name - }; - }); + ["discord_server"] = errorObj.Guild.Name, + ["discord_user"] = errorObj.User.Name + }, + Message = errorObj.Message.Content, + Extra = errorObj + }; + _raven.Capture(sentryEvent); } } } \ No newline at end of file From 35a4f4a122bd35be32d9d3a5c706c38df5d9c9da Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sat, 2 Mar 2019 01:21:42 -0500 Subject: [PATCH 236/553] Limit MTG Page Size to 1 card --- Geekbot.net/Commands/Integrations/MagicTheGathering.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Geekbot.net/Commands/Integrations/MagicTheGathering.cs b/Geekbot.net/Commands/Integrations/MagicTheGathering.cs index bb95eb7..9ccab39 100644 --- a/Geekbot.net/Commands/Integrations/MagicTheGathering.cs +++ b/Geekbot.net/Commands/Integrations/MagicTheGathering.cs @@ -29,7 +29,11 @@ namespace Geekbot.net.Commands.Integrations try { var service = new CardService(); - var result = service.Where(x => x.Name, cardName); + var result = service + .Where(x => x.Name, cardName) + // fewer cards less risk of deserialization problems, don't need more than one anyways... + // ToDo: fix the deserialization issue in card[n].foreignNames[] + .Where(x => x.PageSize, 1); var card = result.All().Value.FirstOrDefault(); if (card == null) From 809adee77854a12bdfd481f73e8c48ede28e6517 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sat, 2 Mar 2019 01:57:43 -0500 Subject: [PATCH 237/553] Add Sentry Release Reporting (attempt 1) --- .gitlab-ci.yml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1ba3063..9f8432a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,5 +1,6 @@ stages: - build + - ops - deploy before_script: @@ -19,6 +20,17 @@ build: - dotnet test Tests - dotnet publish --version-suffix ${CI_COMMIT_SHA:0:8} --configuration Release -o Binaries ./ +sentry: + stage: ops + image: getsentry/sentry-cli + only: + - master + dependencies: + - build + script: + - sentry-cli releases new -p geekbot 4.0.0-${CI_COMMIT_SHA:0:8} + - sentry-cli releases set-commits --auto 4.0.0-${CI_COMMIT_SHA:0:8} + deploy: stage: deploy image: runebaas/rsync-ssh-git @@ -26,6 +38,7 @@ deploy: - master dependencies: - build + - sentry environment: name: Production url: https://discordapp.com/oauth2/authorize?client_id=171249478546882561&scope=bot&permissions=1416834054 @@ -44,6 +57,8 @@ mirror: image: runebaas/rsync-ssh-git only: - master + dependencies: + - build + - sentry script: - git push https://runebaas:$TOKEN@github.com/pizzaandcoffee/Geekbot.net.git origin/master:master -f - \ No newline at end of file From 3a6dd8ea1000eb6b50c54b557d8aebf232b12cc4 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sat, 2 Mar 2019 02:06:46 -0500 Subject: [PATCH 238/553] Add Sentry Release Reporting (attempt 2) --- .gitlab-ci.yml | 7 +++++-- Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9f8432a..42eaca6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -23,13 +23,16 @@ build: sentry: stage: ops image: getsentry/sentry-cli + variables: + VERSION: 4.0.0-${CI_COMMIT_SHA:0:8} only: - master dependencies: - build script: - - sentry-cli releases new -p geekbot 4.0.0-${CI_COMMIT_SHA:0:8} - - sentry-cli releases set-commits --auto 4.0.0-${CI_COMMIT_SHA:0:8} + - sentry-cli releases new -p geekbot $VERSION + - sentry-cli releases set-commits --auto $VERSION + - sentry-cli releases deploys $VERSION new -e Production deploy: stage: deploy diff --git a/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs index c6e1f8d..5323ee6 100644 --- a/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs @@ -28,7 +28,7 @@ namespace Geekbot.net.Lib.ErrorHandling var sentryDsn = Environment.GetEnvironmentVariable("SENTRY"); if (!string.IsNullOrEmpty(sentryDsn)) { - _raven = new RavenClient(sentryDsn) { Release = Constants.BotVersion() }; + _raven = new RavenClient(sentryDsn) { Release = Constants.BotVersion(), Environment = "Production" }; _logger.Information(LogSource.Geekbot, $"Command Errors will be logged to Sentry: {sentryDsn}"); } else From 3f083b520d3d676cd5856cff2de7729c94d00753 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sat, 2 Mar 2019 02:12:03 -0500 Subject: [PATCH 239/553] Add Sentry Release Reporting (attempt 3) --- .gitlab-ci.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 42eaca6..542c761 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -23,16 +23,14 @@ build: sentry: stage: ops image: getsentry/sentry-cli - variables: - VERSION: 4.0.0-${CI_COMMIT_SHA:0:8} only: - master dependencies: - build script: - - sentry-cli releases new -p geekbot $VERSION - - sentry-cli releases set-commits --auto $VERSION - - sentry-cli releases deploys $VERSION new -e Production + - sentry-cli releases new -p geekbot 4.0.0-${CI_COMMIT_SHA:0:8} + - sentry-cli releases set-commits --auto 4.0.0-${CI_COMMIT_SHA:0:8} + - sentry-cli releases deploys 4.0.0-${CI_COMMIT_SHA:0:8} new -e Production deploy: stage: deploy From a1e0c35dd4b887919a2216f8d1e4ce2ed7da49eb Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sun, 3 Mar 2019 20:27:50 -0500 Subject: [PATCH 240/553] Upgrade to DotNet Core 2.2 --- Geekbot.net/Geekbot.net.csproj | 31 +++++++++++++------------ Geekbot.net/Lib/Logger/LoggerFactory.cs | 3 +-- Tests/Tests.csproj | 4 ++-- WikipediaApi/WikipediaApi.csproj | 2 +- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 9e98f9b..9ea7546 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -1,12 +1,13 @@  Exe - netcoreapp2.1 + netcoreapp2.2 win-x64;linux-x64 derp.ico 4.0.0 $(VersionSuffix) $(Version)-$(VersionSuffix) + $(Version)-DEV Pizza and Coffee Studios Pizza and Coffee Studios A Discord bot @@ -25,30 +26,30 @@ - + - - - - - - - - - - - + + + + + + + + + + + - + - + 4.3.0 diff --git a/Geekbot.net/Lib/Logger/LoggerFactory.cs b/Geekbot.net/Lib/Logger/LoggerFactory.cs index 9c5f759..b07bcda 100644 --- a/Geekbot.net/Lib/Logger/LoggerFactory.cs +++ b/Geekbot.net/Lib/Logger/LoggerFactory.cs @@ -25,8 +25,7 @@ namespace Geekbot.net.Lib.Logger Layout = "${message}", UseConsoleLog = false, OptimizeBufferReuse = true, - Name = "Geekbot", - AppendException = false + Name = "Geekbot" }) ); } diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 094bf84..1e26252 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -1,11 +1,11 @@  - netcoreapp2.1 + netcoreapp2.2 false NU1701 - + diff --git a/WikipediaApi/WikipediaApi.csproj b/WikipediaApi/WikipediaApi.csproj index 8198ca2..79206c2 100644 --- a/WikipediaApi/WikipediaApi.csproj +++ b/WikipediaApi/WikipediaApi.csproj @@ -1,6 +1,6 @@  - netcoreapp2.1 + netcoreapp2.2 From dbd36a62d31b371962e139cd14903cda9af29de6 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sun, 3 Mar 2019 20:38:45 -0500 Subject: [PATCH 241/553] Disable Stats Updater when using the InMemory database --- Geekbot.net/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index e2cff4f..7b00055 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -174,13 +174,13 @@ namespace Geekbot.net var handlers = new Handlers(_databaseInitializer, _client, _logger, _redis, _servicesProvider, _commands, _userRepository, reactionListener); _client.MessageReceived += handlers.RunCommand; - _client.MessageReceived += handlers.UpdateStats; _client.MessageDeleted += handlers.MessageDeleted; _client.UserJoined += handlers.UserJoined; _client.UserUpdated += handlers.UserUpdated; _client.UserLeft += handlers.UserLeft; _client.ReactionAdded += handlers.ReactionAdded; _client.ReactionRemoved += handlers.ReactionRemoved; + if (!_runParameters.InMemory) _client.MessageReceived += handlers.UpdateStats; var webserver = _runParameters.DisableApi ? Task.Delay(10) : StartWebApi(); From f4897f7f2ee9aced537a91cc7e580cb0c6f3ca18 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sun, 3 Mar 2019 20:39:31 -0500 Subject: [PATCH 242/553] Comment out unused code in Poll.cs --- Geekbot.net/Commands/Utils/Poll.cs | 110 ++++++++++++++--------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/Geekbot.net/Commands/Utils/Poll.cs b/Geekbot.net/Commands/Utils/Poll.cs index c5a0119..598e78c 100644 --- a/Geekbot.net/Commands/Utils/Poll.cs +++ b/Geekbot.net/Commands/Utils/Poll.cs @@ -62,61 +62,61 @@ namespace Geekbot.net.Commands.Utils await ReplyAsync("Poll creation currently disabled"); return; - var currentPoll = GetCurrentPoll(); - if (currentPoll.Question != null && !currentPoll.IsFinshed) - { - await ReplyAsync("You have not finished you last poll yet. To finish it use `!poll end`"); - return; - } - - var pollList = rawPollString.Split(';').ToList(); - if (pollList.Count <= 2) - { - await ReplyAsync( - "You need a question with atleast 2 options, a valid creation would look like this `question;option1;option2`"); - return; - } - - var question = pollList[0]; - pollList.RemoveAt(0); - - var eb = new EmbedBuilder - { - Title = $"Poll by {Context.User.Username}", - Description = question - }; - - var options = new List(); - var i = 1; - pollList.ForEach(option => - { - options.Add(new PollQuestionModel() - { - OptionId = i, - OptionText = option - }); - eb.AddInlineField($"Option {_emojiConverter.NumberToEmoji(i)}", option); - i++; - }); - var pollMessage = await ReplyAsync("", false, eb.Build()); - - var poll = new PollModel() - { - Creator = Context.User.Id.AsLong(), - MessageId = pollMessage.Id.AsLong(), - IsFinshed = false, - Question = question, - Options = options - }; - _database.Polls.Add(poll); - - i = 1; - pollList.ForEach(option => - { - pollMessage.AddReactionAsync(new Emoji(_emojiConverter.NumberToEmoji(i))); - Task.Delay(500); - i++; - }); +// var currentPoll = GetCurrentPoll(); +// if (currentPoll.Question != null && !currentPoll.IsFinshed) +// { +// await ReplyAsync("You have not finished you last poll yet. To finish it use `!poll end`"); +// return; +// } +// +// var pollList = rawPollString.Split(';').ToList(); +// if (pollList.Count <= 2) +// { +// await ReplyAsync( +// "You need a question with atleast 2 options, a valid creation would look like this `question;option1;option2`"); +// return; +// } +// +// var question = pollList[0]; +// pollList.RemoveAt(0); +// +// var eb = new EmbedBuilder +// { +// Title = $"Poll by {Context.User.Username}", +// Description = question +// }; +// +// var options = new List(); +// var i = 1; +// pollList.ForEach(option => +// { +// options.Add(new PollQuestionModel() +// { +// OptionId = i, +// OptionText = option +// }); +// eb.AddInlineField($"Option {_emojiConverter.NumberToEmoji(i)}", option); +// i++; +// }); +// var pollMessage = await ReplyAsync("", false, eb.Build()); +// +// var poll = new PollModel() +// { +// Creator = Context.User.Id.AsLong(), +// MessageId = pollMessage.Id.AsLong(), +// IsFinshed = false, +// Question = question, +// Options = options +// }; +// _database.Polls.Add(poll); +// +// i = 1; +// pollList.ForEach(option => +// { +// pollMessage.AddReactionAsync(new Emoji(_emojiConverter.NumberToEmoji(i))); +// Task.Delay(500); +// i++; +// }); } catch (Exception e) { From c1ff11ca34663245a4f10f74280ec50b0f7393d0 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sun, 3 Mar 2019 21:01:47 -0500 Subject: [PATCH 243/553] Fix bug in TranslationsHandler where language lookup would fail if user messaged the bot directly --- .../Lib/Localization/TranslationHandler.cs | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/Geekbot.net/Lib/Localization/TranslationHandler.cs b/Geekbot.net/Lib/Localization/TranslationHandler.cs index 88e518e..a1b650b 100644 --- a/Geekbot.net/Lib/Localization/TranslationHandler.cs +++ b/Geekbot.net/Lib/Localization/TranslationHandler.cs @@ -18,8 +18,7 @@ namespace Geekbot.net.Lib.Localization private readonly IGeekbotLogger _logger; private readonly Dictionary _serverLanguages; private Dictionary>> _translations; - private List _supportedLanguages; - + public TranslationHandler(DatabaseContext database, IGeekbotLogger logger) { _database = database; @@ -45,8 +44,10 @@ namespace Geekbot.net.Lib.Localization if (!sortedPerLanguage.ContainsKey(lang.Key)) { var commandDict = new Dictionary>(); - var strDict = new Dictionary(); - strDict.Add(str.Key, lang.Value); + var strDict = new Dictionary + { + {str.Key, lang.Value} + }; commandDict.Add(command.Key, strDict); sortedPerLanguage.Add(lang.Key, commandDict); } @@ -65,10 +66,10 @@ namespace Geekbot.net.Lib.Localization } _translations = sortedPerLanguage; - _supportedLanguages = new List(); + SupportedLanguages = new List(); foreach (var lang in sortedPerLanguage) { - _supportedLanguages.Add(lang.Key); + SupportedLanguages.Add(lang.Key); } } catch (Exception e) @@ -101,7 +102,7 @@ namespace Geekbot.net.Lib.Localization } catch (Exception e) { - _logger.Error(LogSource.Geekbot, "Could not get guild langage", e); + _logger.Error(LogSource.Geekbot, "Could not get guild language", e); return "EN"; } } @@ -123,7 +124,8 @@ namespace Geekbot.net.Lib.Localization try { var command = context.Message.Content.Split(' ').First().TrimStart('!').ToLower(); - return _translations[await GetServerLanguage(context.Guild.Id)][command]; + var serverLanguage = await GetServerLanguage(context.Guild?.Id ?? 0); + return _translations[serverLanguage][command]; } catch (Exception e) { @@ -136,7 +138,8 @@ namespace Geekbot.net.Lib.Localization { try { - return _translations[await GetServerLanguage(context.Guild.Id)][command]; + var serverLanguage = await GetServerLanguage(context.Guild?.Id ?? 0); + return _translations[serverLanguage][command]; } catch (Exception e) { @@ -149,7 +152,7 @@ namespace Geekbot.net.Lib.Localization { try { - if (!_supportedLanguages.Contains(language)) return false; + if (!SupportedLanguages.Contains(language)) return false; var guild = await GetGuild(guildId); guild.Language = language; _database.GuildSettings.Update(guild); @@ -163,7 +166,7 @@ namespace Geekbot.net.Lib.Localization } } - public List SupportedLanguages => _supportedLanguages; + public List SupportedLanguages { get; private set; } private async Task GetGuild(ulong guildId) { From 7dbb2ab89f86473766746613dcab5ad3e0b53d5b Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sun, 3 Mar 2019 21:14:17 -0500 Subject: [PATCH 244/553] Tell the user if the mal api refuses to answer --- Geekbot.net/Commands/Integrations/Mal.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Geekbot.net/Commands/Integrations/Mal.cs b/Geekbot.net/Commands/Integrations/Mal.cs index 88f500e..1ad50bb 100644 --- a/Geekbot.net/Commands/Integrations/Mal.cs +++ b/Geekbot.net/Commands/Integrations/Mal.cs @@ -1,6 +1,7 @@ using System; using System.Threading.Tasks; using System.Web; +using System.Xml; using Discord; using Discord.Commands; using Geekbot.net.Lib.Clients; @@ -62,6 +63,10 @@ namespace Geekbot.net.Commands.Integrations "Unfortunally i'm not connected to MyAnimeList.net, please tell my senpai to connect me"); } } + catch (XmlException e) + { + await _errorHandler.HandleCommandException(e, Context, "The MyAnimeList.net API refused to answer"); + } catch (Exception e) { await _errorHandler.HandleCommandException(e, Context); @@ -110,6 +115,10 @@ namespace Geekbot.net.Commands.Integrations "Unfortunally i'm not connected to MyAnimeList.net, please tell my senpai to connect me"); } } + catch (XmlException e) + { + await _errorHandler.HandleCommandException(e, Context, "The MyAnimeList.net API refused to answer"); + } catch (Exception e) { await _errorHandler.HandleCommandException(e, Context); From 0ae9dcce67d40620f85e648ee2311ce163a8b8e6 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Mon, 4 Mar 2019 15:41:09 -0500 Subject: [PATCH 245/553] Update build image for gitlab-ci to match dotnet 2.2 --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 542c761..a348503 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,7 +10,7 @@ before_script: build: stage: build - image: microsoft/dotnet:2.1.401-sdk-stretch + image: mcr.microsoft.com/dotnet/core/sdk:2.2 artifacts: expire_in: 1h paths: From 3d493fa5315931f518cb9569fcf3d20050d676b5 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sun, 17 Mar 2019 17:52:07 +0100 Subject: [PATCH 246/553] Add kanye command --- .../Commands/Randomness/Kanye/Kanye.cs | 53 +++++++++++++++++++ .../Randomness/Kanye/KanyeResponseDto.cs | 8 +++ 2 files changed, 61 insertions(+) create mode 100644 Geekbot.net/Commands/Randomness/Kanye/Kanye.cs create mode 100644 Geekbot.net/Commands/Randomness/Kanye/KanyeResponseDto.cs diff --git a/Geekbot.net/Commands/Randomness/Kanye/Kanye.cs b/Geekbot.net/Commands/Randomness/Kanye/Kanye.cs new file mode 100644 index 0000000..42a6ca7 --- /dev/null +++ b/Geekbot.net/Commands/Randomness/Kanye/Kanye.cs @@ -0,0 +1,53 @@ +using System; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Threading.Tasks; +using Discord.Commands; +using Geekbot.net.Commands.Randomness.Dad; +using Geekbot.net.Lib.ErrorHandling; +using Microsoft.AspNetCore.Hosting.Internal; +using Newtonsoft.Json; + +namespace Geekbot.net.Commands.Randomness.Kanye +{ + public class Kanye : ModuleBase + { + private readonly IErrorHandler _errorHandler; + + public Kanye(IErrorHandler errorHandler) + { + _errorHandler = errorHandler; + } + + [Command("kanye", RunMode = RunMode.Async)] + [Summary("A random kayne west quote")] + public async Task Say() + { + try + { + using (var client = new HttpClient()) + { + try + { + client.DefaultRequestHeaders.Accept.Clear(); + client.DefaultRequestHeaders.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); + var response = await client.GetAsync("https://api.kanye.rest/"); + response.EnsureSuccessStatusCode(); + + var stringResponse = await response.Content.ReadAsStringAsync(); + var data = JsonConvert.DeserializeObject(stringResponse); + await ReplyAsync(data.Quote); + } + catch (HttpRequestException) + { + await ReplyAsync("Api down..."); + } + } + } + catch (Exception e) + { + await _errorHandler.HandleCommandException(e, Context); + } + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Randomness/Kanye/KanyeResponseDto.cs b/Geekbot.net/Commands/Randomness/Kanye/KanyeResponseDto.cs new file mode 100644 index 0000000..ff74f37 --- /dev/null +++ b/Geekbot.net/Commands/Randomness/Kanye/KanyeResponseDto.cs @@ -0,0 +1,8 @@ +namespace Geekbot.net.Commands.Randomness.Kanye +{ + public class KanyeResponseDto + { + public string Id { get; set; } + public string Quote { get; set; } + } +} \ No newline at end of file From 1e98b44cb7392b76eb9a75cd0c5c5c37bdf41f58 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sun, 17 Mar 2019 18:32:56 +0100 Subject: [PATCH 247/553] Add Attribute to disable commands in DMs --- .../DisableInDirectMessageAttribute.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 Geekbot.net/Lib/CommandPreconditions/DisableInDirectMessageAttribute.cs diff --git a/Geekbot.net/Lib/CommandPreconditions/DisableInDirectMessageAttribute.cs b/Geekbot.net/Lib/CommandPreconditions/DisableInDirectMessageAttribute.cs new file mode 100644 index 0000000..110b69b --- /dev/null +++ b/Geekbot.net/Lib/CommandPreconditions/DisableInDirectMessageAttribute.cs @@ -0,0 +1,16 @@ +using System; +using System.Threading.Tasks; +using Discord.Commands; + +namespace Geekbot.net.Lib.CommandPreconditions +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] + public class DisableInDirectMessageAttribute : PreconditionAttribute + { + public override Task CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services) + { + var result = context.Guild.Id != 0 ? PreconditionResult.FromSuccess() : PreconditionResult.FromError("Command unavailable in Direct Messaging"); + return Task.FromResult(result); + } + } +} \ No newline at end of file From de408dbfd999c11c5daadc85df708a32f60ddb22 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sun, 17 Mar 2019 18:33:18 +0100 Subject: [PATCH 248/553] Apply DM Disable attribute to some commands --- Geekbot.net/Commands/Admin/Admin.cs | 2 ++ Geekbot.net/Commands/Admin/Mod.cs | 2 ++ Geekbot.net/Commands/Admin/Role.cs | 2 ++ Geekbot.net/Commands/User/GuildInfo.cs | 2 ++ Geekbot.net/Commands/User/Karma.cs | 2 ++ Geekbot.net/Commands/User/Ranking/Rank.cs | 2 ++ Geekbot.net/Commands/User/Stats.cs | 2 ++ Geekbot.net/Commands/Utils/Poll.cs | 2 ++ Geekbot.net/Commands/Utils/Quote/Quote.cs | 2 ++ 9 files changed, 18 insertions(+) diff --git a/Geekbot.net/Commands/Admin/Admin.cs b/Geekbot.net/Commands/Admin/Admin.cs index fd7bbc6..f60e5df 100644 --- a/Geekbot.net/Commands/Admin/Admin.cs +++ b/Geekbot.net/Commands/Admin/Admin.cs @@ -7,6 +7,7 @@ using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Database; using Geekbot.net.Database.Models; +using Geekbot.net.Lib.CommandPreconditions; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Localization; @@ -15,6 +16,7 @@ namespace Geekbot.net.Commands.Admin { [Group("admin")] [RequireUserPermission(GuildPermission.Administrator)] + [DisableInDirectMessage] public class Admin : ModuleBase { private readonly DiscordSocketClient _client; diff --git a/Geekbot.net/Commands/Admin/Mod.cs b/Geekbot.net/Commands/Admin/Mod.cs index e1653e9..6c6be5a 100644 --- a/Geekbot.net/Commands/Admin/Mod.cs +++ b/Geekbot.net/Commands/Admin/Mod.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.WebSocket; +using Geekbot.net.Lib.CommandPreconditions; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.UserRepository; @@ -13,6 +14,7 @@ namespace Geekbot.net.Commands.Admin [RequireUserPermission(GuildPermission.KickMembers)] [RequireUserPermission(GuildPermission.ManageMessages)] [RequireUserPermission(GuildPermission.ManageRoles)] + [DisableInDirectMessage] public class Mod : ModuleBase { private readonly DiscordSocketClient _client; diff --git a/Geekbot.net/Commands/Admin/Role.cs b/Geekbot.net/Commands/Admin/Role.cs index a76c9d5..aa767d1 100644 --- a/Geekbot.net/Commands/Admin/Role.cs +++ b/Geekbot.net/Commands/Admin/Role.cs @@ -7,6 +7,7 @@ using Discord.Commands; using Discord.Net; using Geekbot.net.Database; using Geekbot.net.Database.Models; +using Geekbot.net.Lib.CommandPreconditions; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.ReactionListener; @@ -14,6 +15,7 @@ using Geekbot.net.Lib.ReactionListener; namespace Geekbot.net.Commands.Admin { [Group("role")] + [DisableInDirectMessage] public class Role : ModuleBase { private readonly DatabaseContext _database; diff --git a/Geekbot.net/Commands/User/GuildInfo.cs b/Geekbot.net/Commands/User/GuildInfo.cs index 342f80f..6c8b941 100644 --- a/Geekbot.net/Commands/User/GuildInfo.cs +++ b/Geekbot.net/Commands/User/GuildInfo.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Database; +using Geekbot.net.Lib.CommandPreconditions; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Levels; @@ -25,6 +26,7 @@ namespace Geekbot.net.Commands.User [Command("serverstats", RunMode = RunMode.Async)] [Summary("Show some info about the bot.")] + [DisableInDirectMessage] public async Task GetInfo() { try diff --git a/Geekbot.net/Commands/User/Karma.cs b/Geekbot.net/Commands/User/Karma.cs index 39b05be..e2a4739 100644 --- a/Geekbot.net/Commands/User/Karma.cs +++ b/Geekbot.net/Commands/User/Karma.cs @@ -5,12 +5,14 @@ using Discord; using Discord.Commands; using Geekbot.net.Database; using Geekbot.net.Database.Models; +using Geekbot.net.Lib.CommandPreconditions; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Localization; namespace Geekbot.net.Commands.User { + [DisableInDirectMessage] public class Karma : ModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/Geekbot.net/Commands/User/Ranking/Rank.cs b/Geekbot.net/Commands/User/Ranking/Rank.cs index 9c37a4a..9a08d98 100644 --- a/Geekbot.net/Commands/User/Ranking/Rank.cs +++ b/Geekbot.net/Commands/User/Ranking/Rank.cs @@ -5,6 +5,7 @@ using System.Text; using System.Threading.Tasks; using Discord.Commands; using Geekbot.net.Database; +using Geekbot.net.Lib.CommandPreconditions; using Geekbot.net.Lib.Converters; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; @@ -33,6 +34,7 @@ namespace Geekbot.net.Commands.User.Ranking [Command("rank", RunMode = RunMode.Async)] [Summary("get user top 10 in messages or karma")] + [DisableInDirectMessage] public async Task RankCmd([Summary("type")] string typeUnformated = "messages", [Summary("amount")] int amount = 10) { try diff --git a/Geekbot.net/Commands/User/Stats.cs b/Geekbot.net/Commands/User/Stats.cs index a230456..4145d03 100644 --- a/Geekbot.net/Commands/User/Stats.cs +++ b/Geekbot.net/Commands/User/Stats.cs @@ -5,6 +5,7 @@ using Discord; using Discord.Commands; using Geekbot.net.Database; using Geekbot.net.Lib.AlmostRedis; +using Geekbot.net.Lib.CommandPreconditions; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Levels; @@ -28,6 +29,7 @@ namespace Geekbot.net.Commands.User [Command("stats", RunMode = RunMode.Async)] [Summary("Get information about this user")] + [DisableInDirectMessage] public async Task User([Summary("@someone")] IUser user = null) { try diff --git a/Geekbot.net/Commands/Utils/Poll.cs b/Geekbot.net/Commands/Utils/Poll.cs index 598e78c..617d6e2 100644 --- a/Geekbot.net/Commands/Utils/Poll.cs +++ b/Geekbot.net/Commands/Utils/Poll.cs @@ -7,6 +7,7 @@ using Discord; using Discord.Commands; using Geekbot.net.Database; using Geekbot.net.Database.Models; +using Geekbot.net.Lib.CommandPreconditions; using Geekbot.net.Lib.Converters; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; @@ -15,6 +16,7 @@ using Geekbot.net.Lib.UserRepository; namespace Geekbot.net.Commands.Utils { [Group("poll")] + [DisableInDirectMessage] public class Poll : ModuleBase { private readonly IEmojiConverter _emojiConverter; diff --git a/Geekbot.net/Commands/Utils/Quote/Quote.cs b/Geekbot.net/Commands/Utils/Quote/Quote.cs index 9a1d072..e2456e7 100644 --- a/Geekbot.net/Commands/Utils/Quote/Quote.cs +++ b/Geekbot.net/Commands/Utils/Quote/Quote.cs @@ -5,6 +5,7 @@ using Discord; using Discord.Commands; using Geekbot.net.Database; using Geekbot.net.Database.Models; +using Geekbot.net.Lib.CommandPreconditions; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Polyfills; @@ -12,6 +13,7 @@ using Geekbot.net.Lib.Polyfills; namespace Geekbot.net.Commands.Utils.Quote { [Group("quote")] + [DisableInDirectMessage] public class Quote : ModuleBase { private readonly IErrorHandler _errorHandler; From 99ece47925a80086638c6eae70c4c05229818a03 Mon Sep 17 00:00:00 2001 From: Runebaas Date: Sun, 17 Mar 2019 18:38:33 +0100 Subject: [PATCH 249/553] Release 4.1.0 --- .gitlab-ci.yml | 6 +++--- Geekbot.net/Geekbot.net.csproj | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a348503..8c7a530 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -28,9 +28,9 @@ sentry: dependencies: - build script: - - sentry-cli releases new -p geekbot 4.0.0-${CI_COMMIT_SHA:0:8} - - sentry-cli releases set-commits --auto 4.0.0-${CI_COMMIT_SHA:0:8} - - sentry-cli releases deploys 4.0.0-${CI_COMMIT_SHA:0:8} new -e Production + - sentry-cli releases new -p geekbot 4.1.0-${CI_COMMIT_SHA:0:8} + - sentry-cli releases set-commits --auto 4.1.0-${CI_COMMIT_SHA:0:8} + - sentry-cli releases deploys 4.1.0-${CI_COMMIT_SHA:0:8} new -e Production deploy: stage: deploy diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 9ea7546..c0bdca2 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -4,7 +4,7 @@ netcoreapp2.2 win-x64;linux-x64 derp.ico - 4.0.0 + 4.1.0 $(VersionSuffix) $(Version)-$(VersionSuffix) $(Version)-DEV From 8f7aa097632771a8c0932fa24e41f23e6b97dd45 Mon Sep 17 00:00:00 2001 From: Daan Date: Thu, 11 Apr 2019 09:33:03 +0000 Subject: [PATCH 250/553] Add SAST to the build pipeline --- .gitlab-ci.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8c7a530..9149e9c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,5 +1,6 @@ stages: - build + - security - ops - deploy @@ -20,6 +21,36 @@ build: - dotnet test Tests - dotnet publish --version-suffix ${CI_COMMIT_SHA:0:8} --configuration Release -o Binaries ./ +sast: + stage: security + image: docker:stable + variables: + DOCKER_DRIVER: overlay2 + allow_failure: true + services: + - docker:stable-dind + script: + - export SAST_VERSION=${SP_VERSION:-$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')} + - | + docker run \ + --env SAST_ANALYZER_IMAGES \ + --env SAST_ANALYZER_IMAGE_PREFIX \ + --env SAST_ANALYZER_IMAGE_TAG \ + --env SAST_DEFAULT_ANALYZERS \ + --env SAST_BRAKEMAN_LEVEL \ + --env SAST_GOSEC_LEVEL \ + --env SAST_FLAWFINDER_LEVEL \ + --env SAST_DOCKER_CLIENT_NEGOTIATION_TIMEOUT \ + --env SAST_PULL_ANALYZER_IMAGE_TIMEOUT \ + --env SAST_RUN_ANALYZER_TIMEOUT \ + --volume "$PWD:/code" \ + --volume /var/run/docker.sock:/var/run/docker.sock \ + "registry.gitlab.com/gitlab-org/security-products/sast:$SAST_VERSION" /app/bin/run /code + dependencies: [] + artifacts: + reports: + sast: gl-sast-report.json + sentry: stage: ops image: getsentry/sentry-cli From d761e0bf10795336f3eac1a81b50d0affba8af41 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 1 May 2019 18:22:44 +0200 Subject: [PATCH 251/553] Add some dabbing --- Geekbot.net/Commands/Randomness/RandomAnimals.cs | 7 +++++++ Geekbot.net/Lib/Media/IMediaProvider.cs | 1 + Geekbot.net/Lib/Media/MediaProvider.cs | 14 ++++++++++++++ Geekbot.net/Storage/dab | 8 ++++++++ 4 files changed, 30 insertions(+) create mode 100644 Geekbot.net/Storage/dab diff --git a/Geekbot.net/Commands/Randomness/RandomAnimals.cs b/Geekbot.net/Commands/Randomness/RandomAnimals.cs index 38061b1..8562908 100644 --- a/Geekbot.net/Commands/Randomness/RandomAnimals.cs +++ b/Geekbot.net/Commands/Randomness/RandomAnimals.cs @@ -64,6 +64,13 @@ namespace Geekbot.net.Commands.Randomness { await ReplyAsync("", false, Eb(_mediaProvider.GetFox())); } + + [Command("dab", RunMode = RunMode.Async)] + [Summary("Get a random dab image")] + public async Task Dab() + { + await ReplyAsync("", false, Eb(_mediaProvider.GetDab())); + } private static Embed Eb(string image) { diff --git a/Geekbot.net/Lib/Media/IMediaProvider.cs b/Geekbot.net/Lib/Media/IMediaProvider.cs index 79c6c98..a646cea 100644 --- a/Geekbot.net/Lib/Media/IMediaProvider.cs +++ b/Geekbot.net/Lib/Media/IMediaProvider.cs @@ -10,5 +10,6 @@ string GetTurtle(); string GetPinguin(); string GetFox(); + string GetDab(); } } \ No newline at end of file diff --git a/Geekbot.net/Lib/Media/MediaProvider.cs b/Geekbot.net/Lib/Media/MediaProvider.cs index 7f883ae..c88b696 100644 --- a/Geekbot.net/Lib/Media/MediaProvider.cs +++ b/Geekbot.net/Lib/Media/MediaProvider.cs @@ -16,6 +16,7 @@ namespace Geekbot.net.Lib.Media private string[] _turtlesImages; private string[] _pinguinImages; private string[] _foxImages; + private string[] _dabImages; public MediaProvider(IGeekbotLogger logger) { @@ -32,6 +33,7 @@ namespace Geekbot.net.Lib.Media LoadTurtles(); LoadPinguins(); LoadFoxes(); + LoadDab(); } private void LoadCheckem() @@ -90,6 +92,13 @@ namespace Geekbot.net.Lib.Media _logger.Trace(LogSource.Geekbot, $"Loaded {_foxImages.Length} Foxes Images"); } + private void LoadDab() + { + var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/dab")); + _dabImages = rawLinks.Split("\n"); + _logger.Trace(LogSource.Geekbot, $"Loaded {_dabImages.Length} Dab Images"); + } + public string GetCheckem() { return _checkemImages[_random.Next(0, _checkemImages.Length)]; @@ -129,5 +138,10 @@ namespace Geekbot.net.Lib.Media { return _foxImages[_random.Next(0, _foxImages.Length)]; } + + public string GetDab() + { + return _dabImages[_random.Next(0, _dabImages.Length)]; + } } } \ No newline at end of file diff --git a/Geekbot.net/Storage/dab b/Geekbot.net/Storage/dab new file mode 100644 index 0000000..cba5a5c --- /dev/null +++ b/Geekbot.net/Storage/dab @@ -0,0 +1,8 @@ +https://pre00.deviantart.net/dcde/th/pre/i/2018/247/8/1/dabbing_pug_cute_dab_dance_by_manekibb-dcm2lvd.png +https://banner2.kisspng.com/20180625/xfv/kisspng-squidward-tentacles-dab-desktop-wallpaper-dab-emoji-5b31a97a839bf2.6353972915299813065391.jpg +https://djbooth.net/.image/t_share/MTUzNDg2MDIzOTU4NzM0NzA1/life-death-of-dab-dancejpg.jpg +https://res.cloudinary.com/teepublic/image/private/s--gfsWHvaH--/t_Preview/b_rgb:262c3a,c_limit,f_jpg,h_630,q_90,w_630/v1493209189/production/designs/1524888_1.jpg +https://i1.wp.com/fortniteskins.net/wp-content/uploads/2018/04/dab-skin-1.png?quality=90&strip=all&ssl=1 +https://i.pinimg.com/originals/12/d4/0a/12d40a8fc66b7a7ea8b9044ee0303974.png +https://images.bewakoof.com/t540/dab-penguin-boyfriend-t-shirt-women-s-printed-boyfriend-t-shirts-196918-1538034349.jpg +https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSKH1FLh5L3pOR2tamx-5OBqm_W2FFl8F7gteTAs2vMowwJ1Y32 \ No newline at end of file From 38fc6c7f93e6717bd945e3381e73cceec80b4214 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 1 May 2019 18:34:42 +0200 Subject: [PATCH 252/553] Copy dab file... --- Geekbot.net/Geekbot.net.csproj | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index c0bdca2..fcf7b95 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -93,6 +93,9 @@ Always + + PreserveNewest + From b01094f4c26b4c8f5eb05d2ec3368d4e8a1bc5a1 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 1 May 2019 18:38:02 +0200 Subject: [PATCH 253/553] Remove SAST from pipeline --- .gitlab-ci.yml | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9149e9c..8c7a530 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,6 +1,5 @@ stages: - build - - security - ops - deploy @@ -21,36 +20,6 @@ build: - dotnet test Tests - dotnet publish --version-suffix ${CI_COMMIT_SHA:0:8} --configuration Release -o Binaries ./ -sast: - stage: security - image: docker:stable - variables: - DOCKER_DRIVER: overlay2 - allow_failure: true - services: - - docker:stable-dind - script: - - export SAST_VERSION=${SP_VERSION:-$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')} - - | - docker run \ - --env SAST_ANALYZER_IMAGES \ - --env SAST_ANALYZER_IMAGE_PREFIX \ - --env SAST_ANALYZER_IMAGE_TAG \ - --env SAST_DEFAULT_ANALYZERS \ - --env SAST_BRAKEMAN_LEVEL \ - --env SAST_GOSEC_LEVEL \ - --env SAST_FLAWFINDER_LEVEL \ - --env SAST_DOCKER_CLIENT_NEGOTIATION_TIMEOUT \ - --env SAST_PULL_ANALYZER_IMAGE_TIMEOUT \ - --env SAST_RUN_ANALYZER_TIMEOUT \ - --volume "$PWD:/code" \ - --volume /var/run/docker.sock:/var/run/docker.sock \ - "registry.gitlab.com/gitlab-org/security-products/sast:$SAST_VERSION" /app/bin/run /code - dependencies: [] - artifacts: - reports: - sast: gl-sast-report.json - sentry: stage: ops image: getsentry/sentry-cli From 119f4586c7932fa78618f4343d45256e64a8f11d Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 10 May 2019 20:51:13 +0200 Subject: [PATCH 254/553] Add Some Cookies --- Geekbot.net/Commands/Rpg/Cookies.cs | 95 +++++++++++++++++++++ Geekbot.net/Database/DatabaseContext.cs | 1 + Geekbot.net/Database/Models/CookiesModel.cs | 21 +++++ 3 files changed, 117 insertions(+) create mode 100644 Geekbot.net/Commands/Rpg/Cookies.cs create mode 100644 Geekbot.net/Database/Models/CookiesModel.cs diff --git a/Geekbot.net/Commands/Rpg/Cookies.cs b/Geekbot.net/Commands/Rpg/Cookies.cs new file mode 100644 index 0000000..c96d456 --- /dev/null +++ b/Geekbot.net/Commands/Rpg/Cookies.cs @@ -0,0 +1,95 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Discord.Commands; +using Geekbot.net.Database; +using Geekbot.net.Database.Models; +using Geekbot.net.Lib.CommandPreconditions; +using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Extensions; +using Geekbot.net.Lib.Localization; + +namespace Geekbot.net.Commands.Rpg +{ + [DisableInDirectMessage] + [Group("cookie")] + public class Cookies : ModuleBase + { + private readonly DatabaseContext _database; + private readonly IErrorHandler _errorHandler; + private readonly ITranslationHandler _translation; + + public Cookies(DatabaseContext database, IErrorHandler errorHandler, ITranslationHandler translation) + { + _database = database; + _errorHandler = errorHandler; + _translation = translation; + } + + [Command("get", RunMode = RunMode.Async)] + [Summary("Get a cookie every 24 hours")] + public async Task GetCookies() + { + try + { + var actor = await GetUser(Context.User.Id); + if (actor.LastPayout.Value.AddHours(24) > DateTimeOffset.Now) + { + await ReplyAsync($"You already got cookies in the last 24 hours, wait until {actor.LastPayout.Value.AddHours(24):HH:mm:ss} for more cookies"); + return; + } + actor.Cookies += 10; + actor.LastPayout = DateTimeOffset.Now; + await SetUser(actor); + await ReplyAsync($"You got 10 cookies, there are now {actor.Cookies} cookies in you cookie jar"); + + } + catch (Exception e) + { + await _errorHandler.HandleCommandException(e, Context); + } + } + + [Command("jar", RunMode = RunMode.Async)] + [Summary("Look at your cookie jar")] + public async Task PeekIntoCookieJar() + { + try + { + var actor = await GetUser(Context.User.Id); + await ReplyAsync($"There are {actor.Cookies} cookies in you cookie jar"); + + } + catch (Exception e) + { + await _errorHandler.HandleCommandException(e, Context); + } + } + + private async Task GetUser(ulong userId) + { + var user = _database.Cookies.FirstOrDefault(u =>u.GuildId.Equals(Context.Guild.Id.AsLong()) && u.UserId.Equals(userId.AsLong())) ?? await CreateNewRow(userId); + return user; + } + + private async Task SetUser(CookiesModel user) + { + _database.Cookies.Update(user); + await _database.SaveChangesAsync(); + } + + private async Task CreateNewRow(ulong userId) + { + var user = new CookiesModel() + { + GuildId = Context.Guild.Id.AsLong(), + UserId = userId.AsLong(), + Cookies = 0, + LastPayout = DateTimeOffset.MinValue + }; + var newUser = _database.Cookies.Add(user).Entity; + await _database.SaveChangesAsync(); + return newUser; + } + } +} diff --git a/Geekbot.net/Database/DatabaseContext.cs b/Geekbot.net/Database/DatabaseContext.cs index ab786b1..cbfa30d 100644 --- a/Geekbot.net/Database/DatabaseContext.cs +++ b/Geekbot.net/Database/DatabaseContext.cs @@ -17,5 +17,6 @@ namespace Geekbot.net.Database public DbSet Globals { get; set; } public DbSet RoleSelfService { get; set; } public DbSet Polls { get; set; } + public DbSet Cookies { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Database/Models/CookiesModel.cs b/Geekbot.net/Database/Models/CookiesModel.cs new file mode 100644 index 0000000..228f3b0 --- /dev/null +++ b/Geekbot.net/Database/Models/CookiesModel.cs @@ -0,0 +1,21 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace Geekbot.net.Database.Models +{ + public class CookiesModel + { + [Key] + public int Id { get; set; } + + [Required] + public long GuildId { get; set; } + + [Required] + public long UserId { get; set; } + + public int Cookies { get; set; } = 0; + + public DateTimeOffset? LastPayout { get; set; } + } +} \ No newline at end of file From efaaf594f0b2b048747576f2e67528c8514134b7 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 10 May 2019 21:10:49 +0200 Subject: [PATCH 255/553] Make sure that stats works with the inmemory database and add cookies --- Geekbot.net/Commands/User/Stats.cs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/Geekbot.net/Commands/User/Stats.cs b/Geekbot.net/Commands/User/Stats.cs index 4145d03..6ddf7d4 100644 --- a/Geekbot.net/Commands/User/Stats.cs +++ b/Geekbot.net/Commands/User/Stats.cs @@ -42,17 +42,20 @@ namespace Geekbot.net.Commands.User var joinedDayAgo = Math.Floor((DateTime.Now - joinedAt).TotalDays); var messages = _database.Messages - .First(e => e.GuildId.Equals(Context.Guild.Id.AsLong()) && e.UserId.Equals(userInfo.Id.AsLong())) - .MessageCount; + ?.FirstOrDefault(e => e.GuildId.Equals(Context.Guild.Id.AsLong()) && e.UserId.Equals(userInfo.Id.AsLong())) + ?.MessageCount ?? 0; var guildMessages = _database.Messages - .Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())) - .Select(e => e.MessageCount) - .Sum(); -// var messages = (int) _redis.Db.HashGet($"{Context.Guild.Id}:Messages", userInfo.Id.ToString()); -// var guildMessages = (int) _redis.Db.HashGet($"{Context.Guild.Id}:Messages", 0.ToString()); + ?.Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())) + .Select(e => e.MessageCount) + .Sum() ?? 0; + var level = _levelCalc.GetLevel(messages); - var percent = Math.Round((double) (100 * messages) / guildMessages, 2); + var percent = Math.Round((double) (100 * messages) / guildMessages, digits: 2); + + var cookies = _database.Cookies + ?.FirstOrDefault(e => e.GuildId.Equals(Context.Guild.Id.AsLong()) && e.UserId.Equals(userInfo.Id.AsLong())) + ?.Cookies ?? 0; var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder() @@ -77,6 +80,7 @@ namespace Geekbot.net.Commands.User .AddInlineField("Server Total", $"{percent}%"); if (correctRolls != null) eb.AddInlineField("Guessed Rolls", correctRolls.Rolls); + if (cookies > 0) eb.AddInlineField("Cookies", cookies); await ReplyAsync("", false, eb.Build()); } From d3038b90a8f5a7717699bbddfb1dfc00107c8d13 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 10 May 2019 21:37:52 +0200 Subject: [PATCH 256/553] Add Cookies to the highscore --- Geekbot.net/Commands/User/Ranking/Rank.cs | 2 +- Geekbot.net/Lib/Highscores/HighscoreManager.cs | 12 ++++++++++++ Geekbot.net/Lib/Highscores/HighscoreTypes.cs | 3 ++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Geekbot.net/Commands/User/Ranking/Rank.cs b/Geekbot.net/Commands/User/Ranking/Rank.cs index 9a08d98..8a79fa6 100644 --- a/Geekbot.net/Commands/User/Ranking/Rank.cs +++ b/Geekbot.net/Commands/User/Ranking/Rank.cs @@ -46,7 +46,7 @@ namespace Geekbot.net.Commands.User.Ranking } catch { - await ReplyAsync("Valid types are '`messages`' '`karma`', '`rolls`'"); + await ReplyAsync("Valid types are '`messages`' '`karma`', '`rolls`' and '`cookies`'"); return; } diff --git a/Geekbot.net/Lib/Highscores/HighscoreManager.cs b/Geekbot.net/Lib/Highscores/HighscoreManager.cs index c684254..f3b3a18 100644 --- a/Geekbot.net/Lib/Highscores/HighscoreManager.cs +++ b/Geekbot.net/Lib/Highscores/HighscoreManager.cs @@ -34,6 +34,9 @@ namespace Geekbot.net.Lib.Highscores case HighscoreTypes.rolls: list = GetRollsList(guildId, amount); break; + case HighscoreTypes.cookies: + list = GetCookiesList(guildId, amount); + break; default: list = new Dictionary(); break; @@ -102,5 +105,14 @@ namespace Geekbot.net.Lib.Highscores .Take(amount) .ToDictionary(key => key.UserId.AsUlong(), key => key.Rolls); } + + public Dictionary GetCookiesList(ulong guildId, int amount) + { + return _database.Cookies + .Where(k => k.GuildId.Equals(guildId.AsLong())) + .OrderByDescending(o => o.Cookies) + .Take(amount) + .ToDictionary(key => key.UserId.AsUlong(), key => key.Cookies); + } } } \ No newline at end of file diff --git a/Geekbot.net/Lib/Highscores/HighscoreTypes.cs b/Geekbot.net/Lib/Highscores/HighscoreTypes.cs index 492d08d..adf5698 100644 --- a/Geekbot.net/Lib/Highscores/HighscoreTypes.cs +++ b/Geekbot.net/Lib/Highscores/HighscoreTypes.cs @@ -4,6 +4,7 @@ { messages, karma, - rolls + rolls, + cookies } } \ No newline at end of file From ba4de946dcd90f6da16f5bd7733a2f643e21b36e Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 10 May 2019 22:06:58 +0200 Subject: [PATCH 257/553] Add translations for cookies/guetzli --- Geekbot.net/Commands/Rpg/Cookies.cs | 9 +++++---- Geekbot.net/Lib/Localization/Translations.json | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/Geekbot.net/Commands/Rpg/Cookies.cs b/Geekbot.net/Commands/Rpg/Cookies.cs index c96d456..f55fa6c 100644 --- a/Geekbot.net/Commands/Rpg/Cookies.cs +++ b/Geekbot.net/Commands/Rpg/Cookies.cs @@ -32,16 +32,17 @@ namespace Geekbot.net.Commands.Rpg { try { + var transDict = await _translation.GetDict(Context); var actor = await GetUser(Context.User.Id); if (actor.LastPayout.Value.AddHours(24) > DateTimeOffset.Now) { - await ReplyAsync($"You already got cookies in the last 24 hours, wait until {actor.LastPayout.Value.AddHours(24):HH:mm:ss} for more cookies"); + await ReplyAsync(string.Format(transDict["WaitForMoreCookies"], actor.LastPayout.Value.AddHours(24).ToString("HH:mm:ss"))); return; } actor.Cookies += 10; actor.LastPayout = DateTimeOffset.Now; await SetUser(actor); - await ReplyAsync($"You got 10 cookies, there are now {actor.Cookies} cookies in you cookie jar"); + await ReplyAsync(string.Format(transDict["GetCookies"], 10, actor.Cookies)); } catch (Exception e) @@ -56,9 +57,9 @@ namespace Geekbot.net.Commands.Rpg { try { + var transDict = await _translation.GetDict(Context); var actor = await GetUser(Context.User.Id); - await ReplyAsync($"There are {actor.Cookies} cookies in you cookie jar"); - + await ReplyAsync(string.Format(transDict["InYourJar"], actor.Cookies)); } catch (Exception e) { diff --git a/Geekbot.net/Lib/Localization/Translations.json b/Geekbot.net/Lib/Localization/Translations.json index 2d3414e..41865a1 100644 --- a/Geekbot.net/Lib/Localization/Translations.json +++ b/Geekbot.net/Lib/Localization/Translations.json @@ -96,5 +96,19 @@ "EN": ":red_circle: {0}, you can't guess the same number again", "CHDE": ":red_circle: {0}, du chasch nid nomol es gliche rate" } + }, + "cookie": { + "GetCookies": { + "EN": "You got {0} cookies, there are now {1} cookies in you cookie jar", + "CHDE": "Du häsch {0} guetzli becho, du häsch jetzt {1} guetzli ih dr büchse" + }, + "WaitForMoreCookies": { + "EN": "You already got cookies in the last 24 hours, wait until {0} for more cookies", + "CHDE": "Du hesch scho guetzli becho ih de letzti 24 stund, wart no bis {0}" + }, + "InYourJar": { + "EN": "There are {0} cookies in you cookie jar", + "CHDE": "Es hät {0} guetzli ih dineri büchs" + } } } \ No newline at end of file From fd75fef9739d4eb593c4e396117d1cb5e585315c Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 10 May 2019 22:30:48 +0200 Subject: [PATCH 258/553] Add the ability for users to give cookies away --- Geekbot.net/Commands/Rpg/Cookies.cs | 32 +++++++++++++++++++ .../Lib/Localization/Translations.json | 8 +++++ 2 files changed, 40 insertions(+) diff --git a/Geekbot.net/Commands/Rpg/Cookies.cs b/Geekbot.net/Commands/Rpg/Cookies.cs index f55fa6c..21077bf 100644 --- a/Geekbot.net/Commands/Rpg/Cookies.cs +++ b/Geekbot.net/Commands/Rpg/Cookies.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Threading.Tasks; +using Discord; using Discord.Commands; using Geekbot.net.Database; using Geekbot.net.Database.Models; @@ -67,6 +68,37 @@ namespace Geekbot.net.Commands.Rpg } } + [Command("give", RunMode = RunMode.Async)] + [Summary("Give cookies to someone")] + public async Task PeekIntoCookieJar([Summary("User")] IUser user, [Summary("amount")] int amount) + { + try + { + var transDict = await _translation.GetDict(Context); + var giver = await GetUser(Context.User.Id); + + if (giver.Cookies < amount) + { + await ReplyAsync(string.Format(transDict["NotEnoughToGive"])); + return; + } + + var taker = await GetUser(user.Id); + + giver.Cookies -= amount; + taker.Cookies += amount; + + await SetUser(giver); + await SetUser(taker); + + await ReplyAsync(string.Format(transDict["Given"], amount, user.Username)); + } + catch (Exception e) + { + await _errorHandler.HandleCommandException(e, Context); + } + } + private async Task GetUser(ulong userId) { var user = _database.Cookies.FirstOrDefault(u =>u.GuildId.Equals(Context.Guild.Id.AsLong()) && u.UserId.Equals(userId.AsLong())) ?? await CreateNewRow(userId); diff --git a/Geekbot.net/Lib/Localization/Translations.json b/Geekbot.net/Lib/Localization/Translations.json index 41865a1..191c4ff 100644 --- a/Geekbot.net/Lib/Localization/Translations.json +++ b/Geekbot.net/Lib/Localization/Translations.json @@ -109,6 +109,14 @@ "InYourJar": { "EN": "There are {0} cookies in you cookie jar", "CHDE": "Es hät {0} guetzli ih dineri büchs" + }, + "Given": { + "EN": "You gave {0} cookies to {1}", + "CHDE": "Du hesch {1} {0} guetzli geh" + }, + "NotEnoughToGive": { + "EN": "You don't have enough cookies", + "CHDE": "Du hesch nid gnueg guetzli" } } } \ No newline at end of file From fe08eee04966450b1c2e1b9ba9cd8c66a3482498 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 10 May 2019 22:42:53 +0200 Subject: [PATCH 259/553] Let users eat their cookies --- Geekbot.net/Commands/Rpg/Cookies.cs | 30 ++++++++++++++++++- .../Lib/Localization/Translations.json | 8 +++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/Geekbot.net/Commands/Rpg/Cookies.cs b/Geekbot.net/Commands/Rpg/Cookies.cs index 21077bf..3e3e98c 100644 --- a/Geekbot.net/Commands/Rpg/Cookies.cs +++ b/Geekbot.net/Commands/Rpg/Cookies.cs @@ -70,7 +70,7 @@ namespace Geekbot.net.Commands.Rpg [Command("give", RunMode = RunMode.Async)] [Summary("Give cookies to someone")] - public async Task PeekIntoCookieJar([Summary("User")] IUser user, [Summary("amount")] int amount) + public async Task GiveACookie([Summary("User")] IUser user, [Summary("amount")] int amount) { try { @@ -99,6 +99,34 @@ namespace Geekbot.net.Commands.Rpg } } + [Command("eat", RunMode = RunMode.Async)] + [Summary("Eat a cookie")] + public async Task EatACookie() + { + try + { + var transDict = await _translation.GetDict(Context); + var actor = await GetUser(Context.User.Id); + + if (actor.Cookies < 5) + { + await ReplyAsync(string.Format(transDict["NotEnoughCookiesToEat"])); + return; + } + + var amount = new Random().Next(1, 5); + actor.Cookies -= amount; + + await SetUser(actor); + + await ReplyAsync(string.Format(transDict["AteCookies"], amount, actor.Cookies)); + } + catch (Exception e) + { + await _errorHandler.HandleCommandException(e, Context); + } + } + private async Task GetUser(ulong userId) { var user = _database.Cookies.FirstOrDefault(u =>u.GuildId.Equals(Context.Guild.Id.AsLong()) && u.UserId.Equals(userId.AsLong())) ?? await CreateNewRow(userId); diff --git a/Geekbot.net/Lib/Localization/Translations.json b/Geekbot.net/Lib/Localization/Translations.json index 191c4ff..7747016 100644 --- a/Geekbot.net/Lib/Localization/Translations.json +++ b/Geekbot.net/Lib/Localization/Translations.json @@ -117,6 +117,14 @@ "NotEnoughToGive": { "EN": "You don't have enough cookies", "CHDE": "Du hesch nid gnueg guetzli" + }, + "NotEnoughCookiesToEat": { + "EN": "Your cookie jar looks almost empty, you should probably not eat a cookie", + "CHDE": "Du hesch chuum no guetzli ih dineri büchs, du sötsch warschinli keini esse" + }, + "AteCookies": { + "EN": "You ate {0} cookies, you've only got {1} cookies left", + "CHDE": "Du hesch {0} guetzli gesse und hesch jezt no {1} übrig" } } } \ No newline at end of file From 4143180b42fe54b3e11a1821a6c3fdc98e7c5492 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 11 May 2019 01:18:22 +0200 Subject: [PATCH 260/553] Add a better random number generator --- Geekbot.net/Commands/Games/Roll.cs | 7 ++- Geekbot.net/Commands/Randomness/Ship.cs | 7 ++- Geekbot.net/Commands/Rpg/Cookies.cs | 7 ++- Geekbot.net/Commands/Utils/Dice/Dice.cs | 10 +++- Geekbot.net/Commands/Utils/Quote/Quote.cs | 7 ++- .../IRandomNumberGenerator.cs | 7 +++ .../RandomNumberGenerator.cs | 46 +++++++++++++++++++ Geekbot.net/Program.cs | 3 ++ 8 files changed, 85 insertions(+), 9 deletions(-) create mode 100644 Geekbot.net/Lib/RandomNumberGenerator/IRandomNumberGenerator.cs create mode 100644 Geekbot.net/Lib/RandomNumberGenerator/RandomNumberGenerator.cs diff --git a/Geekbot.net/Commands/Games/Roll.cs b/Geekbot.net/Commands/Games/Roll.cs index 8db295c..ac9279a 100644 --- a/Geekbot.net/Commands/Games/Roll.cs +++ b/Geekbot.net/Commands/Games/Roll.cs @@ -8,6 +8,7 @@ using Geekbot.net.Lib.AlmostRedis; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Localization; +using Geekbot.net.Lib.RandomNumberGenerator; using StackExchange.Redis; namespace Geekbot.net.Commands.Games @@ -18,12 +19,14 @@ namespace Geekbot.net.Commands.Games private readonly IAlmostRedis _redis; private readonly ITranslationHandler _translation; private readonly DatabaseContext _database; + private readonly IRandomNumberGenerator _randomNumberGenerator; - public Roll(IAlmostRedis redis, IErrorHandler errorHandler, ITranslationHandler translation, DatabaseContext database) + public Roll(IAlmostRedis redis, IErrorHandler errorHandler, ITranslationHandler translation, DatabaseContext database, IRandomNumberGenerator randomNumberGenerator) { _redis = redis; _translation = translation; _database = database; + _randomNumberGenerator = randomNumberGenerator; _errorHandler = errorHandler; } @@ -33,7 +36,7 @@ namespace Geekbot.net.Commands.Games { try { - var number = new Random().Next(1, 100); + var number = _randomNumberGenerator.Next(1, 100); var guess = 1000; int.TryParse(stuff, out guess); var transDict = await _translation.GetDict(Context); diff --git a/Geekbot.net/Commands/Randomness/Ship.cs b/Geekbot.net/Commands/Randomness/Ship.cs index 45956b6..3d876ef 100644 --- a/Geekbot.net/Commands/Randomness/Ship.cs +++ b/Geekbot.net/Commands/Randomness/Ship.cs @@ -7,18 +7,21 @@ using Geekbot.net.Database; using Geekbot.net.Database.Models; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; +using Geekbot.net.Lib.RandomNumberGenerator; namespace Geekbot.net.Commands.Randomness { public class Ship : ModuleBase { private readonly IErrorHandler _errorHandler; + private readonly IRandomNumberGenerator _randomNumberGenerator; private readonly DatabaseContext _database; - public Ship(DatabaseContext database, IErrorHandler errorHandler) + public Ship(DatabaseContext database, IErrorHandler errorHandler, IRandomNumberGenerator randomNumberGenerator) { _database = database; _errorHandler = errorHandler; + _randomNumberGenerator = randomNumberGenerator; } [Command("Ship", RunMode = RunMode.Async)] @@ -38,7 +41,7 @@ namespace Geekbot.net.Commands.Randomness var shippingRate = 0; if (dbval == null) { - shippingRate = new Random().Next(1, 100); + shippingRate = _randomNumberGenerator.Next(1, 100); _database.Ships.Add(new ShipsModel() { FirstUserId = userKeys.Item1, diff --git a/Geekbot.net/Commands/Rpg/Cookies.cs b/Geekbot.net/Commands/Rpg/Cookies.cs index 3e3e98c..594dd5e 100644 --- a/Geekbot.net/Commands/Rpg/Cookies.cs +++ b/Geekbot.net/Commands/Rpg/Cookies.cs @@ -9,6 +9,7 @@ using Geekbot.net.Lib.CommandPreconditions; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Localization; +using Geekbot.net.Lib.RandomNumberGenerator; namespace Geekbot.net.Commands.Rpg { @@ -19,12 +20,14 @@ namespace Geekbot.net.Commands.Rpg private readonly DatabaseContext _database; private readonly IErrorHandler _errorHandler; private readonly ITranslationHandler _translation; + private readonly IRandomNumberGenerator _randomNumberGenerator; - public Cookies(DatabaseContext database, IErrorHandler errorHandler, ITranslationHandler translation) + public Cookies(DatabaseContext database, IErrorHandler errorHandler, ITranslationHandler translation , IRandomNumberGenerator randomNumberGenerator) { _database = database; _errorHandler = errorHandler; _translation = translation; + _randomNumberGenerator = randomNumberGenerator; } [Command("get", RunMode = RunMode.Async)] @@ -114,7 +117,7 @@ namespace Geekbot.net.Commands.Rpg return; } - var amount = new Random().Next(1, 5); + var amount = _randomNumberGenerator.Next(1, 5); actor.Cookies -= amount; await SetUser(actor); diff --git a/Geekbot.net/Commands/Utils/Dice/Dice.cs b/Geekbot.net/Commands/Utils/Dice/Dice.cs index 7733476..8b23fe6 100644 --- a/Geekbot.net/Commands/Utils/Dice/Dice.cs +++ b/Geekbot.net/Commands/Utils/Dice/Dice.cs @@ -4,11 +4,19 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.net.Lib.RandomNumberGenerator; namespace Geekbot.net.Commands.Utils.Dice { public class Dice : ModuleBase { + private readonly IRandomNumberGenerator _randomNumberGenerator; + + public Dice(IRandomNumberGenerator randomNumberGenerator) + { + _randomNumberGenerator = randomNumberGenerator; + } + [Command("dice", RunMode = RunMode.Async)] [Summary("Roll a dice.")] public async Task RollCommand([Remainder] [Summary("diceType")] string diceType = "1d20") @@ -66,7 +74,7 @@ namespace Geekbot.net.Commands.Utils.Dice var results = new List(); for (var i = 0; i < dice.Times; i++) { - var roll = new Random().Next(1, dice.Sides); + var roll = _randomNumberGenerator.Next(1, dice.Sides); total += roll; results.Add(roll); if (roll == dice.Sides) extraText = "**Critical Hit!**"; diff --git a/Geekbot.net/Commands/Utils/Quote/Quote.cs b/Geekbot.net/Commands/Utils/Quote/Quote.cs index e2456e7..a6f3ec9 100644 --- a/Geekbot.net/Commands/Utils/Quote/Quote.cs +++ b/Geekbot.net/Commands/Utils/Quote/Quote.cs @@ -9,6 +9,7 @@ using Geekbot.net.Lib.CommandPreconditions; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Polyfills; +using Geekbot.net.Lib.RandomNumberGenerator; namespace Geekbot.net.Commands.Utils.Quote { @@ -18,11 +19,13 @@ namespace Geekbot.net.Commands.Utils.Quote { private readonly IErrorHandler _errorHandler; private readonly DatabaseContext _database; + private readonly IRandomNumberGenerator _randomNumberGenerator; - public Quote(IErrorHandler errorHandler, DatabaseContext database) + public Quote(IErrorHandler errorHandler, DatabaseContext database, IRandomNumberGenerator randomNumberGenerator) { _errorHandler = errorHandler; _database = database; + _randomNumberGenerator = randomNumberGenerator; } [Command] @@ -39,7 +42,7 @@ namespace Geekbot.net.Commands.Utils.Quote return; } - var random = new Random().Next(s.Count()); + var random = _randomNumberGenerator.Next(0, s.Count()); var quote = s[random]; var embed = QuoteBuilder(quote); diff --git a/Geekbot.net/Lib/RandomNumberGenerator/IRandomNumberGenerator.cs b/Geekbot.net/Lib/RandomNumberGenerator/IRandomNumberGenerator.cs new file mode 100644 index 0000000..32c6285 --- /dev/null +++ b/Geekbot.net/Lib/RandomNumberGenerator/IRandomNumberGenerator.cs @@ -0,0 +1,7 @@ +namespace Geekbot.net.Lib.RandomNumberGenerator +{ + public interface IRandomNumberGenerator + { + int Next(int minValue, int maxExclusiveValue); + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/RandomNumberGenerator/RandomNumberGenerator.cs b/Geekbot.net/Lib/RandomNumberGenerator/RandomNumberGenerator.cs new file mode 100644 index 0000000..79b4620 --- /dev/null +++ b/Geekbot.net/Lib/RandomNumberGenerator/RandomNumberGenerator.cs @@ -0,0 +1,46 @@ +using System; +using System.Security.Cryptography; + +namespace Geekbot.net.Lib.RandomNumberGenerator +{ + public class RandomNumberGenerator : IRandomNumberGenerator + { + readonly RNGCryptoServiceProvider csp; + + public RandomNumberGenerator() + { + csp = new RNGCryptoServiceProvider(); + } + + public int Next(int minValue, int maxExclusiveValue) + { + if (minValue >= maxExclusiveValue) + { + throw new ArgumentOutOfRangeException("minValue must be lower than maxExclusiveValue"); + } + + var diff = (long)maxExclusiveValue - minValue; + var upperBound = uint.MaxValue / diff * diff; + + uint ui; + do + { + ui = GetRandomUInt(); + } while (ui >= upperBound); + return (int)(minValue + (ui % diff)); + } + + private uint GetRandomUInt() + { + var randomBytes = GenerateRandomBytes(sizeof(uint)); + return BitConverter.ToUInt32(randomBytes, 0); + } + + private byte[] GenerateRandomBytes(int bytesNumber) + { + var buffer = new byte[bytesNumber]; + csp.GetBytes(buffer); + return buffer; + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 7b00055..43c16d1 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -19,6 +19,7 @@ using Geekbot.net.Lib.Levels; using Geekbot.net.Lib.Localization; using Geekbot.net.Lib.Logger; using Geekbot.net.Lib.Media; +using Geekbot.net.Lib.RandomNumberGenerator; using Geekbot.net.Lib.ReactionListener; using Geekbot.net.Lib.UserRepository; using Microsoft.EntityFrameworkCore; @@ -124,6 +125,7 @@ namespace Geekbot.net var mtgManaConverter = new MtgManaConverter(); var wikipediaClient = new WikipediaClient(); var audioUtils = new AudioUtils(); + var randomNumberGenerator = new RandomNumberGenerator(); _highscoreManager = new HighscoreManager(_databaseInitializer.Initialize(), _userRepository); _services.AddSingleton(_redis); @@ -137,6 +139,7 @@ namespace Geekbot.net _services.AddSingleton(mtgManaConverter); _services.AddSingleton(wikipediaClient); _services.AddSingleton(audioUtils); + _services.AddSingleton(randomNumberGenerator); _services.AddSingleton(_highscoreManager); _services.AddSingleton(_globalSettings); _services.AddTransient((e) => _databaseInitializer.Initialize()); From 8effc42f92a7f36163de306e5e30387f084e7e78 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 12 May 2019 00:17:34 +0200 Subject: [PATCH 261/553] Rewrite huge parts of the localization class to support plurals and localized date time formating, also created a TranslationGuildContext class for use in commands --- Geekbot.net/Commands/Rpg/Cookies.cs | 23 +-- .../Lib/Localization/ITranslationHandler.cs | 2 + .../Localization/TranslationGuildContext.cs | 90 ++++++++++++ .../Lib/Localization/TranslationHandler.cs | 41 ++++-- .../Lib/Localization/Translations.json | 134 ++++++++++-------- 5 files changed, 211 insertions(+), 79 deletions(-) create mode 100644 Geekbot.net/Lib/Localization/TranslationGuildContext.cs diff --git a/Geekbot.net/Commands/Rpg/Cookies.cs b/Geekbot.net/Commands/Rpg/Cookies.cs index 594dd5e..6d527ef 100644 --- a/Geekbot.net/Commands/Rpg/Cookies.cs +++ b/Geekbot.net/Commands/Rpg/Cookies.cs @@ -36,17 +36,18 @@ namespace Geekbot.net.Commands.Rpg { try { - var transDict = await _translation.GetDict(Context); + var transContext = await _translation.GetGuildContext(Context); var actor = await GetUser(Context.User.Id); if (actor.LastPayout.Value.AddHours(24) > DateTimeOffset.Now) { - await ReplyAsync(string.Format(transDict["WaitForMoreCookies"], actor.LastPayout.Value.AddHours(24).ToString("HH:mm:ss"))); + var formatedWaitTime = transContext.FormatDateTimeAsRemaining(actor.LastPayout.Value.AddHours(24)); + await ReplyAsync(transContext.GetString("WaitForMoreCookies", formatedWaitTime)); return; } actor.Cookies += 10; actor.LastPayout = DateTimeOffset.Now; await SetUser(actor); - await ReplyAsync(string.Format(transDict["GetCookies"], 10, actor.Cookies)); + await ReplyAsync(transContext.GetString("GetCookies", 10, actor.Cookies)); } catch (Exception e) @@ -61,9 +62,9 @@ namespace Geekbot.net.Commands.Rpg { try { - var transDict = await _translation.GetDict(Context); + var transContext = await _translation.GetGuildContext(Context); var actor = await GetUser(Context.User.Id); - await ReplyAsync(string.Format(transDict["InYourJar"], actor.Cookies)); + await ReplyAsync(transContext.GetString("InYourJar", actor.Cookies)); } catch (Exception e) { @@ -77,12 +78,12 @@ namespace Geekbot.net.Commands.Rpg { try { - var transDict = await _translation.GetDict(Context); + var transContext = await _translation.GetGuildContext(Context); var giver = await GetUser(Context.User.Id); if (giver.Cookies < amount) { - await ReplyAsync(string.Format(transDict["NotEnoughToGive"])); + await ReplyAsync(transContext.GetString("NotEnoughToGive")); return; } @@ -94,7 +95,7 @@ namespace Geekbot.net.Commands.Rpg await SetUser(giver); await SetUser(taker); - await ReplyAsync(string.Format(transDict["Given"], amount, user.Username)); + await ReplyAsync(transContext.GetString("Given", amount, user.Username)); } catch (Exception e) { @@ -108,12 +109,12 @@ namespace Geekbot.net.Commands.Rpg { try { - var transDict = await _translation.GetDict(Context); + var transContext = await _translation.GetGuildContext(Context); var actor = await GetUser(Context.User.Id); if (actor.Cookies < 5) { - await ReplyAsync(string.Format(transDict["NotEnoughCookiesToEat"])); + await ReplyAsync(transContext.GetString("NotEnoughCookiesToEat")); return; } @@ -122,7 +123,7 @@ namespace Geekbot.net.Commands.Rpg await SetUser(actor); - await ReplyAsync(string.Format(transDict["AteCookies"], amount, actor.Cookies)); + await ReplyAsync(transContext.GetString("AteCookies", amount, actor.Cookies)); } catch (Exception e) { diff --git a/Geekbot.net/Lib/Localization/ITranslationHandler.cs b/Geekbot.net/Lib/Localization/ITranslationHandler.cs index 2124d4e..7a46e56 100644 --- a/Geekbot.net/Lib/Localization/ITranslationHandler.cs +++ b/Geekbot.net/Lib/Localization/ITranslationHandler.cs @@ -7,8 +7,10 @@ namespace Geekbot.net.Lib.Localization public interface ITranslationHandler { Task GetString(ulong guildId, string command, string stringName); + List GetStrings(string language, string command, string stringName); Task> GetDict(ICommandContext context); Task> GetDict(ICommandContext context, string command); + Task GetGuildContext(ICommandContext context); Task SetLanguage(ulong guildId, string language); List SupportedLanguages { get; } } diff --git a/Geekbot.net/Lib/Localization/TranslationGuildContext.cs b/Geekbot.net/Lib/Localization/TranslationGuildContext.cs new file mode 100644 index 0000000..037ef3a --- /dev/null +++ b/Geekbot.net/Lib/Localization/TranslationGuildContext.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Geekbot.net.Lib.Localization +{ + public class TranslationGuildContext + { + public ITranslationHandler TranslationHandler { get; } + public string Language { get; } + public Dictionary Dict { get; } + + public TranslationGuildContext(ITranslationHandler translationHandler, string language, Dictionary dict) + { + TranslationHandler = translationHandler; + Language = language; + Dict = dict; + } + + public string GetString(string stringToFormat, params object[] args) + { + return string.Format(Dict[stringToFormat] ?? "", args); + } + + public string FormatDateTimeAsRemaining(DateTimeOffset dateTime) + { + var remaining = dateTime - DateTimeOffset.Now; + const string formattable = "{0} {1}"; + var sb = new StringBuilder(); + + if (remaining.Days > 0) + { + var s = GetTimeString(TimeTypes.Days); + sb.AppendFormat(formattable, remaining.Days, GetSingOrPlur(remaining.Days, s)); + } + + if (remaining.Hours > 0) + { + if (sb.Length > 0) sb.Append(", "); + var s = GetTimeString(TimeTypes.Hours); + sb.AppendFormat(formattable, remaining.Hours, GetSingOrPlur(remaining.Hours, s)); + } + + if (remaining.Minutes > 0) + { + if (sb.Length > 0) sb.Append(", "); + var s = GetTimeString(TimeTypes.Minutes); + sb.AppendFormat(formattable, remaining.Minutes, GetSingOrPlur(remaining.Minutes, s)); + } + + if (remaining.Seconds > 0) + { + if (sb.Length > 0) + { + var and = TranslationHandler.GetStrings(Language, "dateTime", "And").First(); + sb.AppendFormat(" {0} ", and); + } + var s = GetTimeString(TimeTypes.Seconds); + sb.AppendFormat(formattable, remaining.Seconds, GetSingOrPlur(remaining.Seconds, s)); + } + + return sb.ToString().Trim(); + } + + public Task SetLanguage(ulong guildId, string language) + { + return TranslationHandler.SetLanguage(guildId, language); + } + + private List GetTimeString(TimeTypes type) + { + return TranslationHandler.GetStrings(Language, "dateTime", type.ToString()); + } + + private string GetSingOrPlur(int number, List versions) + { + return number == 1 ? versions[0] : versions[1]; + } + + private enum TimeTypes + { + Days, + Hours, + Minutes, + Seconds + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Localization/TranslationHandler.cs b/Geekbot.net/Lib/Localization/TranslationHandler.cs index a1b650b..b61c93c 100644 --- a/Geekbot.net/Lib/Localization/TranslationHandler.cs +++ b/Geekbot.net/Lib/Localization/TranslationHandler.cs @@ -17,7 +17,7 @@ namespace Geekbot.net.Lib.Localization private readonly DatabaseContext _database; private readonly IGeekbotLogger _logger; private readonly Dictionary _serverLanguages; - private Dictionary>> _translations; + private Dictionary>>> _translations; public TranslationHandler(DatabaseContext database, IGeekbotLogger logger) { @@ -33,8 +33,8 @@ namespace Geekbot.net.Lib.Localization try { var translationFile = File.ReadAllText(Path.GetFullPath("./Lib/Localization/Translations.json")); - var rawTranslations = JsonSerializer.Deserialize>>>(translationFile); - var sortedPerLanguage = new Dictionary>>(); + var rawTranslations = JsonSerializer.Deserialize>>>>(translationFile); + var sortedPerLanguage = new Dictionary>>>(); foreach (var command in rawTranslations) { foreach (var str in command.Value) @@ -43,8 +43,8 @@ namespace Geekbot.net.Lib.Localization { if (!sortedPerLanguage.ContainsKey(lang.Key)) { - var commandDict = new Dictionary>(); - var strDict = new Dictionary + var commandDict = new Dictionary>>(); + var strDict = new Dictionary> { {str.Key, lang.Value} }; @@ -53,8 +53,10 @@ namespace Geekbot.net.Lib.Localization } if (!sortedPerLanguage[lang.Key].ContainsKey(command.Key)) { - var strDict = new Dictionary(); - strDict.Add(str.Key, lang.Value); + var strDict = new Dictionary> + { + {str.Key, lang.Value} + }; sortedPerLanguage[lang.Key].Add(command.Key, strDict); } if (!sortedPerLanguage[lang.Key][command.Key].ContainsKey(str.Key)) @@ -109,10 +111,16 @@ namespace Geekbot.net.Lib.Localization public async Task GetString(ulong guildId, string command, string stringName) { - var translation = _translations[await GetServerLanguage(guildId)][command][stringName]; - if (!string.IsNullOrWhiteSpace(translation)) return translation; + var serverLang = await GetServerLanguage(guildId); + return GetStrings(serverLang, command, stringName).First(); + } + + public List GetStrings(string language, string command, string stringName) + { + var translation = _translations[language][command][stringName]; + if (!string.IsNullOrWhiteSpace(translation.First())) return translation; translation = _translations[command][stringName]["EN"]; - if (string.IsNullOrWhiteSpace(translation)) + if (string.IsNullOrWhiteSpace(translation.First())) { _logger.Warning(LogSource.Geekbot, $"No translation found for {command} - {stringName}"); } @@ -125,7 +133,8 @@ namespace Geekbot.net.Lib.Localization { var command = context.Message.Content.Split(' ').First().TrimStart('!').ToLower(); var serverLanguage = await GetServerLanguage(context.Guild?.Id ?? 0); - return _translations[serverLanguage][command]; + return _translations[serverLanguage][command] + .ToDictionary(dict => dict.Key, dict => dict.Value.First()); } catch (Exception e) { @@ -133,13 +142,21 @@ namespace Geekbot.net.Lib.Localization return new Dictionary(); } } + + public async Task GetGuildContext(ICommandContext context) + { + var dict = await GetDict(context); + var language = await GetServerLanguage(context.Guild?.Id ?? 0); + return new TranslationGuildContext(this, language, dict); + } public async Task> GetDict(ICommandContext context, string command) { try { var serverLanguage = await GetServerLanguage(context.Guild?.Id ?? 0); - return _translations[serverLanguage][command]; + return _translations[serverLanguage][command] + .ToDictionary(dict => dict.Key, dict => dict.Value.First()); } catch (Exception e) { diff --git a/Geekbot.net/Lib/Localization/Translations.json b/Geekbot.net/Lib/Localization/Translations.json index 7747016..356deb5 100644 --- a/Geekbot.net/Lib/Localization/Translations.json +++ b/Geekbot.net/Lib/Localization/Translations.json @@ -1,130 +1,152 @@ { + "dateTime": { + "Days": { + "EN": ["day", "days"], + "CHDE": ["tag", "täg"] + }, + "Hours": { + "EN": ["hour", "hours"], + "CHDE": ["stund", "stunde"] + }, + "Minutes": { + "EN": ["minute", "minutes"], + "CHDE": ["minute", "minute"] + }, + "Seconds": { + "EN": ["second", "seconds"], + "CHDE": ["sekunde", "sekunde"] + }, + "And": { + "EN": ["and"], + "CHDE": ["und"] + } + }, "admin": { "NewLanguageSet": { - "EN": "I will reply in english from now on", - "CHDE": "I werd ab jetzt uf schwiizerdüütsch antworte, äuuä" + "EN": ["I will reply in english from now on"], + "CHDE": ["I werd ab jetzt uf schwiizerdüütsch antworte, äuuä"] }, "GetLanguage": { - "EN": "I'm talking english", - "CHDE": "I red schwiizerdüütsch" + "EN": ["I'm talking english"], + "CHDE": ["I red schwiizerdüütsch"] } }, "errorHandler": { "SomethingWentWrong": { - "EN": "Something went wrong :confused:", - "CHDE": "Öppis isch schief gange :confused:" + "EN": ["Something went wrong :confused:"], + "CHDE": ["Öppis isch schief gange :confused:"] } }, "httpErrors": { "403": { - "EN": "Seems like i don't have enough permission to that :confused:", - "CHDE": "Gseht danach us das ich nid gnueg recht han zum das mache :confused:" + "EN": ["Seems like i don't have enough permission to that :confused:"], + "CHDE": ["Gseht danach us das ich nid gnueg recht han zum das mache :confused:"] } }, "choose": { "Choice": { - "EN": "I Choose **{0}**", - "CHDE": "I nimme **{0}**" + "EN": ["I Choose **{0}**"], + "CHDE": ["I nimme **{0}**"] } }, "good": { "CannotChangeOwn": { - "EN": "Sorry {0}, but you can't give yourself karma", - "CHDE": "Sorry {0}, aber du chasch dr selber kei karma geh" + "EN": ["Sorry {0}, but you can't give yourself karma"], + "CHDE": ["Sorry {0}, aber du chasch dr selber kei karma geh"] }, "WaitUntill": { - "EN": "Sorry {0}, but you have to wait {1} before you can give karma again...", - "CHDE": "Sorry {0}, aber du musch no {1} warte bisch d wieder karma chasch geh..." + "EN": ["Sorry {0}, but you have to wait {1} before you can give karma again..."], + "CHDE": ["Sorry {0}, aber du musch no {1} warte bisch d wieder karma chasch geh..."] }, "Increased": { - "EN": "Karma gained", - "CHDE": "Karma becho" + "EN": ["Karma gained"], + "CHDE": ["Karma becho"] }, "By": { - "EN": "By", - "CHDE": "Vo" + "EN": ["By"], + "CHDE": ["Vo"] }, "Amount": { - "EN": "Amount", - "CHDE": "Mengi" + "EN": ["Amount"], + "CHDE": ["Mengi"] }, "Current": { - "EN": "Current", - "CHDE": "Jetzt" + "EN": ["Current"], + "CHDE": ["Jetzt"] } }, "bad": { "CannotChangeOwn": { - "EN": "Sorry {0}, but you can't lower your own karma", - "CHDE": "Sorry {0}, aber du chasch dr din eigete karma nid weg neh" + "EN": ["Sorry {0}, but you can't lower your own karma"], + "CHDE": ["Sorry {0}, aber du chasch dr din eigete karma nid weg neh"] }, "WaitUntill": { - "EN": "Sorry {0}, but you have to wait {1} before you can lower karma again...", - "CHDE": "Sorry {0}, aber du musch no {1} warte bisch d wieder karma chasch senke..." + "EN": ["Sorry {0}, but you have to wait {1} before you can lower karma again..."], + "CHDE": ["Sorry {0}, aber du musch no {1} warte bisch d wieder karma chasch senke..."] }, "Decreased": { - "EN": "Karma lowered", - "CHDE": "Karma gsenkt" + "EN": ["Karma lowered"], + "CHDE": ["Karma gsenkt"] }, "By": { - "EN": "By", - "CHDE": "Vo" + "EN": ["By"], + "CHDE": ["Vo"] }, "Amount": { - "EN": "Amount", - "CHDE": "Mengi" + "EN": ["Amount"], + "CHDE": ["Mengi"] }, "Current": { - "EN": "Current", - "CHDE": "Jetzt" + "EN": ["Current"], + "CHDE": ["Jetzt"] } }, "roll": { "Rolled": { - "EN": "{0}, you rolled {1}, your guess was {2}", - "CHDE": "{0}, du hesch {1} grollt und hesch {2} grate" + "EN": ["{0}, you rolled {1}, your guess was {2}"], + "CHDE": ["{0}, du hesch {1} grollt und hesch {2} grate"] }, "Gratz": { - "EN": "Congratulations {0}, your guess was correct!", - "CHDE": "Gratuliere {0}, du hesch richtig grate!" + "EN": ["Congratulations {0}, your guess was correct!"], + "CHDE": ["Gratuliere {0}, du hesch richtig grate!"] }, "RolledNoGuess": { - "EN": "{0}, you rolled {1}", - "CHDE": "{0}, du hesch {1} grollt" + "EN": ["{0}, you rolled {1}"], + "CHDE": ["{0}, du hesch {1} grollt"] }, "NoPrevGuess": { - "EN": ":red_circle: {0}, you can't guess the same number again", - "CHDE": ":red_circle: {0}, du chasch nid nomol es gliche rate" + "EN": [":red_circle: {0}, you can't guess the same number again"], + "CHDE": [":red_circle: {0}, du chasch nid nomol es gliche rate"] } }, "cookie": { "GetCookies": { - "EN": "You got {0} cookies, there are now {1} cookies in you cookie jar", - "CHDE": "Du häsch {0} guetzli becho, du häsch jetzt {1} guetzli ih dr büchse" + "EN": ["You got {0} cookies, there are now {1} cookies in you cookie jar"], + "CHDE": ["Du häsch {0} guetzli becho, du häsch jetzt {1} guetzli ih dr büchse"] }, "WaitForMoreCookies": { - "EN": "You already got cookies in the last 24 hours, wait until {0} for more cookies", - "CHDE": "Du hesch scho guetzli becho ih de letzti 24 stund, wart no bis {0}" + "EN": ["You already got cookies in the last 24 hours, you can have more cookies in {0}"], + "CHDE": ["Du hesch scho guetzli becho ih de letzti 24 stund, du chasch meh ha in {0}"] }, "InYourJar": { - "EN": "There are {0} cookies in you cookie jar", - "CHDE": "Es hät {0} guetzli ih dineri büchs" + "EN": ["There are {0} cookies in you cookie jar"], + "CHDE": ["Es hät {0} guetzli ih dineri büchs"] }, "Given": { - "EN": "You gave {0} cookies to {1}", - "CHDE": "Du hesch {1} {0} guetzli geh" + "EN": ["You gave {0} cookies to {1}"], + "CHDE": ["Du hesch {1} {0} guetzli geh"] }, "NotEnoughToGive": { - "EN": "You don't have enough cookies", - "CHDE": "Du hesch nid gnueg guetzli" + "EN": ["You don't have enough cookies"], + "CHDE": ["Du hesch nid gnueg guetzli"] }, "NotEnoughCookiesToEat": { - "EN": "Your cookie jar looks almost empty, you should probably not eat a cookie", - "CHDE": "Du hesch chuum no guetzli ih dineri büchs, du sötsch warschinli keini esse" + "EN": ["Your cookie jar looks almost empty, you should probably not eat a cookie"], + "CHDE": ["Du hesch chuum no guetzli ih dineri büchs, du sötsch warschinli keini esse"] }, "AteCookies": { - "EN": "You ate {0} cookies, you've only got {1} cookies left", - "CHDE": "Du hesch {0} guetzli gesse und hesch jezt no {1} übrig" + "EN": ["You ate {0} cookies, you've only got {1} cookies left"], + "CHDE": ["Du hesch {0} guetzli gesse und hesch jezt no {1} übrig"] } } } \ No newline at end of file From 0f0c0684c62c2e385fd941d122bef7d81406d63e Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 12 May 2019 00:32:07 +0200 Subject: [PATCH 262/553] Convert karma command to use new GuildContext for translations --- Geekbot.net/Commands/User/Karma.cs | 38 +++++++++++++----------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/Geekbot.net/Commands/User/Karma.cs b/Geekbot.net/Commands/User/Karma.cs index e2a4739..ed221ff 100644 --- a/Geekbot.net/Commands/User/Karma.cs +++ b/Geekbot.net/Commands/User/Karma.cs @@ -32,16 +32,16 @@ namespace Geekbot.net.Commands.User { try { - var transDict = await _translation.GetDict(Context); + var transContext = await _translation.GetGuildContext(Context); var actor = await GetUser(Context.User.Id); if (user.Id == Context.User.Id) { - await ReplyAsync(string.Format(transDict["CannotChangeOwn"], Context.User.Username)); + await ReplyAsync(transContext.GetString("CannotChangeOwn", Context.User.Username)); } else if (TimeoutFinished(actor.TimeOut)) { - await ReplyAsync(string.Format(transDict["WaitUntill"], Context.User.Username, - GetTimeLeft(actor.TimeOut))); + var formatedWaitTime = transContext.FormatDateTimeAsRemaining(actor.TimeOut.AddMinutes(3)); + await ReplyAsync(transContext.GetString("WaitUntill", Context.User.Username, formatedWaitTime)); } else { @@ -60,10 +60,10 @@ namespace Geekbot.net.Commands.User .WithName(user.Username)); eb.WithColor(new Color(138, 219, 146)); - eb.Title = transDict["Increased"]; - eb.AddInlineField(transDict["By"], Context.User.Username); - eb.AddInlineField(transDict["Amount"], "+1"); - eb.AddInlineField(transDict["Current"], target.Karma); + eb.Title = transContext.GetString("Increased"); + eb.AddInlineField(transContext.GetString("By"), Context.User.Username); + eb.AddInlineField(transContext.GetString("Amount"), "+1"); + eb.AddInlineField(transContext.GetString("Current"), target.Karma); await ReplyAsync("", false, eb.Build()); } } @@ -79,16 +79,16 @@ namespace Geekbot.net.Commands.User { try { - var transDict = await _translation.GetDict(Context); + var transContext = await _translation.GetGuildContext(Context); var actor = await GetUser(Context.User.Id); if (user.Id == Context.User.Id) { - await ReplyAsync(string.Format(transDict["CannotChangeOwn"], Context.User.Username)); + await ReplyAsync(transContext.GetString("CannotChangeOwn", Context.User.Username)); } else if (TimeoutFinished(actor.TimeOut)) { - await ReplyAsync(string.Format(transDict["WaitUntill"], Context.User.Username, - GetTimeLeft(actor.TimeOut))); + var formatedWaitTime = transContext.FormatDateTimeAsRemaining(actor.TimeOut.AddMinutes(3)); + await ReplyAsync(transContext.GetString("WaitUntill", Context.User.Username, formatedWaitTime)); } else { @@ -107,10 +107,10 @@ namespace Geekbot.net.Commands.User .WithName(user.Username)); eb.WithColor(new Color(138, 219, 146)); - eb.Title = transDict["Decreased"]; - eb.AddInlineField(transDict["By"], Context.User.Username); - eb.AddInlineField(transDict["Amount"], "-1"); - eb.AddInlineField(transDict["Current"], target.Karma); + eb.Title = transContext.GetString("Decreased"); + eb.AddInlineField(transContext.GetString("By"), Context.User.Username); + eb.AddInlineField(transContext.GetString("Amount"), "-1"); + eb.AddInlineField(transContext.GetString("Current"), target.Karma); await ReplyAsync("", false, eb.Build()); } } @@ -125,12 +125,6 @@ namespace Geekbot.net.Commands.User return lastKarma.AddMinutes(3) > DateTimeOffset.Now; } - private string GetTimeLeft(DateTimeOffset lastKarma) - { - var dt = lastKarma.AddMinutes(3).Subtract(DateTimeOffset.Now); - return $"{dt.Minutes} Minutes and {dt.Seconds} Seconds"; - } - private async Task GetUser(ulong userId) { var user = _database.Karma.FirstOrDefault(u =>u.GuildId.Equals(Context.Guild.Id.AsLong()) && u.UserId.Equals(userId.AsLong())) ?? await CreateNewRow(userId); From 67add36e51070a7e90c451c770f9c4eeb6820922 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 12 May 2019 00:44:25 +0200 Subject: [PATCH 263/553] Remove all in-command usages of GetDict for translations --- Geekbot.net/Commands/Admin/Admin.cs | 4 ++-- Geekbot.net/Commands/Games/Roll.cs | 10 +++++----- Geekbot.net/Commands/Utils/Choose.cs | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Geekbot.net/Commands/Admin/Admin.cs b/Geekbot.net/Commands/Admin/Admin.cs index f60e5df..ba31e54 100644 --- a/Geekbot.net/Commands/Admin/Admin.cs +++ b/Geekbot.net/Commands/Admin/Admin.cs @@ -134,8 +134,8 @@ namespace Geekbot.net.Commands.Admin _database.GuildSettings.Update(guild); await _database.SaveChangesAsync(); - var trans = await _translation.GetDict(Context); - await ReplyAsync(trans["NewLanguageSet"]); + var transContext = await _translation.GetGuildContext(Context); + await ReplyAsync(transContext.GetString("NewLanguageSet")); return; } diff --git a/Geekbot.net/Commands/Games/Roll.cs b/Geekbot.net/Commands/Games/Roll.cs index ac9279a..4fbb24e 100644 --- a/Geekbot.net/Commands/Games/Roll.cs +++ b/Geekbot.net/Commands/Games/Roll.cs @@ -39,7 +39,7 @@ namespace Geekbot.net.Commands.Games var number = _randomNumberGenerator.Next(1, 100); var guess = 1000; int.TryParse(stuff, out guess); - var transDict = await _translation.GetDict(Context); + var transContext = await _translation.GetGuildContext(Context); if (guess <= 100 && guess > 0) { var prevRoll = _redis.Db.HashGet($"{Context.Guild.Id}:RollsPrevious2", Context.Message.Author.Id).ToString()?.Split('|'); @@ -47,17 +47,17 @@ namespace Geekbot.net.Commands.Games { if (prevRoll[0] == guess.ToString() && DateTime.Parse(prevRoll[1]) > DateTime.Now.AddDays(-1)) { - await ReplyAsync(string.Format(transDict["NoPrevGuess"], Context.Message.Author.Mention)); + await ReplyAsync(transContext.GetString("NoPrevGuess", Context.Message.Author.Mention)); return; } } _redis.Db.HashSet($"{Context.Guild.Id}:RollsPrevious2", new[] {new HashEntry(Context.Message.Author.Id, $"{guess}|{DateTime.Now}")}); - await ReplyAsync(string.Format(transDict["Rolled"], Context.Message.Author.Mention, number, guess)); + await ReplyAsync(transContext.GetString("Rolled", Context.Message.Author.Mention, number, guess)); if (guess == number) { - await ReplyAsync(string.Format(transDict["Gratz"], Context.Message.Author)); + await ReplyAsync(transContext.GetString("Gratz", Context.Message.Author)); _redis.Db.HashIncrement($"{Context.Guild.Id}:Rolls", Context.User.Id.ToString()); var user = await GetUser(Context.User.Id); user.Rolls += 1; @@ -67,7 +67,7 @@ namespace Geekbot.net.Commands.Games } else { - await ReplyAsync(string.Format(transDict["RolledNoGuess"], Context.Message.Author.Mention, number)); + await ReplyAsync(transContext.GetString("RolledNoGuess", Context.Message.Author.Mention, number)); } } catch (Exception e) diff --git a/Geekbot.net/Commands/Utils/Choose.cs b/Geekbot.net/Commands/Utils/Choose.cs index ee2bf0d..7060755 100644 --- a/Geekbot.net/Commands/Utils/Choose.cs +++ b/Geekbot.net/Commands/Utils/Choose.cs @@ -24,10 +24,10 @@ namespace Geekbot.net.Commands.Utils { try { - var transDict = await _translation.GetDict(Context); + var transContext = await _translation.GetGuildContext(Context); var choicesArray = choices.Split(';'); var choice = new Random().Next(choicesArray.Length); - await ReplyAsync(string.Format(transDict["Choice"], choicesArray[choice])); + await ReplyAsync(transContext.GetString("Choice", choicesArray[choice])); } catch (Exception e) { From b309f155bec37802d23ebaf6fb3f94ef48a78f2a Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 12 May 2019 00:56:22 +0200 Subject: [PATCH 264/553] Make GetDict private in the TranslationHandler --- Geekbot.net/Lib/Localization/ITranslationHandler.cs | 1 - Geekbot.net/Lib/Localization/TranslationHandler.cs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Geekbot.net/Lib/Localization/ITranslationHandler.cs b/Geekbot.net/Lib/Localization/ITranslationHandler.cs index 7a46e56..bb70046 100644 --- a/Geekbot.net/Lib/Localization/ITranslationHandler.cs +++ b/Geekbot.net/Lib/Localization/ITranslationHandler.cs @@ -8,7 +8,6 @@ namespace Geekbot.net.Lib.Localization { Task GetString(ulong guildId, string command, string stringName); List GetStrings(string language, string command, string stringName); - Task> GetDict(ICommandContext context); Task> GetDict(ICommandContext context, string command); Task GetGuildContext(ICommandContext context); Task SetLanguage(ulong guildId, string language); diff --git a/Geekbot.net/Lib/Localization/TranslationHandler.cs b/Geekbot.net/Lib/Localization/TranslationHandler.cs index b61c93c..f298e2d 100644 --- a/Geekbot.net/Lib/Localization/TranslationHandler.cs +++ b/Geekbot.net/Lib/Localization/TranslationHandler.cs @@ -127,7 +127,7 @@ namespace Geekbot.net.Lib.Localization return translation; } - public async Task> GetDict(ICommandContext context) + private async Task> GetDict(ICommandContext context) { try { From 495288b88700c56cf07ab756e4db9a755c68ee37 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 12 May 2019 01:07:22 +0200 Subject: [PATCH 265/553] Pass full translation dictionary to TranslationGuildContext and decide there whether to use singular or plural --- Geekbot.net/Commands/Utils/Choose.cs | 2 +- Geekbot.net/Lib/Localization/TranslationGuildContext.cs | 6 +++--- Geekbot.net/Lib/Localization/TranslationHandler.cs | 7 +++---- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Geekbot.net/Commands/Utils/Choose.cs b/Geekbot.net/Commands/Utils/Choose.cs index 7060755..62069bd 100644 --- a/Geekbot.net/Commands/Utils/Choose.cs +++ b/Geekbot.net/Commands/Utils/Choose.cs @@ -27,7 +27,7 @@ namespace Geekbot.net.Commands.Utils var transContext = await _translation.GetGuildContext(Context); var choicesArray = choices.Split(';'); var choice = new Random().Next(choicesArray.Length); - await ReplyAsync(transContext.GetString("Choice", choicesArray[choice])); + await ReplyAsync(transContext.GetString("Choice", choicesArray[choice].Trim())); } catch (Exception e) { diff --git a/Geekbot.net/Lib/Localization/TranslationGuildContext.cs b/Geekbot.net/Lib/Localization/TranslationGuildContext.cs index 037ef3a..3f6f923 100644 --- a/Geekbot.net/Lib/Localization/TranslationGuildContext.cs +++ b/Geekbot.net/Lib/Localization/TranslationGuildContext.cs @@ -10,9 +10,9 @@ namespace Geekbot.net.Lib.Localization { public ITranslationHandler TranslationHandler { get; } public string Language { get; } - public Dictionary Dict { get; } + public Dictionary> Dict { get; } - public TranslationGuildContext(ITranslationHandler translationHandler, string language, Dictionary dict) + public TranslationGuildContext(ITranslationHandler translationHandler, string language, Dictionary> dict) { TranslationHandler = translationHandler; Language = language; @@ -21,7 +21,7 @@ namespace Geekbot.net.Lib.Localization public string GetString(string stringToFormat, params object[] args) { - return string.Format(Dict[stringToFormat] ?? "", args); + return string.Format(Dict[stringToFormat].First() ?? "", args); } public string FormatDateTimeAsRemaining(DateTimeOffset dateTime) diff --git a/Geekbot.net/Lib/Localization/TranslationHandler.cs b/Geekbot.net/Lib/Localization/TranslationHandler.cs index f298e2d..8100478 100644 --- a/Geekbot.net/Lib/Localization/TranslationHandler.cs +++ b/Geekbot.net/Lib/Localization/TranslationHandler.cs @@ -127,19 +127,18 @@ namespace Geekbot.net.Lib.Localization return translation; } - private async Task> GetDict(ICommandContext context) + private async Task>> GetDict(ICommandContext context) { try { var command = context.Message.Content.Split(' ').First().TrimStart('!').ToLower(); var serverLanguage = await GetServerLanguage(context.Guild?.Id ?? 0); - return _translations[serverLanguage][command] - .ToDictionary(dict => dict.Key, dict => dict.Value.First()); + return _translations[serverLanguage][command]; } catch (Exception e) { _logger.Error(LogSource.Geekbot, "No translations for command found", e); - return new Dictionary(); + return new Dictionary>(); } } From f9269b877cf4ae3e44dd2244f08de10dea0c9c1f Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 12 May 2019 01:38:56 +0200 Subject: [PATCH 266/553] Use typed TestData for unit tests --- Tests/Lib/Converters/EmojiConverter.test.cs | 94 +++++++++++++++++++++ Tests/Lib/EmojiConverter.test.cs | 74 ---------------- Tests/Lib/LevelCalc.test.cs | 48 ----------- Tests/Lib/Levels/LevelCalc.test.cs | 60 +++++++++++++ Tests/TestData.cs | 21 +++++ Tests/Tests.csproj | 1 + 6 files changed, 176 insertions(+), 122 deletions(-) create mode 100644 Tests/Lib/Converters/EmojiConverter.test.cs delete mode 100644 Tests/Lib/EmojiConverter.test.cs delete mode 100644 Tests/Lib/LevelCalc.test.cs create mode 100644 Tests/Lib/Levels/LevelCalc.test.cs create mode 100644 Tests/TestData.cs diff --git a/Tests/Lib/Converters/EmojiConverter.test.cs b/Tests/Lib/Converters/EmojiConverter.test.cs new file mode 100644 index 0000000..ad37824 --- /dev/null +++ b/Tests/Lib/Converters/EmojiConverter.test.cs @@ -0,0 +1,94 @@ +using Geekbot.net.Lib.Converters; +using Xunit; + +namespace Tests.Lib.Converters +{ + public class EmojiConverterTest + { + public class NumberToEmojiTestDto + { + public int Number { get; set; } + public string Expected { get; set; } + } + + public static TestData NumberToEmojiTestData => + new TestData + { + { + "2", + new NumberToEmojiTestDto + { + Number = 2, + Expected = ":two:" + } + }, + { + "10", + new NumberToEmojiTestDto + { + Number = 10, + Expected = "🔟" + } + }, + { + "15", + new NumberToEmojiTestDto + { + Number = 15, + Expected = ":one::five:" + } + }, + { + "null", + new NumberToEmojiTestDto + { + Number = 0, + Expected = ":zero:" + } + } + }; + + [Theory, MemberData(nameof(NumberToEmojiTestData))] + public void NumberToEmoji(string testName, NumberToEmojiTestDto testData) + { + var emojiConverter = new EmojiConverter(); + var result = emojiConverter.NumberToEmoji(testData.Number); + Assert.Equal(result, testData.Expected); + } + + public class TextToEmojiTestDto + { + public string Text { get; set; } + public string Expected { get; set; } + } + + public static TestData TextToEmojiTestData => + new TestData + { + { + "Test", + new TextToEmojiTestDto + { + Text = "test", + Expected = ":regional_indicator_t: :regional_indicator_e: :regional_indicator_s: :regional_indicator_t: " + } + }, + { + "Best3+?", + new TextToEmojiTestDto + { + Text = "Best3+?", + Expected = ":b: :regional_indicator_e: :regional_indicator_s: :regional_indicator_t: :three: :heavy_plus_sign: :question: " + } + } + }; + + [Theory, MemberData(nameof(TextToEmojiTestData))] + public void TextToEmoji(string testName, TextToEmojiTestDto testData) + { + var emojiConverter = new EmojiConverter(); + var result = emojiConverter.TextToEmoji(testData.Text); + Assert.Equal(result, testData.Expected); + } + } +} \ No newline at end of file diff --git a/Tests/Lib/EmojiConverter.test.cs b/Tests/Lib/EmojiConverter.test.cs deleted file mode 100644 index 170d521..0000000 --- a/Tests/Lib/EmojiConverter.test.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System.Collections.Generic; -using Geekbot.net.Lib.Converters; -using Xunit; - -namespace Tests.Lib -{ - public class EmojiConverterTest - { - public static IEnumerable NumberToEmojiTestData - { - get - { - yield return new object[] - { - 2, - ":two:" - }; - - yield return new object[] - { - 10, - "🔟" - }; - - yield return new object[] - { - 15, - ":one::five:" - }; - - yield return new object[] - { - null, - ":zero:" - }; - } - } - - - [Theory, MemberData(nameof(NumberToEmojiTestData))] - public void NumberToEmoji(int number, string expectedResult) - { - var emojiConverter = new EmojiConverter(); - var result = emojiConverter.NumberToEmoji(number); - Assert.Equal(result, expectedResult); - } - - public static IEnumerable TextToEmojiTestData - { - get - { - yield return new object[] - { - "test", - ":regional_indicator_t: :regional_indicator_e: :regional_indicator_s: :regional_indicator_t: " - }; - yield return new object[] - { - "Best3+?", - ":b: :regional_indicator_e: :regional_indicator_s: :regional_indicator_t: :three: :heavy_plus_sign: :question: " - }; - } - } - - - [Theory, MemberData(nameof(TextToEmojiTestData))] - public void TextToEmoji(string text, string expectedResult) - { - var emojiConverter = new EmojiConverter(); - var result = emojiConverter.TextToEmoji(text); - Assert.Equal(result, expectedResult); - } - } -} \ No newline at end of file diff --git a/Tests/Lib/LevelCalc.test.cs b/Tests/Lib/LevelCalc.test.cs deleted file mode 100644 index 5ac5fd3..0000000 --- a/Tests/Lib/LevelCalc.test.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Collections.Generic; -using Geekbot.net.Lib.Levels; -using Xunit; - -namespace Tests.Lib -{ - public class LevelCalcTest - { - public static IEnumerable LevelCalcTestData - { - get - { - yield return new object[] - { - 500, - 13 - }; - - yield return new object[] - { - 41659, - 55 - }; - - yield return new object[] - { - 0, - 1 - }; - - yield return new object[] - { - 4000000, - 101 - }; - } - } - - - [Theory, MemberData(nameof(LevelCalcTestData))] - public void GetLevel(int messages, int expectedResult) - { - var levelCalc = new LevelCalc(); - var result = levelCalc.GetLevel(messages); - Assert.Equal(result, expectedResult); - } - } -} \ No newline at end of file diff --git a/Tests/Lib/Levels/LevelCalc.test.cs b/Tests/Lib/Levels/LevelCalc.test.cs new file mode 100644 index 0000000..9b4b97c --- /dev/null +++ b/Tests/Lib/Levels/LevelCalc.test.cs @@ -0,0 +1,60 @@ +using System.Collections.Generic; +using Geekbot.net.Lib.Levels; +using Xunit; + +namespace Tests.Lib.Levels +{ + public class LevelCalcTest + { + public class LevelCalcTestDto + { + public int Messages { get; set; } + public int ExpectedLevel { get; set; } + } + + public static TestData LevelCalcTestData => + new TestData() + { + { + "500", + new LevelCalcTestDto + { + Messages = 500, + ExpectedLevel = 13 + } + }, + { + "41659", + new LevelCalcTestDto + { + Messages = 41659, + ExpectedLevel = 55 + } + }, + { + "0", + new LevelCalcTestDto + { + Messages = 0, + ExpectedLevel = 1 + } + }, + { + "4000000", + new LevelCalcTestDto + { + Messages = 4000000, + ExpectedLevel = 101 + } + } + }; + + [Theory, MemberData(nameof(LevelCalcTestData))] + public void GetLevel(string testName, LevelCalcTestDto testData) + { + var levelCalc = new LevelCalc(); + var result = levelCalc.GetLevel(testData.Messages); + Assert.Equal(result, testData.ExpectedLevel); + } + } +} \ No newline at end of file diff --git a/Tests/TestData.cs b/Tests/TestData.cs new file mode 100644 index 0000000..6c61f0b --- /dev/null +++ b/Tests/TestData.cs @@ -0,0 +1,21 @@ +using Xunit; + +namespace Tests +{ + /// + /// Represents a set of data for a theory. Data can be added to the data set using the collection initializer syntax. + /// + /// + public class TestData : TheoryData + { + /// + /// Adds a theory to the Test + /// + /// Name of the Test + /// Data used in the Test + public void Add(string testName, T testObject) + { + AddRow(testName, testObject); + } + } +} \ No newline at end of file diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 1e26252..108b314 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -3,6 +3,7 @@ netcoreapp2.2 false NU1701 + xUnit1026 From 7d7d393a3d72c86d7dd856c22578a2e2b7e8abc4 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 12 May 2019 01:59:55 +0200 Subject: [PATCH 267/553] Add tests for FormatDateTimeAsRemaining --- .../TranslationGuildContext.test.cs | 71 +++++++++++++++++++ Tests/Tests.csproj | 1 + 2 files changed, 72 insertions(+) create mode 100644 Tests/Lib/Localization/TranslationGuildContext.test.cs diff --git a/Tests/Lib/Localization/TranslationGuildContext.test.cs b/Tests/Lib/Localization/TranslationGuildContext.test.cs new file mode 100644 index 0000000..90f1446 --- /dev/null +++ b/Tests/Lib/Localization/TranslationGuildContext.test.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using Geekbot.net.Lib.Localization; +using Moq; +using Xunit; + +namespace Tests.Lib.Localization +{ + public class TranslationGuildContext_test + { + public class FormatDateTimeAsRemainingTestDto + { + public DateTimeOffset DateTime { get; set; } + public string Expected { get; set; } + } + + public static TestData FormatDateTimeAsRemainingData => + new TestData + { + { + "Wait for days", + new FormatDateTimeAsRemainingTestDto + { + DateTime = DateTimeOffset.Now.AddDays(5), + Expected = "4 days, 23 hours, 59 minutes and 59 seconds" + } + }, + { + "Wait for minutes", + new FormatDateTimeAsRemainingTestDto + { + DateTime = DateTimeOffset.Now.AddMinutes(5), + Expected = "4 minutes and 59 seconds" + } + }, + { + "Wait for seconds", + new FormatDateTimeAsRemainingTestDto + { + DateTime = DateTimeOffset.Now.AddSeconds(5), + Expected = "4 seconds" + } + } + }; + + [Theory, MemberData(nameof(FormatDateTimeAsRemainingData))] + public void FormatDateTimeAsRemaining(string testName, FormatDateTimeAsRemainingTestDto testData) + { + var translationHandlerMock = new Mock(MockBehavior.Loose); + translationHandlerMock + .Setup(thm => thm.GetStrings("EN", "dateTime", "Days")) + .Returns(new List {{"day"}, {"days"}}); + translationHandlerMock + .Setup(thm => thm.GetStrings("EN", "dateTime", "Hours")) + .Returns(new List {{"hour"}, {"hours"}}); + translationHandlerMock + .Setup(thm => thm.GetStrings("EN", "dateTime", "Minutes")) + .Returns(new List {{"minute"}, {"minutes"}}); + translationHandlerMock + .Setup(thm => thm.GetStrings("EN", "dateTime", "Seconds")) + .Returns(new List {{"second"}, {"seconds"}}); + translationHandlerMock + .Setup(thm => thm.GetStrings("EN", "dateTime", "And")) + .Returns(new List {{"and"}}); + + var context = new TranslationGuildContext(translationHandlerMock.Object, "EN", new Dictionary>()); + var result = context.FormatDateTimeAsRemaining(testData.DateTime); + Assert.Equal(result, testData.Expected); + } + } +} \ No newline at end of file diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 108b314..771a9d4 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -7,6 +7,7 @@ + From a86a33635cf960c0a355ff362ad5cd0b46368db0 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 12 May 2019 12:25:42 +0200 Subject: [PATCH 268/553] Rename cookie command to cookies --- Geekbot.net/Commands/Rpg/Cookies.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Geekbot.net/Commands/Rpg/Cookies.cs b/Geekbot.net/Commands/Rpg/Cookies.cs index 6d527ef..e7192c6 100644 --- a/Geekbot.net/Commands/Rpg/Cookies.cs +++ b/Geekbot.net/Commands/Rpg/Cookies.cs @@ -14,7 +14,7 @@ using Geekbot.net.Lib.RandomNumberGenerator; namespace Geekbot.net.Commands.Rpg { [DisableInDirectMessage] - [Group("cookie")] + [Group("cookies")] public class Cookies : ModuleBase { private readonly DatabaseContext _database; From 4b67bb51d1f1a6fcac1b011b70eb39c9f2d5f48a Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 12 May 2019 12:31:31 +0200 Subject: [PATCH 269/553] Reflect cookies command change in translations --- Geekbot.net/Lib/Localization/Translations.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Geekbot.net/Lib/Localization/Translations.json b/Geekbot.net/Lib/Localization/Translations.json index 356deb5..617106d 100644 --- a/Geekbot.net/Lib/Localization/Translations.json +++ b/Geekbot.net/Lib/Localization/Translations.json @@ -119,7 +119,7 @@ "CHDE": [":red_circle: {0}, du chasch nid nomol es gliche rate"] } }, - "cookie": { + "cookies": { "GetCookies": { "EN": ["You got {0} cookies, there are now {1} cookies in you cookie jar"], "CHDE": ["Du häsch {0} guetzli becho, du häsch jetzt {1} guetzli ih dr büchse"] From 68a62ab4ec4f21bf98d0443ba742e5e2230fec53 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 12 May 2019 13:47:15 +0200 Subject: [PATCH 270/553] Add translations for the role command --- Geekbot.net/Commands/Admin/Role.cs | 34 ++++++++------- .../Lib/Localization/Translations.json | 42 +++++++++++++++++++ 2 files changed, 62 insertions(+), 14 deletions(-) diff --git a/Geekbot.net/Commands/Admin/Role.cs b/Geekbot.net/Commands/Admin/Role.cs index aa767d1..47d7246 100644 --- a/Geekbot.net/Commands/Admin/Role.cs +++ b/Geekbot.net/Commands/Admin/Role.cs @@ -10,6 +10,7 @@ using Geekbot.net.Database.Models; using Geekbot.net.Lib.CommandPreconditions; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; +using Geekbot.net.Lib.Localization; using Geekbot.net.Lib.ReactionListener; namespace Geekbot.net.Commands.Admin @@ -21,12 +22,14 @@ namespace Geekbot.net.Commands.Admin private readonly DatabaseContext _database; private readonly IErrorHandler _errorHandler; private readonly IReactionListener _reactionListener; + private readonly TranslationHandler _translationHandler; - public Role(DatabaseContext database, IErrorHandler errorHandler, IReactionListener reactionListener) + public Role(DatabaseContext database, IErrorHandler errorHandler, IReactionListener reactionListener, TranslationHandler translationHandler) { _database = database; _errorHandler = errorHandler; _reactionListener = reactionListener; + _translationHandler = translationHandler; } [Command(RunMode = RunMode.Async)] @@ -35,16 +38,17 @@ namespace Geekbot.net.Commands.Admin { try { + var transContext = await _translationHandler.GetGuildContext(Context); var roles = _database.RoleSelfService.Where(g => g.GuildId.Equals(Context.Guild.Id.AsLong())).ToList(); if (roles.Count == 0) { - await ReplyAsync("There are no roles configured for this server"); + await ReplyAsync(transContext.GetString("NoRolesConfigured")); return; } var sb = new StringBuilder(); - sb.AppendLine($"**Self Service Roles on {Context.Guild.Name}**"); - sb.AppendLine("To get a role, use `!role name`"); + sb.AppendLine(transContext.GetString("ListHeader", Context.Guild.Name)); + sb.AppendLine(transContext.GetString("ListInstruction")); foreach (var role in roles) sb.AppendLine($"- {role.WhiteListName}"); await ReplyAsync(sb.ToString()); } @@ -60,6 +64,7 @@ namespace Geekbot.net.Commands.Admin { try { + var transContext = await _translationHandler.GetGuildContext(Context); var roleName = roleNameRaw.ToLower(); var roleFromDb = _database.RoleSelfService.FirstOrDefault(e => e.GuildId.Equals(Context.Guild.Id.AsLong()) && e.WhiteListName.Equals(roleName)); @@ -69,23 +74,23 @@ namespace Geekbot.net.Commands.Admin var role = Context.Guild.Roles.First(r => r.Id == roleFromDb.RoleId.AsUlong()); if (role == null) { - await ReplyAsync("That role doesn't seem to exist"); + await ReplyAsync(transContext.GetString("RoleNotFound")); return; } if (guildUser.RoleIds.Contains(role.Id)) { await guildUser.RemoveRoleAsync(role); - await ReplyAsync($"Removed you from {role.Name}"); + await ReplyAsync(transContext.GetString("RemovedUserFromRole", role.Name)); return; } await guildUser.AddRoleAsync(role); - await ReplyAsync($"Added you to {role.Name}"); + await ReplyAsync(transContext.GetString("AddedUserFromRole", role.Name)); return; } - await ReplyAsync("That role doesn't seem to exist"); + await ReplyAsync(transContext.GetString("RoleNotFound")); } catch (HttpException e) { @@ -104,9 +109,10 @@ namespace Geekbot.net.Commands.Admin { try { + var transContext = await _translationHandler.GetGuildContext(Context); if (role.IsManaged) { - await ReplyAsync("You can't add a role that is managed by discord"); + await ReplyAsync(transContext.GetString("CannotAddManagedRole")); return; } @@ -116,8 +122,7 @@ namespace Geekbot.net.Commands.Admin || role.Permissions.BanMembers || role.Permissions.KickMembers) { - await ReplyAsync( - "You cannot add that role to self service because it contains one or more dangerous permissions"); + await ReplyAsync(transContext.GetString("CannotAddDangerousRole")); return; } @@ -128,7 +133,7 @@ namespace Geekbot.net.Commands.Admin WhiteListName = roleName }); await _database.SaveChangesAsync(); - await ReplyAsync($"Added {role.Name} to the whitelist"); + await ReplyAsync(transContext.GetString("CannotAddDangerousRole", role.Name)); } catch (Exception e) { @@ -143,17 +148,18 @@ namespace Geekbot.net.Commands.Admin { try { + var transContext = await _translationHandler.GetGuildContext(Context); var roleFromDb = _database.RoleSelfService.FirstOrDefault(e => e.GuildId.Equals(Context.Guild.Id.AsLong()) && e.WhiteListName.Equals(roleName)); if (roleFromDb != null) { _database.RoleSelfService.Remove(roleFromDb); await _database.SaveChangesAsync(); - await ReplyAsync($"Removed {roleName} from the whitelist"); + await ReplyAsync(transContext.GetString("RemovedRoleFromWhitelist", roleName)); return; } - await ReplyAsync("There is not whitelisted role with that name"); + await ReplyAsync(transContext.GetString("RoleNotFound")); } catch (Exception e) { diff --git a/Geekbot.net/Lib/Localization/Translations.json b/Geekbot.net/Lib/Localization/Translations.json index 617106d..6a864fc 100644 --- a/Geekbot.net/Lib/Localization/Translations.json +++ b/Geekbot.net/Lib/Localization/Translations.json @@ -148,5 +148,47 @@ "EN": ["You ate {0} cookies, you've only got {1} cookies left"], "CHDE": ["Du hesch {0} guetzli gesse und hesch jezt no {1} übrig"] } + }, + "role": { + "NoRolesConfigured": { + "EN": ["There are no roles configured for this server"], + "CHDE": ["Es sind kei rolle für dä server konfiguriert"] + }, + "ListHeader": { + "EN": ["**Self Service Roles on {0}**"], + "CHDE": ["**Self Service Rollene uf {0}**"] + }, + "ListInstruction": { + "EN": ["To get a role, use `!role [name]`"], + "CHDE": ["Zum ä rolle becho, schriib `!role [name]`"] + }, + "RoleNotFound": { + "EN": ["That role doesn't exist or is not on the whitelist"], + "CHDE": ["Die rolle gids nid or isch nid uf dr whitelist"] + }, + "RemovedUserFromRole": { + "EN": ["Removed you from {0}"], + "CHDE": ["Han di entfernt vo {0}"] + }, + "AddedUserFromRole": { + "EN": ["Added you to {0}"], + "CHDE": ["Han di hinzue gfüegt zu {0}"] + }, + "CannotAddManagedRole": { + "EN": ["You can't add a role that is managed by discord"], + "CHDE": ["Du chasch kei rolle hinzuefüge wo verwalted wird vo discord"] + }, + "CannotAddDangerousRole": { + "EN": ["You cannot add that role to self service because it contains one or more dangerous permissions"], + "CHDE": ["Du chasch die rolle nid hinzuefüge will er ein oder mehreri gföhrlichi berechtigunge het"] + }, + "AddedRoleToWhitelist": { + "EN": ["Added {0} to the whitelist"], + "CHDE": ["{0} isch zur whitelist hinzuegfüegt"] + }, + "RemovedRoleFromWhitelist": { + "EN": ["Removed {0} from the whitelist"], + "CHDE": ["{0} isch vo dr whitelist glöscht"] + } } } \ No newline at end of file From c6271cbaa0de233cf0fcc1f923268e4e463e06b0 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 12 May 2019 13:48:37 +0200 Subject: [PATCH 271/553] Remove AudioUtils --- Geekbot.net/Commands/Audio/Voice.cs | 101 --------------------------- Geekbot.net/Lib/Audio/AudioUtils.cs | 96 ------------------------- Geekbot.net/Lib/Audio/IAudioUtils.cs | 15 ---- Geekbot.net/Program.cs | 3 - 4 files changed, 215 deletions(-) delete mode 100644 Geekbot.net/Commands/Audio/Voice.cs delete mode 100644 Geekbot.net/Lib/Audio/AudioUtils.cs delete mode 100644 Geekbot.net/Lib/Audio/IAudioUtils.cs diff --git a/Geekbot.net/Commands/Audio/Voice.cs b/Geekbot.net/Commands/Audio/Voice.cs deleted file mode 100644 index b12d6e2..0000000 --- a/Geekbot.net/Commands/Audio/Voice.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System; -using System.Threading.Tasks; -using Discord; -using Discord.Commands; -using Geekbot.net.Lib.Audio; -using Geekbot.net.Lib.ErrorHandling; - -namespace Geekbot.net.Commands.Audio -{ - public class Voice : ModuleBase - { - private readonly IAudioUtils _audioUtils; - private readonly IErrorHandler _errorHandler; - - public Voice(IErrorHandler errorHandler, IAudioUtils audioUtils) - { - _errorHandler = errorHandler; - _audioUtils = audioUtils; - } - -// [Command("join")] - public async Task JoinChannel() - { - try - { - // Get the audio channel - var channel = (Context.User as IGuildUser)?.VoiceChannel; - if (channel == null) - { - await Context.Channel.SendMessageAsync("You must be in a voice channel."); - return; - } - - var audioClient = await channel.ConnectAsync(); - _audioUtils.StoreAudioClient(Context.Guild.Id, audioClient); - await ReplyAsync($"Connected to {channel.Name}"); - } - catch (Exception e) - { - await _errorHandler.HandleCommandException(e, Context); - } - } - -// [Command("disconnect")] - public async Task DisconnectChannel() - { - try - { - var audioClient = _audioUtils.GetAudioClient(Context.Guild.Id); - if (audioClient == null) - { - await Context.Channel.SendMessageAsync("I'm not in a voice channel at the moment"); - return; - } - - await audioClient.StopAsync(); - await ReplyAsync("Disconnected from channel!"); - _audioUtils.Cleanup(Context.Guild.Id); - } - catch (Exception e) - { - await _errorHandler.HandleCommandException(e, Context); - _audioUtils.Cleanup(Context.Guild.Id); - } - } - -// [Command("ytplay")] - public async Task Ytplay(string url) - { - try - { - if (!url.Contains("youtube")) - { - await ReplyAsync("I can only play youtube videos"); - return; - } - var audioClient = _audioUtils.GetAudioClient(Context.Guild.Id); - if (audioClient == null) - { - await ReplyAsync("I'm not in a voice channel at the moment"); - return; - } - - var message = await Context.Channel.SendMessageAsync("Just a second, i'm still a bit slow at this"); - var ffmpeg = _audioUtils.CreateStreamFromYoutube(url, Context.Guild.Id); - var output = ffmpeg.StandardOutput.BaseStream; - await message.ModifyAsync(msg => msg.Content = "**Playing!** Please note that this feature is experimental"); - var discord = audioClient.CreatePCMStream(Discord.Audio.AudioApplication.Mixed); - await output.CopyToAsync(discord); - await discord.FlushAsync(); - _audioUtils.Cleanup(Context.Guild.Id); - } - catch (Exception e) - { - await _errorHandler.HandleCommandException(e, Context); - _audioUtils.Cleanup(Context.Guild.Id); - } - } - } - -} \ No newline at end of file diff --git a/Geekbot.net/Lib/Audio/AudioUtils.cs b/Geekbot.net/Lib/Audio/AudioUtils.cs deleted file mode 100644 index 024019d..0000000 --- a/Geekbot.net/Lib/Audio/AudioUtils.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Net; -using Discord.Audio; - -namespace Geekbot.net.Lib.Audio -{ - public class AudioUtils : IAudioUtils - { - private string _tempFolderPath; - private Dictionary _audioClients; - - public AudioUtils() - { - _audioClients = new Dictionary(); - _tempFolderPath = Path.GetFullPath("./tmp/"); - if (Directory.Exists(_tempFolderPath)) - { - Directory.Delete(_tempFolderPath, true); - } - Directory.CreateDirectory(_tempFolderPath); - } - - public IAudioClient GetAudioClient(ulong guildId) - { - return _audioClients[guildId]; - } - - public void StoreAudioClient(ulong guildId, IAudioClient client) - { - _audioClients[guildId] = client; - } - - public Process CreateStreamFromFile(string path) - { - var ffmpeg = new ProcessStartInfo - { - FileName = "ffmpeg", - Arguments = $"-i {path} -ac 2 -f s16le -ar 48000 pipe:1", - UseShellExecute = false, - RedirectStandardOutput = true, - }; - return Process.Start(ffmpeg); - } - - public Process CreateStreamFromYoutube(string url, ulong guildId) - { - var ytdlMediaUrl = GetYoutubeMediaUrl(url); - DownloadMediaUrl(ytdlMediaUrl, guildId); - return CreateStreamFromFile($"{_tempFolderPath}{guildId}"); - } - - public void Cleanup(ulong guildId) - { - File.Delete($"{_tempFolderPath}{guildId}"); - } - - private string GetYoutubeMediaUrl(string url) - { - var ytdl = new ProcessStartInfo() - { - FileName = "youtube-dl", - Arguments = $"-f bestaudio -g {url}", - UseShellExecute = false, - RedirectStandardOutput = true - }; - var output = Process.Start(ytdl).StandardOutput.ReadToEnd(); - if (string.IsNullOrWhiteSpace(output)) - { - throw new Exception("Could not get Youtube Media URL"); - } - return output; - } - - private void DownloadMediaUrl(string url, ulong guildId) - { - using (var web = new WebClient()) - { - web.DownloadFile(url, $"{_tempFolderPath}{guildId}"); - } -// var ffmpeg = new ProcessStartInfo -// { -// FileName = "ffmpeg", -// Arguments = $"-i \"{_tempFolderPath}{guildId}\" -c:a mp3 -b:a 256k {_tempFolderPath}{guildId}.mp3", -// UseShellExecute = false, -// RedirectStandardOutput = true, -// }; -// Process.Start(ffmpeg).WaitForExit(); -// File.Delete($"{_tempFolderPath}{guildId}"); - return; - } - - } -} \ No newline at end of file diff --git a/Geekbot.net/Lib/Audio/IAudioUtils.cs b/Geekbot.net/Lib/Audio/IAudioUtils.cs deleted file mode 100644 index 4af1293..0000000 --- a/Geekbot.net/Lib/Audio/IAudioUtils.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Diagnostics; -using Discord.Audio; - -namespace Geekbot.net.Lib.Audio -{ - public interface IAudioUtils - { - IAudioClient GetAudioClient(ulong guildId); - void StoreAudioClient(ulong guildId, IAudioClient client); - Process CreateStreamFromFile(string path); - Process CreateStreamFromYoutube(string url, ulong guildId); - void Cleanup(ulong guildId); - - } -} \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 43c16d1..27274d2 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -9,7 +9,6 @@ using Discord.WebSocket; using Geekbot.net.Database; using Geekbot.net.Lib; using Geekbot.net.Lib.AlmostRedis; -using Geekbot.net.Lib.Audio; using Geekbot.net.Lib.Clients; using Geekbot.net.Lib.Converters; using Geekbot.net.Lib.ErrorHandling; @@ -124,7 +123,6 @@ namespace Geekbot.net var emojiConverter = new EmojiConverter(); var mtgManaConverter = new MtgManaConverter(); var wikipediaClient = new WikipediaClient(); - var audioUtils = new AudioUtils(); var randomNumberGenerator = new RandomNumberGenerator(); _highscoreManager = new HighscoreManager(_databaseInitializer.Initialize(), _userRepository); @@ -138,7 +136,6 @@ namespace Geekbot.net _services.AddSingleton(malClient); _services.AddSingleton(mtgManaConverter); _services.AddSingleton(wikipediaClient); - _services.AddSingleton(audioUtils); _services.AddSingleton(randomNumberGenerator); _services.AddSingleton(_highscoreManager); _services.AddSingleton(_globalSettings); From 03d1607d646dcb3e02576c24626e637169d3e1a7 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 12 May 2019 13:49:01 +0200 Subject: [PATCH 272/553] Remove Poll command --- Geekbot.net/Commands/Utils/Poll.cs | 202 ----------------------------- 1 file changed, 202 deletions(-) delete mode 100644 Geekbot.net/Commands/Utils/Poll.cs diff --git a/Geekbot.net/Commands/Utils/Poll.cs b/Geekbot.net/Commands/Utils/Poll.cs deleted file mode 100644 index 617d6e2..0000000 --- a/Geekbot.net/Commands/Utils/Poll.cs +++ /dev/null @@ -1,202 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Discord; -using Discord.Commands; -using Geekbot.net.Database; -using Geekbot.net.Database.Models; -using Geekbot.net.Lib.CommandPreconditions; -using Geekbot.net.Lib.Converters; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.Extensions; -using Geekbot.net.Lib.UserRepository; - -namespace Geekbot.net.Commands.Utils -{ - [Group("poll")] - [DisableInDirectMessage] - public class Poll : ModuleBase - { - private readonly IEmojiConverter _emojiConverter; - private readonly IErrorHandler _errorHandler; - private readonly DatabaseContext _database; - private readonly IUserRepository _userRepository; - - public Poll(IErrorHandler errorHandler, DatabaseContext database, IEmojiConverter emojiConverter, IUserRepository userRepository) - { - _errorHandler = errorHandler; - _database = database; - _emojiConverter = emojiConverter; - _userRepository = userRepository; - } - - [Command(RunMode = RunMode.Async)] - [Summary("Check status of the current poll")] - public async Task Dflt() - { - try - { - var currentPoll = GetCurrentPoll(); - if (currentPoll.Question == null) - { - await ReplyAsync( - "There is no poll in this channel ongoing at the moment\r\nYou can create one with `!poll create question;option1;option2;option3`"); - return; - } - - await ReplyAsync("There is a poll running at the moment"); - } - catch (Exception e) - { - await _errorHandler.HandleCommandException(e, Context); - } - } - - [Command("create", RunMode = RunMode.Async)] - [Summary("Create a poll")] - public async Task Create([Remainder] [Summary("question;option1;option2")] - string rawPollString) - { - try - { - await ReplyAsync("Poll creation currently disabled"); - return; - -// var currentPoll = GetCurrentPoll(); -// if (currentPoll.Question != null && !currentPoll.IsFinshed) -// { -// await ReplyAsync("You have not finished you last poll yet. To finish it use `!poll end`"); -// return; -// } -// -// var pollList = rawPollString.Split(';').ToList(); -// if (pollList.Count <= 2) -// { -// await ReplyAsync( -// "You need a question with atleast 2 options, a valid creation would look like this `question;option1;option2`"); -// return; -// } -// -// var question = pollList[0]; -// pollList.RemoveAt(0); -// -// var eb = new EmbedBuilder -// { -// Title = $"Poll by {Context.User.Username}", -// Description = question -// }; -// -// var options = new List(); -// var i = 1; -// pollList.ForEach(option => -// { -// options.Add(new PollQuestionModel() -// { -// OptionId = i, -// OptionText = option -// }); -// eb.AddInlineField($"Option {_emojiConverter.NumberToEmoji(i)}", option); -// i++; -// }); -// var pollMessage = await ReplyAsync("", false, eb.Build()); -// -// var poll = new PollModel() -// { -// Creator = Context.User.Id.AsLong(), -// MessageId = pollMessage.Id.AsLong(), -// IsFinshed = false, -// Question = question, -// Options = options -// }; -// _database.Polls.Add(poll); -// -// i = 1; -// pollList.ForEach(option => -// { -// pollMessage.AddReactionAsync(new Emoji(_emojiConverter.NumberToEmoji(i))); -// Task.Delay(500); -// i++; -// }); - } - catch (Exception e) - { - await _errorHandler.HandleCommandException(e, Context); - } - } - - [Command("end", RunMode = RunMode.Async)] - [Summary("End the current poll")] - public async Task End() - { - try - { - var currentPoll = GetCurrentPoll(); - if (currentPoll.Question == null || currentPoll.IsFinshed) - { - await ReplyAsync("There is no ongoing poll at the moment"); - return; - } - - currentPoll = await GetPollResults(currentPoll); - var sb = new StringBuilder(); - sb.AppendLine("**Poll Results**"); - sb.AppendLine(currentPoll.Question); - foreach (var result in currentPoll.Options) sb.AppendLine($"{result.Votes} - {result.OptionText}"); - await ReplyAsync(sb.ToString()); - currentPoll.IsFinshed = true; - _database.Polls.Update(currentPoll); - } - catch (Exception e) - { - await _errorHandler.HandleCommandException(e, Context); - } - } - - private PollModel GetCurrentPoll() - { - try - { - var currentPoll = _database.Polls.FirstOrDefault(poll => - poll.ChannelId.Equals(Context.Channel.Id.AsLong()) && - poll.GuildId.Equals(Context.Guild.Id.AsLong()) - ); - return currentPoll ?? new PollModel(); - - } - catch - { - return new PollModel(); - } - } - - private async Task GetPollResults(PollModel poll) - { - var message = (IUserMessage) await Context.Channel.GetMessageAsync(poll.MessageId.AsUlong()); - - var results = new Dictionary(); - foreach (var r in message.Reactions) - { - try - { - results.Add(r.Key.Name.ToCharArray()[0], r.Value.ReactionCount); - } - catch - { - // ignored - } - } - - foreach (var q in poll.Options) - { - q.Votes = results.FirstOrDefault(e => e.Key.Equals(q.OptionId)).Value; - } - - return poll; - -// var sortedValues = results.OrderBy(e => e.Value); -// return sortedValues; - } - } -} \ No newline at end of file From e5742165d1236b0dfa3acb4f09f1259c6b380da6 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 12 May 2019 15:29:22 +0200 Subject: [PATCH 273/553] Parially translate quote --- Geekbot.net/Commands/Admin/Role.cs | 4 +-- Geekbot.net/Commands/Utils/Quote/Quote.cs | 27 ++++++++++++------- .../Lib/Localization/Translations.json | 26 ++++++++++++++++++ 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/Geekbot.net/Commands/Admin/Role.cs b/Geekbot.net/Commands/Admin/Role.cs index 47d7246..f0aa7bd 100644 --- a/Geekbot.net/Commands/Admin/Role.cs +++ b/Geekbot.net/Commands/Admin/Role.cs @@ -22,9 +22,9 @@ namespace Geekbot.net.Commands.Admin private readonly DatabaseContext _database; private readonly IErrorHandler _errorHandler; private readonly IReactionListener _reactionListener; - private readonly TranslationHandler _translationHandler; + private readonly ITranslationHandler _translationHandler; - public Role(DatabaseContext database, IErrorHandler errorHandler, IReactionListener reactionListener, TranslationHandler translationHandler) + public Role(DatabaseContext database, IErrorHandler errorHandler, IReactionListener reactionListener, ITranslationHandler translationHandler) { _database = database; _errorHandler = errorHandler; diff --git a/Geekbot.net/Commands/Utils/Quote/Quote.cs b/Geekbot.net/Commands/Utils/Quote/Quote.cs index a6f3ec9..84a3786 100644 --- a/Geekbot.net/Commands/Utils/Quote/Quote.cs +++ b/Geekbot.net/Commands/Utils/Quote/Quote.cs @@ -8,6 +8,7 @@ using Geekbot.net.Database.Models; using Geekbot.net.Lib.CommandPreconditions; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; +using Geekbot.net.Lib.Localization; using Geekbot.net.Lib.Polyfills; using Geekbot.net.Lib.RandomNumberGenerator; @@ -20,12 +21,14 @@ namespace Geekbot.net.Commands.Utils.Quote private readonly IErrorHandler _errorHandler; private readonly DatabaseContext _database; private readonly IRandomNumberGenerator _randomNumberGenerator; + private readonly ITranslationHandler _translationHandler; - public Quote(IErrorHandler errorHandler, DatabaseContext database, IRandomNumberGenerator randomNumberGenerator) + public Quote(IErrorHandler errorHandler, DatabaseContext database, IRandomNumberGenerator randomNumberGenerator, ITranslationHandler translationHandler) { _errorHandler = errorHandler; _database = database; _randomNumberGenerator = randomNumberGenerator; + _translationHandler = translationHandler; } [Command] @@ -38,7 +41,8 @@ namespace Geekbot.net.Commands.Utils.Quote if (!s.Any()) { - await ReplyAsync("This server doesn't seem to have any quotes yet. You can add a quote with `!quote save @user` or `!quote save `"); + var transContext = await _translationHandler.GetGuildContext(Context); + await ReplyAsync(transContext.GetString("NoQuotesFound")); return; } @@ -60,15 +64,16 @@ namespace Geekbot.net.Commands.Utils.Quote { try { + var transContext = await _translationHandler.GetGuildContext(Context); if (user.Id == Context.Message.Author.Id) { - await ReplyAsync("You can't save your own quotes..."); + await ReplyAsync(transContext.GetString("CannotSaveOwnQuotes")); return; } if (user.IsBot) { - await ReplyAsync("You can't save quotes by a bot..."); + await ReplyAsync(transContext.GetString("CannotQuoteBots")); return; } @@ -80,7 +85,7 @@ namespace Geekbot.net.Commands.Utils.Quote await _database.SaveChangesAsync(); var embed = QuoteBuilder(quote); - await ReplyAsync("**Quote Added**", false, embed.Build()); + await ReplyAsync(transContext.GetString("QuoteAdded"), false, embed.Build()); } catch (Exception e) { @@ -95,16 +100,17 @@ namespace Geekbot.net.Commands.Utils.Quote { try { + var transContext = await _translationHandler.GetGuildContext(Context); var message = await Context.Channel.GetMessageAsync(messageId); if (message.Author.Id == Context.Message.Author.Id) { - await ReplyAsync("You can't save your own quotes..."); + await ReplyAsync(transContext.GetString("CannotSaveOwnQuotes")); return; } if (message.Author.IsBot) { - await ReplyAsync("You can't save quotes by a bot..."); + await ReplyAsync(transContext.GetString("CannotQuoteBots")); return; } @@ -113,7 +119,7 @@ namespace Geekbot.net.Commands.Utils.Quote await _database.SaveChangesAsync(); var embed = QuoteBuilder(quote); - await ReplyAsync("**Quote Added**", false, embed.Build()); + await ReplyAsync(transContext.GetString("QuoteAdded"), false, embed.Build()); } catch (Exception e) { @@ -168,17 +174,18 @@ namespace Geekbot.net.Commands.Utils.Quote { try { + var transContext = await _translationHandler.GetGuildContext(Context); var quote = _database.Quotes.Where(e => e.GuildId == Context.Guild.Id.AsLong() && e.InternalId == id)?.FirstOrDefault(); if (quote != null) { _database.Quotes.Remove(quote); await _database.SaveChangesAsync(); var embed = QuoteBuilder(quote); - await ReplyAsync($"**Removed #{id}**", false, embed.Build()); + await ReplyAsync(transContext.GetString("Removed", id), false, embed.Build()); } else { - await ReplyAsync("I couldn't find a quote with that id :disappointed:"); + await ReplyAsync(transContext.GetString("NotFoundWithId")); } } catch (Exception e) diff --git a/Geekbot.net/Lib/Localization/Translations.json b/Geekbot.net/Lib/Localization/Translations.json index 6a864fc..689085e 100644 --- a/Geekbot.net/Lib/Localization/Translations.json +++ b/Geekbot.net/Lib/Localization/Translations.json @@ -190,5 +190,31 @@ "EN": ["Removed {0} from the whitelist"], "CHDE": ["{0} isch vo dr whitelist glöscht"] } + }, + "quote": { + "NoQuotesFound": { + "EN": ["This server doesn't seem to have any quotes yet. You can add a quote with `!quote save @user` or `!quote save `"], + "CHDE": ["Dä server het no kei quotes. Du chasch quotes hinzuefüege mit `!quote save @user` oder `!quote save `"] + }, + "CannotSaveOwnQuotes": { + "EN": ["You can't save your own quotes..."], + "CHDE": ["Du chasch kei quotes vo dir selber speichere..."] + }, + "CannotQuoteBots": { + "EN": ["You can't save quotes by a bot..."], + "CHDE": ["Du chasch kei quotes vomne bot speichere..."] + }, + "QuoteAdded": { + "EN": ["**Quote Added**"], + "CHDE": ["**Quote hinzugfüegt**"] + }, + "Removed": { + "EN": ["**Removed #{0}**"], + "CHDE": ["**#{0} glöscht**"] + }, + "NotFoundWithId": { + "EN": ["I couldn't find a quote with that ID :disappointed:"], + "CHDE": ["Ich chan kei quote finde mit därri ID :disappointed:"] + } } } \ No newline at end of file From e0e76d7c27a80346ef34aedb3e62b4d48678035b Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 12 May 2019 15:40:28 +0200 Subject: [PATCH 274/553] Use YAML for translations --- Geekbot.net/Geekbot.net.csproj | 4 +- .../Lib/Localization/TranslationHandler.cs | 14 +- .../Lib/Localization/Translations.json | 220 --------------- Geekbot.net/Lib/Localization/Translations.yml | 265 ++++++++++++++++++ 4 files changed, 278 insertions(+), 225 deletions(-) delete mode 100644 Geekbot.net/Lib/Localization/Translations.json create mode 100644 Geekbot.net/Lib/Localization/Translations.yml diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index fcf7b95..405c17e 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -58,6 +58,7 @@ 4.3.0 + @@ -87,9 +88,6 @@ PreserveNewest - - Always - Always diff --git a/Geekbot.net/Lib/Localization/TranslationHandler.cs b/Geekbot.net/Lib/Localization/TranslationHandler.cs index 8100478..51c516c 100644 --- a/Geekbot.net/Lib/Localization/TranslationHandler.cs +++ b/Geekbot.net/Lib/Localization/TranslationHandler.cs @@ -9,6 +9,8 @@ using Geekbot.net.Database.Models; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Logger; using Utf8Json; +using YamlDotNet.RepresentationModel; +using YamlDotNet.Serialization; namespace Geekbot.net.Lib.Localization { @@ -32,8 +34,15 @@ namespace Geekbot.net.Lib.Localization { try { - var translationFile = File.ReadAllText(Path.GetFullPath("./Lib/Localization/Translations.json")); - var rawTranslations = JsonSerializer.Deserialize>>>>(translationFile); + // Read the file + var translationFile = File.ReadAllText(Path.GetFullPath("./Lib/Localization/Translations.yml")); + + // Deserialize + var input = new StringReader(translationFile); + var deserializer = new DeserializerBuilder().Build(); + var rawTranslations = deserializer.Deserialize>>>>(input); + + // Sort var sortedPerLanguage = new Dictionary>>>(); foreach (var command in rawTranslations) { @@ -68,6 +77,7 @@ namespace Geekbot.net.Lib.Localization } _translations = sortedPerLanguage; + // Find Languages SupportedLanguages = new List(); foreach (var lang in sortedPerLanguage) { diff --git a/Geekbot.net/Lib/Localization/Translations.json b/Geekbot.net/Lib/Localization/Translations.json deleted file mode 100644 index 689085e..0000000 --- a/Geekbot.net/Lib/Localization/Translations.json +++ /dev/null @@ -1,220 +0,0 @@ -{ - "dateTime": { - "Days": { - "EN": ["day", "days"], - "CHDE": ["tag", "täg"] - }, - "Hours": { - "EN": ["hour", "hours"], - "CHDE": ["stund", "stunde"] - }, - "Minutes": { - "EN": ["minute", "minutes"], - "CHDE": ["minute", "minute"] - }, - "Seconds": { - "EN": ["second", "seconds"], - "CHDE": ["sekunde", "sekunde"] - }, - "And": { - "EN": ["and"], - "CHDE": ["und"] - } - }, - "admin": { - "NewLanguageSet": { - "EN": ["I will reply in english from now on"], - "CHDE": ["I werd ab jetzt uf schwiizerdüütsch antworte, äuuä"] - }, - "GetLanguage": { - "EN": ["I'm talking english"], - "CHDE": ["I red schwiizerdüütsch"] - } - }, - "errorHandler": { - "SomethingWentWrong": { - "EN": ["Something went wrong :confused:"], - "CHDE": ["Öppis isch schief gange :confused:"] - } - }, - "httpErrors": { - "403": { - "EN": ["Seems like i don't have enough permission to that :confused:"], - "CHDE": ["Gseht danach us das ich nid gnueg recht han zum das mache :confused:"] - } - }, - "choose": { - "Choice": { - "EN": ["I Choose **{0}**"], - "CHDE": ["I nimme **{0}**"] - } - }, - "good": { - "CannotChangeOwn": { - "EN": ["Sorry {0}, but you can't give yourself karma"], - "CHDE": ["Sorry {0}, aber du chasch dr selber kei karma geh"] - }, - "WaitUntill": { - "EN": ["Sorry {0}, but you have to wait {1} before you can give karma again..."], - "CHDE": ["Sorry {0}, aber du musch no {1} warte bisch d wieder karma chasch geh..."] - }, - "Increased": { - "EN": ["Karma gained"], - "CHDE": ["Karma becho"] - }, - "By": { - "EN": ["By"], - "CHDE": ["Vo"] - }, - "Amount": { - "EN": ["Amount"], - "CHDE": ["Mengi"] - }, - "Current": { - "EN": ["Current"], - "CHDE": ["Jetzt"] - } - }, - "bad": { - "CannotChangeOwn": { - "EN": ["Sorry {0}, but you can't lower your own karma"], - "CHDE": ["Sorry {0}, aber du chasch dr din eigete karma nid weg neh"] - }, - "WaitUntill": { - "EN": ["Sorry {0}, but you have to wait {1} before you can lower karma again..."], - "CHDE": ["Sorry {0}, aber du musch no {1} warte bisch d wieder karma chasch senke..."] - }, - "Decreased": { - "EN": ["Karma lowered"], - "CHDE": ["Karma gsenkt"] - }, - "By": { - "EN": ["By"], - "CHDE": ["Vo"] - }, - "Amount": { - "EN": ["Amount"], - "CHDE": ["Mengi"] - }, - "Current": { - "EN": ["Current"], - "CHDE": ["Jetzt"] - } - }, - "roll": { - "Rolled": { - "EN": ["{0}, you rolled {1}, your guess was {2}"], - "CHDE": ["{0}, du hesch {1} grollt und hesch {2} grate"] - }, - "Gratz": { - "EN": ["Congratulations {0}, your guess was correct!"], - "CHDE": ["Gratuliere {0}, du hesch richtig grate!"] - }, - "RolledNoGuess": { - "EN": ["{0}, you rolled {1}"], - "CHDE": ["{0}, du hesch {1} grollt"] - }, - "NoPrevGuess": { - "EN": [":red_circle: {0}, you can't guess the same number again"], - "CHDE": [":red_circle: {0}, du chasch nid nomol es gliche rate"] - } - }, - "cookies": { - "GetCookies": { - "EN": ["You got {0} cookies, there are now {1} cookies in you cookie jar"], - "CHDE": ["Du häsch {0} guetzli becho, du häsch jetzt {1} guetzli ih dr büchse"] - }, - "WaitForMoreCookies": { - "EN": ["You already got cookies in the last 24 hours, you can have more cookies in {0}"], - "CHDE": ["Du hesch scho guetzli becho ih de letzti 24 stund, du chasch meh ha in {0}"] - }, - "InYourJar": { - "EN": ["There are {0} cookies in you cookie jar"], - "CHDE": ["Es hät {0} guetzli ih dineri büchs"] - }, - "Given": { - "EN": ["You gave {0} cookies to {1}"], - "CHDE": ["Du hesch {1} {0} guetzli geh"] - }, - "NotEnoughToGive": { - "EN": ["You don't have enough cookies"], - "CHDE": ["Du hesch nid gnueg guetzli"] - }, - "NotEnoughCookiesToEat": { - "EN": ["Your cookie jar looks almost empty, you should probably not eat a cookie"], - "CHDE": ["Du hesch chuum no guetzli ih dineri büchs, du sötsch warschinli keini esse"] - }, - "AteCookies": { - "EN": ["You ate {0} cookies, you've only got {1} cookies left"], - "CHDE": ["Du hesch {0} guetzli gesse und hesch jezt no {1} übrig"] - } - }, - "role": { - "NoRolesConfigured": { - "EN": ["There are no roles configured for this server"], - "CHDE": ["Es sind kei rolle für dä server konfiguriert"] - }, - "ListHeader": { - "EN": ["**Self Service Roles on {0}**"], - "CHDE": ["**Self Service Rollene uf {0}**"] - }, - "ListInstruction": { - "EN": ["To get a role, use `!role [name]`"], - "CHDE": ["Zum ä rolle becho, schriib `!role [name]`"] - }, - "RoleNotFound": { - "EN": ["That role doesn't exist or is not on the whitelist"], - "CHDE": ["Die rolle gids nid or isch nid uf dr whitelist"] - }, - "RemovedUserFromRole": { - "EN": ["Removed you from {0}"], - "CHDE": ["Han di entfernt vo {0}"] - }, - "AddedUserFromRole": { - "EN": ["Added you to {0}"], - "CHDE": ["Han di hinzue gfüegt zu {0}"] - }, - "CannotAddManagedRole": { - "EN": ["You can't add a role that is managed by discord"], - "CHDE": ["Du chasch kei rolle hinzuefüge wo verwalted wird vo discord"] - }, - "CannotAddDangerousRole": { - "EN": ["You cannot add that role to self service because it contains one or more dangerous permissions"], - "CHDE": ["Du chasch die rolle nid hinzuefüge will er ein oder mehreri gföhrlichi berechtigunge het"] - }, - "AddedRoleToWhitelist": { - "EN": ["Added {0} to the whitelist"], - "CHDE": ["{0} isch zur whitelist hinzuegfüegt"] - }, - "RemovedRoleFromWhitelist": { - "EN": ["Removed {0} from the whitelist"], - "CHDE": ["{0} isch vo dr whitelist glöscht"] - } - }, - "quote": { - "NoQuotesFound": { - "EN": ["This server doesn't seem to have any quotes yet. You can add a quote with `!quote save @user` or `!quote save `"], - "CHDE": ["Dä server het no kei quotes. Du chasch quotes hinzuefüege mit `!quote save @user` oder `!quote save `"] - }, - "CannotSaveOwnQuotes": { - "EN": ["You can't save your own quotes..."], - "CHDE": ["Du chasch kei quotes vo dir selber speichere..."] - }, - "CannotQuoteBots": { - "EN": ["You can't save quotes by a bot..."], - "CHDE": ["Du chasch kei quotes vomne bot speichere..."] - }, - "QuoteAdded": { - "EN": ["**Quote Added**"], - "CHDE": ["**Quote hinzugfüegt**"] - }, - "Removed": { - "EN": ["**Removed #{0}**"], - "CHDE": ["**#{0} glöscht**"] - }, - "NotFoundWithId": { - "EN": ["I couldn't find a quote with that ID :disappointed:"], - "CHDE": ["Ich chan kei quote finde mit därri ID :disappointed:"] - } - } -} \ No newline at end of file diff --git a/Geekbot.net/Lib/Localization/Translations.yml b/Geekbot.net/Lib/Localization/Translations.yml new file mode 100644 index 0000000..02e13f4 --- /dev/null +++ b/Geekbot.net/Lib/Localization/Translations.yml @@ -0,0 +1,265 @@ +--- +dateTime: + Days: + EN: + - "day" + - "days" + CHDE: + - "tag" + - "täg" + Hours: + EN: + - "hour" + - "hours" + CHDE: + - "stund" + - "stunde" + Minutes: + EN: + - "minute" + - "minutes" + CHDE: + - "minute" + - "minute" + Seconds: + EN: + - "second" + - "seconds" + CHDE: + - "sekunde" + - "sekunde" + And: + EN: + - "and" + CHDE: + - "und" +admin: + NewLanguageSet: + EN: + - "I will reply in english from now on" + CHDE: + - "I werd ab jetzt uf schwiizerdüütsch antworte, äuuä" + GetLanguage: + EN: + - "I'm talking english" + CHDE: + - "I red schwiizerdüütsch" +errorHandler: + SomethingWentWrong: + EN: + - "Something went wrong :confused:" + CHDE: + - "Öppis isch schief gange :confused:" +httpErrors: + 403: + EN: + - "Seems like i don't have enough permission to that :confused:" + CHDE: + - "Gseht danach us das ich nid gnueg recht han zum das mache :confused:" +choose: + Choice: + EN: + - "I Choose **{0}**" + CHDE: + - "I nimme **{0}**" +good: + CannotChangeOwn: + EN: + - "Sorry {0}, but you can't give yourself karma" + CHDE: + - "Sorry {0}, aber du chasch dr selber kei karma geh" + WaitUntill: + EN: + - "Sorry {0}, but you have to wait {1} before you can give karma again..." + CHDE: + - "Sorry {0}, aber du musch no {1} warte bisch d wieder karma chasch geh..." + Increased: + EN: + - "Karma gained" + CHDE: + - "Karma becho" + By: + EN: + - "By" + CHDE: + - "Vo" + Amount: + EN: + - "Amount" + CHDE: + - "Mengi" + Current: + EN: + - "Current" + CHDE: + - "Jetzt" +bad: + CannotChangeOwn: + EN: + - "Sorry {0}, but you can't lower your own karma" + CHDE: + - "Sorry {0}, aber du chasch dr din eigete karma nid weg neh" + WaitUntill: + EN: + - "Sorry {0}, but you have to wait {1} before you can lower karma again..." + CHDE: + - "Sorry {0}, aber du musch no {1} warte bisch d wieder karma chasch senke..." + Decreased: + EN: + - "Karma lowered" + CHDE: + - "Karma gsenkt" + By: + EN: + - "By" + CHDE: + - "Vo" + Amount: + EN: + - "Amount" + CHDE: + - "Mengi" + Current: + EN: + - "Current" + CHDE: + - "Jetzt" +roll: + Rolled: + EN: + - "{0}, you rolled {1}, your guess was {2}" + CHDE: + - "{0}, du hesch {1} grollt und hesch {2} grate" + Gratz: + EN: + - "Congratulations {0}, your guess was correct!" + CHDE: + - "Gratuliere {0}, du hesch richtig grate!" + RolledNoGuess: + EN: + - "{0}, you rolled {1}" + CHDE: + - "{0}, du hesch {1} grollt" + NoPrevGuess: + EN: + - ":red_circle: {0}, you can't guess the same number again" + CHDE: + - ":red_circle: {0}, du chasch nid nomol es gliche rate" +cookies: + GetCookies: + EN: + - "You got {0} cookies, there are now {1} cookies in you cookie jar" + CHDE: + - "Du häsch {0} guetzli becho, du häsch jetzt {1} guetzli ih dr büchse" + WaitForMoreCookies: + EN: + - "You already got cookies in the last 24 hours, you can have more cookies in {0}" + CHDE: + - "Du hesch scho guetzli becho ih de letzti 24 stund, du chasch meh ha in {0}" + InYourJar: + EN: + - "There are {0} cookies in you cookie jar" + CHDE: + - "Es hät {0} guetzli ih dineri büchs" + Given: + EN: + - "You gave {0} cookies to {1}" + CHDE: + - "Du hesch {1} {0} guetzli geh" + NotEnoughToGive: + EN: + - "You don't have enough cookies" + CHDE: + - "Du hesch nid gnueg guetzli" + NotEnoughCookiesToEat: + EN: + - "Your cookie jar looks almost empty, you should probably not eat a cookie" + CHDE: + - "Du hesch chuum no guetzli ih dineri büchs, du sötsch warschinli keini esse" + AteCookies: + EN: + - "You ate {0} cookies, you've only got {1} cookies left" + CHDE: + - "Du hesch {0} guetzli gesse und hesch jezt no {1} übrig" +role: + NoRolesConfigured: + EN: + - "There are no roles configured for this server" + CHDE: + - "Es sind kei rolle für dä server konfiguriert" + ListHeader: + EN: + - "**Self Service Roles on {0}**" + CHDE: + - "**Self Service Rollene uf {0}**" + ListInstruction: + EN: + - "To get a role, use `!role [name]`" + CHDE: + - "Zum ä rolle becho, schriib `!role [name]`" + RoleNotFound: + EN: + - "That role doesn't exist or is not on the whitelist" + CHDE: + - "Die rolle gids nid or isch nid uf dr whitelist" + RemovedUserFromRole: + EN: + - "Removed you from {0}" + CHDE: + - "Han di entfernt vo {0}" + AddedUserFromRole: + EN: + - "Added you to {0}" + CHDE: + - "Han di hinzue gfüegt zu {0}" + CannotAddManagedRole: + EN: + - "You can't add a role that is managed by discord" + CHDE: + - "Du chasch kei rolle hinzuefüge wo verwalted wird vo discord" + CannotAddDangerousRole: + EN: + - "You cannot add that role to self service because it contains one or more dangerous permissions" + CHDE: + - "Du chasch die rolle nid hinzuefüge will er ein oder mehreri gföhrlichi berechtigunge het" + AddedRoleToWhitelist: + EN: + - "Added {0} to the whitelist" + CHDE: + - "{0} isch zur whitelist hinzuegfüegt" + RemovedRoleFromWhitelist: + EN: + - "Removed {0} from the whitelist" + CHDE: + - "{0} isch vo dr whitelist glöscht" +quote: + NoQuotesFound: + EN: + - "This server doesn't seem to have any quotes yet. You can add a quote with `!quote save @user` or `!quote save `" + CHDE: + - "Dä server het no kei quotes. Du chasch quotes hinzuefüege mit `!quote save @user` oder `!quote save `" + CannotSaveOwnQuotes: + EN: + - "You can't save your own quotes..." + CHDE: + - "Du chasch kei quotes vo dir selber speichere..." + CannotQuoteBots: + EN: + - "You can't save quotes by a bot..." + CHDE: + - "Du chasch kei quotes vomne bot speichere..." + QuoteAdded: + EN: + - "**Quote Added**" + CHDE: + - "**Quote hinzugfüegt**" + Removed: + EN: + - "**Removed #{0}**" + CHDE: + - "**#{0} glöscht**" + NotFoundWithId: + EN: + - "I couldn't find a quote with that ID :disappointed:" + CHDE: + - "Ich chan kei quote finde mit därri ID :disappointed:" \ No newline at end of file From 53f894676c88370b281c7f4abb258034db76e159 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 12 May 2019 15:49:00 +0200 Subject: [PATCH 275/553] Revert back to using strings in stead of arrays in the translations --- .../Lib/Localization/ITranslationHandler.cs | 2 +- .../Localization/TranslationGuildContext.cs | 15 +- .../Lib/Localization/TranslationHandler.cs | 27 +- Geekbot.net/Lib/Localization/Translations.yml | 302 ++++++------------ 4 files changed, 120 insertions(+), 226 deletions(-) diff --git a/Geekbot.net/Lib/Localization/ITranslationHandler.cs b/Geekbot.net/Lib/Localization/ITranslationHandler.cs index bb70046..9cd0680 100644 --- a/Geekbot.net/Lib/Localization/ITranslationHandler.cs +++ b/Geekbot.net/Lib/Localization/ITranslationHandler.cs @@ -7,7 +7,7 @@ namespace Geekbot.net.Lib.Localization public interface ITranslationHandler { Task GetString(ulong guildId, string command, string stringName); - List GetStrings(string language, string command, string stringName); + string GetString(string language, string command, string stringName); Task> GetDict(ICommandContext context, string command); Task GetGuildContext(ICommandContext context); Task SetLanguage(ulong guildId, string language); diff --git a/Geekbot.net/Lib/Localization/TranslationGuildContext.cs b/Geekbot.net/Lib/Localization/TranslationGuildContext.cs index 3f6f923..6181c04 100644 --- a/Geekbot.net/Lib/Localization/TranslationGuildContext.cs +++ b/Geekbot.net/Lib/Localization/TranslationGuildContext.cs @@ -10,9 +10,9 @@ namespace Geekbot.net.Lib.Localization { public ITranslationHandler TranslationHandler { get; } public string Language { get; } - public Dictionary> Dict { get; } + public Dictionary Dict { get; } - public TranslationGuildContext(ITranslationHandler translationHandler, string language, Dictionary> dict) + public TranslationGuildContext(ITranslationHandler translationHandler, string language, Dictionary dict) { TranslationHandler = translationHandler; Language = language; @@ -21,7 +21,7 @@ namespace Geekbot.net.Lib.Localization public string GetString(string stringToFormat, params object[] args) { - return string.Format(Dict[stringToFormat].First() ?? "", args); + return string.Format(Dict[stringToFormat] ?? "", args); } public string FormatDateTimeAsRemaining(DateTimeOffset dateTime) @@ -54,7 +54,7 @@ namespace Geekbot.net.Lib.Localization { if (sb.Length > 0) { - var and = TranslationHandler.GetStrings(Language, "dateTime", "And").First(); + var and = TranslationHandler.GetString(Language, "dateTime", "And"); sb.AppendFormat(" {0} ", and); } var s = GetTimeString(TimeTypes.Seconds); @@ -69,13 +69,14 @@ namespace Geekbot.net.Lib.Localization return TranslationHandler.SetLanguage(guildId, language); } - private List GetTimeString(TimeTypes type) + private string GetTimeString(TimeTypes type) { - return TranslationHandler.GetStrings(Language, "dateTime", type.ToString()); + return TranslationHandler.GetString(Language, "dateTime", type.ToString()); } - private string GetSingOrPlur(int number, List versions) + private string GetSingOrPlur(int number, string rawString) { + var versions = rawString.Split('|'); return number == 1 ? versions[0] : versions[1]; } diff --git a/Geekbot.net/Lib/Localization/TranslationHandler.cs b/Geekbot.net/Lib/Localization/TranslationHandler.cs index 51c516c..3d1ee3a 100644 --- a/Geekbot.net/Lib/Localization/TranslationHandler.cs +++ b/Geekbot.net/Lib/Localization/TranslationHandler.cs @@ -19,7 +19,7 @@ namespace Geekbot.net.Lib.Localization private readonly DatabaseContext _database; private readonly IGeekbotLogger _logger; private readonly Dictionary _serverLanguages; - private Dictionary>>> _translations; + private Dictionary>> _translations; public TranslationHandler(DatabaseContext database, IGeekbotLogger logger) { @@ -40,10 +40,10 @@ namespace Geekbot.net.Lib.Localization // Deserialize var input = new StringReader(translationFile); var deserializer = new DeserializerBuilder().Build(); - var rawTranslations = deserializer.Deserialize>>>>(input); + var rawTranslations = deserializer.Deserialize>>>(input); // Sort - var sortedPerLanguage = new Dictionary>>>(); + var sortedPerLanguage = new Dictionary>>(); foreach (var command in rawTranslations) { foreach (var str in command.Value) @@ -52,8 +52,8 @@ namespace Geekbot.net.Lib.Localization { if (!sortedPerLanguage.ContainsKey(lang.Key)) { - var commandDict = new Dictionary>>(); - var strDict = new Dictionary> + var commandDict = new Dictionary>(); + var strDict = new Dictionary { {str.Key, lang.Value} }; @@ -62,7 +62,7 @@ namespace Geekbot.net.Lib.Localization } if (!sortedPerLanguage[lang.Key].ContainsKey(command.Key)) { - var strDict = new Dictionary> + var strDict = new Dictionary { {str.Key, lang.Value} }; @@ -122,22 +122,22 @@ namespace Geekbot.net.Lib.Localization public async Task GetString(ulong guildId, string command, string stringName) { var serverLang = await GetServerLanguage(guildId); - return GetStrings(serverLang, command, stringName).First(); + return GetString(serverLang, command, stringName); } - public List GetStrings(string language, string command, string stringName) + public string GetString(string language, string command, string stringName) { var translation = _translations[language][command][stringName]; - if (!string.IsNullOrWhiteSpace(translation.First())) return translation; + if (!string.IsNullOrWhiteSpace(translation)) return translation; translation = _translations[command][stringName]["EN"]; - if (string.IsNullOrWhiteSpace(translation.First())) + if (string.IsNullOrWhiteSpace(translation)) { _logger.Warning(LogSource.Geekbot, $"No translation found for {command} - {stringName}"); } return translation; } - private async Task>> GetDict(ICommandContext context) + private async Task> GetDict(ICommandContext context) { try { @@ -148,7 +148,7 @@ namespace Geekbot.net.Lib.Localization catch (Exception e) { _logger.Error(LogSource.Geekbot, "No translations for command found", e); - return new Dictionary>(); + return new Dictionary(); } } @@ -164,8 +164,7 @@ namespace Geekbot.net.Lib.Localization try { var serverLanguage = await GetServerLanguage(context.Guild?.Id ?? 0); - return _translations[serverLanguage][command] - .ToDictionary(dict => dict.Key, dict => dict.Value.First()); + return _translations[serverLanguage][command]; } catch (Exception e) { diff --git a/Geekbot.net/Lib/Localization/Translations.yml b/Geekbot.net/Lib/Localization/Translations.yml index 02e13f4..6b8d1cd 100644 --- a/Geekbot.net/Lib/Localization/Translations.yml +++ b/Geekbot.net/Lib/Localization/Translations.yml @@ -1,265 +1,159 @@ --- dateTime: Days: - EN: - - "day" - - "days" - CHDE: - - "tag" - - "täg" + EN: "day|days" + CHDE: "tag|täg" Hours: - EN: - - "hour" - - "hours" - CHDE: - - "stund" - - "stunde" + EN: "hour|hours" + CHDE: "stund|stunde" Minutes: - EN: - - "minute" - - "minutes" - CHDE: - - "minute" - - "minute" + EN: "minute|minutes" + CHDE: "minute|minute" Seconds: - EN: - - "second" - - "seconds" - CHDE: - - "sekunde" - - "sekunde" + EN: "second|seconds" + CHDE: "sekunde|sekunde" And: - EN: - - "and" - CHDE: - - "und" + EN: "and" + CHDE: "und" admin: NewLanguageSet: - EN: - - "I will reply in english from now on" - CHDE: - - "I werd ab jetzt uf schwiizerdüütsch antworte, äuuä" + EN: "I will reply in english from now on" + CHDE: "I werd ab jetzt uf schwiizerdüütsch antworte, äuuä" GetLanguage: - EN: - - "I'm talking english" - CHDE: - - "I red schwiizerdüütsch" + EN: "I'm talking english" + CHDE: "I red schwiizerdüütsch" errorHandler: SomethingWentWrong: - EN: - - "Something went wrong :confused:" - CHDE: - - "Öppis isch schief gange :confused:" + EN: "Something went wrong :confused:" + CHDE: "Öppis isch schief gange :confused:" httpErrors: 403: - EN: - - "Seems like i don't have enough permission to that :confused:" - CHDE: - - "Gseht danach us das ich nid gnueg recht han zum das mache :confused:" + EN: "Seems like i don't have enough permission to that :confused:" + CHDE: "Gseht danach us das ich nid gnueg recht han zum das mache :confused:" choose: Choice: - EN: - - "I Choose **{0}**" - CHDE: - - "I nimme **{0}**" + EN: "I Choose **{0}**" + CHDE: "I nimme **{0}**" good: CannotChangeOwn: - EN: - - "Sorry {0}, but you can't give yourself karma" - CHDE: - - "Sorry {0}, aber du chasch dr selber kei karma geh" + EN: "Sorry {0}, but you can't give yourself karma" + CHDE: "Sorry {0}, aber du chasch dr selber kei karma geh" WaitUntill: - EN: - - "Sorry {0}, but you have to wait {1} before you can give karma again..." - CHDE: - - "Sorry {0}, aber du musch no {1} warte bisch d wieder karma chasch geh..." + EN: "Sorry {0}, but you have to wait {1} before you can give karma again..." + CHDE: "Sorry {0}, aber du musch no {1} warte bisch d wieder karma chasch geh..." Increased: - EN: - - "Karma gained" - CHDE: - - "Karma becho" + EN: "Karma gained" + CHDE: "Karma becho" By: - EN: - - "By" - CHDE: - - "Vo" + EN: "By" + CHDE: "Vo" Amount: - EN: - - "Amount" - CHDE: - - "Mengi" + EN: "Amount" + CHDE: "Mengi" Current: - EN: - - "Current" - CHDE: - - "Jetzt" + EN: "Current" + CHDE: "Jetzt" bad: CannotChangeOwn: - EN: - - "Sorry {0}, but you can't lower your own karma" - CHDE: - - "Sorry {0}, aber du chasch dr din eigete karma nid weg neh" + EN: "Sorry {0}, but you can't lower your own karma" + CHDE: "Sorry {0}, aber du chasch dr din eigete karma nid weg neh" WaitUntill: - EN: - - "Sorry {0}, but you have to wait {1} before you can lower karma again..." - CHDE: - - "Sorry {0}, aber du musch no {1} warte bisch d wieder karma chasch senke..." + EN: "Sorry {0}, but you have to wait {1} before you can lower karma again..." + CHDE: "Sorry {0}, aber du musch no {1} warte bisch d wieder karma chasch senke..." Decreased: - EN: - - "Karma lowered" - CHDE: - - "Karma gsenkt" + EN: "Karma lowered" + CHDE: "Karma gsenkt" By: - EN: - - "By" - CHDE: - - "Vo" + EN: "By" + CHDE: "Vo" Amount: - EN: - - "Amount" - CHDE: - - "Mengi" + EN: "Amount" + CHDE: "Mengi" Current: - EN: - - "Current" - CHDE: - - "Jetzt" + EN: "Current" + CHDE: "Jetzt" roll: Rolled: - EN: - - "{0}, you rolled {1}, your guess was {2}" - CHDE: - - "{0}, du hesch {1} grollt und hesch {2} grate" + EN: "{0}, you rolled {1}, your guess was {2}" + CHDE: "{0}, du hesch {1} grollt und hesch {2} grate" Gratz: - EN: - - "Congratulations {0}, your guess was correct!" - CHDE: - - "Gratuliere {0}, du hesch richtig grate!" + EN: "Congratulations {0}, your guess was correct!" + CHDE: "Gratuliere {0}, du hesch richtig grate!" RolledNoGuess: - EN: - - "{0}, you rolled {1}" - CHDE: - - "{0}, du hesch {1} grollt" + EN: "{0}, you rolled {1}" + CHDE: "{0}, du hesch {1} grollt" NoPrevGuess: - EN: - - ":red_circle: {0}, you can't guess the same number again" - CHDE: - - ":red_circle: {0}, du chasch nid nomol es gliche rate" + EN: ":red_circle: {0}, you can't guess the same number again" + CHDE: ":red_circle: {0}, du chasch nid nomol es gliche rate" cookies: GetCookies: - EN: - - "You got {0} cookies, there are now {1} cookies in you cookie jar" - CHDE: - - "Du häsch {0} guetzli becho, du häsch jetzt {1} guetzli ih dr büchse" + EN: "You got {0} cookies, there are now {1} cookies in you cookie jar" + CHDE: "Du häsch {0} guetzli becho, du häsch jetzt {1} guetzli ih dr büchse" WaitForMoreCookies: - EN: - - "You already got cookies in the last 24 hours, you can have more cookies in {0}" - CHDE: - - "Du hesch scho guetzli becho ih de letzti 24 stund, du chasch meh ha in {0}" + EN: "You already got cookies in the last 24 hours, you can have more cookies in {0}" + CHDE: "Du hesch scho guetzli becho ih de letzti 24 stund, du chasch meh ha in {0}" InYourJar: - EN: - - "There are {0} cookies in you cookie jar" - CHDE: - - "Es hät {0} guetzli ih dineri büchs" + EN: "There are {0} cookies in you cookie jar" + CHDE: "Es hät {0} guetzli ih dineri büchs" Given: - EN: - - "You gave {0} cookies to {1}" - CHDE: - - "Du hesch {1} {0} guetzli geh" + EN: "You gave {0} cookies to {1}" + CHDE: "Du hesch {1} {0} guetzli geh" NotEnoughToGive: - EN: - - "You don't have enough cookies" - CHDE: - - "Du hesch nid gnueg guetzli" + EN: "You don't have enough cookies" + CHDE: "Du hesch nid gnueg guetzli" NotEnoughCookiesToEat: - EN: - - "Your cookie jar looks almost empty, you should probably not eat a cookie" - CHDE: - - "Du hesch chuum no guetzli ih dineri büchs, du sötsch warschinli keini esse" + EN: "Your cookie jar looks almost empty, you should probably not eat a cookie" + CHDE: "Du hesch chuum no guetzli ih dineri büchs, du sötsch warschinli keini esse" AteCookies: - EN: - - "You ate {0} cookies, you've only got {1} cookies left" - CHDE: - - "Du hesch {0} guetzli gesse und hesch jezt no {1} übrig" + EN: "You ate {0} cookies, you've only got {1} cookies left" + CHDE: "Du hesch {0} guetzli gesse und hesch jezt no {1} übrig" role: NoRolesConfigured: - EN: - - "There are no roles configured for this server" - CHDE: - - "Es sind kei rolle für dä server konfiguriert" + EN: "There are no roles configured for this server" + CHDE: "Es sind kei rolle für dä server konfiguriert" ListHeader: - EN: - - "**Self Service Roles on {0}**" - CHDE: - - "**Self Service Rollene uf {0}**" + EN: "**Self Service Roles on {0}**" + CHDE: "**Self Service Rollene uf {0}**" ListInstruction: - EN: - - "To get a role, use `!role [name]`" - CHDE: - - "Zum ä rolle becho, schriib `!role [name]`" + EN: "To get a role, use `!role [name]`" + CHDE: "Zum ä rolle becho, schriib `!role [name]`" RoleNotFound: - EN: - - "That role doesn't exist or is not on the whitelist" - CHDE: - - "Die rolle gids nid or isch nid uf dr whitelist" + EN: "That role doesn't exist or is not on the whitelist" + CHDE: "Die rolle gids nid or isch nid uf dr whitelist" RemovedUserFromRole: - EN: - - "Removed you from {0}" - CHDE: - - "Han di entfernt vo {0}" + EN: "Removed you from {0}" + CHDE: "Han di entfernt vo {0}" AddedUserFromRole: - EN: - - "Added you to {0}" - CHDE: - - "Han di hinzue gfüegt zu {0}" + EN: "Added you to {0}" + CHDE: "Han di hinzue gfüegt zu {0}" CannotAddManagedRole: - EN: - - "You can't add a role that is managed by discord" - CHDE: - - "Du chasch kei rolle hinzuefüge wo verwalted wird vo discord" + EN: "You can't add a role that is managed by discord" + CHDE: "Du chasch kei rolle hinzuefüge wo verwalted wird vo discord" CannotAddDangerousRole: - EN: - - "You cannot add that role to self service because it contains one or more dangerous permissions" - CHDE: - - "Du chasch die rolle nid hinzuefüge will er ein oder mehreri gföhrlichi berechtigunge het" + EN: "You cannot add that role to self service because it contains one or more dangerous permissions" + CHDE: "Du chasch die rolle nid hinzuefüge will er ein oder mehreri gföhrlichi berechtigunge het" AddedRoleToWhitelist: - EN: - - "Added {0} to the whitelist" - CHDE: - - "{0} isch zur whitelist hinzuegfüegt" + EN: "Added {0} to the whitelist" + CHDE: "{0} isch zur whitelist hinzuegfüegt" RemovedRoleFromWhitelist: - EN: - - "Removed {0} from the whitelist" - CHDE: - - "{0} isch vo dr whitelist glöscht" + EN: "Removed {0} from the whitelist" + CHDE: "{0} isch vo dr whitelist glöscht" quote: NoQuotesFound: - EN: - - "This server doesn't seem to have any quotes yet. You can add a quote with `!quote save @user` or `!quote save `" - CHDE: - - "Dä server het no kei quotes. Du chasch quotes hinzuefüege mit `!quote save @user` oder `!quote save `" + EN: "This server doesn't seem to have any quotes yet. You can add a quote with `!quote save @user` or `!quote save `" + CHDE: "Dä server het no kei quotes. Du chasch quotes hinzuefüege mit `!quote save @user` oder `!quote save `" CannotSaveOwnQuotes: - EN: - - "You can't save your own quotes..." - CHDE: - - "Du chasch kei quotes vo dir selber speichere..." + EN: "You can't save your own quotes..." + CHDE: "Du chasch kei quotes vo dir selber speichere..." CannotQuoteBots: - EN: - - "You can't save quotes by a bot..." - CHDE: - - "Du chasch kei quotes vomne bot speichere..." + EN: "You can't save quotes by a bot..." + CHDE: "Du chasch kei quotes vomne bot speichere..." QuoteAdded: - EN: - - "**Quote Added**" - CHDE: - - "**Quote hinzugfüegt**" + EN: "**Quote Added**" + CHDE: "**Quote hinzugfüegt**" Removed: - EN: - - "**Removed #{0}**" - CHDE: - - "**#{0} glöscht**" + EN: "**Removed #{0}**" + CHDE: "**#{0} glöscht**" NotFoundWithId: - EN: - - "I couldn't find a quote with that ID :disappointed:" - CHDE: - - "Ich chan kei quote finde mit därri ID :disappointed:" \ No newline at end of file + EN: "I couldn't find a quote with that ID :disappointed:" + CHDE: "Ich chan kei quote finde mit därri ID :disappointed:" \ No newline at end of file From 5efb146d18568448c1d05076ba8feba7d8d65d96 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 12 May 2019 15:57:58 +0200 Subject: [PATCH 276/553] Fix Unit tests --- Geekbot.net/Geekbot.net.csproj | 3 +++ .../TranslationGuildContext.test.cs | 22 +++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 405c17e..9c5c5c7 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -94,6 +94,9 @@ PreserveNewest + + Always + diff --git a/Tests/Lib/Localization/TranslationGuildContext.test.cs b/Tests/Lib/Localization/TranslationGuildContext.test.cs index 90f1446..aeea0e1 100644 --- a/Tests/Lib/Localization/TranslationGuildContext.test.cs +++ b/Tests/Lib/Localization/TranslationGuildContext.test.cs @@ -48,22 +48,22 @@ namespace Tests.Lib.Localization { var translationHandlerMock = new Mock(MockBehavior.Loose); translationHandlerMock - .Setup(thm => thm.GetStrings("EN", "dateTime", "Days")) - .Returns(new List {{"day"}, {"days"}}); + .Setup(thm => thm.GetString("EN", "dateTime", "Days")) + .Returns("day|days"); translationHandlerMock - .Setup(thm => thm.GetStrings("EN", "dateTime", "Hours")) - .Returns(new List {{"hour"}, {"hours"}}); + .Setup(thm => thm.GetString("EN", "dateTime", "Hours")) + .Returns("hour|hours"); translationHandlerMock - .Setup(thm => thm.GetStrings("EN", "dateTime", "Minutes")) - .Returns(new List {{"minute"}, {"minutes"}}); + .Setup(thm => thm.GetString("EN", "dateTime", "Minutes")) + .Returns("minute|minutes"); translationHandlerMock - .Setup(thm => thm.GetStrings("EN", "dateTime", "Seconds")) - .Returns(new List {{"second"}, {"seconds"}}); + .Setup(thm => thm.GetString("EN", "dateTime", "Seconds")) + .Returns("second|seconds"); translationHandlerMock - .Setup(thm => thm.GetStrings("EN", "dateTime", "And")) - .Returns(new List {{"and"}}); + .Setup(thm => thm.GetString("EN", "dateTime", "And")) + .Returns("and"); - var context = new TranslationGuildContext(translationHandlerMock.Object, "EN", new Dictionary>()); + var context = new TranslationGuildContext(translationHandlerMock.Object, "EN", new Dictionary()); var result = context.FormatDateTimeAsRemaining(testData.DateTime); Assert.Equal(result, testData.Expected); } From 92c2d173eb64c9b373f97d384aa322d47bf3420b Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 12 May 2019 16:15:42 +0200 Subject: [PATCH 277/553] make HighscoreManager transient to solve a bug where the information reported would be wrong --- Geekbot.net/Program.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 27274d2..d04dcbb 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -40,7 +40,6 @@ namespace Geekbot.net private IUserRepository _userRepository; private RunParameters _runParameters; private IAlmostRedis _redis; - private IHighscoreManager _highscoreManager; private static void Main(string[] args) { @@ -124,7 +123,6 @@ namespace Geekbot.net var mtgManaConverter = new MtgManaConverter(); var wikipediaClient = new WikipediaClient(); var randomNumberGenerator = new RandomNumberGenerator(); - _highscoreManager = new HighscoreManager(_databaseInitializer.Initialize(), _userRepository); _services.AddSingleton(_redis); _services.AddSingleton(_userRepository); @@ -137,8 +135,8 @@ namespace Geekbot.net _services.AddSingleton(mtgManaConverter); _services.AddSingleton(wikipediaClient); _services.AddSingleton(randomNumberGenerator); - _services.AddSingleton(_highscoreManager); _services.AddSingleton(_globalSettings); + _services.AddTransient((e) => new HighscoreManager(_databaseInitializer.Initialize(), _userRepository)); _services.AddTransient((e) => _databaseInitializer.Initialize()); logger.Information(LogSource.Geekbot, "Connecting to Discord"); @@ -206,7 +204,8 @@ namespace Geekbot.net private Task StartWebApi() { _logger.Information(LogSource.Api, "Starting Webserver"); - WebApi.WebApiStartup.StartWebApi(_logger, _runParameters, _commands, _databaseInitializer.Initialize(), _client, _globalSettings, _highscoreManager); + var highscoreManager = new HighscoreManager(_databaseInitializer.Initialize(), _userRepository); + WebApi.WebApiStartup.StartWebApi(_logger, _runParameters, _commands, _databaseInitializer.Initialize(), _client, _globalSettings, highscoreManager); return Task.CompletedTask; } } From 5109cc03a444c5e145e62e062077fd958a21edb7 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 12 May 2019 16:38:43 +0200 Subject: [PATCH 278/553] Translate rank command --- Geekbot.net/Commands/Rpg/Cookies.cs | 2 +- Geekbot.net/Commands/User/Ranking/Rank.cs | 16 ++++++++++------ Geekbot.net/Lib/Localization/Translations.yml | 18 +++++++++++++++++- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/Geekbot.net/Commands/Rpg/Cookies.cs b/Geekbot.net/Commands/Rpg/Cookies.cs index e7192c6..6e4ff54 100644 --- a/Geekbot.net/Commands/Rpg/Cookies.cs +++ b/Geekbot.net/Commands/Rpg/Cookies.cs @@ -74,7 +74,7 @@ namespace Geekbot.net.Commands.Rpg [Command("give", RunMode = RunMode.Async)] [Summary("Give cookies to someone")] - public async Task GiveACookie([Summary("User")] IUser user, [Summary("amount")] int amount) + public async Task GiveACookie([Summary("User")] IUser user, [Summary("amount")] int amount = 1) { try { diff --git a/Geekbot.net/Commands/User/Ranking/Rank.cs b/Geekbot.net/Commands/User/Ranking/Rank.cs index 8a79fa6..fdc8011 100644 --- a/Geekbot.net/Commands/User/Ranking/Rank.cs +++ b/Geekbot.net/Commands/User/Ranking/Rank.cs @@ -10,6 +10,7 @@ using Geekbot.net.Lib.Converters; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Highscores; +using Geekbot.net.Lib.Localization; using Geekbot.net.Lib.UserRepository; namespace Geekbot.net.Commands.User.Ranking @@ -18,18 +19,20 @@ namespace Geekbot.net.Commands.User.Ranking { private readonly IEmojiConverter _emojiConverter; private readonly IHighscoreManager _highscoreManager; + private readonly ITranslationHandler _translationHandler; private readonly IErrorHandler _errorHandler; private readonly DatabaseContext _database; private readonly IUserRepository _userRepository; public Rank(DatabaseContext database, IErrorHandler errorHandler, IUserRepository userRepository, - IEmojiConverter emojiConverter, IHighscoreManager highscoreManager) + IEmojiConverter emojiConverter, IHighscoreManager highscoreManager, ITranslationHandler translationHandler) { _database = database; _errorHandler = errorHandler; _userRepository = userRepository; _emojiConverter = emojiConverter; _highscoreManager = highscoreManager; + _translationHandler = translationHandler; } [Command("rank", RunMode = RunMode.Async)] @@ -39,6 +42,7 @@ namespace Geekbot.net.Commands.User.Ranking { try { + var transContext = await _translationHandler.GetGuildContext(Context); HighscoreTypes type; try { @@ -46,14 +50,14 @@ namespace Geekbot.net.Commands.User.Ranking } catch { - await ReplyAsync("Valid types are '`messages`' '`karma`', '`rolls`' and '`cookies`'"); + await ReplyAsync(transContext.GetString("InvalidType")); return; } var replyBuilder = new StringBuilder(); if (amount > 20) { - replyBuilder.AppendLine(":warning: Limiting to 20\n"); + await ReplyAsync(transContext.GetString("LimitingTo20Warning")); amount = 20; } @@ -65,7 +69,7 @@ namespace Geekbot.net.Commands.User.Ranking } catch (HighscoreListEmptyException) { - await ReplyAsync($"No {type} found on this server"); + await ReplyAsync(transContext.GetString("NoTypeFoundForServer", type)); return; } @@ -80,8 +84,8 @@ namespace Geekbot.net.Commands.User.Ranking var failedToRetrieveUser = highscoreUsers.Any(e => string.IsNullOrEmpty(e.Key.Username)); - if (failedToRetrieveUser) replyBuilder.AppendLine(":warning: I couldn't find all usernames. Maybe they left the server?\n"); - replyBuilder.AppendLine($":bar_chart: **{type.ToString().CapitalizeFirst()} Highscore for {Context.Guild.Name}**"); + if (failedToRetrieveUser) replyBuilder.AppendLine(transContext.GetString("FailedToResolveAllUsernames")); + replyBuilder.AppendLine(transContext.GetString("HighscoresFor", type.ToString().CapitalizeFirst(), Context.Guild.Name)); var highscorePlace = 1; foreach (var user in highscoreUsers) { diff --git a/Geekbot.net/Lib/Localization/Translations.yml b/Geekbot.net/Lib/Localization/Translations.yml index 6b8d1cd..04835a2 100644 --- a/Geekbot.net/Lib/Localization/Translations.yml +++ b/Geekbot.net/Lib/Localization/Translations.yml @@ -156,4 +156,20 @@ quote: CHDE: "**#{0} glöscht**" NotFoundWithId: EN: "I couldn't find a quote with that ID :disappointed:" - CHDE: "Ich chan kei quote finde mit därri ID :disappointed:" \ No newline at end of file + CHDE: "Ich chan kei quote finde mit därri ID :disappointed:" +rank: + InvalidType: + EN: "Valid types are '`messages`' '`karma`', '`rolls`' and '`cookies`'" + CHDE: "Gültigi paramenter sind '`messages`' '`karma`', '`rolls`' und '`cookies`'" + LimitingTo20Warning: + EN: ":warning: Limiting to 20\n" + CHDE: ":warning: Limitiert uf 20\n" + NoTypeFoundForServer: + EN: "No {0} found on this server" + CHDE: "Kei {0} gfunde für dä server" + FailedToResolveAllUsernames: + EN: ":warning: I couldn't find all usernames. Maybe they left the server?\n" + CHDE: ":warning: Ich han nid alli benutzername gfunde. villiicht hend sie de server verlah?\n" + HighscoresFor: + EN: ":bar_chart: **{0} Highscore for {1}**" + CHDE: ":bar_chart: **{0} Highscore für {1}**" \ No newline at end of file From 3e3cbc257e1e60e6d0da731e39ddc9e383146055 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 12 May 2019 17:29:07 +0200 Subject: [PATCH 279/553] Fix bug where Enum.Parse would always pass if a number was given as argument in rank --- Geekbot.net/Commands/User/Ranking/Rank.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Geekbot.net/Commands/User/Ranking/Rank.cs b/Geekbot.net/Commands/User/Ranking/Rank.cs index fdc8011..0ad21d5 100644 --- a/Geekbot.net/Commands/User/Ranking/Rank.cs +++ b/Geekbot.net/Commands/User/Ranking/Rank.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -46,7 +46,8 @@ namespace Geekbot.net.Commands.User.Ranking HighscoreTypes type; try { - type = Enum.Parse(typeUnformated.ToLower()); + type = Enum.Parse(typeUnformated, true); + if (!Enum.IsDefined(typeof(HighscoreTypes), type)) throw new Exception(); } catch { From 4833ccd65ac268a33f7f7e1304428af48b3543dc Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 12 May 2019 17:29:52 +0200 Subject: [PATCH 280/553] Use SortedDictionary for Highscores instead of a simple Dictionary --- Geekbot.net/Commands/User/Ranking/Rank.cs | 4 ++-- Geekbot.net/Lib/Highscores/HighscoreManager.cs | 4 ++-- Geekbot.net/Lib/Highscores/IHighscoreManager.cs | 2 +- .../WebApi/Controllers/Highscores/HighscoreController.cs | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Geekbot.net/Commands/User/Ranking/Rank.cs b/Geekbot.net/Commands/User/Ranking/Rank.cs index 0ad21d5..1cd45e8 100644 --- a/Geekbot.net/Commands/User/Ranking/Rank.cs +++ b/Geekbot.net/Commands/User/Ranking/Rank.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -63,7 +63,7 @@ namespace Geekbot.net.Commands.User.Ranking } var guildId = Context.Guild.Id; - Dictionary highscoreUsers; + SortedDictionary highscoreUsers; try { highscoreUsers = _highscoreManager.GetHighscoresWithUserData(type, guildId, amount); diff --git a/Geekbot.net/Lib/Highscores/HighscoreManager.cs b/Geekbot.net/Lib/Highscores/HighscoreManager.cs index f3b3a18..02a0b69 100644 --- a/Geekbot.net/Lib/Highscores/HighscoreManager.cs +++ b/Geekbot.net/Lib/Highscores/HighscoreManager.cs @@ -20,7 +20,7 @@ namespace Geekbot.net.Lib.Highscores } - public Dictionary GetHighscoresWithUserData(HighscoreTypes type, ulong guildId, int amount) + public SortedDictionary GetHighscoresWithUserData(HighscoreTypes type, ulong guildId, int amount) { Dictionary list; switch (type) @@ -47,7 +47,7 @@ namespace Geekbot.net.Lib.Highscores throw new HighscoreListEmptyException($"No {type} found for guild {guildId}"); } - var highscoreUsers = new Dictionary(); + var highscoreUsers = new SortedDictionary(); foreach (var user in list) { try diff --git a/Geekbot.net/Lib/Highscores/IHighscoreManager.cs b/Geekbot.net/Lib/Highscores/IHighscoreManager.cs index a09b07e..aca3513 100644 --- a/Geekbot.net/Lib/Highscores/IHighscoreManager.cs +++ b/Geekbot.net/Lib/Highscores/IHighscoreManager.cs @@ -4,7 +4,7 @@ namespace Geekbot.net.Lib.Highscores { public interface IHighscoreManager { - Dictionary GetHighscoresWithUserData(HighscoreTypes type, ulong guildId, int amount); + SortedDictionary GetHighscoresWithUserData(HighscoreTypes type, ulong guildId, int amount); Dictionary GetMessageList(ulong guildId, int amount); Dictionary GetKarmaList(ulong guildId, int amount); Dictionary GetRollsList(ulong guildId, int amount); diff --git a/Geekbot.net/WebApi/Controllers/Highscores/HighscoreController.cs b/Geekbot.net/WebApi/Controllers/Highscores/HighscoreController.cs index 3cccb0e..2b03260 100644 --- a/Geekbot.net/WebApi/Controllers/Highscores/HighscoreController.cs +++ b/Geekbot.net/WebApi/Controllers/Highscores/HighscoreController.cs @@ -25,7 +25,7 @@ namespace Geekbot.net.WebApi.Controllers.Highscores return BadRequest(error); } - Dictionary list; + SortedDictionary list; try { list = _highscoreManager.GetHighscoresWithUserData(body.Type, body.GuildId, body.Amount); From aef50aa2dee1b68452c07ea54b4b02b9dfa135f1 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 12 May 2019 17:57:03 +0200 Subject: [PATCH 281/553] Revert "Use SortedDictionary for Highscores instead of a simple Dictionary" This reverts commit 4833ccd6 --- Geekbot.net/Commands/User/Ranking/Rank.cs | 4 ++-- Geekbot.net/Lib/Highscores/HighscoreManager.cs | 4 ++-- Geekbot.net/Lib/Highscores/IHighscoreManager.cs | 2 +- .../WebApi/Controllers/Highscores/HighscoreController.cs | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Geekbot.net/Commands/User/Ranking/Rank.cs b/Geekbot.net/Commands/User/Ranking/Rank.cs index 1cd45e8..0ad21d5 100644 --- a/Geekbot.net/Commands/User/Ranking/Rank.cs +++ b/Geekbot.net/Commands/User/Ranking/Rank.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -63,7 +63,7 @@ namespace Geekbot.net.Commands.User.Ranking } var guildId = Context.Guild.Id; - SortedDictionary highscoreUsers; + Dictionary highscoreUsers; try { highscoreUsers = _highscoreManager.GetHighscoresWithUserData(type, guildId, amount); diff --git a/Geekbot.net/Lib/Highscores/HighscoreManager.cs b/Geekbot.net/Lib/Highscores/HighscoreManager.cs index 02a0b69..f3b3a18 100644 --- a/Geekbot.net/Lib/Highscores/HighscoreManager.cs +++ b/Geekbot.net/Lib/Highscores/HighscoreManager.cs @@ -20,7 +20,7 @@ namespace Geekbot.net.Lib.Highscores } - public SortedDictionary GetHighscoresWithUserData(HighscoreTypes type, ulong guildId, int amount) + public Dictionary GetHighscoresWithUserData(HighscoreTypes type, ulong guildId, int amount) { Dictionary list; switch (type) @@ -47,7 +47,7 @@ namespace Geekbot.net.Lib.Highscores throw new HighscoreListEmptyException($"No {type} found for guild {guildId}"); } - var highscoreUsers = new SortedDictionary(); + var highscoreUsers = new Dictionary(); foreach (var user in list) { try diff --git a/Geekbot.net/Lib/Highscores/IHighscoreManager.cs b/Geekbot.net/Lib/Highscores/IHighscoreManager.cs index aca3513..a09b07e 100644 --- a/Geekbot.net/Lib/Highscores/IHighscoreManager.cs +++ b/Geekbot.net/Lib/Highscores/IHighscoreManager.cs @@ -4,7 +4,7 @@ namespace Geekbot.net.Lib.Highscores { public interface IHighscoreManager { - SortedDictionary GetHighscoresWithUserData(HighscoreTypes type, ulong guildId, int amount); + Dictionary GetHighscoresWithUserData(HighscoreTypes type, ulong guildId, int amount); Dictionary GetMessageList(ulong guildId, int amount); Dictionary GetKarmaList(ulong guildId, int amount); Dictionary GetRollsList(ulong guildId, int amount); diff --git a/Geekbot.net/WebApi/Controllers/Highscores/HighscoreController.cs b/Geekbot.net/WebApi/Controllers/Highscores/HighscoreController.cs index 2b03260..3cccb0e 100644 --- a/Geekbot.net/WebApi/Controllers/Highscores/HighscoreController.cs +++ b/Geekbot.net/WebApi/Controllers/Highscores/HighscoreController.cs @@ -25,7 +25,7 @@ namespace Geekbot.net.WebApi.Controllers.Highscores return BadRequest(error); } - SortedDictionary list; + Dictionary list; try { list = _highscoreManager.GetHighscoresWithUserData(body.Type, body.GuildId, body.Amount); From f5cd0ffcc8ba0fd5e6a3c2c6a873ae0032d69b03 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 12 May 2019 22:05:35 +0200 Subject: [PATCH 282/553] add unit test for making sure all translations keys exist --- Tests/Lib/Localization/Translations.test.cs | 44 +++++++++++++++++++++ Tests/Tests.csproj | 2 + 2 files changed, 46 insertions(+) create mode 100644 Tests/Lib/Localization/Translations.test.cs diff --git a/Tests/Lib/Localization/Translations.test.cs b/Tests/Lib/Localization/Translations.test.cs new file mode 100644 index 0000000..fc43091 --- /dev/null +++ b/Tests/Lib/Localization/Translations.test.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using FluentAssertions; +using Xunit; +using YamlDotNet.Serialization; + +namespace Tests.Lib.Localization +{ + public class Translations_test + { + [Fact] + public void TranslationsYamlIsValid() + { + // Read the file + var translationFile = File.ReadAllText(Path.GetFullPath("./../../../../Geekbot.net/Lib/Localization/Translations.yml")); + + // Deserialize + var input = new StringReader(translationFile); + var deserializer = new DeserializerBuilder().Build(); + var rawTranslations = deserializer.Deserialize>>>(input); + + // These languages must be supported + var supportedLanguages = new List + { + "EN", + "CHDE" + }; + + // Iterate every single key to make sure it's populated + foreach (var command in rawTranslations) + { + foreach (var str in command.Value) + { + str.Value.Select(e => e.Key).ToList().Should().BeEquivalentTo(supportedLanguages, str.Key); + foreach (var lang in str.Value) + { + lang.Value.Should().NotBeNullOrEmpty($"{command.Key} / {str.Key} / {lang.Key}"); + } + } + } + } + } +} \ No newline at end of file diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 771a9d4..1c07b9c 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -6,11 +6,13 @@ xUnit1026 + + From 5f3d7f8a737223faa9f1b1cc5c69adba75e8d32d Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 15 May 2019 21:41:29 +0200 Subject: [PATCH 283/553] Add bdcc (Benedict Cumberbatch Name Generator) --- .../BenedictCumberbatchNameGenerator.cs | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 Geekbot.net/Commands/Randomness/BenedictCumberbatchNameGenerator.cs diff --git a/Geekbot.net/Commands/Randomness/BenedictCumberbatchNameGenerator.cs b/Geekbot.net/Commands/Randomness/BenedictCumberbatchNameGenerator.cs new file mode 100644 index 0000000..699d550 --- /dev/null +++ b/Geekbot.net/Commands/Randomness/BenedictCumberbatchNameGenerator.cs @@ -0,0 +1,54 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Discord.Commands; +using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.RandomNumberGenerator; + +namespace Geekbot.net.Commands.Randomness +{ + public class BenedictCumberbatchNameGenerator : ModuleBase + { + private readonly IErrorHandler _errorHandler; + private readonly IRandomNumberGenerator _randomNumberGenerator; + + public BenedictCumberbatchNameGenerator(IErrorHandler errorHandler, IRandomNumberGenerator randomNumberGenerator) + { + _errorHandler = errorHandler; + _randomNumberGenerator = randomNumberGenerator; + } + + [Command("bdcc", RunMode = RunMode.Async)] + [Summary("Benedict Cumberbatch Name Generator")] + public async Task GetQuote() + { + var firstnameList = new List + { + "Bumblebee", "Bandersnatch", "Broccoli", "Rinkydink", "Bombadil", "Boilerdang", "Bandicoot", "Fragglerock", "Muffintop", "Congleton", "Blubberdick", "Buffalo", "Benadryl", + "Butterfree", "Burberry", "Whippersnatch", "Buttermilk", "Beezlebub", "Budapest", "Boilerdang", "Blubberwhale", "Bumberstump", "Bulbasaur", "Cogglesnatch", "Liverswort", "Bodybuild", + "Johnnycash", "Bendydick", "Burgerking", "Bonaparte", "Bunsenburner", "Billiardball", "Bukkake", "Baseballmitt", "Blubberbutt", "Baseballbat", "Rumblesack", "Barister", "Danglerack", + "Rinkydink", "Bombadil", "Honkytonk", "Billyray", "Bumbleshack", "Snorkeldink", "Beetlejuice", "Bedlington", "Bandicoot", "Boobytrap", "Blenderdick", "Bentobox", "Pallettown", + "Wimbledon", "Buttercup", "Blasphemy", "Syphilis", "Snorkeldink", "Brandenburg", "Barbituate", "Snozzlebert", "Tiddleywomp", "Bouillabaisse", "Wellington", "Benetton", "Bendandsnap", + "Timothy", "Brewery", "Bentobox", "Brandybuck", "Benjamin", "Buckminster", "Bourgeoisie", "Bakery", "Oscarbait", "Buckyball", "Bourgeoisie", "Burlington", "Buckingham", "Barnoldswick", + "Bumblesniff", "Butercup", "Bubblebath", "Fiddlestick", "Bulbasaur", "Bumblebee", "Bettyboop", "Botany", "Cadbury", "Brendadirk", "Buckingham", "Barnabus", "Barnacle", "Billybong", + "Botany", "Benddadick", "Benderchick" + }; + + var lastnameList = new List + { + "Coddleswort", "Crumplesack", "Curdlesnoot", "Calldispatch", "Humperdinck", "Rivendell", "Cuttlefish", "Lingerie", "Vegemite", "Ampersand", "Cumberbund", "Candycrush", "Clombyclomp", + "Cragglethatch", "Nottinghill", "Cabbagepatch", "Camouflage", "Creamsicle", "Curdlemilk", "Upperclass", "Frumblesnatch", "Crumplehorn", "Talisman", "Candlestick", "Chesterfield", + "Bumbersplat", "Scratchnsniff", "Snugglesnatch", "Charizard", "Carrotstick", "Cumbercooch", "Crackerjack", "Crucifix", "Cuckatoo", "Cockletit", "Collywog", "Capncrunch", "Covergirl", + "Cumbersnatch", "Countryside", "Coggleswort", "Splishnsplash", "Copperwire", "Animorph", "Curdledmilk", "Cheddarcheese", "Cottagecheese", "Crumplehorn", "Snickersbar", "Banglesnatch", + "Stinkyrash", "Cameltoe", "Chickenbroth", "Concubine", "Candygram", "Moldyspore", "Chuckecheese", "Cankersore", "Crimpysnitch", "Wafflesmack", "Chowderpants", "Toodlesnoot", + "Clavichord", "Cuckooclock", "Oxfordshire", "Cumbersome", "Chickenstrips", "Battleship", "Commonwealth", "Cunningsnatch", "Custardbath", "Kryptonite", "Curdlesnoot", "Cummerbund", + "Coochyrash", "Crackerdong", "Crackerdong", "Curdledong", "Crackersprout", "Crumplebutt", "Colonist", "Coochierash", "Anglerfish", "Cumbersniff", "Charmander", "Scratch-n-sniff", + "Cumberbitch", "Pumpkinpatch", "Cramplesnutch", "Lumberjack", "Bonaparte", "Cul-de-sac", "Cankersore", "Cucumbercatch", "Contradict" + }; + + var lastname = lastnameList[_randomNumberGenerator.Next(0, lastnameList.Count - 1)]; + var firstname = firstnameList[_randomNumberGenerator.Next(0, firstnameList.Count - 1)]; + + await ReplyAsync($"{firstname} {lastname}"); + } + } +} \ No newline at end of file From 761ed7302c0e36924c902d6ebc1db7d1e710997e Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 15 May 2019 22:18:02 +0200 Subject: [PATCH 284/553] Wrap bdcc in a try catch block --- .../BenedictCumberbatchNameGenerator.cs | 65 ++++++++++++------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/Geekbot.net/Commands/Randomness/BenedictCumberbatchNameGenerator.cs b/Geekbot.net/Commands/Randomness/BenedictCumberbatchNameGenerator.cs index 699d550..eee5763 100644 --- a/Geekbot.net/Commands/Randomness/BenedictCumberbatchNameGenerator.cs +++ b/Geekbot.net/Commands/Randomness/BenedictCumberbatchNameGenerator.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Threading.Tasks; using Discord.Commands; @@ -21,34 +22,48 @@ namespace Geekbot.net.Commands.Randomness [Summary("Benedict Cumberbatch Name Generator")] public async Task GetQuote() { - var firstnameList = new List + try { - "Bumblebee", "Bandersnatch", "Broccoli", "Rinkydink", "Bombadil", "Boilerdang", "Bandicoot", "Fragglerock", "Muffintop", "Congleton", "Blubberdick", "Buffalo", "Benadryl", - "Butterfree", "Burberry", "Whippersnatch", "Buttermilk", "Beezlebub", "Budapest", "Boilerdang", "Blubberwhale", "Bumberstump", "Bulbasaur", "Cogglesnatch", "Liverswort", "Bodybuild", - "Johnnycash", "Bendydick", "Burgerking", "Bonaparte", "Bunsenburner", "Billiardball", "Bukkake", "Baseballmitt", "Blubberbutt", "Baseballbat", "Rumblesack", "Barister", "Danglerack", - "Rinkydink", "Bombadil", "Honkytonk", "Billyray", "Bumbleshack", "Snorkeldink", "Beetlejuice", "Bedlington", "Bandicoot", "Boobytrap", "Blenderdick", "Bentobox", "Pallettown", - "Wimbledon", "Buttercup", "Blasphemy", "Syphilis", "Snorkeldink", "Brandenburg", "Barbituate", "Snozzlebert", "Tiddleywomp", "Bouillabaisse", "Wellington", "Benetton", "Bendandsnap", - "Timothy", "Brewery", "Bentobox", "Brandybuck", "Benjamin", "Buckminster", "Bourgeoisie", "Bakery", "Oscarbait", "Buckyball", "Bourgeoisie", "Burlington", "Buckingham", "Barnoldswick", - "Bumblesniff", "Butercup", "Bubblebath", "Fiddlestick", "Bulbasaur", "Bumblebee", "Bettyboop", "Botany", "Cadbury", "Brendadirk", "Buckingham", "Barnabus", "Barnacle", "Billybong", - "Botany", "Benddadick", "Benderchick" - }; + var firstnameList = new List + { + "Bumblebee", "Bandersnatch", "Broccoli", "Rinkydink", "Bombadil", "Boilerdang", "Bandicoot", "Fragglerock", "Muffintop", "Congleton", "Blubberdick", "Buffalo", "Benadryl", + "Butterfree", "Burberry", "Whippersnatch", "Buttermilk", "Beezlebub", "Budapest", "Boilerdang", "Blubberwhale", "Bumberstump", "Bulbasaur", "Cogglesnatch", "Liverswort", + "Bodybuild", + "Johnnycash", "Bendydick", "Burgerking", "Bonaparte", "Bunsenburner", "Billiardball", "Bukkake", "Baseballmitt", "Blubberbutt", "Baseballbat", "Rumblesack", "Barister", + "Danglerack", + "Rinkydink", "Bombadil", "Honkytonk", "Billyray", "Bumbleshack", "Snorkeldink", "Beetlejuice", "Bedlington", "Bandicoot", "Boobytrap", "Blenderdick", "Bentobox", "Pallettown", + "Wimbledon", "Buttercup", "Blasphemy", "Syphilis", "Snorkeldink", "Brandenburg", "Barbituate", "Snozzlebert", "Tiddleywomp", "Bouillabaisse", "Wellington", "Benetton", + "Bendandsnap", + "Timothy", "Brewery", "Bentobox", "Brandybuck", "Benjamin", "Buckminster", "Bourgeoisie", "Bakery", "Oscarbait", "Buckyball", "Bourgeoisie", "Burlington", "Buckingham", + "Barnoldswick", + "Bumblesniff", "Butercup", "Bubblebath", "Fiddlestick", "Bulbasaur", "Bumblebee", "Bettyboop", "Botany", "Cadbury", "Brendadirk", "Buckingham", "Barnabus", "Barnacle", "Billybong", + "Botany", "Benddadick", "Benderchick" + }; - var lastnameList = new List + var lastnameList = new List + { + "Coddleswort", "Crumplesack", "Curdlesnoot", "Calldispatch", "Humperdinck", "Rivendell", "Cuttlefish", "Lingerie", "Vegemite", "Ampersand", "Cumberbund", "Candycrush", + "Clombyclomp", + "Cragglethatch", "Nottinghill", "Cabbagepatch", "Camouflage", "Creamsicle", "Curdlemilk", "Upperclass", "Frumblesnatch", "Crumplehorn", "Talisman", "Candlestick", "Chesterfield", + "Bumbersplat", "Scratchnsniff", "Snugglesnatch", "Charizard", "Carrotstick", "Cumbercooch", "Crackerjack", "Crucifix", "Cuckatoo", "Cockletit", "Collywog", "Capncrunch", + "Covergirl", + "Cumbersnatch", "Countryside", "Coggleswort", "Splishnsplash", "Copperwire", "Animorph", "Curdledmilk", "Cheddarcheese", "Cottagecheese", "Crumplehorn", "Snickersbar", + "Banglesnatch", + "Stinkyrash", "Cameltoe", "Chickenbroth", "Concubine", "Candygram", "Moldyspore", "Chuckecheese", "Cankersore", "Crimpysnitch", "Wafflesmack", "Chowderpants", "Toodlesnoot", + "Clavichord", "Cuckooclock", "Oxfordshire", "Cumbersome", "Chickenstrips", "Battleship", "Commonwealth", "Cunningsnatch", "Custardbath", "Kryptonite", "Curdlesnoot", "Cummerbund", + "Coochyrash", "Crackerdong", "Crackerdong", "Curdledong", "Crackersprout", "Crumplebutt", "Colonist", "Coochierash", "Anglerfish", "Cumbersniff", "Charmander", "Scratch-n-sniff", + "Cumberbitch", "Pumpkinpatch", "Cramplesnutch", "Lumberjack", "Bonaparte", "Cul-de-sac", "Cankersore", "Cucumbercatch", "Contradict" + }; + + var lastname = lastnameList[_randomNumberGenerator.Next(0, lastnameList.Count - 1)]; + var firstname = firstnameList[_randomNumberGenerator.Next(0, firstnameList.Count - 1)]; + + await ReplyAsync($"{firstname} {lastname}"); + } + catch (Exception e) { - "Coddleswort", "Crumplesack", "Curdlesnoot", "Calldispatch", "Humperdinck", "Rivendell", "Cuttlefish", "Lingerie", "Vegemite", "Ampersand", "Cumberbund", "Candycrush", "Clombyclomp", - "Cragglethatch", "Nottinghill", "Cabbagepatch", "Camouflage", "Creamsicle", "Curdlemilk", "Upperclass", "Frumblesnatch", "Crumplehorn", "Talisman", "Candlestick", "Chesterfield", - "Bumbersplat", "Scratchnsniff", "Snugglesnatch", "Charizard", "Carrotstick", "Cumbercooch", "Crackerjack", "Crucifix", "Cuckatoo", "Cockletit", "Collywog", "Capncrunch", "Covergirl", - "Cumbersnatch", "Countryside", "Coggleswort", "Splishnsplash", "Copperwire", "Animorph", "Curdledmilk", "Cheddarcheese", "Cottagecheese", "Crumplehorn", "Snickersbar", "Banglesnatch", - "Stinkyrash", "Cameltoe", "Chickenbroth", "Concubine", "Candygram", "Moldyspore", "Chuckecheese", "Cankersore", "Crimpysnitch", "Wafflesmack", "Chowderpants", "Toodlesnoot", - "Clavichord", "Cuckooclock", "Oxfordshire", "Cumbersome", "Chickenstrips", "Battleship", "Commonwealth", "Cunningsnatch", "Custardbath", "Kryptonite", "Curdlesnoot", "Cummerbund", - "Coochyrash", "Crackerdong", "Crackerdong", "Curdledong", "Crackersprout", "Crumplebutt", "Colonist", "Coochierash", "Anglerfish", "Cumbersniff", "Charmander", "Scratch-n-sniff", - "Cumberbitch", "Pumpkinpatch", "Cramplesnutch", "Lumberjack", "Bonaparte", "Cul-de-sac", "Cankersore", "Cucumbercatch", "Contradict" - }; - - var lastname = lastnameList[_randomNumberGenerator.Next(0, lastnameList.Count - 1)]; - var firstname = firstnameList[_randomNumberGenerator.Next(0, firstnameList.Count - 1)]; - - await ReplyAsync($"{firstname} {lastname}"); + await _errorHandler.HandleCommandException(e, Context); + } } } } \ No newline at end of file From cf5cb2ea869138ca3fee699c904a579f93a41076 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 16 May 2019 21:54:13 +0200 Subject: [PATCH 285/553] Reformat bdcc --- .../BenedictCumberbatchNameGenerator.cs | 33 ++++++++----------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/Geekbot.net/Commands/Randomness/BenedictCumberbatchNameGenerator.cs b/Geekbot.net/Commands/Randomness/BenedictCumberbatchNameGenerator.cs index eee5763..501f891 100644 --- a/Geekbot.net/Commands/Randomness/BenedictCumberbatchNameGenerator.cs +++ b/Geekbot.net/Commands/Randomness/BenedictCumberbatchNameGenerator.cs @@ -28,31 +28,24 @@ namespace Geekbot.net.Commands.Randomness { "Bumblebee", "Bandersnatch", "Broccoli", "Rinkydink", "Bombadil", "Boilerdang", "Bandicoot", "Fragglerock", "Muffintop", "Congleton", "Blubberdick", "Buffalo", "Benadryl", "Butterfree", "Burberry", "Whippersnatch", "Buttermilk", "Beezlebub", "Budapest", "Boilerdang", "Blubberwhale", "Bumberstump", "Bulbasaur", "Cogglesnatch", "Liverswort", - "Bodybuild", - "Johnnycash", "Bendydick", "Burgerking", "Bonaparte", "Bunsenburner", "Billiardball", "Bukkake", "Baseballmitt", "Blubberbutt", "Baseballbat", "Rumblesack", "Barister", - "Danglerack", - "Rinkydink", "Bombadil", "Honkytonk", "Billyray", "Bumbleshack", "Snorkeldink", "Beetlejuice", "Bedlington", "Bandicoot", "Boobytrap", "Blenderdick", "Bentobox", "Pallettown", - "Wimbledon", "Buttercup", "Blasphemy", "Syphilis", "Snorkeldink", "Brandenburg", "Barbituate", "Snozzlebert", "Tiddleywomp", "Bouillabaisse", "Wellington", "Benetton", - "Bendandsnap", - "Timothy", "Brewery", "Bentobox", "Brandybuck", "Benjamin", "Buckminster", "Bourgeoisie", "Bakery", "Oscarbait", "Buckyball", "Bourgeoisie", "Burlington", "Buckingham", - "Barnoldswick", - "Bumblesniff", "Butercup", "Bubblebath", "Fiddlestick", "Bulbasaur", "Bumblebee", "Bettyboop", "Botany", "Cadbury", "Brendadirk", "Buckingham", "Barnabus", "Barnacle", "Billybong", - "Botany", "Benddadick", "Benderchick" + "Bodybuild", "Johnnycash", "Bendydick", "Burgerking", "Bonaparte", "Bunsenburner", "Billiardball", "Bukkake", "Baseballmitt", "Blubberbutt", "Baseballbat", "Rumblesack", + "Barister", "Danglerack", "Rinkydink", "Bombadil", "Honkytonk", "Billyray", "Bumbleshack", "Snorkeldink", "Beetlejuice", "Bedlington", "Bandicoot", "Boobytrap", "Blenderdick", + "Bentobox", "Pallettown", "Wimbledon", "Buttercup", "Blasphemy", "Syphilis", "Snorkeldink", "Brandenburg", "Barbituate", "Snozzlebert", "Tiddleywomp", "Bouillabaisse", + "Wellington", "Benetton", "Bendandsnap", "Timothy", "Brewery", "Bentobox", "Brandybuck", "Benjamin", "Buckminster", "Bourgeoisie", "Bakery", "Oscarbait", "Buckyball", + "Bourgeoisie", "Burlington", "Buckingham", "Barnoldswick", "Bumblesniff", "Butercup", "Bubblebath", "Fiddlestick", "Bulbasaur", "Bumblebee", "Bettyboop", "Botany", "Cadbury", + "Brendadirk", "Buckingham", "Barnabus", "Barnacle", "Billybong", "Botany", "Benddadick", "Benderchick" }; var lastnameList = new List { "Coddleswort", "Crumplesack", "Curdlesnoot", "Calldispatch", "Humperdinck", "Rivendell", "Cuttlefish", "Lingerie", "Vegemite", "Ampersand", "Cumberbund", "Candycrush", - "Clombyclomp", - "Cragglethatch", "Nottinghill", "Cabbagepatch", "Camouflage", "Creamsicle", "Curdlemilk", "Upperclass", "Frumblesnatch", "Crumplehorn", "Talisman", "Candlestick", "Chesterfield", - "Bumbersplat", "Scratchnsniff", "Snugglesnatch", "Charizard", "Carrotstick", "Cumbercooch", "Crackerjack", "Crucifix", "Cuckatoo", "Cockletit", "Collywog", "Capncrunch", - "Covergirl", - "Cumbersnatch", "Countryside", "Coggleswort", "Splishnsplash", "Copperwire", "Animorph", "Curdledmilk", "Cheddarcheese", "Cottagecheese", "Crumplehorn", "Snickersbar", - "Banglesnatch", - "Stinkyrash", "Cameltoe", "Chickenbroth", "Concubine", "Candygram", "Moldyspore", "Chuckecheese", "Cankersore", "Crimpysnitch", "Wafflesmack", "Chowderpants", "Toodlesnoot", - "Clavichord", "Cuckooclock", "Oxfordshire", "Cumbersome", "Chickenstrips", "Battleship", "Commonwealth", "Cunningsnatch", "Custardbath", "Kryptonite", "Curdlesnoot", "Cummerbund", - "Coochyrash", "Crackerdong", "Crackerdong", "Curdledong", "Crackersprout", "Crumplebutt", "Colonist", "Coochierash", "Anglerfish", "Cumbersniff", "Charmander", "Scratch-n-sniff", - "Cumberbitch", "Pumpkinpatch", "Cramplesnutch", "Lumberjack", "Bonaparte", "Cul-de-sac", "Cankersore", "Cucumbercatch", "Contradict" + "Clombyclomp", "Cragglethatch", "Nottinghill", "Cabbagepatch", "Camouflage", "Creamsicle", "Curdlemilk", "Upperclass", "Frumblesnatch", "Crumplehorn", "Talisman", "Candlestick", + "Chesterfield", "Bumbersplat", "Scratchnsniff", "Snugglesnatch", "Charizard", "Carrotstick", "Cumbercooch", "Crackerjack", "Crucifix", "Cuckatoo", "Cockletit", "Collywog", + "Capncrunch", "Covergirl", "Cumbersnatch", "Countryside", "Coggleswort", "Splishnsplash", "Copperwire", "Animorph", "Curdledmilk", "Cheddarcheese", "Cottagecheese", "Crumplehorn", + "Snickersbar", "Banglesnatch", "Stinkyrash", "Cameltoe", "Chickenbroth", "Concubine", "Candygram", "Moldyspore", "Chuckecheese", "Cankersore", "Crimpysnitch", "Wafflesmack", + "Chowderpants", "Toodlesnoot", "Clavichord", "Cuckooclock", "Oxfordshire", "Cumbersome", "Chickenstrips", "Battleship", "Commonwealth", "Cunningsnatch", "Custardbath", + "Kryptonite", "Curdlesnoot", "Cummerbund", "Coochyrash", "Crackerdong", "Crackerdong", "Curdledong", "Crackersprout", "Crumplebutt", "Colonist", "Coochierash", "Anglerfish", + "Cumbersniff", "Charmander", "Scratch-n-sniff", "Cumberbitch", "Pumpkinpatch", "Cramplesnutch", "Lumberjack", "Bonaparte", "Cul-de-sac", "Cankersore", "Cucumbercatch", "Contradict" }; var lastname = lastnameList[_randomNumberGenerator.Next(0, lastnameList.Count - 1)]; From 0e1084ccad2d6b4de3c4d06e40139d405944786f Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 16 May 2019 22:00:28 +0200 Subject: [PATCH 286/553] Remove Database migration scripts --- .../Commands/Admin/Owner/MigrationMethods.cs | 8 - Geekbot.net/Commands/Admin/Owner/Owner.cs | 57 +-- Geekbot.net/Database/MessageMigration.cs | 73 ---- Geekbot.net/Database/RedisMigration.cs | 396 ------------------ 4 files changed, 3 insertions(+), 531 deletions(-) delete mode 100644 Geekbot.net/Commands/Admin/Owner/MigrationMethods.cs delete mode 100644 Geekbot.net/Database/MessageMigration.cs delete mode 100644 Geekbot.net/Database/RedisMigration.cs diff --git a/Geekbot.net/Commands/Admin/Owner/MigrationMethods.cs b/Geekbot.net/Commands/Admin/Owner/MigrationMethods.cs deleted file mode 100644 index 6f50257..0000000 --- a/Geekbot.net/Commands/Admin/Owner/MigrationMethods.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Geekbot.net.Commands.Admin.Owner -{ - public enum MigrationMethods - { - redis, - messages - } -} \ No newline at end of file diff --git a/Geekbot.net/Commands/Admin/Owner/Owner.cs b/Geekbot.net/Commands/Admin/Owner/Owner.cs index b02ee47..6263e46 100644 --- a/Geekbot.net/Commands/Admin/Owner/Owner.cs +++ b/Geekbot.net/Commands/Admin/Owner/Owner.cs @@ -1,9 +1,8 @@ -using System; +using System; using System.Threading.Tasks; +using Discord; using Discord.Commands; using Discord.WebSocket; -using Geekbot.net.Database; -using Geekbot.net.Lib.AlmostRedis; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.GlobalSettings; using Geekbot.net.Lib.Logger; @@ -17,69 +16,19 @@ namespace Geekbot.net.Commands.Admin.Owner { private readonly DiscordSocketClient _client; private readonly IErrorHandler _errorHandler; - private readonly DatabaseContext _database; private readonly IGlobalSettings _globalSettings; private readonly IGeekbotLogger _logger; - private readonly IAlmostRedis _redis; private readonly IUserRepository _userRepository; - public Owner(IAlmostRedis redis, DiscordSocketClient client, IGeekbotLogger logger, IUserRepository userRepositry, IErrorHandler errorHandler, DatabaseContext database, IGlobalSettings globalSettings) + public Owner(DiscordSocketClient client, IGeekbotLogger logger, IUserRepository userRepositry, IErrorHandler errorHandler, IGlobalSettings globalSettings) { - _redis = redis; _client = client; _logger = logger; _userRepository = userRepositry; _errorHandler = errorHandler; - _database = database; _globalSettings = globalSettings; } - [Command("migrate", RunMode = RunMode.Async)] - public async Task Migrate(MigrationMethods method, string force = "") - { - try - { - switch (method) - { - case MigrationMethods.redis: - var status = _globalSettings.GetKey("MigrationStatus"); - if (status.Equals("Running")) - { - await ReplyAsync("Migration already running"); - return; - } - if (status.Equals("Done") && !force.Equals("force")) - { - await ReplyAsync("Migration already ran, write `!owner migrate redis force` to run again"); - return; - } - - await ReplyAsync("starting migration"); - await _globalSettings.SetKey("MigrationStatus", "Running"); - var redisMigration = new RedisMigration(_database, _redis, _logger, _client); - await redisMigration.Migrate(); - await _globalSettings.SetKey("MigrationStatus", "Done"); - break; - - case MigrationMethods.messages: - await ReplyAsync("Migrating Messages to postgres..."); - var messageMigration = new MessageMigration(_database, _redis, _logger); - await messageMigration.Migrate(); - break; - - default: - await ReplyAsync("No Migration Method specified..."); - break; - } - } - catch (Exception e) - { - await _errorHandler.HandleCommandException(e, Context); - } - - await ReplyAsync("done"); - } - [Command("youtubekey", RunMode = RunMode.Async)] [Summary("Set the youtube api key")] public async Task SetYoutubeKey([Summary("API Key")] string key) diff --git a/Geekbot.net/Database/MessageMigration.cs b/Geekbot.net/Database/MessageMigration.cs deleted file mode 100644 index ed07072..0000000 --- a/Geekbot.net/Database/MessageMigration.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System; -using System.Linq; -using System.Threading.Tasks; -using Geekbot.net.Database.Models; -using Geekbot.net.Lib.AlmostRedis; -using Geekbot.net.Lib.Extensions; -using Geekbot.net.Lib.Logger; - -namespace Geekbot.net.Database -{ - public class MessageMigration - { - private readonly DatabaseContext _database; - private readonly IAlmostRedis _redis; - private readonly IGeekbotLogger _logger; - - public MessageMigration(DatabaseContext database, IAlmostRedis redis, IGeekbotLogger logger) - { - _database = database; - _redis = redis; - _logger = logger; - } - - public async Task Migrate() - { - _logger.Warning(LogSource.Migration, "Starting message migration"); - try - { - var messageKeys = _redis.GetAllKeys().Where(e => e.ToString().EndsWith("Messages")); - foreach (var keyName in messageKeys) - { - try - { - var guildId = ulong.Parse(keyName.ToString().Split(':').FirstOrDefault()); - var guildUsers = _redis.Db.HashGetAll(keyName); - foreach (var user in guildUsers) - { - try - { - var userId = ulong.Parse(user.Name); - if (userId != 0) - { - var userMessages = int.Parse(user.Value); - _database.Messages.Add(new MessagesModel - { - UserId = userId.AsLong(), - GuildId = guildId.AsLong(), - MessageCount = userMessages - }); - } - } - catch (Exception e) - { - _logger.Error(LogSource.Migration, $"Failed to add record for a user in {guildId}", e); - } - } - - await _database.SaveChangesAsync(); - } - catch (Exception e) - { - _logger.Error(LogSource.Migration, "Failed to determinate guild", e); - } - } - _logger.Warning(LogSource.Migration, "Successfully finished message migration"); - } - catch (Exception e) - { - _logger.Error(LogSource.Migration, "Message migration failed", e); - } - } - } -} \ No newline at end of file diff --git a/Geekbot.net/Database/RedisMigration.cs b/Geekbot.net/Database/RedisMigration.cs deleted file mode 100644 index 74d97d2..0000000 --- a/Geekbot.net/Database/RedisMigration.cs +++ /dev/null @@ -1,396 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Discord; -using Discord.WebSocket; -using Geekbot.net.Commands.Utils.Quote; -using Geekbot.net.Database.Models; -using Geekbot.net.Lib.AlmostRedis; -using Geekbot.net.Lib.Extensions; -using Geekbot.net.Lib.Logger; -using Newtonsoft.Json; - -namespace Geekbot.net.Database -{ - public class RedisMigration - { - private readonly DatabaseContext _database; - private readonly IAlmostRedis _redis; - private readonly IGeekbotLogger _logger; - private readonly DiscordSocketClient _client; - - public RedisMigration(DatabaseContext database, IAlmostRedis redis, IGeekbotLogger logger, DiscordSocketClient client) - { - _database = database; - _redis = redis; - _logger = logger; - _client = client; - } - - public async Task Migrate() - { - _logger.Information(LogSource.Migration, "Starting migration process"); - - var keys = _redis.GetAllKeys().Where(e => e.ToString().EndsWith("Messages")); - var allGuilds = new List(); - - foreach (var key in keys) - { - try - { - var g = _client.GetGuild(ulong.Parse(key.ToString().Split(':').First())); - Console.WriteLine(g.Name); - allGuilds.Add(g); - } - catch (Exception) - { - // ignore - } - } - - _logger.Information(LogSource.Migration, $"Found {allGuilds.Count} guilds in redis"); - - var guilds = allGuilds.FindAll(e => e.MemberCount < 10000); - - foreach (var guild in guilds) - { - _logger.Information(LogSource.Migration, $"Start Migration for {guild.Name}"); - #region Quotes - /** - * Quotes - */ - try - { - var data = _redis.Db.SetScan($"{guild.Id}:Quotes"); - foreach (var q in data) - { - try - { - var qd = JsonConvert.DeserializeObject(q); - var quote = CreateQuoteObject(guild.Id, qd); - _database.Quotes.Add(quote); - await _database.SaveChangesAsync(); - } - catch (Exception e) - { - _logger.Error(LogSource.Migration, $"quote failed: {q}", e); - } - } - } - catch (Exception e) - { - _logger.Error(LogSource.Migration, "quote migration failed", e); - } - #endregion - - #region Karma - /** - * Karma - */ - try - { - var data = _redis.Db.HashGetAll($"{guild.Id}:Karma"); - foreach (var q in data) - { - try - { - var user = new KarmaModel() - { - GuildId = guild.Id.AsLong(), - UserId = ulong.Parse(q.Name).AsLong(), - Karma = int.Parse(q.Value), - TimeOut = DateTimeOffset.MinValue - }; - _database.Karma.Add(user); - await _database.SaveChangesAsync(); - } - catch (Exception e) - { - _logger.Error(LogSource.Migration, $"karma failed for: {q.Name}", e); - } - } - } - catch (Exception e) - { - _logger.Error(LogSource.Migration, "karma migration failed", e); - } - #endregion - - #region Rolls - /** - * Rolls - */ - try - { - var data = _redis.Db.HashGetAll($"{guild.Id}:Rolls"); - foreach (var q in data) - { - try - { - var user = new RollsModel() - { - GuildId = guild.Id.AsLong(), - UserId = ulong.Parse(q.Name).AsLong(), - Rolls = int.Parse(q.Value) - }; - _database.Rolls.Add(user); - await _database.SaveChangesAsync(); - } - catch (Exception e) - { - _logger.Error(LogSource.Migration, $"Rolls failed for: {q.Name}", e); - } - } - } - catch (Exception e) - { - _logger.Error(LogSource.Migration, "rolls migration failed", e); - } - #endregion - - #region Slaps - /** - * Slaps - */ - try - { - var given = _redis.Db.HashGetAll($"{guild.Id}:SlapsGiven"); - var gotten = _redis.Db.HashGetAll($"{guild.Id}:SlapsGiven"); - foreach (var q in given) - { - try - { - var user = new SlapsModel() - { - GuildId = guild.Id.AsLong(), - UserId = ulong.Parse(q.Name).AsLong(), - Given = int.Parse(q.Value), - Recieved= int.Parse(gotten[long.Parse(q.Name)].Value) - }; - _database.Slaps.Add(user); - await _database.SaveChangesAsync(); - } - catch (Exception e) - { - _logger.Error(LogSource.Migration, $"Slaps failed for: {q.Name}", e); - } - } - } - catch (Exception e) - { - _logger.Error(LogSource.Migration, "Slaps migration failed", e); - } - #endregion - - #region Messages - /** - * Messages - */ - /*try - { - var data = _redis.Db.HashGetAll($"{guild.Id}:Messages"); - foreach (var q in data) - { - try - { - var user = new MessagesModel() - { - GuildId = guild.Id.AsLong(), - UserId = ulong.Parse(q.Name).AsLong(), - MessageCount= int.Parse(q.Value) - }; - _database.Messages.Add(user); - await _database.SaveChangesAsync(); - } - catch (Exception e) - { - _logger.Error(LogSource.Migration, $"Messages failed for: {q.Name}", e); - } - } - } - catch (Exception e) - { - _logger.Error(LogSource.Migration, "Messages migration failed", e); - }*/ - #endregion - - #region Ships - /** - * Ships - */ - try - { - var data = _redis.Db.HashGetAll($"{guild.Id}:Ships"); - var done = new List(); - foreach (var q in data) - { - try - { - if (done.Contains(q.Name)) continue; - var split = q.Name.ToString().Split('-'); - var user = new ShipsModel() - { - FirstUserId = ulong.Parse(split[0]).AsLong(), - SecondUserId = ulong.Parse(split[1]).AsLong(), - Strength = int.Parse(q.Value) - }; - _database.Ships.Add(user); - await _database.SaveChangesAsync(); - done.Add(q.Name); - } - catch (Exception e) - { - _logger.Error(LogSource.Migration, $"Ships failed for: {q.Name}", e); - } - } - } - catch (Exception e) - { - _logger.Error(LogSource.Migration, "Ships migration failed", e); - } - #endregion - - #region GuildSettings - /** - * Users - */ - try - { - var data = _redis.Db.HashGetAll($"{guild.Id}:Settings"); - var settings = new GuildSettingsModel() - { - GuildId = guild.Id.AsLong(), - Hui = true - }; - foreach (var setting in data) - { - try - { - switch (setting.Name) - { - case "ShowLeave": - settings.ShowLeave = setting.Value.ToString() == "1"; - break; - case "ShowDelete": - settings.ShowDelete = setting.Value.ToString() == "1"; - break; - case "WikiLang": - settings.WikiLang = setting.Value.ToString(); - break; - case "Language": - settings.Language = setting.Value.ToString(); - break; - case "WelcomeMsg": - settings.WelcomeMessage = setting.Value.ToString(); - break; - case "ping": - settings.Ping = bool.Parse(setting.Value.ToString()); - break; - case "ModChannel": - settings.ModChannel = long.Parse(setting.Value); - break; - } - } - catch (Exception e) - { - _logger.Error(LogSource.Migration, $"Setting failed: {setting.Name} - {guild.Id}", e); - } - } - } - catch (Exception e) - { - _logger.Error(LogSource.Migration, "Settings migration failed", e); - } - - #endregion - - #region Users - /** - * Users - */ - try - { - var data = guild.Users.ToList().FindAll(e => !e.IsBot); - foreach (var user in data) - { - try - { - if (user.Username == null) - { - await Task.Delay(100); - if (user.Username == null) break; - } - - var namesSerialized = _redis.Db.HashGet($"User:{user.Id}", "UsedNames").ToString(); - var names = namesSerialized != null - ? Utf8Json.JsonSerializer.Deserialize(namesSerialized) - : new string[] {user.Username}; - _database.Users.AddIfNotExists(new UserModel() - { - UserId = user.Id.AsLong(), - Username = user.Username, - Discriminator = user.Discriminator, - AvatarUrl = user.GetAvatarUrl(ImageFormat.Auto, 1024), - IsBot = user.IsBot, - Joined = user.CreatedAt, - UsedNames = names.Select(name => new UserUsedNamesModel() {Name = name, FirstSeen = DateTimeOffset.Now}).ToList() - }, model => model.UserId.Equals(user.Id.AsLong())); - await _database.SaveChangesAsync(); - } - catch (Exception e) - { - _logger.Error(LogSource.Migration, $"User failed: {user.Username}", e); - } - } - } - catch (Exception e) - { - _logger.Error(LogSource.Migration, "User migration failed", e); - } - #endregion - - #region Guilds - - try - { - _database.Guilds.Add(new GuildsModel - { - CreatedAt = guild.CreatedAt, - GuildId = guild.Id.AsLong(), - IconUrl = guild?.IconUrl, - Name = guild.Name, - Owner = guild.Owner.Id.AsLong() - }); - await _database.SaveChangesAsync(); - } - catch (Exception e) - { - _logger.Error(LogSource.Migration, $"Guild migration failed: {guild.Name}", e); - } - - #endregion - _logger.Information(LogSource.Migration, $"Finished Migration for {guild.Name}"); - await Task.Delay(1000); - } - _logger.Information(LogSource.Migration, "Finished migration process"); - } - - private QuoteModel CreateQuoteObject(ulong guild, QuoteObjectDto quote) - { - var last = _database.Quotes.Where(e => e.GuildId.Equals(guild.AsLong())) - .OrderByDescending(e => e.InternalId).FirstOrDefault(); - int internalId = 1; - if (last != null) internalId = last.InternalId + 1; - return new QuoteModel() - { - InternalId = internalId, - GuildId = guild.AsLong(), - UserId = quote.UserId.AsLong(), - Time = quote.Time, - Quote = quote.Quote, - Image = quote.Image - }; - } - } -} \ No newline at end of file From 03343918b0fe392baad639dbae30d78e68eee8df Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 16 May 2019 22:01:35 +0200 Subject: [PATCH 287/553] Add a refresh user command to the owner commands --- Geekbot.net/Commands/Admin/Owner/Owner.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Geekbot.net/Commands/Admin/Owner/Owner.cs b/Geekbot.net/Commands/Admin/Owner/Owner.cs index 6263e46..661e5a3 100644 --- a/Geekbot.net/Commands/Admin/Owner/Owner.cs +++ b/Geekbot.net/Commands/Admin/Owner/Owner.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using Discord; using Discord.Commands; @@ -78,6 +78,21 @@ namespace Geekbot.net.Commands.Admin.Owner } } + [Command("refreshuser", RunMode = RunMode.Async)] + [Summary("Refresh a user in the user cache")] + public async Task PopUserRepoCommand([Summary("@user")] IUser user) + { + try + { + await _userRepository.Update(user as SocketUser); + await ReplyAsync($"Refreshed: {user.Username}#{user.Discriminator}"); + } + catch (Exception e) + { + await _errorHandler.HandleCommandException(e, Context); + } + } + [Command("error", RunMode = RunMode.Async)] [Summary("Throw an error un purpose")] public async Task PurposefulError() From e4fd828a132ca0b9b195e6144eab738480207196 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 16 May 2019 22:10:56 +0200 Subject: [PATCH 288/553] Make the command documentation slightly more consistent across most all commands --- Geekbot.net/Commands/Admin/Admin.cs | 2 +- Geekbot.net/Commands/Admin/Mod.cs | 2 +- Geekbot.net/Commands/Admin/Owner/Owner.cs | 4 ++-- Geekbot.net/Commands/Admin/Role.cs | 6 +++--- Geekbot.net/Commands/Games/Pokedex.cs | 2 +- Geekbot.net/Commands/Games/Roll.cs | 2 +- Geekbot.net/Commands/Integrations/Google/Google.cs | 2 +- Geekbot.net/Commands/Integrations/MagicTheGathering.cs | 2 +- Geekbot.net/Commands/Integrations/Mal.cs | 4 ++-- Geekbot.net/Commands/Integrations/Wikipedia.cs | 2 +- Geekbot.net/Commands/Integrations/Youtube.cs | 2 +- Geekbot.net/Commands/Randomness/EightBall.cs | 2 +- Geekbot.net/Commands/Randomness/Ship.cs | 2 +- Geekbot.net/Commands/Randomness/Slap.cs | 2 +- Geekbot.net/Commands/Rpg/Cookies.cs | 2 +- Geekbot.net/Commands/Utils/AvatarGetter.cs | 2 +- Geekbot.net/Commands/Utils/Dice/Dice.cs | 2 +- Geekbot.net/Commands/Utils/Quote/Quote.cs | 10 +++++----- 18 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Geekbot.net/Commands/Admin/Admin.cs b/Geekbot.net/Commands/Admin/Admin.cs index ba31e54..e2e1f86 100644 --- a/Geekbot.net/Commands/Admin/Admin.cs +++ b/Geekbot.net/Commands/Admin/Admin.cs @@ -35,7 +35,7 @@ namespace Geekbot.net.Commands.Admin [Command("welcome", RunMode = RunMode.Async)] [Summary("Set a Welcome Message (use '$user' to mention the new joined user).")] - public async Task SetWelcomeMessage([Remainder] [Summary("message")] string welcomeMessage) + public async Task SetWelcomeMessage([Remainder, Summary("message")] string welcomeMessage) { var guild = await GetGuildSettings(Context.Guild.Id); guild.WelcomeMessage = welcomeMessage; diff --git a/Geekbot.net/Commands/Admin/Mod.cs b/Geekbot.net/Commands/Admin/Mod.cs index 6c6be5a..1188504 100644 --- a/Geekbot.net/Commands/Admin/Mod.cs +++ b/Geekbot.net/Commands/Admin/Mod.cs @@ -30,7 +30,7 @@ namespace Geekbot.net.Commands.Admin [Command("namehistory", RunMode = RunMode.Async)] [Summary("See past usernames of an user")] - public async Task UsernameHistory([Summary("@user")] IUser user) + public async Task UsernameHistory([Summary("@someone")] IUser user) { try { diff --git a/Geekbot.net/Commands/Admin/Owner/Owner.cs b/Geekbot.net/Commands/Admin/Owner/Owner.cs index 661e5a3..74e0e8e 100644 --- a/Geekbot.net/Commands/Admin/Owner/Owner.cs +++ b/Geekbot.net/Commands/Admin/Owner/Owner.cs @@ -31,7 +31,7 @@ namespace Geekbot.net.Commands.Admin.Owner [Command("youtubekey", RunMode = RunMode.Async)] [Summary("Set the youtube api key")] - public async Task SetYoutubeKey([Summary("API Key")] string key) + public async Task SetYoutubeKey([Summary("API-Key")] string key) { await _globalSettings.SetKey("YoutubeKey", key); await ReplyAsync("Apikey has been set"); @@ -80,7 +80,7 @@ namespace Geekbot.net.Commands.Admin.Owner [Command("refreshuser", RunMode = RunMode.Async)] [Summary("Refresh a user in the user cache")] - public async Task PopUserRepoCommand([Summary("@user")] IUser user) + public async Task PopUserRepoCommand([Summary("@someone")] IUser user) { try { diff --git a/Geekbot.net/Commands/Admin/Role.cs b/Geekbot.net/Commands/Admin/Role.cs index f0aa7bd..85b7160 100644 --- a/Geekbot.net/Commands/Admin/Role.cs +++ b/Geekbot.net/Commands/Admin/Role.cs @@ -60,7 +60,7 @@ namespace Geekbot.net.Commands.Admin [Command(RunMode = RunMode.Async)] [Summary("Get a role by mentioning it.")] - public async Task GiveRole([Summary("roleNickname")] string roleNameRaw) + public async Task GiveRole([Summary("role-nickname")] string roleNameRaw) { try { @@ -144,7 +144,7 @@ namespace Geekbot.net.Commands.Admin [RequireUserPermission(GuildPermission.ManageRoles)] [Command("remove", RunMode = RunMode.Async)] [Summary("Remove a role from the whitelist.")] - public async Task RemoveRole([Summary("roleNickname")] string roleName) + public async Task RemoveRole([Summary("role-nickname")] string roleName) { try { @@ -170,7 +170,7 @@ namespace Geekbot.net.Commands.Admin [RequireUserPermission(GuildPermission.ManageRoles)] [Summary("Give a role by clicking on an emoji")] [Command("listen", RunMode = RunMode.Async)] - public async Task AddListener([Summary("messageID")] string messageId, [Summary("Emoji")] string emoji, [Summary("@role")] IRole role) + public async Task AddListener([Summary("message-ID")] string messageId, [Summary("Emoji")] string emoji, [Summary("@role")] IRole role) { try { diff --git a/Geekbot.net/Commands/Games/Pokedex.cs b/Geekbot.net/Commands/Games/Pokedex.cs index fbfb568..a0d2ae0 100644 --- a/Geekbot.net/Commands/Games/Pokedex.cs +++ b/Geekbot.net/Commands/Games/Pokedex.cs @@ -20,7 +20,7 @@ namespace Geekbot.net.Commands.Games [Command("pokedex", RunMode = RunMode.Async)] [Summary("A Pokedex Tool")] - public async Task GetPokemon([Summary("pokemonName")] string pokemonName) + public async Task GetPokemon([Summary("pokemon-name")] string pokemonName) { try { diff --git a/Geekbot.net/Commands/Games/Roll.cs b/Geekbot.net/Commands/Games/Roll.cs index 4fbb24e..dfecb13 100644 --- a/Geekbot.net/Commands/Games/Roll.cs +++ b/Geekbot.net/Commands/Games/Roll.cs @@ -32,7 +32,7 @@ namespace Geekbot.net.Commands.Games [Command("roll", RunMode = RunMode.Async)] [Summary("Guess which number the bot will roll (1-100")] - public async Task RollCommand([Remainder] [Summary("guess")] string stuff = "noGuess") + public async Task RollCommand([Remainder] [Summary("guess")] string stuff = null) { try { diff --git a/Geekbot.net/Commands/Integrations/Google/Google.cs b/Geekbot.net/Commands/Integrations/Google/Google.cs index 6ff926d..db059b4 100644 --- a/Geekbot.net/Commands/Integrations/Google/Google.cs +++ b/Geekbot.net/Commands/Integrations/Google/Google.cs @@ -23,7 +23,7 @@ namespace Geekbot.net.Commands.Integrations.Google [Command("google", RunMode = RunMode.Async)] [Summary("Google Something.")] - public async Task AskGoogle([Remainder, Summary("SearchText")] string searchText) + public async Task AskGoogle([Remainder, Summary("search-text")] string searchText) { try { diff --git a/Geekbot.net/Commands/Integrations/MagicTheGathering.cs b/Geekbot.net/Commands/Integrations/MagicTheGathering.cs index 9ccab39..ecf09cd 100644 --- a/Geekbot.net/Commands/Integrations/MagicTheGathering.cs +++ b/Geekbot.net/Commands/Integrations/MagicTheGathering.cs @@ -24,7 +24,7 @@ namespace Geekbot.net.Commands.Integrations [Command("mtg", RunMode = RunMode.Async)] [Summary("Find a Magic The Gathering Card.")] - public async Task GetCard([Remainder] [Summary("name")] string cardName) + public async Task GetCard([Remainder] [Summary("card-name")] string cardName) { try { diff --git a/Geekbot.net/Commands/Integrations/Mal.cs b/Geekbot.net/Commands/Integrations/Mal.cs index 1ad50bb..ecc91bf 100644 --- a/Geekbot.net/Commands/Integrations/Mal.cs +++ b/Geekbot.net/Commands/Integrations/Mal.cs @@ -23,7 +23,7 @@ namespace Geekbot.net.Commands.Integrations [Command("anime", RunMode = RunMode.Async)] [Summary("Show Info about an Anime.")] - public async Task SearchAnime([Remainder] [Summary("AnimeName")] string animeName) + public async Task SearchAnime([Remainder] [Summary("anime-name")] string animeName) { try { @@ -75,7 +75,7 @@ namespace Geekbot.net.Commands.Integrations [Command("manga", RunMode = RunMode.Async)] [Summary("Show Info about a Manga.")] - public async Task SearchManga([Remainder] [Summary("MangaName")] string mangaName) + public async Task SearchManga([Remainder] [Summary("manga-name")] string mangaName) { try { diff --git a/Geekbot.net/Commands/Integrations/Wikipedia.cs b/Geekbot.net/Commands/Integrations/Wikipedia.cs index e1f6092..9124670 100644 --- a/Geekbot.net/Commands/Integrations/Wikipedia.cs +++ b/Geekbot.net/Commands/Integrations/Wikipedia.cs @@ -29,7 +29,7 @@ namespace Geekbot.net.Commands.Integrations [Command("wiki", RunMode = RunMode.Async)] [Summary("Get an article from wikipedia.")] - public async Task GetPreview([Remainder] [Summary("Article")] string articleName) + public async Task GetPreview([Remainder] [Summary("article")] string articleName) { try { diff --git a/Geekbot.net/Commands/Integrations/Youtube.cs b/Geekbot.net/Commands/Integrations/Youtube.cs index ed630ee..1672bab 100644 --- a/Geekbot.net/Commands/Integrations/Youtube.cs +++ b/Geekbot.net/Commands/Integrations/Youtube.cs @@ -21,7 +21,7 @@ namespace Geekbot.net.Commands.Integrations [Command("yt", RunMode = RunMode.Async)] [Summary("Search for something on youtube.")] - public async Task Yt([Remainder] [Summary("Title")] string searchQuery) + public async Task Yt([Remainder] [Summary("title")] string searchQuery) { var key = _globalSettings.GetKey("YoutubeKey"); if (string.IsNullOrEmpty(key)) diff --git a/Geekbot.net/Commands/Randomness/EightBall.cs b/Geekbot.net/Commands/Randomness/EightBall.cs index 7b3bb1f..d07451d 100644 --- a/Geekbot.net/Commands/Randomness/EightBall.cs +++ b/Geekbot.net/Commands/Randomness/EightBall.cs @@ -17,7 +17,7 @@ namespace Geekbot.net.Commands.Randomness [Command("8ball", RunMode = RunMode.Async)] [Summary("Ask 8Ball a Question.")] - public async Task Ball([Remainder] [Summary("Question")] string echo) + public async Task Ball([Remainder] [Summary("question")] string echo) { try { diff --git a/Geekbot.net/Commands/Randomness/Ship.cs b/Geekbot.net/Commands/Randomness/Ship.cs index 3d876ef..2571891 100644 --- a/Geekbot.net/Commands/Randomness/Ship.cs +++ b/Geekbot.net/Commands/Randomness/Ship.cs @@ -26,7 +26,7 @@ namespace Geekbot.net.Commands.Randomness [Command("Ship", RunMode = RunMode.Async)] [Summary("Ask the Shipping meter")] - public async Task Command([Summary("@User1")] IUser user1, [Summary("@User2")] IUser user2) + public async Task Command([Summary("@user1")] IUser user1, [Summary("@user2")] IUser user2) { try { diff --git a/Geekbot.net/Commands/Randomness/Slap.cs b/Geekbot.net/Commands/Randomness/Slap.cs index 13cd22a..20e83c3 100644 --- a/Geekbot.net/Commands/Randomness/Slap.cs +++ b/Geekbot.net/Commands/Randomness/Slap.cs @@ -24,7 +24,7 @@ namespace Geekbot.net.Commands.Randomness [Command("slap", RunMode = RunMode.Async)] [Summary("slap someone")] - public async Task Slapper([Summary("@user")] IUser user) + public async Task Slapper([Summary("@someone")] IUser user) { try { diff --git a/Geekbot.net/Commands/Rpg/Cookies.cs b/Geekbot.net/Commands/Rpg/Cookies.cs index 6e4ff54..f22eccf 100644 --- a/Geekbot.net/Commands/Rpg/Cookies.cs +++ b/Geekbot.net/Commands/Rpg/Cookies.cs @@ -74,7 +74,7 @@ namespace Geekbot.net.Commands.Rpg [Command("give", RunMode = RunMode.Async)] [Summary("Give cookies to someone")] - public async Task GiveACookie([Summary("User")] IUser user, [Summary("amount")] int amount = 1) + public async Task GiveACookie([Summary("@someone")] IUser user, [Summary("amount")] int amount = 1) { try { diff --git a/Geekbot.net/Commands/Utils/AvatarGetter.cs b/Geekbot.net/Commands/Utils/AvatarGetter.cs index e329ad4..142b3e3 100644 --- a/Geekbot.net/Commands/Utils/AvatarGetter.cs +++ b/Geekbot.net/Commands/Utils/AvatarGetter.cs @@ -17,7 +17,7 @@ namespace Geekbot.net.Commands.Utils [Command("avatar", RunMode = RunMode.Async)] [Summary("Get someones avatar")] - public async Task GetAvatar([Remainder] [Summary("user")] IUser user = null) + public async Task GetAvatar([Remainder, Summary("@someone")] IUser user = null) { try { diff --git a/Geekbot.net/Commands/Utils/Dice/Dice.cs b/Geekbot.net/Commands/Utils/Dice/Dice.cs index 8b23fe6..6b95903 100644 --- a/Geekbot.net/Commands/Utils/Dice/Dice.cs +++ b/Geekbot.net/Commands/Utils/Dice/Dice.cs @@ -19,7 +19,7 @@ namespace Geekbot.net.Commands.Utils.Dice [Command("dice", RunMode = RunMode.Async)] [Summary("Roll a dice.")] - public async Task RollCommand([Remainder] [Summary("diceType")] string diceType = "1d20") + public async Task RollCommand([Remainder] [Summary("dice-type")] string diceType = "1d20") { var splitedDices = diceType.Split("+"); var dices = new List(); diff --git a/Geekbot.net/Commands/Utils/Quote/Quote.cs b/Geekbot.net/Commands/Utils/Quote/Quote.cs index 84a3786..f06c6ab 100644 --- a/Geekbot.net/Commands/Utils/Quote/Quote.cs +++ b/Geekbot.net/Commands/Utils/Quote/Quote.cs @@ -60,7 +60,7 @@ namespace Geekbot.net.Commands.Utils.Quote [Command("save")] [Summary("Save a quote from the last sent message by @user")] - public async Task SaveQuote([Summary("@user")] IUser user) + public async Task SaveQuote([Summary("@someone")] IUser user) { try { @@ -96,7 +96,7 @@ namespace Geekbot.net.Commands.Utils.Quote [Command("save")] [Summary("Save a quote from a message id")] - public async Task SaveQuote([Summary("messageId")] ulong messageId) + public async Task SaveQuote([Summary("message-ID")] ulong messageId) { try { @@ -130,7 +130,7 @@ namespace Geekbot.net.Commands.Utils.Quote [Command("make")] [Summary("Create a quote from the last sent message by @user")] - public async Task ReturnSpecifiedQuote([Summary("@user")] IUser user) + public async Task ReturnSpecifiedQuote([Summary("@someone")] IUser user) { try { @@ -149,7 +149,7 @@ namespace Geekbot.net.Commands.Utils.Quote [Command("make")] [Summary("Create a quote from a message id")] - public async Task ReturnSpecifiedQuote([Summary("messageId")] ulong messageId) + public async Task ReturnSpecifiedQuote([Summary("message-ID")] ulong messageId) { try { @@ -170,7 +170,7 @@ namespace Geekbot.net.Commands.Utils.Quote [RequireUserPermission(GuildPermission.ManageMessages)] [RequireUserPermission(GuildPermission.ManageRoles)] [Summary("Remove a quote (required mod permissions)")] - public async Task RemoveQuote([Summary("quoteId")] int id) + public async Task RemoveQuote([Summary("quote-ID")] int id) { try { From 8f861ee0bcbb52251a7394b65f320764752d1c44 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 16 May 2019 22:17:33 +0200 Subject: [PATCH 289/553] overload owner refreshuser with a user-id as parameter --- Geekbot.net/Commands/Admin/Owner/Owner.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Geekbot.net/Commands/Admin/Owner/Owner.cs b/Geekbot.net/Commands/Admin/Owner/Owner.cs index 74e0e8e..996d848 100644 --- a/Geekbot.net/Commands/Admin/Owner/Owner.cs +++ b/Geekbot.net/Commands/Admin/Owner/Owner.cs @@ -92,6 +92,22 @@ namespace Geekbot.net.Commands.Admin.Owner await _errorHandler.HandleCommandException(e, Context); } } + + [Command("refreshuser", RunMode = RunMode.Async)] + [Summary("Refresh a user in the user cache")] + public async Task PopUserRepoCommand([Summary("user-id")] ulong userId) + { + try + { + var user = _client.GetUser(userId); + await _userRepository.Update(user); + await ReplyAsync($"Refreshed: {user.Username}#{user.Discriminator}"); + } + catch (Exception e) + { + await _errorHandler.HandleCommandException(e, Context); + } + } [Command("error", RunMode = RunMode.Async)] [Summary("Throw an error un purpose")] From 57698c8ce63b5aa10fed87cba1918e9fa1321f9b Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 16 May 2019 22:40:11 +0200 Subject: [PATCH 290/553] Fix mtg issue and update json.net --- Geekbot.net/Commands/Integrations/MagicTheGathering.cs | 1 - Geekbot.net/Geekbot.net.csproj | 4 ++-- WikipediaApi/WikipediaApi.csproj | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Geekbot.net/Commands/Integrations/MagicTheGathering.cs b/Geekbot.net/Commands/Integrations/MagicTheGathering.cs index ecf09cd..ef16fee 100644 --- a/Geekbot.net/Commands/Integrations/MagicTheGathering.cs +++ b/Geekbot.net/Commands/Integrations/MagicTheGathering.cs @@ -32,7 +32,6 @@ namespace Geekbot.net.Commands.Integrations var result = service .Where(x => x.Name, cardName) // fewer cards less risk of deserialization problems, don't need more than one anyways... - // ToDo: fix the deserialization issue in card[n].foreignNames[] .Where(x => x.PageSize, 1); var card = result.All().Value.FirstOrDefault(); diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 9c5c5c7..db8cf08 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -39,9 +39,9 @@ - + - + diff --git a/WikipediaApi/WikipediaApi.csproj b/WikipediaApi/WikipediaApi.csproj index 79206c2..3e82c68 100644 --- a/WikipediaApi/WikipediaApi.csproj +++ b/WikipediaApi/WikipediaApi.csproj @@ -3,6 +3,6 @@ netcoreapp2.2 - + \ No newline at end of file From 8822e65e6a8fcb8b51b495c90d9f901dc4fa1951 Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 21 May 2019 19:42:04 +0200 Subject: [PATCH 291/553] Upgrade Discord.net to V2.1 --- Geekbot.net/Geekbot.net.csproj | 2 +- Geekbot.net/Program.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index db8cf08..4749374 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -22,7 +22,7 @@ - 2.0.1 + 2.1.0 diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index d04dcbb..b7251a8 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -79,7 +79,8 @@ namespace Geekbot.net _client = new DiscordSocketClient(new DiscordSocketConfig { LogLevel = LogSeverity.Verbose, - MessageCacheSize = 1000 + MessageCacheSize = 1000, + ExclusiveBulkDelete = true }); _client.Log += discordLogger.Log; _commands = new CommandService(); From ced287e492d970f2dcb151a008916df093f4d79d Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 21 May 2019 20:50:50 +0200 Subject: [PATCH 292/553] Allow a server admin to specify a channel for the welcome message --- Geekbot.net/Commands/Admin/Admin.cs | 25 +++++++++++++- .../Database/Models/GuildSettingsModel.cs | 6 ++-- Geekbot.net/Handlers.cs | 33 +++++++++++++++---- 3 files changed, 55 insertions(+), 9 deletions(-) diff --git a/Geekbot.net/Commands/Admin/Admin.cs b/Geekbot.net/Commands/Admin/Admin.cs index e2e1f86..15b4df1 100644 --- a/Geekbot.net/Commands/Admin/Admin.cs +++ b/Geekbot.net/Commands/Admin/Admin.cs @@ -46,6 +46,29 @@ namespace Geekbot.net.Commands.Admin await ReplyAsync($"Welcome message has been changed\r\nHere is an example of how it would look:\r\n{formatedMessage}"); } + [Command("welcomechannel", RunMode = RunMode.Async)] + [Summary("Set a channel for the welcome messages (by default it uses the top most channel)")] + public async Task SelectWelcomeChannel([Summary("#Channel")] ISocketMessageChannel channel) + { + try + { + var m = await channel.SendMessageAsync("..."); + + var guild = await GetGuildSettings(Context.Guild.Id); + guild.WelcomeChannel = channel.Id.AsLong(); + _database.GuildSettings.Update(guild); + await _database.SaveChangesAsync(); + + await m.DeleteAsync(); + + await ReplyAsync("Successfully saved the welcome channel"); + } + catch (Exception e) + { + await _errorHandler.HandleCommandException(e, Context, "That channel doesn't seem to exist or i don't have write permissions"); + } + } + [Command("modchannel", RunMode = RunMode.Async)] [Summary("Set a channel for moderation purposes")] public async Task SelectModChannel([Summary("#Channel")] ISocketMessageChannel channel) @@ -67,7 +90,7 @@ namespace Geekbot.net.Commands.Admin } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context, "That channel doesn't seem to be valid"); + await _errorHandler.HandleCommandException(e, Context, "That channel doesn't seem to exist or i don't have write permissions"); } } diff --git a/Geekbot.net/Database/Models/GuildSettingsModel.cs b/Geekbot.net/Database/Models/GuildSettingsModel.cs index 6bc98b1..ebb6dc4 100644 --- a/Geekbot.net/Database/Models/GuildSettingsModel.cs +++ b/Geekbot.net/Database/Models/GuildSettingsModel.cs @@ -6,7 +6,7 @@ namespace Geekbot.net.Database.Models { [Key] public int Id { get; set; } - + [Required] public long GuildId { get; set; } @@ -15,9 +15,11 @@ namespace Geekbot.net.Database.Models public bool Hui { get; set; } = false; public long ModChannel { get; set; } = 0; - + public string WelcomeMessage { get; set; } + public long WelcomeChannel { get; set; } + public bool ShowDelete { get; set; } = false; public bool ShowLeave { get; set; } = false; diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index 6dd53d0..a254c14 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -4,6 +4,7 @@ using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Discord.Rest; using Discord.WebSocket; using Geekbot.net.Database; using Geekbot.net.Database.Models; @@ -143,18 +144,38 @@ namespace Geekbot.net { try { + var userRepoUpdate = _userRepository.Update(user); + _logger.Information(LogSource.Geekbot, $"{user.Username} ({user.Id}) joined {user.Guild.Name} ({user.Guild.Id})"); + if (!user.IsBot) { - var message = _database.GuildSettings.FirstOrDefault(guild => guild.GuildId.Equals(user.Guild.Id.AsLong()))?.WelcomeMessage; - if (!string.IsNullOrEmpty(message)) + var guildSettings = _database.GuildSettings.FirstOrDefault(guild => guild.GuildId == user.Guild.Id.AsLong()); + var message = guildSettings?.WelcomeMessage; + if (string.IsNullOrEmpty(message)) return; + message = message.Replace("$user", user.Mention); + + var fallbackSender = new Func>(() => user.Guild.DefaultChannel.SendMessageAsync(message)); + if (guildSettings.WelcomeChannel != 0) { - message = message.Replace("$user", user.Mention); - await user.Guild.DefaultChannel.SendMessageAsync(message); + try + { + var target = await _client.GetChannelAsync(guildSettings.WelcomeChannel.AsUlong()); + var channel = target as ISocketMessageChannel; + await channel.SendMessageAsync(message); + } + catch (Exception e) + { + _logger.Error(LogSource.Geekbot, "Failed to send welcome message to user defined welcome channel", e); + await fallbackSender(); + } + } + else + { + await fallbackSender(); } } - await _userRepository.Update(user); - _logger.Information(LogSource.Geekbot, $"{user.Username} ({user.Id}) joined {user.Guild.Name} ({user.Guild.Id})"); + await userRepoUpdate; } catch (Exception e) { From 288c976674afe692af29e27b1f8f19962e68e4d5 Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 28 May 2019 20:32:15 +0200 Subject: [PATCH 293/553] rename bdcc to bdcb --- .../Commands/Randomness/BenedictCumberbatchNameGenerator.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Geekbot.net/Commands/Randomness/BenedictCumberbatchNameGenerator.cs b/Geekbot.net/Commands/Randomness/BenedictCumberbatchNameGenerator.cs index 501f891..838dff2 100644 --- a/Geekbot.net/Commands/Randomness/BenedictCumberbatchNameGenerator.cs +++ b/Geekbot.net/Commands/Randomness/BenedictCumberbatchNameGenerator.cs @@ -18,7 +18,7 @@ namespace Geekbot.net.Commands.Randomness _randomNumberGenerator = randomNumberGenerator; } - [Command("bdcc", RunMode = RunMode.Async)] + [Command("bdcb", RunMode = RunMode.Async)] [Summary("Benedict Cumberbatch Name Generator")] public async Task GetQuote() { @@ -59,4 +59,4 @@ namespace Geekbot.net.Commands.Randomness } } } -} \ No newline at end of file +} From 8fadff4092d2c92f495555c677ce2963e2f2f5d0 Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 4 Jun 2019 23:00:16 +0200 Subject: [PATCH 294/553] Cookies timeout is now at midnight instead of every 24h --- Geekbot.net/Commands/Rpg/Cookies.cs | 4 ++-- Geekbot.net/Lib/Localization/Translations.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Geekbot.net/Commands/Rpg/Cookies.cs b/Geekbot.net/Commands/Rpg/Cookies.cs index f22eccf..3c41044 100644 --- a/Geekbot.net/Commands/Rpg/Cookies.cs +++ b/Geekbot.net/Commands/Rpg/Cookies.cs @@ -38,9 +38,9 @@ namespace Geekbot.net.Commands.Rpg { var transContext = await _translation.GetGuildContext(Context); var actor = await GetUser(Context.User.Id); - if (actor.LastPayout.Value.AddHours(24) > DateTimeOffset.Now) + if (actor.LastPayout.Value.AddDays(1).Date > DateTime.Now.Date) { - var formatedWaitTime = transContext.FormatDateTimeAsRemaining(actor.LastPayout.Value.AddHours(24)); + var formatedWaitTime = transContext.FormatDateTimeAsRemaining(DateTimeOffset.Now.AddDays(1).Date); await ReplyAsync(transContext.GetString("WaitForMoreCookies", formatedWaitTime)); return; } diff --git a/Geekbot.net/Lib/Localization/Translations.yml b/Geekbot.net/Lib/Localization/Translations.yml index 04835a2..4bf4d14 100644 --- a/Geekbot.net/Lib/Localization/Translations.yml +++ b/Geekbot.net/Lib/Localization/Translations.yml @@ -90,8 +90,8 @@ cookies: EN: "You got {0} cookies, there are now {1} cookies in you cookie jar" CHDE: "Du häsch {0} guetzli becho, du häsch jetzt {1} guetzli ih dr büchse" WaitForMoreCookies: - EN: "You already got cookies in the last 24 hours, you can have more cookies in {0}" - CHDE: "Du hesch scho guetzli becho ih de letzti 24 stund, du chasch meh ha in {0}" + EN: "You already got cookies today, you can have more cookies in {0}" + CHDE: "Du hesch scho guetzli becho hüt, du chasch meh ha in {0}" InYourJar: EN: "There are {0} cookies in you cookie jar" CHDE: "Es hät {0} guetzli ih dineri büchs" From ac43d087b175686081b8e29d1e0f86e008b09e8c Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 21 Jul 2019 13:00:02 +0200 Subject: [PATCH 295/553] Add the !cookie alias and allow yaml alliases in the translations file --- Geekbot.net/Commands/Rpg/Cookies.cs | 1 + Geekbot.net/Lib/Localization/TranslationHandler.cs | 6 +++--- Geekbot.net/Lib/Localization/Translations.yml | 5 ++++- Tests/Lib/Localization/Translations.test.cs | 4 +++- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Geekbot.net/Commands/Rpg/Cookies.cs b/Geekbot.net/Commands/Rpg/Cookies.cs index 3c41044..b1a2d7d 100644 --- a/Geekbot.net/Commands/Rpg/Cookies.cs +++ b/Geekbot.net/Commands/Rpg/Cookies.cs @@ -15,6 +15,7 @@ namespace Geekbot.net.Commands.Rpg { [DisableInDirectMessage] [Group("cookies")] + [Alias("cookie")] public class Cookies : ModuleBase { private readonly DatabaseContext _database; diff --git a/Geekbot.net/Lib/Localization/TranslationHandler.cs b/Geekbot.net/Lib/Localization/TranslationHandler.cs index 3d1ee3a..a7a1a12 100644 --- a/Geekbot.net/Lib/Localization/TranslationHandler.cs +++ b/Geekbot.net/Lib/Localization/TranslationHandler.cs @@ -8,8 +8,7 @@ using Geekbot.net.Database; using Geekbot.net.Database.Models; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Logger; -using Utf8Json; -using YamlDotNet.RepresentationModel; +using YamlDotNet.Core; using YamlDotNet.Serialization; namespace Geekbot.net.Lib.Localization @@ -39,8 +38,9 @@ namespace Geekbot.net.Lib.Localization // Deserialize var input = new StringReader(translationFile); + var mergingParser = new MergingParser(new Parser(input)); var deserializer = new DeserializerBuilder().Build(); - var rawTranslations = deserializer.Deserialize>>>(input); + var rawTranslations = deserializer.Deserialize>>>(mergingParser); // Sort var sortedPerLanguage = new Dictionary>>(); diff --git a/Geekbot.net/Lib/Localization/Translations.yml b/Geekbot.net/Lib/Localization/Translations.yml index 4bf4d14..730ea40 100644 --- a/Geekbot.net/Lib/Localization/Translations.yml +++ b/Geekbot.net/Lib/Localization/Translations.yml @@ -85,7 +85,7 @@ roll: NoPrevGuess: EN: ":red_circle: {0}, you can't guess the same number again" CHDE: ":red_circle: {0}, du chasch nid nomol es gliche rate" -cookies: +cookies: &cookiesAlias GetCookies: EN: "You got {0} cookies, there are now {1} cookies in you cookie jar" CHDE: "Du häsch {0} guetzli becho, du häsch jetzt {1} guetzli ih dr büchse" @@ -107,6 +107,9 @@ cookies: AteCookies: EN: "You ate {0} cookies, you've only got {1} cookies left" CHDE: "Du hesch {0} guetzli gesse und hesch jezt no {1} übrig" +cookie: + # because command aliases are to hard to deal with... + <<: *cookiesAlias role: NoRolesConfigured: EN: "There are no roles configured for this server" diff --git a/Tests/Lib/Localization/Translations.test.cs b/Tests/Lib/Localization/Translations.test.cs index fc43091..736ed83 100644 --- a/Tests/Lib/Localization/Translations.test.cs +++ b/Tests/Lib/Localization/Translations.test.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; using FluentAssertions; using Xunit; +using YamlDotNet.Core; using YamlDotNet.Serialization; namespace Tests.Lib.Localization @@ -17,8 +18,9 @@ namespace Tests.Lib.Localization // Deserialize var input = new StringReader(translationFile); + var mergingParser = new MergingParser(new Parser(input)); var deserializer = new DeserializerBuilder().Build(); - var rawTranslations = deserializer.Deserialize>>>(input); + var rawTranslations = deserializer.Deserialize>>>(mergingParser); // These languages must be supported var supportedLanguages = new List From 7a250f664215d3a36739469b30ced674e32546f4 Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 30 Jul 2019 00:42:08 +0200 Subject: [PATCH 296/553] Ignore commands on certain serves --- Geekbot.net/Handlers.cs | 28 +++++++++++++++++++++++++--- Geekbot.net/Program.cs | 3 ++- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index a254c14..d16750b 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -28,10 +29,12 @@ namespace Geekbot.net private readonly IUserRepository _userRepository; private readonly IReactionListener _reactionListener; private readonly DatabaseContext _messageCounterDatabaseContext; + private readonly RestApplication _applicationInfo; + private readonly List _ignoredServers; public Handlers(DatabaseInitializer databaseInitializer, IDiscordClient client, IGeekbotLogger logger, IAlmostRedis redis, IServiceProvider servicesProvider, CommandService commands, IUserRepository userRepository, - IReactionListener reactionListener) + IReactionListener reactionListener, RestApplication applicationInfo) { _database = databaseInitializer.Initialize(); _messageCounterDatabaseContext = databaseInitializer.Initialize(); @@ -42,6 +45,14 @@ namespace Geekbot.net _commands = commands; _userRepository = userRepository; _reactionListener = reactionListener; + _applicationInfo = applicationInfo; + // ToDo: create a clean solution for this... + _ignoredServers = new List() + { + 228623803201224704, // SwitzerLAN + 169844523181015040, // EEvent + 248531441548263425 // MYI + }; } // @@ -56,10 +67,21 @@ namespace Geekbot.net if (message.Author.IsBot) return Task.CompletedTask; var argPos = 0; + var guildId = ((SocketGuildChannel) message.Channel).Guild.Id; + // Some guilds only wanted very specific functionally without any of the commands, a quick hack that solves that short term... + // ToDo: cleanup + if (_ignoredServers.Contains(guildId)) + { + if (message.Author.Id != _applicationInfo.Owner.Id) + { + return Task.CompletedTask; + } + } + var lowCaseMsg = message.ToString().ToLower(); if (lowCaseMsg.StartsWith("hui")) { - var hasPing = _database.GuildSettings.FirstOrDefault(guild => guild.GuildId.Equals(((SocketGuildChannel) message.Channel).Guild.Id.AsLong()))?.Hui ?? false; + var hasPing = _database.GuildSettings.FirstOrDefault(guild => guild.GuildId.Equals(guildId.AsLong()))?.Hui ?? false; if (hasPing) { message.Channel.SendMessageAsync("hui!!!"); @@ -69,7 +91,7 @@ namespace Geekbot.net if (lowCaseMsg.StartsWith("ping ") || lowCaseMsg.Equals("ping")) { - var hasPing = _database.GuildSettings.FirstOrDefault(guild => guild.GuildId.Equals(((SocketGuildChannel) message.Channel).Guild.Id.AsLong()))?.Ping ?? false; + var hasPing = _database.GuildSettings.FirstOrDefault(guild => guild.GuildId.Equals(guildId.AsLong()))?.Ping ?? false; if (hasPing) { message.Channel.SendMessageAsync("pong"); diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index b7251a8..72ec6d5 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -156,6 +156,7 @@ namespace Geekbot.net var isConneted = await IsConnected(); if (isConneted) { + var applicationInfo = await _client.GetApplicationInfoAsync(); await _client.SetGameAsync(_globalSettings.GetKey("Game")); _logger.Information(LogSource.Geekbot, $"Now Connected as {_client.CurrentUser.Username} to {_client.Guilds.Count} Servers"); @@ -170,7 +171,7 @@ namespace Geekbot.net _servicesProvider = _services.BuildServiceProvider(); await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _servicesProvider); - var handlers = new Handlers(_databaseInitializer, _client, _logger, _redis, _servicesProvider, _commands, _userRepository, reactionListener); + var handlers = new Handlers(_databaseInitializer, _client, _logger, _redis, _servicesProvider, _commands, _userRepository, reactionListener, applicationInfo); _client.MessageReceived += handlers.RunCommand; _client.MessageDeleted += handlers.MessageDeleted; From fe4a78b7433fc096472353831159033317e6eace Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 30 Jul 2019 00:47:32 +0200 Subject: [PATCH 297/553] Allow failure on sentry during deployment --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8c7a530..fc60d1b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -23,6 +23,7 @@ build: sentry: stage: ops image: getsentry/sentry-cli + allow_failure: true only: - master dependencies: From 1bfd7c7a129fc675f19a317bb3554e3d5b19d80b Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 5 Aug 2019 09:14:58 +0200 Subject: [PATCH 298/553] Ignore the discord bots server aswell --- Geekbot.net/Handlers.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index d16750b..09f95be 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -51,7 +51,8 @@ namespace Geekbot.net { 228623803201224704, // SwitzerLAN 169844523181015040, // EEvent - 248531441548263425 // MYI + 248531441548263425, // MYI + 110373943822540800 // Discord Bots }; } From 143722eccf3b775dc2eaf0a0d5ea4b90c218c916 Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 5 Aug 2019 09:18:16 +0200 Subject: [PATCH 299/553] Stop using redis for counting messages --- Geekbot.net/Handlers.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index 09f95be..4671e07 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -129,7 +129,6 @@ namespace Geekbot.net var channel = (SocketGuildChannel) message.Channel; - // just testing, redis will remain the source of truth for now var rowId = await _messageCounterDatabaseContext.Database.ExecuteSqlCommandAsync( "UPDATE \"Messages\" SET \"MessageCount\" = \"MessageCount\" + 1 WHERE \"GuildId\" = {0} AND \"UserId\" = {1}", channel.Guild.Id.AsLong(), @@ -147,9 +146,6 @@ namespace Geekbot.net _messageCounterDatabaseContext.SaveChanges(); } - await _redis.Db.HashIncrementAsync($"{channel.Guild.Id}:Messages", message.Author.Id.ToString()); - await _redis.Db.HashIncrementAsync($"{channel.Guild.Id}:Messages", 0.ToString()); - if (message.Author.IsBot) return; _logger.Information(LogSource.Message, message.Content, SimpleConextConverter.ConvertSocketMessage(message)); } From f1387f824e34e99b8fd017767d620be7563f1736 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 19 Sep 2019 13:40:02 +0200 Subject: [PATCH 300/553] Remove the google command --- .../Commands/Integrations/Google/Google.cs | 68 ------------------- .../Google/GoogleKgApiDetailedDto.cs | 9 --- .../Google/GoogleKgApiElementDto.cs | 8 --- .../Google/GoogleKgApiImageDto.cs | 8 --- .../Google/GoogleKgApiResponseDto.cs | 9 --- .../Google/GoogleKgApiResultDto.cs | 10 --- 6 files changed, 112 deletions(-) delete mode 100644 Geekbot.net/Commands/Integrations/Google/Google.cs delete mode 100644 Geekbot.net/Commands/Integrations/Google/GoogleKgApiDetailedDto.cs delete mode 100644 Geekbot.net/Commands/Integrations/Google/GoogleKgApiElementDto.cs delete mode 100644 Geekbot.net/Commands/Integrations/Google/GoogleKgApiImageDto.cs delete mode 100644 Geekbot.net/Commands/Integrations/Google/GoogleKgApiResponseDto.cs delete mode 100644 Geekbot.net/Commands/Integrations/Google/GoogleKgApiResultDto.cs diff --git a/Geekbot.net/Commands/Integrations/Google/Google.cs b/Geekbot.net/Commands/Integrations/Google/Google.cs deleted file mode 100644 index db059b4..0000000 --- a/Geekbot.net/Commands/Integrations/Google/Google.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Linq; -using System.Net; -using System.Threading.Tasks; -using Discord; -using Discord.Commands; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.GlobalSettings; -using Newtonsoft.Json; - -namespace Geekbot.net.Commands.Integrations.Google -{ - public class Google : ModuleBase - { - private readonly IErrorHandler _errorHandler; - private readonly IGlobalSettings _globalSettings; - - public Google(IErrorHandler errorHandler, IGlobalSettings globalSettings) - { - _errorHandler = errorHandler; - _globalSettings = globalSettings; - } - - [Command("google", RunMode = RunMode.Async)] - [Summary("Google Something.")] - public async Task AskGoogle([Remainder, Summary("search-text")] string searchText) - { - try - { - using (var client = new WebClient()) - { - var apiKey = _globalSettings.GetKey("GoogleGraphKey"); - if (string.IsNullOrEmpty(apiKey)) - { - await ReplyAsync("No Google API key has been set, please contact my owner"); - return; - } - - var url = new Uri($"https://kgsearch.googleapis.com/v1/entities:search?languages=en&limit=1&query={searchText}&key={apiKey}"); - var responseString = client.DownloadString(url); - var response = JsonConvert.DeserializeObject(responseString); - - if (!response.ItemListElement.Any()) - { - await ReplyAsync("No results were found..."); - return; - } - - var data = response.ItemListElement.First().Result; - var eb = new EmbedBuilder - { - Title = data.Name - }; - if(!string.IsNullOrEmpty(data.Description)) eb.WithDescription(data.Description); - if(!string.IsNullOrEmpty(data.DetailedDtoDescription?.Url)) eb.WithUrl(data.DetailedDtoDescription.Url); - if(!string.IsNullOrEmpty(data.DetailedDtoDescription?.ArticleBody)) eb.AddField("Details", data.DetailedDtoDescription.ArticleBody); - if(!string.IsNullOrEmpty(data.Image?.ContentUrl)) eb.WithThumbnailUrl(data.Image.ContentUrl); - - await ReplyAsync("", false, eb.Build()); - } - } - catch (Exception e) - { - await _errorHandler.HandleCommandException(e, Context); - } - } - } -} \ No newline at end of file diff --git a/Geekbot.net/Commands/Integrations/Google/GoogleKgApiDetailedDto.cs b/Geekbot.net/Commands/Integrations/Google/GoogleKgApiDetailedDto.cs deleted file mode 100644 index 031d1e7..0000000 --- a/Geekbot.net/Commands/Integrations/Google/GoogleKgApiDetailedDto.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Geekbot.net.Commands.Integrations.Google -{ - public class GoogleKgApiDetailedDto - { - public string ArticleBody { get; set; } - public string Url { get; set; } - public string License { get; set; } - } -} \ No newline at end of file diff --git a/Geekbot.net/Commands/Integrations/Google/GoogleKgApiElementDto.cs b/Geekbot.net/Commands/Integrations/Google/GoogleKgApiElementDto.cs deleted file mode 100644 index a48b184..0000000 --- a/Geekbot.net/Commands/Integrations/Google/GoogleKgApiElementDto.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Geekbot.net.Commands.Integrations.Google -{ - public class GoogleKgApiElementDto - { - public GoogleKgApiResultDto Result { get; set; } - public double ResultScore { get; set; } - } -} \ No newline at end of file diff --git a/Geekbot.net/Commands/Integrations/Google/GoogleKgApiImageDto.cs b/Geekbot.net/Commands/Integrations/Google/GoogleKgApiImageDto.cs deleted file mode 100644 index fe7cdaa..0000000 --- a/Geekbot.net/Commands/Integrations/Google/GoogleKgApiImageDto.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Geekbot.net.Commands.Integrations.Google -{ - public class GoogleKgApiImageDto - { - public string ContentUrl { get; set; } - public string Url { get; set; } - } -} \ No newline at end of file diff --git a/Geekbot.net/Commands/Integrations/Google/GoogleKgApiResponseDto.cs b/Geekbot.net/Commands/Integrations/Google/GoogleKgApiResponseDto.cs deleted file mode 100644 index af337db..0000000 --- a/Geekbot.net/Commands/Integrations/Google/GoogleKgApiResponseDto.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Collections.Generic; - -namespace Geekbot.net.Commands.Integrations.Google -{ - public class GoogleKgApiResponseDto - { - public List ItemListElement { get; set; } - } -} \ No newline at end of file diff --git a/Geekbot.net/Commands/Integrations/Google/GoogleKgApiResultDto.cs b/Geekbot.net/Commands/Integrations/Google/GoogleKgApiResultDto.cs deleted file mode 100644 index 465f1d7..0000000 --- a/Geekbot.net/Commands/Integrations/Google/GoogleKgApiResultDto.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Geekbot.net.Commands.Integrations.Google -{ - public class GoogleKgApiResultDto - { - public string Name { get; set; } - public string Description { get; set; } - public GoogleKgApiImageDto Image { get; set; } - public GoogleKgApiDetailedDto DetailedDtoDescription { get; set; } - } -} \ No newline at end of file From 309f06370b73c6c656adbebe9e21e45f341c6bc9 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 19 Sep 2019 13:42:48 +0200 Subject: [PATCH 301/553] Cut urban dictionary word definitions at the 1800 character mark --- .../Commands/Integrations/UbranDictionary/UrbanDictionary.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs b/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs index 4f29f10..932425b 100644 --- a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs +++ b/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs @@ -48,7 +48,7 @@ namespace Geekbot.net.Commands.Integrations.UbranDictionary Url = definition.Permalink }); eb.WithColor(new Color(239, 255, 0)); - if (!string.IsNullOrEmpty(definition.Definition)) eb.Description = definition.Definition; + if (!string.IsNullOrEmpty(definition.Definition)) eb.Description = definition.Definition.Substring(0, 1800); if (!string.IsNullOrEmpty(definition.Example)) eb.AddField("Example", definition.Example ?? "(no example given...)"); if (!string.IsNullOrEmpty(definition.ThumbsUp)) eb.AddInlineField("Upvotes", definition.ThumbsUp); if (!string.IsNullOrEmpty(definition.ThumbsDown)) eb.AddInlineField("Downvotes", definition.ThumbsDown); From 19df65fc760bec170ffc1f9652f9e2ce94d68559 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 19 Sep 2019 21:27:34 +0200 Subject: [PATCH 302/553] Fix out of bounds error in the urban dict. command --- .../Integrations/UbranDictionary/UrbanDictionary.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs b/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs index 932425b..254c2bb 100644 --- a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs +++ b/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs @@ -41,6 +41,12 @@ namespace Geekbot.net.Commands.Integrations.UbranDictionary var definition = definitions.List.First(e => !string.IsNullOrWhiteSpace(e.Example)); + var description = definition.Definition; + if (description.Length > 1801) + { + description = description.Substring(0, 1800) + " [...]"; + } + var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder { @@ -48,7 +54,7 @@ namespace Geekbot.net.Commands.Integrations.UbranDictionary Url = definition.Permalink }); eb.WithColor(new Color(239, 255, 0)); - if (!string.IsNullOrEmpty(definition.Definition)) eb.Description = definition.Definition.Substring(0, 1800); + if (!string.IsNullOrEmpty(definition.Definition)) eb.Description = description; if (!string.IsNullOrEmpty(definition.Example)) eb.AddField("Example", definition.Example ?? "(no example given...)"); if (!string.IsNullOrEmpty(definition.ThumbsUp)) eb.AddInlineField("Upvotes", definition.ThumbsUp); if (!string.IsNullOrEmpty(definition.ThumbsDown)) eb.AddInlineField("Downvotes", definition.ThumbsDown); From b7b4a600cd69b0f03d0a1087101778d6e53d3dbf Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 11 Oct 2019 00:55:55 +0200 Subject: [PATCH 303/553] Fix message when a role has been added to the whitelist --- Geekbot.net/Commands/Admin/Role.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Geekbot.net/Commands/Admin/Role.cs b/Geekbot.net/Commands/Admin/Role.cs index 85b7160..decb7fc 100644 --- a/Geekbot.net/Commands/Admin/Role.cs +++ b/Geekbot.net/Commands/Admin/Role.cs @@ -133,7 +133,7 @@ namespace Geekbot.net.Commands.Admin WhiteListName = roleName }); await _database.SaveChangesAsync(); - await ReplyAsync(transContext.GetString("CannotAddDangerousRole", role.Name)); + await ReplyAsync(transContext.GetString("AddedRoleToWhitelist", role.Name)); } catch (Exception e) { From 8dd914e0124471974e56c07bcc4f88a774d0888b Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 11 Oct 2019 01:08:59 +0200 Subject: [PATCH 304/553] Properly log errors when adding a role emoji --- Geekbot.net/Commands/Admin/Role.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Geekbot.net/Commands/Admin/Role.cs b/Geekbot.net/Commands/Admin/Role.cs index decb7fc..b0df4bb 100644 --- a/Geekbot.net/Commands/Admin/Role.cs +++ b/Geekbot.net/Commands/Admin/Role.cs @@ -196,8 +196,7 @@ namespace Geekbot.net.Commands.Admin } catch (Exception e) { - await Context.Channel.SendMessageAsync("Something went wrong... please try again on a new message"); - Console.WriteLine(e); + await _errorHandler.HandleCommandException(e, Context); } } } From 20c75019f9391a612380f96571e4f8377826991a Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 26 Oct 2019 21:54:34 +0200 Subject: [PATCH 305/553] Upgrade to dotnet core 3 and update dependencies --- .gitlab-ci.yml | 2 +- Geekbot.net/Geekbot.net.csproj | 41 +++++++++++++++----------------- Geekbot.net/Handlers.cs | 2 +- Tests/Tests.csproj | 6 ++--- WikipediaApi/WikipediaApi.csproj | 2 +- 5 files changed, 25 insertions(+), 28 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fc60d1b..7e32f69 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,7 +10,7 @@ before_script: build: stage: build - image: mcr.microsoft.com/dotnet/core/sdk:2.2 + image: mcr.microsoft.com/dotnet/core/sdk:3.0 artifacts: expire_in: 1h paths: diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 4749374..3fb4ee1 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -1,7 +1,7 @@  Exe - netcoreapp2.2 + netcoreapp3.0 win-x64;linux-x64 derp.ico 4.1.0 @@ -20,33 +20,30 @@ true - - - 2.1.0 - - - + + + + - + - - - - - - - - - + + + + + + + + + - - - - - + + + + diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index 4671e07..7317274 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -129,7 +129,7 @@ namespace Geekbot.net var channel = (SocketGuildChannel) message.Channel; - var rowId = await _messageCounterDatabaseContext.Database.ExecuteSqlCommandAsync( + var rowId = await _messageCounterDatabaseContext.Database.ExecuteSqlRawAsync( "UPDATE \"Messages\" SET \"MessageCount\" = \"MessageCount\" + 1 WHERE \"GuildId\" = {0} AND \"UserId\" = {1}", channel.Guild.Id.AsLong(), message.Author.Id.AsLong() diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 1c07b9c..854efc4 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -1,13 +1,13 @@  - netcoreapp2.2 + netcoreapp3.0 false NU1701 xUnit1026 - - + + diff --git a/WikipediaApi/WikipediaApi.csproj b/WikipediaApi/WikipediaApi.csproj index 3e82c68..349fc0b 100644 --- a/WikipediaApi/WikipediaApi.csproj +++ b/WikipediaApi/WikipediaApi.csproj @@ -1,6 +1,6 @@  - netcoreapp2.2 + netcoreapp3.0 From cd04549834ca7eb4756a70866462c329b5f303ab Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 26 Oct 2019 22:20:22 +0200 Subject: [PATCH 306/553] Fix deployment to accomodate dotnet core 3 changes --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7e32f69..13858d2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -16,9 +16,9 @@ build: paths: - Geekbot.net/Binaries/ script: - - dotnet restore -s https://api.nuget.org/v3/index.json -s https://www.myget.org/F/discord-net/api/v3/index.json + - dotnet restore - dotnet test Tests - - dotnet publish --version-suffix ${CI_COMMIT_SHA:0:8} --configuration Release -o Binaries ./ + - dotnet publish --version-suffix ${CI_COMMIT_SHA:0:8} --configuration Release -o ./Geekbot.net/Binaries ./Geekbot.net/ sentry: stage: ops From dd9cf3c5d7ec02384f79b82e3bed054064ad300e Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 8 Feb 2020 15:32:58 +0100 Subject: [PATCH 307/553] Upgrade to dotnet core 3.1 --- .gitlab-ci.yml | 2 +- Geekbot.net/Geekbot.net.csproj | 34 ++++++++++++++++---------------- Tests/Tests.csproj | 8 ++++---- WikipediaApi/WikipediaApi.csproj | 4 ++-- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 13858d2..cffe539 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,7 +10,7 @@ before_script: build: stage: build - image: mcr.microsoft.com/dotnet/core/sdk:3.0 + image: mcr.microsoft.com/dotnet/core/sdk:3.1 artifacts: expire_in: 1h paths: diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 3fb4ee1..fe2f8cc 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -1,7 +1,7 @@  Exe - netcoreapp3.0 + netcoreapp3.1 win-x64;linux-x64 derp.ico 4.1.0 @@ -20,32 +20,32 @@ true - + - - + + - - - - - - - - + + + + + + + + - - - - + + + + - + diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 854efc4..235cc0b 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -1,14 +1,14 @@  - netcoreapp3.0 + netcoreapp3.1 false NU1701 xUnit1026 - - - + + + diff --git a/WikipediaApi/WikipediaApi.csproj b/WikipediaApi/WikipediaApi.csproj index 349fc0b..24c20f7 100644 --- a/WikipediaApi/WikipediaApi.csproj +++ b/WikipediaApi/WikipediaApi.csproj @@ -1,8 +1,8 @@  - netcoreapp3.0 + netcoreapp3.1 - + \ No newline at end of file From 21f813d342b847ce552fda6576f7a9459ccf3860 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 8 Feb 2020 15:42:42 +0100 Subject: [PATCH 308/553] Remove redundant code --- Geekbot.net/Commands/Randomness/Kanye/Kanye.cs | 2 -- Geekbot.net/Commands/Utils/Dice/Dice.cs | 3 +-- Geekbot.net/Database/DatabaseInitializer.cs | 1 - Geekbot.net/Handlers.cs | 2 +- Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs | 3 +-- Geekbot.net/Lib/GeekbotExitCode.cs | 2 +- Geekbot.net/Lib/Highscores/HighscoreManager.cs | 2 -- .../Lib/Localization/TranslationGuildContext.cs | 1 - .../Lib/ReactionListener/ReactionListener.cs | 4 +--- Geekbot.net/Program.cs | 15 ++++++++------- .../WebApi/Controllers/Commands/CommandDto.cs | 3 +-- Geekbot.net/WebApi/WebApiStartup.cs | 10 +++++----- 12 files changed, 19 insertions(+), 29 deletions(-) diff --git a/Geekbot.net/Commands/Randomness/Kanye/Kanye.cs b/Geekbot.net/Commands/Randomness/Kanye/Kanye.cs index 42a6ca7..dcd3bdc 100644 --- a/Geekbot.net/Commands/Randomness/Kanye/Kanye.cs +++ b/Geekbot.net/Commands/Randomness/Kanye/Kanye.cs @@ -3,9 +3,7 @@ using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Commands.Randomness.Dad; using Geekbot.net.Lib.ErrorHandling; -using Microsoft.AspNetCore.Hosting.Internal; using Newtonsoft.Json; namespace Geekbot.net.Commands.Randomness.Kanye diff --git a/Geekbot.net/Commands/Utils/Dice/Dice.cs b/Geekbot.net/Commands/Utils/Dice/Dice.cs index 6b95903..bc0244e 100644 --- a/Geekbot.net/Commands/Utils/Dice/Dice.cs +++ b/Geekbot.net/Commands/Utils/Dice/Dice.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; diff --git a/Geekbot.net/Database/DatabaseInitializer.cs b/Geekbot.net/Database/DatabaseInitializer.cs index 6adff44..582327f 100644 --- a/Geekbot.net/Database/DatabaseInitializer.cs +++ b/Geekbot.net/Database/DatabaseInitializer.cs @@ -2,7 +2,6 @@ using Geekbot.net.Database.LoggingAdapter; using Geekbot.net.Lib; using Geekbot.net.Lib.Logger; -using Microsoft.EntityFrameworkCore; using Npgsql.Logging; namespace Geekbot.net.Database diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index 7317274..13f523c 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -103,7 +103,7 @@ namespace Geekbot.net if (!(message.HasCharPrefix('!', ref argPos) || message.HasMentionPrefix(_client.CurrentUser, ref argPos))) return Task.CompletedTask; var context = new CommandContext(_client, message); - var commandExec = _commands.ExecuteAsync(context, argPos, _servicesProvider); + _commands.ExecuteAsync(context, argPos, _servicesProvider); _logger.Information(LogSource.Command, context.Message.Content.Split(" ")[0].Replace("!", ""), SimpleConextConverter.ConvertContext(context)); diff --git a/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs index 5323ee6..7c9d8ff 100644 --- a/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs @@ -3,7 +3,6 @@ using System.Net; using System.Threading.Tasks; using Discord.Commands; using Discord.Net; -using Geekbot.net.Lib.GlobalSettings; using Geekbot.net.Lib.Localization; using Geekbot.net.Lib.Logger; using SharpRaven; @@ -19,7 +18,7 @@ namespace Geekbot.net.Lib.ErrorHandling private readonly IRavenClient _raven; private readonly bool _errorsInChat; - public ErrorHandler(IGeekbotLogger logger, ITranslationHandler translation, IGlobalSettings globalSettings, bool errorsInChat) + public ErrorHandler(IGeekbotLogger logger, ITranslationHandler translation, bool errorsInChat) { _logger = logger; _translation = translation; diff --git a/Geekbot.net/Lib/GeekbotExitCode.cs b/Geekbot.net/Lib/GeekbotExitCode.cs index d68aa4a..130d435 100644 --- a/Geekbot.net/Lib/GeekbotExitCode.cs +++ b/Geekbot.net/Lib/GeekbotExitCode.cs @@ -1,6 +1,6 @@ namespace Geekbot.net.Lib { - public enum GeekbotExitCode : int + public enum GeekbotExitCode { // General Clean = 0, diff --git a/Geekbot.net/Lib/Highscores/HighscoreManager.cs b/Geekbot.net/Lib/Highscores/HighscoreManager.cs index f3b3a18..e668ff2 100644 --- a/Geekbot.net/Lib/Highscores/HighscoreManager.cs +++ b/Geekbot.net/Lib/Highscores/HighscoreManager.cs @@ -1,9 +1,7 @@ -using System; using System.Collections.Generic; using System.Linq; using Geekbot.net.Database; using Geekbot.net.Lib.Extensions; -using Geekbot.net.Lib.Logger; using Geekbot.net.Lib.UserRepository; namespace Geekbot.net.Lib.Highscores diff --git a/Geekbot.net/Lib/Localization/TranslationGuildContext.cs b/Geekbot.net/Lib/Localization/TranslationGuildContext.cs index 6181c04..fb65aa6 100644 --- a/Geekbot.net/Lib/Localization/TranslationGuildContext.cs +++ b/Geekbot.net/Lib/Localization/TranslationGuildContext.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; using System.Threading.Tasks; diff --git a/Geekbot.net/Lib/ReactionListener/ReactionListener.cs b/Geekbot.net/Lib/ReactionListener/ReactionListener.cs index 18490db..26a60d3 100644 --- a/Geekbot.net/Lib/ReactionListener/ReactionListener.cs +++ b/Geekbot.net/Lib/ReactionListener/ReactionListener.cs @@ -18,7 +18,7 @@ namespace Geekbot.net.Lib.ReactionListener LoadListeners(); } - private Task LoadListeners() + private void LoadListeners() { var ids = _redis.SetMembers("MessageIds"); _listener = new Dictionary>(); @@ -43,8 +43,6 @@ namespace Geekbot.net.Lib.ReactionListener } _listener.Add(messageId, emojiDict); } - - return Task.CompletedTask; } public bool IsListener(ulong id) diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 72ec6d5..4907431 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -21,6 +21,7 @@ using Geekbot.net.Lib.Media; using Geekbot.net.Lib.RandomNumberGenerator; using Geekbot.net.Lib.ReactionListener; using Geekbot.net.Lib.UserRepository; +using Geekbot.net.WebApi; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using WikipediaApi; @@ -125,8 +126,8 @@ namespace Geekbot.net var wikipediaClient = new WikipediaClient(); var randomNumberGenerator = new RandomNumberGenerator(); - _services.AddSingleton(_redis); - _services.AddSingleton(_userRepository); + _services.AddSingleton(_redis); + _services.AddSingleton(_userRepository); _services.AddSingleton(logger); _services.AddSingleton(levelCalc); _services.AddSingleton(emojiConverter); @@ -136,9 +137,9 @@ namespace Geekbot.net _services.AddSingleton(mtgManaConverter); _services.AddSingleton(wikipediaClient); _services.AddSingleton(randomNumberGenerator); - _services.AddSingleton(_globalSettings); - _services.AddTransient((e) => new HighscoreManager(_databaseInitializer.Initialize(), _userRepository)); - _services.AddTransient((e) => _databaseInitializer.Initialize()); + _services.AddSingleton(_globalSettings); + _services.AddTransient(e => new HighscoreManager(_databaseInitializer.Initialize(), _userRepository)); + _services.AddTransient(e => _databaseInitializer.Initialize()); logger.Information(LogSource.Geekbot, "Connecting to Discord"); @@ -162,7 +163,7 @@ namespace Geekbot.net _logger.Information(LogSource.Geekbot, "Registering Stuff"); var translationHandler = new TranslationHandler(_databaseInitializer.Initialize(), _logger); - var errorHandler = new ErrorHandler(_logger, translationHandler, _globalSettings, _runParameters.ExposeErrors); + var errorHandler = new ErrorHandler(_logger, translationHandler, _runParameters.ExposeErrors); var reactionListener = new ReactionListener(_redis.Db); _services.AddSingleton(errorHandler); _services.AddSingleton(translationHandler); @@ -207,7 +208,7 @@ namespace Geekbot.net { _logger.Information(LogSource.Api, "Starting Webserver"); var highscoreManager = new HighscoreManager(_databaseInitializer.Initialize(), _userRepository); - WebApi.WebApiStartup.StartWebApi(_logger, _runParameters, _commands, _databaseInitializer.Initialize(), _client, _globalSettings, highscoreManager); + WebApiStartup.StartWebApi(_logger, _runParameters, _commands, _databaseInitializer.Initialize(), _client, _globalSettings, highscoreManager); return Task.CompletedTask; } } diff --git a/Geekbot.net/WebApi/Controllers/Commands/CommandDto.cs b/Geekbot.net/WebApi/Controllers/Commands/CommandDto.cs index 68c4e74..981d0f2 100644 --- a/Geekbot.net/WebApi/Controllers/Commands/CommandDto.cs +++ b/Geekbot.net/WebApi/Controllers/Commands/CommandDto.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; namespace Geekbot.net.WebApi.Controllers.Commands { diff --git a/Geekbot.net/WebApi/WebApiStartup.cs b/Geekbot.net/WebApi/WebApiStartup.cs index 2459362..7d3adc9 100644 --- a/Geekbot.net/WebApi/WebApiStartup.cs +++ b/Geekbot.net/WebApi/WebApiStartup.cs @@ -29,11 +29,11 @@ namespace Geekbot.net.WebApi .ConfigureServices(services => { services.AddMvc(); - services.AddSingleton(commandService); - services.AddSingleton(databaseContext); - services.AddSingleton(client); - services.AddSingleton(globalSettings); - services.AddSingleton(highscoreManager); + services.AddSingleton(commandService); + services.AddSingleton(databaseContext); + services.AddSingleton(client); + services.AddSingleton(globalSettings); + services.AddSingleton(highscoreManager); services.AddCors(options => { options.AddPolicy("AllowSpecificOrigin", From 3568b61f38412abc4080474fcf2b6a6179c472be Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 8 Feb 2020 15:58:17 +0100 Subject: [PATCH 309/553] Use the new Csharp 8 features (pattern matching and using assignments) and cleanup some insignificant resparper complaints --- Geekbot.net/Commands/Admin/Mod.cs | 4 +- .../Integrations/MagicTheGathering.cs | 30 ++++---- .../UbranDictionary/UrbanDictionary.cs | 68 +++++++++---------- Geekbot.net/Commands/Randomness/Cat/Cat.cs | 31 +++++---- Geekbot.net/Commands/Randomness/CheckEm.cs | 2 +- .../Randomness/Chuck/ChuckNorrisJokes.cs | 28 ++++---- .../Commands/Randomness/Dad/DadJokes.cs | 28 ++++---- Geekbot.net/Commands/Randomness/Dog/Dog.cs | 30 ++++---- Geekbot.net/Commands/Randomness/Gdq.cs | 10 ++- .../Commands/Randomness/Kanye/Kanye.cs | 28 ++++---- Geekbot.net/Commands/Randomness/Ship.cs | 10 +-- Geekbot.net/Commands/User/Karma.cs | 4 +- Geekbot.net/Commands/User/Ranking/Rank.cs | 4 +- Geekbot.net/Commands/User/Stats.cs | 2 +- .../Commands/Utils/Changelog/Changelog.cs | 52 +++++++------- Geekbot.net/Commands/Utils/Quote/Quote.cs | 4 +- .../LoggingAdapter/NpgsqlLoggingAdapter.cs | 25 +++---- Geekbot.net/Lib/Clients/MalClient.cs | 2 +- .../DisableInDirectMessageAttribute.cs | 2 +- .../Lib/Converters/MtgManaConverter.cs | 2 +- .../Lib/Highscores/HighscoreManager.cs | 31 +++------ Geekbot.net/Lib/Levels/LevelCalc.cs | 11 +-- .../Lib/Logger/SimpleConextConverter.cs | 2 +- .../Lib/ReactionListener/ReactionListener.cs | 7 +- .../Callback/CallbackController.cs | 18 ++--- .../HighscoreControllerPostBodyDto.cs | 4 +- Geekbot.net/WebApi/Logging/AspLogger.cs | 28 +++----- 27 files changed, 217 insertions(+), 250 deletions(-) diff --git a/Geekbot.net/Commands/Admin/Mod.cs b/Geekbot.net/Commands/Admin/Mod.cs index 1188504..f4beb54 100644 --- a/Geekbot.net/Commands/Admin/Mod.cs +++ b/Geekbot.net/Commands/Admin/Mod.cs @@ -35,7 +35,7 @@ namespace Geekbot.net.Commands.Admin try { var userRepo = _userRepository.Get(user.Id); - if (userRepo != null && userRepo.UsedNames != null) + if (userRepo?.UsedNames != null) { var sb = new StringBuilder(); sb.AppendLine($":bust_in_silhouette: {user.Username} has been known as:"); @@ -50,7 +50,7 @@ namespace Geekbot.net.Commands.Admin catch (Exception e) { await _errorHandler.HandleCommandException(e, Context, - $"I don't have enough permissions do that"); + "I don't have enough permissions do that"); } } } diff --git a/Geekbot.net/Commands/Integrations/MagicTheGathering.cs b/Geekbot.net/Commands/Integrations/MagicTheGathering.cs index ef16fee..1075c46 100644 --- a/Geekbot.net/Commands/Integrations/MagicTheGathering.cs +++ b/Geekbot.net/Commands/Integrations/MagicTheGathering.cs @@ -41,9 +41,11 @@ namespace Geekbot.net.Commands.Integrations return; } - var eb = new EmbedBuilder(); - eb.Title = card.Name; - eb.Description = card.Type; + var eb = new EmbedBuilder + { + Title = card.Name, + Description = card.Type + }; if (card.Colors != null) eb.WithColor(GetColor(card.Colors)); @@ -74,21 +76,15 @@ namespace Geekbot.net.Commands.Integrations private Color GetColor(IEnumerable colors) { var color = colors.FirstOrDefault(); - switch (color) + return color switch { - case "Black": - return new Color(203, 194, 191); - case "White": - return new Color(255, 251, 213); - case "Blue": - return new Color(170, 224, 250); - case "Red": - return new Color(250, 170, 143); - case "Green": - return new Color(155, 211, 174); - default: - return new Color(204, 194, 212); - } + "Black" => new Color(203, 194, 191), + "White" => new Color(255, 251, 213), + "Blue" => new Color(170, 224, 250), + "Red" => new Color(250, 170, 143), + "Green" => new Color(155, 211, 174), + _ => new Color(204, 194, 212) + }; } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs b/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs index 254c2bb..1f33573 100644 --- a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs +++ b/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs @@ -25,43 +25,43 @@ namespace Geekbot.net.Commands.Integrations.UbranDictionary { try { - using (var client = new HttpClient()) + using var client = new HttpClient { - client.BaseAddress = new Uri("https://api.urbandictionary.com"); - var response = await client.GetAsync($"/v0/define?term={word}"); - response.EnsureSuccessStatusCode(); + BaseAddress = new Uri("https://api.urbandictionary.com") + }; + var response = await client.GetAsync($"/v0/define?term={word}"); + response.EnsureSuccessStatusCode(); - var stringResponse = await response.Content.ReadAsStringAsync(); - var definitions = JsonConvert.DeserializeObject(stringResponse); - if (definitions.List.Count == 0) - { - await ReplyAsync("That word hasn't been defined..."); - return; - } - - var definition = definitions.List.First(e => !string.IsNullOrWhiteSpace(e.Example)); - - var description = definition.Definition; - if (description.Length > 1801) - { - description = description.Substring(0, 1800) + " [...]"; - } - - var eb = new EmbedBuilder(); - eb.WithAuthor(new EmbedAuthorBuilder - { - Name = definition.Word, - Url = definition.Permalink - }); - eb.WithColor(new Color(239, 255, 0)); - if (!string.IsNullOrEmpty(definition.Definition)) eb.Description = description; - if (!string.IsNullOrEmpty(definition.Example)) eb.AddField("Example", definition.Example ?? "(no example given...)"); - if (!string.IsNullOrEmpty(definition.ThumbsUp)) eb.AddInlineField("Upvotes", definition.ThumbsUp); - if (!string.IsNullOrEmpty(definition.ThumbsDown)) eb.AddInlineField("Downvotes", definition.ThumbsDown); - if (definitions.Tags?.Length > 0) eb.AddField("Tags", string.Join(", ", definitions.Tags)); - - await ReplyAsync("", false, eb.Build()); + var stringResponse = await response.Content.ReadAsStringAsync(); + var definitions = JsonConvert.DeserializeObject(stringResponse); + if (definitions.List.Count == 0) + { + await ReplyAsync("That word hasn't been defined..."); + return; } + + var definition = definitions.List.First(e => !string.IsNullOrWhiteSpace(e.Example)); + + var description = definition.Definition; + if (description.Length > 1801) + { + description = description.Substring(0, 1800) + " [...]"; + } + + var eb = new EmbedBuilder(); + eb.WithAuthor(new EmbedAuthorBuilder + { + Name = definition.Word, + Url = definition.Permalink + }); + eb.WithColor(new Color(239, 255, 0)); + if (!string.IsNullOrEmpty(definition.Definition)) eb.Description = description; + if (!string.IsNullOrEmpty(definition.Example)) eb.AddField("Example", definition.Example ?? "(no example given...)"); + if (!string.IsNullOrEmpty(definition.ThumbsUp)) eb.AddInlineField("Upvotes", definition.ThumbsUp); + if (!string.IsNullOrEmpty(definition.ThumbsDown)) eb.AddInlineField("Downvotes", definition.ThumbsDown); + if (definitions.Tags?.Length > 0) eb.AddField("Tags", string.Join(", ", definitions.Tags)); + + await ReplyAsync("", false, eb.Build()); } catch (Exception e) { diff --git a/Geekbot.net/Commands/Randomness/Cat/Cat.cs b/Geekbot.net/Commands/Randomness/Cat/Cat.cs index 4d43a4c..3ac0764 100644 --- a/Geekbot.net/Commands/Randomness/Cat/Cat.cs +++ b/Geekbot.net/Commands/Randomness/Cat/Cat.cs @@ -23,24 +23,27 @@ namespace Geekbot.net.Commands.Randomness.Cat { try { - using (var client = new HttpClient()) + + try { - try + using var client = new HttpClient { - client.BaseAddress = new Uri("https://aws.random.cat"); - var response = await client.GetAsync("/meow"); - response.EnsureSuccessStatusCode(); + BaseAddress = new Uri("https://aws.random.cat") + }; + var response = await client.GetAsync("/meow"); + response.EnsureSuccessStatusCode(); - var stringResponse = await response.Content.ReadAsStringAsync(); - var catFile = JsonConvert.DeserializeObject(stringResponse); - var eb = new EmbedBuilder(); - eb.ImageUrl = catFile.File; - await ReplyAsync("", false, eb.Build()); - } - catch + var stringResponse = await response.Content.ReadAsStringAsync(); + var catFile = JsonConvert.DeserializeObject(stringResponse); + var eb = new EmbedBuilder { - await ReplyAsync("Seems like the dog cought the cat (error occured)"); - } + ImageUrl = catFile.File + }; + await ReplyAsync("", false, eb.Build()); + } + catch + { + await ReplyAsync("Seems like the dog cought the cat (error occured)"); } } catch (Exception e) diff --git a/Geekbot.net/Commands/Randomness/CheckEm.cs b/Geekbot.net/Commands/Randomness/CheckEm.cs index f8191ad..0596872 100644 --- a/Geekbot.net/Commands/Randomness/CheckEm.cs +++ b/Geekbot.net/Commands/Randomness/CheckEm.cs @@ -61,7 +61,7 @@ namespace Geekbot.net.Commands.Randomness while (num > 0) { listOfInts.Add(num % 10); - num = num / 10; + num /= 10; } listOfInts.Reverse(); diff --git a/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs b/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs index 07ea41f..5c28a9a 100644 --- a/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs +++ b/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs @@ -23,23 +23,21 @@ namespace Geekbot.net.Commands.Randomness.Chuck { try { - using (var client = new HttpClient()) + try { - try - { - client.DefaultRequestHeaders.Accept.Clear(); - client.DefaultRequestHeaders.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); - var response = await client.GetAsync("https://api.chucknorris.io/jokes/random"); - response.EnsureSuccessStatusCode(); + using var client = new HttpClient(); + client.DefaultRequestHeaders.Accept.Clear(); + client.DefaultRequestHeaders.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); + var response = await client.GetAsync("https://api.chucknorris.io/jokes/random"); + response.EnsureSuccessStatusCode(); - var stringResponse = await response.Content.ReadAsStringAsync(); - var data = JsonConvert.DeserializeObject(stringResponse); - await ReplyAsync(data.Value); - } - catch (HttpRequestException) - { - await ReplyAsync("Api down..."); - } + var stringResponse = await response.Content.ReadAsStringAsync(); + var data = JsonConvert.DeserializeObject(stringResponse); + await ReplyAsync(data.Value); + } + catch (HttpRequestException) + { + await ReplyAsync("Api down..."); } } catch (Exception e) diff --git a/Geekbot.net/Commands/Randomness/Dad/DadJokes.cs b/Geekbot.net/Commands/Randomness/Dad/DadJokes.cs index 2c51781..bcedd96 100644 --- a/Geekbot.net/Commands/Randomness/Dad/DadJokes.cs +++ b/Geekbot.net/Commands/Randomness/Dad/DadJokes.cs @@ -23,23 +23,21 @@ namespace Geekbot.net.Commands.Randomness.Dad { try { - using (var client = new HttpClient()) + try { - try - { - client.DefaultRequestHeaders.Accept.Clear(); - client.DefaultRequestHeaders.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); - var response = await client.GetAsync("https://icanhazdadjoke.com/"); - response.EnsureSuccessStatusCode(); + using var client = new HttpClient(); + client.DefaultRequestHeaders.Accept.Clear(); + client.DefaultRequestHeaders.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); + var response = await client.GetAsync("https://icanhazdadjoke.com/"); + response.EnsureSuccessStatusCode(); - var stringResponse = await response.Content.ReadAsStringAsync(); - var data = JsonConvert.DeserializeObject(stringResponse); - await ReplyAsync(data.Joke); - } - catch (HttpRequestException) - { - await ReplyAsync("Api down..."); - } + var stringResponse = await response.Content.ReadAsStringAsync(); + var data = JsonConvert.DeserializeObject(stringResponse); + await ReplyAsync(data.Joke); + } + catch (HttpRequestException) + { + await ReplyAsync("Api down..."); } } catch (Exception e) diff --git a/Geekbot.net/Commands/Randomness/Dog/Dog.cs b/Geekbot.net/Commands/Randomness/Dog/Dog.cs index 176cbad..d7404c6 100644 --- a/Geekbot.net/Commands/Randomness/Dog/Dog.cs +++ b/Geekbot.net/Commands/Randomness/Dog/Dog.cs @@ -23,24 +23,26 @@ namespace Geekbot.net.Commands.Randomness.Dog { try { - using (var client = new HttpClient()) + try { - try + using var client = new HttpClient { - client.BaseAddress = new Uri("http://random.dog"); - var response = await client.GetAsync("/woof.json"); - response.EnsureSuccessStatusCode(); + BaseAddress = new Uri("http://random.dog") + }; + var response = await client.GetAsync("/woof.json"); + response.EnsureSuccessStatusCode(); - var stringResponse = await response.Content.ReadAsStringAsync(); - var dogFile = JsonConvert.DeserializeObject(stringResponse); - var eb = new EmbedBuilder(); - eb.ImageUrl = dogFile.Url; - await ReplyAsync("", false, eb.Build()); - } - catch (HttpRequestException e) + var stringResponse = await response.Content.ReadAsStringAsync(); + var dogFile = JsonConvert.DeserializeObject(stringResponse); + var eb = new EmbedBuilder { - await ReplyAsync($"Seems like the dog got lost (error occured)\r\n{e.Message}"); - } + ImageUrl = dogFile.Url + }; + await ReplyAsync("", false, eb.Build()); + } + catch (HttpRequestException e) + { + await ReplyAsync($"Seems like the dog got lost (error occured)\r\n{e.Message}"); } } catch (Exception e) diff --git a/Geekbot.net/Commands/Randomness/Gdq.cs b/Geekbot.net/Commands/Randomness/Gdq.cs index 2685b33..4c16bed 100644 --- a/Geekbot.net/Commands/Randomness/Gdq.cs +++ b/Geekbot.net/Commands/Randomness/Gdq.cs @@ -21,13 +21,11 @@ namespace Geekbot.net.Commands.Randomness { try { - using (var client = new WebClient()) - { - var url = new Uri("http://taskinoz.com/gdq/api/"); - var response = client.DownloadString(url); + using var client = new WebClient(); + var url = new Uri("http://taskinoz.com/gdq/api/"); + var response = client.DownloadString(url); - await ReplyAsync(response); - } + await ReplyAsync(response); } catch (Exception e) { diff --git a/Geekbot.net/Commands/Randomness/Kanye/Kanye.cs b/Geekbot.net/Commands/Randomness/Kanye/Kanye.cs index dcd3bdc..36f1d1a 100644 --- a/Geekbot.net/Commands/Randomness/Kanye/Kanye.cs +++ b/Geekbot.net/Commands/Randomness/Kanye/Kanye.cs @@ -23,23 +23,21 @@ namespace Geekbot.net.Commands.Randomness.Kanye { try { - using (var client = new HttpClient()) + try { - try - { - client.DefaultRequestHeaders.Accept.Clear(); - client.DefaultRequestHeaders.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); - var response = await client.GetAsync("https://api.kanye.rest/"); - response.EnsureSuccessStatusCode(); + using var client = new HttpClient(); + client.DefaultRequestHeaders.Accept.Clear(); + client.DefaultRequestHeaders.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); + var response = await client.GetAsync("https://api.kanye.rest/"); + response.EnsureSuccessStatusCode(); - var stringResponse = await response.Content.ReadAsStringAsync(); - var data = JsonConvert.DeserializeObject(stringResponse); - await ReplyAsync(data.Quote); - } - catch (HttpRequestException) - { - await ReplyAsync("Api down..."); - } + var stringResponse = await response.Content.ReadAsStringAsync(); + var data = JsonConvert.DeserializeObject(stringResponse); + await ReplyAsync(data.Quote); + } + catch (HttpRequestException) + { + await ReplyAsync("Api down..."); } } catch (Exception e) diff --git a/Geekbot.net/Commands/Randomness/Ship.cs b/Geekbot.net/Commands/Randomness/Ship.cs index 2571891..bf52a73 100644 --- a/Geekbot.net/Commands/Randomness/Ship.cs +++ b/Geekbot.net/Commands/Randomness/Ship.cs @@ -56,8 +56,8 @@ namespace Geekbot.net.Commands.Randomness } var reply = ":heartpulse: **Matchmaking** :heartpulse:\r\n"; - reply = reply + $":two_hearts: {user1.Mention} :heart: {user2.Mention} :two_hearts:\r\n"; - reply = reply + $"0% [{BlockCounter(shippingRate)}] 100% - {DeterminateSuccess(shippingRate)}"; + reply += $":two_hearts: {user1.Mention} :heart: {user2.Mention} :two_hearts:\r\n"; + reply += $"0% [{BlockCounter(shippingRate)}] 100% - {DeterminateSuccess(shippingRate)}"; await ReplyAsync(reply); } catch (Exception e) @@ -87,13 +87,13 @@ namespace Geekbot.net.Commands.Randomness for (var i = 1; i <= 10; i++) if (i <= amount) { - blocks = blocks + ":white_medium_small_square:"; + blocks += ":white_medium_small_square:"; if (i == amount) - blocks = blocks + $" {rate}% "; + blocks += $" {rate}% "; } else { - blocks = blocks + ":black_medium_small_square:"; + blocks += ":black_medium_small_square:"; } return blocks; diff --git a/Geekbot.net/Commands/User/Karma.cs b/Geekbot.net/Commands/User/Karma.cs index ed221ff..bf85c91 100644 --- a/Geekbot.net/Commands/User/Karma.cs +++ b/Geekbot.net/Commands/User/Karma.cs @@ -46,7 +46,7 @@ namespace Geekbot.net.Commands.User else { var target = await GetUser(user.Id); - target.Karma = target.Karma + 1; + target.Karma += 1; SetUser(target); actor.TimeOut = DateTimeOffset.Now; @@ -93,7 +93,7 @@ namespace Geekbot.net.Commands.User else { var target = await GetUser(user.Id); - target.Karma = target.Karma - 1; + target.Karma -= 1; SetUser(target); actor.TimeOut = DateTimeOffset.Now; diff --git a/Geekbot.net/Commands/User/Ranking/Rank.cs b/Geekbot.net/Commands/User/Ranking/Rank.cs index 0ad21d5..9021b4e 100644 --- a/Geekbot.net/Commands/User/Ranking/Rank.cs +++ b/Geekbot.net/Commands/User/Ranking/Rank.cs @@ -74,7 +74,7 @@ namespace Geekbot.net.Commands.User.Ranking return; } - int guildMessages = 0; + var guildMessages = 0; if (type == HighscoreTypes.messages) { guildMessages = _database.Messages @@ -99,7 +99,7 @@ namespace Geekbot.net.Commands.User.Ranking : $"**{user.Key.Id}**"); replyBuilder.Append(type == HighscoreTypes.messages - ? $" - {user.Value} {type} - {Math.Round((double) (100 * user.Value) / guildMessages, digits: 2)}%\n" + ? $" - {user.Value} {type} - {Math.Round((double) (100 * user.Value) / guildMessages, 2)}%\n" : $" - {user.Value} {type}\n"); highscorePlace++; diff --git a/Geekbot.net/Commands/User/Stats.cs b/Geekbot.net/Commands/User/Stats.cs index 6ddf7d4..05ea324 100644 --- a/Geekbot.net/Commands/User/Stats.cs +++ b/Geekbot.net/Commands/User/Stats.cs @@ -51,7 +51,7 @@ namespace Geekbot.net.Commands.User var level = _levelCalc.GetLevel(messages); - var percent = Math.Round((double) (100 * messages) / guildMessages, digits: 2); + var percent = Math.Round((double) (100 * messages) / guildMessages, 2); var cookies = _database.Cookies ?.FirstOrDefault(e => e.GuildId.Equals(Context.Guild.Id.AsLong()) && e.UserId.Equals(userInfo.Id.AsLong())) diff --git a/Geekbot.net/Commands/Utils/Changelog/Changelog.cs b/Geekbot.net/Commands/Utils/Changelog/Changelog.cs index adcc9a3..02981df 100644 --- a/Geekbot.net/Commands/Utils/Changelog/Changelog.cs +++ b/Geekbot.net/Commands/Utils/Changelog/Changelog.cs @@ -29,34 +29,34 @@ namespace Geekbot.net.Commands.Utils.Changelog { try { - using (var client = new HttpClient()) + using var client = new HttpClient { - client.BaseAddress = new Uri("https://api.github.com"); - client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", - "http://developer.github.com/v3/#user-agent-required"); - var response = await client.GetAsync("/repos/pizzaandcoffee/geekbot.net/commits"); - response.EnsureSuccessStatusCode(); + BaseAddress = new Uri("https://api.github.com") + }; + client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", + "http://developer.github.com/v3/#user-agent-required"); + var response = await client.GetAsync("/repos/pizzaandcoffee/geekbot.net/commits"); + response.EnsureSuccessStatusCode(); - var stringResponse = await response.Content.ReadAsStringAsync(); - var commits = JsonConvert.DeserializeObject>(stringResponse); - var eb = new EmbedBuilder(); - eb.WithColor(new Color(143, 165, 102)); - eb.WithAuthor(new EmbedAuthorBuilder - { - IconUrl = _client.CurrentUser.GetAvatarUrl(), - Name = "Latest Updates", - Url = "https://geekbot.pizzaandcoffee.rocks/updates" - }); - var sb = new StringBuilder(); - foreach (var commit in commits.Take(10)) - sb.AppendLine($"- {commit.Commit.Message} ({commit.Commit.Author.Date:yyyy-MM-dd})"); - eb.Description = sb.ToString(); - eb.WithFooter(new EmbedFooterBuilder - { - Text = $"List generated from github commits on {DateTime.Now:yyyy-MM-dd}" - }); - await ReplyAsync("", false, eb.Build()); - } + var stringResponse = await response.Content.ReadAsStringAsync(); + var commits = JsonConvert.DeserializeObject>(stringResponse); + var eb = new EmbedBuilder(); + eb.WithColor(new Color(143, 165, 102)); + eb.WithAuthor(new EmbedAuthorBuilder + { + IconUrl = _client.CurrentUser.GetAvatarUrl(), + Name = "Latest Updates", + Url = "https://geekbot.pizzaandcoffee.rocks/updates" + }); + var sb = new StringBuilder(); + foreach (var commit in commits.Take(10)) + sb.AppendLine($"- {commit.Commit.Message} ({commit.Commit.Author.Date:yyyy-MM-dd})"); + eb.Description = sb.ToString(); + eb.WithFooter(new EmbedFooterBuilder + { + Text = $"List generated from github commits on {DateTime.Now:yyyy-MM-dd}" + }); + await ReplyAsync("", false, eb.Build()); } catch (Exception e) { diff --git a/Geekbot.net/Commands/Utils/Quote/Quote.cs b/Geekbot.net/Commands/Utils/Quote/Quote.cs index f06c6ab..e9c4706 100644 --- a/Geekbot.net/Commands/Utils/Quote/Quote.cs +++ b/Geekbot.net/Commands/Utils/Quote/Quote.cs @@ -46,7 +46,7 @@ namespace Geekbot.net.Commands.Utils.Quote return; } - var random = _randomNumberGenerator.Next(0, s.Count()); + var random = _randomNumberGenerator.Next(0, s.Count); var quote = s[random]; var embed = QuoteBuilder(quote); @@ -238,7 +238,7 @@ namespace Geekbot.net.Commands.Utils.Quote var last = _database.Quotes.Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())) .OrderByDescending(e => e.InternalId).FirstOrDefault(); - int internalId = 1; + var internalId = 1; if (last != null) internalId = last.InternalId + 1; return new QuoteModel() { diff --git a/Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingAdapter.cs b/Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingAdapter.cs index e8850cd..ceebd56 100644 --- a/Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingAdapter.cs +++ b/Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingAdapter.cs @@ -54,23 +54,16 @@ namespace Geekbot.net.Database.LoggingAdapter private static LogLevel ToGeekbotLogLevel(NpgsqlLogLevel level) { - switch (level) + return level switch { - case NpgsqlLogLevel.Trace: - return LogLevel.Trace; - case NpgsqlLogLevel.Debug: - return LogLevel.Debug; - case NpgsqlLogLevel.Info: - return LogLevel.Info; - case NpgsqlLogLevel.Warn: - return LogLevel.Warn; - case NpgsqlLogLevel.Error: - return LogLevel.Error; - case NpgsqlLogLevel.Fatal: - return LogLevel.Fatal; - default: - throw new ArgumentOutOfRangeException(nameof(level)); - } + NpgsqlLogLevel.Trace => LogLevel.Trace, + NpgsqlLogLevel.Debug => LogLevel.Debug, + NpgsqlLogLevel.Info => LogLevel.Info, + NpgsqlLogLevel.Warn => LogLevel.Warn, + NpgsqlLogLevel.Error => LogLevel.Error, + NpgsqlLogLevel.Fatal => LogLevel.Fatal, + _ => throw new ArgumentOutOfRangeException(nameof(level)) + }; } } } \ No newline at end of file diff --git a/Geekbot.net/Lib/Clients/MalClient.cs b/Geekbot.net/Lib/Clients/MalClient.cs index a014cf1..8e5d950 100644 --- a/Geekbot.net/Lib/Clients/MalClient.cs +++ b/Geekbot.net/Lib/Clients/MalClient.cs @@ -22,7 +22,7 @@ namespace Geekbot.net.Lib.Clients ReloadClient(); } - public bool ReloadClient() + private bool ReloadClient() { var malCredentials = _globalSettings.GetKey("MalCredentials"); if (!string.IsNullOrEmpty(malCredentials)) diff --git a/Geekbot.net/Lib/CommandPreconditions/DisableInDirectMessageAttribute.cs b/Geekbot.net/Lib/CommandPreconditions/DisableInDirectMessageAttribute.cs index 110b69b..2bb5cfd 100644 --- a/Geekbot.net/Lib/CommandPreconditions/DisableInDirectMessageAttribute.cs +++ b/Geekbot.net/Lib/CommandPreconditions/DisableInDirectMessageAttribute.cs @@ -4,7 +4,7 @@ using Discord.Commands; namespace Geekbot.net.Lib.CommandPreconditions { - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] public class DisableInDirectMessageAttribute : PreconditionAttribute { public override Task CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services) diff --git a/Geekbot.net/Lib/Converters/MtgManaConverter.cs b/Geekbot.net/Lib/Converters/MtgManaConverter.cs index c29e1e0..31a2db0 100644 --- a/Geekbot.net/Lib/Converters/MtgManaConverter.cs +++ b/Geekbot.net/Lib/Converters/MtgManaConverter.cs @@ -7,7 +7,7 @@ namespace Geekbot.net.Lib.Converters { public class MtgManaConverter : IMtgManaConverter { - private Dictionary _manaDict; + private readonly Dictionary _manaDict; public MtgManaConverter() { diff --git a/Geekbot.net/Lib/Highscores/HighscoreManager.cs b/Geekbot.net/Lib/Highscores/HighscoreManager.cs index e668ff2..8218532 100644 --- a/Geekbot.net/Lib/Highscores/HighscoreManager.cs +++ b/Geekbot.net/Lib/Highscores/HighscoreManager.cs @@ -20,26 +20,15 @@ namespace Geekbot.net.Lib.Highscores public Dictionary GetHighscoresWithUserData(HighscoreTypes type, ulong guildId, int amount) { - Dictionary list; - switch (type) + var list = type switch { - case HighscoreTypes.messages: - list = GetMessageList(guildId, amount); - break; - case HighscoreTypes.karma: - list = GetKarmaList(guildId, amount); - break; - case HighscoreTypes.rolls: - list = GetRollsList(guildId, amount); - break; - case HighscoreTypes.cookies: - list = GetCookiesList(guildId, amount); - break; - default: - list = new Dictionary(); - break; - } - + HighscoreTypes.messages => GetMessageList(guildId, amount), + HighscoreTypes.karma => GetKarmaList(guildId, amount), + HighscoreTypes.rolls => GetRollsList(guildId, amount), + HighscoreTypes.cookies => GetCookiesList(guildId, amount), + _ => new Dictionary() + }; + if (!list.Any()) { throw new HighscoreListEmptyException($"No {type} found for guild {guildId}"); @@ -103,8 +92,8 @@ namespace Geekbot.net.Lib.Highscores .Take(amount) .ToDictionary(key => key.UserId.AsUlong(), key => key.Rolls); } - - public Dictionary GetCookiesList(ulong guildId, int amount) + + private Dictionary GetCookiesList(ulong guildId, int amount) { return _database.Cookies .Where(k => k.GuildId.Equals(guildId.AsLong())) diff --git a/Geekbot.net/Lib/Levels/LevelCalc.cs b/Geekbot.net/Lib/Levels/LevelCalc.cs index f5b6b80..74747b7 100644 --- a/Geekbot.net/Lib/Levels/LevelCalc.cs +++ b/Geekbot.net/Lib/Levels/LevelCalc.cs @@ -1,11 +1,12 @@ using System; using System.Collections.Generic; +using System.Linq; namespace Geekbot.net.Lib.Levels { public class LevelCalc : ILevelCalc { - private int[] _levels; + private readonly int[] _levels; public LevelCalc() { @@ -21,13 +22,7 @@ namespace Geekbot.net.Lib.Levels public int GetLevel(int? messages) { - var returnVal = 1; - foreach (var level in _levels) - { - if (level > messages) break; - returnVal++; - } - return returnVal; + return 1 + _levels.TakeWhile(level => !(level > messages)).Count(); } } } \ No newline at end of file diff --git a/Geekbot.net/Lib/Logger/SimpleConextConverter.cs b/Geekbot.net/Lib/Logger/SimpleConextConverter.cs index 8b8b0ed..d01da67 100644 --- a/Geekbot.net/Lib/Logger/SimpleConextConverter.cs +++ b/Geekbot.net/Lib/Logger/SimpleConextConverter.cs @@ -37,7 +37,7 @@ namespace Geekbot.net.Lib.Logger } public static MessageDto ConvertSocketMessage(SocketMessage message, bool isPrivate = false) { - SocketGuildChannel channel = isPrivate ? null : (SocketGuildChannel) message.Channel; + var channel = isPrivate ? null : (SocketGuildChannel) message.Channel; return new MessageDto { Message = new MessageDto.MessageContent diff --git a/Geekbot.net/Lib/ReactionListener/ReactionListener.cs b/Geekbot.net/Lib/ReactionListener/ReactionListener.cs index 26a60d3..2349028 100644 --- a/Geekbot.net/Lib/ReactionListener/ReactionListener.cs +++ b/Geekbot.net/Lib/ReactionListener/ReactionListener.cs @@ -63,8 +63,11 @@ namespace Geekbot.net.Lib.ReactionListener _listener[messageId].Add(emoji, role.Id); return Task.CompletedTask; } - var dict = new Dictionary(); - dict.Add(emoji, role.Id); + + var dict = new Dictionary + { + {emoji, role.Id} + }; _listener.Add(messageId, dict); return Task.CompletedTask; } diff --git a/Geekbot.net/WebApi/Controllers/Callback/CallbackController.cs b/Geekbot.net/WebApi/Controllers/Callback/CallbackController.cs index 58bdb83..78fb38d 100644 --- a/Geekbot.net/WebApi/Controllers/Callback/CallbackController.cs +++ b/Geekbot.net/WebApi/Controllers/Callback/CallbackController.cs @@ -32,14 +32,16 @@ namespace Geekbot.net.WebApi.Controllers.Callback var accessToken = _globalSettings.GetKey("OAuthToken"); var callbackUrl = _globalSettings.GetKey("OAuthCallbackUrl"); - var form = new Dictionary(); - form.Add("client_id", appInfo.Id.ToString()); - form.Add("client_secret", accessToken); - form.Add("grant_type", "authorization_code"); - form.Add("code", code); - form.Add("scope", "identify email guilds"); - form.Add("redirect_uri", callbackUrl); - + var form = new Dictionary + { + {"client_id", appInfo.Id.ToString()}, + {"client_secret", accessToken}, + {"grant_type", "authorization_code"}, + {"code", code}, + {"scope", "identify email guilds"}, + {"redirect_uri", callbackUrl} + }; + client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded")); var result = await client.PostAsync("/api/oauth2/token", new FormUrlEncodedContent(form)); result.EnsureSuccessStatusCode(); diff --git a/Geekbot.net/WebApi/Controllers/Highscores/HighscoreControllerPostBodyDto.cs b/Geekbot.net/WebApi/Controllers/Highscores/HighscoreControllerPostBodyDto.cs index 22da3c7..6e7aec3 100644 --- a/Geekbot.net/WebApi/Controllers/Highscores/HighscoreControllerPostBodyDto.cs +++ b/Geekbot.net/WebApi/Controllers/Highscores/HighscoreControllerPostBodyDto.cs @@ -8,9 +8,9 @@ namespace Geekbot.net.WebApi.Controllers.Highscores [Required] public ulong GuildId { get; set; } - public HighscoreTypes Type { get; set; } = HighscoreTypes.messages; + public HighscoreTypes Type { get; } = HighscoreTypes.messages; [Range(1, 150)] - public int Amount { get; set; } = 50; + public int Amount { get; } = 50; } } \ No newline at end of file diff --git a/Geekbot.net/WebApi/Logging/AspLogger.cs b/Geekbot.net/WebApi/Logging/AspLogger.cs index 3316150..5899b26 100644 --- a/Geekbot.net/WebApi/Logging/AspLogger.cs +++ b/Geekbot.net/WebApi/Logging/AspLogger.cs @@ -55,25 +55,17 @@ namespace Geekbot.net.WebApi.Logging private static NLog.LogLevel ToGeekbotLogLevel(LogLevel level) { - switch (level) + return level switch { - case LogLevel.Trace: - return NLog.LogLevel.Trace; - case LogLevel.Debug: - return NLog.LogLevel.Debug; - case LogLevel.Information: - return NLog.LogLevel.Info; - case LogLevel.Warning: - return NLog.LogLevel.Warn; - case LogLevel.Error: - return NLog.LogLevel.Error; - case LogLevel.Critical: - return NLog.LogLevel.Fatal; - case LogLevel.None: - return NLog.LogLevel.Off; - default: - throw new ArgumentOutOfRangeException(nameof(level)); - } + LogLevel.Trace => NLog.LogLevel.Trace, + LogLevel.Debug => NLog.LogLevel.Debug, + LogLevel.Information => NLog.LogLevel.Info, + LogLevel.Warning => NLog.LogLevel.Warn, + LogLevel.Error => NLog.LogLevel.Error, + LogLevel.Critical => NLog.LogLevel.Fatal, + LogLevel.None => NLog.LogLevel.Off, + _ => throw new ArgumentOutOfRangeException(nameof(level)) + }; } } } \ No newline at end of file From 3bd7274d68c633599b3fbcbd4eff10f9c1f466aa Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 4 Apr 2020 21:21:15 +0200 Subject: [PATCH 310/553] Remove some unnecessary text from the dice command --- Geekbot.net/Commands/Utils/Dice/Dice.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Geekbot.net/Commands/Utils/Dice/Dice.cs b/Geekbot.net/Commands/Utils/Dice/Dice.cs index bc0244e..c335982 100644 --- a/Geekbot.net/Commands/Utils/Dice/Dice.cs +++ b/Geekbot.net/Commands/Utils/Dice/Dice.cs @@ -67,7 +67,6 @@ namespace Geekbot.net.Commands.Utils.Dice rep.Append("**Result:** "); var resultStrings = new List(); var total = 0; - var extraText = ""; foreach (var dice in dices) { var results = new List(); @@ -76,8 +75,6 @@ namespace Geekbot.net.Commands.Utils.Dice var roll = _randomNumberGenerator.Next(1, dice.Sides); total += roll; results.Add(roll); - if (roll == dice.Sides) extraText = "**Critical Hit!**"; - if (roll == 1) extraText = "**Critical Fail!**"; } resultStrings.Add($"{dice.DiceType} ({string.Join(",", results)})"); @@ -92,7 +89,6 @@ namespace Geekbot.net.Commands.Utils.Dice rep.AppendLine(); rep.AppendLine($"**Total:** {total}"); - if (extraText != "") rep.AppendLine(extraText); await ReplyAsync(rep.ToString()); } From f12bdcf4cd1d1794a22b7997d3ef7416092f66e8 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 4 Apr 2020 23:05:18 +0200 Subject: [PATCH 311/553] Translate the ship command --- Geekbot.net/Commands/Randomness/Ship.cs | 33 +++++++++++-------- Geekbot.net/Lib/Localization/Translations.yml | 22 ++++++++++++- 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/Geekbot.net/Commands/Randomness/Ship.cs b/Geekbot.net/Commands/Randomness/Ship.cs index bf52a73..d5386d4 100644 --- a/Geekbot.net/Commands/Randomness/Ship.cs +++ b/Geekbot.net/Commands/Randomness/Ship.cs @@ -7,6 +7,7 @@ using Geekbot.net.Database; using Geekbot.net.Database.Models; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; +using Geekbot.net.Lib.Localization; using Geekbot.net.Lib.RandomNumberGenerator; namespace Geekbot.net.Commands.Randomness @@ -15,13 +16,15 @@ namespace Geekbot.net.Commands.Randomness { private readonly IErrorHandler _errorHandler; private readonly IRandomNumberGenerator _randomNumberGenerator; + private readonly ITranslationHandler _translation; private readonly DatabaseContext _database; - public Ship(DatabaseContext database, IErrorHandler errorHandler, IRandomNumberGenerator randomNumberGenerator) + public Ship(DatabaseContext database, IErrorHandler errorHandler, IRandomNumberGenerator randomNumberGenerator, ITranslationHandler translation) { _database = database; _errorHandler = errorHandler; _randomNumberGenerator = randomNumberGenerator; + _translation = translation; } [Command("Ship", RunMode = RunMode.Async)] @@ -55,9 +58,11 @@ namespace Geekbot.net.Commands.Randomness shippingRate = dbval.Strength; } - var reply = ":heartpulse: **Matchmaking** :heartpulse:\r\n"; + var transContext = await _translation.GetGuildContext(Context); + + var reply = $":heartpulse: **{transContext.GetString("Matchmaking")}** :heartpulse:\r\n"; reply += $":two_hearts: {user1.Mention} :heart: {user2.Mention} :two_hearts:\r\n"; - reply += $"0% [{BlockCounter(shippingRate)}] 100% - {DeterminateSuccess(shippingRate)}"; + reply += $"0% [{BlockCounter(shippingRate)}] 100% - {DeterminateSuccess(shippingRate, transContext)}"; await ReplyAsync(reply); } catch (Exception e) @@ -66,22 +71,22 @@ namespace Geekbot.net.Commands.Randomness } } - private string DeterminateSuccess(int rate) + private string DeterminateSuccess(int rate, TranslationGuildContext transContext) { - if (rate < 20) - return "Not gonna happen"; - if (rate >= 20 && rate < 40) - return "Not such a good idea"; - if (rate >= 40 && rate < 60) - return "There might be a chance"; - if (rate >= 60 && rate < 80) - return "Almost a match, but could work"; - return rate >= 80 ? "It's a match" : "a"; + return (rate / 20) switch + { + 0 => transContext.GetString("NotGonnaToHappen"), + 1 => transContext.GetString("NotSuchAGoodIdea"), + 2 => transContext.GetString("ThereMightBeAChance"), + 3 => transContext.GetString("CouldWork"), + 4 => transContext.GetString("ItsAMatch"), + _ => "nope" + }; } private string BlockCounter(int rate) { - var amount = Math.Floor(decimal.Floor(rate / 10)); + var amount = rate / 10; Console.WriteLine(amount); var blocks = ""; for (var i = 1; i <= 10; i++) diff --git a/Geekbot.net/Lib/Localization/Translations.yml b/Geekbot.net/Lib/Localization/Translations.yml index 730ea40..5744741 100644 --- a/Geekbot.net/Lib/Localization/Translations.yml +++ b/Geekbot.net/Lib/Localization/Translations.yml @@ -175,4 +175,24 @@ rank: CHDE: ":warning: Ich han nid alli benutzername gfunde. villiicht hend sie de server verlah?\n" HighscoresFor: EN: ":bar_chart: **{0} Highscore for {1}**" - CHDE: ":bar_chart: **{0} Highscore für {1}**" \ No newline at end of file + CHDE: ":bar_chart: **{0} Highscore für {1}**" +ship: + Matchmaking: + EN: "Matchmaking" + CHDE: "Verkupple" + NotGonnaToHappen: + EN: "Not gonna happen" + CHDE: "Wird nöd klappe" + NotSuchAGoodIdea: + EN: "Not such a good idea" + CHDE: "Nöd so ä gueti idee" + ThereMightBeAChance: + EN: "There might be a chance" + CHDE: "Es gid eventuel ä chance" + CouldWork: + EN: "Almost a match" + CHDE: "Fasch en match" + ItsAMatch: + EN: "It's a match" + CHDE: "Es isch es traumpaar" + \ No newline at end of file From 77b3d612f2da6dbbcf8fca008deef0c307962583 Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 6 Apr 2020 15:35:28 +0200 Subject: [PATCH 312/553] Re-use the database connection everywhere --- Geekbot.net/Handlers.cs | 15 +++++---------- Geekbot.net/Program.cs | 23 ++++++++++++----------- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index 13f523c..48bf966 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -9,7 +9,6 @@ using Discord.Rest; using Discord.WebSocket; using Geekbot.net.Database; using Geekbot.net.Database.Models; -using Geekbot.net.Lib.AlmostRedis; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Logger; using Geekbot.net.Lib.ReactionListener; @@ -23,24 +22,20 @@ namespace Geekbot.net private readonly DatabaseContext _database; private readonly IDiscordClient _client; private readonly IGeekbotLogger _logger; - private readonly IAlmostRedis _redis; private readonly IServiceProvider _servicesProvider; private readonly CommandService _commands; private readonly IUserRepository _userRepository; private readonly IReactionListener _reactionListener; - private readonly DatabaseContext _messageCounterDatabaseContext; private readonly RestApplication _applicationInfo; private readonly List _ignoredServers; - public Handlers(DatabaseInitializer databaseInitializer, IDiscordClient client, IGeekbotLogger logger, IAlmostRedis redis, + public Handlers(DatabaseContext database, IDiscordClient client, IGeekbotLogger logger, IServiceProvider servicesProvider, CommandService commands, IUserRepository userRepository, IReactionListener reactionListener, RestApplication applicationInfo) { - _database = databaseInitializer.Initialize(); - _messageCounterDatabaseContext = databaseInitializer.Initialize(); + _database = database; _client = client; _logger = logger; - _redis = redis; _servicesProvider = servicesProvider; _commands = commands; _userRepository = userRepository; @@ -129,7 +124,7 @@ namespace Geekbot.net var channel = (SocketGuildChannel) message.Channel; - var rowId = await _messageCounterDatabaseContext.Database.ExecuteSqlRawAsync( + var rowId = await _database.Database.ExecuteSqlRawAsync( "UPDATE \"Messages\" SET \"MessageCount\" = \"MessageCount\" + 1 WHERE \"GuildId\" = {0} AND \"UserId\" = {1}", channel.Guild.Id.AsLong(), message.Author.Id.AsLong() @@ -137,13 +132,13 @@ namespace Geekbot.net if (rowId == 0) { - _messageCounterDatabaseContext.Messages.Add(new MessagesModel + await _database.Messages.AddAsync(new MessagesModel { UserId = message.Author.Id.AsLong(), GuildId = channel.Guild.Id.AsLong(), MessageCount = 1 }); - _messageCounterDatabaseContext.SaveChanges(); + await _database.SaveChangesAsync(); } if (message.Author.IsBot) return; diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 4907431..9ff6e90 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -41,6 +41,7 @@ namespace Geekbot.net private IUserRepository _userRepository; private RunParameters _runParameters; private IAlmostRedis _redis; + private DatabaseContext _database; private static void Main(string[] args) { @@ -87,11 +88,11 @@ namespace Geekbot.net _commands = new CommandService(); _databaseInitializer = new DatabaseInitializer(runParameters, logger); - var database = _databaseInitializer.Initialize(); - database.Database.EnsureCreated(); - if(!_runParameters.InMemory) database.Database.Migrate(); + _database = _databaseInitializer.Initialize(); + _database.Database.EnsureCreated(); + if(!_runParameters.InMemory) _database.Database.Migrate(); - _globalSettings = new GlobalSettings(database); + _globalSettings = new GlobalSettings(_database); try { @@ -116,7 +117,7 @@ namespace Geekbot.net _services = new ServiceCollection(); - _userRepository = new UserRepository(_databaseInitializer.Initialize(), logger); + _userRepository = new UserRepository(_database, logger); var fortunes = new FortunesProvider(logger); var mediaProvider = new MediaProvider(logger); var malClient = new MalClient(_globalSettings, logger); @@ -137,9 +138,9 @@ namespace Geekbot.net _services.AddSingleton(mtgManaConverter); _services.AddSingleton(wikipediaClient); _services.AddSingleton(randomNumberGenerator); + _services.AddSingleton(_database); _services.AddSingleton(_globalSettings); - _services.AddTransient(e => new HighscoreManager(_databaseInitializer.Initialize(), _userRepository)); - _services.AddTransient(e => _databaseInitializer.Initialize()); + _services.AddTransient(e => new HighscoreManager(_database, _userRepository)); logger.Information(LogSource.Geekbot, "Connecting to Discord"); @@ -162,7 +163,7 @@ namespace Geekbot.net _logger.Information(LogSource.Geekbot, $"Now Connected as {_client.CurrentUser.Username} to {_client.Guilds.Count} Servers"); _logger.Information(LogSource.Geekbot, "Registering Stuff"); - var translationHandler = new TranslationHandler(_databaseInitializer.Initialize(), _logger); + var translationHandler = new TranslationHandler(_database, _logger); var errorHandler = new ErrorHandler(_logger, translationHandler, _runParameters.ExposeErrors); var reactionListener = new ReactionListener(_redis.Db); _services.AddSingleton(errorHandler); @@ -172,7 +173,7 @@ namespace Geekbot.net _servicesProvider = _services.BuildServiceProvider(); await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _servicesProvider); - var handlers = new Handlers(_databaseInitializer, _client, _logger, _redis, _servicesProvider, _commands, _userRepository, reactionListener, applicationInfo); + var handlers = new Handlers(_database, _client, _logger, _servicesProvider, _commands, _userRepository, reactionListener, applicationInfo); _client.MessageReceived += handlers.RunCommand; _client.MessageDeleted += handlers.MessageDeleted; @@ -207,8 +208,8 @@ namespace Geekbot.net private Task StartWebApi() { _logger.Information(LogSource.Api, "Starting Webserver"); - var highscoreManager = new HighscoreManager(_databaseInitializer.Initialize(), _userRepository); - WebApiStartup.StartWebApi(_logger, _runParameters, _commands, _databaseInitializer.Initialize(), _client, _globalSettings, highscoreManager); + var highscoreManager = new HighscoreManager(_database, _userRepository); + WebApiStartup.StartWebApi(_logger, _runParameters, _commands, _database, _client, _globalSettings, highscoreManager); return Task.CompletedTask; } } From 2a616f8c5d315f253834802821fc0399f81cc618 Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 6 Apr 2020 15:51:28 +0200 Subject: [PATCH 313/553] Revert "Re-use the database connection everywhere" This reverts commit 77b3d612f2da6dbbcf8fca008deef0c307962583. --- Geekbot.net/Handlers.cs | 15 ++++++++++----- Geekbot.net/Program.cs | 23 +++++++++++------------ 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index 48bf966..13f523c 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -9,6 +9,7 @@ using Discord.Rest; using Discord.WebSocket; using Geekbot.net.Database; using Geekbot.net.Database.Models; +using Geekbot.net.Lib.AlmostRedis; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Logger; using Geekbot.net.Lib.ReactionListener; @@ -22,20 +23,24 @@ namespace Geekbot.net private readonly DatabaseContext _database; private readonly IDiscordClient _client; private readonly IGeekbotLogger _logger; + private readonly IAlmostRedis _redis; private readonly IServiceProvider _servicesProvider; private readonly CommandService _commands; private readonly IUserRepository _userRepository; private readonly IReactionListener _reactionListener; + private readonly DatabaseContext _messageCounterDatabaseContext; private readonly RestApplication _applicationInfo; private readonly List _ignoredServers; - public Handlers(DatabaseContext database, IDiscordClient client, IGeekbotLogger logger, + public Handlers(DatabaseInitializer databaseInitializer, IDiscordClient client, IGeekbotLogger logger, IAlmostRedis redis, IServiceProvider servicesProvider, CommandService commands, IUserRepository userRepository, IReactionListener reactionListener, RestApplication applicationInfo) { - _database = database; + _database = databaseInitializer.Initialize(); + _messageCounterDatabaseContext = databaseInitializer.Initialize(); _client = client; _logger = logger; + _redis = redis; _servicesProvider = servicesProvider; _commands = commands; _userRepository = userRepository; @@ -124,7 +129,7 @@ namespace Geekbot.net var channel = (SocketGuildChannel) message.Channel; - var rowId = await _database.Database.ExecuteSqlRawAsync( + var rowId = await _messageCounterDatabaseContext.Database.ExecuteSqlRawAsync( "UPDATE \"Messages\" SET \"MessageCount\" = \"MessageCount\" + 1 WHERE \"GuildId\" = {0} AND \"UserId\" = {1}", channel.Guild.Id.AsLong(), message.Author.Id.AsLong() @@ -132,13 +137,13 @@ namespace Geekbot.net if (rowId == 0) { - await _database.Messages.AddAsync(new MessagesModel + _messageCounterDatabaseContext.Messages.Add(new MessagesModel { UserId = message.Author.Id.AsLong(), GuildId = channel.Guild.Id.AsLong(), MessageCount = 1 }); - await _database.SaveChangesAsync(); + _messageCounterDatabaseContext.SaveChanges(); } if (message.Author.IsBot) return; diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 9ff6e90..4907431 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -41,7 +41,6 @@ namespace Geekbot.net private IUserRepository _userRepository; private RunParameters _runParameters; private IAlmostRedis _redis; - private DatabaseContext _database; private static void Main(string[] args) { @@ -88,11 +87,11 @@ namespace Geekbot.net _commands = new CommandService(); _databaseInitializer = new DatabaseInitializer(runParameters, logger); - _database = _databaseInitializer.Initialize(); - _database.Database.EnsureCreated(); - if(!_runParameters.InMemory) _database.Database.Migrate(); + var database = _databaseInitializer.Initialize(); + database.Database.EnsureCreated(); + if(!_runParameters.InMemory) database.Database.Migrate(); - _globalSettings = new GlobalSettings(_database); + _globalSettings = new GlobalSettings(database); try { @@ -117,7 +116,7 @@ namespace Geekbot.net _services = new ServiceCollection(); - _userRepository = new UserRepository(_database, logger); + _userRepository = new UserRepository(_databaseInitializer.Initialize(), logger); var fortunes = new FortunesProvider(logger); var mediaProvider = new MediaProvider(logger); var malClient = new MalClient(_globalSettings, logger); @@ -138,9 +137,9 @@ namespace Geekbot.net _services.AddSingleton(mtgManaConverter); _services.AddSingleton(wikipediaClient); _services.AddSingleton(randomNumberGenerator); - _services.AddSingleton(_database); _services.AddSingleton(_globalSettings); - _services.AddTransient(e => new HighscoreManager(_database, _userRepository)); + _services.AddTransient(e => new HighscoreManager(_databaseInitializer.Initialize(), _userRepository)); + _services.AddTransient(e => _databaseInitializer.Initialize()); logger.Information(LogSource.Geekbot, "Connecting to Discord"); @@ -163,7 +162,7 @@ namespace Geekbot.net _logger.Information(LogSource.Geekbot, $"Now Connected as {_client.CurrentUser.Username} to {_client.Guilds.Count} Servers"); _logger.Information(LogSource.Geekbot, "Registering Stuff"); - var translationHandler = new TranslationHandler(_database, _logger); + var translationHandler = new TranslationHandler(_databaseInitializer.Initialize(), _logger); var errorHandler = new ErrorHandler(_logger, translationHandler, _runParameters.ExposeErrors); var reactionListener = new ReactionListener(_redis.Db); _services.AddSingleton(errorHandler); @@ -173,7 +172,7 @@ namespace Geekbot.net _servicesProvider = _services.BuildServiceProvider(); await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _servicesProvider); - var handlers = new Handlers(_database, _client, _logger, _servicesProvider, _commands, _userRepository, reactionListener, applicationInfo); + var handlers = new Handlers(_databaseInitializer, _client, _logger, _redis, _servicesProvider, _commands, _userRepository, reactionListener, applicationInfo); _client.MessageReceived += handlers.RunCommand; _client.MessageDeleted += handlers.MessageDeleted; @@ -208,8 +207,8 @@ namespace Geekbot.net private Task StartWebApi() { _logger.Information(LogSource.Api, "Starting Webserver"); - var highscoreManager = new HighscoreManager(_database, _userRepository); - WebApiStartup.StartWebApi(_logger, _runParameters, _commands, _database, _client, _globalSettings, highscoreManager); + var highscoreManager = new HighscoreManager(_databaseInitializer.Initialize(), _userRepository); + WebApiStartup.StartWebApi(_logger, _runParameters, _commands, _databaseInitializer.Initialize(), _client, _globalSettings, highscoreManager); return Task.CompletedTask; } } From ee548390a560aa95842d2efd344a03d2d9d48fdb Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 17 Apr 2020 23:48:50 +0200 Subject: [PATCH 314/553] Add Prometheus with 1 metric --- Geekbot.net/Geekbot.net.csproj | 1 + Geekbot.net/Handlers.cs | 6 ++++++ Geekbot.net/Lib/RunParameters.cs | 9 +++++++++ Geekbot.net/Program.cs | 11 +++++++++++ 4 files changed, 27 insertions(+) diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index fe2f8cc..e50613a 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -44,6 +44,7 @@ + diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index 13f523c..dc1ce71 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -15,6 +15,7 @@ using Geekbot.net.Lib.Logger; using Geekbot.net.Lib.ReactionListener; using Geekbot.net.Lib.UserRepository; using Microsoft.EntityFrameworkCore; +using Prometheus; namespace Geekbot.net { @@ -32,6 +33,9 @@ namespace Geekbot.net private readonly RestApplication _applicationInfo; private readonly List _ignoredServers; + private readonly Counter _messageCounterPrometheus = + Metrics.CreateCounter("messages", "Number of discord messages", new CounterConfiguration() {LabelNames = new[] {"guild", "channel", "user"}}); + public Handlers(DatabaseInitializer databaseInitializer, IDiscordClient client, IGeekbotLogger logger, IAlmostRedis redis, IServiceProvider servicesProvider, CommandService commands, IUserRepository userRepository, IReactionListener reactionListener, RestApplication applicationInfo) @@ -146,6 +150,8 @@ namespace Geekbot.net _messageCounterDatabaseContext.SaveChanges(); } + _messageCounterPrometheus.WithLabels(channel.Guild.Id.ToString(), channel.Id.ToString(), message.Author.Id.ToString()).Inc(); + if (message.Author.IsBot) return; _logger.Information(LogSource.Message, message.Content, SimpleConextConverter.ConvertSocketMessage(message)); } diff --git a/Geekbot.net/Lib/RunParameters.cs b/Geekbot.net/Lib/RunParameters.cs index 444a60f..e16f644 100644 --- a/Geekbot.net/Lib/RunParameters.cs +++ b/Geekbot.net/Lib/RunParameters.cs @@ -72,5 +72,14 @@ namespace Geekbot.net.Lib [Option("api-port", Default = "12995", HelpText = "Port on which the WebApi listens")] public string ApiPort { get; set; } + + /************************************ + * Prometheus * + ************************************/ + [Option("prometheus-host", Default = "localhost", HelpText = "Host on which the Prometheus Metric Server listens")] + public string PrometheusHost { get; set; } + + [Option("prometheus-port", Default = "12991", HelpText = "Port on which the Prometheus Metric Server listens")] + public string PrometheusPort { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 4907431..bccc23f 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -24,6 +24,7 @@ using Geekbot.net.Lib.UserRepository; using Geekbot.net.WebApi; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; +using Prometheus; using WikipediaApi; namespace Geekbot.net @@ -185,6 +186,8 @@ namespace Geekbot.net var webserver = _runParameters.DisableApi ? Task.Delay(10) : StartWebApi(); + StartPrometheusServer(); + _logger.Information(LogSource.Geekbot, "Done and ready for use"); await webserver; @@ -211,5 +214,13 @@ namespace Geekbot.net WebApiStartup.StartWebApi(_logger, _runParameters, _commands, _databaseInitializer.Initialize(), _client, _globalSettings, highscoreManager); return Task.CompletedTask; } + + private void StartPrometheusServer() + { + var port = int.Parse(_runParameters.PrometheusPort); + var server = new MetricServer(_runParameters.PrometheusHost, port); + server.Start(); + _logger.Information(LogSource.Geekbot, $"Prometheus Metric Server running on {_runParameters.PrometheusHost}:{_runParameters.PrometheusPort}"); + } } } \ No newline at end of file From 569715f124fe2be626c753a20bda6ec892c53819 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 18 Apr 2020 00:05:09 +0200 Subject: [PATCH 315/553] fix prometheus metric server startup --- Geekbot.net/Program.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index bccc23f..6830bba 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -184,10 +184,9 @@ namespace Geekbot.net _client.ReactionRemoved += handlers.ReactionRemoved; if (!_runParameters.InMemory) _client.MessageReceived += handlers.UpdateStats; - var webserver = _runParameters.DisableApi ? Task.Delay(10) : StartWebApi(); - StartPrometheusServer(); + var webserver = _runParameters.DisableApi ? Task.Delay(10) : StartWebApi(); _logger.Information(LogSource.Geekbot, "Done and ready for use"); await webserver; @@ -217,7 +216,7 @@ namespace Geekbot.net private void StartPrometheusServer() { - var port = int.Parse(_runParameters.PrometheusPort); + var port = _runParameters.PrometheusPort == "12991" ? 12991 : int.Parse(_runParameters.PrometheusPort); var server = new MetricServer(_runParameters.PrometheusHost, port); server.Start(); _logger.Information(LogSource.Geekbot, $"Prometheus Metric Server running on {_runParameters.PrometheusHost}:{_runParameters.PrometheusPort}"); From fc5ff87c8fd4880ba26f78c223aae35755589d35 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 19 Apr 2020 13:52:44 +0200 Subject: [PATCH 316/553] Only the ManageMessages is now required to delete a quote --- Geekbot.net/Commands/Utils/Quote/Quote.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Geekbot.net/Commands/Utils/Quote/Quote.cs b/Geekbot.net/Commands/Utils/Quote/Quote.cs index e9c4706..f568036 100644 --- a/Geekbot.net/Commands/Utils/Quote/Quote.cs +++ b/Geekbot.net/Commands/Utils/Quote/Quote.cs @@ -166,10 +166,8 @@ namespace Geekbot.net.Commands.Utils.Quote } [Command("remove")] - [RequireUserPermission(GuildPermission.KickMembers)] [RequireUserPermission(GuildPermission.ManageMessages)] - [RequireUserPermission(GuildPermission.ManageRoles)] - [Summary("Remove a quote (required mod permissions)")] + [Summary("Remove a quote (user needs the 'ManageMessages' permission)")] public async Task RemoveQuote([Summary("quote-ID")] int id) { try From c031d2bfb42ef5ecba58710f3453a0e58cf61884 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 7 May 2020 13:11:00 +0200 Subject: [PATCH 317/553] Remove Prometheus --- Geekbot.net/Handlers.cs | 11 +---------- Geekbot.net/Program.cs | 13 +------------ 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index dc1ce71..52cf937 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -15,8 +15,6 @@ using Geekbot.net.Lib.Logger; using Geekbot.net.Lib.ReactionListener; using Geekbot.net.Lib.UserRepository; using Microsoft.EntityFrameworkCore; -using Prometheus; - namespace Geekbot.net { public class Handlers @@ -24,7 +22,6 @@ namespace Geekbot.net private readonly DatabaseContext _database; private readonly IDiscordClient _client; private readonly IGeekbotLogger _logger; - private readonly IAlmostRedis _redis; private readonly IServiceProvider _servicesProvider; private readonly CommandService _commands; private readonly IUserRepository _userRepository; @@ -33,10 +30,7 @@ namespace Geekbot.net private readonly RestApplication _applicationInfo; private readonly List _ignoredServers; - private readonly Counter _messageCounterPrometheus = - Metrics.CreateCounter("messages", "Number of discord messages", new CounterConfiguration() {LabelNames = new[] {"guild", "channel", "user"}}); - - public Handlers(DatabaseInitializer databaseInitializer, IDiscordClient client, IGeekbotLogger logger, IAlmostRedis redis, + public Handlers(DatabaseInitializer databaseInitializer, IDiscordClient client, IGeekbotLogger logger, IServiceProvider servicesProvider, CommandService commands, IUserRepository userRepository, IReactionListener reactionListener, RestApplication applicationInfo) { @@ -44,7 +38,6 @@ namespace Geekbot.net _messageCounterDatabaseContext = databaseInitializer.Initialize(); _client = client; _logger = logger; - _redis = redis; _servicesProvider = servicesProvider; _commands = commands; _userRepository = userRepository; @@ -150,8 +143,6 @@ namespace Geekbot.net _messageCounterDatabaseContext.SaveChanges(); } - _messageCounterPrometheus.WithLabels(channel.Guild.Id.ToString(), channel.Id.ToString(), message.Author.Id.ToString()).Inc(); - if (message.Author.IsBot) return; _logger.Information(LogSource.Message, message.Content, SimpleConextConverter.ConvertSocketMessage(message)); } diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 6830bba..3bd5a8f 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -24,7 +24,6 @@ using Geekbot.net.Lib.UserRepository; using Geekbot.net.WebApi; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; -using Prometheus; using WikipediaApi; namespace Geekbot.net @@ -173,7 +172,7 @@ namespace Geekbot.net _servicesProvider = _services.BuildServiceProvider(); await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _servicesProvider); - var handlers = new Handlers(_databaseInitializer, _client, _logger, _redis, _servicesProvider, _commands, _userRepository, reactionListener, applicationInfo); + var handlers = new Handlers(_databaseInitializer, _client, _logger, _servicesProvider, _commands, _userRepository, reactionListener, applicationInfo); _client.MessageReceived += handlers.RunCommand; _client.MessageDeleted += handlers.MessageDeleted; @@ -183,8 +182,6 @@ namespace Geekbot.net _client.ReactionAdded += handlers.ReactionAdded; _client.ReactionRemoved += handlers.ReactionRemoved; if (!_runParameters.InMemory) _client.MessageReceived += handlers.UpdateStats; - - StartPrometheusServer(); var webserver = _runParameters.DisableApi ? Task.Delay(10) : StartWebApi(); _logger.Information(LogSource.Geekbot, "Done and ready for use"); @@ -213,13 +210,5 @@ namespace Geekbot.net WebApiStartup.StartWebApi(_logger, _runParameters, _commands, _databaseInitializer.Initialize(), _client, _globalSettings, highscoreManager); return Task.CompletedTask; } - - private void StartPrometheusServer() - { - var port = _runParameters.PrometheusPort == "12991" ? 12991 : int.Parse(_runParameters.PrometheusPort); - var server = new MetricServer(_runParameters.PrometheusHost, port); - server.Start(); - _logger.Information(LogSource.Geekbot, $"Prometheus Metric Server running on {_runParameters.PrometheusHost}:{_runParameters.PrometheusPort}"); - } } } \ No newline at end of file From 5cf1248bf04df3b5a6c1fe8bb46a4019057904ad Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 11 May 2020 23:44:15 +0200 Subject: [PATCH 318/553] Add !quote stats (v1) --- Geekbot.net/Commands/Utils/Quote/Quote.cs | 48 ++++++++++++++++++- Geekbot.net/Lib/Localization/Translations.yml | 9 ++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/Geekbot.net/Commands/Utils/Quote/Quote.cs b/Geekbot.net/Commands/Utils/Quote/Quote.cs index f568036..454ad9b 100644 --- a/Geekbot.net/Commands/Utils/Quote/Quote.cs +++ b/Geekbot.net/Commands/Utils/Quote/Quote.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Threading.Tasks; using Discord; @@ -192,6 +192,52 @@ namespace Geekbot.net.Commands.Utils.Quote } } + [Command("stats")] + [Summary("Show quote stats for this server")] + public async Task GetQuoteStatsForServer() + { + try + { + var transContext = await _translationHandler.GetGuildContext(Context); + var eb = new EmbedBuilder(); + eb.Author = new EmbedAuthorBuilder() + { + IconUrl = Context.Guild.IconUrl, + Name = $"{Context.Guild.Name} - {transContext.GetString("QuoteStats")}" + }; + + var totalQuotes = _database.Quotes.Count(row => row.GuildId == Context.Guild.Id.AsLong()); + if (totalQuotes == 0) + { + await ReplyAsync(transContext.GetString("NoQuotesFound")); + return; + } + eb.AddInlineField(transContext.GetString("TotalQuotes"), totalQuotes); + + var mostQuotedPerson = _database.Quotes + .Where(row => row.GuildId == Context.Guild.Id.AsLong()) + .GroupBy(row => row.UserId) + .Max(row => row.Key); + var user = Context.Client.GetUserAsync(mostQuotedPerson.AsUlong()).Result ?? new UserPolyfillDto {Username = "Unknown User"}; + eb.AddInlineField(transContext.GetString("MostQuotesPerson"), user); + + var quotesByYear = _database.Quotes + .Where(row => row.GuildId == Context.Guild.Id.AsLong()) + .GroupBy(row => row.Time.Year) + .Select(row => new { year = row.Key, amount = row.Count()}); + foreach (var year in quotesByYear) + { + eb.AddInlineField(year.year.ToString(), year.amount); + } + + await ReplyAsync("", false, eb.Build()); + } + catch (Exception e) + { + await _errorHandler.HandleCommandException(e, Context); + } + } + private async Task GetLastMessageByUser(IUser user) { try diff --git a/Geekbot.net/Lib/Localization/Translations.yml b/Geekbot.net/Lib/Localization/Translations.yml index 5744741..a19a6f3 100644 --- a/Geekbot.net/Lib/Localization/Translations.yml +++ b/Geekbot.net/Lib/Localization/Translations.yml @@ -160,6 +160,15 @@ quote: NotFoundWithId: EN: "I couldn't find a quote with that ID :disappointed:" CHDE: "Ich chan kei quote finde mit därri ID :disappointed:" + QuoteStats: + EN: "Quote Stats" + CHDE: "Quote statistike" + TotalQuotes: + EN: "Total" + CHDE: "Total" + MostQuotesPerson: + EN: "Most quoted person" + CHDE: "Meist quoteti person" rank: InvalidType: EN: "Valid types are '`messages`' '`karma`', '`rolls`' and '`cookies`'" From 656393cc7b40654023ec44dbcde207d466e9f8fe Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 12 May 2020 00:04:20 +0200 Subject: [PATCH 319/553] '!quote stats' bug fixes --- Geekbot.net/Commands/Utils/Quote/Quote.cs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/Geekbot.net/Commands/Utils/Quote/Quote.cs b/Geekbot.net/Commands/Utils/Quote/Quote.cs index 454ad9b..5c2bd3b 100644 --- a/Geekbot.net/Commands/Utils/Quote/Quote.cs +++ b/Geekbot.net/Commands/Utils/Quote/Quote.cs @@ -198,6 +198,7 @@ namespace Geekbot.net.Commands.Utils.Quote { try { + // setup var transContext = await _translationHandler.GetGuildContext(Context); var eb = new EmbedBuilder(); eb.Author = new EmbedAuthorBuilder() @@ -206,25 +207,33 @@ namespace Geekbot.net.Commands.Utils.Quote Name = $"{Context.Guild.Name} - {transContext.GetString("QuoteStats")}" }; + // gather data var totalQuotes = _database.Quotes.Count(row => row.GuildId == Context.Guild.Id.AsLong()); if (totalQuotes == 0) { + // no quotes, no stats, end of the road await ReplyAsync(transContext.GetString("NoQuotesFound")); return; } - eb.AddInlineField(transContext.GetString("TotalQuotes"), totalQuotes); - + var mostQuotedPerson = _database.Quotes .Where(row => row.GuildId == Context.Guild.Id.AsLong()) .GroupBy(row => row.UserId) - .Max(row => row.Key); - var user = Context.Client.GetUserAsync(mostQuotedPerson.AsUlong()).Result ?? new UserPolyfillDto {Username = "Unknown User"}; - eb.AddInlineField(transContext.GetString("MostQuotesPerson"), user); + .Select(row => new { userId = row.Key, amount = row.Count()}) + .OrderBy(row => row.amount) + .Last(); + var mostQuotedPersonUser = Context.Client.GetUserAsync(mostQuotedPerson.userId.AsUlong()).Result ?? new UserPolyfillDto {Username = "Unknown User"}; var quotesByYear = _database.Quotes .Where(row => row.GuildId == Context.Guild.Id.AsLong()) .GroupBy(row => row.Time.Year) - .Select(row => new { year = row.Key, amount = row.Count()}); + .Select(row => new { year = row.Key, amount = row.Count()}) + .OrderBy(row => row.year); + + // add data to the embed + eb.AddField(transContext.GetString("MostQuotesPerson"), $"{mostQuotedPersonUser.Username} ({mostQuotedPerson.amount})"); + eb.AddInlineField(transContext.GetString("TotalQuotes"), totalQuotes); + foreach (var year in quotesByYear) { eb.AddInlineField(year.year.ToString(), year.amount); From 2e501008df466b6fb2eda39dcd7bda6f823edaf3 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 21 May 2020 15:55:04 +0200 Subject: [PATCH 320/553] Remove !checkem --- Geekbot.net/Commands/Randomness/CheckEm.cs | 71 ------------ Geekbot.net/Geekbot.net.csproj | 3 - Geekbot.net/Lib/Media/IMediaProvider.cs | 1 - Geekbot.net/Lib/Media/MediaProvider.cs | 18 +-- Geekbot.net/Storage/checkEmPics | 122 --------------------- 5 files changed, 2 insertions(+), 213 deletions(-) delete mode 100644 Geekbot.net/Commands/Randomness/CheckEm.cs delete mode 100644 Geekbot.net/Storage/checkEmPics diff --git a/Geekbot.net/Commands/Randomness/CheckEm.cs b/Geekbot.net/Commands/Randomness/CheckEm.cs deleted file mode 100644 index 0596872..0000000 --- a/Geekbot.net/Commands/Randomness/CheckEm.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading.Tasks; -using Discord.Commands; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.Media; - -namespace Geekbot.net.Commands.Randomness -{ - public class CheckEm : ModuleBase - { - private readonly IMediaProvider _checkEmImages; - private readonly IErrorHandler _errorHandler; - - public CheckEm(IMediaProvider mediaProvider, IErrorHandler errorHandler) - { - _checkEmImages = mediaProvider; - _errorHandler = errorHandler; - } - - [Command("checkem", RunMode = RunMode.Async)] - [Summary("Check for dubs")] - public async Task MuhDubs() - { - try - { - var number = new Random().Next(10000000, 99999999); - var dubtriqua = ""; - - var ns = GetIntArray(number); - if (ns[7] == ns[6]) - { - dubtriqua = "DUBS"; - if (ns[6] == ns[5]) - { - dubtriqua = "TRIPS"; - if (ns[5] == ns[4]) - dubtriqua = "QUADS"; - } - } - - var sb = new StringBuilder(); - sb.AppendLine($"Check em {Context.User.Mention}"); - sb.AppendLine($"**{number}**"); - if (!string.IsNullOrEmpty(dubtriqua)) - sb.AppendLine($":tada: {dubtriqua} :tada:"); - sb.AppendLine(_checkEmImages.GetCheckem()); - - await ReplyAsync(sb.ToString()); - } - catch (Exception e) - { - await _errorHandler.HandleCommandException(e, Context); - } - } - - private int[] GetIntArray(int num) - { - var listOfInts = new List(); - while (num > 0) - { - listOfInts.Add(num % 10); - num /= 10; - } - - listOfInts.Reverse(); - return listOfInts.ToArray(); - } - } -} \ No newline at end of file diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index e50613a..baf326d 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -59,9 +59,6 @@ - - PreserveNewest - PreserveNewest diff --git a/Geekbot.net/Lib/Media/IMediaProvider.cs b/Geekbot.net/Lib/Media/IMediaProvider.cs index a646cea..33a0d7c 100644 --- a/Geekbot.net/Lib/Media/IMediaProvider.cs +++ b/Geekbot.net/Lib/Media/IMediaProvider.cs @@ -2,7 +2,6 @@ { public interface IMediaProvider { - string GetCheckem(); string GetPanda(); string GetCrossant(); string GetSquirrel(); diff --git a/Geekbot.net/Lib/Media/MediaProvider.cs b/Geekbot.net/Lib/Media/MediaProvider.cs index c88b696..f7ea9df 100644 --- a/Geekbot.net/Lib/Media/MediaProvider.cs +++ b/Geekbot.net/Lib/Media/MediaProvider.cs @@ -8,7 +8,6 @@ namespace Geekbot.net.Lib.Media { private readonly Random _random; private readonly IGeekbotLogger _logger; - private string[] _checkemImages; private string[] _pandaImages; private string[] _croissantImages; private string[] _squirrelImages; @@ -24,8 +23,7 @@ namespace Geekbot.net.Lib.Media _logger = logger; logger.Information(LogSource.Geekbot, "Loading Media Files"); - - LoadCheckem(); +; LoadPandas(); BakeCroissants(); LoadSquirrels(); @@ -35,13 +33,6 @@ namespace Geekbot.net.Lib.Media LoadFoxes(); LoadDab(); } - - private void LoadCheckem() - { - var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/checkEmPics")); - _checkemImages = rawLinks.Split("\n"); - _logger.Trace(LogSource.Geekbot, $"Loaded {_checkemImages.Length} CheckEm Images"); - } private void LoadPandas() { @@ -98,12 +89,7 @@ namespace Geekbot.net.Lib.Media _dabImages = rawLinks.Split("\n"); _logger.Trace(LogSource.Geekbot, $"Loaded {_dabImages.Length} Dab Images"); } - - public string GetCheckem() - { - return _checkemImages[_random.Next(0, _checkemImages.Length)]; - } - + public string GetPanda() { return _pandaImages[_random.Next(0, _pandaImages.Length)]; diff --git a/Geekbot.net/Storage/checkEmPics b/Geekbot.net/Storage/checkEmPics deleted file mode 100644 index 03be23e..0000000 --- a/Geekbot.net/Storage/checkEmPics +++ /dev/null @@ -1,122 +0,0 @@ -http://s19.postimg.org/pcq2kwzoj/4cb.png -http://s19.postimg.org/cvetk0f4z/5_Dim_Dy6p.jpg -http://s19.postimg.org/5hzfl1v37/1310151998600.jpg -http://s19.postimg.org/53y3lgazn/1324181141954.jpg -http://s19.postimg.org/724rjg3hf/1392512742365.png -http://s19.postimg.org/3rgejkdk3/1393501296733.png -http://s19.postimg.org/a6ffg8k9v/1401667341503.jpg -http://s19.postimg.org/qiph5yylf/1419231572452.jpg -http://s19.postimg.org/fqwi4m8ir/1427600681401.png -http://s19.postimg.org/4c00zzw6b/1447813628974.png -http://s19.postimg.org/uuio8puw3/b5_3q_ycaaavxtf.jpg -http://s19.postimg.org/bghu913fn/check_em_by_boyboy99100_d57xp3y.png -http://s19.postimg.org/s1pgooujn/l_Hkppjs.jpg -http://s19.postimg.org/m08itft0j/checkem.jpg -https://old.postimg.org/image/6vx33rb1b/ -https://old.postimg.org/image/wxiaz1mov/ -https://old.postimg.org/image/azqfizx27/ -https://old.postimg.org/image/6iy2kbiu7/ -https://old.postimg.org/image/k8slt45y7/ -https://old.postimg.org/image/t7ruxmplr/ -https://old.postimg.org/image/ssbzqvean/ -https://old.postimg.org/image/kbchfy9lr/ -https://old.postimg.org/image/dl0lk9btr/ -https://old.postimg.org/image/e5k80oufz/ -https://old.postimg.org/image/er005baqn/ -https://old.postimg.org/image/bfk2uzcin/ -https://old.postimg.org/image/556fp0jkv/ -https://old.postimg.org/image/i0efbryu7/ -https://old.postimg.org/image/943n7u87z/ -https://old.postimg.org/image/xn5op5cm7/ -https://old.postimg.org/image/3l5p4d0kf/ -https://old.postimg.org/image/5boq5ui3j/ -https://old.postimg.org/image/ru082bqcf/ -https://old.postimg.org/image/ytea1oqan/ -https://old.postimg.org/image/vu7dekgtb/ -https://old.postimg.org/image/hl7qwi2an/ -https://old.postimg.org/image/5aescfg9r/ -https://old.postimg.org/image/9gzmrrfvj/ -https://old.postimg.org/image/50bv6tr1b/ -https://old.postimg.org/image/afkl7silb/ -https://old.postimg.org/image/nrdsgzllr/ -https://old.postimg.org/image/s32e5zsin/ -https://old.postimg.org/image/5sej60v8f/ -https://old.postimg.org/image/lgfqctau7/ -https://old.postimg.org/image/tn7q4e0wv/ -https://old.postimg.org/image/8612arz1b/ -https://old.postimg.org/image/w5tf52mn3/ -https://old.postimg.org/image/zdxwi48wv/ -https://old.postimg.org/image/lphwghd0f/ -https://old.postimg.org/image/uzu0k0nq7/ -https://old.postimg.org/image/3vqzsxjbz/ -https://old.postimg.org/image/5d7uqqyov/ -https://old.postimg.org/image/dntnyku8v/ -https://old.postimg.org/image/dsxf891jz/ -https://old.postimg.org/image/3nyrioizj/ -https://old.postimg.org/image/6zx2bzaqn/ -https://old.postimg.org/image/wu6v1raqn/ -https://old.postimg.org/image/hb9f4n2fz/ -https://old.postimg.org/image/p7yhqm3a7/ -https://old.postimg.org/image/oelvxzx9b/ -https://old.postimg.org/image/vcq03xvdr/ -https://old.postimg.org/image/b08t1yqlb/ -https://old.postimg.org/image/6yrpwayan/ -https://old.postimg.org/image/btleukwm7/ -https://old.postimg.org/image/62ztuldzz/ -https://old.postimg.org/image/w3iq9pxr3/ -https://old.postimg.org/image/byp6493xb/ -https://old.postimg.org/image/xp2lf9xcv/ -https://old.postimg.org/image/j9p9u49pb/ -https://old.postimg.org/image/hvxmytafz/ -https://old.postimg.org/image/5eqzbnfa7/ -https://old.postimg.org/image/do2uq290f/ -https://old.postimg.org/image/54o261q1r/ -https://old.postimg.org/image/94qm4jr4v/ -https://old.postimg.org/image/lee88y0pr/ -https://old.postimg.org/image/bncb58cv3/ -https://old.postimg.org/image/5246j7me7/ -https://old.postimg.org/image/4uby8ym1r/ -https://old.postimg.org/image/qn996tj4v/ -https://old.postimg.org/image/c1dn4twyn/ -https://old.postimg.org/image/6rd9ra23j/ -https://lehcark14.files.wordpress.com/2008/08/botan16.jpg -http://i.imgur.com/p9vALew.jpg -http://i.imgur.com/4a9l2Rm.png -http://i.imgur.com/RNtixMQ.jpg -https://pbs.twimg.com/media/Cro9aIGUEAAkXCP.jpg -http://s16.postimg.org/empvloimd/Check_em_Guts.png -https://s18.postimg.io/qgbhe7u09/1424491645996.gif -http://s19.postimg.org/hhemlt7xf/3eb.jpg -http://s19.postimg.org/cwsg6vo83/8aa.png -http://s19.postimg.org/rh9j1pj6r/28mohl4.png -http://s19.postimg.org/zba4n3qzn/86d.jpg -http://s19.postimg.org/cb3hart5v/2016_09_16_08_58_45.png -http://s19.postimg.org/m9ofx92lf/bb1.jpg -http://s19.postimg.org/maydqo4f7/e8b.jpg -http://s19.postimg.org/yqzoy5n4z/fbe.png -http://s19.postimg.org/xd822unvn/giphy.gif -http://s19.postimg.org/c4udlf9er/l_TU3eup.jpg -https://66.media.tumblr.com/cc893a0ee40d73d083da3df4bdaf45cc/tumblr_mx8psiFduG1t1g1k8o1_500.gif -http://i.imgur.com/swbXHSy.gif -http://img1.reactor.cc/pics/post/full/Anime-Touhou-Project-Yakumo-Yukari-%D0%A0%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D1%8F-1303807.jpeg -http://i.imgur.com/ftGLHE0.png -http://i.imgur.com/JELDhKQ.png -http://imgur.com/yBJound -http://i.imgur.com/f7gAVPJ.png -http://i.imgur.com/HxWyo2Z.jpg -http://i.imgur.com/8Eb9CxQ.png -http://i.imgur.com/kOECcjz.png -http://i.imgur.com/MJLu7oJ.jpg -http://i.imgur.com/itG3rPM.jpg -http://i.imgur.com/G83Go9t.jpg -http://i.imgur.com/jI2dBnU.jpg -http://i.imgur.com/FtALzg0.jpg -http://i.imgur.com/GwZpJEv.gif -http://i.imgur.com/TYGRD3B.gif -http://i.imgur.com/P6TxLS3.png -http://i.imgur.com/phTVTdn.jpg -http://i.imgur.com/thhR6UE.jpg -http://i.imgur.com/KbROufx.jpg -http://i.imgur.com/sQqWbcm.jpg -http://i.imgur.com/YYpis53.png -http://i.imgur.com/kwaRd54.gif \ No newline at end of file From 33b17b373f1a55e829d6b4bcb953e7a6384ffae3 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 30 May 2020 17:02:17 +0200 Subject: [PATCH 321/553] Remove all dependencies on redis --- Geekbot.net/Commands/Admin/Role.cs | 19 ++--- Geekbot.net/Commands/Games/Roll.cs | 23 +++-- Geekbot.net/Commands/User/Stats.cs | 5 +- Geekbot.net/Database/DatabaseContext.cs | 1 + .../Database/Models/ReactionListenerModel.cs | 22 +++++ Geekbot.net/Handlers.cs | 2 +- .../Lib/KvInMemoryStore/IKvInMemoryStore.cs | 9 ++ .../Lib/KvInMemoryStore/KvInMemoryStore.cs | 32 +++++++ .../Lib/ReactionListener/IReactionListener.cs | 3 +- .../Lib/ReactionListener/ReactionListener.cs | 85 +++++++++---------- Geekbot.net/Program.cs | 5 +- 11 files changed, 129 insertions(+), 77 deletions(-) create mode 100644 Geekbot.net/Database/Models/ReactionListenerModel.cs create mode 100644 Geekbot.net/Lib/KvInMemoryStore/IKvInMemoryStore.cs create mode 100644 Geekbot.net/Lib/KvInMemoryStore/KvInMemoryStore.cs diff --git a/Geekbot.net/Commands/Admin/Role.cs b/Geekbot.net/Commands/Admin/Role.cs index b0df4bb..6d4557d 100644 --- a/Geekbot.net/Commands/Admin/Role.cs +++ b/Geekbot.net/Commands/Admin/Role.cs @@ -170,23 +170,16 @@ namespace Geekbot.net.Commands.Admin [RequireUserPermission(GuildPermission.ManageRoles)] [Summary("Give a role by clicking on an emoji")] [Command("listen", RunMode = RunMode.Async)] - public async Task AddListener([Summary("message-ID")] string messageId, [Summary("Emoji")] string emoji, [Summary("@role")] IRole role) + public async Task AddListener([Summary("message-ID")] string messageIdStr, [Summary("Emoji")] string emoji, [Summary("@role")] IRole role) { try { - var message = (IUserMessage) await Context.Channel.GetMessageAsync(ulong.Parse(messageId)); - IEmote emote; - if (!emoji.StartsWith('<')) - { - var emo = new Emoji(emoji); - emote = emo; - } - else - { - emote = Emote.Parse(emoji); - } + var messageId = ulong.Parse(messageIdStr); + var message = (IUserMessage) await Context.Channel.GetMessageAsync(messageId); + var emote = _reactionListener.ConvertStringToEmote(emoji); + await message.AddReactionAsync(emote); - await _reactionListener.AddRoleToListener(messageId, emote, role); + await _reactionListener.AddRoleToListener(messageId, Context.Guild.Id, emoji, role); await Context.Message.DeleteAsync(); } catch (HttpException e) diff --git a/Geekbot.net/Commands/Games/Roll.cs b/Geekbot.net/Commands/Games/Roll.cs index dfecb13..076cf8f 100644 --- a/Geekbot.net/Commands/Games/Roll.cs +++ b/Geekbot.net/Commands/Games/Roll.cs @@ -4,26 +4,25 @@ using System.Threading.Tasks; using Discord.Commands; using Geekbot.net.Database; using Geekbot.net.Database.Models; -using Geekbot.net.Lib.AlmostRedis; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; +using Geekbot.net.Lib.KvInMemoryStore; using Geekbot.net.Lib.Localization; using Geekbot.net.Lib.RandomNumberGenerator; -using StackExchange.Redis; namespace Geekbot.net.Commands.Games { public class Roll : ModuleBase { private readonly IErrorHandler _errorHandler; - private readonly IAlmostRedis _redis; + private readonly IKvInMemoryStore _kvInMemoryStore; private readonly ITranslationHandler _translation; private readonly DatabaseContext _database; private readonly IRandomNumberGenerator _randomNumberGenerator; - public Roll(IAlmostRedis redis, IErrorHandler errorHandler, ITranslationHandler translation, DatabaseContext database, IRandomNumberGenerator randomNumberGenerator) + public Roll(IKvInMemoryStore kvInMemoryStore,IErrorHandler errorHandler, ITranslationHandler translation, DatabaseContext database, IRandomNumberGenerator randomNumberGenerator) { - _redis = redis; + _kvInMemoryStore = kvInMemoryStore; _translation = translation; _database = database; _randomNumberGenerator = randomNumberGenerator; @@ -37,28 +36,28 @@ namespace Geekbot.net.Commands.Games try { var number = _randomNumberGenerator.Next(1, 100); - var guess = 1000; - int.TryParse(stuff, out guess); + int.TryParse(stuff, out var guess); var transContext = await _translation.GetGuildContext(Context); if (guess <= 100 && guess > 0) { - var prevRoll = _redis.Db.HashGet($"{Context.Guild.Id}:RollsPrevious2", Context.Message.Author.Id).ToString()?.Split('|'); - if (prevRoll?.Length == 2) + var kvKey = $"{Context.Guild.Id}:{Context.User.Id}:RollsPrevious"; + + var prevRoll = _kvInMemoryStore.Get(kvKey); + if (prevRoll > 0) { - if (prevRoll[0] == guess.ToString() && DateTime.Parse(prevRoll[1]) > DateTime.Now.AddDays(-1)) + if (prevRoll == guess) { await ReplyAsync(transContext.GetString("NoPrevGuess", Context.Message.Author.Mention)); return; } } - _redis.Db.HashSet($"{Context.Guild.Id}:RollsPrevious2", new[] {new HashEntry(Context.Message.Author.Id, $"{guess}|{DateTime.Now}")}); + _kvInMemoryStore.Set(kvKey, guess); await ReplyAsync(transContext.GetString("Rolled", Context.Message.Author.Mention, number, guess)); if (guess == number) { await ReplyAsync(transContext.GetString("Gratz", Context.Message.Author)); - _redis.Db.HashIncrement($"{Context.Guild.Id}:Rolls", Context.User.Id.ToString()); var user = await GetUser(Context.User.Id); user.Rolls += 1; _database.Rolls.Update(user); diff --git a/Geekbot.net/Commands/User/Stats.cs b/Geekbot.net/Commands/User/Stats.cs index 05ea324..08b69d2 100644 --- a/Geekbot.net/Commands/User/Stats.cs +++ b/Geekbot.net/Commands/User/Stats.cs @@ -4,7 +4,6 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.net.Database; -using Geekbot.net.Lib.AlmostRedis; using Geekbot.net.Lib.CommandPreconditions; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; @@ -16,12 +15,10 @@ namespace Geekbot.net.Commands.User { private readonly IErrorHandler _errorHandler; private readonly ILevelCalc _levelCalc; - private readonly IAlmostRedis _redis; private readonly DatabaseContext _database; - public Stats(IAlmostRedis redis, DatabaseContext database, IErrorHandler errorHandler, ILevelCalc levelCalc) + public Stats(DatabaseContext database, IErrorHandler errorHandler, ILevelCalc levelCalc) { - _redis = redis; _database = database; _errorHandler = errorHandler; _levelCalc = levelCalc; diff --git a/Geekbot.net/Database/DatabaseContext.cs b/Geekbot.net/Database/DatabaseContext.cs index cbfa30d..56c19f8 100644 --- a/Geekbot.net/Database/DatabaseContext.cs +++ b/Geekbot.net/Database/DatabaseContext.cs @@ -18,5 +18,6 @@ namespace Geekbot.net.Database public DbSet RoleSelfService { get; set; } public DbSet Polls { get; set; } public DbSet Cookies { get; set; } + public DbSet ReactionListeners { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Database/Models/ReactionListenerModel.cs b/Geekbot.net/Database/Models/ReactionListenerModel.cs new file mode 100644 index 0000000..05ab5b3 --- /dev/null +++ b/Geekbot.net/Database/Models/ReactionListenerModel.cs @@ -0,0 +1,22 @@ +using System.ComponentModel.DataAnnotations; + +namespace Geekbot.net.Database.Models +{ + public class ReactionListenerModel + { + [Key] + public int Id { get; set; } + + [Required] + public long GuildId { get; set; } + + [Required] + public long MessageId { get; set; } + + [Required] + public long RoleId { get; set; } + + [Required] + public string Reaction { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs index 52cf937..6f98041 100644 --- a/Geekbot.net/Handlers.cs +++ b/Geekbot.net/Handlers.cs @@ -9,12 +9,12 @@ using Discord.Rest; using Discord.WebSocket; using Geekbot.net.Database; using Geekbot.net.Database.Models; -using Geekbot.net.Lib.AlmostRedis; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Logger; using Geekbot.net.Lib.ReactionListener; using Geekbot.net.Lib.UserRepository; using Microsoft.EntityFrameworkCore; + namespace Geekbot.net { public class Handlers diff --git a/Geekbot.net/Lib/KvInMemoryStore/IKvInMemoryStore.cs b/Geekbot.net/Lib/KvInMemoryStore/IKvInMemoryStore.cs new file mode 100644 index 0000000..88f3863 --- /dev/null +++ b/Geekbot.net/Lib/KvInMemoryStore/IKvInMemoryStore.cs @@ -0,0 +1,9 @@ +namespace Geekbot.net.Lib.KvInMemoryStore +{ + public interface IKvInMemoryStore + { + public T Get(string key); + public void Set(string key, T value); + public void Remove(string key); + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/KvInMemoryStore/KvInMemoryStore.cs b/Geekbot.net/Lib/KvInMemoryStore/KvInMemoryStore.cs new file mode 100644 index 0000000..33b7155 --- /dev/null +++ b/Geekbot.net/Lib/KvInMemoryStore/KvInMemoryStore.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; + +namespace Geekbot.net.Lib.KvInMemoryStore +{ + public class KvInInMemoryStore : IKvInMemoryStore + { + private readonly Dictionary _storage = new Dictionary(); + + public T Get(string key) + { + try + { + return (T) _storage[key]; + } + catch + { + return default; + } + } + + public void Set(string key, T value) + { + _storage.Remove(key); + _storage.Add(key, value); + } + + public void Remove(string key) + { + _storage.Remove(key); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/ReactionListener/IReactionListener.cs b/Geekbot.net/Lib/ReactionListener/IReactionListener.cs index 792a516..b2ab9fb 100644 --- a/Geekbot.net/Lib/ReactionListener/IReactionListener.cs +++ b/Geekbot.net/Lib/ReactionListener/IReactionListener.cs @@ -7,8 +7,9 @@ namespace Geekbot.net.Lib.ReactionListener public interface IReactionListener { bool IsListener(ulong id); - Task AddRoleToListener(string messageId, IEmote emoji, IRole role); + Task AddRoleToListener(ulong messageId, ulong guildId, string emoji, IRole role); void RemoveRole(ISocketMessageChannel channel, SocketReaction reaction); void GiveRole(ISocketMessageChannel message, SocketReaction reaction); + IEmote ConvertStringToEmote(string emoji); } } \ No newline at end of file diff --git a/Geekbot.net/Lib/ReactionListener/ReactionListener.cs b/Geekbot.net/Lib/ReactionListener/ReactionListener.cs index 2349028..4a9a08c 100644 --- a/Geekbot.net/Lib/ReactionListener/ReactionListener.cs +++ b/Geekbot.net/Lib/ReactionListener/ReactionListener.cs @@ -1,80 +1,66 @@ using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using Discord; using Discord.WebSocket; -using StackExchange.Redis; +using Geekbot.net.Database; +using Geekbot.net.Database.Models; +using Geekbot.net.Lib.Extensions; namespace Geekbot.net.Lib.ReactionListener { public class ReactionListener : IReactionListener { - private readonly IDatabase _redis; - private Dictionary> _listener; + private readonly DatabaseContext _database; + private Dictionary> _listener; - public ReactionListener(IDatabase redis) + public ReactionListener(DatabaseContext database) { - _redis = redis; + _database = database; LoadListeners(); } private void LoadListeners() { - var ids = _redis.SetMembers("MessageIds"); - _listener = new Dictionary>(); - foreach (var id in ids) + _listener = new Dictionary>(); + foreach (var row in _database.ReactionListeners) { - var reactions = _redis.HashGetAll($"Messages:{id}"); - var messageId = id; - var emojiDict = new Dictionary(); - foreach (var r in reactions) + var messageId = row.MessageId.AsUlong(); + if (!_listener.ContainsKey(messageId)) { - IEmote emote; - if (!r.Name.ToString().StartsWith('<')) - { - var emo = new Emoji(r.Name); - emote = emo; - } - else - { - emote = Emote.Parse(r.Name); - } - emojiDict.Add(emote, ulong.Parse(r.Value)); + _listener.Add(messageId, new Dictionary()); } - _listener.Add(messageId, emojiDict); + + _listener[messageId].Add(ConvertStringToEmote(row.Reaction), row.RoleId.AsUlong()); } } public bool IsListener(ulong id) { - return _listener.ContainsKey(id.ToString()); + return _listener.ContainsKey(id); } - public Task AddRoleToListener(string messageId, IEmote emoji, IRole role) + public async Task AddRoleToListener(ulong messageId, ulong guildId, string emoji, IRole role) { - if (_redis.SetMembers("MessageIds").All(e => e.ToString() != messageId)) - { - _redis.SetAdd("MessageIds", messageId); - } - _redis.HashSet($"Messages:{messageId}", new[] {new HashEntry(emoji.ToString(), role.Id.ToString())}); - _redis.SetAdd("MessageIds", messageId); - if (_listener.ContainsKey(messageId)) - { - _listener[messageId].Add(emoji, role.Id); - return Task.CompletedTask; - } + var emote = ConvertStringToEmote(emoji); - var dict = new Dictionary + await _database.ReactionListeners.AddAsync(new ReactionListenerModel() { - {emoji, role.Id} - }; - _listener.Add(messageId, dict); - return Task.CompletedTask; + GuildId = guildId.AsLong(), + MessageId = messageId.AsLong(), + RoleId = role.Id.AsLong(), + Reaction = emoji + }); + + if (!_listener.ContainsKey(messageId)) + { + _listener.Add(messageId, new Dictionary()); + } + _listener[messageId].Add(emote, role.Id); } public async void RemoveRole(ISocketMessageChannel channel, SocketReaction reaction) { - var roleId = _listener[reaction.MessageId.ToString()][reaction.Emote]; + var roleId = _listener[reaction.MessageId][reaction.Emote]; var guild = (SocketGuildChannel) channel; var role = guild.Guild.GetRole(roleId); await ((IGuildUser) reaction.User.Value).RemoveRoleAsync(role); @@ -82,10 +68,19 @@ namespace Geekbot.net.Lib.ReactionListener public async void GiveRole(ISocketMessageChannel channel, SocketReaction reaction) { - var roleId = _listener[reaction.MessageId.ToString()][reaction.Emote]; + var roleId = _listener[reaction.MessageId][reaction.Emote]; var guild = (SocketGuildChannel) channel; var role = guild.Guild.GetRole(roleId); await ((IGuildUser) reaction.User.Value).AddRoleAsync(role); } + + public IEmote ConvertStringToEmote(string emoji) + { + if (!emoji.StartsWith('<')) + { + return new Emoji(emoji); + } + return Emote.Parse(emoji); + } } } \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 3bd5a8f..389c051 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -14,6 +14,7 @@ using Geekbot.net.Lib.Converters; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.GlobalSettings; using Geekbot.net.Lib.Highscores; +using Geekbot.net.Lib.KvInMemoryStore; using Geekbot.net.Lib.Levels; using Geekbot.net.Lib.Localization; using Geekbot.net.Lib.Logger; @@ -125,6 +126,7 @@ namespace Geekbot.net var mtgManaConverter = new MtgManaConverter(); var wikipediaClient = new WikipediaClient(); var randomNumberGenerator = new RandomNumberGenerator(); + var kvMemoryStore = new KvInInMemoryStore(); _services.AddSingleton(_redis); _services.AddSingleton(_userRepository); @@ -137,6 +139,7 @@ namespace Geekbot.net _services.AddSingleton(mtgManaConverter); _services.AddSingleton(wikipediaClient); _services.AddSingleton(randomNumberGenerator); + _services.AddSingleton(kvMemoryStore); _services.AddSingleton(_globalSettings); _services.AddTransient(e => new HighscoreManager(_databaseInitializer.Initialize(), _userRepository)); _services.AddTransient(e => _databaseInitializer.Initialize()); @@ -164,7 +167,7 @@ namespace Geekbot.net _logger.Information(LogSource.Geekbot, "Registering Stuff"); var translationHandler = new TranslationHandler(_databaseInitializer.Initialize(), _logger); var errorHandler = new ErrorHandler(_logger, translationHandler, _runParameters.ExposeErrors); - var reactionListener = new ReactionListener(_redis.Db); + var reactionListener = new ReactionListener(_databaseInitializer.Initialize()); _services.AddSingleton(errorHandler); _services.AddSingleton(translationHandler); _services.AddSingleton(_client); From 46fee88f039bf796f54278298151b0b9aee82656 Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 1 Jun 2020 00:52:56 +0200 Subject: [PATCH 322/553] Add a migration script for role listeners --- Geekbot.net/Commands/Admin/Owner/Owner.cs | 79 ++++++++++++++++++- .../Lib/ReactionListener/ReactionListener.cs | 2 + 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/Geekbot.net/Commands/Admin/Owner/Owner.cs b/Geekbot.net/Commands/Admin/Owner/Owner.cs index 996d848..12f41a2 100644 --- a/Geekbot.net/Commands/Admin/Owner/Owner.cs +++ b/Geekbot.net/Commands/Admin/Owner/Owner.cs @@ -1,12 +1,16 @@ using System; +using System.Collections.Generic; using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.WebSocket; +using Geekbot.net.Lib.AlmostRedis; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.GlobalSettings; using Geekbot.net.Lib.Logger; +using Geekbot.net.Lib.ReactionListener; using Geekbot.net.Lib.UserRepository; +using StackExchange.Redis; namespace Geekbot.net.Commands.Admin.Owner { @@ -17,16 +21,22 @@ namespace Geekbot.net.Commands.Admin.Owner private readonly DiscordSocketClient _client; private readonly IErrorHandler _errorHandler; private readonly IGlobalSettings _globalSettings; + private readonly IDatabase _redis; + private readonly IReactionListener _reactionListener; private readonly IGeekbotLogger _logger; private readonly IUserRepository _userRepository; - public Owner(DiscordSocketClient client, IGeekbotLogger logger, IUserRepository userRepositry, IErrorHandler errorHandler, IGlobalSettings globalSettings) + public Owner(DiscordSocketClient client, IGeekbotLogger logger, IUserRepository userRepositry, IErrorHandler errorHandler, IGlobalSettings globalSettings, + IAlmostRedis redis, IReactionListener reactionListener + ) { _client = client; _logger = logger; _userRepository = userRepositry; _errorHandler = errorHandler; _globalSettings = globalSettings; + _redis = redis.Db; + _reactionListener = reactionListener; } [Command("youtubekey", RunMode = RunMode.Async)] @@ -122,5 +132,72 @@ namespace Geekbot.net.Commands.Admin.Owner await _errorHandler.HandleCommandException(e, Context); } } + + [Command("migrate_listeners", RunMode = RunMode.Async)] + public async Task MigrateListeners() + { + try + { + var messageIds = _redis.SetMembers("MessageIds"); + var connectedGuilds = _client.Guilds; + var messageGuildAssociation = new Dictionary(); + foreach (var messageIdUnparsed in messageIds) + { + var messageId = ulong.Parse(messageIdUnparsed); + var reactions = _redis.HashGetAll($"Messages:{messageIdUnparsed.ToString()}"); + + foreach (var reaction in reactions) + { + _logger.Information(LogSource.Migration, $"{messageIdUnparsed.ToString()} - Starting"); + try + { + ulong guildId = 0; + IRole role = null; + + var roleId = ulong.Parse(reaction.Value); + if (messageGuildAssociation.ContainsKey(messageId)) + { + guildId = messageGuildAssociation[messageId]; + _logger.Information(LogSource.Migration, $"{messageIdUnparsed.ToString()} - known to be in {guildId}"); + role = _client.GetGuild(guildId).GetRole(roleId); + } + else + { + _logger.Information(LogSource.Migration, $"{messageIdUnparsed.ToString()} - Attempting to find guild"); + IRole foundRole = null; + try + { + foreach (var guild in connectedGuilds) + { + foundRole = guild.GetRole(roleId); + if (foundRole != null) + { + role = _client.GetGuild(foundRole.Guild.Id).GetRole(ulong.Parse(reaction.Value)); + messageGuildAssociation.Add(messageId, foundRole.Guild.Id); + } + } + } catch { /* ignore */ } + + if (foundRole == null) + { + _logger.Warning(LogSource.Migration, $"{messageIdUnparsed.ToString()} - Could not find guild for message"); + continue; + } + } + _logger.Information(LogSource.Migration, $"{messageIdUnparsed.ToString()} - Found Role {roleId.ToString()}"); + await _reactionListener.AddRoleToListener(ulong.Parse(messageIdUnparsed), guildId, reaction.Name, role); + } + catch (Exception e) + { + _logger.Error(LogSource.Migration, $"Failed to migrate reaction for {messageIdUnparsed.ToString()}", e); + } + } + } + } + catch (Exception e) + { + await _errorHandler.HandleCommandException(e, Context); + } + } } } \ No newline at end of file diff --git a/Geekbot.net/Lib/ReactionListener/ReactionListener.cs b/Geekbot.net/Lib/ReactionListener/ReactionListener.cs index 4a9a08c..bd335af 100644 --- a/Geekbot.net/Lib/ReactionListener/ReactionListener.cs +++ b/Geekbot.net/Lib/ReactionListener/ReactionListener.cs @@ -11,6 +11,7 @@ namespace Geekbot.net.Lib.ReactionListener public class ReactionListener : IReactionListener { private readonly DatabaseContext _database; + // private Dictionary> _listener; public ReactionListener(DatabaseContext database) @@ -50,6 +51,7 @@ namespace Geekbot.net.Lib.ReactionListener RoleId = role.Id.AsLong(), Reaction = emoji }); + await _database.SaveChangesAsync(); if (!_listener.ContainsKey(messageId)) { From 520633c590a7e1f51794145e18b12f1e3730eedb Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 1 Jun 2020 01:02:36 +0200 Subject: [PATCH 323/553] Remove all redis leftovers --- Geekbot.net/Commands/Admin/Owner/Owner.cs | 79 +-------------------- Geekbot.net/Geekbot.net.csproj | 1 - Geekbot.net/Lib/AlmostRedis/AlmostRedis.cs | 35 --------- Geekbot.net/Lib/AlmostRedis/IAlmostRedis.cs | 13 ---- Geekbot.net/Lib/GeekbotExitCode.cs | 2 +- Geekbot.net/Lib/Logger/LogSource.cs | 1 - Geekbot.net/Lib/RunParameters.cs | 13 ---- Geekbot.net/Program.cs | 14 ---- 8 files changed, 2 insertions(+), 156 deletions(-) delete mode 100644 Geekbot.net/Lib/AlmostRedis/AlmostRedis.cs delete mode 100644 Geekbot.net/Lib/AlmostRedis/IAlmostRedis.cs diff --git a/Geekbot.net/Commands/Admin/Owner/Owner.cs b/Geekbot.net/Commands/Admin/Owner/Owner.cs index 12f41a2..996d848 100644 --- a/Geekbot.net/Commands/Admin/Owner/Owner.cs +++ b/Geekbot.net/Commands/Admin/Owner/Owner.cs @@ -1,16 +1,12 @@ using System; -using System.Collections.Generic; using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.WebSocket; -using Geekbot.net.Lib.AlmostRedis; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.GlobalSettings; using Geekbot.net.Lib.Logger; -using Geekbot.net.Lib.ReactionListener; using Geekbot.net.Lib.UserRepository; -using StackExchange.Redis; namespace Geekbot.net.Commands.Admin.Owner { @@ -21,22 +17,16 @@ namespace Geekbot.net.Commands.Admin.Owner private readonly DiscordSocketClient _client; private readonly IErrorHandler _errorHandler; private readonly IGlobalSettings _globalSettings; - private readonly IDatabase _redis; - private readonly IReactionListener _reactionListener; private readonly IGeekbotLogger _logger; private readonly IUserRepository _userRepository; - public Owner(DiscordSocketClient client, IGeekbotLogger logger, IUserRepository userRepositry, IErrorHandler errorHandler, IGlobalSettings globalSettings, - IAlmostRedis redis, IReactionListener reactionListener - ) + public Owner(DiscordSocketClient client, IGeekbotLogger logger, IUserRepository userRepositry, IErrorHandler errorHandler, IGlobalSettings globalSettings) { _client = client; _logger = logger; _userRepository = userRepositry; _errorHandler = errorHandler; _globalSettings = globalSettings; - _redis = redis.Db; - _reactionListener = reactionListener; } [Command("youtubekey", RunMode = RunMode.Async)] @@ -132,72 +122,5 @@ namespace Geekbot.net.Commands.Admin.Owner await _errorHandler.HandleCommandException(e, Context); } } - - [Command("migrate_listeners", RunMode = RunMode.Async)] - public async Task MigrateListeners() - { - try - { - var messageIds = _redis.SetMembers("MessageIds"); - var connectedGuilds = _client.Guilds; - var messageGuildAssociation = new Dictionary(); - foreach (var messageIdUnparsed in messageIds) - { - var messageId = ulong.Parse(messageIdUnparsed); - var reactions = _redis.HashGetAll($"Messages:{messageIdUnparsed.ToString()}"); - - foreach (var reaction in reactions) - { - _logger.Information(LogSource.Migration, $"{messageIdUnparsed.ToString()} - Starting"); - try - { - ulong guildId = 0; - IRole role = null; - - var roleId = ulong.Parse(reaction.Value); - if (messageGuildAssociation.ContainsKey(messageId)) - { - guildId = messageGuildAssociation[messageId]; - _logger.Information(LogSource.Migration, $"{messageIdUnparsed.ToString()} - known to be in {guildId}"); - role = _client.GetGuild(guildId).GetRole(roleId); - } - else - { - _logger.Information(LogSource.Migration, $"{messageIdUnparsed.ToString()} - Attempting to find guild"); - IRole foundRole = null; - try - { - foreach (var guild in connectedGuilds) - { - foundRole = guild.GetRole(roleId); - if (foundRole != null) - { - role = _client.GetGuild(foundRole.Guild.Id).GetRole(ulong.Parse(reaction.Value)); - messageGuildAssociation.Add(messageId, foundRole.Guild.Id); - } - } - } catch { /* ignore */ } - - if (foundRole == null) - { - _logger.Warning(LogSource.Migration, $"{messageIdUnparsed.ToString()} - Could not find guild for message"); - continue; - } - } - _logger.Information(LogSource.Migration, $"{messageIdUnparsed.ToString()} - Found Role {roleId.ToString()}"); - await _reactionListener.AddRoleToListener(ulong.Parse(messageIdUnparsed), guildId, reaction.Name, role); - } - catch (Exception e) - { - _logger.Error(LogSource.Migration, $"Failed to migrate reaction for {messageIdUnparsed.ToString()}", e); - } - } - } - } - catch (Exception e) - { - await _errorHandler.HandleCommandException(e, Context); - } - } } } \ No newline at end of file diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index baf326d..32555e7 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -25,7 +25,6 @@ - diff --git a/Geekbot.net/Lib/AlmostRedis/AlmostRedis.cs b/Geekbot.net/Lib/AlmostRedis/AlmostRedis.cs deleted file mode 100644 index c6faf52..0000000 --- a/Geekbot.net/Lib/AlmostRedis/AlmostRedis.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Collections.Generic; -using Geekbot.net.Lib.Logger; -using StackExchange.Redis; - -namespace Geekbot.net.Lib.AlmostRedis -{ - // if anyone ever sees this, please come up with a better fucking name, i'd appriciate it - public class AlmostRedis : IAlmostRedis - { - private readonly GeekbotLogger _logger; - private readonly RunParameters _runParameters; - - public AlmostRedis(GeekbotLogger logger, RunParameters runParameters) - { - _logger = logger; - _runParameters = runParameters; - } - - public void Connect() - { - Connection = ConnectionMultiplexer.Connect($"{_runParameters.RedisHost}:{_runParameters.RedisPort}"); - Db = Connection.GetDatabase(int.Parse(_runParameters.RedisDatabase)); - _logger.Information(LogSource.Redis, $"Connected to Redis on {Connection.Configuration} at {Db.Database}"); - } - - public IDatabase Db { get; private set; } - - public ConnectionMultiplexer Connection { get; private set; } - - public IEnumerable GetAllKeys() - { - return Connection.GetServer($"{_runParameters.RedisHost}:{_runParameters.RedisPort}").Keys(int.Parse(_runParameters.RedisDatabase)); - } - } -} \ No newline at end of file diff --git a/Geekbot.net/Lib/AlmostRedis/IAlmostRedis.cs b/Geekbot.net/Lib/AlmostRedis/IAlmostRedis.cs deleted file mode 100644 index 549c49e..0000000 --- a/Geekbot.net/Lib/AlmostRedis/IAlmostRedis.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Collections.Generic; -using StackExchange.Redis; - -namespace Geekbot.net.Lib.AlmostRedis -{ - public interface IAlmostRedis - { - void Connect(); - IDatabase Db { get; } - ConnectionMultiplexer Connection { get; } - IEnumerable GetAllKeys(); - } -} \ No newline at end of file diff --git a/Geekbot.net/Lib/GeekbotExitCode.cs b/Geekbot.net/Lib/GeekbotExitCode.cs index 130d435..4d91d18 100644 --- a/Geekbot.net/Lib/GeekbotExitCode.cs +++ b/Geekbot.net/Lib/GeekbotExitCode.cs @@ -10,7 +10,7 @@ TranslationsFailed = 201, // Dependent Services - RedisConnectionFailed = 301, + /* 301 not in use anymore (redis) */ DatabaseConnectionFailed = 302, // Discord Related diff --git a/Geekbot.net/Lib/Logger/LogSource.cs b/Geekbot.net/Lib/Logger/LogSource.cs index 7cd92ff..48ad7d0 100644 --- a/Geekbot.net/Lib/Logger/LogSource.cs +++ b/Geekbot.net/Lib/Logger/LogSource.cs @@ -10,7 +10,6 @@ namespace Geekbot.net.Lib.Logger Rest, Gateway, Discord, - Redis, Database, Message, UserRepository, diff --git a/Geekbot.net/Lib/RunParameters.cs b/Geekbot.net/Lib/RunParameters.cs index e16f644..e17825f 100644 --- a/Geekbot.net/Lib/RunParameters.cs +++ b/Geekbot.net/Lib/RunParameters.cs @@ -50,19 +50,6 @@ namespace Geekbot.net.Lib [Option("db-logging", Default = false, HelpText = "Enable database logging")] public bool DbLogging { get; set; } - /************************************ - * Redis * - ************************************/ - - [Option("redis-host", Default = "127.0.0.1", HelpText = "Set a redis host")] - public string RedisHost { get; set; } - - [Option("redis-port", Default = "6379", HelpText = "Set a redis port")] - public string RedisPort { get; set; } - - [Option("redis-database", Default = "6", HelpText = "Select a redis database (1-15)")] - public string RedisDatabase { get; set; } - /************************************ * WebApi * ************************************/ diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 389c051..d46df90 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -8,7 +8,6 @@ using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Database; using Geekbot.net.Lib; -using Geekbot.net.Lib.AlmostRedis; using Geekbot.net.Lib.Clients; using Geekbot.net.Lib.Converters; using Geekbot.net.Lib.ErrorHandling; @@ -41,7 +40,6 @@ namespace Geekbot.net private GeekbotLogger _logger; private IUserRepository _userRepository; private RunParameters _runParameters; - private IAlmostRedis _redis; private static void Main(string[] args) { @@ -94,17 +92,6 @@ namespace Geekbot.net _globalSettings = new GlobalSettings(database); - try - { - _redis = new AlmostRedis(logger, runParameters); - _redis.Connect(); - } - catch (Exception e) - { - logger.Error(LogSource.Redis, "Redis Connection Failed", e); - Environment.Exit(GeekbotExitCode.RedisConnectionFailed.GetHashCode()); - } - _token = runParameters.Token ?? _globalSettings.GetKey("DiscordToken"); if (string.IsNullOrEmpty(_token)) { @@ -128,7 +115,6 @@ namespace Geekbot.net var randomNumberGenerator = new RandomNumberGenerator(); var kvMemoryStore = new KvInInMemoryStore(); - _services.AddSingleton(_redis); _services.AddSingleton(_userRepository); _services.AddSingleton(logger); _services.AddSingleton(levelCalc); From ff968a490f6b0ebf36235b861240e0245950c9b8 Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 1 Jun 2020 01:13:45 +0200 Subject: [PATCH 324/553] Cleanup some dead code and database models --- Geekbot.net/Database/DatabaseContext.cs | 2 -- Geekbot.net/Database/Models/GuildsModel.cs | 24 ----------------- Geekbot.net/Database/Models/PollModel.cs | 27 ------------------- .../Database/Models/PollQuestionModel.cs | 16 ----------- Geekbot.net/Lib/RunParameters.cs | 9 ------- 5 files changed, 78 deletions(-) delete mode 100644 Geekbot.net/Database/Models/GuildsModel.cs delete mode 100644 Geekbot.net/Database/Models/PollModel.cs delete mode 100644 Geekbot.net/Database/Models/PollQuestionModel.cs diff --git a/Geekbot.net/Database/DatabaseContext.cs b/Geekbot.net/Database/DatabaseContext.cs index 56c19f8..505486f 100644 --- a/Geekbot.net/Database/DatabaseContext.cs +++ b/Geekbot.net/Database/DatabaseContext.cs @@ -7,7 +7,6 @@ namespace Geekbot.net.Database { public DbSet Quotes { get; set; } public DbSet Users { get; set; } - public DbSet Guilds { get; set; } public DbSet GuildSettings { get; set; } public DbSet Karma { get; set; } public DbSet Ships { get; set; } @@ -16,7 +15,6 @@ namespace Geekbot.net.Database public DbSet Slaps { get; set; } public DbSet Globals { get; set; } public DbSet RoleSelfService { get; set; } - public DbSet Polls { get; set; } public DbSet Cookies { get; set; } public DbSet ReactionListeners { get; set; } } diff --git a/Geekbot.net/Database/Models/GuildsModel.cs b/Geekbot.net/Database/Models/GuildsModel.cs deleted file mode 100644 index b6347a6..0000000 --- a/Geekbot.net/Database/Models/GuildsModel.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.ComponentModel.DataAnnotations; - -namespace Geekbot.net.Database.Models -{ - public class GuildsModel - { - [Key] - public int Id { get; set; } - - [Required] - public long GuildId { get; set; } - - [Required] - public string Name { get; set; } - - [Required] - public long Owner { get; set; } - - public string IconUrl { get; set; } - - public DateTimeOffset CreatedAt { get; set; } - } -} \ No newline at end of file diff --git a/Geekbot.net/Database/Models/PollModel.cs b/Geekbot.net/Database/Models/PollModel.cs deleted file mode 100644 index 3b12410..0000000 --- a/Geekbot.net/Database/Models/PollModel.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; - -namespace Geekbot.net.Database.Models -{ - public class PollModel - { - [Key] - public int Id { get; set; } - - [Required] - public long GuildId { get; set; } - - [Required] - public long ChannelId { get; set; } - - public string Question { get; set; } - - public long Creator { get; set; } - - public long MessageId { get; set; } - - public List Options { get; set; } - - public bool IsFinshed { get; set; } - } -} \ No newline at end of file diff --git a/Geekbot.net/Database/Models/PollQuestionModel.cs b/Geekbot.net/Database/Models/PollQuestionModel.cs deleted file mode 100644 index e251fe2..0000000 --- a/Geekbot.net/Database/Models/PollQuestionModel.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace Geekbot.net.Database.Models -{ - public class PollQuestionModel - { - [Key] - public int Id { get; set; } - - public int OptionId { get; set; } - - public string OptionText { get; set; } - - public int Votes { get; set; } - } -} \ No newline at end of file diff --git a/Geekbot.net/Lib/RunParameters.cs b/Geekbot.net/Lib/RunParameters.cs index e17825f..e1386d3 100644 --- a/Geekbot.net/Lib/RunParameters.cs +++ b/Geekbot.net/Lib/RunParameters.cs @@ -59,14 +59,5 @@ namespace Geekbot.net.Lib [Option("api-port", Default = "12995", HelpText = "Port on which the WebApi listens")] public string ApiPort { get; set; } - - /************************************ - * Prometheus * - ************************************/ - [Option("prometheus-host", Default = "localhost", HelpText = "Host on which the Prometheus Metric Server listens")] - public string PrometheusHost { get; set; } - - [Option("prometheus-port", Default = "12991", HelpText = "Port on which the Prometheus Metric Server listens")] - public string PrometheusPort { get; set; } } } \ No newline at end of file From 3108a68407341a64b3ce3d07ef7419414ef35c3c Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 1 Jun 2020 02:16:29 +0200 Subject: [PATCH 325/553] Dependency Upgrades --- Geekbot.net/Commands/Utils/Quote/Quote.cs | 2 +- Geekbot.net/Geekbot.net.csproj | 30 +++++++++---------- Geekbot.net/Lib/Extensions/DbSetExtensions.cs | 11 +++++++ Geekbot.net/Lib/Polyfills/UserPolyfillDto.cs | 2 ++ Tests/Tests.csproj | 6 ++-- 5 files changed, 32 insertions(+), 19 deletions(-) diff --git a/Geekbot.net/Commands/Utils/Quote/Quote.cs b/Geekbot.net/Commands/Utils/Quote/Quote.cs index 5c2bd3b..6288bef 100644 --- a/Geekbot.net/Commands/Utils/Quote/Quote.cs +++ b/Geekbot.net/Commands/Utils/Quote/Quote.cs @@ -252,7 +252,7 @@ namespace Geekbot.net.Commands.Utils.Quote try { var list = Context.Channel.GetMessagesAsync().Flatten(); - return await list.FirstOrDefault(msg => + return await list.FirstOrDefaultAsync(msg => msg.Author.Id == user.Id && msg.Embeds.Count == 0 && msg.Id != Context.Message.Id && diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 32555e7..0d39cae 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -20,28 +20,28 @@ true - - - - + + + + - - - - - - - - + + + + + + + + - - - + + + diff --git a/Geekbot.net/Lib/Extensions/DbSetExtensions.cs b/Geekbot.net/Lib/Extensions/DbSetExtensions.cs index c731fc0..e08b2d4 100644 --- a/Geekbot.net/Lib/Extensions/DbSetExtensions.cs +++ b/Geekbot.net/Lib/Extensions/DbSetExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore; @@ -13,5 +14,15 @@ namespace Geekbot.net.Lib.Extensions var exists = predicate != null ? dbSet.Any(predicate) : dbSet.Any(); return !exists ? dbSet.Add(entity) : null; } + + // https://github.com/dotnet/efcore/issues/18124 + public static IAsyncEnumerable AsAsyncEnumerable(this Microsoft.EntityFrameworkCore.DbSet obj) where TEntity : class + { + return Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.AsAsyncEnumerable(obj); + } + public static IQueryable Where(this Microsoft.EntityFrameworkCore.DbSet obj, System.Linq.Expressions.Expression> predicate) where TEntity : class + { + return System.Linq.Queryable.Where(obj, predicate); + } } } \ No newline at end of file diff --git a/Geekbot.net/Lib/Polyfills/UserPolyfillDto.cs b/Geekbot.net/Lib/Polyfills/UserPolyfillDto.cs index 6d81581..32ea663 100644 --- a/Geekbot.net/Lib/Polyfills/UserPolyfillDto.cs +++ b/Geekbot.net/Lib/Polyfills/UserPolyfillDto.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Immutable; using System.Threading.Tasks; using Discord; @@ -11,6 +12,7 @@ namespace Geekbot.net.Lib.Polyfills public string Mention { get; set; } public IActivity Activity { get; } public UserStatus Status { get; set; } + public IImmutableSet ActiveClients { get; } public string AvatarId { get; set; } public string Discriminator { get; set; } public ushort DiscriminatorValue { get; set; } diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 235cc0b..345dacd 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -6,9 +6,9 @@ xUnit1026 - - - + + + From 6692b3bc778bdb90db6a737e44ecddeae1cd7431 Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 1 Jun 2020 02:17:15 +0200 Subject: [PATCH 326/553] Don't show a quote id when using '!quote make' --- Geekbot.net/Commands/Utils/Quote/Quote.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Geekbot.net/Commands/Utils/Quote/Quote.cs b/Geekbot.net/Commands/Utils/Quote/Quote.cs index 6288bef..7af8a4c 100644 --- a/Geekbot.net/Commands/Utils/Quote/Quote.cs +++ b/Geekbot.net/Commands/Utils/Quote/Quote.cs @@ -270,7 +270,14 @@ namespace Geekbot.net.Commands.Utils.Quote var user = Context.Client.GetUserAsync(quote.UserId.AsUlong()).Result ?? new UserPolyfillDto { Username = "Unknown User" }; var eb = new EmbedBuilder(); eb.WithColor(new Color(143, 167, 232)); - eb.Title = $"#{quote.InternalId} | {user.Username} @ {quote.Time.Day}.{quote.Time.Month}.{quote.Time.Year}"; + if (quote.InternalId == 0) + { + eb.Title = $"{user.Username} @ {quote.Time.Day}.{quote.Time.Month}.{quote.Time.Year}"; + } + else + { + eb.Title = $"#{quote.InternalId} | {user.Username} @ {quote.Time.Day}.{quote.Time.Month}.{quote.Time.Year}"; + } eb.Description = quote.Quote; eb.ThumbnailUrl = user.GetAvatarUrl(); if (quote.Image != null) eb.ImageUrl = quote.Image; @@ -289,9 +296,8 @@ namespace Geekbot.net.Commands.Utils.Quote image = null; } - var last = _database.Quotes.Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())) - .OrderByDescending(e => e.InternalId).FirstOrDefault(); - var internalId = 1; + var last = _database.Quotes.Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())).OrderByDescending(e => e.InternalId).FirstOrDefault(); + var internalId = 0; if (last != null) internalId = last.InternalId + 1; return new QuoteModel() { From d91c21e607f4aeb7be3eee88106319b22914aef0 Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 1 Jun 2020 02:20:27 +0200 Subject: [PATCH 327/553] update readme --- readme.md | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/readme.md b/readme.md index 7d8544f..ffc320c 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -[![pipeline status](https://git.boerlage.me/open/Geekbot.net/badges/master/pipeline.svg)](https://git.boerlage.me/open/Geekbot.net/commits/master) +[![pipeline status](https://gitlab.com/dbgit/open/geekbot/badges/master/pipeline.svg)](https://gitlab.com/dbgit/open/geekbot/commits/master) # [Geekbot.net](https://geekbot.pizzaandcoffee.rocks/) @@ -8,22 +8,19 @@ You can invite Geekbot to your server with [this link](https://discordapp.com/oa ## Technologies -* DotNet Core 2 -* Redis +* DotNet Core 3.1 +* PostgreSQL * Discord.net ## Running -Make sure redis is running +You can start geekbot with: `dotnet run` -Run these commands +On your first run geekbot will ask for your bot token. -* `dotnet restore` -* `dotnet run` +You might need to pass some additional configuration (e.g. database credentials), these can be passed as commandline arguments. -On your first run geekbot will ask for your bot token, everything else is taken care of. - -For a list of launch options use `dotnet run -h` +For a list of commandline arguments use `dotnet run -- -h` ## Contributing From 8018d5e7501d09a32186a4fe5bd374ab9bb2b957 Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 1 Jun 2020 15:22:41 +0200 Subject: [PATCH 328/553] Allow configuration to be passed as environment variables --- Geekbot.net/Lib/RunParameters.cs | 98 +++++++++++++++++++++----------- readme.md | 6 +- 2 files changed, 70 insertions(+), 34 deletions(-) diff --git a/Geekbot.net/Lib/RunParameters.cs b/Geekbot.net/Lib/RunParameters.cs index e1386d3..1ddbd46 100644 --- a/Geekbot.net/Lib/RunParameters.cs +++ b/Geekbot.net/Lib/RunParameters.cs @@ -1,4 +1,5 @@ -using CommandLine; +using System; +using CommandLine; namespace Geekbot.net.Lib { @@ -8,56 +9,89 @@ namespace Geekbot.net.Lib * General * ************************************/ - [Option('V', "verbose", Default = false, HelpText = "Logs everything.")] - public bool Verbose { get; set; } + [Option("token", HelpText = "Set a new bot token. By default it will use your previous bot token which was stored in the database (default: null) (env: TOKEN)")] + public string Token { get; set; } = ParamFallback("TOKEN"); - [Option('j', "log-json", Default = false, HelpText = "Logger outputs json")] - public bool LogJson { get; set; } + [Option('V', "verbose", HelpText = "Logs everything. (default: false) (env: LOG_VERBOSE)")] + public bool Verbose { get; set; } = ParamFallback("LOG_VERBOSE", false); - [Option('a', "disable-api", Default = false, HelpText = "Disables the web api")] - public bool DisableApi { get; set; } + [Option('j', "log-json", HelpText = "Logger outputs json (default: false ) (env: LOG_JSON)")] + public bool LogJson { get; set; } = ParamFallback("LOG_JSON", false); + + [Option('e', "expose-errors", HelpText = "Shows internal errors in the chat (default: false) (env: EXPOSE_ERRORS)")] + public bool ExposeErrors { get; set; } = ParamFallback("EXPOSE_ERRORS", false); - [Option('e', "expose-errors", Default = false, HelpText = "Shows internal errors in the chat")] - public bool ExposeErrors { get; set; } - - [Option("token", Default = null, HelpText = "Set a new bot token")] - public string Token { get; set; } - /************************************ * Database * ************************************/ - [Option("in-memory", Default = false, HelpText = "Uses the in-memory database instead of postgresql")] - public bool InMemory { get; set; } + [Option("in-memory", HelpText = "Uses the in-memory database instead of postgresql (default: false) (env: DB_INMEMORY)")] + public bool InMemory { get; set; } = ParamFallback("DB_INMEMORY", false); // Postresql connection - [Option("database", Default = "geekbot", HelpText = "Select a postgresql database")] - public string DbDatabase { get; set; } + [Option("database", HelpText = "Select a postgresql database (default: geekbot) (env: DB_DATABASE)")] + public string DbDatabase { get; set; } = ParamFallback("DB_DATABASE", "geekbot"); - [Option("db-host", Default = "localhost", HelpText = "Set a postgresql host (e.g. 127.0.0.1)")] - public string DbHost { get; set; } + [Option("db-host", HelpText = "Set a postgresql host (default: localhost) (env: DB_HOST)")] + public string DbHost { get; set; } = ParamFallback("DB_HOST", "localhost"); - [Option("db-port", Default = "5432", HelpText = "Set a postgresql host (e.g. 5432)")] - public string DbPort { get; set; } + [Option("db-port", HelpText = "Set a postgresql host (default: 5432) (env: DB_PORT)")] + public string DbPort { get; set; } = ParamFallback("DB_PORT", "5432"); - [Option("db-user", Default = "geekbot", HelpText = "Set a postgresql user")] - public string DbUser { get; set; } + [Option("db-user", HelpText = "Set a postgresql user (default: geekbot) (env: DB_USER)")] + public string DbUser { get; set; } = ParamFallback("DB_USER", "geekbot"); - [Option("db-password", Default = "", HelpText = "Set a posgresql password")] - public string DbPassword { get; set; } + [Option("db-password", HelpText = "Set a posgresql password (default: empty) (env: DB_PASSWORD)")] + public string DbPassword { get; set; } = ParamFallback("DB_PASSWORD", ""); // Logging - [Option("db-logging", Default = false, HelpText = "Enable database logging")] - public bool DbLogging { get; set; } + [Option("db-logging", HelpText = "Enable database logging (default: false) (env: DB_LOGGING)")] + public bool DbLogging { get; set; } = ParamFallback("DB_LOGGING", false); /************************************ * WebApi * ************************************/ - - [Option("api-host", Default = "localhost", HelpText = "Host on which the WebApi listens")] - public string ApiHost { get; set; } - [Option("api-port", Default = "12995", HelpText = "Port on which the WebApi listens")] - public string ApiPort { get; set; } + [Option('a', "disable-api", HelpText = "Disables the WebApi (default: false) (env: API_DISABLE)")] + public bool DisableApi { get; set; } = ParamFallback("API_DISABLE", false); + + [Option("api-host", HelpText = "Host on which the WebApi listens (default: localhost) (env: API_HOST)")] + public string ApiHost { get; set; } = ParamFallback("API_HOST", "localhost"); + + [Option("api-port", HelpText = "Port on which the WebApi listens (default: 12995) (env: API_PORT)")] + public string ApiPort { get; set; } = ParamFallback("API_PORT", "12995"); + + /************************************ + * Helper Functions * + ************************************/ + + private static string ParamFallback(string key, string defaultValue = null) + { + var envVar = GetEnvironmentVariable(key); + return !string.IsNullOrEmpty(envVar) ? envVar : defaultValue; + } + + private static bool ParamFallback(string key, bool defaultValue) + { + var envVar = GetEnvironmentVariable(key); + if (!string.IsNullOrEmpty(envVar)) + { + return envVar.ToLower() switch + { + "true" => true, + "1" => true, + "false" => false, + "0" => false, + _ => defaultValue + }; + } + + return defaultValue; + } + + private static string GetEnvironmentVariable(string name) + { + return Environment.GetEnvironmentVariable($"GEEKBOT_{name}"); + } } } \ No newline at end of file diff --git a/readme.md b/readme.md index ffc320c..c7f3f33 100644 --- a/readme.md +++ b/readme.md @@ -18,9 +18,11 @@ You can start geekbot with: `dotnet run` On your first run geekbot will ask for your bot token. -You might need to pass some additional configuration (e.g. database credentials), these can be passed as commandline arguments. +You might need to pass some additional configuration (e.g. database credentials), these can be passed as commandline arguments or environment variables. -For a list of commandline arguments use `dotnet run -- -h` +For a list of commandline arguments and environment variables use `dotnet run -- -h` + +All Environment Variables must be prefixed with `GEEKBOT_` ## Contributing From 0898e9b6bd9e6c135e951e0a1a0c89fbb6df00c6 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 14 Jun 2020 17:27:07 +0200 Subject: [PATCH 329/553] Add the timeout in !roll back --- Geekbot.net/Commands/Games/{ => Roll}/Roll.cs | 19 ++++++++++--------- .../Commands/Games/Roll/RollTimeout.cs | 10 ++++++++++ Geekbot.net/Lib/Localization/Translations.yml | 4 ++-- 3 files changed, 22 insertions(+), 11 deletions(-) rename Geekbot.net/Commands/Games/{ => Roll}/Roll.cs (83%) create mode 100644 Geekbot.net/Commands/Games/Roll/RollTimeout.cs diff --git a/Geekbot.net/Commands/Games/Roll.cs b/Geekbot.net/Commands/Games/Roll/Roll.cs similarity index 83% rename from Geekbot.net/Commands/Games/Roll.cs rename to Geekbot.net/Commands/Games/Roll/Roll.cs index 076cf8f..1c89f19 100644 --- a/Geekbot.net/Commands/Games/Roll.cs +++ b/Geekbot.net/Commands/Games/Roll/Roll.cs @@ -10,7 +10,7 @@ using Geekbot.net.Lib.KvInMemoryStore; using Geekbot.net.Lib.Localization; using Geekbot.net.Lib.RandomNumberGenerator; -namespace Geekbot.net.Commands.Games +namespace Geekbot.net.Commands.Games.Roll { public class Roll : ModuleBase { @@ -42,17 +42,18 @@ namespace Geekbot.net.Commands.Games { var kvKey = $"{Context.Guild.Id}:{Context.User.Id}:RollsPrevious"; - var prevRoll = _kvInMemoryStore.Get(kvKey); - if (prevRoll > 0) + var prevRoll = _kvInMemoryStore.Get(kvKey); + + if (prevRoll?.LastGuess == guess && prevRoll?.GuessedOn.AddDays(1) > DateTime.Now) { - if (prevRoll == guess) - { - await ReplyAsync(transContext.GetString("NoPrevGuess", Context.Message.Author.Mention)); - return; - } + await ReplyAsync(transContext.GetString( + "NoPrevGuess", + Context.Message.Author.Mention, + transContext.FormatDateTimeAsRemaining(prevRoll.GuessedOn.AddDays(1)))); + return; } - _kvInMemoryStore.Set(kvKey, guess); + _kvInMemoryStore.Set(kvKey, new RollTimeout { LastGuess = guess, GuessedOn = DateTime.Now }); await ReplyAsync(transContext.GetString("Rolled", Context.Message.Author.Mention, number, guess)); if (guess == number) diff --git a/Geekbot.net/Commands/Games/Roll/RollTimeout.cs b/Geekbot.net/Commands/Games/Roll/RollTimeout.cs new file mode 100644 index 0000000..81a520f --- /dev/null +++ b/Geekbot.net/Commands/Games/Roll/RollTimeout.cs @@ -0,0 +1,10 @@ +using System; + +namespace Geekbot.net.Commands.Games.Roll +{ + public class RollTimeout + { + public int LastGuess { get; set; } + public DateTime GuessedOn { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Localization/Translations.yml b/Geekbot.net/Lib/Localization/Translations.yml index a19a6f3..3c59977 100644 --- a/Geekbot.net/Lib/Localization/Translations.yml +++ b/Geekbot.net/Lib/Localization/Translations.yml @@ -83,8 +83,8 @@ roll: EN: "{0}, you rolled {1}" CHDE: "{0}, du hesch {1} grollt" NoPrevGuess: - EN: ":red_circle: {0}, you can't guess the same number again" - CHDE: ":red_circle: {0}, du chasch nid nomol es gliche rate" + EN: ":red_circle: {0}, you can't guess the same number again, guess another number or wait {1}" + CHDE: ":red_circle: {0}, du chasch nid nomol es gliche rate, rate öppis anders oder warte {1}" cookies: &cookiesAlias GetCookies: EN: "You got {0} cookies, there are now {1} cookies in you cookie jar" From 12199f4ad475554be327dada2e2369fd428ab9e7 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 18 Jun 2020 19:19:02 +0200 Subject: [PATCH 330/553] Add greetings in 299 languages --- .../Randomness/Greetings/GreetingDto.cs | 10 + .../Randomness/Greetings/GreetingProvider.cs | 1600 +++++++++++++++++ .../Randomness/Greetings/Greetings.cs | 50 + 3 files changed, 1660 insertions(+) create mode 100644 Geekbot.net/Commands/Randomness/Greetings/GreetingDto.cs create mode 100644 Geekbot.net/Commands/Randomness/Greetings/GreetingProvider.cs create mode 100644 Geekbot.net/Commands/Randomness/Greetings/Greetings.cs diff --git a/Geekbot.net/Commands/Randomness/Greetings/GreetingDto.cs b/Geekbot.net/Commands/Randomness/Greetings/GreetingDto.cs new file mode 100644 index 0000000..42792a5 --- /dev/null +++ b/Geekbot.net/Commands/Randomness/Greetings/GreetingDto.cs @@ -0,0 +1,10 @@ +namespace Geekbot.net.Commands.Randomness.Greetings +{ + public class GreetingDto + { + public string Text { get; set; } + public string Language { get; set; } + public string Dialect { get; set; } = null; + public string Romanization { get; set; } = null; + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Randomness/Greetings/GreetingProvider.cs b/Geekbot.net/Commands/Randomness/Greetings/GreetingProvider.cs new file mode 100644 index 0000000..52d8d18 --- /dev/null +++ b/Geekbot.net/Commands/Randomness/Greetings/GreetingProvider.cs @@ -0,0 +1,1600 @@ +using System.Collections.Generic; + +namespace Geekbot.net.Commands.Randomness.Greetings +{ + public class GreetingProvider + { + public static readonly List Greetings = new List + { + new GreetingDto() + { + Text = "Бзиа збаша", + Language = "Abkhaz", + Romanization = "Bzia zbaşa" + }, + new GreetingDto() + { + Text = "Фэсапщы", + Language = "Adyghe", + Romanization = "Fèsapŝy" + }, + new GreetingDto() + { + Text = "Haai", + Language = "Afrikaans" + }, + new GreetingDto() + { + Text = "Kamusta", + Language = "Aklan" + }, + new GreetingDto() + { + Text = "Fâla", + Language = "Albanian" + }, + new GreetingDto() + { + Text = "Ç'kemi", + Language = "Albanian" + }, + new GreetingDto() + { + Text = "Aang", + Language = "Aleut" + }, + new GreetingDto() + { + Text = "Hallo", + Language = "Alsatian" + }, + new GreetingDto() + { + Text = "Эзендер", + Language = "Altay", + Romanization = "Ezender" + }, + new GreetingDto() + { + Text = "ሰላም።", + Language = "Amharic", + Romanization = "sälam" + }, + new GreetingDto() + { + Text = "السلام عليكم", + Language = "Arabic", + Romanization = "as-salām 'alaykum" + }, + new GreetingDto() + { + Text = "Ola", + Language = "Aragonese" + }, + new GreetingDto() + { + Text = "Shl'am lak", + Language = "Aramaic" + }, + new GreetingDto() + { + Text = "Héébee", + Language = "Arapaho" + }, + new GreetingDto() + { + Text = "Բարեւ", + Language = "Armenian", + Romanization = "Parev" + }, + new GreetingDto() + { + Text = "Bunâ dzuâ", + Language = "Aromanian" + }, + new GreetingDto() + { + Text = "Werte", + Language = "Arrernte" + }, + new GreetingDto() + { + Text = "নমস্কাৰ", + Language = "Assamese", + Romanization = "নমস্কাৰ" + }, + new GreetingDto() + { + Text = "Hola", + Language = "Asturian" + }, + new GreetingDto() + { + Text = "Kwei", + Language = "Atikamekw" + }, + new GreetingDto() + { + Text = "Laphi!", + Language = "Aymara" + }, + new GreetingDto() + { + Text = "Salam", + Language = "Azerbaijani" + }, + new GreetingDto() + { + Text = "Swastyastu", + Language = "Balinese" + }, + new GreetingDto() + { + Text = "I ni ce", + Language = "Bambara" + }, + new GreetingDto() + { + Text = "Haku'", + Language = "Barbareño" + }, + new GreetingDto() + { + Text = "сәләм", + Language = "Bashkir", + Romanization = "sәlәm" + }, + new GreetingDto() + { + Text = "Kaixo", + Language = "Basque" + }, + new GreetingDto() + { + Text = "Horas", + Language = "Batak" + }, + new GreetingDto() + { + Text = "მარშიხ ვალ", + Language = "Batsbi", + Romanization = "Maršix val" + }, + new GreetingDto() + { + Text = "Seavus", + Language = "Bavarian" + }, + new GreetingDto() + { + Text = "Вітаю", + Language = "Belarusian", + Romanization = "Vіtaju" + }, + new GreetingDto() + { + Text = "Shani", + Language = "Bemba" + }, + new GreetingDto() + { + Text = "নমস্কার", + Language = "Bengali", + Romanization = "Nômôskar", + Dialect = "Hindus" + }, + new GreetingDto() + { + Text = "আসসালামু আলাইকুম", + Language = "Bengali", + Romanization = "Asôlamu alaikum", + Dialect = "Muslims" + }, + new GreetingDto() + { + Text = "प्रणाम", + Language = "Bhojpuri", + Romanization = "prannam" + }, + new GreetingDto() + { + Text = "Hello", + Language = "Bikol" + }, + new GreetingDto() + { + Text = "Halo", + Language = "Bislama" + }, + new GreetingDto() + { + Text = "Dobar dan", + Language = "Bosnian" + }, + new GreetingDto() + { + Text = "Salud", + Language = "Breton" + }, + new GreetingDto() + { + Text = "Здравейте", + Language = "Bulgarian" + }, + new GreetingDto() + { + Text = "မဂႆလာပၝ", + Language = "Burmese", + Romanization = "min-ga-la-ba" + }, + new GreetingDto() + { + Text = "Olá", + Language = "Cape Verdean Creole" + }, + new GreetingDto() + { + Text = "Hola", + Language = "Catalan" + }, + new GreetingDto() + { + Text = "Hello", + Language = "Cebuano" + }, + new GreetingDto() + { + Text = "Kopisanangan", + Language = "Central Dusun" + }, + new GreetingDto() + { + Text = "Que tal?", + Language = "Chabacano de Zamboanga" + }, + new GreetingDto() + { + Text = "Ola", + Language = "Chabacano de Cavite" + }, + new GreetingDto() + { + Text = "Håfa ådai", + Language = "Chamorro", + Dialect = "Guam" + }, + new GreetingDto() + { + Text = "Hafa Adai", + Language = "Chamorro", + Dialect = "North Marianas" + }, + new GreetingDto() + { + Text = "Салам", + Language = "Chechen", + Romanization = "Salam" + }, + new GreetingDto() + { + Text = "ᎣᏏᏲ", + Language = "Cherokee", + Romanization = "Osiyo" + }, + new GreetingDto() + { + Text = "Moni", + Language = "Chichewa" + }, + new GreetingDto() + { + Text = "你好", + Language = "Chinese", + Romanization = "nǐ hǎo", + Dialect = "Mandarin" + }, + new GreetingDto() + { + Text = "ʔédlánet’é", + Language = "Chipewyan" + }, + new GreetingDto() + { + Text = "Halito", + Language = "Choctaw" + }, + new GreetingDto() + { + Text = "Ran annim", + Language = "Chuukese" + }, + new GreetingDto() + { + Text = "Салам!", + Language = "Chuvash", + Romanization = "Salam!" + }, + new GreetingDto() + { + Text = "Guuten takh!", + Language = "Cimbrian" + }, + new GreetingDto() + { + Text = "Kopivosian", + Language = "Coastal Kadazan" + }, + new GreetingDto() + { + Text = "Marʉ́awe", + Language = "Comanche" + }, + new GreetingDto() + { + Text = "Dydh da", + Language = "Cornish" + }, + new GreetingDto() + { + Text = "Salute", + Language = "Corsican" + }, + new GreetingDto() + { + Text = "ᑕᓂᓯ", + Language = "Cree", + Romanization = "Tanisi" + }, + new GreetingDto() + { + Text = "Bok", + Language = "Croatian" + }, + new GreetingDto() + { + Text = "Sho'daache", + Language = "Crow" + }, + new GreetingDto() + { + Text = "Míyaxwe", + Language = "Cupeño" + }, + new GreetingDto() + { + Text = "Hello", + Language = "Cuyonon" + }, + new GreetingDto() + { + Text = "Ahoj", + Language = "Czech" + }, + new GreetingDto() + { + Text = "Hej", + Language = "Danish" + }, + new GreetingDto() + { + Text = "ااسال م عليكم", + Language = "Dari", + Romanization = "As-salâmo 'alaykom" + }, + new GreetingDto() + { + Text = "Misawa", + Language = "Dholuo" + }, + new GreetingDto() + { + Text = "Goededag", + Language = "Dutch" + }, + new GreetingDto() + { + Text = "སྐུ་གཟུགས་བཟང་པོ་ལགས།", + Language = "Dzongkha", + Romanization = "Kuzu zangpo la" + }, + new GreetingDto() + { + Text = "Mọkọm", + Language = "Efik" + }, + new GreetingDto() + { + Text = "Häj ą̊ dig!", + Language = "Elfdalian" + }, + new GreetingDto() + { + Text = "Hello", + Language = "English" + }, + new GreetingDto() + { + Text = "Tere", + Language = "Estonian" + }, + new GreetingDto() + { + Text = "Ola!", + Language = "Extremaduran" + }, + new GreetingDto() + { + Text = "Hallo", + Language = "Faroese" + }, + new GreetingDto() + { + Text = "Bula", + Language = "Fijian" + }, + new GreetingDto() + { + Text = "Hyvää päivää", + Language = "Finnish" + }, + new GreetingDto() + { + Text = "Bonjour", + Language = "French" + }, + new GreetingDto() + { + Text = "Guundach", + Language = "Frisian", + Dialect = "North Frisian" + }, + new GreetingDto() + { + Text = "Gouden Dai", + Language = "Frisian", + Dialect = "Saterland" + }, + new GreetingDto() + { + Text = "Goeie", + Language = "Frisian", + Dialect = "West Frisian" + }, + new GreetingDto() + { + Text = "Mandi", + Language = "Friulian" + }, + new GreetingDto() + { + Text = "Ola", + Language = "Galician" + }, + new GreetingDto() + { + Text = "सिवासौँळी", + Language = "Garhwali", + Romanization = "sivāsauṁḻī" + }, + new GreetingDto() + { + Text = "Buiti binafi", + Language = "Garifuna" + }, + new GreetingDto() + { + Text = "გამარჯობა", + Language = "Georgian", + Romanization = "gamarjoba" + }, + new GreetingDto() + { + Text = "Guten Tag", + Language = "German" + }, + new GreetingDto() + { + Text = "Χαῖρε", + Language = "Greek", + Romanization = "Khaĩre", + Dialect = "Ancient" + }, + new GreetingDto() + { + Text = "Γειά", + Language = "Greek", + Romanization = "Geiá", + Dialect = "Ancient" + }, + new GreetingDto() + { + Text = "something", + Language = "something" + }, + new GreetingDto() + { + Text = "Aluu", + Language = "Greenlandic" + }, + new GreetingDto() + { + Text = "નમસ્તે", + Language = "Gujarati", + Romanization = "namaste" + }, + new GreetingDto() + { + Text = "Bonjou", + Language = "Haitian Creole" + }, + new GreetingDto() + { + Text = "Sannu", + Language = "Hausa" + }, + new GreetingDto() + { + Text = "Aloha", + Language = "Hawaiian" + }, + new GreetingDto() + { + Text = "שלום", + Language = "Hebrew", + Romanization = "Shalom" + }, + new GreetingDto() + { + Text = "something", + Language = "something" + }, + new GreetingDto() + { + Text = "Tjike", + Language = "Herero" + }, + new GreetingDto() + { + Text = "Mono", + Language = "Himba" + }, + new GreetingDto() + { + Text = "नमस्ते", + Language = "Hindi", + Romanization = "namaste" + }, + new GreetingDto() + { + Text = "Nyob zoo", + Language = "Hmong", + Dialect = "White" + }, + new GreetingDto() + { + Text = "Jó napot kívánok", + Language = "Hungarian" + }, + new GreetingDto() + { + Text = "Góðan dag", + Language = "Icelandic" + }, + new GreetingDto() + { + Text = "Ndeewo", + Language = "Igbo" + }, + new GreetingDto() + { + Text = "Kablaaw", + Language = "Iloko" + }, + new GreetingDto() + { + Text = "Tiervâ", + Language = "Inari Saami" + }, + new GreetingDto() + { + Text = "Hi", + Language = "Indonesian" + }, + new GreetingDto() + { + Text = "ᐊᐃ", + Language = "Inuktitut", + Romanization = "Ai" + }, + new GreetingDto() + { + Text = "Haluu", + Language = "Iñupiaq" + }, + new GreetingDto() + { + Text = "Dia dhuit", + Language = "Irish" + }, + new GreetingDto() + { + Text = "Ciao", + Language = "Italian" + }, + new GreetingDto() + { + Text = "Míyaxwen", + Language = "Ivilyuat" + }, + new GreetingDto() + { + Text = "Ello", + Language = "Jamaican" + }, + new GreetingDto() + { + Text = "今日は", + Language = "Japanese", + Romanization = "konnichiwa" + }, + new GreetingDto() + { + Text = "ꦲꦭꦺꦴ", + Language = "Javanese", + Romanization = "Halo" + }, + new GreetingDto() + { + Text = "Puiznu", + Language = "Jenesch" + }, + new GreetingDto() + { + Text = "Salut", + Language = "Jèrriais" + }, + new GreetingDto() + { + Text = "Godaw", + Language = "Jutish" + }, + new GreetingDto() + { + Text = "Мендвт", + Language = "Kalmyk" + }, + new GreetingDto() + { + Text = "Tọi", + Language = "Kam" + }, + new GreetingDto() + { + Text = "ನಮಸ್ತೆ", + Language = "Kannada", + Romanization = "namaste" + }, + new GreetingDto() + { + Text = "Xsaqär", + Language = "Kaqchikel" + }, + new GreetingDto() + { + Text = "Ayukîi", + Language = "Karuk" + }, + new GreetingDto() + { + Text = "Witéj", + Language = "Kashubian" + }, + new GreetingDto() + { + Text = "असलामु अलैकुम", + Language = "Kashmiri", + Romanization = "asalāmu alaikuma" + }, + new GreetingDto() + { + Text = "Hagare'enaam", + Language = "Kawaiisu" + }, + new GreetingDto() + { + Text = "Сәлем", + Language = "Kazakh", + Romanization = "Sälem" + }, + new GreetingDto() + { + Text = "ជំរាបសួរ", + Language = "Khmer", + Romanization = "chôm rab suôr" + }, + new GreetingDto() + { + Text = "Halau", + Language = "Khoekhoe" + }, + new GreetingDto() + { + Text = "wĩmwega", + Language = "Kikuyu" + }, + new GreetingDto() + { + Text = "Muraho", + Language = "Kinyarwanda" + }, + new GreetingDto() + { + Text = "Ko na mauri", + Language = "Kiribati" + }, + new GreetingDto() + { + Text = "안녕하십니까", + Language = "Korean", + Romanization = "annyeong-hasimnikka" + }, + new GreetingDto() + { + Text = "Haawka", + Language = "Kumeyaay" + }, + new GreetingDto() + { + Text = "!kao", + Language = "Kung San" + }, + new GreetingDto() + { + Text = "Rojbash", + Language = "Kurdish", + Dialect = "Kurmanji" + }, + new GreetingDto() + { + Text = "Sillaw", + Language = "Kurdish", + Dialect = "Sorani" + }, + new GreetingDto() + { + Text = "Салам!", + Language = "Kyrgyz", + Romanization = "Salam!" + }, + new GreetingDto() + { + Text = "בוינוס דייאס", + Language = "Ladino", + Romanization = "Buenos diyas" + }, + new GreetingDto() + { + Text = "Hau", + Language = "Lakota Sioux" + }, + new GreetingDto() + { + Text = "ສະບາຍດີ", + Language = "Lao", + Romanization = "sába̖ai-di̖i" + }, + new GreetingDto() + { + Text = "Ave", + Language = "Latin" + }, + new GreetingDto() + { + Text = "Sveiki", + Language = "Latvian" + }, + new GreetingDto() + { + Text = "გეგაჯგინას", + Language = "Laz", + Romanization = "Gegacginas" + }, + new GreetingDto() + { + Text = "Салам алейкум", + Language = "Lezgi", + Romanization = "Salam alejkum" + }, + new GreetingDto() + { + Text = "Hallo", + Language = "Limburgish" + }, + new GreetingDto() + { + Text = "Mbote", + Language = "Lingala" + }, + new GreetingDto() + { + Text = "Labas", + Language = "Lithuanian" + }, + new GreetingDto() + { + Text = "Moin", + Language = "Low Saxon" + }, + new GreetingDto() + { + Text = "Lumela", + Language = "Lozi" + }, + new GreetingDto() + { + Text = "Gyebale ko", + Language = "Luganda" + }, + new GreetingDto() + { + Text = "Buoris", + Language = "Lule Sámi" + }, + new GreetingDto() + { + Text = "Mííyu", + Language = "Luiseño" + }, + new GreetingDto() + { + Text = "Moien", + Language = "Luxembourgish" + }, + new GreetingDto() + { + Text = "Здраво", + Language = "Macedonian", + Romanization = "Zdravo" + }, + new GreetingDto() + { + Text = "परनाम", + Language = "Magahi", + Romanization = "Pernaam" + }, + new GreetingDto() + { + Text = "प्रनाम", + Language = "Maithili", + Romanization = "Pranaam" + }, + new GreetingDto() + { + Text = "Manao ahoana", + Language = "Malagasy" + }, + new GreetingDto() + { + Text = "Selamat pagi", + Language = "Malay" + }, + new GreetingDto() + { + Text = "നമസ്തേ", + Language = "Malayalam", + Romanization = "namastē" + }, + new GreetingDto() + { + Text = "Jeeka, ma tzuula", + Language = "Mam" + }, + new GreetingDto() + { + Text = "Moghrey mie", + Language = "Gaelic", + Dialect = "Manx" + }, + new GreetingDto() + { + Text = "Assalaamu Alaikum", + Language = "Maldivian" + }, + new GreetingDto() + { + Text = "Ħello", + Language = "Maltese" + }, + new GreetingDto() + { + Text = "Kia ora", + Language = "Māori" + }, + new GreetingDto() + { + Text = "Mari mari", + Language = "Mapuche" + }, + new GreetingDto() + { + Text = "नमस्कार", + Language = "Marathi", + Romanization = "namaskāra" + }, + new GreetingDto() + { + Text = "Io̧kwe", + Language = "Marshallese" + }, + new GreetingDto() + { + Text = "Bonzur", + Language = "Mauritian Creole" + }, + new GreetingDto() + { + Text = "Gwe’", + Language = "Míkmaq" + }, + new GreetingDto() + { + Text = "ဟာဲ", + Language = "Mon", + Romanization = "hāai" + }, + new GreetingDto() + { + Text = "Ciau", + Language = "Monégasque" + }, + new GreetingDto() + { + Text = "Сайн уу", + Language = "Mongolian", + Romanization = "Sain uu" + }, + new GreetingDto() + { + Text = "Manahúú", + Language = "Mono" + }, + new GreetingDto() + { + Text = "Ne y windiga", + Language = "Mossi" + }, + new GreetingDto() + { + Text = "Niltze", + Language = "Nahuatl" + }, + new GreetingDto() + { + Text = "Ekamowir omo", + Language = "Nauruan" + }, + new GreetingDto() + { + Text = "Yá'át'ééh", + Language = "Navajo" + }, + new GreetingDto() + { + Text = "ज्वजलपा", + Language = "Newari", + Romanization = "jvajalapā" + }, + new GreetingDto() + { + Text = "Oraire ota?", + Language = "Nkore" + }, + new GreetingDto() + { + Text = "Salibonani", + Language = "Ndebele" + }, + new GreetingDto() + { + Text = "Lotjhani", + Language = "Southern Ndebele" + }, + new GreetingDto() + { + Text = "नमस्ते", + Language = "Nepali", + Romanization = "namaste" + }, + new GreetingDto() + { + Text = "Fakaalofa atu", + Language = "Niuean" + }, + new GreetingDto() + { + Text = "Салам!", + Language = "Nogai" + }, + new GreetingDto() + { + Text = "Bures", + Language = "Northern Sámi" + }, + new GreetingDto() + { + Text = "Dumêlang", + Language = "Northern Sotho" + }, + new GreetingDto() + { + Text = "Goddag", + Language = "Norwegian" + }, + new GreetingDto() + { + Text = "Hatʸu", + Language = "Northern Chumash" + }, + new GreetingDto() + { + Text = "Bonjorn", + Language = "Occitan" + }, + new GreetingDto() + { + Text = "Aniin", + Language = "Ojibwe" + }, + new GreetingDto() + { + Text = "今日拝なびら", + Language = "Okinawan", + Romanization = "chuu wuganabira" + }, + new GreetingDto() + { + Text = "Wes hāl", + Language = "Old English" + }, + new GreetingDto() + { + Text = "Ƿes hāl", + Language = "Old Prussian" + }, + new GreetingDto() + { + Text = "Ahó", + Language = "Omaha" + }, + new GreetingDto() + { + Text = "ନମସ୍କାର", + Language = "Oriya", + Romanization = "Namascāra" + }, + new GreetingDto() + { + Text = "Alii", + Language = "Palauan" + }, + new GreetingDto() + { + Text = "Bon dia", + Language = "Papiamento" + }, + new GreetingDto() + { + Text = "ښې چارې", + Language = "Pashto", + Romanization = "khe chare" + }, + new GreetingDto() + { + Text = "Gude Daag", + Language = "Pennsylvania Deitsch" + }, + new GreetingDto() + { + Text = "درود", + Language = "Persian", + Romanization = "dorood", + Dialect = "Farsi" + }, + new GreetingDto() + { + Text = "Bojour", + Language = "Picard" + }, + new GreetingDto() + { + Text = "Wai", + Language = "Pitjantjatjara" + }, + new GreetingDto() + { + Text = "Cześć", + Language = "Polish" + }, + new GreetingDto() + { + Text = "Olá", + Language = "Portuguese", + Dialect = "Protugal" + }, + new GreetingDto() + { + Text = "Oi", + Language = "Portuguese", + Dialect = "Brazilian" + }, + new GreetingDto() + { + Text = "ਸਤਿ ਸ੍ਰੀ ਅਕਾਲ।", + Language = "Punjabi", + Romanization = "sat srī akāl" + }, + new GreetingDto() + { + Text = "Rimaykullayki", + Language = "Quechua" + }, + new GreetingDto() + { + Text = "'Iorana", + Language = "Rapa Nui" + }, + new GreetingDto() + { + Text = "Bonzour", + Language = "Réunion Creole" + }, + new GreetingDto() + { + Text = "Sastipe", + Language = "Romani" + }, + new GreetingDto() + { + Text = "Salut", + Language = "Romanian" + }, + new GreetingDto() + { + Text = "Ciao", + Language = "Romansh" + }, + new GreetingDto() + { + Text = "Привет", + Language = "Russian", + Romanization = "Privet" + }, + new GreetingDto() + { + Text = "Слава Исусу Христу", + Language = "Rusyn", + Dialect = "Slava Ysusu Chrystu" + }, + new GreetingDto() + { + Text = "бирибиэт", + Language = "Sakha", + Romanization = "biribiet" + }, + new GreetingDto() + { + Text = "Malō", + Language = "Samoan" + }, + new GreetingDto() + { + Text = "Bara mo", + Language = "Sango" + }, + new GreetingDto() + { + Text = "नमस्ते", + Language = "Sanskrit", + Romanization = "namaste" + }, + new GreetingDto() + { + Text = "Saludi", + Language = "Sardinian", + Dialect = "Campidanese" + }, + new GreetingDto() + { + Text = "Bone die", + Language = "Sardinian", + Dialect = "Logudorese" + }, + new GreetingDto() + { + Text = "Hullo", + Language = "Scots" + }, + new GreetingDto() + { + Text = "Halò", + Language = "Gaelic", + Dialect = "Scottish" + }, + new GreetingDto() + { + Text = "Здраво", + Language = "Serbian", + Dialect = "Zdravo" + }, + new GreetingDto() + { + Text = "Lumela", + Language = "Sesotho" + }, + new GreetingDto() + { + Text = "Mhoro", + Language = "Shona" + }, + new GreetingDto() + { + Text = "Ciau", + Language = "Sicilian" + }, + new GreetingDto() + { + Text = "سَلامُ", + Language = "Sindhi", + Romanization = "Salāmu" + }, + new GreetingDto() + { + Text = "ආයුඛෝවන්", + Language = "Sinhala", + Romanization = "āyubūvan" + }, + new GreetingDto() + { + Text = "Dobry den", + Language = "Slovak" + }, + new GreetingDto() + { + Text = "Pozdravljeni", + Language = "Slovenian" + }, + new GreetingDto() + { + Text = "Simi", + Language = "Solresol" + }, + new GreetingDto() + { + Text = "Salaam alaykum", + Language = "Somali" + }, + new GreetingDto() + { + Text = "Dobry źeń", + Language = "Sorbian", + Dialect = "Lower Sorbian" + }, + new GreetingDto() + { + Text = "Dobry dźeń", + Language = "Sorbian", + Dialect = "Upper Sorbian" + }, + new GreetingDto() + { + Text = "Buaregh", + Language = "Southern Sámi" + }, + new GreetingDto() + { + Text = "¡Hola!", + Language = "Spanish" + }, + new GreetingDto() + { + Text = "Hoj", + Language = "Stellingwarfs" + }, + new GreetingDto() + { + Text = "Sampurasun", + Language = "Sundanese" + }, + new GreetingDto() + { + Text = "Habari", + Language = "Swahili" + }, + new GreetingDto() + { + Text = "Sawubona", + Language = "Swazi" + }, + new GreetingDto() + { + Text = "God dag", + Language = "Swedish" + }, + new GreetingDto() + { + Text = "Grüezi", + Language = "Swiss German" + }, + new GreetingDto() + { + Text = "Салам", + Language = "Tabassaran", + Romanization = "Salam" + }, + new GreetingDto() + { + Text = "Musta?", + Language = "Tagalog" + }, + new GreetingDto() + { + Text = "'Ia ora na", + Language = "Tahitian" + }, + new GreetingDto() + { + Text = "Ассалому алейкум", + Language = "Tajik", + Romanization = "Assalomu alejkym" + }, + new GreetingDto() + { + Text = "வணக்கம்", + Language = "Tamil", + Romanization = "vaṇakkam" + }, + new GreetingDto() + { + Text = "Isänme", + Language = "Tatar" + }, + new GreetingDto() + { + Text = "నమస్కారం", + Language = "Telugu", + Romanization = "namaskārām" + }, + new GreetingDto() + { + Text = "Elo", + Language = "Tetum" + }, + new GreetingDto() + { + Text = "Miga", + Language = "Teribe" + }, + new GreetingDto() + { + Text = "สวัสดี", + Language = "Thai", + Romanization = "sà-wàt-dee" + }, + new GreetingDto() + { + Text = "བཀྲ་ཤིས་བདེ་ལེགས།", + Language = "Tibetan", + Romanization = "tashi delek" + }, + new GreetingDto() + { + Text = "ሰላም", + Language = "Tigrinya", + Romanization = "selam" + }, + new GreetingDto() + { + Text = "Tālofa", + Language = "Tokelauan" + }, + new GreetingDto() + { + Text = "Gude", + Language = "Tok Pisin" + }, + new GreetingDto() + { + Text = "Mālō e lelei", + Language = "Tongan" + }, + new GreetingDto() + { + Text = "Miiyiha", + Language = "Tongva", + Dialect = "Gabrielino" + }, + new GreetingDto() + { + Text = "Xewani", + Language = "Tsonga" + }, + new GreetingDto() + { + Text = "K'uxi", + Language = "Tsotsil" + }, + new GreetingDto() + { + Text = "Dumela", + Language = "Tswana" + }, + new GreetingDto() + { + Text = "АсаламугIалейкум!", + Language = "Tsez", + Romanization = "AsalamugIalejkum!" + }, + new GreetingDto() + { + Text = "Monile", + Language = "Tumbuka" + }, + new GreetingDto() + { + Text = "Merhaba", + Language = "Turkish" + }, + new GreetingDto() + { + Text = "Salam", + Language = "Turkmen" + }, + new GreetingDto() + { + Text = "Вітаю", + Language = "Ukrainian" + }, + new GreetingDto() + { + Text = "Сородэ", + Language = "Ulch", + Romanization = "Sorodè" + }, + new GreetingDto() + { + Text = "السلام علیکم", + Language = "Urdu", + Romanization = "āssālam 'alaykum" + }, + new GreetingDto() + { + Text = "ئەسسالامۇ ئەلەيكۇم", + Language = "Uyghur", + Romanization = "Ässalamu äläykum" + }, + new GreetingDto() + { + Text = "Assalomu Alaykum", + Language = "Uzbek" + }, + new GreetingDto() + { + Text = "I nhlikanhi", + Language = "Venda" + }, + new GreetingDto() + { + Text = "Ciao", + Language = "Venetian" + }, + new GreetingDto() + { + Text = "Tervhen", + Language = "Veps" + }, + new GreetingDto() + { + Text = "Chào anh", + Language = "Vietnamese" + }, + new GreetingDto() + { + Text = "Tereq", + Language = "Võro" + }, + new GreetingDto() + { + Text = "Bondjoû", + Language = "Walloon" + }, + new GreetingDto() + { + Text = "Ngurrju mayinpa", + Language = "Warlpiri" + }, + new GreetingDto() + { + Text = "Helô", + Language = "Welsh" + }, + new GreetingDto() + { + Text = "Hej", + Language = "Westrobothnian" + }, + new GreetingDto() + { + Text = "Na nga def", + Language = "Wolof" + }, + new GreetingDto() + { + Text = "Molo", + Language = "Xhosa" + }, + new GreetingDto() + { + Text = "Mogethin", + Language = "Yapese" + }, + new GreetingDto() + { + Text = "אַ גוטן טאָג", + Language = "Yiddish", + Romanization = "A gutn tog" + }, + new GreetingDto() + { + Text = "Ẹ n lẹ", + Language = "Yoruba" + }, + new GreetingDto() + { + Text = "Ba'ax ka wa'alik?", + Language = "Yucatec Maya" + }, + new GreetingDto() + { + Text = "Selam", + Language = "Zazaki" + }, + new GreetingDto() + { + Text = "Sawubona", + Language = "Zulu" + }, + new GreetingDto() + { + Text = "Saluton", + Language = "Esperanto" + }, + new GreetingDto() + { + Text = "Bon die!", + Language = "Interlingua" + }, + new GreetingDto() + { + Text = "nuqneH", + Language = "Klingon" + }, + new GreetingDto() + { + Text = "Aiya", + Language = "Quenya" + }, + new GreetingDto() + { + Text = "Glidö", + Language = "Volapük" + }, + new GreetingDto() + { + Text = "Saluto", + Language = "Ido" + } + }; + + public static readonly int GreetingCount = Greetings.Count; + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Randomness/Greetings/Greetings.cs b/Geekbot.net/Commands/Randomness/Greetings/Greetings.cs new file mode 100644 index 0000000..83cdd63 --- /dev/null +++ b/Geekbot.net/Commands/Randomness/Greetings/Greetings.cs @@ -0,0 +1,50 @@ +using System; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Extensions; + +namespace Geekbot.net.Commands.Randomness.Greetings +{ + public class Greetings : ModuleBase + { + private readonly IErrorHandler _errorHandler; + + public Greetings(IErrorHandler errorHandler) + { + _errorHandler = errorHandler; + } + + [Command("hello", RunMode = RunMode.Async)] + [Alias("greeting")] + [Summary("Say hello to the bot and get a reply in a random language")] + public async Task GetGreeting() + { + try + { + var greeting = GreetingProvider.Greetings[new Random().Next(GreetingProvider.GreetingCount - 1)]; + + var eb = new EmbedBuilder(); + eb.Title = greeting.Text; + eb.AddInlineField("Language", greeting.Language); + + if (greeting.Dialect != null) + { + eb.AddInlineField("Dialect", greeting.Dialect); + } + + if (greeting.Romanization != null) + { + eb.AddInlineField("Romanization", greeting.Romanization); + } + + await ReplyAsync(string.Empty, false, eb.Build()); + } + catch (Exception e) + { + await _errorHandler.HandleCommandException(e, Context); + } + } + } +} \ No newline at end of file From f7908c2a0c2a48ba2d0c73f654cf01a5884155a1 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 19 Jun 2020 00:10:43 +0200 Subject: [PATCH 331/553] - Remove accidental leftover from the GreetingProvider - Add 2 additional aliases for !hello - Change Romanization to Roman in the !hello embed --- .../Commands/Randomness/Greetings/GreetingProvider.cs | 5 ----- Geekbot.net/Commands/Randomness/Greetings/Greetings.cs | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Geekbot.net/Commands/Randomness/Greetings/GreetingProvider.cs b/Geekbot.net/Commands/Randomness/Greetings/GreetingProvider.cs index 52d8d18..a15f32e 100644 --- a/Geekbot.net/Commands/Randomness/Greetings/GreetingProvider.cs +++ b/Geekbot.net/Commands/Randomness/Greetings/GreetingProvider.cs @@ -507,11 +507,6 @@ namespace Geekbot.net.Commands.Randomness.Greetings Dialect = "Ancient" }, new GreetingDto() - { - Text = "something", - Language = "something" - }, - new GreetingDto() { Text = "Aluu", Language = "Greenlandic" diff --git a/Geekbot.net/Commands/Randomness/Greetings/Greetings.cs b/Geekbot.net/Commands/Randomness/Greetings/Greetings.cs index 83cdd63..334b894 100644 --- a/Geekbot.net/Commands/Randomness/Greetings/Greetings.cs +++ b/Geekbot.net/Commands/Randomness/Greetings/Greetings.cs @@ -17,7 +17,7 @@ namespace Geekbot.net.Commands.Randomness.Greetings } [Command("hello", RunMode = RunMode.Async)] - [Alias("greeting")] + [Alias("greeting", "hi", "hallo")] [Summary("Say hello to the bot and get a reply in a random language")] public async Task GetGreeting() { @@ -36,7 +36,7 @@ namespace Geekbot.net.Commands.Randomness.Greetings if (greeting.Romanization != null) { - eb.AddInlineField("Romanization", greeting.Romanization); + eb.AddInlineField("Roman", greeting.Romanization); } await ReplyAsync(string.Empty, false, eb.Build()); From 83dc2c8e49350a3bcb1e3cc2cd8ca3ec1a81338b Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 19 Jun 2020 03:34:37 +0200 Subject: [PATCH 332/553] Attempt to improve code quality with a fearless refactor - Completely refactor Program.cs - Split Handlers into separate files - Split up the command handler into multiple functions --- Geekbot.net/Handlers.cs | 280 ------------------ Geekbot.net/Handlers/CommandHandler.cs | 117 ++++++++ Geekbot.net/Handlers/MessageDeletedHandler.cs | 55 ++++ Geekbot.net/Handlers/ReactionHandler.cs | 33 +++ Geekbot.net/Handlers/StatsHandler.cs | 62 ++++ Geekbot.net/Handlers/UserHandler.cs | 96 ++++++ .../Lib/Logger/SimpleConextConverter.cs | 3 +- Geekbot.net/Program.cs | 223 +++++++------- 8 files changed, 488 insertions(+), 381 deletions(-) delete mode 100644 Geekbot.net/Handlers.cs create mode 100644 Geekbot.net/Handlers/CommandHandler.cs create mode 100644 Geekbot.net/Handlers/MessageDeletedHandler.cs create mode 100644 Geekbot.net/Handlers/ReactionHandler.cs create mode 100644 Geekbot.net/Handlers/StatsHandler.cs create mode 100644 Geekbot.net/Handlers/UserHandler.cs diff --git a/Geekbot.net/Handlers.cs b/Geekbot.net/Handlers.cs deleted file mode 100644 index 6f98041..0000000 --- a/Geekbot.net/Handlers.cs +++ /dev/null @@ -1,280 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Discord; -using Discord.Commands; -using Discord.Rest; -using Discord.WebSocket; -using Geekbot.net.Database; -using Geekbot.net.Database.Models; -using Geekbot.net.Lib.Extensions; -using Geekbot.net.Lib.Logger; -using Geekbot.net.Lib.ReactionListener; -using Geekbot.net.Lib.UserRepository; -using Microsoft.EntityFrameworkCore; - -namespace Geekbot.net -{ - public class Handlers - { - private readonly DatabaseContext _database; - private readonly IDiscordClient _client; - private readonly IGeekbotLogger _logger; - private readonly IServiceProvider _servicesProvider; - private readonly CommandService _commands; - private readonly IUserRepository _userRepository; - private readonly IReactionListener _reactionListener; - private readonly DatabaseContext _messageCounterDatabaseContext; - private readonly RestApplication _applicationInfo; - private readonly List _ignoredServers; - - public Handlers(DatabaseInitializer databaseInitializer, IDiscordClient client, IGeekbotLogger logger, - IServiceProvider servicesProvider, CommandService commands, IUserRepository userRepository, - IReactionListener reactionListener, RestApplication applicationInfo) - { - _database = databaseInitializer.Initialize(); - _messageCounterDatabaseContext = databaseInitializer.Initialize(); - _client = client; - _logger = logger; - _servicesProvider = servicesProvider; - _commands = commands; - _userRepository = userRepository; - _reactionListener = reactionListener; - _applicationInfo = applicationInfo; - // ToDo: create a clean solution for this... - _ignoredServers = new List() - { - 228623803201224704, // SwitzerLAN - 169844523181015040, // EEvent - 248531441548263425, // MYI - 110373943822540800 // Discord Bots - }; - } - - // - // Incoming Messages - // - - public Task RunCommand(SocketMessage messageParam) - { - try - { - if (!(messageParam is SocketUserMessage message)) return Task.CompletedTask; - if (message.Author.IsBot) return Task.CompletedTask; - var argPos = 0; - - var guildId = ((SocketGuildChannel) message.Channel).Guild.Id; - // Some guilds only wanted very specific functionally without any of the commands, a quick hack that solves that short term... - // ToDo: cleanup - if (_ignoredServers.Contains(guildId)) - { - if (message.Author.Id != _applicationInfo.Owner.Id) - { - return Task.CompletedTask; - } - } - - var lowCaseMsg = message.ToString().ToLower(); - if (lowCaseMsg.StartsWith("hui")) - { - var hasPing = _database.GuildSettings.FirstOrDefault(guild => guild.GuildId.Equals(guildId.AsLong()))?.Hui ?? false; - if (hasPing) - { - message.Channel.SendMessageAsync("hui!!!"); - return Task.CompletedTask; - } - } - - if (lowCaseMsg.StartsWith("ping ") || lowCaseMsg.Equals("ping")) - { - var hasPing = _database.GuildSettings.FirstOrDefault(guild => guild.GuildId.Equals(guildId.AsLong()))?.Ping ?? false; - if (hasPing) - { - message.Channel.SendMessageAsync("pong"); - return Task.CompletedTask; - } - } - - if (!(message.HasCharPrefix('!', ref argPos) || - message.HasMentionPrefix(_client.CurrentUser, ref argPos))) return Task.CompletedTask; - var context = new CommandContext(_client, message); - _commands.ExecuteAsync(context, argPos, _servicesProvider); - _logger.Information(LogSource.Command, - context.Message.Content.Split(" ")[0].Replace("!", ""), - SimpleConextConverter.ConvertContext(context)); - return Task.CompletedTask; - } - catch (Exception e) - { - _logger.Error(LogSource.Geekbot, "Failed to Process Message", e); - return Task.CompletedTask; - } - } - - public async Task UpdateStats(SocketMessage message) - { - try - { - if (message == null) return; - if (message.Channel.Name.StartsWith('@')) - { - _logger.Information(LogSource.Message, $"[DM-Channel] {message.Content}", SimpleConextConverter.ConvertSocketMessage(message, true)); - return; - } - - var channel = (SocketGuildChannel) message.Channel; - - var rowId = await _messageCounterDatabaseContext.Database.ExecuteSqlRawAsync( - "UPDATE \"Messages\" SET \"MessageCount\" = \"MessageCount\" + 1 WHERE \"GuildId\" = {0} AND \"UserId\" = {1}", - channel.Guild.Id.AsLong(), - message.Author.Id.AsLong() - ); - - if (rowId == 0) - { - _messageCounterDatabaseContext.Messages.Add(new MessagesModel - { - UserId = message.Author.Id.AsLong(), - GuildId = channel.Guild.Id.AsLong(), - MessageCount = 1 - }); - _messageCounterDatabaseContext.SaveChanges(); - } - - if (message.Author.IsBot) return; - _logger.Information(LogSource.Message, message.Content, SimpleConextConverter.ConvertSocketMessage(message)); - } - catch (Exception e) - { - _logger.Error(LogSource.Message, "Could not process message stats", e); - } - } - - // - // User Stuff - // - - public async Task UserJoined(SocketGuildUser user) - { - try - { - var userRepoUpdate = _userRepository.Update(user); - _logger.Information(LogSource.Geekbot, $"{user.Username} ({user.Id}) joined {user.Guild.Name} ({user.Guild.Id})"); - - if (!user.IsBot) - { - var guildSettings = _database.GuildSettings.FirstOrDefault(guild => guild.GuildId == user.Guild.Id.AsLong()); - var message = guildSettings?.WelcomeMessage; - if (string.IsNullOrEmpty(message)) return; - message = message.Replace("$user", user.Mention); - - var fallbackSender = new Func>(() => user.Guild.DefaultChannel.SendMessageAsync(message)); - if (guildSettings.WelcomeChannel != 0) - { - try - { - var target = await _client.GetChannelAsync(guildSettings.WelcomeChannel.AsUlong()); - var channel = target as ISocketMessageChannel; - await channel.SendMessageAsync(message); - } - catch (Exception e) - { - _logger.Error(LogSource.Geekbot, "Failed to send welcome message to user defined welcome channel", e); - await fallbackSender(); - } - } - else - { - await fallbackSender(); - } - } - - await userRepoUpdate; - } - catch (Exception e) - { - _logger.Error(LogSource.Geekbot, "Failed to send welcome message", e); - } - } - - public async Task UserUpdated(SocketUser oldUser, SocketUser newUser) - { - await _userRepository.Update(newUser); - } - - public async Task UserLeft(SocketGuildUser user) - { - try - { - var guild = _database.GuildSettings.FirstOrDefault(g => - g.GuildId.Equals(user.Guild.Id.AsLong())); - if (guild?.ShowLeave ?? false) - { - var modChannelSocket = (ISocketMessageChannel) await _client.GetChannelAsync(guild.ModChannel.AsUlong()); - await modChannelSocket.SendMessageAsync($"{user.Username}#{user.Discriminator} left the server"); - } - } - catch (Exception e) - { - _logger.Error(LogSource.Geekbot, "Failed to send leave message", e); - } - - _logger.Information(LogSource.Geekbot, $"{user.Username} ({user.Id}) joined {user.Guild.Name} ({user.Guild.Id})"); - } - - // - // Message Stuff - // - - public async Task MessageDeleted(Cacheable message, ISocketMessageChannel channel) - { - try - { - var guildSocketData = ((IGuildChannel) channel).Guild; - var guild = _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(guildSocketData.Id.AsLong())); - if ((guild?.ShowDelete ?? false) && guild?.ModChannel != 0) - { - var modChannelSocket = (ISocketMessageChannel) await _client.GetChannelAsync(guild.ModChannel.AsUlong()); - var sb = new StringBuilder(); - if (message.Value != null) - { - sb.AppendLine($"The following message from {message.Value.Author.Username}#{message.Value.Author.Discriminator} was deleted in <#{channel.Id}>"); - sb.AppendLine(message.Value.Content); - } - else - { - sb.AppendLine("Someone deleted a message, the message was not cached..."); - } - - await modChannelSocket.SendMessageAsync(sb.ToString()); - } - } - catch (Exception e) - { - _logger.Error(LogSource.Geekbot, "Failed to send delete message...", e); - } - } - - // - // Reactions - // - - public Task ReactionAdded(Cacheable cacheable, ISocketMessageChannel socketMessageChannel, SocketReaction reaction) - { - if (reaction.User.Value.IsBot) return Task.CompletedTask; - if (!_reactionListener.IsListener(reaction.MessageId)) return Task.CompletedTask; - _reactionListener.GiveRole(socketMessageChannel, reaction); - return Task.CompletedTask; - } - - public Task ReactionRemoved(Cacheable cacheable, ISocketMessageChannel socketMessageChannel, SocketReaction reaction) - { - if (reaction.User.Value.IsBot) return Task.CompletedTask; - if (!_reactionListener.IsListener(reaction.MessageId)) return Task.CompletedTask; - _reactionListener.RemoveRole(socketMessageChannel, reaction); - return Task.CompletedTask; - } - } -} \ No newline at end of file diff --git a/Geekbot.net/Handlers/CommandHandler.cs b/Geekbot.net/Handlers/CommandHandler.cs new file mode 100644 index 0000000..5074ff2 --- /dev/null +++ b/Geekbot.net/Handlers/CommandHandler.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Discord.Rest; +using Discord.WebSocket; +using Geekbot.net.Database; +using Geekbot.net.Database.Models; +using Geekbot.net.Lib.Extensions; +using Geekbot.net.Lib.Logger; + +namespace Geekbot.net.Handlers +{ + public class CommandHandler + { + private readonly IDiscordClient _client; + private readonly IGeekbotLogger _logger; + private readonly IServiceProvider _servicesProvider; + private readonly CommandService _commands; + private readonly RestApplication _applicationInfo; + private readonly List _ignoredServers; + private readonly DatabaseContext _database; + + public CommandHandler(DatabaseContext database, IDiscordClient client, IGeekbotLogger logger, IServiceProvider servicesProvider, CommandService commands, RestApplication applicationInfo) + { + _database = database; + _client = client; + _logger = logger; + _servicesProvider = servicesProvider; + _commands = commands; + _applicationInfo = applicationInfo; + + // Some guilds only want very specific functionally without any of the commands, a quick hack that solves that "short term" + // ToDo: create a clean solution for this... + _ignoredServers = new List + { + 228623803201224704, // SwitzerLAN + 169844523181015040, // EEvent + 248531441548263425, // MYI + 110373943822540800 // Discord Bots + }; + } + + public Task RunCommand(SocketMessage messageParam) + { + try + { + if (!(messageParam is SocketUserMessage message)) return Task.CompletedTask; + if (message.Author.IsBot) return Task.CompletedTask; + + var guildId = ((SocketGuildChannel) message.Channel).Guild.Id; + if (IsIgnoredGuild(guildId, message.Author.Id)) return Task.CompletedTask; + + var lowCaseMsg = message.ToString().ToLower(); + if (ShouldHui(lowCaseMsg, guildId)) + { + message.Channel.SendMessageAsync("hui!!!"); + return Task.CompletedTask; + } + + if (ShouldPong(lowCaseMsg, guildId)) + { + message.Channel.SendMessageAsync("pong"); + return Task.CompletedTask; + } + + var argPos = 0; + if (!IsCommand(message, ref argPos)) return Task.CompletedTask; + + ExecuteCommand(message, argPos); + } + catch (Exception e) + { + _logger.Error(LogSource.Geekbot, "Failed to Process Message", e); + } + + return Task.CompletedTask; + } + + private void ExecuteCommand(IUserMessage message, int argPos) + { + var context = new CommandContext(_client, message); + _commands.ExecuteAsync(context, argPos, _servicesProvider); + _logger.Information(LogSource.Command, context.Message.Content.Split(" ")[0].Replace("!", ""), SimpleConextConverter.ConvertContext(context)); + } + + private bool IsIgnoredGuild(ulong guildId, ulong authorId) + { + if (!_ignoredServers.Contains(guildId)) return false; + return authorId == _applicationInfo.Owner.Id; + } + + private bool IsCommand(IUserMessage message, ref int argPos) + { + return message.HasCharPrefix('!', ref argPos) || message.HasMentionPrefix(_client.CurrentUser, ref argPos); + } + + private bool ShouldPong(string lowerCaseMessage, ulong guildId) + { + if (!lowerCaseMessage.StartsWith("ping ") && !lowerCaseMessage.Equals("ping")) return false; + return GetGuildSettings(guildId)?.Ping ?? false; + } + + private bool ShouldHui(string lowerCaseMessage, ulong guildId) + { + if (!lowerCaseMessage.StartsWith("hui")) return false; + return GetGuildSettings(guildId)?.Hui ?? false; + } + + private GuildSettingsModel GetGuildSettings(ulong guildId) + { + return _database.GuildSettings.FirstOrDefault(guild => guild.GuildId.Equals(guildId.AsLong())); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Handlers/MessageDeletedHandler.cs b/Geekbot.net/Handlers/MessageDeletedHandler.cs new file mode 100644 index 0000000..5595cff --- /dev/null +++ b/Geekbot.net/Handlers/MessageDeletedHandler.cs @@ -0,0 +1,55 @@ +using System; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Discord; +using Discord.WebSocket; +using Geekbot.net.Database; +using Geekbot.net.Lib.Extensions; +using Geekbot.net.Lib.Logger; + +namespace Geekbot.net.Handlers +{ + public class MessageDeletedHandler + { + private readonly DatabaseContext _database; + private readonly IGeekbotLogger _logger; + private readonly IDiscordClient _client; + + public MessageDeletedHandler(DatabaseContext database, IGeekbotLogger logger, IDiscordClient client) + { + _database = database; + _logger = logger; + _client = client; + } + + public async Task HandleMessageDeleted(Cacheable message, ISocketMessageChannel channel) + { + try + { + var guildSocketData = ((IGuildChannel) channel).Guild; + var guild = _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(guildSocketData.Id.AsLong())); + if ((guild?.ShowDelete ?? false) && guild?.ModChannel != 0) + { + var modChannelSocket = (ISocketMessageChannel) await _client.GetChannelAsync(guild.ModChannel.AsUlong()); + var sb = new StringBuilder(); + if (message.Value != null) + { + sb.AppendLine($"The following message from {message.Value.Author.Username}#{message.Value.Author.Discriminator} was deleted in <#{channel.Id}>"); + sb.AppendLine(message.Value.Content); + } + else + { + sb.AppendLine("Someone deleted a message, the message was not cached..."); + } + + await modChannelSocket.SendMessageAsync(sb.ToString()); + } + } + catch (Exception e) + { + _logger.Error(LogSource.Geekbot, "Failed to send delete message...", e); + } + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Handlers/ReactionHandler.cs b/Geekbot.net/Handlers/ReactionHandler.cs new file mode 100644 index 0000000..e2355a8 --- /dev/null +++ b/Geekbot.net/Handlers/ReactionHandler.cs @@ -0,0 +1,33 @@ +using System.Threading.Tasks; +using Discord; +using Discord.WebSocket; +using Geekbot.net.Lib.ReactionListener; + +namespace Geekbot.net.Handlers +{ + public class ReactionHandler + { + private readonly IReactionListener _reactionListener; + + public ReactionHandler(IReactionListener reactionListener) + { + _reactionListener = reactionListener; + } + + public Task Added(Cacheable cacheable, ISocketMessageChannel socketMessageChannel, SocketReaction reaction) + { + if (reaction.User.Value.IsBot) return Task.CompletedTask; + if (!_reactionListener.IsListener(reaction.MessageId)) return Task.CompletedTask; + _reactionListener.GiveRole(socketMessageChannel, reaction); + return Task.CompletedTask; + } + + public Task Removed(Cacheable cacheable, ISocketMessageChannel socketMessageChannel, SocketReaction reaction) + { + if (reaction.User.Value.IsBot) return Task.CompletedTask; + if (!_reactionListener.IsListener(reaction.MessageId)) return Task.CompletedTask; + _reactionListener.RemoveRole(socketMessageChannel, reaction); + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Handlers/StatsHandler.cs b/Geekbot.net/Handlers/StatsHandler.cs new file mode 100644 index 0000000..56c0894 --- /dev/null +++ b/Geekbot.net/Handlers/StatsHandler.cs @@ -0,0 +1,62 @@ +using System; +using System.Threading.Tasks; +using Discord.WebSocket; +using Geekbot.net.Database; +using Geekbot.net.Database.Models; +using Geekbot.net.Lib.Extensions; +using Geekbot.net.Lib.Logger; +using Microsoft.EntityFrameworkCore; + +namespace Geekbot.net.Handlers +{ + public class StatsHandler + { + private readonly IGeekbotLogger _logger; + private readonly DatabaseContext _database; + + public StatsHandler(IGeekbotLogger logger, DatabaseContext database) + { + _logger = logger; + _database = database; + } + + public async Task UpdateStats(SocketMessage message) + { + try + { + if (message == null) return; + if (message.Channel.Name.StartsWith('@')) + { + _logger.Information(LogSource.Message, $"[DM-Channel] {message.Content}", SimpleConextConverter.ConvertSocketMessage(message, true)); + return; + } + + var channel = (SocketGuildChannel) message.Channel; + + var rowId = await _database.Database.ExecuteSqlRawAsync( + "UPDATE \"Messages\" SET \"MessageCount\" = \"MessageCount\" + 1 WHERE \"GuildId\" = {0} AND \"UserId\" = {1}", + channel.Guild.Id.AsLong(), + message.Author.Id.AsLong() + ); + + if (rowId == 0) + { + await _database.Messages.AddAsync(new MessagesModel + { + UserId = message.Author.Id.AsLong(), + GuildId = channel.Guild.Id.AsLong(), + MessageCount = 1 + }); + await _database.SaveChangesAsync(); + } + + if (message.Author.IsBot) return; + _logger.Information(LogSource.Message, message.Content, SimpleConextConverter.ConvertSocketMessage(message)); + } + catch (Exception e) + { + _logger.Error(LogSource.Message, "Could not process message stats", e); + } + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Handlers/UserHandler.cs b/Geekbot.net/Handlers/UserHandler.cs new file mode 100644 index 0000000..fb26d70 --- /dev/null +++ b/Geekbot.net/Handlers/UserHandler.cs @@ -0,0 +1,96 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Discord; +using Discord.Rest; +using Discord.WebSocket; +using Geekbot.net.Database; +using Geekbot.net.Lib.Extensions; +using Geekbot.net.Lib.Logger; +using Geekbot.net.Lib.UserRepository; + +namespace Geekbot.net.Handlers +{ + public class UserHandler + { + private readonly IUserRepository _userRepository; + private readonly IGeekbotLogger _logger; + private readonly DatabaseContext _database; + private readonly IDiscordClient _client; + + public UserHandler(IUserRepository userRepository, IGeekbotLogger logger, DatabaseContext database, IDiscordClient client) + { + _userRepository = userRepository; + _logger = logger; + _database = database; + _client = client; + } + + public async Task Joined(SocketGuildUser user) + { + try + { + var userRepoUpdate = _userRepository.Update(user); + _logger.Information(LogSource.Geekbot, $"{user.Username} ({user.Id}) joined {user.Guild.Name} ({user.Guild.Id})"); + + if (!user.IsBot) + { + var guildSettings = _database.GuildSettings.FirstOrDefault(guild => guild.GuildId == user.Guild.Id.AsLong()); + var message = guildSettings?.WelcomeMessage; + if (string.IsNullOrEmpty(message)) return; + message = message.Replace("$user", user.Mention); + + var fallbackSender = new Func>(() => user.Guild.DefaultChannel.SendMessageAsync(message)); + if (guildSettings.WelcomeChannel != 0) + { + try + { + var target = await _client.GetChannelAsync(guildSettings.WelcomeChannel.AsUlong()); + var channel = target as ISocketMessageChannel; + await channel.SendMessageAsync(message); + } + catch (Exception e) + { + _logger.Error(LogSource.Geekbot, "Failed to send welcome message to user defined welcome channel", e); + await fallbackSender(); + } + } + else + { + await fallbackSender(); + } + } + + await userRepoUpdate; + } + catch (Exception e) + { + _logger.Error(LogSource.Geekbot, "Failed to send welcome message", e); + } + } + + public async Task Updated(SocketUser oldUser, SocketUser newUser) + { + await _userRepository.Update(newUser); + } + + public async Task Left(SocketGuildUser user) + { + try + { + var guild = _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(user.Guild.Id.AsLong())); + if (guild?.ShowLeave ?? false) + { + var modChannelSocket = (ISocketMessageChannel) await _client.GetChannelAsync(guild.ModChannel.AsUlong()); + await modChannelSocket.SendMessageAsync($"{user.Username}#{user.Discriminator} left the server"); + } + } + catch (Exception e) + { + _logger.Error(LogSource.Geekbot, "Failed to send leave message", e); + } + + _logger.Information(LogSource.Geekbot, $"{user.Username} ({user.Id}) joined {user.Guild.Name} ({user.Guild.Id})"); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Logger/SimpleConextConverter.cs b/Geekbot.net/Lib/Logger/SimpleConextConverter.cs index d01da67..1eef12c 100644 --- a/Geekbot.net/Lib/Logger/SimpleConextConverter.cs +++ b/Geekbot.net/Lib/Logger/SimpleConextConverter.cs @@ -11,7 +11,7 @@ namespace Geekbot.net.Lib.Logger { Message = new MessageDto.MessageContent { - Content = context.Message.Content, + Content = context.Message.Content, // Only when an error occurs, including for diagnostic reason Id = context.Message.Id.ToString(), Attachments = context.Message.Attachments.Count, ChannelMentions = context.Message.MentionedChannelIds.Count, @@ -42,7 +42,6 @@ namespace Geekbot.net.Lib.Logger { Message = new MessageDto.MessageContent { - Content = message.Content, Id = message.Id.ToString(), Attachments = message.Attachments.Count, ChannelMentions = message.MentionedChannels.Count, diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index d46df90..262d830 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -7,6 +7,7 @@ using Discord; using Discord.Commands; using Discord.WebSocket; using Geekbot.net.Database; +using Geekbot.net.Handlers; using Geekbot.net.Lib; using Geekbot.net.Lib.Clients; using Geekbot.net.Lib.Converters; @@ -34,12 +35,11 @@ namespace Geekbot.net private CommandService _commands; private DatabaseInitializer _databaseInitializer; private IGlobalSettings _globalSettings; - private IServiceCollection _services; private IServiceProvider _servicesProvider; - private string _token; private GeekbotLogger _logger; private IUserRepository _userRepository; private RunParameters _runParameters; + private IReactionListener _reactionListener; private static void Main(string[] args) { @@ -73,66 +73,25 @@ namespace Geekbot.net { _logger = logger; _runParameters = runParameters; - logger.Information(LogSource.Geekbot, "Initing Stuff"); - var discordLogger = new DiscordLogger(logger); - - _client = new DiscordSocketClient(new DiscordSocketConfig - { - LogLevel = LogSeverity.Verbose, - MessageCacheSize = 1000, - ExclusiveBulkDelete = true - }); - _client.Log += discordLogger.Log; - _commands = new CommandService(); - - _databaseInitializer = new DatabaseInitializer(runParameters, logger); - var database = _databaseInitializer.Initialize(); - database.Database.EnsureCreated(); - if(!_runParameters.InMemory) database.Database.Migrate(); + logger.Information(LogSource.Geekbot, "Connecting to Database"); + var database = ConnectToDatabase(); _globalSettings = new GlobalSettings(database); - - _token = runParameters.Token ?? _globalSettings.GetKey("DiscordToken"); - if (string.IsNullOrEmpty(_token)) - { - Console.Write("Your bot Token: "); - var newToken = Console.ReadLine(); - await _globalSettings.SetKey("DiscordToken", newToken); - await _globalSettings.SetKey("Game", "Ping Pong"); - _token = newToken; - } - - _services = new ServiceCollection(); - - _userRepository = new UserRepository(_databaseInitializer.Initialize(), logger); - var fortunes = new FortunesProvider(logger); - var mediaProvider = new MediaProvider(logger); - var malClient = new MalClient(_globalSettings, logger); - var levelCalc = new LevelCalc(); - var emojiConverter = new EmojiConverter(); - var mtgManaConverter = new MtgManaConverter(); - var wikipediaClient = new WikipediaClient(); - var randomNumberGenerator = new RandomNumberGenerator(); - var kvMemoryStore = new KvInInMemoryStore(); - - _services.AddSingleton(_userRepository); - _services.AddSingleton(logger); - _services.AddSingleton(levelCalc); - _services.AddSingleton(emojiConverter); - _services.AddSingleton(fortunes); - _services.AddSingleton(mediaProvider); - _services.AddSingleton(malClient); - _services.AddSingleton(mtgManaConverter); - _services.AddSingleton(wikipediaClient); - _services.AddSingleton(randomNumberGenerator); - _services.AddSingleton(kvMemoryStore); - _services.AddSingleton(_globalSettings); - _services.AddTransient(e => new HighscoreManager(_databaseInitializer.Initialize(), _userRepository)); - _services.AddTransient(e => _databaseInitializer.Initialize()); logger.Information(LogSource.Geekbot, "Connecting to Discord"); - + SetupDiscordClient(); await Login(); + _logger.Information(LogSource.Geekbot, $"Now Connected as {_client.CurrentUser.Username} to {_client.Guilds.Count} Servers"); + await _client.SetGameAsync(_globalSettings.GetKey("Game")); + + _logger.Information(LogSource.Geekbot, "Loading Dependencies and Handlers"); + RegisterDependencies(); + await RegisterHandlers(); + + _logger.Information(LogSource.Api, "Starting Web API"); + StartWebApi(); + + _logger.Information(LogSource.Geekbot, "Done and ready for use"); await Task.Delay(-1); } @@ -141,42 +100,10 @@ namespace Geekbot.net { try { - await _client.LoginAsync(TokenType.Bot, _token); + var token = await GetToken(); + await _client.LoginAsync(TokenType.Bot, token); await _client.StartAsync(); - var isConneted = await IsConnected(); - if (isConneted) - { - var applicationInfo = await _client.GetApplicationInfoAsync(); - await _client.SetGameAsync(_globalSettings.GetKey("Game")); - _logger.Information(LogSource.Geekbot, $"Now Connected as {_client.CurrentUser.Username} to {_client.Guilds.Count} Servers"); - - _logger.Information(LogSource.Geekbot, "Registering Stuff"); - var translationHandler = new TranslationHandler(_databaseInitializer.Initialize(), _logger); - var errorHandler = new ErrorHandler(_logger, translationHandler, _runParameters.ExposeErrors); - var reactionListener = new ReactionListener(_databaseInitializer.Initialize()); - _services.AddSingleton(errorHandler); - _services.AddSingleton(translationHandler); - _services.AddSingleton(_client); - _services.AddSingleton(reactionListener); - _servicesProvider = _services.BuildServiceProvider(); - await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _servicesProvider); - - var handlers = new Handlers(_databaseInitializer, _client, _logger, _servicesProvider, _commands, _userRepository, reactionListener, applicationInfo); - - _client.MessageReceived += handlers.RunCommand; - _client.MessageDeleted += handlers.MessageDeleted; - _client.UserJoined += handlers.UserJoined; - _client.UserUpdated += handlers.UserUpdated; - _client.UserLeft += handlers.UserLeft; - _client.ReactionAdded += handlers.ReactionAdded; - _client.ReactionRemoved += handlers.ReactionRemoved; - if (!_runParameters.InMemory) _client.MessageReceived += handlers.UpdateStats; - - var webserver = _runParameters.DisableApi ? Task.Delay(10) : StartWebApi(); - _logger.Information(LogSource.Geekbot, "Done and ready for use"); - - await webserver; - } + while (!_client.ConnectionState.Equals(ConnectionState.Connected)) await Task.Delay(25); } catch (Exception e) { @@ -185,19 +112,117 @@ namespace Geekbot.net } } - private async Task IsConnected() + private DatabaseContext ConnectToDatabase() { - while (!_client.ConnectionState.Equals(ConnectionState.Connected)) - await Task.Delay(25); - return true; + _databaseInitializer = new DatabaseInitializer(_runParameters, _logger); + var database = _databaseInitializer.Initialize(); + database.Database.EnsureCreated(); + if(!_runParameters.InMemory) database.Database.Migrate(); + + return database; } - private Task StartWebApi() + private async Task GetToken() { - _logger.Information(LogSource.Api, "Starting Webserver"); + var token = _runParameters.Token ?? _globalSettings.GetKey("DiscordToken"); + if (string.IsNullOrEmpty(token)) + { + Console.Write("Your bot Token: "); + var newToken = Console.ReadLine(); + await _globalSettings.SetKey("DiscordToken", newToken); + await _globalSettings.SetKey("Game", "Ping Pong"); + token = newToken; + } + + return token; + } + + private void SetupDiscordClient() + { + _client = new DiscordSocketClient(new DiscordSocketConfig + { + LogLevel = LogSeverity.Verbose, + MessageCacheSize = 1000, + ExclusiveBulkDelete = true + }); + + var discordLogger = new DiscordLogger(_logger); + _client.Log += discordLogger.Log; + } + + private void RegisterDependencies() + { + var services = new ServiceCollection(); + + _userRepository = new UserRepository(_databaseInitializer.Initialize(), _logger); + _reactionListener = new ReactionListener(_databaseInitializer.Initialize()); + var fortunes = new FortunesProvider(_logger); + var mediaProvider = new MediaProvider(_logger); + var malClient = new MalClient(_globalSettings, _logger); + var levelCalc = new LevelCalc(); + var emojiConverter = new EmojiConverter(); + var mtgManaConverter = new MtgManaConverter(); + var wikipediaClient = new WikipediaClient(); + var randomNumberGenerator = new RandomNumberGenerator(); + var kvMemoryStore = new KvInInMemoryStore(); + var translationHandler = new TranslationHandler(_databaseInitializer.Initialize(), _logger); + var errorHandler = new ErrorHandler(_logger, translationHandler, _runParameters.ExposeErrors); + + services.AddSingleton(_userRepository); + services.AddSingleton(_logger); + services.AddSingleton(levelCalc); + services.AddSingleton(emojiConverter); + services.AddSingleton(fortunes); + services.AddSingleton(mediaProvider); + services.AddSingleton(malClient); + services.AddSingleton(mtgManaConverter); + services.AddSingleton(wikipediaClient); + services.AddSingleton(randomNumberGenerator); + services.AddSingleton(kvMemoryStore); + services.AddSingleton(_globalSettings); + services.AddSingleton(errorHandler); + services.AddSingleton(translationHandler); + services.AddSingleton(_reactionListener); + services.AddSingleton(_client); + services.AddTransient(e => new HighscoreManager(_databaseInitializer.Initialize(), _userRepository)); + services.AddTransient(e => _databaseInitializer.Initialize()); + + _servicesProvider = services.BuildServiceProvider(); + } + + private async Task RegisterHandlers() + { + var applicationInfo = await _client.GetApplicationInfoAsync(); + + _commands = new CommandService(); + await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _servicesProvider); + + var commandHandler = new CommandHandler(_databaseInitializer.Initialize(), _client, _logger, _servicesProvider, _commands, applicationInfo); + var userHandler = new UserHandler(_userRepository, _logger, _databaseInitializer.Initialize(), _client); + var reactionHandler = new ReactionHandler(_reactionListener); + var statsHandler = new StatsHandler(_logger, _databaseInitializer.Initialize()); + var messageDeletedHandler = new MessageDeletedHandler(_databaseInitializer.Initialize(), _logger, _client); + + _client.MessageReceived += commandHandler.RunCommand; + _client.MessageDeleted += messageDeletedHandler.HandleMessageDeleted; + _client.UserJoined += userHandler.Joined; + _client.UserUpdated += userHandler.Updated; + _client.UserLeft += userHandler.Left; + _client.ReactionAdded += reactionHandler.Added; + _client.ReactionRemoved += reactionHandler.Removed; + if (!_runParameters.InMemory) _client.MessageReceived += statsHandler.UpdateStats; + } + + private void StartWebApi() + { + if (_runParameters.DisableApi) + { + _logger.Warning(LogSource.Api, "Web API is disabled"); + return; + } + var highscoreManager = new HighscoreManager(_databaseInitializer.Initialize(), _userRepository); WebApiStartup.StartWebApi(_logger, _runParameters, _commands, _databaseInitializer.Initialize(), _client, _globalSettings, highscoreManager); - return Task.CompletedTask; } } } \ No newline at end of file From fb676e8918750ccaaad04cb6e2244d831626b0a5 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 19 Jun 2020 04:10:26 +0200 Subject: [PATCH 333/553] Add GuildSettingsManager to centrally manage guild settings --- Geekbot.net/Commands/Admin/Admin.cs | 107 ++++++------------ Geekbot.net/Handlers/CommandHandler.cs | 16 +-- .../GuildSettingsManager.cs | 68 +++++++++++ .../IGuildSettingsManager.cs | 11 ++ .../Lib/Localization/TranslationHandler.cs | 28 ++--- Geekbot.net/Program.cs | 8 +- 6 files changed, 138 insertions(+), 100 deletions(-) create mode 100644 Geekbot.net/Lib/GuildSettingsManager/GuildSettingsManager.cs create mode 100644 Geekbot.net/Lib/GuildSettingsManager/IGuildSettingsManager.cs diff --git a/Geekbot.net/Commands/Admin/Admin.cs b/Geekbot.net/Commands/Admin/Admin.cs index 15b4df1..9120971 100644 --- a/Geekbot.net/Commands/Admin/Admin.cs +++ b/Geekbot.net/Commands/Admin/Admin.cs @@ -1,15 +1,13 @@ using System; -using System.Linq; using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.WebSocket; -using Geekbot.net.Database; -using Geekbot.net.Database.Models; using Geekbot.net.Lib.CommandPreconditions; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; +using Geekbot.net.Lib.GuildSettingsManager; using Geekbot.net.Lib.Localization; namespace Geekbot.net.Commands.Admin @@ -21,15 +19,14 @@ namespace Geekbot.net.Commands.Admin { private readonly DiscordSocketClient _client; private readonly IErrorHandler _errorHandler; - private readonly DatabaseContext _database; + private readonly IGuildSettingsManager _guildSettingsManager; private readonly ITranslationHandler _translation; - public Admin(DatabaseContext database, DiscordSocketClient client, IErrorHandler errorHandler, - ITranslationHandler translationHandler) + public Admin(DiscordSocketClient client, IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager, ITranslationHandler translationHandler) { - _database = database; _client = client; _errorHandler = errorHandler; + _guildSettingsManager = guildSettingsManager; _translation = translationHandler; } @@ -37,11 +34,10 @@ namespace Geekbot.net.Commands.Admin [Summary("Set a Welcome Message (use '$user' to mention the new joined user).")] public async Task SetWelcomeMessage([Remainder, Summary("message")] string welcomeMessage) { - var guild = await GetGuildSettings(Context.Guild.Id); + var guild = _guildSettingsManager.GetSettings(Context.Guild.Id); guild.WelcomeMessage = welcomeMessage; - _database.GuildSettings.Update(guild); - await _database.SaveChangesAsync(); - + await _guildSettingsManager.UpdateSettings(guild); + var formatedMessage = welcomeMessage.Replace("$user", Context.User.Mention); await ReplyAsync($"Welcome message has been changed\r\nHere is an example of how it would look:\r\n{formatedMessage}"); } @@ -54,13 +50,12 @@ namespace Geekbot.net.Commands.Admin { var m = await channel.SendMessageAsync("..."); - var guild = await GetGuildSettings(Context.Guild.Id); + var guild = _guildSettingsManager.GetSettings(Context.Guild.Id); guild.WelcomeChannel = channel.Id.AsLong(); - _database.GuildSettings.Update(guild); - await _database.SaveChangesAsync(); - + await _guildSettingsManager.UpdateSettings(guild); + await m.DeleteAsync(); - + await ReplyAsync("Successfully saved the welcome channel"); } catch (Exception e) @@ -68,7 +63,7 @@ namespace Geekbot.net.Commands.Admin await _errorHandler.HandleCommandException(e, Context, "That channel doesn't seem to exist or i don't have write permissions"); } } - + [Command("modchannel", RunMode = RunMode.Async)] [Summary("Set a channel for moderation purposes")] public async Task SelectModChannel([Summary("#Channel")] ISocketMessageChannel channel) @@ -77,11 +72,10 @@ namespace Geekbot.net.Commands.Admin { var m = await channel.SendMessageAsync("verifying..."); - var guild = await GetGuildSettings(Context.Guild.Id); + var guild = _guildSettingsManager.GetSettings(Context.Guild.Id); guild.ModChannel = channel.Id.AsLong(); - _database.GuildSettings.Update(guild); - await _database.SaveChangesAsync(); - + await _guildSettingsManager.UpdateSettings(guild); + var sb = new StringBuilder(); sb.AppendLine("Successfully saved mod channel, you can now do the following"); sb.AppendLine("- `!admin showleave` - send message to mod channel when someone leaves"); @@ -100,13 +94,12 @@ namespace Geekbot.net.Commands.Admin { try { - var guild = await GetGuildSettings(Context.Guild.Id); + var guild = _guildSettingsManager.GetSettings(Context.Guild.Id); var modChannel = await GetModChannel(guild.ModChannel.AsUlong()); if (modChannel == null) return; - + guild.ShowLeave = !guild.ShowLeave; - _database.GuildSettings.Update(guild); - await _database.SaveChangesAsync(); + await _guildSettingsManager.UpdateSettings(guild); await modChannel.SendMessageAsync(guild.ShowLeave ? "Saved - now sending messages here when someone leaves" : "Saved - stopping sending messages here when someone leaves" @@ -124,13 +117,12 @@ namespace Geekbot.net.Commands.Admin { try { - var guild = await GetGuildSettings(Context.Guild.Id); + var guild = _guildSettingsManager.GetSettings(Context.Guild.Id); var modChannel = await GetModChannel(guild.ModChannel.AsUlong()); if (modChannel == null) return; - + guild.ShowDelete = !guild.ShowDelete; - _database.GuildSettings.Update(guild); - await _database.SaveChangesAsync(); + await _guildSettingsManager.UpdateSettings(guild); await modChannel.SendMessageAsync(guild.ShowDelete ? "Saved - now sending messages here when someone deletes a message" : "Saved - stopping sending messages here when someone deletes a message" @@ -152,11 +144,10 @@ namespace Geekbot.net.Commands.Admin var success = await _translation.SetLanguage(Context.Guild.Id, language); if (success) { - var guild = await GetGuildSettings(Context.Guild.Id); + var guild = _guildSettingsManager.GetSettings(Context.Guild.Id); guild.Language = language; - _database.GuildSettings.Update(guild); - await _database.SaveChangesAsync(); - + await _guildSettingsManager.UpdateSettings(guild); + var transContext = await _translation.GetGuildContext(Context); await ReplyAsync(transContext.GetString("NewLanguageSet")); return; @@ -170,7 +161,7 @@ namespace Geekbot.net.Commands.Admin await _errorHandler.HandleCommandException(e, Context); } } - + [Command("wiki", RunMode = RunMode.Async)] [Summary("Change the wikipedia instance (use lang code in xx.wikipedia.org)")] public async Task SetWikiLanguage([Summary("language")] string languageRaw) @@ -178,11 +169,10 @@ namespace Geekbot.net.Commands.Admin try { var language = languageRaw.ToLower(); - var guild = await GetGuildSettings(Context.Guild.Id); + var guild = _guildSettingsManager.GetSettings(Context.Guild.Id); guild.WikiLang = language; - _database.GuildSettings.Update(guild); - await _database.SaveChangesAsync(); - + await _guildSettingsManager.UpdateSettings(guild); + await ReplyAsync($"Now using the {language} wikipedia"); } catch (Exception e) @@ -190,17 +180,16 @@ namespace Geekbot.net.Commands.Admin await _errorHandler.HandleCommandException(e, Context); } } - + [Command("ping", RunMode = RunMode.Async)] [Summary("Enable the ping reply.")] public async Task TogglePing() { try { - var guild = await GetGuildSettings(Context.Guild.Id); + var guild = _guildSettingsManager.GetSettings(Context.Guild.Id); guild.Ping = !guild.Ping; - _database.GuildSettings.Update(guild); - await _database.SaveChangesAsync(); + await _guildSettingsManager.UpdateSettings(guild); await ReplyAsync(guild.Ping ? "i will reply to ping now" : "No more pongs..."); } catch (Exception e) @@ -208,17 +197,16 @@ namespace Geekbot.net.Commands.Admin await _errorHandler.HandleCommandException(e, Context); } } - + [Command("hui", RunMode = RunMode.Async)] [Summary("Enable the ping reply.")] public async Task ToggleHui() { try { - var guild = await GetGuildSettings(Context.Guild.Id); + var guild = _guildSettingsManager.GetSettings(Context.Guild.Id); guild.Hui = !guild.Hui; - _database.GuildSettings.Update(guild); - await _database.SaveChangesAsync(); + await _guildSettingsManager.UpdateSettings(guild); await ReplyAsync(guild.Hui ? "i will reply to hui now" : "No more hui's..."); } catch (Exception e) @@ -227,41 +215,20 @@ namespace Geekbot.net.Commands.Admin } } - private async Task GetGuildSettings(ulong guildId) - { - var guild = _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(guildId.AsLong())); - if (guild != null) return guild; - Console.WriteLine("Adding non-exist Guild Settings to database"); - _database.GuildSettings.Add(new GuildSettingsModel() - { - GuildId = guildId.AsLong(), - Hui = false, - Ping = false, - Language = "EN", - ShowDelete = false, - ShowLeave = false, - WikiLang = "en" - }); - await _database.SaveChangesAsync(); - return _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(guildId.AsLong())); - } - private async Task GetModChannel(ulong channelId) { try { - if(channelId == ulong.MinValue) throw new Exception(); + if (channelId == ulong.MinValue) throw new Exception(); var modChannel = (ISocketMessageChannel) _client.GetChannel(channelId); - if(modChannel == null) throw new Exception(); + if (modChannel == null) throw new Exception(); return modChannel; } catch { - await ReplyAsync( - "Modchannel doesn't seem to exist, please set one with `!admin modchannel [channelId]`"); + await ReplyAsync("Modchannel doesn't seem to exist, please set one with `!admin modchannel [channelId]`"); return null; } } - } } \ No newline at end of file diff --git a/Geekbot.net/Handlers/CommandHandler.cs b/Geekbot.net/Handlers/CommandHandler.cs index 5074ff2..b811a8e 100644 --- a/Geekbot.net/Handlers/CommandHandler.cs +++ b/Geekbot.net/Handlers/CommandHandler.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; @@ -8,7 +7,7 @@ using Discord.Rest; using Discord.WebSocket; using Geekbot.net.Database; using Geekbot.net.Database.Models; -using Geekbot.net.Lib.Extensions; +using Geekbot.net.Lib.GuildSettingsManager; using Geekbot.net.Lib.Logger; namespace Geekbot.net.Handlers @@ -20,10 +19,12 @@ namespace Geekbot.net.Handlers private readonly IServiceProvider _servicesProvider; private readonly CommandService _commands; private readonly RestApplication _applicationInfo; + private readonly IGuildSettingsManager _guildSettingsManager; private readonly List _ignoredServers; private readonly DatabaseContext _database; - public CommandHandler(DatabaseContext database, IDiscordClient client, IGeekbotLogger logger, IServiceProvider servicesProvider, CommandService commands, RestApplication applicationInfo) + public CommandHandler(DatabaseContext database, IDiscordClient client, IGeekbotLogger logger, IServiceProvider servicesProvider, CommandService commands, RestApplication applicationInfo, + IGuildSettingsManager guildSettingsManager) { _database = database; _client = client; @@ -31,6 +32,7 @@ namespace Geekbot.net.Handlers _servicesProvider = servicesProvider; _commands = commands; _applicationInfo = applicationInfo; + _guildSettingsManager = guildSettingsManager; // Some guilds only want very specific functionally without any of the commands, a quick hack that solves that "short term" // ToDo: create a clean solution for this... @@ -68,14 +70,14 @@ namespace Geekbot.net.Handlers var argPos = 0; if (!IsCommand(message, ref argPos)) return Task.CompletedTask; - + ExecuteCommand(message, argPos); } catch (Exception e) { _logger.Error(LogSource.Geekbot, "Failed to Process Message", e); } - + return Task.CompletedTask; } @@ -102,7 +104,7 @@ namespace Geekbot.net.Handlers if (!lowerCaseMessage.StartsWith("ping ") && !lowerCaseMessage.Equals("ping")) return false; return GetGuildSettings(guildId)?.Ping ?? false; } - + private bool ShouldHui(string lowerCaseMessage, ulong guildId) { if (!lowerCaseMessage.StartsWith("hui")) return false; @@ -111,7 +113,7 @@ namespace Geekbot.net.Handlers private GuildSettingsModel GetGuildSettings(ulong guildId) { - return _database.GuildSettings.FirstOrDefault(guild => guild.GuildId.Equals(guildId.AsLong())); + return _guildSettingsManager.GetSettings(guildId, false); } } } \ No newline at end of file diff --git a/Geekbot.net/Lib/GuildSettingsManager/GuildSettingsManager.cs b/Geekbot.net/Lib/GuildSettingsManager/GuildSettingsManager.cs new file mode 100644 index 0000000..bfa7556 --- /dev/null +++ b/Geekbot.net/Lib/GuildSettingsManager/GuildSettingsManager.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Geekbot.net.Database; +using Geekbot.net.Database.Models; +using Geekbot.net.Lib.Extensions; + +namespace Geekbot.net.Lib.GuildSettingsManager +{ + public class GuildSettingsManager : IGuildSettingsManager + { + private readonly DatabaseContext _database; + private readonly Dictionary _settings; + + public GuildSettingsManager(DatabaseContext database) + { + _database = database; + _settings = new Dictionary(); + } + + public GuildSettingsModel GetSettings(ulong guildId, bool createIfNonExist = true) + { + return _settings.ContainsKey(guildId) ? _settings[guildId] : GetFromDatabase(guildId, createIfNonExist); + } + + public async Task UpdateSettings(GuildSettingsModel settings) + { + _database.GuildSettings.Update(settings); + if (_settings.ContainsKey(settings.GuildId.AsUlong())) + { + _settings[settings.GuildId.AsUlong()] = settings; + } + else + { + _settings.Add(settings.GuildId.AsUlong(), settings); + } + await _database.SaveChangesAsync(); + } + + private GuildSettingsModel GetFromDatabase(ulong guildId, bool createIfNonExist) + { + var settings = _database.GuildSettings.FirstOrDefault(guild => guild.GuildId.Equals(guildId.AsLong())); + if (createIfNonExist && settings == null) + { + settings = CreateSettings(guildId); + } + + _settings.Add(guildId, settings); + return settings; + } + + private GuildSettingsModel CreateSettings(ulong guildId) + { + _database.GuildSettings.Add(new GuildSettingsModel + { + GuildId = guildId.AsLong(), + Hui = false, + Ping = false, + Language = "EN", + ShowDelete = false, + ShowLeave = false, + WikiLang = "en" + }); + _database.SaveChanges(); + return _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(guildId.AsLong())); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/GuildSettingsManager/IGuildSettingsManager.cs b/Geekbot.net/Lib/GuildSettingsManager/IGuildSettingsManager.cs new file mode 100644 index 0000000..a45b263 --- /dev/null +++ b/Geekbot.net/Lib/GuildSettingsManager/IGuildSettingsManager.cs @@ -0,0 +1,11 @@ +using System.Threading.Tasks; +using Geekbot.net.Database.Models; + +namespace Geekbot.net.Lib.GuildSettingsManager +{ + public interface IGuildSettingsManager + { + GuildSettingsModel GetSettings(ulong guildId, bool createIfNonExist = true); + Task UpdateSettings(GuildSettingsModel settings); + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Localization/TranslationHandler.cs b/Geekbot.net/Lib/Localization/TranslationHandler.cs index a7a1a12..89ba632 100644 --- a/Geekbot.net/Lib/Localization/TranslationHandler.cs +++ b/Geekbot.net/Lib/Localization/TranslationHandler.cs @@ -4,9 +4,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Database; -using Geekbot.net.Database.Models; -using Geekbot.net.Lib.Extensions; +using Geekbot.net.Lib.GuildSettingsManager; using Geekbot.net.Lib.Logger; using YamlDotNet.Core; using YamlDotNet.Serialization; @@ -15,15 +13,15 @@ namespace Geekbot.net.Lib.Localization { public class TranslationHandler : ITranslationHandler { - private readonly DatabaseContext _database; private readonly IGeekbotLogger _logger; + private readonly IGuildSettingsManager _guildSettingsManager; private readonly Dictionary _serverLanguages; private Dictionary>> _translations; - public TranslationHandler(DatabaseContext database, IGeekbotLogger logger) + public TranslationHandler(IGeekbotLogger logger, IGuildSettingsManager guildSettingsManager) { - _database = database; _logger = logger; + _guildSettingsManager = guildSettingsManager; _logger.Information(LogSource.Geekbot, "Loading Translations"); LoadTranslations(); _serverLanguages = new Dictionary(); @@ -107,7 +105,7 @@ namespace Geekbot.net.Lib.Localization } catch { - lang = (await GetGuild(guildId)).Language ?? "EN"; + lang = _guildSettingsManager.GetSettings(guildId, false)?.Language ?? "EN"; _serverLanguages[guildId] = lang; return lang; } @@ -178,9 +176,9 @@ namespace Geekbot.net.Lib.Localization try { if (!SupportedLanguages.Contains(language)) return false; - var guild = await GetGuild(guildId); + var guild = _guildSettingsManager.GetSettings(guildId); guild.Language = language; - _database.GuildSettings.Update(guild); + await _guildSettingsManager.UpdateSettings(guild); _serverLanguages[guildId] = language; return true; } @@ -192,17 +190,5 @@ namespace Geekbot.net.Lib.Localization } public List SupportedLanguages { get; private set; } - - private async Task GetGuild(ulong guildId) - { - var guild = _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(guildId.AsLong())); - if (guild != null) return guild; - _database.GuildSettings.Add(new GuildSettingsModel - { - GuildId = guildId.AsLong() - }); - await _database.SaveChangesAsync(); - return _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(guildId.AsLong())); - } } } \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 262d830..1299583 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -13,6 +13,7 @@ using Geekbot.net.Lib.Clients; using Geekbot.net.Lib.Converters; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.GlobalSettings; +using Geekbot.net.Lib.GuildSettingsManager; using Geekbot.net.Lib.Highscores; using Geekbot.net.Lib.KvInMemoryStore; using Geekbot.net.Lib.Levels; @@ -40,6 +41,7 @@ namespace Geekbot.net private IUserRepository _userRepository; private RunParameters _runParameters; private IReactionListener _reactionListener; + private IGuildSettingsManager _guildSettingsManager; private static void Main(string[] args) { @@ -156,6 +158,7 @@ namespace Geekbot.net _userRepository = new UserRepository(_databaseInitializer.Initialize(), _logger); _reactionListener = new ReactionListener(_databaseInitializer.Initialize()); + _guildSettingsManager = new GuildSettingsManager(_databaseInitializer.Initialize()); var fortunes = new FortunesProvider(_logger); var mediaProvider = new MediaProvider(_logger); var malClient = new MalClient(_globalSettings, _logger); @@ -165,7 +168,7 @@ namespace Geekbot.net var wikipediaClient = new WikipediaClient(); var randomNumberGenerator = new RandomNumberGenerator(); var kvMemoryStore = new KvInInMemoryStore(); - var translationHandler = new TranslationHandler(_databaseInitializer.Initialize(), _logger); + var translationHandler = new TranslationHandler(_logger, _guildSettingsManager); var errorHandler = new ErrorHandler(_logger, translationHandler, _runParameters.ExposeErrors); services.AddSingleton(_userRepository); @@ -183,6 +186,7 @@ namespace Geekbot.net services.AddSingleton(errorHandler); services.AddSingleton(translationHandler); services.AddSingleton(_reactionListener); + services.AddSingleton(_guildSettingsManager); services.AddSingleton(_client); services.AddTransient(e => new HighscoreManager(_databaseInitializer.Initialize(), _userRepository)); services.AddTransient(e => _databaseInitializer.Initialize()); @@ -197,7 +201,7 @@ namespace Geekbot.net _commands = new CommandService(); await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _servicesProvider); - var commandHandler = new CommandHandler(_databaseInitializer.Initialize(), _client, _logger, _servicesProvider, _commands, applicationInfo); + var commandHandler = new CommandHandler(_databaseInitializer.Initialize(), _client, _logger, _servicesProvider, _commands, applicationInfo, _guildSettingsManager); var userHandler = new UserHandler(_userRepository, _logger, _databaseInitializer.Initialize(), _client); var reactionHandler = new ReactionHandler(_reactionListener); var statsHandler = new StatsHandler(_logger, _databaseInitializer.Initialize()); From 1ea851be22cff73ee85536a287f5f55fdf902de2 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 19 Jun 2020 04:13:26 +0200 Subject: [PATCH 334/553] Release Geekbot 4.2 --- .gitlab-ci.yml | 6 +++--- Geekbot.net/Geekbot.net.csproj | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cffe539..7b6b593 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -29,9 +29,9 @@ sentry: dependencies: - build script: - - sentry-cli releases new -p geekbot 4.1.0-${CI_COMMIT_SHA:0:8} - - sentry-cli releases set-commits --auto 4.1.0-${CI_COMMIT_SHA:0:8} - - sentry-cli releases deploys 4.1.0-${CI_COMMIT_SHA:0:8} new -e Production + - sentry-cli releases new -p geekbot 4.2.0-${CI_COMMIT_SHA:0:8} + - sentry-cli releases set-commits --auto 4.2.0-${CI_COMMIT_SHA:0:8} + - sentry-cli releases deploys 4.2.0-${CI_COMMIT_SHA:0:8} new -e Production deploy: stage: deploy diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 0d39cae..0d58104 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -4,7 +4,7 @@ netcoreapp3.1 win-x64;linux-x64 derp.ico - 4.1.0 + 4.2.0 $(VersionSuffix) $(Version)-$(VersionSuffix) $(Version)-DEV From 76bb645394d8cb447d8495b9334f06d20aa774c6 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 19 Jun 2020 12:08:28 +0200 Subject: [PATCH 335/553] Inline MTG Emoji converter --- Geekbot.net/Geekbot.net.csproj | 3 -- .../Lib/Converters/MtgManaConverter.cs | 54 ++++++++++++++++++- Geekbot.net/Lib/Converters/MtgManaEmojis.json | 50 ----------------- 3 files changed, 52 insertions(+), 55 deletions(-) delete mode 100644 Geekbot.net/Lib/Converters/MtgManaEmojis.json diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 0d58104..b3f537e 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -82,9 +82,6 @@ PreserveNewest - - Always - PreserveNewest diff --git a/Geekbot.net/Lib/Converters/MtgManaConverter.cs b/Geekbot.net/Lib/Converters/MtgManaConverter.cs index 31a2db0..7e90df0 100644 --- a/Geekbot.net/Lib/Converters/MtgManaConverter.cs +++ b/Geekbot.net/Lib/Converters/MtgManaConverter.cs @@ -12,8 +12,57 @@ namespace Geekbot.net.Lib.Converters public MtgManaConverter() { // these emotes can be found at https://discord.gg/bz8HyA7 - var mtgEmojis = File.ReadAllText(Path.GetFullPath("./Lib/Converters/MtgManaEmojis.json")); - _manaDict = JsonSerializer.Deserialize>(mtgEmojis); + _manaDict = new Dictionary + { + {"{0}", "<:mtg_0:415216130043412482>"}, + {"{1}", "<:mtg_1:415216130253389835>"}, + {"{2}", "<:mtg_2:415216130031091713>"}, + {"{3}", "<:mtg_3:415216130467037194>"}, + {"{4}", "<:mtg_4:415216130026635295>"}, + {"{5}", "<:mtg_5:415216130492203008>"}, + {"{6}", "<:mtg_6:415216130458779658>"}, + {"{7}", "<:mtg_7:415216130190475265>"}, + {"{8}", "<:mtg_8:415216130517630986>"}, + {"{9}", "<:mtg_9:415216130500722689>"}, + {"{10", "<:mtg_10:415216130450391051>"}, + {"{11}", "<:mtg_11:415216130811101185>"}, + {"{12}", "<:mtg_12:415216130525888532>"}, + {"{13}", "<:mtg_13:415216130517631000>"}, + {"{14}", "<:mtg_14:415216130165178370>"}, + {"{15}", "<:mtg_15:415216130576089108>"}, + {"{16}", "<:mtg_16:415216130358247425>"}, + {"{17}", "<:mtg_17:415216130601517056>"}, + {"{18}", "<:mtg_18:415216130462842891>"}, + {"{19}", "<:mtg_19:415216130614099988>"}, + {"{20}", "<:mtg_20:415216130656043038>"}, + {"{W}", "<:mtg_white:415216131515744256>"}, + {"{U}", "<:mtg_blue:415216130521694209>"}, + {"{B}", "<:mtg_black:415216130873884683>"}, + {"{R}", "<:mtg_red:415216131322806272>"}, + {"{G}", "<:mtg_green:415216131180331009>"}, + {"{S}", "<:mtg_s:415216131293446144>"}, + {"{T}", "<:mtg_tap:415258392727257088>"}, + {"{C}", "<:mtg_colorless:415216130706374666>"}, + {"{2/W}", "<:mtg_2w:415216130446065664>"}, + {"{2/U}", "<:mtg_2u:415216130429550592>"}, + {"{2/B}", "<:mtg_2b:415216130160984065>"}, + {"{2/R}", "<:mtg_2r:415216130454716436>"}, + {"{2/G}", "<:mtg_2g:415216130420899840>"}, + {"{W/U}", "<:mtg_wu:415216130970484736>"}, + {"{W/B}", "<:mtg_wb:415216131222011914>"}, + {"{U/R}", "<:mtg_ur:415216130962096128>"}, + {"{U/B}", "<:mtg_ub:415216130865758218>"}, + {"{R/W}", "<:mtg_rw:415216130878210057>"}, + {"{G/W}", "<:mtg_gw:415216130567962646>"}, + {"{G/U}", "<:mtg_gu:415216130739666945>"}, + {"{B/R}", "<:mtg_br:415216130580283394>"}, + {"{B/G}", "<:mtg_bg:415216130781609994>"}, + {"{U/P}", "<:mtg_up:415216130861432842>"}, + {"{R/P}", "<:mtg_rp:415216130597322783>"}, + {"{G/P}", "<:mtg_gp:415216130760769546>"}, + {"{W/P}", "<:mtg_wp:415216131541041172>"}, + {"{B/P}", "<:mtg_bp:415216130664169482>"} + }; } public string ConvertMana(string mana) @@ -27,6 +76,7 @@ namespace Geekbot.net.Lib.Converters mana = mana.Replace(manaTypes.Value, m); } } + return mana; } } diff --git a/Geekbot.net/Lib/Converters/MtgManaEmojis.json b/Geekbot.net/Lib/Converters/MtgManaEmojis.json deleted file mode 100644 index 8ebe75b..0000000 --- a/Geekbot.net/Lib/Converters/MtgManaEmojis.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "{0}": "<:mtg_0:415216130043412482>", - "{1}": "<:mtg_1:415216130253389835>", - "{2}": "<:mtg_2:415216130031091713>", - "{3}": "<:mtg_3:415216130467037194>", - "{4}": "<:mtg_4:415216130026635295>", - "{5}": "<:mtg_5:415216130492203008>", - "{6}": "<:mtg_6:415216130458779658>", - "{7}": "<:mtg_7:415216130190475265>", - "{8}": "<:mtg_8:415216130517630986>", - "{9}": "<:mtg_9:415216130500722689>", - "{10": "<:mtg_10:415216130450391051>", - "{11}": "<:mtg_11:415216130811101185>", - "{12}": "<:mtg_12:415216130525888532>", - "{13}": "<:mtg_13:415216130517631000>", - "{14}": "<:mtg_14:415216130165178370>", - "{15}": "<:mtg_15:415216130576089108>", - "{16}": "<:mtg_16:415216130358247425>", - "{17}": "<:mtg_17:415216130601517056>", - "{18}": "<:mtg_18:415216130462842891>", - "{19}": "<:mtg_19:415216130614099988>", - "{20}": "<:mtg_20:415216130656043038>", - "{W}": "<:mtg_white:415216131515744256>", - "{U}": "<:mtg_blue:415216130521694209>", - "{B}": "<:mtg_black:415216130873884683>", - "{R}": "<:mtg_red:415216131322806272>", - "{G}": "<:mtg_green:415216131180331009>", - "{S}": "<:mtg_s:415216131293446144>", - "{T}": "<:mtg_tap:415258392727257088>", - "{C}": "<:mtg_colorless:415216130706374666>", - "{2/W}": "<:mtg_2w:415216130446065664>", - "{2/U}": "<:mtg_2u:415216130429550592>", - "{2/B}": "<:mtg_2b:415216130160984065>", - "{2/R}": "<:mtg_2r:415216130454716436>", - "{2/G}": "<:mtg_2g:415216130420899840>", - "{W/U}": "<:mtg_wu:415216130970484736>", - "{W/B}": "<:mtg_wb:415216131222011914>", - "{U/R}": "<:mtg_ur:415216130962096128>", - "{U/B}": "<:mtg_ub:415216130865758218>", - "{R/W}": "<:mtg_rw:415216130878210057>", - "{G/W}": "<:mtg_gw:415216130567962646>", - "{G/U}": "<:mtg_gu:415216130739666945>", - "{B/R}": "<:mtg_br:415216130580283394>", - "{B/G}": "<:mtg_bg:415216130781609994>", - "{U/P}": "<:mtg_up:415216130861432842>", - "{R/P}": "<:mtg_rp:415216130597322783>", - "{G/P}": "<:mtg_gp:415216130760769546>", - "{W/P}": "<:mtg_wp:415216131541041172>", - "{B/P}": "<:mtg_bp:415216130664169482>" -} \ No newline at end of file From e564e80849c5f425dac1c729120966de5a7dbcb4 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 19 Jun 2020 12:15:17 +0200 Subject: [PATCH 336/553] Copy every file in storage by default instead of listing every single one --- Geekbot.net/Geekbot.net.csproj | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index b3f537e..23f331f 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -58,31 +58,7 @@ - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - + PreserveNewest From 9cc944fcc10d7fd284de89357c7a65ff2535dce0 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 19 Jun 2020 12:28:22 +0200 Subject: [PATCH 337/553] Use a single message for !mtg and show a searching message when the command starts executing --- Geekbot.net/Commands/Integrations/MagicTheGathering.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Geekbot.net/Commands/Integrations/MagicTheGathering.cs b/Geekbot.net/Commands/Integrations/MagicTheGathering.cs index 1075c46..f9e006c 100644 --- a/Geekbot.net/Commands/Integrations/MagicTheGathering.cs +++ b/Geekbot.net/Commands/Integrations/MagicTheGathering.cs @@ -28,6 +28,8 @@ namespace Geekbot.net.Commands.Integrations { try { + var message = await Context.Channel.SendMessageAsync($":mag: Looking up\"{cardName}\", please wait..."); + var service = new CardService(); var result = service .Where(x => x.Name, cardName) @@ -37,7 +39,7 @@ namespace Geekbot.net.Commands.Integrations var card = result.All().Value.FirstOrDefault(); if (card == null) { - await ReplyAsync("I couldn't find that card..."); + await message.ModifyAsync(properties => properties.Content = ":red_circle: I couldn't find a card with that name..."); return; } @@ -65,7 +67,11 @@ namespace Geekbot.net.Commands.Integrations if (card.Legalities != null && card.Legalities.Count > 0) eb.AddField("Legality", string.Join(", ", card.Legalities.Select(e => e.Format))); - await ReplyAsync("", false, eb.Build()); + await message.ModifyAsync(properties => + { + properties.Content = string.Empty; + properties.Embed = eb.Build(); + }); } catch (Exception e) { From 4655424fb034adbf9f0c11c60a50565ddbe8afc4 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 19 Jun 2020 12:40:17 +0200 Subject: [PATCH 338/553] Remove prometheus-net from the dependencies --- Geekbot.net/Geekbot.net.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 23f331f..8fc35f4 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -43,7 +43,6 @@ - From a0b1ec44f65ef39495755326f39fd278c04d906e Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 19 Jun 2020 21:46:19 +0200 Subject: [PATCH 339/553] Make it possible to connect to the database with ssl enabled --- Geekbot.net/Database/DatabaseInitializer.cs | 4 +++- Geekbot.net/Database/SqlConnectionString.cs | 5 ++++- Geekbot.net/Lib/RunParameters.cs | 6 ++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Geekbot.net/Database/DatabaseInitializer.cs b/Geekbot.net/Database/DatabaseInitializer.cs index 582327f..637e7b8 100644 --- a/Geekbot.net/Database/DatabaseInitializer.cs +++ b/Geekbot.net/Database/DatabaseInitializer.cs @@ -35,7 +35,9 @@ namespace Geekbot.net.Database Port = _runParameters.DbPort, Database = _runParameters.DbDatabase, Username = _runParameters.DbUser, - Password = _runParameters.DbPassword + Password = _runParameters.DbPassword, + RequireSsl = _runParameters.DbSsl, + TrustServerCertificate = _runParameters.DbTrustCert }); } } diff --git a/Geekbot.net/Database/SqlConnectionString.cs b/Geekbot.net/Database/SqlConnectionString.cs index 3228a05..70346eb 100644 --- a/Geekbot.net/Database/SqlConnectionString.cs +++ b/Geekbot.net/Database/SqlConnectionString.cs @@ -7,10 +7,13 @@ public string Database { get; set; } public string Username { get; set; } public string Password { get; set; } + public bool RequireSsl { get; set; } + public bool TrustServerCertificate { get; set; } public override string ToString() { - return $"Server={Host};Port={Port};Database={Database};Uid={Username};Pwd={Password};"; + var sslMode = RequireSsl ? "Require" : "Prefer"; + return $"ApplicationName=Geekbot;Server={Host};Port={Port};Database={Database};Uid={Username};Pwd={Password};SSLMode={sslMode};TrustServerCertificate={TrustServerCertificate.ToString()};"; } } } \ No newline at end of file diff --git a/Geekbot.net/Lib/RunParameters.cs b/Geekbot.net/Lib/RunParameters.cs index 1ddbd46..8ebed67 100644 --- a/Geekbot.net/Lib/RunParameters.cs +++ b/Geekbot.net/Lib/RunParameters.cs @@ -43,6 +43,12 @@ namespace Geekbot.net.Lib [Option("db-password", HelpText = "Set a posgresql password (default: empty) (env: DB_PASSWORD)")] public string DbPassword { get; set; } = ParamFallback("DB_PASSWORD", ""); + + [Option("db-require-ssl", HelpText = "Require SSL to connect to the database (default: false) (env: DB_REQUIRE_SSL)")] + public bool DbSsl { get; set; } = ParamFallback("DB_REQUIRE_SSL", false); + + [Option("db-trust-cert", HelpText = "Trust the database certificate, regardless if it is valid (default: false) (env: DB_TRUST_CERT)")] + public bool DbTrustCert { get; set; } = ParamFallback("DB_TRUST_CERT", false); // Logging [Option("db-logging", HelpText = "Enable database logging (default: false) (env: DB_LOGGING)")] From e0f17d00ea90021e1864963de6a60938087cb8b9 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 19 Jun 2020 22:19:26 +0200 Subject: [PATCH 340/553] Upgrade to .NET 5 --- .gitlab-ci.yml | 2 +- Geekbot.net/Geekbot.net.csproj | 3 +-- Tests/Tests.csproj | 2 +- WikipediaApi/WikipediaApi.csproj | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7b6b593..d6f3e15 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,7 +10,7 @@ before_script: build: stage: build - image: mcr.microsoft.com/dotnet/core/sdk:3.1 + image: mcr.microsoft.com/dotnet/core/sdk:5.0-focal artifacts: expire_in: 1h paths: diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 8fc35f4..4e13438 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -1,7 +1,7 @@  Exe - netcoreapp3.1 + net5.0 win-x64;linux-x64 derp.ico 4.2.0 @@ -53,7 +53,6 @@ 4.3.0 - diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 345dacd..eaf88a3 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -1,6 +1,6 @@  - netcoreapp3.1 + net5.0 false NU1701 xUnit1026 diff --git a/WikipediaApi/WikipediaApi.csproj b/WikipediaApi/WikipediaApi.csproj index 24c20f7..e53e3c2 100644 --- a/WikipediaApi/WikipediaApi.csproj +++ b/WikipediaApi/WikipediaApi.csproj @@ -1,6 +1,6 @@  - netcoreapp3.1 + net5.0 From f23b8099f1b5687cf17b62dfe1a33c8f951d7e32 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 19 Jun 2020 22:20:05 +0200 Subject: [PATCH 341/553] Try to create a docker image --- .gitignore | 10 +-- .gitlab-ci.yml | 62 ++++++++++--------- Dockerfile | 6 +- .../Lib/Converters/MtgManaConverter.cs | 2 - 4 files changed, 38 insertions(+), 42 deletions(-) diff --git a/.gitignore b/.gitignore index fe7e3d4..5db124b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,6 @@ -Geekbot.net/bin -Geekbot.net/obj +*/bin/ +*/obj/ Geekbot.net/tmp/ -Tests/bin -Tests/obj -Backup/ .vs/ UpgradeLog.htm .idea @@ -12,5 +9,4 @@ Geekbot.net/Logs/* !/Geekbot.net/Logs/.keep Geekbot.net.sln.DotSettings.user Geekbot.net/temp/ -WikipediaApi/bin/ -WikipediaApi/obj/ +app \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d6f3e15..86c6459 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,46 +1,40 @@ stages: - build - - ops + - docker - deploy + - ops -before_script: - - set -e - - set -u - - set -o pipefail - -build: +Build: stage: build image: mcr.microsoft.com/dotnet/core/sdk:5.0-focal artifacts: expire_in: 1h paths: - - Geekbot.net/Binaries/ + - app script: - dotnet restore - dotnet test Tests - - dotnet publish --version-suffix ${CI_COMMIT_SHA:0:8} --configuration Release -o ./Geekbot.net/Binaries ./Geekbot.net/ + - dotnet publish --version-suffix ${CI_COMMIT_SHA:0:8} -r linux-x64 -c Release -o ./app ./Geekbot.net/ -sentry: - stage: ops - image: getsentry/sentry-cli - allow_failure: true - only: - - master - dependencies: - - build - script: - - sentry-cli releases new -p geekbot 4.2.0-${CI_COMMIT_SHA:0:8} - - sentry-cli releases set-commits --auto 4.2.0-${CI_COMMIT_SHA:0:8} - - sentry-cli releases deploys 4.2.0-${CI_COMMIT_SHA:0:8} new -e Production +Package: + stage: docker + image: docker +# only: +# - master + services: + - docker:stable-dind + variables: + IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG + script: + - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + - docker build -t $IMAGE_TAG . + - docker push $IMAGE_TAG -deploy: +Deploy: stage: deploy image: runebaas/rsync-ssh-git only: - master - dependencies: - - build - - sentry environment: name: Production url: https://discordapp.com/oauth2/authorize?client_id=171249478546882561&scope=bot&permissions=1416834054 @@ -54,13 +48,21 @@ deploy: - rsync -rav -e "ssh -p 65432" ./Geekbot.net/Binaries/* geekbot@$DEPIP:$DEPPATH - ssh -p 65432 geekbot@$DEPIP "sudo systemctl restart geekbot.service" -mirror: - stage: deploy +Sentry: + stage: ops + image: getsentry/sentry-cli + allow_failure: true + only: + - master + script: + - sentry-cli releases new -p geekbot 4.2.0-${CI_COMMIT_SHA:0:8} + - sentry-cli releases set-commits --auto 4.2.0-${CI_COMMIT_SHA:0:8} + - sentry-cli releases deploys 4.2.0-${CI_COMMIT_SHA:0:8} new -e Production + +Github Mirror: + stage: ops image: runebaas/rsync-ssh-git only: - master - dependencies: - - build - - sentry script: - git push https://runebaas:$TOKEN@github.com/pizzaandcoffee/Geekbot.net.git origin/master:master -f diff --git a/Dockerfile b/Dockerfile index 7594bec..822471d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ -FROM microsoft/dotnet:2.1-aspnetcore-runtime +FROM mcr.microsoft.com/dotnet/core/aspnet:5.0-focal -COPY Geekbot.net/Binaries /app/ +COPY ./app /app/ EXPOSE 12995/tcp WORKDIR /app -ENTRYPOINT ./run.sh +ENTRYPOINT ./Geekbot.net diff --git a/Geekbot.net/Lib/Converters/MtgManaConverter.cs b/Geekbot.net/Lib/Converters/MtgManaConverter.cs index 7e90df0..cfd893b 100644 --- a/Geekbot.net/Lib/Converters/MtgManaConverter.cs +++ b/Geekbot.net/Lib/Converters/MtgManaConverter.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; -using System.IO; using System.Text.RegularExpressions; -using Utf8Json; namespace Geekbot.net.Lib.Converters { From 3213e10b88ef131a53d7ad53cf2cf77e0e154d29 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 20 Jun 2020 00:20:00 +0200 Subject: [PATCH 342/553] Add Sumologic and Sentry to the run parameters --- Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs | 6 +++--- Geekbot.net/Lib/Logger/GeekbotLogger.cs | 6 +++--- Geekbot.net/Lib/Logger/LoggerFactory.cs | 6 +++--- Geekbot.net/Lib/RunParameters.cs | 10 ++++++++++ Geekbot.net/Program.cs | 5 ++--- 5 files changed, 21 insertions(+), 12 deletions(-) diff --git a/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs b/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs index 7c9d8ff..cda9129 100644 --- a/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs +++ b/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs @@ -18,13 +18,13 @@ namespace Geekbot.net.Lib.ErrorHandling private readonly IRavenClient _raven; private readonly bool _errorsInChat; - public ErrorHandler(IGeekbotLogger logger, ITranslationHandler translation, bool errorsInChat) + public ErrorHandler(IGeekbotLogger logger, ITranslationHandler translation, RunParameters runParameters) { _logger = logger; _translation = translation; - _errorsInChat = errorsInChat; + _errorsInChat = runParameters.ExposeErrors; - var sentryDsn = Environment.GetEnvironmentVariable("SENTRY"); + var sentryDsn = runParameters.SentryEndpoint; if (!string.IsNullOrEmpty(sentryDsn)) { _raven = new RavenClient(sentryDsn) { Release = Constants.BotVersion(), Environment = "Production" }; diff --git a/Geekbot.net/Lib/Logger/GeekbotLogger.cs b/Geekbot.net/Lib/Logger/GeekbotLogger.cs index 09a3ecb..e2a3714 100644 --- a/Geekbot.net/Lib/Logger/GeekbotLogger.cs +++ b/Geekbot.net/Lib/Logger/GeekbotLogger.cs @@ -9,10 +9,10 @@ namespace Geekbot.net.Lib.Logger private readonly NLog.Logger _logger; private readonly JsonSerializerSettings _serializerSettings; - public GeekbotLogger(RunParameters runParameters, bool sumologicActive) + public GeekbotLogger(RunParameters runParameters) { - _logAsJson = sumologicActive || runParameters.LogJson; - _logger = LoggerFactory.CreateNLog(runParameters, sumologicActive); + _logAsJson = !string.IsNullOrEmpty(runParameters.SumologicEndpoint) || runParameters.LogJson; + _logger = LoggerFactory.CreateNLog(runParameters); _serializerSettings = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Serialize, diff --git a/Geekbot.net/Lib/Logger/LoggerFactory.cs b/Geekbot.net/Lib/Logger/LoggerFactory.cs index b07bcda..e31686e 100644 --- a/Geekbot.net/Lib/Logger/LoggerFactory.cs +++ b/Geekbot.net/Lib/Logger/LoggerFactory.cs @@ -9,18 +9,18 @@ namespace Geekbot.net.Lib.Logger { public class LoggerFactory { - public static NLog.Logger CreateNLog(RunParameters runParameters, bool sumologicActive) + public static NLog.Logger CreateNLog(RunParameters runParameters) { var config = new LoggingConfiguration(); - if (sumologicActive) + if (!string.IsNullOrEmpty(runParameters.SumologicEndpoint)) { Console.WriteLine("Logging Geekbot Logs to Sumologic"); config.LoggingRules.Add( new LoggingRule("*", LogLevel.Debug, LogLevel.Fatal, new SumoLogicTarget() { - Url = Environment.GetEnvironmentVariable("GEEKBOT_SUMO"), + Url = runParameters.SumologicEndpoint, SourceName = "GeekbotLogger", Layout = "${message}", UseConsoleLog = false, diff --git a/Geekbot.net/Lib/RunParameters.cs b/Geekbot.net/Lib/RunParameters.cs index 8ebed67..bd8ce25 100644 --- a/Geekbot.net/Lib/RunParameters.cs +++ b/Geekbot.net/Lib/RunParameters.cs @@ -67,6 +67,16 @@ namespace Geekbot.net.Lib [Option("api-port", HelpText = "Port on which the WebApi listens (default: 12995) (env: API_PORT)")] public string ApiPort { get; set; } = ParamFallback("API_PORT", "12995"); + /************************************ + * Intergrations * + ************************************/ + + [Option("sumologic", HelpText = "Sumologic endpoint for logging (default: null) (env: SUMOLOGIC)")] + public string SumologicEndpoint { get; set; } = ParamFallback("SUMOLOGIC"); + + [Option("sentry", HelpText = "Sentry endpoint for error reporting (default: null) (env: SENTRY)")] + public string SentryEndpoint { get; set; } = ParamFallback("SENTRY"); + /************************************ * Helper Functions * ************************************/ diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 1299583..a5b0668 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -58,8 +58,7 @@ namespace Geekbot.net logo.AppendLine(@" \____|_____|_____|_|\_\____/ \___/ |_|"); logo.AppendLine($"Version {Constants.BotVersion()} ".PadRight(41, '=')); Console.WriteLine(logo.ToString()); - var sumologicActive = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("GEEKBOT_SUMO")); - var logger = new GeekbotLogger(runParameters, sumologicActive); + var logger = new GeekbotLogger(runParameters); logger.Information(LogSource.Geekbot, "Starting..."); try { @@ -169,7 +168,7 @@ namespace Geekbot.net var randomNumberGenerator = new RandomNumberGenerator(); var kvMemoryStore = new KvInInMemoryStore(); var translationHandler = new TranslationHandler(_logger, _guildSettingsManager); - var errorHandler = new ErrorHandler(_logger, translationHandler, _runParameters.ExposeErrors); + var errorHandler = new ErrorHandler(_logger, translationHandler, _runParameters); services.AddSingleton(_userRepository); services.AddSingleton(_logger); From a4b914d576fd3effdded6ad13c8fd3f3db30faf8 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 20 Jun 2020 00:43:59 +0200 Subject: [PATCH 343/553] Use Ansible for deployment --- .deploy.yml | 37 +++++++++++++++++++++++++++++++++++++ .gitlab-ci.yml | 31 +++++++++++++++++-------------- 2 files changed, 54 insertions(+), 14 deletions(-) create mode 100644 .deploy.yml diff --git a/.deploy.yml b/.deploy.yml new file mode 100644 index 0000000..39e3233 --- /dev/null +++ b/.deploy.yml @@ -0,0 +1,37 @@ +--- +- name: Geekbot Deploy + hosts: all + remote_user: geekbot + vars: + ansible_port: 65432 + ansible_python_interpreter: /usr/bin/python3 + tasks: + - name: Login to Gitlab Docker Registry + docker_login: + registry_url: "{{ lookup('env', 'CI_REGISTRY') }}" + username: "{{ lookup('env', 'CI_REGISTRY_USER') }}" + password: "{{ lookup('env', 'CI_REGISTRY_PASSWORD') }}" + reauthorize: yes + - name: Replace Prod Container + docker_container: + name: GeekbotProd + image: "{{ lookup('env', 'IMAGE_TAG') }}" + recreate: yes + pull: yes + restart_policy: always + keep_volumes: no + ports: + - "12995:12995" + env: + GEEKBOT_DB_HOST: "{{ lookup('env', 'GEEKBOT_DB_HOST') }}" + GEEKBOT_DB_USER: "{{ lookup('env', 'GEEKBOT_DB_USER') }}" + GEEKBOT_DB_PASSWORD: "{{ lookup('env', 'GEEKBOT_DB_PASSWORD') }}" + GEEKBOT_DB_PORT: "{{ lookup('env', 'GEEKBOT_DB_PORT') }}" + GEEKBOT_DB_DATABASE: "{{ lookup('env', 'GEEKBOT_DB_DATABASE') }}" + GEEKBOT_DB_REQUIRE_SSL: "true" + GEEKBOT_DB_TRUST_CERT: "true" + GEEKBOT_SUMOLOCIG: "{{ lookup('env', 'GEEKBOT_SUMOLOCIG') }}" + GEEKBOT_SENTRY: "{{ lookup('env', 'GEEKBOT_SENTRY') }}" + - name: Cleanup Old Container + docker_prune: + images: yes diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 86c6459..6015b14 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,6 +4,8 @@ stages: - deploy - ops +.imageTag: &IMAGE_TAG $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG + Build: stage: build image: mcr.microsoft.com/dotnet/core/sdk:5.0-focal @@ -19,12 +21,13 @@ Build: Package: stage: docker image: docker -# only: -# - master + only: + - master + - docker services: - docker:stable-dind variables: - IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG + IMAGE_TAG: *IMAGE_TAG script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - docker build -t $IMAGE_TAG . @@ -32,21 +35,21 @@ Package: Deploy: stage: deploy - image: runebaas/rsync-ssh-git + image: ansible/ansible-runner only: - master - environment: - name: Production - url: https://discordapp.com/oauth2/authorize?client_id=171249478546882561&scope=bot&permissions=1416834054 + - docker + variables: + ANSIBLE_NOCOWS: 1 + IMAGE_TAG: *IMAGE_TAG before_script: - - eval $(ssh-agent -s) - - mkdir -p ~/.ssh - - '[[ -f /.dockerenv ]] && echo -e "Host *\n StrictHostKeyChecking no" > ~/.ssh/config' - - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null - - chmod 700 ~/.ssh + - mkdir /root/.ssh + - cp $SSH_PRIVATE_KEY /root/.ssh/id_ed25519 + - cp $SSH_PUBLIC_KEY /root/.ssh/id_ed25519.pub + - chmod -R 600 /root/.ssh + - ssh-keyscan -p 65432 $PROD_IP > /root/.ssh/known_hosts script: - - rsync -rav -e "ssh -p 65432" ./Geekbot.net/Binaries/* geekbot@$DEPIP:$DEPPATH - - ssh -p 65432 geekbot@$DEPIP "sudo systemctl restart geekbot.service" + - ansible-playbook -i $PROD_IP, .deploy.yml Sentry: stage: ops From d9f8e9a80ecb76b89c19fbfa2445cd789088754d Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 20 Jun 2020 03:05:51 +0200 Subject: [PATCH 344/553] Add redshift (and DigitalOcean Managed DB) compatibility and start using a string building to create the sql connection string --- .deploy.yml | 1 + Geekbot.net/Database/DatabaseInitializer.cs | 3 ++- Geekbot.net/Database/SqlConnectionString.cs | 24 +++++++++++++++++++-- Geekbot.net/Lib/RunParameters.cs | 3 +++ 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/.deploy.yml b/.deploy.yml index 39e3233..fd2df00 100644 --- a/.deploy.yml +++ b/.deploy.yml @@ -32,6 +32,7 @@ GEEKBOT_DB_TRUST_CERT: "true" GEEKBOT_SUMOLOCIG: "{{ lookup('env', 'GEEKBOT_SUMOLOCIG') }}" GEEKBOT_SENTRY: "{{ lookup('env', 'GEEKBOT_SENTRY') }}" + GEEKBOT_DB_REDSHIFT_COMPAT: "true" - name: Cleanup Old Container docker_prune: images: yes diff --git a/Geekbot.net/Database/DatabaseInitializer.cs b/Geekbot.net/Database/DatabaseInitializer.cs index 637e7b8..9f60d8a 100644 --- a/Geekbot.net/Database/DatabaseInitializer.cs +++ b/Geekbot.net/Database/DatabaseInitializer.cs @@ -37,7 +37,8 @@ namespace Geekbot.net.Database Username = _runParameters.DbUser, Password = _runParameters.DbPassword, RequireSsl = _runParameters.DbSsl, - TrustServerCertificate = _runParameters.DbTrustCert + TrustServerCertificate = _runParameters.DbTrustCert, + RedshiftCompatibility = _runParameters.DbRedshiftCompatibility }); } } diff --git a/Geekbot.net/Database/SqlConnectionString.cs b/Geekbot.net/Database/SqlConnectionString.cs index 70346eb..61804cf 100644 --- a/Geekbot.net/Database/SqlConnectionString.cs +++ b/Geekbot.net/Database/SqlConnectionString.cs @@ -1,4 +1,6 @@ -namespace Geekbot.net.Database +using System.Text; + +namespace Geekbot.net.Database { public class SqlConnectionString { @@ -9,11 +11,29 @@ public string Password { get; set; } public bool RequireSsl { get; set; } public bool TrustServerCertificate { get; set; } + public bool RedshiftCompatibility { get; set; } public override string ToString() { + var sb = new StringBuilder(); + sb.Append("Application Name=Geekbot;"); + + sb.Append($"Host={Host};"); + sb.Append($"Port={Port};"); + sb.Append($"Database={Database};"); + sb.Append($"Username={Username};"); + sb.Append($"Password={Password};"); + var sslMode = RequireSsl ? "Require" : "Prefer"; - return $"ApplicationName=Geekbot;Server={Host};Port={Port};Database={Database};Uid={Username};Pwd={Password};SSLMode={sslMode};TrustServerCertificate={TrustServerCertificate.ToString()};"; + sb.Append($"SSL Mode={sslMode};"); + sb.Append($"Trust Server Certificate={TrustServerCertificate.ToString()};"); + + if (RedshiftCompatibility) + { + sb.Append("Server Compatibility Mode=Redshift"); + } + + return sb.ToString(); } } } \ No newline at end of file diff --git a/Geekbot.net/Lib/RunParameters.cs b/Geekbot.net/Lib/RunParameters.cs index bd8ce25..eb8c078 100644 --- a/Geekbot.net/Lib/RunParameters.cs +++ b/Geekbot.net/Lib/RunParameters.cs @@ -49,6 +49,9 @@ namespace Geekbot.net.Lib [Option("db-trust-cert", HelpText = "Trust the database certificate, regardless if it is valid (default: false) (env: DB_TRUST_CERT)")] public bool DbTrustCert { get; set; } = ParamFallback("DB_TRUST_CERT", false); + + [Option("db-redshift-compat", HelpText = "Enable compatibility for AWS Redshift and DigitalOcean Managed Database (default: false) (env: DB_REDSHIFT_COMPAT)")] + public bool DbRedshiftCompatibility { get; set; } = ParamFallback("DB_REDSHIFT_COMPAT", false); // Logging [Option("db-logging", HelpText = "Enable database logging (default: false) (env: DB_LOGGING)")] From 56f788878ad83623da69daf6b13ebddb2e1336e5 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 20 Jun 2020 03:17:17 +0200 Subject: [PATCH 345/553] Fix Sumologic environment variable in docker --- .deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.deploy.yml b/.deploy.yml index fd2df00..cf0e485 100644 --- a/.deploy.yml +++ b/.deploy.yml @@ -30,7 +30,7 @@ GEEKBOT_DB_DATABASE: "{{ lookup('env', 'GEEKBOT_DB_DATABASE') }}" GEEKBOT_DB_REQUIRE_SSL: "true" GEEKBOT_DB_TRUST_CERT: "true" - GEEKBOT_SUMOLOCIG: "{{ lookup('env', 'GEEKBOT_SUMOLOCIG') }}" + GEEKBOT_SUMOLOGIC: "{{ lookup('env', 'GEEKBOT_SUMOLOCIG') }}" GEEKBOT_SENTRY: "{{ lookup('env', 'GEEKBOT_SENTRY') }}" GEEKBOT_DB_REDSHIFT_COMPAT: "true" - name: Cleanup Old Container From 619f63067c9f4726f06cda4982b4a800c34d38aa Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 20 Jun 2020 03:23:27 +0200 Subject: [PATCH 346/553] Remove the ability the lookup username history for moderators --- Geekbot.net/Commands/Admin/Mod.cs | 25 +++---------------- Geekbot.net/Database/Models/UserModel.cs | 2 -- .../Database/Models/UserUsedNamesModel.cs | 15 ----------- .../Lib/UserRepository/UserRepository.cs | 5 ---- 4 files changed, 3 insertions(+), 44 deletions(-) delete mode 100644 Geekbot.net/Database/Models/UserUsedNamesModel.cs diff --git a/Geekbot.net/Commands/Admin/Mod.cs b/Geekbot.net/Commands/Admin/Mod.cs index f4beb54..b0114a8 100644 --- a/Geekbot.net/Commands/Admin/Mod.cs +++ b/Geekbot.net/Commands/Admin/Mod.cs @@ -1,12 +1,9 @@ using System; -using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Discord.WebSocket; using Geekbot.net.Lib.CommandPreconditions; using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.UserRepository; namespace Geekbot.net.Commands.Admin { @@ -17,15 +14,11 @@ namespace Geekbot.net.Commands.Admin [DisableInDirectMessage] public class Mod : ModuleBase { - private readonly DiscordSocketClient _client; private readonly IErrorHandler _errorHandler; - private readonly IUserRepository _userRepository; - public Mod(IUserRepository userRepositry, IErrorHandler errorHandler, DiscordSocketClient client) + public Mod(IErrorHandler errorHandler) { - _userRepository = userRepositry; _errorHandler = errorHandler; - _client = client; } [Command("namehistory", RunMode = RunMode.Async)] @@ -34,23 +27,11 @@ namespace Geekbot.net.Commands.Admin { try { - var userRepo = _userRepository.Get(user.Id); - if (userRepo?.UsedNames != null) - { - var sb = new StringBuilder(); - sb.AppendLine($":bust_in_silhouette: {user.Username} has been known as:"); - foreach (var name in userRepo.UsedNames) sb.AppendLine($"- `{name.Name}`"); - await ReplyAsync(sb.ToString()); - } - else - { - await ReplyAsync($"No name changes found for {user.Username}"); - } + await Context.Channel.SendMessageAsync("This command has been removed due to low usage and excessively high database usage"); } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context, - "I don't have enough permissions do that"); + await _errorHandler.HandleCommandException(e, Context); } } } diff --git a/Geekbot.net/Database/Models/UserModel.cs b/Geekbot.net/Database/Models/UserModel.cs index b9c60ca..43d3a9a 100644 --- a/Geekbot.net/Database/Models/UserModel.cs +++ b/Geekbot.net/Database/Models/UserModel.cs @@ -24,7 +24,5 @@ namespace Geekbot.net.Database.Models public bool IsBot { get; set; } public DateTimeOffset Joined { get; set; } - - public List UsedNames { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Database/Models/UserUsedNamesModel.cs b/Geekbot.net/Database/Models/UserUsedNamesModel.cs deleted file mode 100644 index 48ba873..0000000 --- a/Geekbot.net/Database/Models/UserUsedNamesModel.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.ComponentModel.DataAnnotations; - -namespace Geekbot.net.Database.Models -{ - public class UserUsedNamesModel - { - [Key] - public int Id { get; set; } - - public string Name { get; set; } - - public DateTimeOffset FirstSeen { get; set; } - } -} \ No newline at end of file diff --git a/Geekbot.net/Lib/UserRepository/UserRepository.cs b/Geekbot.net/Lib/UserRepository/UserRepository.cs index b27a0a2..41e8e73 100644 --- a/Geekbot.net/Lib/UserRepository/UserRepository.cs +++ b/Geekbot.net/Lib/UserRepository/UserRepository.cs @@ -37,11 +37,6 @@ namespace Geekbot.net.Lib.UserRepository savedUser.AvatarUrl = user.GetAvatarUrl() ?? ""; savedUser.IsBot = user.IsBot; savedUser.Joined = user.CreatedAt; - if (savedUser.UsedNames == null) savedUser.UsedNames = new List(); - if (!savedUser.UsedNames.Any(e => e.Name.Equals(user.Username))) - { - savedUser.UsedNames.Add(new UserUsedNamesModel { Name = user.Username, FirstSeen = DateTimeOffset.Now }); - } if (isNew) { From 8f41999015f90817e556b0c2958b28fa3fb48251 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 20 Jun 2020 03:25:28 +0200 Subject: [PATCH 347/553] Expose the web api directly on port 80 --- .deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.deploy.yml b/.deploy.yml index cf0e485..e9915ba 100644 --- a/.deploy.yml +++ b/.deploy.yml @@ -21,7 +21,7 @@ restart_policy: always keep_volumes: no ports: - - "12995:12995" + - "80:12995" env: GEEKBOT_DB_HOST: "{{ lookup('env', 'GEEKBOT_DB_HOST') }}" GEEKBOT_DB_USER: "{{ lookup('env', 'GEEKBOT_DB_USER') }}" From 194bfd3d3b61c0a8ae4534fe742ef743a8cf32fe Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 20 Jun 2020 03:27:08 +0200 Subject: [PATCH 348/553] remove traces of the docker branch from the ci file --- .gitlab-ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6015b14..2e22e02 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -23,7 +23,6 @@ Package: image: docker only: - master - - docker services: - docker:stable-dind variables: @@ -38,7 +37,6 @@ Deploy: image: ansible/ansible-runner only: - master - - docker variables: ANSIBLE_NOCOWS: 1 IMAGE_TAG: *IMAGE_TAG From 279a8975c91eb8c061d1320709617d31ffaf1fd5 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 20 Jun 2020 03:42:41 +0200 Subject: [PATCH 349/553] Expose web api on port 12995 again --- .deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.deploy.yml b/.deploy.yml index e9915ba..cf0e485 100644 --- a/.deploy.yml +++ b/.deploy.yml @@ -21,7 +21,7 @@ restart_policy: always keep_volumes: no ports: - - "80:12995" + - "12995:12995" env: GEEKBOT_DB_HOST: "{{ lookup('env', 'GEEKBOT_DB_HOST') }}" GEEKBOT_DB_USER: "{{ lookup('env', 'GEEKBOT_DB_USER') }}" From d7e313c9fa996cf008dae2721f892d4bad23ca30 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 20 Jun 2020 03:43:02 +0200 Subject: [PATCH 350/553] Update readme --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index c7f3f33..883e553 100644 --- a/readme.md +++ b/readme.md @@ -2,13 +2,13 @@ # [Geekbot.net](https://geekbot.pizzaandcoffee.rocks/) -A General Purpose Discord Bot written in DotNet Core. +A General Purpose Discord Bot written in C# You can invite Geekbot to your server with [this link](https://discordapp.com/oauth2/authorize?client_id=171249478546882561&scope=bot&permissions=1416834054) ## Technologies -* DotNet Core 3.1 +* .NET 5 * PostgreSQL * Discord.net From 6d449608671cb47c5705d65ad6f0f367d6b9801c Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 21 Jun 2020 03:33:05 +0200 Subject: [PATCH 351/553] Rewrite the !dice command from scratch --- Geekbot.net/Commands/Utils/Dice.cs | 107 ++++++++++++++++ Geekbot.net/Commands/Utils/Dice/Dice.cs | 116 ------------------ .../Commands/Utils/Dice/DiceTypeDto.cs | 10 -- Geekbot.net/Lib/DiceParser/DiceException.cs | 13 ++ Geekbot.net/Lib/DiceParser/DiceInput.cs | 11 ++ .../Lib/DiceParser/DiceInputOptions.cs | 7 ++ Geekbot.net/Lib/DiceParser/DiceParser.cs | 102 +++++++++++++++ .../Lib/DiceParser/DieAdvantageType.cs | 9 ++ Geekbot.net/Lib/DiceParser/DieResult.cs | 30 +++++ Geekbot.net/Lib/DiceParser/IDiceParser.cs | 7 ++ Geekbot.net/Lib/DiceParser/SingleDie.cs | 72 +++++++++++ Geekbot.net/Lib/Extensions/IntExtensions.cs | 15 +++ Geekbot.net/Program.cs | 3 + 13 files changed, 376 insertions(+), 126 deletions(-) create mode 100644 Geekbot.net/Commands/Utils/Dice.cs delete mode 100644 Geekbot.net/Commands/Utils/Dice/Dice.cs delete mode 100644 Geekbot.net/Commands/Utils/Dice/DiceTypeDto.cs create mode 100644 Geekbot.net/Lib/DiceParser/DiceException.cs create mode 100644 Geekbot.net/Lib/DiceParser/DiceInput.cs create mode 100644 Geekbot.net/Lib/DiceParser/DiceInputOptions.cs create mode 100644 Geekbot.net/Lib/DiceParser/DiceParser.cs create mode 100644 Geekbot.net/Lib/DiceParser/DieAdvantageType.cs create mode 100644 Geekbot.net/Lib/DiceParser/DieResult.cs create mode 100644 Geekbot.net/Lib/DiceParser/IDiceParser.cs create mode 100644 Geekbot.net/Lib/DiceParser/SingleDie.cs create mode 100644 Geekbot.net/Lib/Extensions/IntExtensions.cs diff --git a/Geekbot.net/Commands/Utils/Dice.cs b/Geekbot.net/Commands/Utils/Dice.cs new file mode 100644 index 0000000..f570271 --- /dev/null +++ b/Geekbot.net/Commands/Utils/Dice.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Discord.Commands; +using Geekbot.net.Lib.DiceParser; +using Geekbot.net.Lib.ErrorHandling; + +namespace Geekbot.net.Commands.Utils +{ + public class Dice : ModuleBase + { + private readonly IErrorHandler _errorHandler; + private readonly IDiceParser _diceParser; + + public Dice(IErrorHandler errorHandler, IDiceParser diceParser) + { + _errorHandler = errorHandler; + _diceParser = diceParser; + } + + // ToDo: Separate representation and logic + // ToDo: Translate + [Command("dice", RunMode = RunMode.Async)] + [Summary("Roll a dice. (use '!dice help' for a manual)")] + public async Task RollCommand([Remainder] [Summary("input")] string diceInput = "1d20") + { + try + { + if (diceInput == "help") + { + await ShowDiceHelp(); + return; + } + + var parsed = _diceParser.Parse(diceInput); + + var sb = new StringBuilder(); + sb.AppendLine($"{Context.User.Mention} :game_die:"); + foreach (var die in parsed.Dice) + { + sb.AppendLine($"**{die.DiceName}**"); + var diceResultList = new List(); + var total = 0; + + foreach (var roll in die.Roll()) + { + diceResultList.Add(roll.ToString()); + total += roll.Result; + } + + sb.AppendLine(string.Join(" | ", diceResultList)); + + if (parsed.SkillModifier != 0) + { + sb.AppendLine($"Skill: {parsed.SkillModifier}"); + } + + if (parsed.Options.ShowTotal) + { + var totalLine = $"Total: {total}"; + if (parsed.SkillModifier > 0) + { + totalLine += ($" (+{parsed.SkillModifier} = {total + parsed.SkillModifier})"); + } + + if (parsed.SkillModifier < 0) + { + totalLine += ($" ({parsed.SkillModifier} = {total - parsed.SkillModifier})"); + } + + sb.AppendLine(totalLine); + } + } + + await Context.Channel.SendMessageAsync(sb.ToString()); + } + catch (DiceException e) + { + await Context.Channel.SendMessageAsync($"**:warning: {e.DiceName} is invalid:** {e.Message}"); + } + catch (Exception e) + { + await _errorHandler.HandleCommandException(e, Context); + } + } + + private async Task ShowDiceHelp() + { + var sb = new StringBuilder(); + sb.AppendLine("**__Examples__**"); + sb.AppendLine("```"); + sb.AppendLine("'!dice' - throw a 1d20"); + sb.AppendLine("'!dice 1d12' - throw a 1d12"); + sb.AppendLine("'!dice +1d20' - throw with advantage"); + sb.AppendLine("'!dice -1d20' - throw with disadvantage"); + sb.AppendLine("'!dice 1d20 +2' - throw with a +2 skill bonus"); + sb.AppendLine("'!dice 1d20 -2' - throw with a -2 skill bonus"); + sb.AppendLine("'!dice 8d6' - throw ~~a fireball~~ a 8d6"); + sb.AppendLine("'!dice 8d6 total' - calculate the total"); + sb.AppendLine("'!dice 2d20 6d6 2d4 2d12' - drop your dice pouch"); + sb.AppendLine("```"); + + await Context.Channel.SendMessageAsync(sb.ToString()); + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Utils/Dice/Dice.cs b/Geekbot.net/Commands/Utils/Dice/Dice.cs deleted file mode 100644 index c335982..0000000 --- a/Geekbot.net/Commands/Utils/Dice/Dice.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Discord.Commands; -using Geekbot.net.Lib.RandomNumberGenerator; - -namespace Geekbot.net.Commands.Utils.Dice -{ - public class Dice : ModuleBase - { - private readonly IRandomNumberGenerator _randomNumberGenerator; - - public Dice(IRandomNumberGenerator randomNumberGenerator) - { - _randomNumberGenerator = randomNumberGenerator; - } - - [Command("dice", RunMode = RunMode.Async)] - [Summary("Roll a dice.")] - public async Task RollCommand([Remainder] [Summary("dice-type")] string diceType = "1d20") - { - var splitedDices = diceType.Split("+"); - var dices = new List(); - var mod = 0; - foreach (var i in splitedDices) - { - var dice = ToDice(i); - if (dice.Sides != 0 && dice.Times != 0) - { - dices.Add(dice); - } - else if (dice.Mod != 0) - { - if (mod != 0) - { - await ReplyAsync("You can only have one mod"); - return; - } - - mod = dice.Mod; - } - } - - if (!dices.Any()) - { - await ReplyAsync( - "That is not a valid dice, examples are: 1d20, 1d6, 2d6, 1d6+2, 1d6+2d8+1d20+6, etc..."); - return; - } - - - if (dices.Any(d => d.Times > 20)) - { - await ReplyAsync("You can't throw more than 20 dices"); - return; - } - - if (dices.Any(d => d.Sides > 144)) - { - await ReplyAsync("A dice can't have more than 144 sides"); - return; - } - - var rep = new StringBuilder(); - rep.AppendLine($":game_die: {Context.User.Mention}"); - rep.Append("**Result:** "); - var resultStrings = new List(); - var total = 0; - foreach (var dice in dices) - { - var results = new List(); - for (var i = 0; i < dice.Times; i++) - { - var roll = _randomNumberGenerator.Next(1, dice.Sides); - total += roll; - results.Add(roll); - } - - resultStrings.Add($"{dice.DiceType} ({string.Join(",", results)})"); - } - - rep.Append(string.Join(" + ", resultStrings)); - if (mod != 0) - { - rep.Append($" + {mod}"); - total += mod; - } - - rep.AppendLine(); - rep.AppendLine($"**Total:** {total}"); - await ReplyAsync(rep.ToString()); - } - - private DiceTypeDto ToDice(string dice) - { - var diceParts = dice.Split('d'); - if (diceParts.Length == 2 - && int.TryParse(diceParts[0], out var times) - && int.TryParse(diceParts[1], out var max)) - return new DiceTypeDto - { - DiceType = dice, - Times = times, - Sides = max - }; - if (dice.Length == 1 - && int.TryParse(diceParts[0], out var mod)) - return new DiceTypeDto - { - Mod = mod - }; - return new DiceTypeDto(); - } - } -} \ No newline at end of file diff --git a/Geekbot.net/Commands/Utils/Dice/DiceTypeDto.cs b/Geekbot.net/Commands/Utils/Dice/DiceTypeDto.cs deleted file mode 100644 index 5c54792..0000000 --- a/Geekbot.net/Commands/Utils/Dice/DiceTypeDto.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Geekbot.net.Commands.Utils.Dice -{ - internal class DiceTypeDto - { - public string DiceType { get; set; } - public int Times { get; set; } - public int Sides { get; set; } - public int Mod { get; set; } - } -} \ No newline at end of file diff --git a/Geekbot.net/Lib/DiceParser/DiceException.cs b/Geekbot.net/Lib/DiceParser/DiceException.cs new file mode 100644 index 0000000..d2a66ad --- /dev/null +++ b/Geekbot.net/Lib/DiceParser/DiceException.cs @@ -0,0 +1,13 @@ +using System; + +namespace Geekbot.net.Lib.DiceParser +{ + public class DiceException : Exception + { + public DiceException(string message) : base(message) + { + } + + public string DiceName { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/DiceParser/DiceInput.cs b/Geekbot.net/Lib/DiceParser/DiceInput.cs new file mode 100644 index 0000000..baca42c --- /dev/null +++ b/Geekbot.net/Lib/DiceParser/DiceInput.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; + +namespace Geekbot.net.Lib.DiceParser +{ + public class DiceInput + { + public List Dice { get; set; } = new List(); + public DiceInputOptions Options { get; set; } = new DiceInputOptions(); + public int SkillModifier { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/DiceParser/DiceInputOptions.cs b/Geekbot.net/Lib/DiceParser/DiceInputOptions.cs new file mode 100644 index 0000000..41f2def --- /dev/null +++ b/Geekbot.net/Lib/DiceParser/DiceInputOptions.cs @@ -0,0 +1,7 @@ +namespace Geekbot.net.Lib.DiceParser +{ + public struct DiceInputOptions + { + public bool ShowTotal { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/DiceParser/DiceParser.cs b/Geekbot.net/Lib/DiceParser/DiceParser.cs new file mode 100644 index 0000000..7f90865 --- /dev/null +++ b/Geekbot.net/Lib/DiceParser/DiceParser.cs @@ -0,0 +1,102 @@ +using System; +using System.Linq; +using System.Text.RegularExpressions; +using Geekbot.net.Lib.RandomNumberGenerator; + +namespace Geekbot.net.Lib.DiceParser +{ + public class DiceParser : IDiceParser + { + private readonly IRandomNumberGenerator _randomNumberGenerator; + private readonly Regex _inputRegex; + private readonly Regex _singleDieRegex; + + public DiceParser(IRandomNumberGenerator randomNumberGenerator) + { + _randomNumberGenerator = randomNumberGenerator; + _inputRegex = new Regex( + @"((?\+\d+d\d+)|(?\-\d+d\d+)|(?\d+d\d+)|(?(total))|(?(\+|\-)\d+))\s", + RegexOptions.Compiled | RegexOptions.IgnoreCase, + new TimeSpan(0, 0, 2)); + _singleDieRegex = new Regex( + @"\d+d\d+", + RegexOptions.Compiled | RegexOptions.IgnoreCase, + new TimeSpan(0, 0, 0, 0, 500)); + } + + public DiceInput Parse(string input) + { + // adding a whitespace at the end, otherwise the parser might pickup on false items + var inputWithExtraWhitespace = $"{input} "; + + var matches = _inputRegex.Matches(inputWithExtraWhitespace); + var result = new DiceInput(); + var resultOptions = new DiceInputOptions(); + + foreach (Match match in matches) + { + foreach (Group matchGroup in match.Groups) + { + if (matchGroup.Success) + { + switch (matchGroup.Name) + { + case "DieNormal": + result.Dice.Add(Die(matchGroup.Value, DieAdvantageType.None)); + break; + case "DieAdvantage": + result.Dice.Add(Die(matchGroup.Value, DieAdvantageType.Advantage)); + break; + case "DieDisadvantage": + result.Dice.Add(Die(matchGroup.Value, DieAdvantageType.Disadvantage)); + break; + case "Keywords": + Keywords(matchGroup.Value, ref resultOptions); + break; + case "SkillModifer": + result.SkillModifier = SkillModifer(matchGroup.Value); + break; + } + } + } + } + + if (!result.Dice.Any()) + { + result.Dice.Add(new SingleDie(_randomNumberGenerator)); + } + + result.Options = resultOptions; + + return result; + } + + private SingleDie Die(string match, DieAdvantageType advantageType) + { + var x = _singleDieRegex.Match(match).Value.Split('d'); + var die = new SingleDie(_randomNumberGenerator) + { + Amount = int.Parse(x[0]), + Sides = int.Parse(x[1]), + AdvantageType = advantageType + }; + die.ValidateDie(); + return die; + } + + private int SkillModifer(string match) + { + return int.Parse(match); + } + + private void Keywords(string match, ref DiceInputOptions options) + { + switch (match) + { + case "total": + options.ShowTotal = true; + break; + } + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/DiceParser/DieAdvantageType.cs b/Geekbot.net/Lib/DiceParser/DieAdvantageType.cs new file mode 100644 index 0000000..91818cb --- /dev/null +++ b/Geekbot.net/Lib/DiceParser/DieAdvantageType.cs @@ -0,0 +1,9 @@ +namespace Geekbot.net.Lib.DiceParser +{ + public enum DieAdvantageType + { + Advantage, + Disadvantage, + None + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/DiceParser/DieResult.cs b/Geekbot.net/Lib/DiceParser/DieResult.cs new file mode 100644 index 0000000..2f99fb6 --- /dev/null +++ b/Geekbot.net/Lib/DiceParser/DieResult.cs @@ -0,0 +1,30 @@ +using System; + +namespace Geekbot.net.Lib.DiceParser +{ + public class DieResult + { + // public int Result { get; set; } + public int Roll1 { get; set; } + public int Roll2 { get; set; } + public DieAdvantageType AdvantageType { get; set; } + + public override string ToString() + { + return AdvantageType switch + { + DieAdvantageType.Advantage => Roll1 > Roll2 ? $"(**{Roll1}**, {Roll2})" : $"({Roll1}, **{Roll2}**)", + DieAdvantageType.Disadvantage => Roll1 < Roll2 ? $"(**{Roll1}**, {Roll2})" : $"({Roll1}, **{Roll2}**)", + _ => Result.ToString() + }; + } + + public int Result => AdvantageType switch + { + DieAdvantageType.None => Roll1, + DieAdvantageType.Advantage => Math.Max(Roll1, Roll2), + DieAdvantageType.Disadvantage => Math.Min(Roll1, Roll2), + _ => 0 + }; + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/DiceParser/IDiceParser.cs b/Geekbot.net/Lib/DiceParser/IDiceParser.cs new file mode 100644 index 0000000..608b379 --- /dev/null +++ b/Geekbot.net/Lib/DiceParser/IDiceParser.cs @@ -0,0 +1,7 @@ +namespace Geekbot.net.Lib.DiceParser +{ + public interface IDiceParser + { + DiceInput Parse(string input); + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/DiceParser/SingleDie.cs b/Geekbot.net/Lib/DiceParser/SingleDie.cs new file mode 100644 index 0000000..24280d1 --- /dev/null +++ b/Geekbot.net/Lib/DiceParser/SingleDie.cs @@ -0,0 +1,72 @@ +using System.Collections.Generic; +using Geekbot.net.Lib.Extensions; +using Geekbot.net.Lib.RandomNumberGenerator; + +namespace Geekbot.net.Lib.DiceParser +{ + public class SingleDie + { + private readonly IRandomNumberGenerator _random; + + public SingleDie(IRandomNumberGenerator random) + { + _random = random; + } + + public int Sides { get; set; } = 20; + public int Amount { get; set; } = 1; + public DieAdvantageType AdvantageType { get; set; } = DieAdvantageType.None; + + public string DiceName => AdvantageType switch + { + DieAdvantageType.Advantage => $"{Amount}d{Sides} (with advantage)", + DieAdvantageType.Disadvantage => $"{Amount}d{Sides} (with disadvantage)", + _ => $"{Amount}d{Sides}" + }; + + public List Roll() + { + var results = new List(); + + Amount.Times(() => + { + var result = new DieResult + { + Roll1 = _random.Next(1, Sides), + AdvantageType = AdvantageType + }; + + if (AdvantageType == DieAdvantageType.Advantage || AdvantageType == DieAdvantageType.Disadvantage) + { + result.Roll2 = _random.Next(1, Sides); + } + + results.Add(result); + }); + + return results; + } + + public void ValidateDie() + { + if (Amount < 1) + { + throw new DiceException("To few dice, must be a minimum of 1"); + } + if (Amount > 24) + { + throw new DiceException("To many dice, maximum allowed is 24") { DiceName = DiceName }; + } + + if (Sides < 2) + { + throw new DiceException("Die must have at least 2 sides") { DiceName = DiceName }; + } + + if (Sides > 144) + { + throw new DiceException("Die can not have more than 144 sides") { DiceName = DiceName }; + } + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Lib/Extensions/IntExtensions.cs b/Geekbot.net/Lib/Extensions/IntExtensions.cs new file mode 100644 index 0000000..ed0fc10 --- /dev/null +++ b/Geekbot.net/Lib/Extensions/IntExtensions.cs @@ -0,0 +1,15 @@ +using System; + +namespace Geekbot.net.Lib.Extensions +{ + public static class IntExtensions + { + public static void Times(this int count, Action action) + { + for (var i = 0; i < count; i++) + { + action(); + } + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index a5b0668..3d98ad9 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -11,6 +11,7 @@ using Geekbot.net.Handlers; using Geekbot.net.Lib; using Geekbot.net.Lib.Clients; using Geekbot.net.Lib.Converters; +using Geekbot.net.Lib.DiceParser; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.GlobalSettings; using Geekbot.net.Lib.GuildSettingsManager; @@ -169,6 +170,7 @@ namespace Geekbot.net var kvMemoryStore = new KvInInMemoryStore(); var translationHandler = new TranslationHandler(_logger, _guildSettingsManager); var errorHandler = new ErrorHandler(_logger, translationHandler, _runParameters); + var diceParser = new DiceParser(randomNumberGenerator); services.AddSingleton(_userRepository); services.AddSingleton(_logger); @@ -183,6 +185,7 @@ namespace Geekbot.net services.AddSingleton(kvMemoryStore); services.AddSingleton(_globalSettings); services.AddSingleton(errorHandler); + services.AddSingleton(diceParser); services.AddSingleton(translationHandler); services.AddSingleton(_reactionListener); services.AddSingleton(_guildSettingsManager); From acd1cee16cbdc2c695be7662cb929fc5da0f6581 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 21 Jun 2020 03:43:11 +0200 Subject: [PATCH 352/553] Reformat !dice help --- Geekbot.net/Commands/Utils/Dice.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Geekbot.net/Commands/Utils/Dice.cs b/Geekbot.net/Commands/Utils/Dice.cs index f570271..2cd2e19 100644 --- a/Geekbot.net/Commands/Utils/Dice.cs +++ b/Geekbot.net/Commands/Utils/Dice.cs @@ -90,15 +90,15 @@ namespace Geekbot.net.Commands.Utils var sb = new StringBuilder(); sb.AppendLine("**__Examples__**"); sb.AppendLine("```"); - sb.AppendLine("'!dice' - throw a 1d20"); - sb.AppendLine("'!dice 1d12' - throw a 1d12"); - sb.AppendLine("'!dice +1d20' - throw with advantage"); - sb.AppendLine("'!dice -1d20' - throw with disadvantage"); - sb.AppendLine("'!dice 1d20 +2' - throw with a +2 skill bonus"); - sb.AppendLine("'!dice 1d20 -2' - throw with a -2 skill bonus"); - sb.AppendLine("'!dice 8d6' - throw ~~a fireball~~ a 8d6"); - sb.AppendLine("'!dice 8d6 total' - calculate the total"); - sb.AppendLine("'!dice 2d20 6d6 2d4 2d12' - drop your dice pouch"); + sb.AppendLine("!dice - throw a 1d20"); + sb.AppendLine("!dice 1d12 - throw a 1d12"); + sb.AppendLine("!dice +1d20 - throw with advantage"); + sb.AppendLine("!dice -1d20 - throw with disadvantage"); + sb.AppendLine("!dice 1d20 +2 - throw with a +2 skill bonus"); + sb.AppendLine("!dice 1d20 -2 - throw with a -2 skill bonus"); + sb.AppendLine("!dice 8d6 - throw a fireball 🔥"); + sb.AppendLine("!dice 8d6 total - calculate the total"); + sb.AppendLine("!dice 2d20 6d6 2d12 - drop your dice pouch"); sb.AppendLine("```"); await Context.Channel.SendMessageAsync(sb.ToString()); From 859db4ebddc4322ab1745c8b7f5744574813b465 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 21 Jun 2020 15:49:18 +0200 Subject: [PATCH 353/553] Add some unit tests for the dice parser --- Tests/Lib/DiceParser/DiceParser.test.cs | 209 ++++++++++++++++++++++++ Tests/Lib/DiceParser/SingleDie.test.cs | 125 ++++++++++++++ 2 files changed, 334 insertions(+) create mode 100644 Tests/Lib/DiceParser/DiceParser.test.cs create mode 100644 Tests/Lib/DiceParser/SingleDie.test.cs diff --git a/Tests/Lib/DiceParser/DiceParser.test.cs b/Tests/Lib/DiceParser/DiceParser.test.cs new file mode 100644 index 0000000..48a362c --- /dev/null +++ b/Tests/Lib/DiceParser/DiceParser.test.cs @@ -0,0 +1,209 @@ +using System.Collections.Generic; +using System.Text.Json; +using Geekbot.net.Lib.DiceParser; +using Geekbot.net.Lib.RandomNumberGenerator; +using Xunit; +using YamlDotNet.Serialization; + +namespace Tests.Lib.DiceParser +{ + public class DiceParserTest + { + private static readonly RandomNumberGenerator _randomNumberGenerator = new RandomNumberGenerator(); + + public struct DiceParserTestDto + { + public string Input { get; set; } + public DiceInput Expected { get; set; } + } + + public static TestData DiceParserTestData => + new TestData + { + { + "Empty Input", + new DiceParserTestDto + { + Input = "", + Expected = new DiceInput() + { + Dice = new List + { + new SingleDie(_randomNumberGenerator) + { + Amount = 1, + Sides = 20, + AdvantageType = DieAdvantageType.None + } + } + } + } + }, + { + "Simple 1d20 input", + new DiceParserTestDto + { + Input = "1d20", + Expected = new DiceInput() + { + Dice = new List + { + new SingleDie(_randomNumberGenerator) + { + Amount = 1, + Sides = 20, + AdvantageType = DieAdvantageType.None + } + } + } + } + }, + { + "2d8 with advantage", + new DiceParserTestDto + { + Input = "+2d8", + Expected = new DiceInput() + { + Dice = new List + { + new SingleDie(_randomNumberGenerator) + { + Amount = 2, + Sides = 8, + AdvantageType = DieAdvantageType.Advantage + } + } + } + } + }, + { + "2d8 with disadvantage", + new DiceParserTestDto + { + Input = "-2d8", + Expected = new DiceInput() + { + Dice = new List + { + new SingleDie(_randomNumberGenerator) + { + Amount = 2, + Sides = 8, + AdvantageType = DieAdvantageType.Disadvantage + } + } + } + } + }, + { + "multiple dice", + new DiceParserTestDto + { + Input = "2d8 2d6", + Expected = new DiceInput() + { + Dice = new List + { + new SingleDie(_randomNumberGenerator) + { + Amount = 2, + Sides = 8 + }, + new SingleDie(_randomNumberGenerator) + { + Amount = 2, + Sides = 6 + } + } + } + } + }, + { + "with skill modifier, no dice", + new DiceParserTestDto + { + Input = "+2", + Expected = new DiceInput() + { + Dice = new List + { + new SingleDie(_randomNumberGenerator) + { + Amount = 1, + Sides = 20 + } + }, + SkillModifier = 2 + } + } + }, + { + "8d6 with total", + new DiceParserTestDto + { + Input = "8d6 total", + Expected = new DiceInput() + { + Dice = new List + { + new SingleDie(_randomNumberGenerator) + { + Amount = 8, + Sides = 6 + } + }, + Options = new DiceInputOptions + { + ShowTotal = true + } + } + } + }, + { + "All posibilities", + new DiceParserTestDto + { + Input = "2d20 +1d20 -1d20 +1 total", + Expected = new DiceInput() + { + Dice = new List + { + new SingleDie(_randomNumberGenerator) + { + Amount = 2, + Sides = 20 + }, + new SingleDie(_randomNumberGenerator) + { + Amount = 1, + Sides = 20, + AdvantageType = DieAdvantageType.Advantage + }, + new SingleDie(_randomNumberGenerator) + { + Amount = 1, + Sides = 20, + AdvantageType = DieAdvantageType.Disadvantage + }, + }, + Options = new DiceInputOptions + { + ShowTotal = true + }, + SkillModifier = 1 + } + } + }, + }; + + [Theory, MemberData(nameof(DiceParserTestData))] + public void DiceParserTestFunc(string testName, DiceParserTestDto testData) + { + var parser = new Geekbot.net.Lib.DiceParser.DiceParser(_randomNumberGenerator); + var result = parser.Parse(testData.Input); + + Assert.Equal(JsonSerializer.Serialize(result), JsonSerializer.Serialize(testData.Expected)); + } + } +} \ No newline at end of file diff --git a/Tests/Lib/DiceParser/SingleDie.test.cs b/Tests/Lib/DiceParser/SingleDie.test.cs new file mode 100644 index 0000000..2309f98 --- /dev/null +++ b/Tests/Lib/DiceParser/SingleDie.test.cs @@ -0,0 +1,125 @@ +using Geekbot.net.Lib.DiceParser; +using Geekbot.net.Lib.RandomNumberGenerator; +using Xunit; + +namespace Tests.Lib.DiceParser +{ + public class SingleDieTest + { + public struct SingleDieNameTestDto + { + public DieAdvantageType AdvantageType { get; set; } + public string Expected { get; set; } + } + + public static TestData SingleDieNameTestData => new TestData + { + { + "No advantage", + new SingleDieNameTestDto() + { + AdvantageType = DieAdvantageType.None, + Expected = "1d20" + } + }, + { + "With advantage", + new SingleDieNameTestDto() + { + AdvantageType = DieAdvantageType.Advantage, + Expected = "1d20 (with advantage)" + } + }, + { + "With disadvantage", + new SingleDieNameTestDto() + { + AdvantageType = DieAdvantageType.Disadvantage, + Expected = "1d20 (with disadvantage)" + } + } + }; + + [Theory, MemberData(nameof(SingleDieNameTestData))] + public void SingleDieNameTestFunc(string testName, SingleDieNameTestDto testData) + { + var die = new SingleDie(new RandomNumberGenerator()) {AdvantageType = testData.AdvantageType}; + Assert.Equal(die.DiceName, testData.Expected); + } + + public struct SingleDieValidationTestDto + { + public int Sides { get; set; } + public int Amount { get; set; } + public bool PassValidation { get; set; } + } + + public static TestData SingleDieValidationTestData => new TestData + { + { + "To many sides", + new SingleDieValidationTestDto() + { + Amount = 1, + Sides = 200, + PassValidation = false + } + }, + { + "To few sides", + new SingleDieValidationTestDto() + { + Amount = 1, + Sides = 1, + PassValidation = false + } + }, + { + "To many Dice", + new SingleDieValidationTestDto() + { + Amount = 200, + Sides = 20, + PassValidation = false + } + }, + { + "To few Dice", + new SingleDieValidationTestDto() + { + Amount = 0, + Sides = 20, + PassValidation = false + } + }, + { + "Correct Dice", + new SingleDieValidationTestDto() + { + Amount = 1, + Sides = 20, + PassValidation = true + } + } + }; + + [Theory, MemberData(nameof(SingleDieValidationTestData))] + public void SingleDieValidationTestFunc(string testName, SingleDieValidationTestDto testData) + { + var die = new SingleDie(new RandomNumberGenerator()) + { + Amount = testData.Amount, + Sides = testData.Sides + }; + + if (testData.PassValidation) + { + die.ValidateDie(); + } + else + { + Assert.Throws(() => die.ValidateDie()); + } + } + } +} \ No newline at end of file From cc227747295afb9eae1b1fd365d0d959b779c50d Mon Sep 17 00:00:00 2001 From: runebaas Date: Sun, 21 Jun 2020 21:12:34 +0200 Subject: [PATCH 354/553] Make sure a die can actually land on its highest number --- Geekbot.net/Lib/DiceParser/SingleDie.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Geekbot.net/Lib/DiceParser/SingleDie.cs b/Geekbot.net/Lib/DiceParser/SingleDie.cs index 24280d1..582fe29 100644 --- a/Geekbot.net/Lib/DiceParser/SingleDie.cs +++ b/Geekbot.net/Lib/DiceParser/SingleDie.cs @@ -32,7 +32,7 @@ namespace Geekbot.net.Lib.DiceParser { var result = new DieResult { - Roll1 = _random.Next(1, Sides), + Roll1 = _random.Next(1, Sides + 1), AdvantageType = AdvantageType }; From 580a514ce5c648a72c3d4deda0eec8cf07c026b3 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 25 Jun 2020 15:12:41 +0200 Subject: [PATCH 355/553] Rework the media provider --- .../Commands/Randomness/RandomAnimals.cs | 24 ++-- Geekbot.net/Lib/Media/IMediaProvider.cs | 9 +- Geekbot.net/Lib/Media/MediaProvider.cs | 135 +++++------------- Geekbot.net/Lib/Media/MediaType.cs | 14 ++ Geekbot.net/Program.cs | 2 +- Geekbot.net/Storage/{pinguins => penguins} | 24 ++-- 6 files changed, 72 insertions(+), 136 deletions(-) create mode 100644 Geekbot.net/Lib/Media/MediaType.cs rename Geekbot.net/Storage/{pinguins => penguins} (99%) diff --git a/Geekbot.net/Commands/Randomness/RandomAnimals.cs b/Geekbot.net/Commands/Randomness/RandomAnimals.cs index 8562908..47b6ea6 100644 --- a/Geekbot.net/Commands/Randomness/RandomAnimals.cs +++ b/Geekbot.net/Commands/Randomness/RandomAnimals.cs @@ -18,7 +18,7 @@ namespace Geekbot.net.Commands.Randomness [Summary("Get a random panda image")] public async Task Panda() { - await ReplyAsync("", false, Eb(_mediaProvider.GetPanda())); + await ReplyAsync("", false, Eb(_mediaProvider.GetMedia(MediaType.Panda))); } [Command("croissant", RunMode = RunMode.Async)] @@ -26,50 +26,50 @@ namespace Geekbot.net.Commands.Randomness [Summary("Get a random croissant image")] public async Task Croissant() { - await ReplyAsync("", false, Eb(_mediaProvider.GetCrossant())); + await ReplyAsync("", false, Eb(_mediaProvider.GetMedia(MediaType.Croissant))); } [Command("pumpkin", RunMode = RunMode.Async)] [Summary("Get a random pumpkin image")] public async Task Pumpkin() { - await ReplyAsync("", false, Eb(_mediaProvider.GetPumpkin())); + await ReplyAsync("", false, Eb(_mediaProvider.GetMedia(MediaType.Pumpkin))); } [Command("squirrel", RunMode = RunMode.Async)] [Summary("Get a random squirrel image")] public async Task Squirrel() { - await ReplyAsync("", false, Eb(_mediaProvider.GetSquirrel())); + await ReplyAsync("", false, Eb(_mediaProvider.GetMedia(MediaType.Squirrel))); } [Command("turtle", RunMode = RunMode.Async)] [Summary("Get a random turtle image")] public async Task Turtle() { - await ReplyAsync("", false, Eb(_mediaProvider.GetTurtle())); + await ReplyAsync("", false, Eb(_mediaProvider.GetMedia(MediaType.Turtle))); } - [Command("pinguin", RunMode = RunMode.Async)] - [Alias("pingu")] - [Summary("Get a random pinguin image")] - public async Task Pinguin() + [Command("penguin", RunMode = RunMode.Async)] + [Alias("pengu")] + [Summary("Get a random penguin image")] + public async Task Penguin() { - await ReplyAsync("", false, Eb(_mediaProvider.GetPinguin())); + await ReplyAsync("", false, Eb(_mediaProvider.GetMedia(MediaType.Penguin))); } [Command("fox", RunMode = RunMode.Async)] [Summary("Get a random fox image")] public async Task Fox() { - await ReplyAsync("", false, Eb(_mediaProvider.GetFox())); + await ReplyAsync("", false, Eb(_mediaProvider.GetMedia(MediaType.Fox))); } [Command("dab", RunMode = RunMode.Async)] [Summary("Get a random dab image")] public async Task Dab() { - await ReplyAsync("", false, Eb(_mediaProvider.GetDab())); + await ReplyAsync("", false, Eb(_mediaProvider.GetMedia(MediaType.Dab))); } private static Embed Eb(string image) diff --git a/Geekbot.net/Lib/Media/IMediaProvider.cs b/Geekbot.net/Lib/Media/IMediaProvider.cs index 33a0d7c..63c0f41 100644 --- a/Geekbot.net/Lib/Media/IMediaProvider.cs +++ b/Geekbot.net/Lib/Media/IMediaProvider.cs @@ -2,13 +2,6 @@ { public interface IMediaProvider { - string GetPanda(); - string GetCrossant(); - string GetSquirrel(); - string GetPumpkin(); - string GetTurtle(); - string GetPinguin(); - string GetFox(); - string GetDab(); + string GetMedia(MediaType type); } } \ No newline at end of file diff --git a/Geekbot.net/Lib/Media/MediaProvider.cs b/Geekbot.net/Lib/Media/MediaProvider.cs index f7ea9df..45524de 100644 --- a/Geekbot.net/Lib/Media/MediaProvider.cs +++ b/Geekbot.net/Lib/Media/MediaProvider.cs @@ -1,133 +1,62 @@ using System; using System.IO; using Geekbot.net.Lib.Logger; +using Geekbot.net.Lib.RandomNumberGenerator; namespace Geekbot.net.Lib.Media { public class MediaProvider : IMediaProvider { - private readonly Random _random; + private readonly IRandomNumberGenerator _random; private readonly IGeekbotLogger _logger; private string[] _pandaImages; private string[] _croissantImages; private string[] _squirrelImages; private string[] _pumpkinImages; private string[] _turtlesImages; - private string[] _pinguinImages; + private string[] _penguinImages; private string[] _foxImages; private string[] _dabImages; - public MediaProvider(IGeekbotLogger logger) + public MediaProvider(IGeekbotLogger logger, IRandomNumberGenerator random) { - _random = new Random(); + _random = random; _logger = logger; logger.Information(LogSource.Geekbot, "Loading Media Files"); ; - LoadPandas(); - BakeCroissants(); - LoadSquirrels(); - LoadPumpkins(); - LoadTurtles(); - LoadPinguins(); - LoadFoxes(); - LoadDab(); - } - - private void LoadPandas() - { - var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/pandas")); - _pandaImages = rawLinks.Split("\n"); - _logger.Trace(LogSource.Geekbot, $"Loaded {_pandaImages.Length} Panda Images"); - } - - private void BakeCroissants() - { - var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/croissant")); - _croissantImages = rawLinks.Split("\n"); - _logger.Trace(LogSource.Geekbot, $"Loaded {_croissantImages.Length} Croissant Images"); - } - - private void LoadSquirrels() - { - var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/squirrel")); - _squirrelImages = rawLinks.Split("\n"); - _logger.Trace(LogSource.Geekbot, $"Loaded {_squirrelImages.Length} Squirrel Images"); - } - - private void LoadPumpkins() - { - var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/pumpkin")); - _pumpkinImages = rawLinks.Split("\n"); - _logger.Trace(LogSource.Geekbot, $"Loaded {_pumpkinImages.Length} Pumpkin Images"); - } - - private void LoadTurtles() - { - var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/turtles")); - _turtlesImages = rawLinks.Split("\n"); - _logger.Trace(LogSource.Geekbot, $"Loaded {_turtlesImages.Length} Turtle Images"); - } - - private void LoadPinguins() - { - var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/pinguins")); - _pinguinImages = rawLinks.Split("\n"); - _logger.Trace(LogSource.Geekbot, $"Loaded {_pinguinImages.Length} Pinguin Images"); - } - - private void LoadFoxes() - { - var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/foxes")); - _foxImages = rawLinks.Split("\n"); - _logger.Trace(LogSource.Geekbot, $"Loaded {_foxImages.Length} Foxes Images"); - } - - private void LoadDab() - { - var rawLinks = File.ReadAllText(Path.GetFullPath("./Storage/dab")); - _dabImages = rawLinks.Split("\n"); - _logger.Trace(LogSource.Geekbot, $"Loaded {_dabImages.Length} Dab Images"); + LoadMedia("./Storage/pandas", ref _pandaImages); + LoadMedia("./Storage/croissant", ref _croissantImages); + LoadMedia("./Storage/squirrel", ref _squirrelImages); + LoadMedia("./Storage/pumpkin", ref _pumpkinImages); + LoadMedia("./Storage/turtles", ref _turtlesImages); + LoadMedia("./Storage/penguins", ref _penguinImages); + LoadMedia("./Storage/foxes", ref _foxImages); + LoadMedia("./Storage/dab", ref _dabImages); } - public string GetPanda() + private void LoadMedia(string path, ref string[] storage) { - return _pandaImages[_random.Next(0, _pandaImages.Length)]; + var rawLinks = File.ReadAllText(Path.GetFullPath(path)); + storage = rawLinks.Split("\n"); + _logger.Trace(LogSource.Geekbot, $"Loaded {storage.Length} Images from ${path}"); } - - public string GetCrossant() + + public string GetMedia(MediaType type) { - return _croissantImages[_random.Next(0, _croissantImages.Length)]; - } - - public string GetSquirrel() - { - return _squirrelImages[_random.Next(0, _squirrelImages.Length)]; - } - - public string GetPumpkin() - { - return _pumpkinImages[_random.Next(0, _pumpkinImages.Length)]; - } - - public string GetTurtle() - { - return _turtlesImages[_random.Next(0, _turtlesImages.Length)]; - } - - public string GetPinguin() - { - return _pinguinImages[_random.Next(0, _pinguinImages.Length)]; - } - - public string GetFox() - { - return _foxImages[_random.Next(0, _foxImages.Length)]; - } - - public string GetDab() - { - return _dabImages[_random.Next(0, _dabImages.Length)]; + var collection = type switch + { + MediaType.Panda => _pandaImages, + MediaType.Croissant => _croissantImages, + MediaType.Squirrel => _squirrelImages, + MediaType.Pumpkin => _pumpkinImages, + MediaType.Turtle => _turtlesImages, + MediaType.Penguin => _penguinImages, + MediaType.Fox => _foxImages, + MediaType.Dab => _dabImages + }; + + return collection[_random.Next(0, collection.Length)]; } } } \ No newline at end of file diff --git a/Geekbot.net/Lib/Media/MediaType.cs b/Geekbot.net/Lib/Media/MediaType.cs new file mode 100644 index 0000000..aee317b --- /dev/null +++ b/Geekbot.net/Lib/Media/MediaType.cs @@ -0,0 +1,14 @@ +namespace Geekbot.net.Lib.Media +{ + public enum MediaType + { + Panda, + Croissant, + Squirrel, + Pumpkin, + Turtle, + Penguin, + Fox, + Dab + } +} \ No newline at end of file diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 3d98ad9..c96e2f5 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -160,13 +160,13 @@ namespace Geekbot.net _reactionListener = new ReactionListener(_databaseInitializer.Initialize()); _guildSettingsManager = new GuildSettingsManager(_databaseInitializer.Initialize()); var fortunes = new FortunesProvider(_logger); - var mediaProvider = new MediaProvider(_logger); var malClient = new MalClient(_globalSettings, _logger); var levelCalc = new LevelCalc(); var emojiConverter = new EmojiConverter(); var mtgManaConverter = new MtgManaConverter(); var wikipediaClient = new WikipediaClient(); var randomNumberGenerator = new RandomNumberGenerator(); + var mediaProvider = new MediaProvider(_logger, randomNumberGenerator); var kvMemoryStore = new KvInInMemoryStore(); var translationHandler = new TranslationHandler(_logger, _guildSettingsManager); var errorHandler = new ErrorHandler(_logger, translationHandler, _runParameters); diff --git a/Geekbot.net/Storage/pinguins b/Geekbot.net/Storage/penguins similarity index 99% rename from Geekbot.net/Storage/pinguins rename to Geekbot.net/Storage/penguins index 631f9d0..d38d853 100644 --- a/Geekbot.net/Storage/pinguins +++ b/Geekbot.net/Storage/penguins @@ -1,13 +1,13 @@ -https://i.ytimg.com/vi/Qr6sULJnu2o/maxresdefault.jpg -https://www.apex-expeditions.com/wp-content/uploads/2015/08/newzealandSlider_Macquarie_ElephantSealKingPenguins_GRiehle_1366x601.jpg -https://www.birdlife.org/sites/default/files/styles/1600/public/slide.jpg?itok=HRhQfA1S -http://experimentexchange.com/wp-content/uploads/2016/07/penguins-fact.jpg -http://images.mentalfloss.com/sites/default/files/styles/mf_image_16x9/public/istock-511366776.jpg?itok=cWhdWNZ8&resize=1100x619 -https://www.thevaporplace.ch/media/catalog/product/cache/1/thumbnail/800x800/9df78eab33525d08d6e5fb8d27136e95/a/t/atopack_penguin-15.jpg -https://www.superfastbusiness.com/wp-content/uploads/2015/10/real-time-penguin-algorithm-featured.jpg -http://www.antarctica.gov.au/__data/assets/image/0011/147737/varieties/antarctic.jpg -https://vignette.wikia.nocookie.net/robloxcreepypasta/images/1/11/AAEAAQAAAAAAAAdkAAAAJDc3YzkyYjJhLTYyZjctNDY2Mi04M2VjLTg4NjY4ZjgwYzRmNg.png/revision/latest?cb=20180207200526 -https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3xV0lhpZuhT8Nmm6LaITsppZ7VfWcWXuyu2cPHrlv_dt_M92K5g -http://goboiano.com/wp-content/uploads/2017/04/Penguin-Kemeno-Friends-Waifu.jpg -https://cdn.yoast.com/app/uploads/2015/10/Penguins_1200x628.png +https://i.ytimg.com/vi/Qr6sULJnu2o/maxresdefault.jpg +https://www.apex-expeditions.com/wp-content/uploads/2015/08/newzealandSlider_Macquarie_ElephantSealKingPenguins_GRiehle_1366x601.jpg +https://www.birdlife.org/sites/default/files/styles/1600/public/slide.jpg?itok=HRhQfA1S +http://experimentexchange.com/wp-content/uploads/2016/07/penguins-fact.jpg +http://images.mentalfloss.com/sites/default/files/styles/mf_image_16x9/public/istock-511366776.jpg?itok=cWhdWNZ8&resize=1100x619 +https://www.thevaporplace.ch/media/catalog/product/cache/1/thumbnail/800x800/9df78eab33525d08d6e5fb8d27136e95/a/t/atopack_penguin-15.jpg +https://www.superfastbusiness.com/wp-content/uploads/2015/10/real-time-penguin-algorithm-featured.jpg +http://www.antarctica.gov.au/__data/assets/image/0011/147737/varieties/antarctic.jpg +https://vignette.wikia.nocookie.net/robloxcreepypasta/images/1/11/AAEAAQAAAAAAAAdkAAAAJDc3YzkyYjJhLTYyZjctNDY2Mi04M2VjLTg4NjY4ZjgwYzRmNg.png/revision/latest?cb=20180207200526 +https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3xV0lhpZuhT8Nmm6LaITsppZ7VfWcWXuyu2cPHrlv_dt_M92K5g +http://goboiano.com/wp-content/uploads/2017/04/Penguin-Kemeno-Friends-Waifu.jpg +https://cdn.yoast.com/app/uploads/2015/10/Penguins_1200x628.png https://images.justwatch.com/backdrop/8611153/s1440/pingu \ No newline at end of file From c94d73736d6bf5a70273cd2ed020bcc106da9123 Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 30 Jun 2020 17:54:01 +0200 Subject: [PATCH 356/553] Use greetings.dev instead of hardcoded greetings --- .../Randomness/Greetings/GreetingBaseDto.cs | 11 + .../Randomness/Greetings/GreetingDto.cs | 8 +- .../Randomness/Greetings/GreetingProvider.cs | 1595 ----------------- .../Randomness/Greetings/Greetings.cs | 28 +- 4 files changed, 37 insertions(+), 1605 deletions(-) create mode 100644 Geekbot.net/Commands/Randomness/Greetings/GreetingBaseDto.cs delete mode 100644 Geekbot.net/Commands/Randomness/Greetings/GreetingProvider.cs diff --git a/Geekbot.net/Commands/Randomness/Greetings/GreetingBaseDto.cs b/Geekbot.net/Commands/Randomness/Greetings/GreetingBaseDto.cs new file mode 100644 index 0000000..7f4e02f --- /dev/null +++ b/Geekbot.net/Commands/Randomness/Greetings/GreetingBaseDto.cs @@ -0,0 +1,11 @@ +namespace Geekbot.net.Commands.Randomness.Greetings +{ + public class GreetingBaseDto + { + public string Language { get; set; } + public string LanguageNative { get; set; } + public string LanguageCode { get; set; } + public string Script { get; set; } + public GreetingDto Primary { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Randomness/Greetings/GreetingDto.cs b/Geekbot.net/Commands/Randomness/Greetings/GreetingDto.cs index 42792a5..c967885 100644 --- a/Geekbot.net/Commands/Randomness/Greetings/GreetingDto.cs +++ b/Geekbot.net/Commands/Randomness/Greetings/GreetingDto.cs @@ -2,9 +2,9 @@ namespace Geekbot.net.Commands.Randomness.Greetings { public class GreetingDto { - public string Text { get; set; } - public string Language { get; set; } - public string Dialect { get; set; } = null; - public string Romanization { get; set; } = null; + public string Text { get; set; } + public string Dialect { get; set; } + public string Romanization { get; set; } + public string[] Use { get; set; } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Randomness/Greetings/GreetingProvider.cs b/Geekbot.net/Commands/Randomness/Greetings/GreetingProvider.cs deleted file mode 100644 index a15f32e..0000000 --- a/Geekbot.net/Commands/Randomness/Greetings/GreetingProvider.cs +++ /dev/null @@ -1,1595 +0,0 @@ -using System.Collections.Generic; - -namespace Geekbot.net.Commands.Randomness.Greetings -{ - public class GreetingProvider - { - public static readonly List Greetings = new List - { - new GreetingDto() - { - Text = "Бзиа збаша", - Language = "Abkhaz", - Romanization = "Bzia zbaşa" - }, - new GreetingDto() - { - Text = "Фэсапщы", - Language = "Adyghe", - Romanization = "Fèsapŝy" - }, - new GreetingDto() - { - Text = "Haai", - Language = "Afrikaans" - }, - new GreetingDto() - { - Text = "Kamusta", - Language = "Aklan" - }, - new GreetingDto() - { - Text = "Fâla", - Language = "Albanian" - }, - new GreetingDto() - { - Text = "Ç'kemi", - Language = "Albanian" - }, - new GreetingDto() - { - Text = "Aang", - Language = "Aleut" - }, - new GreetingDto() - { - Text = "Hallo", - Language = "Alsatian" - }, - new GreetingDto() - { - Text = "Эзендер", - Language = "Altay", - Romanization = "Ezender" - }, - new GreetingDto() - { - Text = "ሰላም።", - Language = "Amharic", - Romanization = "sälam" - }, - new GreetingDto() - { - Text = "السلام عليكم", - Language = "Arabic", - Romanization = "as-salām 'alaykum" - }, - new GreetingDto() - { - Text = "Ola", - Language = "Aragonese" - }, - new GreetingDto() - { - Text = "Shl'am lak", - Language = "Aramaic" - }, - new GreetingDto() - { - Text = "Héébee", - Language = "Arapaho" - }, - new GreetingDto() - { - Text = "Բարեւ", - Language = "Armenian", - Romanization = "Parev" - }, - new GreetingDto() - { - Text = "Bunâ dzuâ", - Language = "Aromanian" - }, - new GreetingDto() - { - Text = "Werte", - Language = "Arrernte" - }, - new GreetingDto() - { - Text = "নমস্কাৰ", - Language = "Assamese", - Romanization = "নমস্কাৰ" - }, - new GreetingDto() - { - Text = "Hola", - Language = "Asturian" - }, - new GreetingDto() - { - Text = "Kwei", - Language = "Atikamekw" - }, - new GreetingDto() - { - Text = "Laphi!", - Language = "Aymara" - }, - new GreetingDto() - { - Text = "Salam", - Language = "Azerbaijani" - }, - new GreetingDto() - { - Text = "Swastyastu", - Language = "Balinese" - }, - new GreetingDto() - { - Text = "I ni ce", - Language = "Bambara" - }, - new GreetingDto() - { - Text = "Haku'", - Language = "Barbareño" - }, - new GreetingDto() - { - Text = "сәләм", - Language = "Bashkir", - Romanization = "sәlәm" - }, - new GreetingDto() - { - Text = "Kaixo", - Language = "Basque" - }, - new GreetingDto() - { - Text = "Horas", - Language = "Batak" - }, - new GreetingDto() - { - Text = "მარშიხ ვალ", - Language = "Batsbi", - Romanization = "Maršix val" - }, - new GreetingDto() - { - Text = "Seavus", - Language = "Bavarian" - }, - new GreetingDto() - { - Text = "Вітаю", - Language = "Belarusian", - Romanization = "Vіtaju" - }, - new GreetingDto() - { - Text = "Shani", - Language = "Bemba" - }, - new GreetingDto() - { - Text = "নমস্কার", - Language = "Bengali", - Romanization = "Nômôskar", - Dialect = "Hindus" - }, - new GreetingDto() - { - Text = "আসসালামু আলাইকুম", - Language = "Bengali", - Romanization = "Asôlamu alaikum", - Dialect = "Muslims" - }, - new GreetingDto() - { - Text = "प्रणाम", - Language = "Bhojpuri", - Romanization = "prannam" - }, - new GreetingDto() - { - Text = "Hello", - Language = "Bikol" - }, - new GreetingDto() - { - Text = "Halo", - Language = "Bislama" - }, - new GreetingDto() - { - Text = "Dobar dan", - Language = "Bosnian" - }, - new GreetingDto() - { - Text = "Salud", - Language = "Breton" - }, - new GreetingDto() - { - Text = "Здравейте", - Language = "Bulgarian" - }, - new GreetingDto() - { - Text = "မဂႆလာပၝ", - Language = "Burmese", - Romanization = "min-ga-la-ba" - }, - new GreetingDto() - { - Text = "Olá", - Language = "Cape Verdean Creole" - }, - new GreetingDto() - { - Text = "Hola", - Language = "Catalan" - }, - new GreetingDto() - { - Text = "Hello", - Language = "Cebuano" - }, - new GreetingDto() - { - Text = "Kopisanangan", - Language = "Central Dusun" - }, - new GreetingDto() - { - Text = "Que tal?", - Language = "Chabacano de Zamboanga" - }, - new GreetingDto() - { - Text = "Ola", - Language = "Chabacano de Cavite" - }, - new GreetingDto() - { - Text = "Håfa ådai", - Language = "Chamorro", - Dialect = "Guam" - }, - new GreetingDto() - { - Text = "Hafa Adai", - Language = "Chamorro", - Dialect = "North Marianas" - }, - new GreetingDto() - { - Text = "Салам", - Language = "Chechen", - Romanization = "Salam" - }, - new GreetingDto() - { - Text = "ᎣᏏᏲ", - Language = "Cherokee", - Romanization = "Osiyo" - }, - new GreetingDto() - { - Text = "Moni", - Language = "Chichewa" - }, - new GreetingDto() - { - Text = "你好", - Language = "Chinese", - Romanization = "nǐ hǎo", - Dialect = "Mandarin" - }, - new GreetingDto() - { - Text = "ʔédlánet’é", - Language = "Chipewyan" - }, - new GreetingDto() - { - Text = "Halito", - Language = "Choctaw" - }, - new GreetingDto() - { - Text = "Ran annim", - Language = "Chuukese" - }, - new GreetingDto() - { - Text = "Салам!", - Language = "Chuvash", - Romanization = "Salam!" - }, - new GreetingDto() - { - Text = "Guuten takh!", - Language = "Cimbrian" - }, - new GreetingDto() - { - Text = "Kopivosian", - Language = "Coastal Kadazan" - }, - new GreetingDto() - { - Text = "Marʉ́awe", - Language = "Comanche" - }, - new GreetingDto() - { - Text = "Dydh da", - Language = "Cornish" - }, - new GreetingDto() - { - Text = "Salute", - Language = "Corsican" - }, - new GreetingDto() - { - Text = "ᑕᓂᓯ", - Language = "Cree", - Romanization = "Tanisi" - }, - new GreetingDto() - { - Text = "Bok", - Language = "Croatian" - }, - new GreetingDto() - { - Text = "Sho'daache", - Language = "Crow" - }, - new GreetingDto() - { - Text = "Míyaxwe", - Language = "Cupeño" - }, - new GreetingDto() - { - Text = "Hello", - Language = "Cuyonon" - }, - new GreetingDto() - { - Text = "Ahoj", - Language = "Czech" - }, - new GreetingDto() - { - Text = "Hej", - Language = "Danish" - }, - new GreetingDto() - { - Text = "ااسال م عليكم", - Language = "Dari", - Romanization = "As-salâmo 'alaykom" - }, - new GreetingDto() - { - Text = "Misawa", - Language = "Dholuo" - }, - new GreetingDto() - { - Text = "Goededag", - Language = "Dutch" - }, - new GreetingDto() - { - Text = "སྐུ་གཟུགས་བཟང་པོ་ལགས།", - Language = "Dzongkha", - Romanization = "Kuzu zangpo la" - }, - new GreetingDto() - { - Text = "Mọkọm", - Language = "Efik" - }, - new GreetingDto() - { - Text = "Häj ą̊ dig!", - Language = "Elfdalian" - }, - new GreetingDto() - { - Text = "Hello", - Language = "English" - }, - new GreetingDto() - { - Text = "Tere", - Language = "Estonian" - }, - new GreetingDto() - { - Text = "Ola!", - Language = "Extremaduran" - }, - new GreetingDto() - { - Text = "Hallo", - Language = "Faroese" - }, - new GreetingDto() - { - Text = "Bula", - Language = "Fijian" - }, - new GreetingDto() - { - Text = "Hyvää päivää", - Language = "Finnish" - }, - new GreetingDto() - { - Text = "Bonjour", - Language = "French" - }, - new GreetingDto() - { - Text = "Guundach", - Language = "Frisian", - Dialect = "North Frisian" - }, - new GreetingDto() - { - Text = "Gouden Dai", - Language = "Frisian", - Dialect = "Saterland" - }, - new GreetingDto() - { - Text = "Goeie", - Language = "Frisian", - Dialect = "West Frisian" - }, - new GreetingDto() - { - Text = "Mandi", - Language = "Friulian" - }, - new GreetingDto() - { - Text = "Ola", - Language = "Galician" - }, - new GreetingDto() - { - Text = "सिवासौँळी", - Language = "Garhwali", - Romanization = "sivāsauṁḻī" - }, - new GreetingDto() - { - Text = "Buiti binafi", - Language = "Garifuna" - }, - new GreetingDto() - { - Text = "გამარჯობა", - Language = "Georgian", - Romanization = "gamarjoba" - }, - new GreetingDto() - { - Text = "Guten Tag", - Language = "German" - }, - new GreetingDto() - { - Text = "Χαῖρε", - Language = "Greek", - Romanization = "Khaĩre", - Dialect = "Ancient" - }, - new GreetingDto() - { - Text = "Γειά", - Language = "Greek", - Romanization = "Geiá", - Dialect = "Ancient" - }, - new GreetingDto() - { - Text = "Aluu", - Language = "Greenlandic" - }, - new GreetingDto() - { - Text = "નમસ્તે", - Language = "Gujarati", - Romanization = "namaste" - }, - new GreetingDto() - { - Text = "Bonjou", - Language = "Haitian Creole" - }, - new GreetingDto() - { - Text = "Sannu", - Language = "Hausa" - }, - new GreetingDto() - { - Text = "Aloha", - Language = "Hawaiian" - }, - new GreetingDto() - { - Text = "שלום", - Language = "Hebrew", - Romanization = "Shalom" - }, - new GreetingDto() - { - Text = "something", - Language = "something" - }, - new GreetingDto() - { - Text = "Tjike", - Language = "Herero" - }, - new GreetingDto() - { - Text = "Mono", - Language = "Himba" - }, - new GreetingDto() - { - Text = "नमस्ते", - Language = "Hindi", - Romanization = "namaste" - }, - new GreetingDto() - { - Text = "Nyob zoo", - Language = "Hmong", - Dialect = "White" - }, - new GreetingDto() - { - Text = "Jó napot kívánok", - Language = "Hungarian" - }, - new GreetingDto() - { - Text = "Góðan dag", - Language = "Icelandic" - }, - new GreetingDto() - { - Text = "Ndeewo", - Language = "Igbo" - }, - new GreetingDto() - { - Text = "Kablaaw", - Language = "Iloko" - }, - new GreetingDto() - { - Text = "Tiervâ", - Language = "Inari Saami" - }, - new GreetingDto() - { - Text = "Hi", - Language = "Indonesian" - }, - new GreetingDto() - { - Text = "ᐊᐃ", - Language = "Inuktitut", - Romanization = "Ai" - }, - new GreetingDto() - { - Text = "Haluu", - Language = "Iñupiaq" - }, - new GreetingDto() - { - Text = "Dia dhuit", - Language = "Irish" - }, - new GreetingDto() - { - Text = "Ciao", - Language = "Italian" - }, - new GreetingDto() - { - Text = "Míyaxwen", - Language = "Ivilyuat" - }, - new GreetingDto() - { - Text = "Ello", - Language = "Jamaican" - }, - new GreetingDto() - { - Text = "今日は", - Language = "Japanese", - Romanization = "konnichiwa" - }, - new GreetingDto() - { - Text = "ꦲꦭꦺꦴ", - Language = "Javanese", - Romanization = "Halo" - }, - new GreetingDto() - { - Text = "Puiznu", - Language = "Jenesch" - }, - new GreetingDto() - { - Text = "Salut", - Language = "Jèrriais" - }, - new GreetingDto() - { - Text = "Godaw", - Language = "Jutish" - }, - new GreetingDto() - { - Text = "Мендвт", - Language = "Kalmyk" - }, - new GreetingDto() - { - Text = "Tọi", - Language = "Kam" - }, - new GreetingDto() - { - Text = "ನಮಸ್ತೆ", - Language = "Kannada", - Romanization = "namaste" - }, - new GreetingDto() - { - Text = "Xsaqär", - Language = "Kaqchikel" - }, - new GreetingDto() - { - Text = "Ayukîi", - Language = "Karuk" - }, - new GreetingDto() - { - Text = "Witéj", - Language = "Kashubian" - }, - new GreetingDto() - { - Text = "असलामु अलैकुम", - Language = "Kashmiri", - Romanization = "asalāmu alaikuma" - }, - new GreetingDto() - { - Text = "Hagare'enaam", - Language = "Kawaiisu" - }, - new GreetingDto() - { - Text = "Сәлем", - Language = "Kazakh", - Romanization = "Sälem" - }, - new GreetingDto() - { - Text = "ជំរាបសួរ", - Language = "Khmer", - Romanization = "chôm rab suôr" - }, - new GreetingDto() - { - Text = "Halau", - Language = "Khoekhoe" - }, - new GreetingDto() - { - Text = "wĩmwega", - Language = "Kikuyu" - }, - new GreetingDto() - { - Text = "Muraho", - Language = "Kinyarwanda" - }, - new GreetingDto() - { - Text = "Ko na mauri", - Language = "Kiribati" - }, - new GreetingDto() - { - Text = "안녕하십니까", - Language = "Korean", - Romanization = "annyeong-hasimnikka" - }, - new GreetingDto() - { - Text = "Haawka", - Language = "Kumeyaay" - }, - new GreetingDto() - { - Text = "!kao", - Language = "Kung San" - }, - new GreetingDto() - { - Text = "Rojbash", - Language = "Kurdish", - Dialect = "Kurmanji" - }, - new GreetingDto() - { - Text = "Sillaw", - Language = "Kurdish", - Dialect = "Sorani" - }, - new GreetingDto() - { - Text = "Салам!", - Language = "Kyrgyz", - Romanization = "Salam!" - }, - new GreetingDto() - { - Text = "בוינוס דייאס", - Language = "Ladino", - Romanization = "Buenos diyas" - }, - new GreetingDto() - { - Text = "Hau", - Language = "Lakota Sioux" - }, - new GreetingDto() - { - Text = "ສະບາຍດີ", - Language = "Lao", - Romanization = "sába̖ai-di̖i" - }, - new GreetingDto() - { - Text = "Ave", - Language = "Latin" - }, - new GreetingDto() - { - Text = "Sveiki", - Language = "Latvian" - }, - new GreetingDto() - { - Text = "გეგაჯგინას", - Language = "Laz", - Romanization = "Gegacginas" - }, - new GreetingDto() - { - Text = "Салам алейкум", - Language = "Lezgi", - Romanization = "Salam alejkum" - }, - new GreetingDto() - { - Text = "Hallo", - Language = "Limburgish" - }, - new GreetingDto() - { - Text = "Mbote", - Language = "Lingala" - }, - new GreetingDto() - { - Text = "Labas", - Language = "Lithuanian" - }, - new GreetingDto() - { - Text = "Moin", - Language = "Low Saxon" - }, - new GreetingDto() - { - Text = "Lumela", - Language = "Lozi" - }, - new GreetingDto() - { - Text = "Gyebale ko", - Language = "Luganda" - }, - new GreetingDto() - { - Text = "Buoris", - Language = "Lule Sámi" - }, - new GreetingDto() - { - Text = "Mííyu", - Language = "Luiseño" - }, - new GreetingDto() - { - Text = "Moien", - Language = "Luxembourgish" - }, - new GreetingDto() - { - Text = "Здраво", - Language = "Macedonian", - Romanization = "Zdravo" - }, - new GreetingDto() - { - Text = "परनाम", - Language = "Magahi", - Romanization = "Pernaam" - }, - new GreetingDto() - { - Text = "प्रनाम", - Language = "Maithili", - Romanization = "Pranaam" - }, - new GreetingDto() - { - Text = "Manao ahoana", - Language = "Malagasy" - }, - new GreetingDto() - { - Text = "Selamat pagi", - Language = "Malay" - }, - new GreetingDto() - { - Text = "നമസ്തേ", - Language = "Malayalam", - Romanization = "namastē" - }, - new GreetingDto() - { - Text = "Jeeka, ma tzuula", - Language = "Mam" - }, - new GreetingDto() - { - Text = "Moghrey mie", - Language = "Gaelic", - Dialect = "Manx" - }, - new GreetingDto() - { - Text = "Assalaamu Alaikum", - Language = "Maldivian" - }, - new GreetingDto() - { - Text = "Ħello", - Language = "Maltese" - }, - new GreetingDto() - { - Text = "Kia ora", - Language = "Māori" - }, - new GreetingDto() - { - Text = "Mari mari", - Language = "Mapuche" - }, - new GreetingDto() - { - Text = "नमस्कार", - Language = "Marathi", - Romanization = "namaskāra" - }, - new GreetingDto() - { - Text = "Io̧kwe", - Language = "Marshallese" - }, - new GreetingDto() - { - Text = "Bonzur", - Language = "Mauritian Creole" - }, - new GreetingDto() - { - Text = "Gwe’", - Language = "Míkmaq" - }, - new GreetingDto() - { - Text = "ဟာဲ", - Language = "Mon", - Romanization = "hāai" - }, - new GreetingDto() - { - Text = "Ciau", - Language = "Monégasque" - }, - new GreetingDto() - { - Text = "Сайн уу", - Language = "Mongolian", - Romanization = "Sain uu" - }, - new GreetingDto() - { - Text = "Manahúú", - Language = "Mono" - }, - new GreetingDto() - { - Text = "Ne y windiga", - Language = "Mossi" - }, - new GreetingDto() - { - Text = "Niltze", - Language = "Nahuatl" - }, - new GreetingDto() - { - Text = "Ekamowir omo", - Language = "Nauruan" - }, - new GreetingDto() - { - Text = "Yá'át'ééh", - Language = "Navajo" - }, - new GreetingDto() - { - Text = "ज्वजलपा", - Language = "Newari", - Romanization = "jvajalapā" - }, - new GreetingDto() - { - Text = "Oraire ota?", - Language = "Nkore" - }, - new GreetingDto() - { - Text = "Salibonani", - Language = "Ndebele" - }, - new GreetingDto() - { - Text = "Lotjhani", - Language = "Southern Ndebele" - }, - new GreetingDto() - { - Text = "नमस्ते", - Language = "Nepali", - Romanization = "namaste" - }, - new GreetingDto() - { - Text = "Fakaalofa atu", - Language = "Niuean" - }, - new GreetingDto() - { - Text = "Салам!", - Language = "Nogai" - }, - new GreetingDto() - { - Text = "Bures", - Language = "Northern Sámi" - }, - new GreetingDto() - { - Text = "Dumêlang", - Language = "Northern Sotho" - }, - new GreetingDto() - { - Text = "Goddag", - Language = "Norwegian" - }, - new GreetingDto() - { - Text = "Hatʸu", - Language = "Northern Chumash" - }, - new GreetingDto() - { - Text = "Bonjorn", - Language = "Occitan" - }, - new GreetingDto() - { - Text = "Aniin", - Language = "Ojibwe" - }, - new GreetingDto() - { - Text = "今日拝なびら", - Language = "Okinawan", - Romanization = "chuu wuganabira" - }, - new GreetingDto() - { - Text = "Wes hāl", - Language = "Old English" - }, - new GreetingDto() - { - Text = "Ƿes hāl", - Language = "Old Prussian" - }, - new GreetingDto() - { - Text = "Ahó", - Language = "Omaha" - }, - new GreetingDto() - { - Text = "ନମସ୍କାର", - Language = "Oriya", - Romanization = "Namascāra" - }, - new GreetingDto() - { - Text = "Alii", - Language = "Palauan" - }, - new GreetingDto() - { - Text = "Bon dia", - Language = "Papiamento" - }, - new GreetingDto() - { - Text = "ښې چارې", - Language = "Pashto", - Romanization = "khe chare" - }, - new GreetingDto() - { - Text = "Gude Daag", - Language = "Pennsylvania Deitsch" - }, - new GreetingDto() - { - Text = "درود", - Language = "Persian", - Romanization = "dorood", - Dialect = "Farsi" - }, - new GreetingDto() - { - Text = "Bojour", - Language = "Picard" - }, - new GreetingDto() - { - Text = "Wai", - Language = "Pitjantjatjara" - }, - new GreetingDto() - { - Text = "Cześć", - Language = "Polish" - }, - new GreetingDto() - { - Text = "Olá", - Language = "Portuguese", - Dialect = "Protugal" - }, - new GreetingDto() - { - Text = "Oi", - Language = "Portuguese", - Dialect = "Brazilian" - }, - new GreetingDto() - { - Text = "ਸਤਿ ਸ੍ਰੀ ਅਕਾਲ।", - Language = "Punjabi", - Romanization = "sat srī akāl" - }, - new GreetingDto() - { - Text = "Rimaykullayki", - Language = "Quechua" - }, - new GreetingDto() - { - Text = "'Iorana", - Language = "Rapa Nui" - }, - new GreetingDto() - { - Text = "Bonzour", - Language = "Réunion Creole" - }, - new GreetingDto() - { - Text = "Sastipe", - Language = "Romani" - }, - new GreetingDto() - { - Text = "Salut", - Language = "Romanian" - }, - new GreetingDto() - { - Text = "Ciao", - Language = "Romansh" - }, - new GreetingDto() - { - Text = "Привет", - Language = "Russian", - Romanization = "Privet" - }, - new GreetingDto() - { - Text = "Слава Исусу Христу", - Language = "Rusyn", - Dialect = "Slava Ysusu Chrystu" - }, - new GreetingDto() - { - Text = "бирибиэт", - Language = "Sakha", - Romanization = "biribiet" - }, - new GreetingDto() - { - Text = "Malō", - Language = "Samoan" - }, - new GreetingDto() - { - Text = "Bara mo", - Language = "Sango" - }, - new GreetingDto() - { - Text = "नमस्ते", - Language = "Sanskrit", - Romanization = "namaste" - }, - new GreetingDto() - { - Text = "Saludi", - Language = "Sardinian", - Dialect = "Campidanese" - }, - new GreetingDto() - { - Text = "Bone die", - Language = "Sardinian", - Dialect = "Logudorese" - }, - new GreetingDto() - { - Text = "Hullo", - Language = "Scots" - }, - new GreetingDto() - { - Text = "Halò", - Language = "Gaelic", - Dialect = "Scottish" - }, - new GreetingDto() - { - Text = "Здраво", - Language = "Serbian", - Dialect = "Zdravo" - }, - new GreetingDto() - { - Text = "Lumela", - Language = "Sesotho" - }, - new GreetingDto() - { - Text = "Mhoro", - Language = "Shona" - }, - new GreetingDto() - { - Text = "Ciau", - Language = "Sicilian" - }, - new GreetingDto() - { - Text = "سَلامُ", - Language = "Sindhi", - Romanization = "Salāmu" - }, - new GreetingDto() - { - Text = "ආයුඛෝවන්", - Language = "Sinhala", - Romanization = "āyubūvan" - }, - new GreetingDto() - { - Text = "Dobry den", - Language = "Slovak" - }, - new GreetingDto() - { - Text = "Pozdravljeni", - Language = "Slovenian" - }, - new GreetingDto() - { - Text = "Simi", - Language = "Solresol" - }, - new GreetingDto() - { - Text = "Salaam alaykum", - Language = "Somali" - }, - new GreetingDto() - { - Text = "Dobry źeń", - Language = "Sorbian", - Dialect = "Lower Sorbian" - }, - new GreetingDto() - { - Text = "Dobry dźeń", - Language = "Sorbian", - Dialect = "Upper Sorbian" - }, - new GreetingDto() - { - Text = "Buaregh", - Language = "Southern Sámi" - }, - new GreetingDto() - { - Text = "¡Hola!", - Language = "Spanish" - }, - new GreetingDto() - { - Text = "Hoj", - Language = "Stellingwarfs" - }, - new GreetingDto() - { - Text = "Sampurasun", - Language = "Sundanese" - }, - new GreetingDto() - { - Text = "Habari", - Language = "Swahili" - }, - new GreetingDto() - { - Text = "Sawubona", - Language = "Swazi" - }, - new GreetingDto() - { - Text = "God dag", - Language = "Swedish" - }, - new GreetingDto() - { - Text = "Grüezi", - Language = "Swiss German" - }, - new GreetingDto() - { - Text = "Салам", - Language = "Tabassaran", - Romanization = "Salam" - }, - new GreetingDto() - { - Text = "Musta?", - Language = "Tagalog" - }, - new GreetingDto() - { - Text = "'Ia ora na", - Language = "Tahitian" - }, - new GreetingDto() - { - Text = "Ассалому алейкум", - Language = "Tajik", - Romanization = "Assalomu alejkym" - }, - new GreetingDto() - { - Text = "வணக்கம்", - Language = "Tamil", - Romanization = "vaṇakkam" - }, - new GreetingDto() - { - Text = "Isänme", - Language = "Tatar" - }, - new GreetingDto() - { - Text = "నమస్కారం", - Language = "Telugu", - Romanization = "namaskārām" - }, - new GreetingDto() - { - Text = "Elo", - Language = "Tetum" - }, - new GreetingDto() - { - Text = "Miga", - Language = "Teribe" - }, - new GreetingDto() - { - Text = "สวัสดี", - Language = "Thai", - Romanization = "sà-wàt-dee" - }, - new GreetingDto() - { - Text = "བཀྲ་ཤིས་བདེ་ལེགས།", - Language = "Tibetan", - Romanization = "tashi delek" - }, - new GreetingDto() - { - Text = "ሰላም", - Language = "Tigrinya", - Romanization = "selam" - }, - new GreetingDto() - { - Text = "Tālofa", - Language = "Tokelauan" - }, - new GreetingDto() - { - Text = "Gude", - Language = "Tok Pisin" - }, - new GreetingDto() - { - Text = "Mālō e lelei", - Language = "Tongan" - }, - new GreetingDto() - { - Text = "Miiyiha", - Language = "Tongva", - Dialect = "Gabrielino" - }, - new GreetingDto() - { - Text = "Xewani", - Language = "Tsonga" - }, - new GreetingDto() - { - Text = "K'uxi", - Language = "Tsotsil" - }, - new GreetingDto() - { - Text = "Dumela", - Language = "Tswana" - }, - new GreetingDto() - { - Text = "АсаламугIалейкум!", - Language = "Tsez", - Romanization = "AsalamugIalejkum!" - }, - new GreetingDto() - { - Text = "Monile", - Language = "Tumbuka" - }, - new GreetingDto() - { - Text = "Merhaba", - Language = "Turkish" - }, - new GreetingDto() - { - Text = "Salam", - Language = "Turkmen" - }, - new GreetingDto() - { - Text = "Вітаю", - Language = "Ukrainian" - }, - new GreetingDto() - { - Text = "Сородэ", - Language = "Ulch", - Romanization = "Sorodè" - }, - new GreetingDto() - { - Text = "السلام علیکم", - Language = "Urdu", - Romanization = "āssālam 'alaykum" - }, - new GreetingDto() - { - Text = "ئەسسالامۇ ئەلەيكۇم", - Language = "Uyghur", - Romanization = "Ässalamu äläykum" - }, - new GreetingDto() - { - Text = "Assalomu Alaykum", - Language = "Uzbek" - }, - new GreetingDto() - { - Text = "I nhlikanhi", - Language = "Venda" - }, - new GreetingDto() - { - Text = "Ciao", - Language = "Venetian" - }, - new GreetingDto() - { - Text = "Tervhen", - Language = "Veps" - }, - new GreetingDto() - { - Text = "Chào anh", - Language = "Vietnamese" - }, - new GreetingDto() - { - Text = "Tereq", - Language = "Võro" - }, - new GreetingDto() - { - Text = "Bondjoû", - Language = "Walloon" - }, - new GreetingDto() - { - Text = "Ngurrju mayinpa", - Language = "Warlpiri" - }, - new GreetingDto() - { - Text = "Helô", - Language = "Welsh" - }, - new GreetingDto() - { - Text = "Hej", - Language = "Westrobothnian" - }, - new GreetingDto() - { - Text = "Na nga def", - Language = "Wolof" - }, - new GreetingDto() - { - Text = "Molo", - Language = "Xhosa" - }, - new GreetingDto() - { - Text = "Mogethin", - Language = "Yapese" - }, - new GreetingDto() - { - Text = "אַ גוטן טאָג", - Language = "Yiddish", - Romanization = "A gutn tog" - }, - new GreetingDto() - { - Text = "Ẹ n lẹ", - Language = "Yoruba" - }, - new GreetingDto() - { - Text = "Ba'ax ka wa'alik?", - Language = "Yucatec Maya" - }, - new GreetingDto() - { - Text = "Selam", - Language = "Zazaki" - }, - new GreetingDto() - { - Text = "Sawubona", - Language = "Zulu" - }, - new GreetingDto() - { - Text = "Saluton", - Language = "Esperanto" - }, - new GreetingDto() - { - Text = "Bon die!", - Language = "Interlingua" - }, - new GreetingDto() - { - Text = "nuqneH", - Language = "Klingon" - }, - new GreetingDto() - { - Text = "Aiya", - Language = "Quenya" - }, - new GreetingDto() - { - Text = "Glidö", - Language = "Volapük" - }, - new GreetingDto() - { - Text = "Saluto", - Language = "Ido" - } - }; - - public static readonly int GreetingCount = Greetings.Count; - } -} \ No newline at end of file diff --git a/Geekbot.net/Commands/Randomness/Greetings/Greetings.cs b/Geekbot.net/Commands/Randomness/Greetings/Greetings.cs index 334b894..c47bf2a 100644 --- a/Geekbot.net/Commands/Randomness/Greetings/Greetings.cs +++ b/Geekbot.net/Commands/Randomness/Greetings/Greetings.cs @@ -1,9 +1,12 @@ using System; +using System.Net.Http; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.net.Commands.Randomness.Cat; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; +using Newtonsoft.Json; namespace Geekbot.net.Commands.Randomness.Greetings { @@ -23,20 +26,20 @@ namespace Geekbot.net.Commands.Randomness.Greetings { try { - var greeting = GreetingProvider.Greetings[new Random().Next(GreetingProvider.GreetingCount - 1)]; + var greeting = await GetRandomGreeting(); var eb = new EmbedBuilder(); - eb.Title = greeting.Text; + eb.Title = greeting.Primary.Text; eb.AddInlineField("Language", greeting.Language); - if (greeting.Dialect != null) + if (greeting.Primary.Dialect != null) { - eb.AddInlineField("Dialect", greeting.Dialect); + eb.AddInlineField("Dialect", greeting.Primary.Dialect); } - if (greeting.Romanization != null) + if (greeting.Primary.Romanization != null) { - eb.AddInlineField("Roman", greeting.Romanization); + eb.AddInlineField("Roman", greeting.Primary.Romanization); } await ReplyAsync(string.Empty, false, eb.Build()); @@ -46,5 +49,18 @@ namespace Geekbot.net.Commands.Randomness.Greetings await _errorHandler.HandleCommandException(e, Context); } } + + private async Task GetRandomGreeting() + { + using var client = new HttpClient + { + BaseAddress = new Uri("https://api.greetings.dev") + }; + var response = await client.GetAsync("/v1/greeting"); + response.EnsureSuccessStatusCode(); + + var stringResponse = await response.Content.ReadAsStringAsync(); + return JsonConvert.DeserializeObject(stringResponse); + } } } \ No newline at end of file From 0589b8e91b8cf00474f7fafabb8ca1f13740dd95 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 10 Jul 2020 22:32:42 +0200 Subject: [PATCH 357/553] Update EntityFrameworkCore and microsoft.extensions.* to .net5 preview 6 --- Geekbot.net/Geekbot.net.csproj | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 4e13438..969cc30 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -28,31 +28,27 @@ - - - - - - - - + + + + + + + + - + - - 4.3.0 - - - 4.3.0 - + + From ba0d116f3e4e70bdc1a10b9bd8e19e603bf9b774 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 15 Jul 2020 02:52:13 +0200 Subject: [PATCH 358/553] Add an abstraction for http calls --- .../UbranDictionary/UrbanDictionary.cs | 13 +----- Geekbot.net/Commands/Randomness/Cat/Cat.cs | 29 +++---------- .../Randomness/Chuck/ChuckNorrisJokes.cs | 14 ++----- .../Commands/Randomness/Dad/DadJokes.cs | 22 ++-------- Geekbot.net/Commands/Randomness/Dog/Dog.cs | 28 +++---------- .../Randomness/Greetings/Greetings.cs | 19 +-------- .../Commands/Randomness/Kanye/Kanye.cs | 22 ++-------- .../Commands/Utils/Changelog/Changelog.cs | 22 ++++------ Geekbot.net/Lib/HttpAbstractions.cs | 41 +++++++++++++++++++ 9 files changed, 75 insertions(+), 135 deletions(-) create mode 100644 Geekbot.net/Lib/HttpAbstractions.cs diff --git a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs b/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs index 1f33573..882caa5 100644 --- a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs +++ b/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs @@ -1,12 +1,11 @@ using System; using System.Linq; -using System.Net.Http; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; -using Newtonsoft.Json; namespace Geekbot.net.Commands.Integrations.UbranDictionary { @@ -25,15 +24,7 @@ namespace Geekbot.net.Commands.Integrations.UbranDictionary { try { - using var client = new HttpClient - { - BaseAddress = new Uri("https://api.urbandictionary.com") - }; - var response = await client.GetAsync($"/v0/define?term={word}"); - response.EnsureSuccessStatusCode(); - - var stringResponse = await response.Content.ReadAsStringAsync(); - var definitions = JsonConvert.DeserializeObject(stringResponse); + var definitions = await HttpAbstractions.Get(new Uri($"https://api.urbandictionary.com/v0/define?term={word}")); if (definitions.List.Count == 0) { await ReplyAsync("That word hasn't been defined..."); diff --git a/Geekbot.net/Commands/Randomness/Cat/Cat.cs b/Geekbot.net/Commands/Randomness/Cat/Cat.cs index 3ac0764..7cd7b19 100644 --- a/Geekbot.net/Commands/Randomness/Cat/Cat.cs +++ b/Geekbot.net/Commands/Randomness/Cat/Cat.cs @@ -1,10 +1,9 @@ using System; -using System.Net.Http; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; -using Newtonsoft.Json; namespace Geekbot.net.Commands.Randomness.Cat { @@ -23,28 +22,12 @@ namespace Geekbot.net.Commands.Randomness.Cat { try { - - try + var response = await HttpAbstractions.Get(new Uri("https://aws.random.cat/meow")); + var eb = new EmbedBuilder { - using var client = new HttpClient - { - BaseAddress = new Uri("https://aws.random.cat") - }; - var response = await client.GetAsync("/meow"); - response.EnsureSuccessStatusCode(); - - var stringResponse = await response.Content.ReadAsStringAsync(); - var catFile = JsonConvert.DeserializeObject(stringResponse); - var eb = new EmbedBuilder - { - ImageUrl = catFile.File - }; - await ReplyAsync("", false, eb.Build()); - } - catch - { - await ReplyAsync("Seems like the dog cought the cat (error occured)"); - } + ImageUrl = response.File + }; + await ReplyAsync("", false, eb.Build()); } catch (Exception e) { diff --git a/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs b/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs index 5c28a9a..95dcfd4 100644 --- a/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs +++ b/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs @@ -1,10 +1,9 @@ using System; using System.Net.Http; -using System.Net.Http.Headers; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; -using Newtonsoft.Json; namespace Geekbot.net.Commands.Randomness.Chuck { @@ -25,15 +24,8 @@ namespace Geekbot.net.Commands.Randomness.Chuck { try { - using var client = new HttpClient(); - client.DefaultRequestHeaders.Accept.Clear(); - client.DefaultRequestHeaders.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); - var response = await client.GetAsync("https://api.chucknorris.io/jokes/random"); - response.EnsureSuccessStatusCode(); - - var stringResponse = await response.Content.ReadAsStringAsync(); - var data = JsonConvert.DeserializeObject(stringResponse); - await ReplyAsync(data.Value); + var response = await HttpAbstractions.Get(new Uri("https://api.chucknorris.io/jokes/random")); + await ReplyAsync(response.Value); } catch (HttpRequestException) { diff --git a/Geekbot.net/Commands/Randomness/Dad/DadJokes.cs b/Geekbot.net/Commands/Randomness/Dad/DadJokes.cs index bcedd96..7aabff3 100644 --- a/Geekbot.net/Commands/Randomness/Dad/DadJokes.cs +++ b/Geekbot.net/Commands/Randomness/Dad/DadJokes.cs @@ -1,10 +1,8 @@ using System; -using System.Net.Http; -using System.Net.Http.Headers; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; -using Newtonsoft.Json; namespace Geekbot.net.Commands.Randomness.Dad { @@ -23,22 +21,8 @@ namespace Geekbot.net.Commands.Randomness.Dad { try { - try - { - using var client = new HttpClient(); - client.DefaultRequestHeaders.Accept.Clear(); - client.DefaultRequestHeaders.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); - var response = await client.GetAsync("https://icanhazdadjoke.com/"); - response.EnsureSuccessStatusCode(); - - var stringResponse = await response.Content.ReadAsStringAsync(); - var data = JsonConvert.DeserializeObject(stringResponse); - await ReplyAsync(data.Joke); - } - catch (HttpRequestException) - { - await ReplyAsync("Api down..."); - } + var response = await HttpAbstractions.Get(new Uri("https://icanhazdadjoke.com/")); + await ReplyAsync(response.Joke); } catch (Exception e) { diff --git a/Geekbot.net/Commands/Randomness/Dog/Dog.cs b/Geekbot.net/Commands/Randomness/Dog/Dog.cs index d7404c6..b3d603b 100644 --- a/Geekbot.net/Commands/Randomness/Dog/Dog.cs +++ b/Geekbot.net/Commands/Randomness/Dog/Dog.cs @@ -1,10 +1,9 @@ using System; -using System.Net.Http; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; -using Newtonsoft.Json; namespace Geekbot.net.Commands.Randomness.Dog { @@ -23,27 +22,12 @@ namespace Geekbot.net.Commands.Randomness.Dog { try { - try + var response = await HttpAbstractions.Get(new Uri("http://random.dog/woof.json")); + var eb = new EmbedBuilder { - using var client = new HttpClient - { - BaseAddress = new Uri("http://random.dog") - }; - var response = await client.GetAsync("/woof.json"); - response.EnsureSuccessStatusCode(); - - var stringResponse = await response.Content.ReadAsStringAsync(); - var dogFile = JsonConvert.DeserializeObject(stringResponse); - var eb = new EmbedBuilder - { - ImageUrl = dogFile.Url - }; - await ReplyAsync("", false, eb.Build()); - } - catch (HttpRequestException e) - { - await ReplyAsync($"Seems like the dog got lost (error occured)\r\n{e.Message}"); - } + ImageUrl = response.Url + }; + await ReplyAsync("", false, eb.Build()); } catch (Exception e) { diff --git a/Geekbot.net/Commands/Randomness/Greetings/Greetings.cs b/Geekbot.net/Commands/Randomness/Greetings/Greetings.cs index c47bf2a..85e9152 100644 --- a/Geekbot.net/Commands/Randomness/Greetings/Greetings.cs +++ b/Geekbot.net/Commands/Randomness/Greetings/Greetings.cs @@ -1,12 +1,10 @@ using System; -using System.Net.Http; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Commands.Randomness.Cat; +using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; -using Newtonsoft.Json; namespace Geekbot.net.Commands.Randomness.Greetings { @@ -26,7 +24,7 @@ namespace Geekbot.net.Commands.Randomness.Greetings { try { - var greeting = await GetRandomGreeting(); + var greeting = await HttpAbstractions.Get(new Uri("https://api.greetings.dev/v1/greeting")); var eb = new EmbedBuilder(); eb.Title = greeting.Primary.Text; @@ -49,18 +47,5 @@ namespace Geekbot.net.Commands.Randomness.Greetings await _errorHandler.HandleCommandException(e, Context); } } - - private async Task GetRandomGreeting() - { - using var client = new HttpClient - { - BaseAddress = new Uri("https://api.greetings.dev") - }; - var response = await client.GetAsync("/v1/greeting"); - response.EnsureSuccessStatusCode(); - - var stringResponse = await response.Content.ReadAsStringAsync(); - return JsonConvert.DeserializeObject(stringResponse); - } } } \ No newline at end of file diff --git a/Geekbot.net/Commands/Randomness/Kanye/Kanye.cs b/Geekbot.net/Commands/Randomness/Kanye/Kanye.cs index 36f1d1a..2aca31d 100644 --- a/Geekbot.net/Commands/Randomness/Kanye/Kanye.cs +++ b/Geekbot.net/Commands/Randomness/Kanye/Kanye.cs @@ -1,10 +1,8 @@ using System; -using System.Net.Http; -using System.Net.Http.Headers; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; -using Newtonsoft.Json; namespace Geekbot.net.Commands.Randomness.Kanye { @@ -23,22 +21,8 @@ namespace Geekbot.net.Commands.Randomness.Kanye { try { - try - { - using var client = new HttpClient(); - client.DefaultRequestHeaders.Accept.Clear(); - client.DefaultRequestHeaders.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); - var response = await client.GetAsync("https://api.kanye.rest/"); - response.EnsureSuccessStatusCode(); - - var stringResponse = await response.Content.ReadAsStringAsync(); - var data = JsonConvert.DeserializeObject(stringResponse); - await ReplyAsync(data.Quote); - } - catch (HttpRequestException) - { - await ReplyAsync("Api down..."); - } + var response = await HttpAbstractions.Get(new Uri("https://api.kanye.rest/")); + await ReplyAsync(response.Quote); } catch (Exception e) { diff --git a/Geekbot.net/Commands/Utils/Changelog/Changelog.cs b/Geekbot.net/Commands/Utils/Changelog/Changelog.cs index 02981df..335ee3f 100644 --- a/Geekbot.net/Commands/Utils/Changelog/Changelog.cs +++ b/Geekbot.net/Commands/Utils/Changelog/Changelog.cs @@ -1,14 +1,13 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Net.Http; using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.WebSocket; +using Geekbot.net.Lib; using Geekbot.net.Lib.ErrorHandling; -using Newtonsoft.Json; namespace Geekbot.net.Commands.Utils.Changelog { @@ -29,17 +28,14 @@ namespace Geekbot.net.Commands.Utils.Changelog { try { - using var client = new HttpClient - { - BaseAddress = new Uri("https://api.github.com") - }; - client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", - "http://developer.github.com/v3/#user-agent-required"); - var response = await client.GetAsync("/repos/pizzaandcoffee/geekbot.net/commits"); - response.EnsureSuccessStatusCode(); - - var stringResponse = await response.Content.ReadAsStringAsync(); - var commits = JsonConvert.DeserializeObject>(stringResponse); + var commits = await HttpAbstractions.Get>( + new Uri("https://api.github.com/repos/pizzaandcoffee/geekbot.net/commits"), + new Dictionary() + { + { "User-Agent", "http://developer.github.com/v3/#user-agent-required" } + } + ); + var eb = new EmbedBuilder(); eb.WithColor(new Color(143, 165, 102)); eb.WithAuthor(new EmbedAuthorBuilder diff --git a/Geekbot.net/Lib/HttpAbstractions.cs b/Geekbot.net/Lib/HttpAbstractions.cs new file mode 100644 index 0000000..cf609f6 --- /dev/null +++ b/Geekbot.net/Lib/HttpAbstractions.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Threading.Tasks; +using Newtonsoft.Json; + +namespace Geekbot.net.Lib +{ + public class HttpAbstractions + { + public static async Task Get(Uri location, Dictionary additionalHeaders = null) + { + using var client = new HttpClient + { + BaseAddress = location, + DefaultRequestHeaders = + { + Accept = + { + MediaTypeWithQualityHeaderValue.Parse("application/json") + } + } + }; + + if (additionalHeaders != null) + { + foreach (var (name, val) in additionalHeaders) + { + client.DefaultRequestHeaders.TryAddWithoutValidation(name, val); + } + } + + var response = await client.GetAsync(location.PathAndQuery); + response.EnsureSuccessStatusCode(); + + var stringResponse = await response.Content.ReadAsStringAsync(); + return JsonConvert.DeserializeObject(stringResponse); + } + } +} \ No newline at end of file From efed2f712048e904de30299d66477003cd1ac533 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 15 Jul 2020 03:09:43 +0200 Subject: [PATCH 359/553] Add the !corona command --- .../Commands/Utils/Corona/CoronaStats.cs | 67 +++++++++++++++++++ .../Commands/Utils/Corona/CoronaSummaryDto.cs | 9 +++ 2 files changed, 76 insertions(+) create mode 100644 Geekbot.net/Commands/Utils/Corona/CoronaStats.cs create mode 100644 Geekbot.net/Commands/Utils/Corona/CoronaSummaryDto.cs diff --git a/Geekbot.net/Commands/Utils/Corona/CoronaStats.cs b/Geekbot.net/Commands/Utils/Corona/CoronaStats.cs new file mode 100644 index 0000000..4be8195 --- /dev/null +++ b/Geekbot.net/Commands/Utils/Corona/CoronaStats.cs @@ -0,0 +1,67 @@ +using System; +using System.Text; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; +using Geekbot.net.Lib.Extensions; + +namespace Geekbot.net.Commands.Utils.Corona +{ + public class CoronaStats : ModuleBase + { + private readonly IErrorHandler _errorHandler; + + public CoronaStats(IErrorHandler errorHandler) + { + _errorHandler = errorHandler; + } + + [Command("corona", RunMode = RunMode.Async)] + [Summary("Get the latest worldwide corona statistics")] + public async Task Summary() + { + try + { + var summary = await HttpAbstractions.Get(new Uri("https://api.covid19api.com/world/total")); + var activeCases = summary.TotalConfirmed - (summary.TotalRecovered + summary.TotalDeaths); + + string CalculatePercentage(decimal i) => (i / summary.TotalConfirmed).ToString("#0.##%"); + var activePercent = CalculatePercentage(activeCases); + var recoveredPercentage = CalculatePercentage(summary.TotalRecovered); + var deathsPercentage = CalculatePercentage(summary.TotalDeaths); + + var numberFormat = "#,#"; + var totalFormatted = summary.TotalConfirmed.ToString(numberFormat); + var activeFormatted = activeCases.ToString(numberFormat); + var recoveredFormatted = summary.TotalRecovered.ToString(numberFormat); + var deathsFormatted = summary.TotalDeaths.ToString(numberFormat); + + var eb = new EmbedBuilder + { + Author = new EmbedAuthorBuilder + { + Name = "Confirmed Corona Cases", + IconUrl = "https://www.redcross.org/content/dam/icons/disasters/virus/Virus-1000x1000-R-Pl.png" + }, + Footer = new EmbedFooterBuilder + { + Text = "Source: covid19api.com", + }, + Color = Color.Red + }; + eb.AddField("Total", totalFormatted); + eb.AddInlineField("Active", $"{activeFormatted} ({activePercent})"); + eb.AddInlineField("Recovered", $"{recoveredFormatted} ({recoveredPercentage})"); + eb.AddInlineField("Deaths", $"{deathsFormatted} ({deathsPercentage})"); + + await Context.Channel.SendMessageAsync(String.Empty, false, eb.Build()); + } + catch (Exception e) + { + await _errorHandler.HandleCommandException(e, Context); + } + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Utils/Corona/CoronaSummaryDto.cs b/Geekbot.net/Commands/Utils/Corona/CoronaSummaryDto.cs new file mode 100644 index 0000000..5639249 --- /dev/null +++ b/Geekbot.net/Commands/Utils/Corona/CoronaSummaryDto.cs @@ -0,0 +1,9 @@ +namespace Geekbot.net.Commands.Utils.Corona +{ + public class CoronaSummaryDto + { + public decimal TotalConfirmed { get; set; } + public decimal TotalDeaths { get; set; } + public decimal TotalRecovered { get; set; } + } +} \ No newline at end of file From 5e9cb8a4c18f739e00807511d8fa656591711956 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 15 Jul 2020 03:11:36 +0200 Subject: [PATCH 360/553] Make main async --- Geekbot.net/Program.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index c96e2f5..689c170 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -44,7 +44,7 @@ namespace Geekbot.net private IReactionListener _reactionListener; private IGuildSettingsManager _guildSettingsManager; - private static void Main(string[] args) + private static async Task Main(string[] args) { RunParameters runParameters = null; Parser.Default.ParseArguments(args) @@ -63,7 +63,7 @@ namespace Geekbot.net logger.Information(LogSource.Geekbot, "Starting..."); try { - new Program().MainAsync(runParameters, logger).GetAwaiter().GetResult(); + await new Program().Start(runParameters, logger); } catch (Exception e) { @@ -71,7 +71,7 @@ namespace Geekbot.net } } - private async Task MainAsync(RunParameters runParameters, GeekbotLogger logger) + private async Task Start(RunParameters runParameters, GeekbotLogger logger) { _logger = logger; _runParameters = runParameters; From 4cd7ac1d799acac1b2866e9b064223ebcbb98c19 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 15 Jul 2020 17:10:50 +0200 Subject: [PATCH 361/553] Fix broken DM Channel support --- Geekbot.net/Handlers/CommandHandler.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Geekbot.net/Handlers/CommandHandler.cs b/Geekbot.net/Handlers/CommandHandler.cs index b811a8e..b6a3d9f 100644 --- a/Geekbot.net/Handlers/CommandHandler.cs +++ b/Geekbot.net/Handlers/CommandHandler.cs @@ -52,7 +52,12 @@ namespace Geekbot.net.Handlers if (!(messageParam is SocketUserMessage message)) return Task.CompletedTask; if (message.Author.IsBot) return Task.CompletedTask; - var guildId = ((SocketGuildChannel) message.Channel).Guild.Id; + ulong guildId = message.Author switch + { + SocketGuildUser user => user.Guild.Id, + _ => 0 // DM Channel + }; + if (IsIgnoredGuild(guildId, message.Author.Id)) return Task.CompletedTask; var lowCaseMsg = message.ToString().ToLower(); @@ -102,12 +107,14 @@ namespace Geekbot.net.Handlers private bool ShouldPong(string lowerCaseMessage, ulong guildId) { if (!lowerCaseMessage.StartsWith("ping ") && !lowerCaseMessage.Equals("ping")) return false; + if (guildId == 0) return true; return GetGuildSettings(guildId)?.Ping ?? false; } private bool ShouldHui(string lowerCaseMessage, ulong guildId) { if (!lowerCaseMessage.StartsWith("hui")) return false; + if (guildId == 0) return true; return GetGuildSettings(guildId)?.Hui ?? false; } From 77e912501df42181578c4b1187cb94354510aa84 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 22 Jul 2020 14:09:26 +0200 Subject: [PATCH 362/553] Upgrade to .NET5 preview 7 --- Geekbot.net/Geekbot.net.csproj | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 969cc30..37dc310 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -28,14 +28,14 @@ - - - - - - - - + + + + + + + + From fff232423264abed48ad3a4e1d93c09283d3d290 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 22 Jul 2020 14:17:08 +0200 Subject: [PATCH 363/553] Fix build warnings in MediaProvider.cs and TranslationHandler.cs --- .../Lib/Localization/TranslationHandler.cs | 8 +++---- Geekbot.net/Lib/Media/MediaProvider.cs | 21 ++++++++++--------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Geekbot.net/Lib/Localization/TranslationHandler.cs b/Geekbot.net/Lib/Localization/TranslationHandler.cs index 89ba632..6166e6a 100644 --- a/Geekbot.net/Lib/Localization/TranslationHandler.cs +++ b/Geekbot.net/Lib/Localization/TranslationHandler.cs @@ -89,7 +89,7 @@ namespace Geekbot.net.Lib.Localization } } - private async Task GetServerLanguage(ulong guildId) + private Task GetServerLanguage(ulong guildId) { try { @@ -99,7 +99,7 @@ namespace Geekbot.net.Lib.Localization lang = _serverLanguages[guildId]; if (!string.IsNullOrEmpty(lang)) { - return lang; + return Task.FromResult(lang); } throw new Exception(); } @@ -107,13 +107,13 @@ namespace Geekbot.net.Lib.Localization { lang = _guildSettingsManager.GetSettings(guildId, false)?.Language ?? "EN"; _serverLanguages[guildId] = lang; - return lang; + return Task.FromResult(lang); } } catch (Exception e) { _logger.Error(LogSource.Geekbot, "Could not get guild language", e); - return "EN"; + return Task.FromResult("EN"); } } diff --git a/Geekbot.net/Lib/Media/MediaProvider.cs b/Geekbot.net/Lib/Media/MediaProvider.cs index 45524de..5a9a055 100644 --- a/Geekbot.net/Lib/Media/MediaProvider.cs +++ b/Geekbot.net/Lib/Media/MediaProvider.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using Geekbot.net.Lib.Logger; using Geekbot.net.Lib.RandomNumberGenerator; @@ -9,14 +10,14 @@ namespace Geekbot.net.Lib.Media { private readonly IRandomNumberGenerator _random; private readonly IGeekbotLogger _logger; - private string[] _pandaImages; - private string[] _croissantImages; - private string[] _squirrelImages; - private string[] _pumpkinImages; - private string[] _turtlesImages; - private string[] _penguinImages; - private string[] _foxImages; - private string[] _dabImages; + private readonly string[] _pandaImages; + private readonly string[] _croissantImages; + private readonly string[] _squirrelImages; + private readonly string[] _pumpkinImages; + private readonly string[] _turtlesImages; + private readonly string[] _penguinImages; + private readonly string[] _foxImages; + private readonly string[] _dabImages; public MediaProvider(IGeekbotLogger logger, IRandomNumberGenerator random) { @@ -24,7 +25,6 @@ namespace Geekbot.net.Lib.Media _logger = logger; logger.Information(LogSource.Geekbot, "Loading Media Files"); -; LoadMedia("./Storage/pandas", ref _pandaImages); LoadMedia("./Storage/croissant", ref _croissantImages); LoadMedia("./Storage/squirrel", ref _squirrelImages); @@ -53,7 +53,8 @@ namespace Geekbot.net.Lib.Media MediaType.Turtle => _turtlesImages, MediaType.Penguin => _penguinImages, MediaType.Fox => _foxImages, - MediaType.Dab => _dabImages + MediaType.Dab => _dabImages, + _ => new string[0] }; return collection[_random.Next(0, collection.Length)]; From 4659f793f55b689ad5df83987007a7827eccd9e5 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 22 Jul 2020 14:32:47 +0200 Subject: [PATCH 364/553] Add !lmgtfy --- Geekbot.net/Commands/Utils/Lmgtfy.cs | 33 ++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 Geekbot.net/Commands/Utils/Lmgtfy.cs diff --git a/Geekbot.net/Commands/Utils/Lmgtfy.cs b/Geekbot.net/Commands/Utils/Lmgtfy.cs new file mode 100644 index 0000000..9976dad --- /dev/null +++ b/Geekbot.net/Commands/Utils/Lmgtfy.cs @@ -0,0 +1,33 @@ +using System; +using System.Threading.Tasks; +using System.Web; +using Discord.Commands; +using Geekbot.net.Lib.ErrorHandling; + +namespace Geekbot.net.Commands.Utils +{ + public class Lmgtfy : ModuleBase + { + private readonly IErrorHandler _errorHandler; + + public Lmgtfy(IErrorHandler errorHandler) + { + _errorHandler = errorHandler; + } + + [Command("lmgtfy", RunMode = RunMode.Async)] + [Summary("Get a 'Let me google that for you' link")] + public async Task GetUrl([Remainder] [Summary("question")] string question) + { + try + { + var encoded = HttpUtility.UrlEncode(question).Replace("%20", "+"); + await Context.Channel.SendMessageAsync($""); + } + catch (Exception e) + { + await _errorHandler.HandleCommandException(e, Context); + } + } + } +} \ No newline at end of file From 913b4a5f10c4dbbb62932d312e35c28839e721c5 Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 28 Jul 2020 22:14:22 +0200 Subject: [PATCH 365/553] Change the HttpAbstractions so that the caller can provide its own HttpClient instead of creating parameters for every HttpClient Option --- .../Commands/Utils/Changelog/Changelog.cs | 8 +--- Geekbot.net/Lib/HttpAbstractions.cs | 39 ++++++++++--------- 2 files changed, 21 insertions(+), 26 deletions(-) diff --git a/Geekbot.net/Commands/Utils/Changelog/Changelog.cs b/Geekbot.net/Commands/Utils/Changelog/Changelog.cs index 335ee3f..c217619 100644 --- a/Geekbot.net/Commands/Utils/Changelog/Changelog.cs +++ b/Geekbot.net/Commands/Utils/Changelog/Changelog.cs @@ -28,13 +28,7 @@ namespace Geekbot.net.Commands.Utils.Changelog { try { - var commits = await HttpAbstractions.Get>( - new Uri("https://api.github.com/repos/pizzaandcoffee/geekbot.net/commits"), - new Dictionary() - { - { "User-Agent", "http://developer.github.com/v3/#user-agent-required" } - } - ); + var commits = await HttpAbstractions.Get>(new Uri("https://api.github.com/repos/pizzaandcoffee/geekbot.net/commits")); var eb = new EmbedBuilder(); eb.WithColor(new Color(143, 165, 102)); diff --git a/Geekbot.net/Lib/HttpAbstractions.cs b/Geekbot.net/Lib/HttpAbstractions.cs index cf609f6..2cde4cc 100644 --- a/Geekbot.net/Lib/HttpAbstractions.cs +++ b/Geekbot.net/Lib/HttpAbstractions.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; @@ -7,34 +6,36 @@ using Newtonsoft.Json; namespace Geekbot.net.Lib { - public class HttpAbstractions + public static class HttpAbstractions { - public static async Task Get(Uri location, Dictionary additionalHeaders = null) + public static HttpClient CreateDefaultClient() { - using var client = new HttpClient + var client = new HttpClient { - BaseAddress = location, DefaultRequestHeaders = { - Accept = - { - MediaTypeWithQualityHeaderValue.Parse("application/json") - } + Accept = {MediaTypeWithQualityHeaderValue.Parse("application/json")}, } }; + client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "Geekbot/v0.0.0 (+https://geekbot.pizzaandcoffee.rocks/)"); - if (additionalHeaders != null) - { - foreach (var (name, val) in additionalHeaders) - { - client.DefaultRequestHeaders.TryAddWithoutValidation(name, val); - } - } - - var response = await client.GetAsync(location.PathAndQuery); + return client; + } + + public static async Task Get(Uri location, HttpClient httpClient = null, bool disposeClient = true) + { + httpClient ??= CreateDefaultClient(); + httpClient.BaseAddress = location; + + var response = await httpClient.GetAsync(location.PathAndQuery); response.EnsureSuccessStatusCode(); - var stringResponse = await response.Content.ReadAsStringAsync(); + + if (disposeClient) + { + httpClient.Dispose(); + } + return JsonConvert.DeserializeObject(stringResponse); } } From 9003d6249eb62e32302c4b38cf35b42905674cfb Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 28 Jul 2020 22:14:59 +0200 Subject: [PATCH 366/553] Add !mmr to get League of Legends MMR numbers --- .../Commands/Integrations/LolMmr/LolMmr.cs | 61 +++++++++++++++++++ .../Commands/Integrations/LolMmr/LolMmrDto.cs | 9 +++ .../Integrations/LolMmr/LolMrrInfoDto.cs | 11 ++++ 3 files changed, 81 insertions(+) create mode 100644 Geekbot.net/Commands/Integrations/LolMmr/LolMmr.cs create mode 100644 Geekbot.net/Commands/Integrations/LolMmr/LolMmrDto.cs create mode 100644 Geekbot.net/Commands/Integrations/LolMmr/LolMrrInfoDto.cs diff --git a/Geekbot.net/Commands/Integrations/LolMmr/LolMmr.cs b/Geekbot.net/Commands/Integrations/LolMmr/LolMmr.cs new file mode 100644 index 0000000..5de7d63 --- /dev/null +++ b/Geekbot.net/Commands/Integrations/LolMmr/LolMmr.cs @@ -0,0 +1,61 @@ +using System; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using System.Web; +using Discord.Commands; +using Geekbot.net.Lib; +using Geekbot.net.Lib.ErrorHandling; + +namespace Geekbot.net.Commands.Integrations.LolMmr +{ + public class LolMmr : ModuleBase + { + private readonly IErrorHandler _errorHandler; + + public LolMmr(IErrorHandler errorHandler) + { + _errorHandler = errorHandler; + } + + [Command("mmr", RunMode = RunMode.Async)] + [Summary("Get the League of Legends MMR for a specified summoner")] + public async Task GetMmr([Remainder] [Summary("summoner")] string summonerName) + { + try + { + LolMmrDto data; + try + { + var name = HttpUtility.UrlEncode(summonerName.ToLower()); + var httpClient = HttpAbstractions.CreateDefaultClient(); + // setting the user agent in accordance with the whatismymmr.com api rules + httpClient.DefaultRequestHeaders.Remove("User-Agent"); + httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "Linux:rocks.pizzaandcoffee.geekbot:v0.0.0"); + data = await HttpAbstractions.Get(new Uri($"https://euw.whatismymmr.com/api/v1/summoner?name={name}"), httpClient); + } + catch (HttpRequestException e) + { + if (e.StatusCode != HttpStatusCode.NotFound) throw e; + + await Context.Channel.SendMessageAsync("Player not found"); + return; + + } + + var sb = new StringBuilder(); + sb.AppendLine($"**MMR for {summonerName}**"); + sb.AppendLine($"Normal: {data.Normal.Avg}"); + sb.AppendLine($"Ranked: {data.Ranked.Avg}"); + sb.AppendLine($"ARAM: {data.ARAM.Avg}"); + + await Context.Channel.SendMessageAsync(sb.ToString()); + } + catch (Exception e) + { + await _errorHandler.HandleCommandException(e, Context); + } + } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Integrations/LolMmr/LolMmrDto.cs b/Geekbot.net/Commands/Integrations/LolMmr/LolMmrDto.cs new file mode 100644 index 0000000..4a9887d --- /dev/null +++ b/Geekbot.net/Commands/Integrations/LolMmr/LolMmrDto.cs @@ -0,0 +1,9 @@ +namespace Geekbot.net.Commands.Integrations.LolMmr +{ + public class LolMmrDto + { + public LolMrrInfoDto Ranked { get; set; } + public LolMrrInfoDto Normal { get; set; } + public LolMrrInfoDto ARAM { get; set; } + } +} \ No newline at end of file diff --git a/Geekbot.net/Commands/Integrations/LolMmr/LolMrrInfoDto.cs b/Geekbot.net/Commands/Integrations/LolMmr/LolMrrInfoDto.cs new file mode 100644 index 0000000..55804fd --- /dev/null +++ b/Geekbot.net/Commands/Integrations/LolMmr/LolMrrInfoDto.cs @@ -0,0 +1,11 @@ +using System; +using Newtonsoft.Json; + +namespace Geekbot.net.Commands.Integrations.LolMmr +{ + public class LolMrrInfoDto + { + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public decimal Avg { get; set; } = 0; + } +} \ No newline at end of file From 3813290f89ab7c2c9558318ee375fde18a16ca98 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 8 Aug 2020 20:53:50 +0200 Subject: [PATCH 367/553] Simplefy version number during in CI pipeline --- .gitlab-ci.yml | 15 +++++++-------- Geekbot.net/Geekbot.net.csproj | 5 ++--- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2e22e02..3d362ce 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,7 +4,9 @@ stages: - deploy - ops -.imageTag: &IMAGE_TAG $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG +variables: + VERSION: 4.2.0-$CI_COMMIT_SHORT_SHA + IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG Build: stage: build @@ -16,7 +18,7 @@ Build: script: - dotnet restore - dotnet test Tests - - dotnet publish --version-suffix ${CI_COMMIT_SHA:0:8} -r linux-x64 -c Release -o ./app ./Geekbot.net/ + - dotnet publish --version-suffix $VERSION -r linux-x64 -c Release -o ./app ./Geekbot.net/ Package: stage: docker @@ -25,8 +27,6 @@ Package: - master services: - docker:stable-dind - variables: - IMAGE_TAG: *IMAGE_TAG script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - docker build -t $IMAGE_TAG . @@ -39,7 +39,6 @@ Deploy: - master variables: ANSIBLE_NOCOWS: 1 - IMAGE_TAG: *IMAGE_TAG before_script: - mkdir /root/.ssh - cp $SSH_PRIVATE_KEY /root/.ssh/id_ed25519 @@ -56,9 +55,9 @@ Sentry: only: - master script: - - sentry-cli releases new -p geekbot 4.2.0-${CI_COMMIT_SHA:0:8} - - sentry-cli releases set-commits --auto 4.2.0-${CI_COMMIT_SHA:0:8} - - sentry-cli releases deploys 4.2.0-${CI_COMMIT_SHA:0:8} new -e Production + - sentry-cli releases new -p geekbot $VERSION + - sentry-cli releases set-commits --auto $VERSION + - sentry-cli releases deploys $VERSION new -e Production Github Mirror: stage: ops diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj index 37dc310..006e6cb 100755 --- a/Geekbot.net/Geekbot.net.csproj +++ b/Geekbot.net/Geekbot.net.csproj @@ -4,10 +4,9 @@ net5.0 win-x64;linux-x64 derp.ico - 4.2.0 $(VersionSuffix) - $(Version)-$(VersionSuffix) - $(Version)-DEV + $(VersionSuffix) + 0.0.0-DEV Pizza and Coffee Studios Pizza and Coffee Studios A Discord bot From c22d0cf9419c47dd9ccde2eb4a7245b233633644 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 8 Aug 2020 21:09:27 +0200 Subject: [PATCH 368/553] Merge WikipediaApi into the main code base --- Geekbot.net.sln | 6 ------ Geekbot.net/Commands/Integrations/Wikipedia.cs | 4 ++-- .../Lib/WikipediaClient}/IWikipediaClient.cs | 4 ++-- .../Lib/WikipediaClient}/Page/PageApiUrls.cs | 2 +- .../Lib/WikipediaClient}/Page/PageContentUrlCollection.cs | 2 +- .../Lib/WikipediaClient}/Page/PageContentUrls.cs | 2 +- .../Lib/WikipediaClient}/Page/PageCoordinates.cs | 2 +- .../Lib/WikipediaClient}/Page/PageImage.cs | 2 +- .../Lib/WikipediaClient}/Page/PageNamespace.cs | 2 +- .../Lib/WikipediaClient}/Page/PagePreview.cs | 2 +- .../Lib/WikipediaClient}/Page/PageTitles.cs | 2 +- .../Lib/WikipediaClient}/Page/PageTypes.cs | 2 +- .../Lib/WikipediaClient}/WikipediaClient.cs | 4 ++-- Geekbot.net/Program.cs | 2 +- WikipediaApi/WikipediaApi.csproj | 8 -------- 15 files changed, 16 insertions(+), 30 deletions(-) rename {WikipediaApi => Geekbot.net/Lib/WikipediaClient}/IWikipediaClient.cs (63%) rename {WikipediaApi => Geekbot.net/Lib/WikipediaClient}/Page/PageApiUrls.cs (84%) rename {WikipediaApi => Geekbot.net/Lib/WikipediaClient}/Page/PageContentUrlCollection.cs (73%) rename {WikipediaApi => Geekbot.net/Lib/WikipediaClient}/Page/PageContentUrls.cs (79%) rename {WikipediaApi => Geekbot.net/Lib/WikipediaClient}/Page/PageCoordinates.cs (68%) rename {WikipediaApi => Geekbot.net/Lib/WikipediaClient}/Page/PageImage.cs (76%) rename {WikipediaApi => Geekbot.net/Lib/WikipediaClient}/Page/PageNamespace.cs (68%) rename {WikipediaApi => Geekbot.net/Lib/WikipediaClient}/Page/PagePreview.cs (94%) rename {WikipediaApi => Geekbot.net/Lib/WikipediaClient}/Page/PageTitles.cs (76%) rename {WikipediaApi => Geekbot.net/Lib/WikipediaClient}/Page/PageTypes.cs (84%) rename {WikipediaApi => Geekbot.net/Lib/WikipediaClient}/WikipediaClient.cs (87%) delete mode 100644 WikipediaApi/WikipediaApi.csproj diff --git a/Geekbot.net.sln b/Geekbot.net.sln index b542f25..5011ad4 100644 --- a/Geekbot.net.sln +++ b/Geekbot.net.sln @@ -7,8 +7,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Geekbot.net", "Geekbot.net/ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WikipediaApi", "WikipediaApi\WikipediaApi.csproj", "{1084D499-EF94-4834-9E6A-B2AD81B60078}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -23,10 +21,6 @@ Global {4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}.Debug|Any CPU.Build.0 = Debug|Any CPU {4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}.Release|Any CPU.ActiveCfg = Release|Any CPU {4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}.Release|Any CPU.Build.0 = Release|Any CPU - {1084D499-EF94-4834-9E6A-B2AD81B60078}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1084D499-EF94-4834-9E6A-B2AD81B60078}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1084D499-EF94-4834-9E6A-B2AD81B60078}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1084D499-EF94-4834-9E6A-B2AD81B60078}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Geekbot.net/Commands/Integrations/Wikipedia.cs b/Geekbot.net/Commands/Integrations/Wikipedia.cs index 9124670..93f68fd 100644 --- a/Geekbot.net/Commands/Integrations/Wikipedia.cs +++ b/Geekbot.net/Commands/Integrations/Wikipedia.cs @@ -8,9 +8,9 @@ using Discord.Commands; using Geekbot.net.Database; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; +using Geekbot.net.Lib.WikipediaClient; +using Geekbot.net.Lib.WikipediaClient.Page; using HtmlAgilityPack; -using WikipediaApi; -using WikipediaApi.Page; namespace Geekbot.net.Commands.Integrations { diff --git a/WikipediaApi/IWikipediaClient.cs b/Geekbot.net/Lib/WikipediaClient/IWikipediaClient.cs similarity index 63% rename from WikipediaApi/IWikipediaClient.cs rename to Geekbot.net/Lib/WikipediaClient/IWikipediaClient.cs index 4d1dae9..c6cdf3d 100644 --- a/WikipediaApi/IWikipediaClient.cs +++ b/Geekbot.net/Lib/WikipediaClient/IWikipediaClient.cs @@ -1,7 +1,7 @@ using System.Threading.Tasks; -using WikipediaApi.Page; +using Geekbot.net.Lib.WikipediaClient.Page; -namespace WikipediaApi +namespace Geekbot.net.Lib.WikipediaClient { public interface IWikipediaClient { diff --git a/WikipediaApi/Page/PageApiUrls.cs b/Geekbot.net/Lib/WikipediaClient/Page/PageApiUrls.cs similarity index 84% rename from WikipediaApi/Page/PageApiUrls.cs rename to Geekbot.net/Lib/WikipediaClient/Page/PageApiUrls.cs index 8a121be..803f4d7 100644 --- a/WikipediaApi/Page/PageApiUrls.cs +++ b/Geekbot.net/Lib/WikipediaClient/Page/PageApiUrls.cs @@ -1,6 +1,6 @@ using System; -namespace WikipediaApi.Page +namespace Geekbot.net.Lib.WikipediaClient.Page { public class PageApiUrls { diff --git a/WikipediaApi/Page/PageContentUrlCollection.cs b/Geekbot.net/Lib/WikipediaClient/Page/PageContentUrlCollection.cs similarity index 73% rename from WikipediaApi/Page/PageContentUrlCollection.cs rename to Geekbot.net/Lib/WikipediaClient/Page/PageContentUrlCollection.cs index f6c680b..614aaa7 100644 --- a/WikipediaApi/Page/PageContentUrlCollection.cs +++ b/Geekbot.net/Lib/WikipediaClient/Page/PageContentUrlCollection.cs @@ -1,4 +1,4 @@ -namespace WikipediaApi.Page +namespace Geekbot.net.Lib.WikipediaClient.Page { public class PageContentUrlCollection { diff --git a/WikipediaApi/Page/PageContentUrls.cs b/Geekbot.net/Lib/WikipediaClient/Page/PageContentUrls.cs similarity index 79% rename from WikipediaApi/Page/PageContentUrls.cs rename to Geekbot.net/Lib/WikipediaClient/Page/PageContentUrls.cs index 64a80dc..faf7bb5 100644 --- a/WikipediaApi/Page/PageContentUrls.cs +++ b/Geekbot.net/Lib/WikipediaClient/Page/PageContentUrls.cs @@ -1,6 +1,6 @@ using System; -namespace WikipediaApi.Page +namespace Geekbot.net.Lib.WikipediaClient.Page { public class PageContentUrls { diff --git a/WikipediaApi/Page/PageCoordinates.cs b/Geekbot.net/Lib/WikipediaClient/Page/PageCoordinates.cs similarity index 68% rename from WikipediaApi/Page/PageCoordinates.cs rename to Geekbot.net/Lib/WikipediaClient/Page/PageCoordinates.cs index 7fa42ba..ce67f9b 100644 --- a/WikipediaApi/Page/PageCoordinates.cs +++ b/Geekbot.net/Lib/WikipediaClient/Page/PageCoordinates.cs @@ -1,4 +1,4 @@ -namespace WikipediaApi.Page +namespace Geekbot.net.Lib.WikipediaClient.Page { public class PageCoordinates { diff --git a/WikipediaApi/Page/PageImage.cs b/Geekbot.net/Lib/WikipediaClient/Page/PageImage.cs similarity index 76% rename from WikipediaApi/Page/PageImage.cs rename to Geekbot.net/Lib/WikipediaClient/Page/PageImage.cs index 4a8b28d..cdcc2a9 100644 --- a/WikipediaApi/Page/PageImage.cs +++ b/Geekbot.net/Lib/WikipediaClient/Page/PageImage.cs @@ -1,6 +1,6 @@ using System; -namespace WikipediaApi.Page +namespace Geekbot.net.Lib.WikipediaClient.Page { public class PageImage { diff --git a/WikipediaApi/Page/PageNamespace.cs b/Geekbot.net/Lib/WikipediaClient/Page/PageNamespace.cs similarity index 68% rename from WikipediaApi/Page/PageNamespace.cs rename to Geekbot.net/Lib/WikipediaClient/Page/PageNamespace.cs index 66600b6..798e6b9 100644 --- a/WikipediaApi/Page/PageNamespace.cs +++ b/Geekbot.net/Lib/WikipediaClient/Page/PageNamespace.cs @@ -1,4 +1,4 @@ -namespace WikipediaApi.Page +namespace Geekbot.net.Lib.WikipediaClient.Page { public class PageNamespace { diff --git a/WikipediaApi/Page/PagePreview.cs b/Geekbot.net/Lib/WikipediaClient/Page/PagePreview.cs similarity index 94% rename from WikipediaApi/Page/PagePreview.cs rename to Geekbot.net/Lib/WikipediaClient/Page/PagePreview.cs index 8db9dad..37434d3 100644 --- a/WikipediaApi/Page/PagePreview.cs +++ b/Geekbot.net/Lib/WikipediaClient/Page/PagePreview.cs @@ -2,7 +2,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Converters; -namespace WikipediaApi.Page +namespace Geekbot.net.Lib.WikipediaClient.Page { public class PagePreview { diff --git a/WikipediaApi/Page/PageTitles.cs b/Geekbot.net/Lib/WikipediaClient/Page/PageTitles.cs similarity index 76% rename from WikipediaApi/Page/PageTitles.cs rename to Geekbot.net/Lib/WikipediaClient/Page/PageTitles.cs index 31a55b9..dcc2cea 100644 --- a/WikipediaApi/Page/PageTitles.cs +++ b/Geekbot.net/Lib/WikipediaClient/Page/PageTitles.cs @@ -1,4 +1,4 @@ -namespace WikipediaApi.Page +namespace Geekbot.net.Lib.WikipediaClient.Page { public class PageTitles { diff --git a/WikipediaApi/Page/PageTypes.cs b/Geekbot.net/Lib/WikipediaClient/Page/PageTypes.cs similarity index 84% rename from WikipediaApi/Page/PageTypes.cs rename to Geekbot.net/Lib/WikipediaClient/Page/PageTypes.cs index a415d75..63cd4d2 100644 --- a/WikipediaApi/Page/PageTypes.cs +++ b/Geekbot.net/Lib/WikipediaClient/Page/PageTypes.cs @@ -1,6 +1,6 @@ using System.Runtime.Serialization; -namespace WikipediaApi.Page +namespace Geekbot.net.Lib.WikipediaClient.Page { public enum PageTypes { diff --git a/WikipediaApi/WikipediaClient.cs b/Geekbot.net/Lib/WikipediaClient/WikipediaClient.cs similarity index 87% rename from WikipediaApi/WikipediaClient.cs rename to Geekbot.net/Lib/WikipediaClient/WikipediaClient.cs index 6576f3d..ed4902a 100644 --- a/WikipediaApi/WikipediaClient.cs +++ b/Geekbot.net/Lib/WikipediaClient/WikipediaClient.cs @@ -1,9 +1,9 @@ using System.Net.Http; using System.Threading.Tasks; +using Geekbot.net.Lib.WikipediaClient.Page; using Newtonsoft.Json; -using WikipediaApi.Page; -namespace WikipediaApi +namespace Geekbot.net.Lib.WikipediaClient { public class WikipediaClient : IWikipediaClient { diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 689c170..5876c4a 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -24,10 +24,10 @@ using Geekbot.net.Lib.Media; using Geekbot.net.Lib.RandomNumberGenerator; using Geekbot.net.Lib.ReactionListener; using Geekbot.net.Lib.UserRepository; +using Geekbot.net.Lib.WikipediaClient; using Geekbot.net.WebApi; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; -using WikipediaApi; namespace Geekbot.net { diff --git a/WikipediaApi/WikipediaApi.csproj b/WikipediaApi/WikipediaApi.csproj deleted file mode 100644 index e53e3c2..0000000 --- a/WikipediaApi/WikipediaApi.csproj +++ /dev/null @@ -1,8 +0,0 @@ - - - net5.0 - - - - - \ No newline at end of file From 7b6dd2d2f907bb770a8c7a0361ae598c9ab47c32 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 8 Aug 2020 21:17:02 +0200 Subject: [PATCH 369/553] Rename the clients namescape to MalClient, because that was the only thing in there, while other clients got their own namespaces --- Geekbot.net/Commands/Integrations/Mal.cs | 2 +- Geekbot.net/Lib/{Clients => MalClient}/IMalClient.cs | 2 +- Geekbot.net/Lib/{Clients => MalClient}/MalClient.cs | 2 +- Geekbot.net/Program.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename Geekbot.net/Lib/{Clients => MalClient}/IMalClient.cs (83%) rename Geekbot.net/Lib/{Clients => MalClient}/MalClient.cs (95%) diff --git a/Geekbot.net/Commands/Integrations/Mal.cs b/Geekbot.net/Commands/Integrations/Mal.cs index ecc91bf..f8aeb95 100644 --- a/Geekbot.net/Commands/Integrations/Mal.cs +++ b/Geekbot.net/Commands/Integrations/Mal.cs @@ -4,9 +4,9 @@ using System.Web; using System.Xml; using Discord; using Discord.Commands; -using Geekbot.net.Lib.Clients; using Geekbot.net.Lib.ErrorHandling; using Geekbot.net.Lib.Extensions; +using Geekbot.net.Lib.MalClient; namespace Geekbot.net.Commands.Integrations { diff --git a/Geekbot.net/Lib/Clients/IMalClient.cs b/Geekbot.net/Lib/MalClient/IMalClient.cs similarity index 83% rename from Geekbot.net/Lib/Clients/IMalClient.cs rename to Geekbot.net/Lib/MalClient/IMalClient.cs index f59c511..6aaab05 100644 --- a/Geekbot.net/Lib/Clients/IMalClient.cs +++ b/Geekbot.net/Lib/MalClient/IMalClient.cs @@ -1,7 +1,7 @@ using System.Threading.Tasks; using MyAnimeListSharp.Core; -namespace Geekbot.net.Lib.Clients +namespace Geekbot.net.Lib.MalClient { public interface IMalClient { diff --git a/Geekbot.net/Lib/Clients/MalClient.cs b/Geekbot.net/Lib/MalClient/MalClient.cs similarity index 95% rename from Geekbot.net/Lib/Clients/MalClient.cs rename to Geekbot.net/Lib/MalClient/MalClient.cs index 8e5d950..3f121ea 100644 --- a/Geekbot.net/Lib/Clients/MalClient.cs +++ b/Geekbot.net/Lib/MalClient/MalClient.cs @@ -5,7 +5,7 @@ using MyAnimeListSharp.Auth; using MyAnimeListSharp.Core; using MyAnimeListSharp.Facade.Async; -namespace Geekbot.net.Lib.Clients +namespace Geekbot.net.Lib.MalClient { public class MalClient : IMalClient { diff --git a/Geekbot.net/Program.cs b/Geekbot.net/Program.cs index 5876c4a..c55f390 100755 --- a/Geekbot.net/Program.cs +++ b/Geekbot.net/Program.cs @@ -9,7 +9,6 @@ using Discord.WebSocket; using Geekbot.net.Database; using Geekbot.net.Handlers; using Geekbot.net.Lib; -using Geekbot.net.Lib.Clients; using Geekbot.net.Lib.Converters; using Geekbot.net.Lib.DiceParser; using Geekbot.net.Lib.ErrorHandling; @@ -20,6 +19,7 @@ using Geekbot.net.Lib.KvInMemoryStore; using Geekbot.net.Lib.Levels; using Geekbot.net.Lib.Localization; using Geekbot.net.Lib.Logger; +using Geekbot.net.Lib.MalClient; using Geekbot.net.Lib.Media; using Geekbot.net.Lib.RandomNumberGenerator; using Geekbot.net.Lib.ReactionListener; From fc0af492addf933ae08aec4f953110e4be6bcad1 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 8 Aug 2020 22:24:01 +0200 Subject: [PATCH 370/553] Split Geekbot.net into src/Bot, src/Core, and src/Web --- .gitignore | 14 ++-- Geekbot.net.sln | 24 +++++-- Geekbot.net/Geekbot.net.csproj | 64 ------------------ .../Converters/EmojiConverter.test.cs | 4 +- .../DiceParser/DiceParser.test.cs | 9 ++- .../DiceParser/SingleDie.test.cs | 6 +- Tests/{Lib => Core}/Levels/LevelCalc.test.cs | 5 +- .../TranslationGuildContext.test.cs | 4 +- .../Localization/Translations.test.cs | 4 +- Tests/Tests.csproj | 2 +- src/Bot/Bot.csproj | 43 ++++++++++++ .../Bot}/Commands/Admin/Admin.cs | 12 ++-- .../Bot}/Commands/Admin/Mod.cs | 6 +- .../Bot}/Commands/Admin/Owner/Owner.cs | 10 +-- .../Bot}/Commands/Admin/Role.cs | 16 ++--- .../Bot}/Commands/Games/Pokedex.cs | 6 +- .../Bot}/Commands/Games/Roll/Roll.cs | 16 ++--- .../Bot}/Commands/Games/Roll/RollTimeout.cs | 2 +- .../Commands/Integrations/LolMmr/LolMmr.cs | 6 +- .../Commands/Integrations/LolMmr/LolMmrDto.cs | 2 +- .../Integrations/LolMmr/LolMrrInfoDto.cs | 3 +- .../Integrations/MagicTheGathering.cs | 8 +-- .../Bot}/Commands/Integrations/Mal.cs | 8 +-- .../UbranDictionary/UrbanDictListItemDto.cs | 2 +- .../UbranDictionary/UrbanDictResponseDto.cs | 2 +- .../UbranDictionary/UrbanDictionary.cs | 8 +-- .../Bot}/Commands/Integrations/Wikipedia.cs | 12 ++-- .../Bot}/Commands/Integrations/Youtube.cs | 6 +- .../BenedictCumberbatchNameGenerator.cs | 6 +- .../Bot}/Commands/Randomness/Cat/Cat.cs | 6 +- .../Commands/Randomness/Cat/CatResponseDto.cs | 2 +- .../Chuck/ChuckNorrisJokeResponseDto.cs | 2 +- .../Randomness/Chuck/ChuckNorrisJokes.cs | 6 +- .../Randomness/Dad/DadJokeResponseDto.cs | 2 +- .../Bot}/Commands/Randomness/Dad/DadJokes.cs | 6 +- .../Bot}/Commands/Randomness/Dog/Dog.cs | 6 +- .../Commands/Randomness/Dog/DogResponseDto.cs | 2 +- .../Bot}/Commands/Randomness/EightBall.cs | 4 +- .../Bot}/Commands/Randomness/Fortune.cs | 4 +- .../Bot}/Commands/Randomness/Gdq.cs | 4 +- .../Randomness/Greetings/GreetingBaseDto.cs | 2 +- .../Randomness/Greetings/GreetingDto.cs | 2 +- .../Randomness/Greetings/Greetings.cs | 8 +-- .../Bot}/Commands/Randomness/Kanye/Kanye.cs | 6 +- .../Randomness/Kanye/KanyeResponseDto.cs | 2 +- .../Bot}/Commands/Randomness/RandomAnimals.cs | 4 +- .../Bot}/Commands/Randomness/Ship.cs | 14 ++-- .../Bot}/Commands/Randomness/Slap.cs | 10 +-- .../Bot}/Commands/Rpg/Cookies.cs | 16 ++--- .../Bot}/Commands/User/GuildInfo.cs | 12 ++-- .../Bot}/Commands/User/Karma.cs | 14 ++-- .../Bot}/Commands/User/Ranking/Rank.cs | 18 ++--- .../Bot}/Commands/User/Stats.cs | 12 ++-- .../Bot}/Commands/Utils/AvatarGetter.cs | 4 +- .../Commands/Utils/Changelog/Changelog.cs | 6 +- .../Utils/Changelog/CommitAuthorDto.cs | 2 +- .../Commands/Utils/Changelog/CommitDto.cs | 2 +- .../Commands/Utils/Changelog/CommitInfoDto.cs | 2 +- .../Bot}/Commands/Utils/Choose.cs | 6 +- .../Bot}/Commands/Utils/Corona/CoronaStats.cs | 9 ++- .../Commands/Utils/Corona/CoronaSummaryDto.cs | 2 +- .../Bot}/Commands/Utils/Dice.cs | 6 +- .../Bot}/Commands/Utils/Emojify.cs | 6 +- .../Bot}/Commands/Utils/Help.cs | 4 +- .../Bot}/Commands/Utils/Info.cs | 8 +-- .../Bot}/Commands/Utils/Lmgtfy.cs | 4 +- .../Bot}/Commands/Utils/Ping.cs | 2 +- .../Bot}/Commands/Utils/Quote/Quote.cs | 18 ++--- .../Commands/Utils/Quote/QuoteObjectDto.cs | 2 +- .../Bot}/Handlers/CommandHandler.cs | 10 +-- .../Bot}/Handlers/MessageDeletedHandler.cs | 8 +-- .../Bot}/Handlers/ReactionHandler.cs | 4 +- .../Bot}/Handlers/StatsHandler.cs | 10 +-- .../Bot}/Handlers/UserHandler.cs | 10 +-- {Geekbot.net => src/Bot}/Logs/.keep | 0 {Geekbot.net => src/Bot}/Program.cs | 42 ++++++------ {Geekbot.net => src/Bot}/Storage/croissant | 0 {Geekbot.net => src/Bot}/Storage/dab | 0 {Geekbot.net => src/Bot}/Storage/fortunes | 0 {Geekbot.net => src/Bot}/Storage/foxes | 0 {Geekbot.net => src/Bot}/Storage/pandas | 0 {Geekbot.net => src/Bot}/Storage/penguins | 0 {Geekbot.net => src/Bot}/Storage/pumpkin | 0 {Geekbot.net => src/Bot}/Storage/squirrel | 0 {Geekbot.net => src/Bot}/Storage/turtles | 0 {Geekbot.net => src/Bot}/derp.ico | Bin .../DisableInDirectMessageAttribute.cs | 2 +- {Geekbot.net/Lib => src/Core}/Constants.cs | 4 +- .../Core}/Converters/EmojiConverter.cs | 2 +- .../Core}/Converters/IEmojiConverter.cs | 2 +- .../Core}/Converters/IMtgManaConverter.cs | 2 +- .../Core}/Converters/MtgManaConverter.cs | 2 +- src/Core/Core.csproj | 40 +++++++++++ .../Core}/Database/DatabaseContext.cs | 4 +- .../Core}/Database/DatabaseInitializer.cs | 7 +- .../Core}/Database/InMemoryDatabase.cs | 2 +- .../LoggingAdapter/NpgsqlLoggingAdapter.cs | 5 +- .../NpgsqlLoggingProviderAdapter.cs | 5 +- .../Core}/Database/Models/CookiesModel.cs | 2 +- .../Core}/Database/Models/GlobalsModel.cs | 2 +- .../Database/Models/GuildSettingsModel.cs | 2 +- .../Core}/Database/Models/KarmaModel.cs | 2 +- .../Core}/Database/Models/MessagesModel.cs | 2 +- .../Core}/Database/Models/QuoteModel.cs | 2 +- .../Database/Models/ReactionListenerModel.cs | 2 +- .../Database/Models/RoleSelfServiceModel.cs | 2 +- .../Core}/Database/Models/RollsModel.cs | 2 +- .../Core}/Database/Models/ShipsModel.cs | 2 +- .../Core}/Database/Models/SlapsModel.cs | 2 +- .../Core}/Database/Models/UserModel.cs | 3 +- .../Core}/Database/SqlConnectionString.cs | 2 +- .../Core}/Database/SqlDatabase.cs | 2 +- .../Core}/DiceParser/DiceException.cs | 2 +- .../Lib => src/Core}/DiceParser/DiceInput.cs | 2 +- .../Core}/DiceParser/DiceInputOptions.cs | 2 +- .../Lib => src/Core}/DiceParser/DiceParser.cs | 4 +- .../Core}/DiceParser/DieAdvantageType.cs | 2 +- .../Lib => src/Core}/DiceParser/DieResult.cs | 2 +- .../Core}/DiceParser/IDiceParser.cs | 2 +- .../Lib => src/Core}/DiceParser/SingleDie.cs | 6 +- .../Core}/ErrorHandling/ErrorHandler.cs | 6 +- .../Core}/ErrorHandling/IErrorHandler.cs | 2 +- .../Core}/Extensions/DbSetExtensions.cs | 2 +- .../Extensions/EmbedBuilderExtensions.cs | 2 +- .../Core}/Extensions/IntExtensions.cs | 2 +- .../Core}/Extensions/LongExtensions.cs | 2 +- .../Core}/Extensions/StringExtensions.cs | 2 +- .../Core}/Extensions/UlongExtensions.cs | 2 +- .../Lib => src/Core}/GeekbotExitCode.cs | 2 +- .../Core}/GlobalSettings/GlobalSettings.cs | 6 +- .../Core}/GlobalSettings/IGlobalSettings.cs | 4 +- .../GuildSettingsManager.cs | 8 +-- .../IGuildSettingsManager.cs | 4 +- .../Highscores/HighscoreListEmptyException.cs | 2 +- .../Core}/Highscores/HighscoreManager.cs | 8 +-- .../Core}/Highscores/HighscoreTypes.cs | 2 +- .../Core}/Highscores/HighscoreUserDto.cs | 2 +- .../Core}/Highscores/IHighscoreManager.cs | 2 +- .../Lib => src/Core}/HttpAbstractions.cs | 2 +- .../Core}/KvInMemoryStore/IKvInMemoryStore.cs | 2 +- .../Core}/KvInMemoryStore/KvInMemoryStore.cs | 2 +- .../Lib => src/Core}/Levels/ILevelCalc.cs | 2 +- .../Lib => src/Core}/Levels/LevelCalc.cs | 2 +- .../Core}/Localization/ITranslationHandler.cs | 2 +- .../Localization/TranslationGuildContext.cs | 2 +- .../Core}/Localization/TranslationHandler.cs | 6 +- .../Core}/Localization/Translations.yml | 0 .../Lib => src/Core}/Logger/DiscordLogger.cs | 2 +- .../Lib => src/Core}/Logger/GeekbotLogger.cs | 2 +- .../Lib => src/Core}/Logger/IDiscordLogger.cs | 2 +- .../Lib => src/Core}/Logger/IGeekbotLogger.cs | 2 +- .../Lib => src/Core}/Logger/LogDto.cs | 2 +- .../Lib => src/Core}/Logger/LogSource.cs | 2 +- .../Lib => src/Core}/Logger/LoggerFactory.cs | 2 +- .../Lib => src/Core}/Logger/MessageDto.cs | 2 +- .../Core}/Logger/SimpleConextConverter.cs | 2 +- .../Lib => src/Core}/MalClient/IMalClient.cs | 2 +- .../Lib => src/Core}/MalClient/MalClient.cs | 6 +- .../Core}/Media/FortunesProvider.cs | 6 +- .../Core}/Media/IFortunesProvider.cs | 2 +- .../Lib => src/Core}/Media/IMediaProvider.cs | 2 +- .../Lib => src/Core}/Media/MediaProvider.cs | 10 ++- .../Lib => src/Core}/Media/MediaType.cs | 2 +- .../Core}/Polyfills/UserPolyfillDto.cs | 4 +- .../IRandomNumberGenerator.cs | 2 +- .../RandomNumberGenerator.cs | 2 +- .../ReactionListener/IReactionListener.cs | 2 +- .../ReactionListener/ReactionListener.cs | 8 +-- .../Lib => src/Core}/RunParameters.cs | 2 +- .../Core}/UserRepository/IUserRepository.cs | 4 +- .../Core}/UserRepository/UserRepository.cs | 11 ++- .../Core}/WikipediaClient/IWikipediaClient.cs | 4 +- .../Core}/WikipediaClient/Page/PageApiUrls.cs | 2 +- .../Page/PageContentUrlCollection.cs | 2 +- .../WikipediaClient/Page/PageContentUrls.cs | 2 +- .../WikipediaClient/Page/PageCoordinates.cs | 2 +- .../Core}/WikipediaClient/Page/PageImage.cs | 2 +- .../WikipediaClient/Page/PageNamespace.cs | 2 +- .../Core}/WikipediaClient/Page/PagePreview.cs | 2 +- .../Core}/WikipediaClient/Page/PageTitles.cs | 2 +- .../Core}/WikipediaClient/Page/PageTypes.cs | 2 +- .../Core}/WikipediaClient/WikipediaClient.cs | 4 +- {Geekbot.net/WebApi => src/Web}/ApiError.cs | 2 +- .../Callback/CallbackController.cs | 4 +- .../Callback/CallbackTokenResponseDto.cs | 2 +- .../Controllers/Commands/CommandController.cs | 2 +- .../Web}/Controllers/Commands/CommandDto.cs | 2 +- .../Controllers/Commands/CommandParamDto.cs | 2 +- .../Highscores/HighscoreController.cs | 4 +- .../HighscoreControllerPostBodyDto.cs | 4 +- .../HighscoreControllerReponseBody.cs | 4 +- .../Web}/Controllers/Status/ApiStatusDto.cs | 2 +- .../Controllers/Status/StatusController.cs | 4 +- .../Web}/Logging/AspLogProvider.cs | 4 +- .../WebApi => src/Web}/Logging/AspLogger.cs | 4 +- src/Web/Web.csproj | 26 +++++++ .../WebApi => src/Web}/WebApiStartup.cs | 16 ++--- 197 files changed, 542 insertions(+), 498 deletions(-) delete mode 100755 Geekbot.net/Geekbot.net.csproj rename Tests/{Lib => Core}/Converters/EmojiConverter.test.cs (94%) rename Tests/{Lib => Core}/DiceParser/DiceParser.test.cs (97%) rename Tests/{Lib => Core}/DiceParser/SingleDie.test.cs (97%) rename Tests/{Lib => Core}/Levels/LevelCalc.test.cs (91%) rename Tests/{Lib => Core}/Localization/TranslationGuildContext.test.cs (95%) rename Tests/{Lib => Core}/Localization/Translations.test.cs (91%) create mode 100644 src/Bot/Bot.csproj rename {Geekbot.net => src/Bot}/Commands/Admin/Admin.cs (95%) rename {Geekbot.net => src/Bot}/Commands/Admin/Mod.cs (87%) rename {Geekbot.net => src/Bot}/Commands/Admin/Owner/Owner.cs (93%) rename {Geekbot.net => src/Bot}/Commands/Admin/Role.cs (96%) rename {Geekbot.net => src/Bot}/Commands/Games/Pokedex.cs (93%) rename {Geekbot.net => src/Bot}/Commands/Games/Roll/Roll.cs (92%) rename {Geekbot.net => src/Bot}/Commands/Games/Roll/RollTimeout.cs (74%) rename {Geekbot.net => src/Bot}/Commands/Integrations/LolMmr/LolMmr.cs (92%) rename {Geekbot.net => src/Bot}/Commands/Integrations/LolMmr/LolMmrDto.cs (76%) rename {Geekbot.net => src/Bot}/Commands/Integrations/LolMmr/LolMrrInfoDto.cs (71%) rename {Geekbot.net => src/Bot}/Commands/Integrations/MagicTheGathering.cs (93%) rename {Geekbot.net => src/Bot}/Commands/Integrations/Mal.cs (94%) rename {Geekbot.net => src/Bot}/Commands/Integrations/UbranDictionary/UrbanDictListItemDto.cs (81%) rename {Geekbot.net => src/Bot}/Commands/Integrations/UbranDictionary/UrbanDictResponseDto.cs (73%) rename {Geekbot.net => src/Bot}/Commands/Integrations/UbranDictionary/UrbanDictionary.cs (91%) rename {Geekbot.net => src/Bot}/Commands/Integrations/Wikipedia.cs (92%) rename {Geekbot.net => src/Bot}/Commands/Integrations/Youtube.cs (91%) rename {Geekbot.net => src/Bot}/Commands/Randomness/BenedictCumberbatchNameGenerator.cs (95%) rename {Geekbot.net => src/Bot}/Commands/Randomness/Cat/Cat.cs (86%) rename {Geekbot.net => src/Bot}/Commands/Randomness/Cat/CatResponseDto.cs (62%) rename {Geekbot.net => src/Bot}/Commands/Randomness/Chuck/ChuckNorrisJokeResponseDto.cs (64%) rename {Geekbot.net => src/Bot}/Commands/Randomness/Chuck/ChuckNorrisJokes.cs (87%) rename {Geekbot.net => src/Bot}/Commands/Randomness/Dad/DadJokeResponseDto.cs (63%) rename {Geekbot.net => src/Bot}/Commands/Randomness/Dad/DadJokes.cs (85%) rename {Geekbot.net => src/Bot}/Commands/Randomness/Dog/Dog.cs (86%) rename {Geekbot.net => src/Bot}/Commands/Randomness/Dog/DogResponseDto.cs (61%) rename {Geekbot.net => src/Bot}/Commands/Randomness/EightBall.cs (95%) rename {Geekbot.net => src/Bot}/Commands/Randomness/Fortune.cs (83%) rename {Geekbot.net => src/Bot}/Commands/Randomness/Gdq.cs (88%) rename {Geekbot.net => src/Bot}/Commands/Randomness/Greetings/GreetingBaseDto.cs (84%) rename {Geekbot.net => src/Bot}/Commands/Randomness/Greetings/GreetingDto.cs (80%) rename {Geekbot.net => src/Bot}/Commands/Randomness/Greetings/Greetings.cs (90%) rename {Geekbot.net => src/Bot}/Commands/Randomness/Kanye/Kanye.cs (87%) rename {Geekbot.net => src/Bot}/Commands/Randomness/Kanye/KanyeResponseDto.cs (73%) rename {Geekbot.net => src/Bot}/Commands/Randomness/RandomAnimals.cs (97%) rename {Geekbot.net => src/Bot}/Commands/Randomness/Ship.cs (91%) rename {Geekbot.net => src/Bot}/Commands/Randomness/Slap.cs (93%) rename {Geekbot.net => src/Bot}/Commands/Rpg/Cookies.cs (92%) rename {Geekbot.net => src/Bot}/Commands/User/GuildInfo.cs (87%) rename {Geekbot.net => src/Bot}/Commands/User/Karma.cs (95%) rename {Geekbot.net => src/Bot}/Commands/User/Ranking/Rank.cs (90%) rename {Geekbot.net => src/Bot}/Commands/User/Stats.cs (94%) rename {Geekbot.net => src/Bot}/Commands/Utils/AvatarGetter.cs (88%) rename {Geekbot.net => src/Bot}/Commands/Utils/Changelog/Changelog.cs (92%) rename {Geekbot.net => src/Bot}/Commands/Utils/Changelog/CommitAuthorDto.cs (77%) rename {Geekbot.net => src/Bot}/Commands/Utils/Changelog/CommitDto.cs (62%) rename {Geekbot.net => src/Bot}/Commands/Utils/Changelog/CommitInfoDto.cs (71%) rename {Geekbot.net => src/Bot}/Commands/Utils/Choose.cs (88%) rename {Geekbot.net => src/Bot}/Commands/Utils/Corona/CoronaStats.cs (94%) rename {Geekbot.net => src/Bot}/Commands/Utils/Corona/CoronaSummaryDto.cs (82%) rename {Geekbot.net => src/Bot}/Commands/Utils/Dice.cs (97%) rename {Geekbot.net => src/Bot}/Commands/Utils/Emojify.cs (88%) rename {Geekbot.net => src/Bot}/Commands/Utils/Help.cs (93%) rename {Geekbot.net => src/Bot}/Commands/Utils/Info.cs (92%) rename {Geekbot.net => src/Bot}/Commands/Utils/Lmgtfy.cs (92%) rename {Geekbot.net => src/Bot}/Commands/Utils/Ping.cs (89%) rename {Geekbot.net => src/Bot}/Commands/Utils/Quote/Quote.cs (97%) rename {Geekbot.net => src/Bot}/Commands/Utils/Quote/QuoteObjectDto.cs (81%) rename {Geekbot.net => src/Bot}/Handlers/CommandHandler.cs (96%) rename {Geekbot.net => src/Bot}/Handlers/MessageDeletedHandler.cs (93%) rename {Geekbot.net => src/Bot}/Handlers/ReactionHandler.cs (94%) rename {Geekbot.net => src/Bot}/Handlers/StatsHandler.cs (92%) rename {Geekbot.net => src/Bot}/Handlers/UserHandler.cs (95%) rename {Geekbot.net => src/Bot}/Logs/.keep (100%) mode change 100755 => 100644 rename {Geekbot.net => src/Bot}/Program.cs (91%) mode change 100755 => 100644 rename {Geekbot.net => src/Bot}/Storage/croissant (100%) rename {Geekbot.net => src/Bot}/Storage/dab (100%) rename {Geekbot.net => src/Bot}/Storage/fortunes (100%) rename {Geekbot.net => src/Bot}/Storage/foxes (100%) rename {Geekbot.net => src/Bot}/Storage/pandas (100%) rename {Geekbot.net => src/Bot}/Storage/penguins (100%) rename {Geekbot.net => src/Bot}/Storage/pumpkin (100%) rename {Geekbot.net => src/Bot}/Storage/squirrel (100%) rename {Geekbot.net => src/Bot}/Storage/turtles (100%) rename {Geekbot.net => src/Bot}/derp.ico (100%) rename {Geekbot.net/Lib => src/Core}/CommandPreconditions/DisableInDirectMessageAttribute.cs (92%) rename {Geekbot.net/Lib => src/Core}/Constants.cs (72%) rename {Geekbot.net/Lib => src/Core}/Converters/EmojiConverter.cs (96%) rename {Geekbot.net/Lib => src/Core}/Converters/IEmojiConverter.cs (74%) rename {Geekbot.net/Lib => src/Core}/Converters/IMtgManaConverter.cs (67%) rename {Geekbot.net/Lib => src/Core}/Converters/MtgManaConverter.cs (96%) create mode 100644 src/Core/Core.csproj rename {Geekbot.net => src/Core}/Database/DatabaseContext.cs (91%) rename {Geekbot.net => src/Core}/Database/DatabaseInitializer.cs (93%) rename {Geekbot.net => src/Core}/Database/InMemoryDatabase.cs (89%) rename {Geekbot.net => src/Core}/Database/LoggingAdapter/NpgsqlLoggingAdapter.cs (93%) rename {Geekbot.net => src/Core}/Database/LoggingAdapter/NpgsqlLoggingProviderAdapter.cs (82%) rename {Geekbot.net => src/Core}/Database/Models/CookiesModel.cs (87%) rename {Geekbot.net => src/Core}/Database/Models/GlobalsModel.cs (85%) rename {Geekbot.net => src/Core}/Database/Models/GuildSettingsModel.cs (90%) rename {Geekbot.net => src/Core}/Database/Models/KarmaModel.cs (87%) rename {Geekbot.net => src/Core}/Database/Models/MessagesModel.cs (85%) rename {Geekbot.net => src/Core}/Database/Models/QuoteModel.cs (93%) rename {Geekbot.net => src/Core}/Database/Models/ReactionListenerModel.cs (91%) rename {Geekbot.net => src/Core}/Database/Models/RoleSelfServiceModel.cs (85%) rename {Geekbot.net => src/Core}/Database/Models/RollsModel.cs (85%) rename {Geekbot.net => src/Core}/Database/Models/ShipsModel.cs (84%) rename {Geekbot.net => src/Core}/Database/Models/SlapsModel.cs (86%) rename {Geekbot.net => src/Core}/Database/Models/UserModel.cs (84%) rename {Geekbot.net => src/Core}/Database/SqlConnectionString.cs (94%) rename {Geekbot.net => src/Core}/Database/SqlDatabase.cs (90%) rename {Geekbot.net/Lib => src/Core}/DiceParser/DiceException.cs (84%) rename {Geekbot.net/Lib => src/Core}/DiceParser/DiceInput.cs (88%) rename {Geekbot.net/Lib => src/Core}/DiceParser/DiceInputOptions.cs (71%) rename {Geekbot.net/Lib => src/Core}/DiceParser/DiceParser.cs (97%) rename {Geekbot.net/Lib => src/Core}/DiceParser/DieAdvantageType.cs (73%) rename {Geekbot.net/Lib => src/Core}/DiceParser/DieResult.cs (96%) rename {Geekbot.net/Lib => src/Core}/DiceParser/IDiceParser.cs (70%) rename {Geekbot.net/Lib => src/Core}/DiceParser/SingleDie.cs (94%) rename {Geekbot.net/Lib => src/Core}/ErrorHandling/ErrorHandler.cs (97%) rename {Geekbot.net/Lib => src/Core}/ErrorHandling/IErrorHandler.cs (86%) rename {Geekbot.net/Lib => src/Core}/Extensions/DbSetExtensions.cs (94%) rename {Geekbot.net/Lib => src/Core}/Extensions/EmbedBuilderExtensions.cs (86%) rename {Geekbot.net/Lib => src/Core}/Extensions/IntExtensions.cs (87%) rename {Geekbot.net/Lib => src/Core}/Extensions/LongExtensions.cs (79%) rename {Geekbot.net/Lib => src/Core}/Extensions/StringExtensions.cs (83%) rename {Geekbot.net/Lib => src/Core}/Extensions/UlongExtensions.cs (79%) rename {Geekbot.net/Lib => src/Core}/GeekbotExitCode.cs (88%) rename {Geekbot.net/Lib => src/Core}/GlobalSettings/GlobalSettings.cs (91%) rename {Geekbot.net/Lib => src/Core}/GlobalSettings/IGlobalSettings.cs (72%) rename {Geekbot.net/Lib => src/Core}/GuildSettingsManager/GuildSettingsManager.cs (93%) rename {Geekbot.net/Lib => src/Core}/GuildSettingsManager/IGuildSettingsManager.cs (73%) rename {Geekbot.net/Lib => src/Core}/Highscores/HighscoreListEmptyException.cs (86%) rename {Geekbot.net/Lib => src/Core}/Highscores/HighscoreManager.cs (93%) rename {Geekbot.net/Lib => src/Core}/Highscores/HighscoreTypes.cs (69%) rename {Geekbot.net/Lib => src/Core}/Highscores/HighscoreUserDto.cs (82%) rename {Geekbot.net/Lib => src/Core}/Highscores/IHighscoreManager.cs (89%) rename {Geekbot.net/Lib => src/Core}/HttpAbstractions.cs (97%) rename {Geekbot.net/Lib => src/Core}/KvInMemoryStore/IKvInMemoryStore.cs (80%) rename {Geekbot.net/Lib => src/Core}/KvInMemoryStore/KvInMemoryStore.cs (93%) rename {Geekbot.net/Lib => src/Core}/Levels/ILevelCalc.cs (67%) rename {Geekbot.net/Lib => src/Core}/Levels/LevelCalc.cs (95%) rename {Geekbot.net/Lib => src/Core}/Localization/ITranslationHandler.cs (91%) rename {Geekbot.net/Lib => src/Core}/Localization/TranslationGuildContext.cs (95%) rename {Geekbot.net/Lib => src/Core}/Localization/TranslationHandler.cs (96%) rename {Geekbot.net/Lib => src/Core}/Localization/Translations.yml (100%) rename {Geekbot.net/Lib => src/Core}/Logger/DiscordLogger.cs (95%) rename {Geekbot.net/Lib => src/Core}/Logger/GeekbotLogger.cs (96%) rename {Geekbot.net/Lib => src/Core}/Logger/IDiscordLogger.cs (76%) rename {Geekbot.net/Lib => src/Core}/Logger/IGeekbotLogger.cs (92%) rename {Geekbot.net/Lib => src/Core}/Logger/LogDto.cs (88%) rename {Geekbot.net/Lib => src/Core}/Logger/LogSource.cs (87%) rename {Geekbot.net/Lib => src/Core}/Logger/LoggerFactory.cs (98%) rename {Geekbot.net/Lib => src/Core}/Logger/MessageDto.cs (92%) rename {Geekbot.net/Lib => src/Core}/Logger/SimpleConextConverter.cs (96%) rename {Geekbot.net/Lib => src/Core}/MalClient/IMalClient.cs (83%) rename {Geekbot.net/Lib => src/Core}/MalClient/MalClient.cs (92%) rename {Geekbot.net/Lib => src/Core}/Media/FortunesProvider.cs (85%) rename {Geekbot.net/Lib => src/Core}/Media/IFortunesProvider.cs (68%) rename {Geekbot.net/Lib => src/Core}/Media/IMediaProvider.cs (69%) rename {Geekbot.net/Lib => src/Core}/Media/MediaProvider.cs (92%) rename {Geekbot.net/Lib => src/Core}/Media/MediaType.cs (84%) rename {Geekbot.net/Lib => src/Core}/Polyfills/UserPolyfillDto.cs (90%) rename {Geekbot.net/Lib => src/Core}/RandomNumberGenerator/IRandomNumberGenerator.cs (67%) rename {Geekbot.net/Lib => src/Core}/RandomNumberGenerator/RandomNumberGenerator.cs (92%) rename {Geekbot.net/Lib => src/Core}/ReactionListener/IReactionListener.cs (89%) rename {Geekbot.net/Lib => src/Core}/ReactionListener/ReactionListener.cs (92%) rename {Geekbot.net/Lib => src/Core}/RunParameters.cs (97%) rename {Geekbot.net/Lib => src/Core}/UserRepository/IUserRepository.cs (68%) rename {Geekbot.net/Lib => src/Core}/UserRepository/UserRepository.cs (88%) rename {Geekbot.net/Lib => src/Core}/WikipediaClient/IWikipediaClient.cs (63%) rename {Geekbot.net/Lib => src/Core}/WikipediaClient/Page/PageApiUrls.cs (84%) rename {Geekbot.net/Lib => src/Core}/WikipediaClient/Page/PageContentUrlCollection.cs (73%) rename {Geekbot.net/Lib => src/Core}/WikipediaClient/Page/PageContentUrls.cs (79%) rename {Geekbot.net/Lib => src/Core}/WikipediaClient/Page/PageCoordinates.cs (68%) rename {Geekbot.net/Lib => src/Core}/WikipediaClient/Page/PageImage.cs (76%) rename {Geekbot.net/Lib => src/Core}/WikipediaClient/Page/PageNamespace.cs (68%) rename {Geekbot.net/Lib => src/Core}/WikipediaClient/Page/PagePreview.cs (94%) rename {Geekbot.net/Lib => src/Core}/WikipediaClient/Page/PageTitles.cs (76%) rename {Geekbot.net/Lib => src/Core}/WikipediaClient/Page/PageTypes.cs (84%) rename {Geekbot.net/Lib => src/Core}/WikipediaClient/WikipediaClient.cs (87%) rename {Geekbot.net/WebApi => src/Web}/ApiError.cs (70%) rename {Geekbot.net/WebApi => src/Web}/Controllers/Callback/CallbackController.cs (96%) rename {Geekbot.net/WebApi => src/Web}/Controllers/Callback/CallbackTokenResponseDto.cs (85%) rename {Geekbot.net/WebApi => src/Web}/Controllers/Commands/CommandController.cs (93%) rename {Geekbot.net/WebApi => src/Web}/Controllers/Commands/CommandDto.cs (83%) rename {Geekbot.net/WebApi => src/Web}/Controllers/Commands/CommandParamDto.cs (74%) rename {Geekbot.net/WebApi => src/Web}/Controllers/Highscores/HighscoreController.cs (92%) rename {Geekbot.net/WebApi => src/Web}/Controllers/Highscores/HighscoreControllerPostBodyDto.cs (76%) rename {Geekbot.net/WebApi => src/Web}/Controllers/Highscores/HighscoreControllerReponseBody.cs (66%) rename {Geekbot.net/WebApi => src/Web}/Controllers/Status/ApiStatusDto.cs (75%) rename {Geekbot.net/WebApi => src/Web}/Controllers/Status/StatusController.cs (89%) rename {Geekbot.net/WebApi => src/Web}/Logging/AspLogProvider.cs (88%) rename {Geekbot.net/WebApi => src/Web}/Logging/AspLogger.cs (95%) create mode 100644 src/Web/Web.csproj rename {Geekbot.net/WebApi => src/Web}/WebApiStartup.cs (86%) diff --git a/.gitignore b/.gitignore index 5db124b..066c4b4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,10 @@ -*/bin/ -*/obj/ -Geekbot.net/tmp/ +/*/**/bin +/*/**/obj +src/Bot/tmp/ +src/Bot/Logs/* +!/src/Bot/Logs/.keep .vs/ -UpgradeLog.htm .idea .vscode -Geekbot.net/Logs/* -!/Geekbot.net/Logs/.keep Geekbot.net.sln.DotSettings.user -Geekbot.net/temp/ -app \ No newline at end of file +app diff --git a/Geekbot.net.sln b/Geekbot.net.sln index 5011ad4..5dc5e4b 100644 --- a/Geekbot.net.sln +++ b/Geekbot.net.sln @@ -3,24 +3,36 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 VisualStudioVersion = 12.0.0.0 MinimumVisualStudioVersion = 10.0.0.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Geekbot.net", "Geekbot.net/Geekbot.net.csproj", "{FDCB3D92-E7B5-47BB-A9B5-CFAEFA57CDB4}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "src\Core\Core.csproj", "{47671723-52A9-4668-BBC5-2BA76AE3B288}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Web", "src\Web\Web.csproj", "{0A63D5DC-6325-4F53-8ED2-9843239B76CC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bot", "src\Bot\Bot.csproj", "{DBF79896-9F7F-443D-B336-155E276DFF16}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {FDCB3D92-E7B5-47BB-A9B5-CFAEFA57CDB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FDCB3D92-E7B5-47BB-A9B5-CFAEFA57CDB4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FDCB3D92-E7B5-47BB-A9B5-CFAEFA57CDB4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FDCB3D92-E7B5-47BB-A9B5-CFAEFA57CDB4}.Release|Any CPU.Build.0 = Release|Any CPU {4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}.Debug|Any CPU.Build.0 = Debug|Any CPU {4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}.Release|Any CPU.ActiveCfg = Release|Any CPU {4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}.Release|Any CPU.Build.0 = Release|Any CPU + {47671723-52A9-4668-BBC5-2BA76AE3B288}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {47671723-52A9-4668-BBC5-2BA76AE3B288}.Debug|Any CPU.Build.0 = Debug|Any CPU + {47671723-52A9-4668-BBC5-2BA76AE3B288}.Release|Any CPU.ActiveCfg = Release|Any CPU + {47671723-52A9-4668-BBC5-2BA76AE3B288}.Release|Any CPU.Build.0 = Release|Any CPU + {0A63D5DC-6325-4F53-8ED2-9843239B76CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0A63D5DC-6325-4F53-8ED2-9843239B76CC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0A63D5DC-6325-4F53-8ED2-9843239B76CC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0A63D5DC-6325-4F53-8ED2-9843239B76CC}.Release|Any CPU.Build.0 = Release|Any CPU + {DBF79896-9F7F-443D-B336-155E276DFF16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DBF79896-9F7F-443D-B336-155E276DFF16}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DBF79896-9F7F-443D-B336-155E276DFF16}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DBF79896-9F7F-443D-B336-155E276DFF16}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Geekbot.net/Geekbot.net.csproj b/Geekbot.net/Geekbot.net.csproj deleted file mode 100755 index 006e6cb..0000000 --- a/Geekbot.net/Geekbot.net.csproj +++ /dev/null @@ -1,64 +0,0 @@ - - - Exe - net5.0 - win-x64;linux-x64 - derp.ico - $(VersionSuffix) - $(VersionSuffix) - 0.0.0-DEV - Pizza and Coffee Studios - Pizza and Coffee Studios - A Discord bot - https://github.com/pizzaandcoffee/Geekbot.net - NU1701 - git - https://geekbot.pizzaandcoffee.rocks - - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PreserveNewest - - - Always - - - - - - \ No newline at end of file diff --git a/Tests/Lib/Converters/EmojiConverter.test.cs b/Tests/Core/Converters/EmojiConverter.test.cs similarity index 94% rename from Tests/Lib/Converters/EmojiConverter.test.cs rename to Tests/Core/Converters/EmojiConverter.test.cs index ad37824..f58d669 100644 --- a/Tests/Lib/Converters/EmojiConverter.test.cs +++ b/Tests/Core/Converters/EmojiConverter.test.cs @@ -1,7 +1,7 @@ -using Geekbot.net.Lib.Converters; +using Geekbot.Core.Converters; using Xunit; -namespace Tests.Lib.Converters +namespace Tests.Core.Converters { public class EmojiConverterTest { diff --git a/Tests/Lib/DiceParser/DiceParser.test.cs b/Tests/Core/DiceParser/DiceParser.test.cs similarity index 97% rename from Tests/Lib/DiceParser/DiceParser.test.cs rename to Tests/Core/DiceParser/DiceParser.test.cs index 48a362c..8a9163a 100644 --- a/Tests/Lib/DiceParser/DiceParser.test.cs +++ b/Tests/Core/DiceParser/DiceParser.test.cs @@ -1,11 +1,10 @@ using System.Collections.Generic; using System.Text.Json; -using Geekbot.net.Lib.DiceParser; -using Geekbot.net.Lib.RandomNumberGenerator; +using Geekbot.Core.DiceParser; +using Geekbot.Core.RandomNumberGenerator; using Xunit; -using YamlDotNet.Serialization; -namespace Tests.Lib.DiceParser +namespace Tests.Core.DiceParser { public class DiceParserTest { @@ -200,7 +199,7 @@ namespace Tests.Lib.DiceParser [Theory, MemberData(nameof(DiceParserTestData))] public void DiceParserTestFunc(string testName, DiceParserTestDto testData) { - var parser = new Geekbot.net.Lib.DiceParser.DiceParser(_randomNumberGenerator); + var parser = new Geekbot.Core.DiceParser.DiceParser(_randomNumberGenerator); var result = parser.Parse(testData.Input); Assert.Equal(JsonSerializer.Serialize(result), JsonSerializer.Serialize(testData.Expected)); diff --git a/Tests/Lib/DiceParser/SingleDie.test.cs b/Tests/Core/DiceParser/SingleDie.test.cs similarity index 97% rename from Tests/Lib/DiceParser/SingleDie.test.cs rename to Tests/Core/DiceParser/SingleDie.test.cs index 2309f98..813a33b 100644 --- a/Tests/Lib/DiceParser/SingleDie.test.cs +++ b/Tests/Core/DiceParser/SingleDie.test.cs @@ -1,8 +1,8 @@ -using Geekbot.net.Lib.DiceParser; -using Geekbot.net.Lib.RandomNumberGenerator; +using Geekbot.Core.DiceParser; +using Geekbot.Core.RandomNumberGenerator; using Xunit; -namespace Tests.Lib.DiceParser +namespace Tests.Core.DiceParser { public class SingleDieTest { diff --git a/Tests/Lib/Levels/LevelCalc.test.cs b/Tests/Core/Levels/LevelCalc.test.cs similarity index 91% rename from Tests/Lib/Levels/LevelCalc.test.cs rename to Tests/Core/Levels/LevelCalc.test.cs index 9b4b97c..02db6f5 100644 --- a/Tests/Lib/Levels/LevelCalc.test.cs +++ b/Tests/Core/Levels/LevelCalc.test.cs @@ -1,8 +1,7 @@ -using System.Collections.Generic; -using Geekbot.net.Lib.Levels; +using Geekbot.Core.Levels; using Xunit; -namespace Tests.Lib.Levels +namespace Tests.Core.Levels { public class LevelCalcTest { diff --git a/Tests/Lib/Localization/TranslationGuildContext.test.cs b/Tests/Core/Localization/TranslationGuildContext.test.cs similarity index 95% rename from Tests/Lib/Localization/TranslationGuildContext.test.cs rename to Tests/Core/Localization/TranslationGuildContext.test.cs index aeea0e1..4aaca16 100644 --- a/Tests/Lib/Localization/TranslationGuildContext.test.cs +++ b/Tests/Core/Localization/TranslationGuildContext.test.cs @@ -1,10 +1,10 @@ using System; using System.Collections.Generic; -using Geekbot.net.Lib.Localization; +using Geekbot.Core.Localization; using Moq; using Xunit; -namespace Tests.Lib.Localization +namespace Tests.Core.Localization { public class TranslationGuildContext_test { diff --git a/Tests/Lib/Localization/Translations.test.cs b/Tests/Core/Localization/Translations.test.cs similarity index 91% rename from Tests/Lib/Localization/Translations.test.cs rename to Tests/Core/Localization/Translations.test.cs index 736ed83..d8a0879 100644 --- a/Tests/Lib/Localization/Translations.test.cs +++ b/Tests/Core/Localization/Translations.test.cs @@ -6,7 +6,7 @@ using Xunit; using YamlDotNet.Core; using YamlDotNet.Serialization; -namespace Tests.Lib.Localization +namespace Tests.Core.Localization { public class Translations_test { @@ -14,7 +14,7 @@ namespace Tests.Lib.Localization public void TranslationsYamlIsValid() { // Read the file - var translationFile = File.ReadAllText(Path.GetFullPath("./../../../../Geekbot.net/Lib/Localization/Translations.yml")); + var translationFile = File.ReadAllText(Path.GetFullPath("./../../../../src/Core/Localization/Translations.yml")); // Deserialize var input = new StringReader(translationFile); diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index eaf88a3..b8d1fc4 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -15,6 +15,6 @@ - + \ No newline at end of file diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj new file mode 100644 index 0000000..c7889ae --- /dev/null +++ b/src/Bot/Bot.csproj @@ -0,0 +1,43 @@ + + + Exe + net5.0 + win-x64;linux-x64 + derp.ico + $(VersionSuffix) + Geekbot.Bot + Geekbot + $(VersionSuffix) + 0.0.0-DEV + Pizza and Coffee Studios + Pizza and Coffee Studios + A Discord bot + https://github.com/pizzaandcoffee/Geekbot.net + NU1701 + git + https://geekbot.pizzaandcoffee.rocks + + + true + + + + + + + + + + + + + + + PreserveNewest + + + + + + + diff --git a/Geekbot.net/Commands/Admin/Admin.cs b/src/Bot/Commands/Admin/Admin.cs similarity index 95% rename from Geekbot.net/Commands/Admin/Admin.cs rename to src/Bot/Commands/Admin/Admin.cs index 9120971..f6c4210 100644 --- a/Geekbot.net/Commands/Admin/Admin.cs +++ b/src/Bot/Commands/Admin/Admin.cs @@ -4,13 +4,13 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.WebSocket; -using Geekbot.net.Lib.CommandPreconditions; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.Extensions; -using Geekbot.net.Lib.GuildSettingsManager; -using Geekbot.net.Lib.Localization; +using Geekbot.Core.CommandPreconditions; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.Extensions; +using Geekbot.Core.GuildSettingsManager; +using Geekbot.Core.Localization; -namespace Geekbot.net.Commands.Admin +namespace Geekbot.Bot.Commands.Admin { [Group("admin")] [RequireUserPermission(GuildPermission.Administrator)] diff --git a/Geekbot.net/Commands/Admin/Mod.cs b/src/Bot/Commands/Admin/Mod.cs similarity index 87% rename from Geekbot.net/Commands/Admin/Mod.cs rename to src/Bot/Commands/Admin/Mod.cs index b0114a8..b642680 100644 --- a/Geekbot.net/Commands/Admin/Mod.cs +++ b/src/Bot/Commands/Admin/Mod.cs @@ -2,10 +2,10 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib.CommandPreconditions; -using Geekbot.net.Lib.ErrorHandling; +using Geekbot.Core.CommandPreconditions; +using Geekbot.Core.ErrorHandling; -namespace Geekbot.net.Commands.Admin +namespace Geekbot.Bot.Commands.Admin { [Group("mod")] [RequireUserPermission(GuildPermission.KickMembers)] diff --git a/Geekbot.net/Commands/Admin/Owner/Owner.cs b/src/Bot/Commands/Admin/Owner/Owner.cs similarity index 93% rename from Geekbot.net/Commands/Admin/Owner/Owner.cs rename to src/Bot/Commands/Admin/Owner/Owner.cs index 996d848..5fa3976 100644 --- a/Geekbot.net/Commands/Admin/Owner/Owner.cs +++ b/src/Bot/Commands/Admin/Owner/Owner.cs @@ -3,12 +3,12 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.WebSocket; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.GlobalSettings; -using Geekbot.net.Lib.Logger; -using Geekbot.net.Lib.UserRepository; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.GlobalSettings; +using Geekbot.Core.Logger; +using Geekbot.Core.UserRepository; -namespace Geekbot.net.Commands.Admin.Owner +namespace Geekbot.Bot.Commands.Admin.Owner { [Group("owner")] [RequireOwner] diff --git a/Geekbot.net/Commands/Admin/Role.cs b/src/Bot/Commands/Admin/Role.cs similarity index 96% rename from Geekbot.net/Commands/Admin/Role.cs rename to src/Bot/Commands/Admin/Role.cs index 6d4557d..e997fa8 100644 --- a/Geekbot.net/Commands/Admin/Role.cs +++ b/src/Bot/Commands/Admin/Role.cs @@ -5,15 +5,15 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.Net; -using Geekbot.net.Database; -using Geekbot.net.Database.Models; -using Geekbot.net.Lib.CommandPreconditions; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.Extensions; -using Geekbot.net.Lib.Localization; -using Geekbot.net.Lib.ReactionListener; +using Geekbot.Core.CommandPreconditions; +using Geekbot.Core.Database; +using Geekbot.Core.Database.Models; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.Extensions; +using Geekbot.Core.Localization; +using Geekbot.Core.ReactionListener; -namespace Geekbot.net.Commands.Admin +namespace Geekbot.Bot.Commands.Admin { [Group("role")] [DisableInDirectMessage] diff --git a/Geekbot.net/Commands/Games/Pokedex.cs b/src/Bot/Commands/Games/Pokedex.cs similarity index 93% rename from Geekbot.net/Commands/Games/Pokedex.cs rename to src/Bot/Commands/Games/Pokedex.cs index a0d2ae0..426761c 100644 --- a/Geekbot.net/Commands/Games/Pokedex.cs +++ b/src/Bot/Commands/Games/Pokedex.cs @@ -3,11 +3,11 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.Extensions; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.Extensions; using PokeAPI; -namespace Geekbot.net.Commands.Games +namespace Geekbot.Bot.Commands.Games { public class Pokedex : ModuleBase { diff --git a/Geekbot.net/Commands/Games/Roll/Roll.cs b/src/Bot/Commands/Games/Roll/Roll.cs similarity index 92% rename from Geekbot.net/Commands/Games/Roll/Roll.cs rename to src/Bot/Commands/Games/Roll/Roll.cs index 1c89f19..6241ba1 100644 --- a/Geekbot.net/Commands/Games/Roll/Roll.cs +++ b/src/Bot/Commands/Games/Roll/Roll.cs @@ -2,15 +2,15 @@ using System.Linq; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Database; -using Geekbot.net.Database.Models; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.Extensions; -using Geekbot.net.Lib.KvInMemoryStore; -using Geekbot.net.Lib.Localization; -using Geekbot.net.Lib.RandomNumberGenerator; +using Geekbot.Core.Database; +using Geekbot.Core.Database.Models; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.Extensions; +using Geekbot.Core.KvInMemoryStore; +using Geekbot.Core.Localization; +using Geekbot.Core.RandomNumberGenerator; -namespace Geekbot.net.Commands.Games.Roll +namespace Geekbot.Bot.Commands.Games.Roll { public class Roll : ModuleBase { diff --git a/Geekbot.net/Commands/Games/Roll/RollTimeout.cs b/src/Bot/Commands/Games/Roll/RollTimeout.cs similarity index 74% rename from Geekbot.net/Commands/Games/Roll/RollTimeout.cs rename to src/Bot/Commands/Games/Roll/RollTimeout.cs index 81a520f..c53101a 100644 --- a/Geekbot.net/Commands/Games/Roll/RollTimeout.cs +++ b/src/Bot/Commands/Games/Roll/RollTimeout.cs @@ -1,6 +1,6 @@ using System; -namespace Geekbot.net.Commands.Games.Roll +namespace Geekbot.Bot.Commands.Games.Roll { public class RollTimeout { diff --git a/Geekbot.net/Commands/Integrations/LolMmr/LolMmr.cs b/src/Bot/Commands/Integrations/LolMmr/LolMmr.cs similarity index 92% rename from Geekbot.net/Commands/Integrations/LolMmr/LolMmr.cs rename to src/Bot/Commands/Integrations/LolMmr/LolMmr.cs index 5de7d63..4e75034 100644 --- a/Geekbot.net/Commands/Integrations/LolMmr/LolMmr.cs +++ b/src/Bot/Commands/Integrations/LolMmr/LolMmr.cs @@ -5,10 +5,10 @@ using System.Text; using System.Threading.Tasks; using System.Web; using Discord.Commands; -using Geekbot.net.Lib; -using Geekbot.net.Lib.ErrorHandling; +using Geekbot.Core; +using Geekbot.Core.ErrorHandling; -namespace Geekbot.net.Commands.Integrations.LolMmr +namespace Geekbot.Bot.Commands.Integrations.LolMmr { public class LolMmr : ModuleBase { diff --git a/Geekbot.net/Commands/Integrations/LolMmr/LolMmrDto.cs b/src/Bot/Commands/Integrations/LolMmr/LolMmrDto.cs similarity index 76% rename from Geekbot.net/Commands/Integrations/LolMmr/LolMmrDto.cs rename to src/Bot/Commands/Integrations/LolMmr/LolMmrDto.cs index 4a9887d..51d4c85 100644 --- a/Geekbot.net/Commands/Integrations/LolMmr/LolMmrDto.cs +++ b/src/Bot/Commands/Integrations/LolMmr/LolMmrDto.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Commands.Integrations.LolMmr +namespace Geekbot.Bot.Commands.Integrations.LolMmr { public class LolMmrDto { diff --git a/Geekbot.net/Commands/Integrations/LolMmr/LolMrrInfoDto.cs b/src/Bot/Commands/Integrations/LolMmr/LolMrrInfoDto.cs similarity index 71% rename from Geekbot.net/Commands/Integrations/LolMmr/LolMrrInfoDto.cs rename to src/Bot/Commands/Integrations/LolMmr/LolMrrInfoDto.cs index 55804fd..18b096a 100644 --- a/Geekbot.net/Commands/Integrations/LolMmr/LolMrrInfoDto.cs +++ b/src/Bot/Commands/Integrations/LolMmr/LolMrrInfoDto.cs @@ -1,7 +1,6 @@ -using System; using Newtonsoft.Json; -namespace Geekbot.net.Commands.Integrations.LolMmr +namespace Geekbot.Bot.Commands.Integrations.LolMmr { public class LolMrrInfoDto { diff --git a/Geekbot.net/Commands/Integrations/MagicTheGathering.cs b/src/Bot/Commands/Integrations/MagicTheGathering.cs similarity index 93% rename from Geekbot.net/Commands/Integrations/MagicTheGathering.cs rename to src/Bot/Commands/Integrations/MagicTheGathering.cs index f9e006c..66a87fe 100644 --- a/Geekbot.net/Commands/Integrations/MagicTheGathering.cs +++ b/src/Bot/Commands/Integrations/MagicTheGathering.cs @@ -4,12 +4,12 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib.Converters; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.Extensions; +using Geekbot.Core.Converters; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.Extensions; using MtgApiManager.Lib.Service; -namespace Geekbot.net.Commands.Integrations +namespace Geekbot.Bot.Commands.Integrations { public class MagicTheGathering : ModuleBase { diff --git a/Geekbot.net/Commands/Integrations/Mal.cs b/src/Bot/Commands/Integrations/Mal.cs similarity index 94% rename from Geekbot.net/Commands/Integrations/Mal.cs rename to src/Bot/Commands/Integrations/Mal.cs index f8aeb95..ae30493 100644 --- a/Geekbot.net/Commands/Integrations/Mal.cs +++ b/src/Bot/Commands/Integrations/Mal.cs @@ -4,11 +4,11 @@ using System.Web; using System.Xml; using Discord; using Discord.Commands; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.Extensions; -using Geekbot.net.Lib.MalClient; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.Extensions; +using Geekbot.Core.MalClient; -namespace Geekbot.net.Commands.Integrations +namespace Geekbot.Bot.Commands.Integrations { public class Mal : ModuleBase { diff --git a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictListItemDto.cs b/src/Bot/Commands/Integrations/UbranDictionary/UrbanDictListItemDto.cs similarity index 81% rename from Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictListItemDto.cs rename to src/Bot/Commands/Integrations/UbranDictionary/UrbanDictListItemDto.cs index e98885b..0aee35f 100644 --- a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictListItemDto.cs +++ b/src/Bot/Commands/Integrations/UbranDictionary/UrbanDictListItemDto.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Commands.Integrations.UbranDictionary +namespace Geekbot.Bot.Commands.Integrations.UbranDictionary { internal class UrbanListItemDto { diff --git a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictResponseDto.cs b/src/Bot/Commands/Integrations/UbranDictionary/UrbanDictResponseDto.cs similarity index 73% rename from Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictResponseDto.cs rename to src/Bot/Commands/Integrations/UbranDictionary/UrbanDictResponseDto.cs index 2c3e014..1846601 100644 --- a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictResponseDto.cs +++ b/src/Bot/Commands/Integrations/UbranDictionary/UrbanDictResponseDto.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace Geekbot.net.Commands.Integrations.UbranDictionary +namespace Geekbot.Bot.Commands.Integrations.UbranDictionary { internal class UrbanResponseDto { diff --git a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs b/src/Bot/Commands/Integrations/UbranDictionary/UrbanDictionary.cs similarity index 91% rename from Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs rename to src/Bot/Commands/Integrations/UbranDictionary/UrbanDictionary.cs index 882caa5..bc1f478 100644 --- a/Geekbot.net/Commands/Integrations/UbranDictionary/UrbanDictionary.cs +++ b/src/Bot/Commands/Integrations/UbranDictionary/UrbanDictionary.cs @@ -3,11 +3,11 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.Extensions; +using Geekbot.Core; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.Extensions; -namespace Geekbot.net.Commands.Integrations.UbranDictionary +namespace Geekbot.Bot.Commands.Integrations.UbranDictionary { public class UrbanDictionary : ModuleBase { diff --git a/Geekbot.net/Commands/Integrations/Wikipedia.cs b/src/Bot/Commands/Integrations/Wikipedia.cs similarity index 92% rename from Geekbot.net/Commands/Integrations/Wikipedia.cs rename to src/Bot/Commands/Integrations/Wikipedia.cs index 93f68fd..709f974 100644 --- a/Geekbot.net/Commands/Integrations/Wikipedia.cs +++ b/src/Bot/Commands/Integrations/Wikipedia.cs @@ -5,14 +5,14 @@ using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Database; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.Extensions; -using Geekbot.net.Lib.WikipediaClient; -using Geekbot.net.Lib.WikipediaClient.Page; +using Geekbot.Core.Database; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.Extensions; +using Geekbot.Core.WikipediaClient; +using Geekbot.Core.WikipediaClient.Page; using HtmlAgilityPack; -namespace Geekbot.net.Commands.Integrations +namespace Geekbot.Bot.Commands.Integrations { public class Wikipedia : ModuleBase { diff --git a/Geekbot.net/Commands/Integrations/Youtube.cs b/src/Bot/Commands/Integrations/Youtube.cs similarity index 91% rename from Geekbot.net/Commands/Integrations/Youtube.cs rename to src/Bot/Commands/Integrations/Youtube.cs index 1672bab..60ebdaa 100644 --- a/Geekbot.net/Commands/Integrations/Youtube.cs +++ b/src/Bot/Commands/Integrations/Youtube.cs @@ -1,12 +1,12 @@ using System; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.GlobalSettings; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.GlobalSettings; using Google.Apis.Services; using Google.Apis.YouTube.v3; -namespace Geekbot.net.Commands.Integrations +namespace Geekbot.Bot.Commands.Integrations { public class Youtube : ModuleBase { diff --git a/Geekbot.net/Commands/Randomness/BenedictCumberbatchNameGenerator.cs b/src/Bot/Commands/Randomness/BenedictCumberbatchNameGenerator.cs similarity index 95% rename from Geekbot.net/Commands/Randomness/BenedictCumberbatchNameGenerator.cs rename to src/Bot/Commands/Randomness/BenedictCumberbatchNameGenerator.cs index 838dff2..995c921 100644 --- a/Geekbot.net/Commands/Randomness/BenedictCumberbatchNameGenerator.cs +++ b/src/Bot/Commands/Randomness/BenedictCumberbatchNameGenerator.cs @@ -2,10 +2,10 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.RandomNumberGenerator; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.RandomNumberGenerator; -namespace Geekbot.net.Commands.Randomness +namespace Geekbot.Bot.Commands.Randomness { public class BenedictCumberbatchNameGenerator : ModuleBase { diff --git a/Geekbot.net/Commands/Randomness/Cat/Cat.cs b/src/Bot/Commands/Randomness/Cat/Cat.cs similarity index 86% rename from Geekbot.net/Commands/Randomness/Cat/Cat.cs rename to src/Bot/Commands/Randomness/Cat/Cat.cs index 7cd7b19..7bd7e57 100644 --- a/Geekbot.net/Commands/Randomness/Cat/Cat.cs +++ b/src/Bot/Commands/Randomness/Cat/Cat.cs @@ -2,10 +2,10 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib; -using Geekbot.net.Lib.ErrorHandling; +using Geekbot.Core; +using Geekbot.Core.ErrorHandling; -namespace Geekbot.net.Commands.Randomness.Cat +namespace Geekbot.Bot.Commands.Randomness.Cat { public class Cat : ModuleBase { diff --git a/Geekbot.net/Commands/Randomness/Cat/CatResponseDto.cs b/src/Bot/Commands/Randomness/Cat/CatResponseDto.cs similarity index 62% rename from Geekbot.net/Commands/Randomness/Cat/CatResponseDto.cs rename to src/Bot/Commands/Randomness/Cat/CatResponseDto.cs index 05ebf2b..febb66f 100644 --- a/Geekbot.net/Commands/Randomness/Cat/CatResponseDto.cs +++ b/src/Bot/Commands/Randomness/Cat/CatResponseDto.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Commands.Randomness.Cat +namespace Geekbot.Bot.Commands.Randomness.Cat { internal class CatResponseDto { diff --git a/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokeResponseDto.cs b/src/Bot/Commands/Randomness/Chuck/ChuckNorrisJokeResponseDto.cs similarity index 64% rename from Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokeResponseDto.cs rename to src/Bot/Commands/Randomness/Chuck/ChuckNorrisJokeResponseDto.cs index 8d513b8..99d9493 100644 --- a/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokeResponseDto.cs +++ b/src/Bot/Commands/Randomness/Chuck/ChuckNorrisJokeResponseDto.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Commands.Randomness.Chuck +namespace Geekbot.Bot.Commands.Randomness.Chuck { internal class ChuckNorrisJokeResponseDto { diff --git a/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs b/src/Bot/Commands/Randomness/Chuck/ChuckNorrisJokes.cs similarity index 87% rename from Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs rename to src/Bot/Commands/Randomness/Chuck/ChuckNorrisJokes.cs index 95dcfd4..be328b4 100644 --- a/Geekbot.net/Commands/Randomness/Chuck/ChuckNorrisJokes.cs +++ b/src/Bot/Commands/Randomness/Chuck/ChuckNorrisJokes.cs @@ -2,10 +2,10 @@ using System.Net.Http; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib; -using Geekbot.net.Lib.ErrorHandling; +using Geekbot.Core; +using Geekbot.Core.ErrorHandling; -namespace Geekbot.net.Commands.Randomness.Chuck +namespace Geekbot.Bot.Commands.Randomness.Chuck { public class ChuckNorrisJokes : ModuleBase { diff --git a/Geekbot.net/Commands/Randomness/Dad/DadJokeResponseDto.cs b/src/Bot/Commands/Randomness/Dad/DadJokeResponseDto.cs similarity index 63% rename from Geekbot.net/Commands/Randomness/Dad/DadJokeResponseDto.cs rename to src/Bot/Commands/Randomness/Dad/DadJokeResponseDto.cs index 262eee9..2d72bdd 100644 --- a/Geekbot.net/Commands/Randomness/Dad/DadJokeResponseDto.cs +++ b/src/Bot/Commands/Randomness/Dad/DadJokeResponseDto.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Commands.Randomness.Dad +namespace Geekbot.Bot.Commands.Randomness.Dad { internal class DadJokeResponseDto { diff --git a/Geekbot.net/Commands/Randomness/Dad/DadJokes.cs b/src/Bot/Commands/Randomness/Dad/DadJokes.cs similarity index 85% rename from Geekbot.net/Commands/Randomness/Dad/DadJokes.cs rename to src/Bot/Commands/Randomness/Dad/DadJokes.cs index 7aabff3..136650c 100644 --- a/Geekbot.net/Commands/Randomness/Dad/DadJokes.cs +++ b/src/Bot/Commands/Randomness/Dad/DadJokes.cs @@ -1,10 +1,10 @@ using System; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib; -using Geekbot.net.Lib.ErrorHandling; +using Geekbot.Core; +using Geekbot.Core.ErrorHandling; -namespace Geekbot.net.Commands.Randomness.Dad +namespace Geekbot.Bot.Commands.Randomness.Dad { public class DadJokes : ModuleBase { diff --git a/Geekbot.net/Commands/Randomness/Dog/Dog.cs b/src/Bot/Commands/Randomness/Dog/Dog.cs similarity index 86% rename from Geekbot.net/Commands/Randomness/Dog/Dog.cs rename to src/Bot/Commands/Randomness/Dog/Dog.cs index b3d603b..2a8a3f1 100644 --- a/Geekbot.net/Commands/Randomness/Dog/Dog.cs +++ b/src/Bot/Commands/Randomness/Dog/Dog.cs @@ -2,10 +2,10 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib; -using Geekbot.net.Lib.ErrorHandling; +using Geekbot.Core; +using Geekbot.Core.ErrorHandling; -namespace Geekbot.net.Commands.Randomness.Dog +namespace Geekbot.Bot.Commands.Randomness.Dog { public class Dog : ModuleBase { diff --git a/Geekbot.net/Commands/Randomness/Dog/DogResponseDto.cs b/src/Bot/Commands/Randomness/Dog/DogResponseDto.cs similarity index 61% rename from Geekbot.net/Commands/Randomness/Dog/DogResponseDto.cs rename to src/Bot/Commands/Randomness/Dog/DogResponseDto.cs index 1fc1a82..473c1ce 100644 --- a/Geekbot.net/Commands/Randomness/Dog/DogResponseDto.cs +++ b/src/Bot/Commands/Randomness/Dog/DogResponseDto.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Commands.Randomness.Dog +namespace Geekbot.Bot.Commands.Randomness.Dog { internal class DogResponseDto { diff --git a/Geekbot.net/Commands/Randomness/EightBall.cs b/src/Bot/Commands/Randomness/EightBall.cs similarity index 95% rename from Geekbot.net/Commands/Randomness/EightBall.cs rename to src/Bot/Commands/Randomness/EightBall.cs index d07451d..e1a3a71 100644 --- a/Geekbot.net/Commands/Randomness/EightBall.cs +++ b/src/Bot/Commands/Randomness/EightBall.cs @@ -2,9 +2,9 @@ using System.Collections.Generic; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib.ErrorHandling; +using Geekbot.Core.ErrorHandling; -namespace Geekbot.net.Commands.Randomness +namespace Geekbot.Bot.Commands.Randomness { public class EightBall : ModuleBase { diff --git a/Geekbot.net/Commands/Randomness/Fortune.cs b/src/Bot/Commands/Randomness/Fortune.cs similarity index 83% rename from Geekbot.net/Commands/Randomness/Fortune.cs rename to src/Bot/Commands/Randomness/Fortune.cs index d4f6b5f..cc31536 100644 --- a/Geekbot.net/Commands/Randomness/Fortune.cs +++ b/src/Bot/Commands/Randomness/Fortune.cs @@ -1,8 +1,8 @@ using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib.Media; +using Geekbot.Core.Media; -namespace Geekbot.net.Commands.Randomness +namespace Geekbot.Bot.Commands.Randomness { public class Fortune : ModuleBase { diff --git a/Geekbot.net/Commands/Randomness/Gdq.cs b/src/Bot/Commands/Randomness/Gdq.cs similarity index 88% rename from Geekbot.net/Commands/Randomness/Gdq.cs rename to src/Bot/Commands/Randomness/Gdq.cs index 4c16bed..c6d9fa8 100644 --- a/Geekbot.net/Commands/Randomness/Gdq.cs +++ b/src/Bot/Commands/Randomness/Gdq.cs @@ -2,9 +2,9 @@ using System.Net; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib.ErrorHandling; +using Geekbot.Core.ErrorHandling; -namespace Geekbot.net.Commands.Randomness +namespace Geekbot.Bot.Commands.Randomness { public class Gdq : ModuleBase { diff --git a/Geekbot.net/Commands/Randomness/Greetings/GreetingBaseDto.cs b/src/Bot/Commands/Randomness/Greetings/GreetingBaseDto.cs similarity index 84% rename from Geekbot.net/Commands/Randomness/Greetings/GreetingBaseDto.cs rename to src/Bot/Commands/Randomness/Greetings/GreetingBaseDto.cs index 7f4e02f..ae0274b 100644 --- a/Geekbot.net/Commands/Randomness/Greetings/GreetingBaseDto.cs +++ b/src/Bot/Commands/Randomness/Greetings/GreetingBaseDto.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Commands.Randomness.Greetings +namespace Geekbot.Bot.Commands.Randomness.Greetings { public class GreetingBaseDto { diff --git a/Geekbot.net/Commands/Randomness/Greetings/GreetingDto.cs b/src/Bot/Commands/Randomness/Greetings/GreetingDto.cs similarity index 80% rename from Geekbot.net/Commands/Randomness/Greetings/GreetingDto.cs rename to src/Bot/Commands/Randomness/Greetings/GreetingDto.cs index c967885..679e544 100644 --- a/Geekbot.net/Commands/Randomness/Greetings/GreetingDto.cs +++ b/src/Bot/Commands/Randomness/Greetings/GreetingDto.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Commands.Randomness.Greetings +namespace Geekbot.Bot.Commands.Randomness.Greetings { public class GreetingDto { diff --git a/Geekbot.net/Commands/Randomness/Greetings/Greetings.cs b/src/Bot/Commands/Randomness/Greetings/Greetings.cs similarity index 90% rename from Geekbot.net/Commands/Randomness/Greetings/Greetings.cs rename to src/Bot/Commands/Randomness/Greetings/Greetings.cs index 85e9152..cd69010 100644 --- a/Geekbot.net/Commands/Randomness/Greetings/Greetings.cs +++ b/src/Bot/Commands/Randomness/Greetings/Greetings.cs @@ -2,11 +2,11 @@ using System; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.Extensions; +using Geekbot.Core; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.Extensions; -namespace Geekbot.net.Commands.Randomness.Greetings +namespace Geekbot.Bot.Commands.Randomness.Greetings { public class Greetings : ModuleBase { diff --git a/Geekbot.net/Commands/Randomness/Kanye/Kanye.cs b/src/Bot/Commands/Randomness/Kanye/Kanye.cs similarity index 87% rename from Geekbot.net/Commands/Randomness/Kanye/Kanye.cs rename to src/Bot/Commands/Randomness/Kanye/Kanye.cs index 2aca31d..6ad67cb 100644 --- a/Geekbot.net/Commands/Randomness/Kanye/Kanye.cs +++ b/src/Bot/Commands/Randomness/Kanye/Kanye.cs @@ -1,10 +1,10 @@ using System; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib; -using Geekbot.net.Lib.ErrorHandling; +using Geekbot.Core; +using Geekbot.Core.ErrorHandling; -namespace Geekbot.net.Commands.Randomness.Kanye +namespace Geekbot.Bot.Commands.Randomness.Kanye { public class Kanye : ModuleBase { diff --git a/Geekbot.net/Commands/Randomness/Kanye/KanyeResponseDto.cs b/src/Bot/Commands/Randomness/Kanye/KanyeResponseDto.cs similarity index 73% rename from Geekbot.net/Commands/Randomness/Kanye/KanyeResponseDto.cs rename to src/Bot/Commands/Randomness/Kanye/KanyeResponseDto.cs index ff74f37..8ca248e 100644 --- a/Geekbot.net/Commands/Randomness/Kanye/KanyeResponseDto.cs +++ b/src/Bot/Commands/Randomness/Kanye/KanyeResponseDto.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Commands.Randomness.Kanye +namespace Geekbot.Bot.Commands.Randomness.Kanye { public class KanyeResponseDto { diff --git a/Geekbot.net/Commands/Randomness/RandomAnimals.cs b/src/Bot/Commands/Randomness/RandomAnimals.cs similarity index 97% rename from Geekbot.net/Commands/Randomness/RandomAnimals.cs rename to src/Bot/Commands/Randomness/RandomAnimals.cs index 47b6ea6..b9c1bdd 100644 --- a/Geekbot.net/Commands/Randomness/RandomAnimals.cs +++ b/src/Bot/Commands/Randomness/RandomAnimals.cs @@ -1,9 +1,9 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib.Media; +using Geekbot.Core.Media; -namespace Geekbot.net.Commands.Randomness +namespace Geekbot.Bot.Commands.Randomness { public class RandomAnimals : ModuleBase { diff --git a/Geekbot.net/Commands/Randomness/Ship.cs b/src/Bot/Commands/Randomness/Ship.cs similarity index 91% rename from Geekbot.net/Commands/Randomness/Ship.cs rename to src/Bot/Commands/Randomness/Ship.cs index d5386d4..d5d9eea 100644 --- a/Geekbot.net/Commands/Randomness/Ship.cs +++ b/src/Bot/Commands/Randomness/Ship.cs @@ -3,14 +3,14 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Database; -using Geekbot.net.Database.Models; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.Extensions; -using Geekbot.net.Lib.Localization; -using Geekbot.net.Lib.RandomNumberGenerator; +using Geekbot.Core.Database; +using Geekbot.Core.Database.Models; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.Extensions; +using Geekbot.Core.Localization; +using Geekbot.Core.RandomNumberGenerator; -namespace Geekbot.net.Commands.Randomness +namespace Geekbot.Bot.Commands.Randomness { public class Ship : ModuleBase { diff --git a/Geekbot.net/Commands/Randomness/Slap.cs b/src/Bot/Commands/Randomness/Slap.cs similarity index 93% rename from Geekbot.net/Commands/Randomness/Slap.cs rename to src/Bot/Commands/Randomness/Slap.cs index 20e83c3..b512e73 100644 --- a/Geekbot.net/Commands/Randomness/Slap.cs +++ b/src/Bot/Commands/Randomness/Slap.cs @@ -4,12 +4,12 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Database; -using Geekbot.net.Database.Models; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.Extensions; +using Geekbot.Core.Database; +using Geekbot.Core.Database.Models; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.Extensions; -namespace Geekbot.net.Commands.Randomness +namespace Geekbot.Bot.Commands.Randomness { public class Slap : ModuleBase { diff --git a/Geekbot.net/Commands/Rpg/Cookies.cs b/src/Bot/Commands/Rpg/Cookies.cs similarity index 92% rename from Geekbot.net/Commands/Rpg/Cookies.cs rename to src/Bot/Commands/Rpg/Cookies.cs index b1a2d7d..f581105 100644 --- a/Geekbot.net/Commands/Rpg/Cookies.cs +++ b/src/Bot/Commands/Rpg/Cookies.cs @@ -3,15 +3,15 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Database; -using Geekbot.net.Database.Models; -using Geekbot.net.Lib.CommandPreconditions; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.Extensions; -using Geekbot.net.Lib.Localization; -using Geekbot.net.Lib.RandomNumberGenerator; +using Geekbot.Core.CommandPreconditions; +using Geekbot.Core.Database; +using Geekbot.Core.Database.Models; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.Extensions; +using Geekbot.Core.Localization; +using Geekbot.Core.RandomNumberGenerator; -namespace Geekbot.net.Commands.Rpg +namespace Geekbot.Bot.Commands.Rpg { [DisableInDirectMessage] [Group("cookies")] diff --git a/Geekbot.net/Commands/User/GuildInfo.cs b/src/Bot/Commands/User/GuildInfo.cs similarity index 87% rename from Geekbot.net/Commands/User/GuildInfo.cs rename to src/Bot/Commands/User/GuildInfo.cs index 6c8b941..c596186 100644 --- a/Geekbot.net/Commands/User/GuildInfo.cs +++ b/src/Bot/Commands/User/GuildInfo.cs @@ -3,13 +3,13 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Database; -using Geekbot.net.Lib.CommandPreconditions; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.Extensions; -using Geekbot.net.Lib.Levels; +using Geekbot.Core.CommandPreconditions; +using Geekbot.Core.Database; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.Extensions; +using Geekbot.Core.Levels; -namespace Geekbot.net.Commands.User +namespace Geekbot.Bot.Commands.User { public class GuildInfo : ModuleBase { diff --git a/Geekbot.net/Commands/User/Karma.cs b/src/Bot/Commands/User/Karma.cs similarity index 95% rename from Geekbot.net/Commands/User/Karma.cs rename to src/Bot/Commands/User/Karma.cs index bf85c91..3efc381 100644 --- a/Geekbot.net/Commands/User/Karma.cs +++ b/src/Bot/Commands/User/Karma.cs @@ -3,14 +3,14 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Database; -using Geekbot.net.Database.Models; -using Geekbot.net.Lib.CommandPreconditions; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.Extensions; -using Geekbot.net.Lib.Localization; +using Geekbot.Core.CommandPreconditions; +using Geekbot.Core.Database; +using Geekbot.Core.Database.Models; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.Extensions; +using Geekbot.Core.Localization; -namespace Geekbot.net.Commands.User +namespace Geekbot.Bot.Commands.User { [DisableInDirectMessage] public class Karma : ModuleBase diff --git a/Geekbot.net/Commands/User/Ranking/Rank.cs b/src/Bot/Commands/User/Ranking/Rank.cs similarity index 90% rename from Geekbot.net/Commands/User/Ranking/Rank.cs rename to src/Bot/Commands/User/Ranking/Rank.cs index 9021b4e..ae1bec9 100644 --- a/Geekbot.net/Commands/User/Ranking/Rank.cs +++ b/src/Bot/Commands/User/Ranking/Rank.cs @@ -4,16 +4,16 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Database; -using Geekbot.net.Lib.CommandPreconditions; -using Geekbot.net.Lib.Converters; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.Extensions; -using Geekbot.net.Lib.Highscores; -using Geekbot.net.Lib.Localization; -using Geekbot.net.Lib.UserRepository; +using Geekbot.Core.CommandPreconditions; +using Geekbot.Core.Converters; +using Geekbot.Core.Database; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.Extensions; +using Geekbot.Core.Highscores; +using Geekbot.Core.Localization; +using Geekbot.Core.UserRepository; -namespace Geekbot.net.Commands.User.Ranking +namespace Geekbot.Bot.Commands.User.Ranking { public class Rank : ModuleBase { diff --git a/Geekbot.net/Commands/User/Stats.cs b/src/Bot/Commands/User/Stats.cs similarity index 94% rename from Geekbot.net/Commands/User/Stats.cs rename to src/Bot/Commands/User/Stats.cs index 08b69d2..70f6247 100644 --- a/Geekbot.net/Commands/User/Stats.cs +++ b/src/Bot/Commands/User/Stats.cs @@ -3,13 +3,13 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Database; -using Geekbot.net.Lib.CommandPreconditions; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.Extensions; -using Geekbot.net.Lib.Levels; +using Geekbot.Core.CommandPreconditions; +using Geekbot.Core.Database; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.Extensions; +using Geekbot.Core.Levels; -namespace Geekbot.net.Commands.User +namespace Geekbot.Bot.Commands.User { public class Stats : ModuleBase { diff --git a/Geekbot.net/Commands/Utils/AvatarGetter.cs b/src/Bot/Commands/Utils/AvatarGetter.cs similarity index 88% rename from Geekbot.net/Commands/Utils/AvatarGetter.cs rename to src/Bot/Commands/Utils/AvatarGetter.cs index 142b3e3..6585a75 100644 --- a/Geekbot.net/Commands/Utils/AvatarGetter.cs +++ b/src/Bot/Commands/Utils/AvatarGetter.cs @@ -2,9 +2,9 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib.ErrorHandling; +using Geekbot.Core.ErrorHandling; -namespace Geekbot.net.Commands.Utils +namespace Geekbot.Bot.Commands.Utils { public class AvatarGetter : ModuleBase { diff --git a/Geekbot.net/Commands/Utils/Changelog/Changelog.cs b/src/Bot/Commands/Utils/Changelog/Changelog.cs similarity index 92% rename from Geekbot.net/Commands/Utils/Changelog/Changelog.cs rename to src/Bot/Commands/Utils/Changelog/Changelog.cs index c217619..92d5ddd 100644 --- a/Geekbot.net/Commands/Utils/Changelog/Changelog.cs +++ b/src/Bot/Commands/Utils/Changelog/Changelog.cs @@ -6,10 +6,10 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.WebSocket; -using Geekbot.net.Lib; -using Geekbot.net.Lib.ErrorHandling; +using Geekbot.Core; +using Geekbot.Core.ErrorHandling; -namespace Geekbot.net.Commands.Utils.Changelog +namespace Geekbot.Bot.Commands.Utils.Changelog { public class Changelog : ModuleBase { diff --git a/Geekbot.net/Commands/Utils/Changelog/CommitAuthorDto.cs b/src/Bot/Commands/Utils/Changelog/CommitAuthorDto.cs similarity index 77% rename from Geekbot.net/Commands/Utils/Changelog/CommitAuthorDto.cs rename to src/Bot/Commands/Utils/Changelog/CommitAuthorDto.cs index 8debd77..7cabece 100644 --- a/Geekbot.net/Commands/Utils/Changelog/CommitAuthorDto.cs +++ b/src/Bot/Commands/Utils/Changelog/CommitAuthorDto.cs @@ -1,6 +1,6 @@ using System; -namespace Geekbot.net.Commands.Utils.Changelog +namespace Geekbot.Bot.Commands.Utils.Changelog { public class CommitAuthorDto { diff --git a/Geekbot.net/Commands/Utils/Changelog/CommitDto.cs b/src/Bot/Commands/Utils/Changelog/CommitDto.cs similarity index 62% rename from Geekbot.net/Commands/Utils/Changelog/CommitDto.cs rename to src/Bot/Commands/Utils/Changelog/CommitDto.cs index 3379697..a534730 100644 --- a/Geekbot.net/Commands/Utils/Changelog/CommitDto.cs +++ b/src/Bot/Commands/Utils/Changelog/CommitDto.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Commands.Utils.Changelog +namespace Geekbot.Bot.Commands.Utils.Changelog { public class CommitDto { diff --git a/Geekbot.net/Commands/Utils/Changelog/CommitInfoDto.cs b/src/Bot/Commands/Utils/Changelog/CommitInfoDto.cs similarity index 71% rename from Geekbot.net/Commands/Utils/Changelog/CommitInfoDto.cs rename to src/Bot/Commands/Utils/Changelog/CommitInfoDto.cs index 9008343..d6f806e 100644 --- a/Geekbot.net/Commands/Utils/Changelog/CommitInfoDto.cs +++ b/src/Bot/Commands/Utils/Changelog/CommitInfoDto.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Commands.Utils.Changelog +namespace Geekbot.Bot.Commands.Utils.Changelog { public class CommitInfoDto { diff --git a/Geekbot.net/Commands/Utils/Choose.cs b/src/Bot/Commands/Utils/Choose.cs similarity index 88% rename from Geekbot.net/Commands/Utils/Choose.cs rename to src/Bot/Commands/Utils/Choose.cs index 62069bd..d245bd2 100644 --- a/Geekbot.net/Commands/Utils/Choose.cs +++ b/src/Bot/Commands/Utils/Choose.cs @@ -1,10 +1,10 @@ using System; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.Localization; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.Localization; -namespace Geekbot.net.Commands.Utils +namespace Geekbot.Bot.Commands.Utils { public class Choose : ModuleBase { diff --git a/Geekbot.net/Commands/Utils/Corona/CoronaStats.cs b/src/Bot/Commands/Utils/Corona/CoronaStats.cs similarity index 94% rename from Geekbot.net/Commands/Utils/Corona/CoronaStats.cs rename to src/Bot/Commands/Utils/Corona/CoronaStats.cs index 4be8195..3f9f3ea 100644 --- a/Geekbot.net/Commands/Utils/Corona/CoronaStats.cs +++ b/src/Bot/Commands/Utils/Corona/CoronaStats.cs @@ -1,13 +1,12 @@ using System; -using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.Extensions; +using Geekbot.Core; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.Extensions; -namespace Geekbot.net.Commands.Utils.Corona +namespace Geekbot.Bot.Commands.Utils.Corona { public class CoronaStats : ModuleBase { diff --git a/Geekbot.net/Commands/Utils/Corona/CoronaSummaryDto.cs b/src/Bot/Commands/Utils/Corona/CoronaSummaryDto.cs similarity index 82% rename from Geekbot.net/Commands/Utils/Corona/CoronaSummaryDto.cs rename to src/Bot/Commands/Utils/Corona/CoronaSummaryDto.cs index 5639249..3f6a820 100644 --- a/Geekbot.net/Commands/Utils/Corona/CoronaSummaryDto.cs +++ b/src/Bot/Commands/Utils/Corona/CoronaSummaryDto.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Commands.Utils.Corona +namespace Geekbot.Bot.Commands.Utils.Corona { public class CoronaSummaryDto { diff --git a/Geekbot.net/Commands/Utils/Dice.cs b/src/Bot/Commands/Utils/Dice.cs similarity index 97% rename from Geekbot.net/Commands/Utils/Dice.cs rename to src/Bot/Commands/Utils/Dice.cs index 2cd2e19..0668493 100644 --- a/Geekbot.net/Commands/Utils/Dice.cs +++ b/src/Bot/Commands/Utils/Dice.cs @@ -3,10 +3,10 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib.DiceParser; -using Geekbot.net.Lib.ErrorHandling; +using Geekbot.Core.DiceParser; +using Geekbot.Core.ErrorHandling; -namespace Geekbot.net.Commands.Utils +namespace Geekbot.Bot.Commands.Utils { public class Dice : ModuleBase { diff --git a/Geekbot.net/Commands/Utils/Emojify.cs b/src/Bot/Commands/Utils/Emojify.cs similarity index 88% rename from Geekbot.net/Commands/Utils/Emojify.cs rename to src/Bot/Commands/Utils/Emojify.cs index 5355aff..c8328ee 100644 --- a/Geekbot.net/Commands/Utils/Emojify.cs +++ b/src/Bot/Commands/Utils/Emojify.cs @@ -1,10 +1,10 @@ using System; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib.Converters; -using Geekbot.net.Lib.ErrorHandling; +using Geekbot.Core.Converters; +using Geekbot.Core.ErrorHandling; -namespace Geekbot.net.Commands.Utils +namespace Geekbot.Bot.Commands.Utils { public class Emojify : ModuleBase { diff --git a/Geekbot.net/Commands/Utils/Help.cs b/src/Bot/Commands/Utils/Help.cs similarity index 93% rename from Geekbot.net/Commands/Utils/Help.cs rename to src/Bot/Commands/Utils/Help.cs index a6f0084..58630fe 100644 --- a/Geekbot.net/Commands/Utils/Help.cs +++ b/src/Bot/Commands/Utils/Help.cs @@ -3,9 +3,9 @@ using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Lib.ErrorHandling; +using Geekbot.Core.ErrorHandling; -namespace Geekbot.net.Commands.Utils +namespace Geekbot.Bot.Commands.Utils { public class Help : ModuleBase { diff --git a/Geekbot.net/Commands/Utils/Info.cs b/src/Bot/Commands/Utils/Info.cs similarity index 92% rename from Geekbot.net/Commands/Utils/Info.cs rename to src/Bot/Commands/Utils/Info.cs index b1d5403..663dd07 100644 --- a/Geekbot.net/Commands/Utils/Info.cs +++ b/src/Bot/Commands/Utils/Info.cs @@ -5,11 +5,11 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.WebSocket; -using Geekbot.net.Lib; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.Extensions; +using Geekbot.Core; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.Extensions; -namespace Geekbot.net.Commands.Utils +namespace Geekbot.Bot.Commands.Utils { public class Info : ModuleBase { diff --git a/Geekbot.net/Commands/Utils/Lmgtfy.cs b/src/Bot/Commands/Utils/Lmgtfy.cs similarity index 92% rename from Geekbot.net/Commands/Utils/Lmgtfy.cs rename to src/Bot/Commands/Utils/Lmgtfy.cs index 9976dad..6063cf9 100644 --- a/Geekbot.net/Commands/Utils/Lmgtfy.cs +++ b/src/Bot/Commands/Utils/Lmgtfy.cs @@ -2,9 +2,9 @@ using System; using System.Threading.Tasks; using System.Web; using Discord.Commands; -using Geekbot.net.Lib.ErrorHandling; +using Geekbot.Core.ErrorHandling; -namespace Geekbot.net.Commands.Utils +namespace Geekbot.Bot.Commands.Utils { public class Lmgtfy : ModuleBase { diff --git a/Geekbot.net/Commands/Utils/Ping.cs b/src/Bot/Commands/Utils/Ping.cs similarity index 89% rename from Geekbot.net/Commands/Utils/Ping.cs rename to src/Bot/Commands/Utils/Ping.cs index 18cf9cb..d4faa53 100644 --- a/Geekbot.net/Commands/Utils/Ping.cs +++ b/src/Bot/Commands/Utils/Ping.cs @@ -1,7 +1,7 @@ using System.Threading.Tasks; using Discord.Commands; -namespace Geekbot.net.Commands.Utils +namespace Geekbot.Bot.Commands.Utils { public class Ping : ModuleBase { diff --git a/Geekbot.net/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs similarity index 97% rename from Geekbot.net/Commands/Utils/Quote/Quote.cs rename to src/Bot/Commands/Utils/Quote/Quote.cs index 7af8a4c..4022753 100644 --- a/Geekbot.net/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -3,16 +3,16 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; -using Geekbot.net.Database; -using Geekbot.net.Database.Models; -using Geekbot.net.Lib.CommandPreconditions; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.Extensions; -using Geekbot.net.Lib.Localization; -using Geekbot.net.Lib.Polyfills; -using Geekbot.net.Lib.RandomNumberGenerator; +using Geekbot.Core.CommandPreconditions; +using Geekbot.Core.Database; +using Geekbot.Core.Database.Models; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.Extensions; +using Geekbot.Core.Localization; +using Geekbot.Core.Polyfills; +using Geekbot.Core.RandomNumberGenerator; -namespace Geekbot.net.Commands.Utils.Quote +namespace Geekbot.Bot.Commands.Utils.Quote { [Group("quote")] [DisableInDirectMessage] diff --git a/Geekbot.net/Commands/Utils/Quote/QuoteObjectDto.cs b/src/Bot/Commands/Utils/Quote/QuoteObjectDto.cs similarity index 81% rename from Geekbot.net/Commands/Utils/Quote/QuoteObjectDto.cs rename to src/Bot/Commands/Utils/Quote/QuoteObjectDto.cs index a37ff76..32b65cf 100644 --- a/Geekbot.net/Commands/Utils/Quote/QuoteObjectDto.cs +++ b/src/Bot/Commands/Utils/Quote/QuoteObjectDto.cs @@ -1,6 +1,6 @@ using System; -namespace Geekbot.net.Commands.Utils.Quote +namespace Geekbot.Bot.Commands.Utils.Quote { internal class QuoteObjectDto { diff --git a/Geekbot.net/Handlers/CommandHandler.cs b/src/Bot/Handlers/CommandHandler.cs similarity index 96% rename from Geekbot.net/Handlers/CommandHandler.cs rename to src/Bot/Handlers/CommandHandler.cs index b6a3d9f..52e9a52 100644 --- a/Geekbot.net/Handlers/CommandHandler.cs +++ b/src/Bot/Handlers/CommandHandler.cs @@ -5,12 +5,12 @@ using Discord; using Discord.Commands; using Discord.Rest; using Discord.WebSocket; -using Geekbot.net.Database; -using Geekbot.net.Database.Models; -using Geekbot.net.Lib.GuildSettingsManager; -using Geekbot.net.Lib.Logger; +using Geekbot.Core.Database; +using Geekbot.Core.Database.Models; +using Geekbot.Core.GuildSettingsManager; +using Geekbot.Core.Logger; -namespace Geekbot.net.Handlers +namespace Geekbot.Bot.Handlers { public class CommandHandler { diff --git a/Geekbot.net/Handlers/MessageDeletedHandler.cs b/src/Bot/Handlers/MessageDeletedHandler.cs similarity index 93% rename from Geekbot.net/Handlers/MessageDeletedHandler.cs rename to src/Bot/Handlers/MessageDeletedHandler.cs index 5595cff..d0377f7 100644 --- a/Geekbot.net/Handlers/MessageDeletedHandler.cs +++ b/src/Bot/Handlers/MessageDeletedHandler.cs @@ -4,11 +4,11 @@ using System.Text; using System.Threading.Tasks; using Discord; using Discord.WebSocket; -using Geekbot.net.Database; -using Geekbot.net.Lib.Extensions; -using Geekbot.net.Lib.Logger; +using Geekbot.Core.Database; +using Geekbot.Core.Extensions; +using Geekbot.Core.Logger; -namespace Geekbot.net.Handlers +namespace Geekbot.Bot.Handlers { public class MessageDeletedHandler { diff --git a/Geekbot.net/Handlers/ReactionHandler.cs b/src/Bot/Handlers/ReactionHandler.cs similarity index 94% rename from Geekbot.net/Handlers/ReactionHandler.cs rename to src/Bot/Handlers/ReactionHandler.cs index e2355a8..66af3e8 100644 --- a/Geekbot.net/Handlers/ReactionHandler.cs +++ b/src/Bot/Handlers/ReactionHandler.cs @@ -1,9 +1,9 @@ using System.Threading.Tasks; using Discord; using Discord.WebSocket; -using Geekbot.net.Lib.ReactionListener; +using Geekbot.Core.ReactionListener; -namespace Geekbot.net.Handlers +namespace Geekbot.Bot.Handlers { public class ReactionHandler { diff --git a/Geekbot.net/Handlers/StatsHandler.cs b/src/Bot/Handlers/StatsHandler.cs similarity index 92% rename from Geekbot.net/Handlers/StatsHandler.cs rename to src/Bot/Handlers/StatsHandler.cs index 56c0894..197bbb8 100644 --- a/Geekbot.net/Handlers/StatsHandler.cs +++ b/src/Bot/Handlers/StatsHandler.cs @@ -1,13 +1,13 @@ using System; using System.Threading.Tasks; using Discord.WebSocket; -using Geekbot.net.Database; -using Geekbot.net.Database.Models; -using Geekbot.net.Lib.Extensions; -using Geekbot.net.Lib.Logger; +using Geekbot.Core.Database; +using Geekbot.Core.Database.Models; +using Geekbot.Core.Extensions; +using Geekbot.Core.Logger; using Microsoft.EntityFrameworkCore; -namespace Geekbot.net.Handlers +namespace Geekbot.Bot.Handlers { public class StatsHandler { diff --git a/Geekbot.net/Handlers/UserHandler.cs b/src/Bot/Handlers/UserHandler.cs similarity index 95% rename from Geekbot.net/Handlers/UserHandler.cs rename to src/Bot/Handlers/UserHandler.cs index fb26d70..a22d0e1 100644 --- a/Geekbot.net/Handlers/UserHandler.cs +++ b/src/Bot/Handlers/UserHandler.cs @@ -4,12 +4,12 @@ using System.Threading.Tasks; using Discord; using Discord.Rest; using Discord.WebSocket; -using Geekbot.net.Database; -using Geekbot.net.Lib.Extensions; -using Geekbot.net.Lib.Logger; -using Geekbot.net.Lib.UserRepository; +using Geekbot.Core.Database; +using Geekbot.Core.Extensions; +using Geekbot.Core.Logger; +using Geekbot.Core.UserRepository; -namespace Geekbot.net.Handlers +namespace Geekbot.Bot.Handlers { public class UserHandler { diff --git a/Geekbot.net/Logs/.keep b/src/Bot/Logs/.keep old mode 100755 new mode 100644 similarity index 100% rename from Geekbot.net/Logs/.keep rename to src/Bot/Logs/.keep diff --git a/Geekbot.net/Program.cs b/src/Bot/Program.cs old mode 100755 new mode 100644 similarity index 91% rename from Geekbot.net/Program.cs rename to src/Bot/Program.cs index c55f390..04b1450 --- a/Geekbot.net/Program.cs +++ b/src/Bot/Program.cs @@ -6,30 +6,30 @@ using CommandLine; using Discord; using Discord.Commands; using Discord.WebSocket; -using Geekbot.net.Database; -using Geekbot.net.Handlers; -using Geekbot.net.Lib; -using Geekbot.net.Lib.Converters; -using Geekbot.net.Lib.DiceParser; -using Geekbot.net.Lib.ErrorHandling; -using Geekbot.net.Lib.GlobalSettings; -using Geekbot.net.Lib.GuildSettingsManager; -using Geekbot.net.Lib.Highscores; -using Geekbot.net.Lib.KvInMemoryStore; -using Geekbot.net.Lib.Levels; -using Geekbot.net.Lib.Localization; -using Geekbot.net.Lib.Logger; -using Geekbot.net.Lib.MalClient; -using Geekbot.net.Lib.Media; -using Geekbot.net.Lib.RandomNumberGenerator; -using Geekbot.net.Lib.ReactionListener; -using Geekbot.net.Lib.UserRepository; -using Geekbot.net.Lib.WikipediaClient; -using Geekbot.net.WebApi; +using Geekbot.Bot.Handlers; +using Geekbot.Core; +using Geekbot.Core.Converters; +using Geekbot.Core.Database; +using Geekbot.Core.DiceParser; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.GlobalSettings; +using Geekbot.Core.GuildSettingsManager; +using Geekbot.Core.Highscores; +using Geekbot.Core.KvInMemoryStore; +using Geekbot.Core.Levels; +using Geekbot.Core.Localization; +using Geekbot.Core.Logger; +using Geekbot.Core.MalClient; +using Geekbot.Core.Media; +using Geekbot.Core.RandomNumberGenerator; +using Geekbot.Core.ReactionListener; +using Geekbot.Core.UserRepository; +using Geekbot.Core.WikipediaClient; +using Geekbot.Web; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; -namespace Geekbot.net +namespace Geekbot.Bot { internal class Program { diff --git a/Geekbot.net/Storage/croissant b/src/Bot/Storage/croissant similarity index 100% rename from Geekbot.net/Storage/croissant rename to src/Bot/Storage/croissant diff --git a/Geekbot.net/Storage/dab b/src/Bot/Storage/dab similarity index 100% rename from Geekbot.net/Storage/dab rename to src/Bot/Storage/dab diff --git a/Geekbot.net/Storage/fortunes b/src/Bot/Storage/fortunes similarity index 100% rename from Geekbot.net/Storage/fortunes rename to src/Bot/Storage/fortunes diff --git a/Geekbot.net/Storage/foxes b/src/Bot/Storage/foxes similarity index 100% rename from Geekbot.net/Storage/foxes rename to src/Bot/Storage/foxes diff --git a/Geekbot.net/Storage/pandas b/src/Bot/Storage/pandas similarity index 100% rename from Geekbot.net/Storage/pandas rename to src/Bot/Storage/pandas diff --git a/Geekbot.net/Storage/penguins b/src/Bot/Storage/penguins similarity index 100% rename from Geekbot.net/Storage/penguins rename to src/Bot/Storage/penguins diff --git a/Geekbot.net/Storage/pumpkin b/src/Bot/Storage/pumpkin similarity index 100% rename from Geekbot.net/Storage/pumpkin rename to src/Bot/Storage/pumpkin diff --git a/Geekbot.net/Storage/squirrel b/src/Bot/Storage/squirrel similarity index 100% rename from Geekbot.net/Storage/squirrel rename to src/Bot/Storage/squirrel diff --git a/Geekbot.net/Storage/turtles b/src/Bot/Storage/turtles similarity index 100% rename from Geekbot.net/Storage/turtles rename to src/Bot/Storage/turtles diff --git a/Geekbot.net/derp.ico b/src/Bot/derp.ico similarity index 100% rename from Geekbot.net/derp.ico rename to src/Bot/derp.ico diff --git a/Geekbot.net/Lib/CommandPreconditions/DisableInDirectMessageAttribute.cs b/src/Core/CommandPreconditions/DisableInDirectMessageAttribute.cs similarity index 92% rename from Geekbot.net/Lib/CommandPreconditions/DisableInDirectMessageAttribute.cs rename to src/Core/CommandPreconditions/DisableInDirectMessageAttribute.cs index 2bb5cfd..835e0b3 100644 --- a/Geekbot.net/Lib/CommandPreconditions/DisableInDirectMessageAttribute.cs +++ b/src/Core/CommandPreconditions/DisableInDirectMessageAttribute.cs @@ -2,7 +2,7 @@ using System; using System.Threading.Tasks; using Discord.Commands; -namespace Geekbot.net.Lib.CommandPreconditions +namespace Geekbot.Core.CommandPreconditions { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] public class DisableInDirectMessageAttribute : PreconditionAttribute diff --git a/Geekbot.net/Lib/Constants.cs b/src/Core/Constants.cs similarity index 72% rename from Geekbot.net/Lib/Constants.cs rename to src/Core/Constants.cs index 4abee4e..4dd08b9 100644 --- a/Geekbot.net/Lib/Constants.cs +++ b/src/Core/Constants.cs @@ -1,6 +1,6 @@ using System.Reflection; -namespace Geekbot.net.Lib +namespace Geekbot.Core { public static class Constants { @@ -8,7 +8,7 @@ namespace Geekbot.net.Lib public static string BotVersion() { - return typeof(Program).Assembly.GetCustomAttribute().InformationalVersion; + return typeof(Constants).Assembly.GetCustomAttribute().InformationalVersion; } public static string LibraryVersion() diff --git a/Geekbot.net/Lib/Converters/EmojiConverter.cs b/src/Core/Converters/EmojiConverter.cs similarity index 96% rename from Geekbot.net/Lib/Converters/EmojiConverter.cs rename to src/Core/Converters/EmojiConverter.cs index 06f1aa8..327aab8 100644 --- a/Geekbot.net/Lib/Converters/EmojiConverter.cs +++ b/src/Core/Converters/EmojiConverter.cs @@ -1,7 +1,7 @@ using System.Collections; using System.Text; -namespace Geekbot.net.Lib.Converters +namespace Geekbot.Core.Converters { public class EmojiConverter : IEmojiConverter { diff --git a/Geekbot.net/Lib/Converters/IEmojiConverter.cs b/src/Core/Converters/IEmojiConverter.cs similarity index 74% rename from Geekbot.net/Lib/Converters/IEmojiConverter.cs rename to src/Core/Converters/IEmojiConverter.cs index b0f666f..79ca0a7 100644 --- a/Geekbot.net/Lib/Converters/IEmojiConverter.cs +++ b/src/Core/Converters/IEmojiConverter.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Lib.Converters +namespace Geekbot.Core.Converters { public interface IEmojiConverter { diff --git a/Geekbot.net/Lib/Converters/IMtgManaConverter.cs b/src/Core/Converters/IMtgManaConverter.cs similarity index 67% rename from Geekbot.net/Lib/Converters/IMtgManaConverter.cs rename to src/Core/Converters/IMtgManaConverter.cs index d558f09..0dd3034 100644 --- a/Geekbot.net/Lib/Converters/IMtgManaConverter.cs +++ b/src/Core/Converters/IMtgManaConverter.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Lib.Converters +namespace Geekbot.Core.Converters { public interface IMtgManaConverter { diff --git a/Geekbot.net/Lib/Converters/MtgManaConverter.cs b/src/Core/Converters/MtgManaConverter.cs similarity index 96% rename from Geekbot.net/Lib/Converters/MtgManaConverter.cs rename to src/Core/Converters/MtgManaConverter.cs index cfd893b..aa6b74c 100644 --- a/Geekbot.net/Lib/Converters/MtgManaConverter.cs +++ b/src/Core/Converters/MtgManaConverter.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Text.RegularExpressions; -namespace Geekbot.net.Lib.Converters +namespace Geekbot.Core.Converters { public class MtgManaConverter : IMtgManaConverter { diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj new file mode 100644 index 0000000..fcbce09 --- /dev/null +++ b/src/Core/Core.csproj @@ -0,0 +1,40 @@ + + + + net5.0 + $(VersionSuffix) + $(VersionSuffix) + 0.0.0-DEV + Geekbot.Core + Geekbot.Core + NU1701 + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/Geekbot.net/Database/DatabaseContext.cs b/src/Core/Database/DatabaseContext.cs similarity index 91% rename from Geekbot.net/Database/DatabaseContext.cs rename to src/Core/Database/DatabaseContext.cs index 505486f..93d46d3 100644 --- a/Geekbot.net/Database/DatabaseContext.cs +++ b/src/Core/Database/DatabaseContext.cs @@ -1,7 +1,7 @@ -using Geekbot.net.Database.Models; +using Geekbot.Core.Database.Models; using Microsoft.EntityFrameworkCore; -namespace Geekbot.net.Database +namespace Geekbot.Core.Database { public class DatabaseContext : DbContext { diff --git a/Geekbot.net/Database/DatabaseInitializer.cs b/src/Core/Database/DatabaseInitializer.cs similarity index 93% rename from Geekbot.net/Database/DatabaseInitializer.cs rename to src/Core/Database/DatabaseInitializer.cs index 9f60d8a..37f07bc 100644 --- a/Geekbot.net/Database/DatabaseInitializer.cs +++ b/src/Core/Database/DatabaseInitializer.cs @@ -1,10 +1,9 @@ using System; -using Geekbot.net.Database.LoggingAdapter; -using Geekbot.net.Lib; -using Geekbot.net.Lib.Logger; +using Geekbot.Core.Database.LoggingAdapter; +using Geekbot.Core.Logger; using Npgsql.Logging; -namespace Geekbot.net.Database +namespace Geekbot.Core.Database { public class DatabaseInitializer { diff --git a/Geekbot.net/Database/InMemoryDatabase.cs b/src/Core/Database/InMemoryDatabase.cs similarity index 89% rename from Geekbot.net/Database/InMemoryDatabase.cs rename to src/Core/Database/InMemoryDatabase.cs index 2b2cfd0..1077aea 100644 --- a/Geekbot.net/Database/InMemoryDatabase.cs +++ b/src/Core/Database/InMemoryDatabase.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore; -namespace Geekbot.net.Database +namespace Geekbot.Core.Database { public class InMemoryDatabase : DatabaseContext { diff --git a/Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingAdapter.cs b/src/Core/Database/LoggingAdapter/NpgsqlLoggingAdapter.cs similarity index 93% rename from Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingAdapter.cs rename to src/Core/Database/LoggingAdapter/NpgsqlLoggingAdapter.cs index ceebd56..8a46c0d 100644 --- a/Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingAdapter.cs +++ b/src/Core/Database/LoggingAdapter/NpgsqlLoggingAdapter.cs @@ -1,10 +1,9 @@ using System; -using Geekbot.net.Lib; -using Geekbot.net.Lib.Logger; +using Geekbot.Core.Logger; using Npgsql.Logging; using LogLevel = NLog.LogLevel; -namespace Geekbot.net.Database.LoggingAdapter +namespace Geekbot.Core.Database.LoggingAdapter { public class NpgsqlLoggingAdapter : NpgsqlLogger { diff --git a/Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingProviderAdapter.cs b/src/Core/Database/LoggingAdapter/NpgsqlLoggingProviderAdapter.cs similarity index 82% rename from Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingProviderAdapter.cs rename to src/Core/Database/LoggingAdapter/NpgsqlLoggingProviderAdapter.cs index efe82a3..c4f76d7 100644 --- a/Geekbot.net/Database/LoggingAdapter/NpgsqlLoggingProviderAdapter.cs +++ b/src/Core/Database/LoggingAdapter/NpgsqlLoggingProviderAdapter.cs @@ -1,8 +1,7 @@ -using Geekbot.net.Lib; -using Geekbot.net.Lib.Logger; +using Geekbot.Core.Logger; using Npgsql.Logging; -namespace Geekbot.net.Database.LoggingAdapter +namespace Geekbot.Core.Database.LoggingAdapter { public class NpgsqlLoggingProviderAdapter : INpgsqlLoggingProvider { diff --git a/Geekbot.net/Database/Models/CookiesModel.cs b/src/Core/Database/Models/CookiesModel.cs similarity index 87% rename from Geekbot.net/Database/Models/CookiesModel.cs rename to src/Core/Database/Models/CookiesModel.cs index 228f3b0..6ec71f9 100644 --- a/Geekbot.net/Database/Models/CookiesModel.cs +++ b/src/Core/Database/Models/CookiesModel.cs @@ -1,7 +1,7 @@ using System; using System.ComponentModel.DataAnnotations; -namespace Geekbot.net.Database.Models +namespace Geekbot.Core.Database.Models { public class CookiesModel { diff --git a/Geekbot.net/Database/Models/GlobalsModel.cs b/src/Core/Database/Models/GlobalsModel.cs similarity index 85% rename from Geekbot.net/Database/Models/GlobalsModel.cs rename to src/Core/Database/Models/GlobalsModel.cs index 63261fc..af084f9 100644 --- a/Geekbot.net/Database/Models/GlobalsModel.cs +++ b/src/Core/Database/Models/GlobalsModel.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -namespace Geekbot.net.Database.Models +namespace Geekbot.Core.Database.Models { public class GlobalsModel { diff --git a/Geekbot.net/Database/Models/GuildSettingsModel.cs b/src/Core/Database/Models/GuildSettingsModel.cs similarity index 90% rename from Geekbot.net/Database/Models/GuildSettingsModel.cs rename to src/Core/Database/Models/GuildSettingsModel.cs index ebb6dc4..80655f7 100644 --- a/Geekbot.net/Database/Models/GuildSettingsModel.cs +++ b/src/Core/Database/Models/GuildSettingsModel.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -namespace Geekbot.net.Database.Models +namespace Geekbot.Core.Database.Models { public class GuildSettingsModel { diff --git a/Geekbot.net/Database/Models/KarmaModel.cs b/src/Core/Database/Models/KarmaModel.cs similarity index 87% rename from Geekbot.net/Database/Models/KarmaModel.cs rename to src/Core/Database/Models/KarmaModel.cs index 7d5f533..2ec64f0 100644 --- a/Geekbot.net/Database/Models/KarmaModel.cs +++ b/src/Core/Database/Models/KarmaModel.cs @@ -1,7 +1,7 @@ using System; using System.ComponentModel.DataAnnotations; -namespace Geekbot.net.Database.Models +namespace Geekbot.Core.Database.Models { public class KarmaModel { diff --git a/Geekbot.net/Database/Models/MessagesModel.cs b/src/Core/Database/Models/MessagesModel.cs similarity index 85% rename from Geekbot.net/Database/Models/MessagesModel.cs rename to src/Core/Database/Models/MessagesModel.cs index 31332e8..87731d8 100644 --- a/Geekbot.net/Database/Models/MessagesModel.cs +++ b/src/Core/Database/Models/MessagesModel.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -namespace Geekbot.net.Database.Models +namespace Geekbot.Core.Database.Models { public class MessagesModel { diff --git a/Geekbot.net/Database/Models/QuoteModel.cs b/src/Core/Database/Models/QuoteModel.cs similarity index 93% rename from Geekbot.net/Database/Models/QuoteModel.cs rename to src/Core/Database/Models/QuoteModel.cs index 98e8b21..3d356d2 100644 --- a/Geekbot.net/Database/Models/QuoteModel.cs +++ b/src/Core/Database/Models/QuoteModel.cs @@ -1,7 +1,7 @@ using System; using System.ComponentModel.DataAnnotations; -namespace Geekbot.net.Database.Models +namespace Geekbot.Core.Database.Models { public class QuoteModel { diff --git a/Geekbot.net/Database/Models/ReactionListenerModel.cs b/src/Core/Database/Models/ReactionListenerModel.cs similarity index 91% rename from Geekbot.net/Database/Models/ReactionListenerModel.cs rename to src/Core/Database/Models/ReactionListenerModel.cs index 05ab5b3..5ec28be 100644 --- a/Geekbot.net/Database/Models/ReactionListenerModel.cs +++ b/src/Core/Database/Models/ReactionListenerModel.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -namespace Geekbot.net.Database.Models +namespace Geekbot.Core.Database.Models { public class ReactionListenerModel { diff --git a/Geekbot.net/Database/Models/RoleSelfServiceModel.cs b/src/Core/Database/Models/RoleSelfServiceModel.cs similarity index 85% rename from Geekbot.net/Database/Models/RoleSelfServiceModel.cs rename to src/Core/Database/Models/RoleSelfServiceModel.cs index de8c341..4aa92c4 100644 --- a/Geekbot.net/Database/Models/RoleSelfServiceModel.cs +++ b/src/Core/Database/Models/RoleSelfServiceModel.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -namespace Geekbot.net.Database.Models +namespace Geekbot.Core.Database.Models { public class RoleSelfServiceModel { diff --git a/Geekbot.net/Database/Models/RollsModel.cs b/src/Core/Database/Models/RollsModel.cs similarity index 85% rename from Geekbot.net/Database/Models/RollsModel.cs rename to src/Core/Database/Models/RollsModel.cs index de9b82e..aa6613d 100644 --- a/Geekbot.net/Database/Models/RollsModel.cs +++ b/src/Core/Database/Models/RollsModel.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -namespace Geekbot.net.Database.Models +namespace Geekbot.Core.Database.Models { public class RollsModel { diff --git a/Geekbot.net/Database/Models/ShipsModel.cs b/src/Core/Database/Models/ShipsModel.cs similarity index 84% rename from Geekbot.net/Database/Models/ShipsModel.cs rename to src/Core/Database/Models/ShipsModel.cs index d8156b0..23cf367 100644 --- a/Geekbot.net/Database/Models/ShipsModel.cs +++ b/src/Core/Database/Models/ShipsModel.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -namespace Geekbot.net.Database.Models +namespace Geekbot.Core.Database.Models { public class ShipsModel { diff --git a/Geekbot.net/Database/Models/SlapsModel.cs b/src/Core/Database/Models/SlapsModel.cs similarity index 86% rename from Geekbot.net/Database/Models/SlapsModel.cs rename to src/Core/Database/Models/SlapsModel.cs index 6c402aa..09026c8 100644 --- a/Geekbot.net/Database/Models/SlapsModel.cs +++ b/src/Core/Database/Models/SlapsModel.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -namespace Geekbot.net.Database.Models +namespace Geekbot.Core.Database.Models { public class SlapsModel { diff --git a/Geekbot.net/Database/Models/UserModel.cs b/src/Core/Database/Models/UserModel.cs similarity index 84% rename from Geekbot.net/Database/Models/UserModel.cs rename to src/Core/Database/Models/UserModel.cs index 43d3a9a..aa6281d 100644 --- a/Geekbot.net/Database/Models/UserModel.cs +++ b/src/Core/Database/Models/UserModel.cs @@ -1,8 +1,7 @@ using System; -using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -namespace Geekbot.net.Database.Models +namespace Geekbot.Core.Database.Models { public class UserModel { diff --git a/Geekbot.net/Database/SqlConnectionString.cs b/src/Core/Database/SqlConnectionString.cs similarity index 94% rename from Geekbot.net/Database/SqlConnectionString.cs rename to src/Core/Database/SqlConnectionString.cs index 61804cf..ca2858d 100644 --- a/Geekbot.net/Database/SqlConnectionString.cs +++ b/src/Core/Database/SqlConnectionString.cs @@ -1,6 +1,6 @@ using System.Text; -namespace Geekbot.net.Database +namespace Geekbot.Core.Database { public class SqlConnectionString { diff --git a/Geekbot.net/Database/SqlDatabase.cs b/src/Core/Database/SqlDatabase.cs similarity index 90% rename from Geekbot.net/Database/SqlDatabase.cs rename to src/Core/Database/SqlDatabase.cs index e6d03d4..8a4d195 100644 --- a/Geekbot.net/Database/SqlDatabase.cs +++ b/src/Core/Database/SqlDatabase.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore; -namespace Geekbot.net.Database +namespace Geekbot.Core.Database { public class SqlDatabase : DatabaseContext { diff --git a/Geekbot.net/Lib/DiceParser/DiceException.cs b/src/Core/DiceParser/DiceException.cs similarity index 84% rename from Geekbot.net/Lib/DiceParser/DiceException.cs rename to src/Core/DiceParser/DiceException.cs index d2a66ad..6c6c29c 100644 --- a/Geekbot.net/Lib/DiceParser/DiceException.cs +++ b/src/Core/DiceParser/DiceException.cs @@ -1,6 +1,6 @@ using System; -namespace Geekbot.net.Lib.DiceParser +namespace Geekbot.Core.DiceParser { public class DiceException : Exception { diff --git a/Geekbot.net/Lib/DiceParser/DiceInput.cs b/src/Core/DiceParser/DiceInput.cs similarity index 88% rename from Geekbot.net/Lib/DiceParser/DiceInput.cs rename to src/Core/DiceParser/DiceInput.cs index baca42c..60f0bd2 100644 --- a/Geekbot.net/Lib/DiceParser/DiceInput.cs +++ b/src/Core/DiceParser/DiceInput.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace Geekbot.net.Lib.DiceParser +namespace Geekbot.Core.DiceParser { public class DiceInput { diff --git a/Geekbot.net/Lib/DiceParser/DiceInputOptions.cs b/src/Core/DiceParser/DiceInputOptions.cs similarity index 71% rename from Geekbot.net/Lib/DiceParser/DiceInputOptions.cs rename to src/Core/DiceParser/DiceInputOptions.cs index 41f2def..5606a5e 100644 --- a/Geekbot.net/Lib/DiceParser/DiceInputOptions.cs +++ b/src/Core/DiceParser/DiceInputOptions.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Lib.DiceParser +namespace Geekbot.Core.DiceParser { public struct DiceInputOptions { diff --git a/Geekbot.net/Lib/DiceParser/DiceParser.cs b/src/Core/DiceParser/DiceParser.cs similarity index 97% rename from Geekbot.net/Lib/DiceParser/DiceParser.cs rename to src/Core/DiceParser/DiceParser.cs index 7f90865..b0f6a88 100644 --- a/Geekbot.net/Lib/DiceParser/DiceParser.cs +++ b/src/Core/DiceParser/DiceParser.cs @@ -1,9 +1,9 @@ using System; using System.Linq; using System.Text.RegularExpressions; -using Geekbot.net.Lib.RandomNumberGenerator; +using Geekbot.Core.RandomNumberGenerator; -namespace Geekbot.net.Lib.DiceParser +namespace Geekbot.Core.DiceParser { public class DiceParser : IDiceParser { diff --git a/Geekbot.net/Lib/DiceParser/DieAdvantageType.cs b/src/Core/DiceParser/DieAdvantageType.cs similarity index 73% rename from Geekbot.net/Lib/DiceParser/DieAdvantageType.cs rename to src/Core/DiceParser/DieAdvantageType.cs index 91818cb..9bd7486 100644 --- a/Geekbot.net/Lib/DiceParser/DieAdvantageType.cs +++ b/src/Core/DiceParser/DieAdvantageType.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Lib.DiceParser +namespace Geekbot.Core.DiceParser { public enum DieAdvantageType { diff --git a/Geekbot.net/Lib/DiceParser/DieResult.cs b/src/Core/DiceParser/DieResult.cs similarity index 96% rename from Geekbot.net/Lib/DiceParser/DieResult.cs rename to src/Core/DiceParser/DieResult.cs index 2f99fb6..aa309c0 100644 --- a/Geekbot.net/Lib/DiceParser/DieResult.cs +++ b/src/Core/DiceParser/DieResult.cs @@ -1,6 +1,6 @@ using System; -namespace Geekbot.net.Lib.DiceParser +namespace Geekbot.Core.DiceParser { public class DieResult { diff --git a/Geekbot.net/Lib/DiceParser/IDiceParser.cs b/src/Core/DiceParser/IDiceParser.cs similarity index 70% rename from Geekbot.net/Lib/DiceParser/IDiceParser.cs rename to src/Core/DiceParser/IDiceParser.cs index 608b379..ab1ebd3 100644 --- a/Geekbot.net/Lib/DiceParser/IDiceParser.cs +++ b/src/Core/DiceParser/IDiceParser.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Lib.DiceParser +namespace Geekbot.Core.DiceParser { public interface IDiceParser { diff --git a/Geekbot.net/Lib/DiceParser/SingleDie.cs b/src/Core/DiceParser/SingleDie.cs similarity index 94% rename from Geekbot.net/Lib/DiceParser/SingleDie.cs rename to src/Core/DiceParser/SingleDie.cs index 582fe29..f13dbcd 100644 --- a/Geekbot.net/Lib/DiceParser/SingleDie.cs +++ b/src/Core/DiceParser/SingleDie.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; -using Geekbot.net.Lib.Extensions; -using Geekbot.net.Lib.RandomNumberGenerator; +using Geekbot.Core.Extensions; +using Geekbot.Core.RandomNumberGenerator; -namespace Geekbot.net.Lib.DiceParser +namespace Geekbot.Core.DiceParser { public class SingleDie { diff --git a/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs b/src/Core/ErrorHandling/ErrorHandler.cs similarity index 97% rename from Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs rename to src/Core/ErrorHandling/ErrorHandler.cs index cda9129..02402f2 100644 --- a/Geekbot.net/Lib/ErrorHandling/ErrorHandler.cs +++ b/src/Core/ErrorHandling/ErrorHandler.cs @@ -3,13 +3,13 @@ using System.Net; using System.Threading.Tasks; using Discord.Commands; using Discord.Net; -using Geekbot.net.Lib.Localization; -using Geekbot.net.Lib.Logger; +using Geekbot.Core.Localization; +using Geekbot.Core.Logger; using SharpRaven; using SharpRaven.Data; using Exception = System.Exception; -namespace Geekbot.net.Lib.ErrorHandling +namespace Geekbot.Core.ErrorHandling { public class ErrorHandler : IErrorHandler { diff --git a/Geekbot.net/Lib/ErrorHandling/IErrorHandler.cs b/src/Core/ErrorHandling/IErrorHandler.cs similarity index 86% rename from Geekbot.net/Lib/ErrorHandling/IErrorHandler.cs rename to src/Core/ErrorHandling/IErrorHandler.cs index 05e0d8e..c012b82 100644 --- a/Geekbot.net/Lib/ErrorHandling/IErrorHandler.cs +++ b/src/Core/ErrorHandling/IErrorHandler.cs @@ -3,7 +3,7 @@ using System.Threading.Tasks; using Discord.Commands; using Discord.Net; -namespace Geekbot.net.Lib.ErrorHandling +namespace Geekbot.Core.ErrorHandling { public interface IErrorHandler { diff --git a/Geekbot.net/Lib/Extensions/DbSetExtensions.cs b/src/Core/Extensions/DbSetExtensions.cs similarity index 94% rename from Geekbot.net/Lib/Extensions/DbSetExtensions.cs rename to src/Core/Extensions/DbSetExtensions.cs index e08b2d4..3ccffe9 100644 --- a/Geekbot.net/Lib/Extensions/DbSetExtensions.cs +++ b/src/Core/Extensions/DbSetExtensions.cs @@ -5,7 +5,7 @@ using System.Linq.Expressions; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.ChangeTracking; -namespace Geekbot.net.Lib.Extensions +namespace Geekbot.Core.Extensions { public static class DbSetExtensions { diff --git a/Geekbot.net/Lib/Extensions/EmbedBuilderExtensions.cs b/src/Core/Extensions/EmbedBuilderExtensions.cs similarity index 86% rename from Geekbot.net/Lib/Extensions/EmbedBuilderExtensions.cs rename to src/Core/Extensions/EmbedBuilderExtensions.cs index 246be44..c546306 100644 --- a/Geekbot.net/Lib/Extensions/EmbedBuilderExtensions.cs +++ b/src/Core/Extensions/EmbedBuilderExtensions.cs @@ -1,6 +1,6 @@ using Discord; -namespace Geekbot.net.Lib.Extensions +namespace Geekbot.Core.Extensions { public static class EmbedBuilderExtensions { diff --git a/Geekbot.net/Lib/Extensions/IntExtensions.cs b/src/Core/Extensions/IntExtensions.cs similarity index 87% rename from Geekbot.net/Lib/Extensions/IntExtensions.cs rename to src/Core/Extensions/IntExtensions.cs index ed0fc10..dac03e7 100644 --- a/Geekbot.net/Lib/Extensions/IntExtensions.cs +++ b/src/Core/Extensions/IntExtensions.cs @@ -1,6 +1,6 @@ using System; -namespace Geekbot.net.Lib.Extensions +namespace Geekbot.Core.Extensions { public static class IntExtensions { diff --git a/Geekbot.net/Lib/Extensions/LongExtensions.cs b/src/Core/Extensions/LongExtensions.cs similarity index 79% rename from Geekbot.net/Lib/Extensions/LongExtensions.cs rename to src/Core/Extensions/LongExtensions.cs index 1bcdd9b..087910e 100644 --- a/Geekbot.net/Lib/Extensions/LongExtensions.cs +++ b/src/Core/Extensions/LongExtensions.cs @@ -1,6 +1,6 @@ using System; -namespace Geekbot.net.Lib.Extensions +namespace Geekbot.Core.Extensions { public static class LongExtensions { diff --git a/Geekbot.net/Lib/Extensions/StringExtensions.cs b/src/Core/Extensions/StringExtensions.cs similarity index 83% rename from Geekbot.net/Lib/Extensions/StringExtensions.cs rename to src/Core/Extensions/StringExtensions.cs index 9ec1dfe..9affad1 100644 --- a/Geekbot.net/Lib/Extensions/StringExtensions.cs +++ b/src/Core/Extensions/StringExtensions.cs @@ -1,6 +1,6 @@ using System.Linq; -namespace Geekbot.net.Lib.Extensions +namespace Geekbot.Core.Extensions { public static class StringExtensions { diff --git a/Geekbot.net/Lib/Extensions/UlongExtensions.cs b/src/Core/Extensions/UlongExtensions.cs similarity index 79% rename from Geekbot.net/Lib/Extensions/UlongExtensions.cs rename to src/Core/Extensions/UlongExtensions.cs index 8fa2a67..295f317 100644 --- a/Geekbot.net/Lib/Extensions/UlongExtensions.cs +++ b/src/Core/Extensions/UlongExtensions.cs @@ -1,6 +1,6 @@ using System; -namespace Geekbot.net.Lib.Extensions +namespace Geekbot.Core.Extensions { public static class UlongExtensions { diff --git a/Geekbot.net/Lib/GeekbotExitCode.cs b/src/Core/GeekbotExitCode.cs similarity index 88% rename from Geekbot.net/Lib/GeekbotExitCode.cs rename to src/Core/GeekbotExitCode.cs index 4d91d18..5598f48 100644 --- a/Geekbot.net/Lib/GeekbotExitCode.cs +++ b/src/Core/GeekbotExitCode.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Lib +namespace Geekbot.Core { public enum GeekbotExitCode { diff --git a/Geekbot.net/Lib/GlobalSettings/GlobalSettings.cs b/src/Core/GlobalSettings/GlobalSettings.cs similarity index 91% rename from Geekbot.net/Lib/GlobalSettings/GlobalSettings.cs rename to src/Core/GlobalSettings/GlobalSettings.cs index 685a1e5..a000f8b 100644 --- a/Geekbot.net/Lib/GlobalSettings/GlobalSettings.cs +++ b/src/Core/GlobalSettings/GlobalSettings.cs @@ -1,10 +1,10 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Geekbot.net.Database; -using Geekbot.net.Database.Models; +using Geekbot.Core.Database; +using Geekbot.Core.Database.Models; -namespace Geekbot.net.Lib.GlobalSettings +namespace Geekbot.Core.GlobalSettings { public class GlobalSettings : IGlobalSettings { diff --git a/Geekbot.net/Lib/GlobalSettings/IGlobalSettings.cs b/src/Core/GlobalSettings/IGlobalSettings.cs similarity index 72% rename from Geekbot.net/Lib/GlobalSettings/IGlobalSettings.cs rename to src/Core/GlobalSettings/IGlobalSettings.cs index 4833215..082b3dc 100644 --- a/Geekbot.net/Lib/GlobalSettings/IGlobalSettings.cs +++ b/src/Core/GlobalSettings/IGlobalSettings.cs @@ -1,7 +1,7 @@ using System.Threading.Tasks; -using Geekbot.net.Database.Models; +using Geekbot.Core.Database.Models; -namespace Geekbot.net.Lib.GlobalSettings +namespace Geekbot.Core.GlobalSettings { public interface IGlobalSettings { diff --git a/Geekbot.net/Lib/GuildSettingsManager/GuildSettingsManager.cs b/src/Core/GuildSettingsManager/GuildSettingsManager.cs similarity index 93% rename from Geekbot.net/Lib/GuildSettingsManager/GuildSettingsManager.cs rename to src/Core/GuildSettingsManager/GuildSettingsManager.cs index bfa7556..565563f 100644 --- a/Geekbot.net/Lib/GuildSettingsManager/GuildSettingsManager.cs +++ b/src/Core/GuildSettingsManager/GuildSettingsManager.cs @@ -1,11 +1,11 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Geekbot.net.Database; -using Geekbot.net.Database.Models; -using Geekbot.net.Lib.Extensions; +using Geekbot.Core.Database; +using Geekbot.Core.Database.Models; +using Geekbot.Core.Extensions; -namespace Geekbot.net.Lib.GuildSettingsManager +namespace Geekbot.Core.GuildSettingsManager { public class GuildSettingsManager : IGuildSettingsManager { diff --git a/Geekbot.net/Lib/GuildSettingsManager/IGuildSettingsManager.cs b/src/Core/GuildSettingsManager/IGuildSettingsManager.cs similarity index 73% rename from Geekbot.net/Lib/GuildSettingsManager/IGuildSettingsManager.cs rename to src/Core/GuildSettingsManager/IGuildSettingsManager.cs index a45b263..d34eb73 100644 --- a/Geekbot.net/Lib/GuildSettingsManager/IGuildSettingsManager.cs +++ b/src/Core/GuildSettingsManager/IGuildSettingsManager.cs @@ -1,7 +1,7 @@ using System.Threading.Tasks; -using Geekbot.net.Database.Models; +using Geekbot.Core.Database.Models; -namespace Geekbot.net.Lib.GuildSettingsManager +namespace Geekbot.Core.GuildSettingsManager { public interface IGuildSettingsManager { diff --git a/Geekbot.net/Lib/Highscores/HighscoreListEmptyException.cs b/src/Core/Highscores/HighscoreListEmptyException.cs similarity index 86% rename from Geekbot.net/Lib/Highscores/HighscoreListEmptyException.cs rename to src/Core/Highscores/HighscoreListEmptyException.cs index 8c05ca9..5fc08ee 100644 --- a/Geekbot.net/Lib/Highscores/HighscoreListEmptyException.cs +++ b/src/Core/Highscores/HighscoreListEmptyException.cs @@ -1,6 +1,6 @@ using System; -namespace Geekbot.net.Lib.Highscores +namespace Geekbot.Core.Highscores { public class HighscoreListEmptyException : Exception { diff --git a/Geekbot.net/Lib/Highscores/HighscoreManager.cs b/src/Core/Highscores/HighscoreManager.cs similarity index 93% rename from Geekbot.net/Lib/Highscores/HighscoreManager.cs rename to src/Core/Highscores/HighscoreManager.cs index 8218532..ac8580b 100644 --- a/Geekbot.net/Lib/Highscores/HighscoreManager.cs +++ b/src/Core/Highscores/HighscoreManager.cs @@ -1,10 +1,10 @@ using System.Collections.Generic; using System.Linq; -using Geekbot.net.Database; -using Geekbot.net.Lib.Extensions; -using Geekbot.net.Lib.UserRepository; +using Geekbot.Core.Database; +using Geekbot.Core.Extensions; +using Geekbot.Core.UserRepository; -namespace Geekbot.net.Lib.Highscores +namespace Geekbot.Core.Highscores { public class HighscoreManager : IHighscoreManager { diff --git a/Geekbot.net/Lib/Highscores/HighscoreTypes.cs b/src/Core/Highscores/HighscoreTypes.cs similarity index 69% rename from Geekbot.net/Lib/Highscores/HighscoreTypes.cs rename to src/Core/Highscores/HighscoreTypes.cs index adf5698..b577642 100644 --- a/Geekbot.net/Lib/Highscores/HighscoreTypes.cs +++ b/src/Core/Highscores/HighscoreTypes.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Lib.Highscores +namespace Geekbot.Core.Highscores { public enum HighscoreTypes { diff --git a/Geekbot.net/Lib/Highscores/HighscoreUserDto.cs b/src/Core/Highscores/HighscoreUserDto.cs similarity index 82% rename from Geekbot.net/Lib/Highscores/HighscoreUserDto.cs rename to src/Core/Highscores/HighscoreUserDto.cs index 7abb352..58e1897 100644 --- a/Geekbot.net/Lib/Highscores/HighscoreUserDto.cs +++ b/src/Core/Highscores/HighscoreUserDto.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Lib.Highscores +namespace Geekbot.Core.Highscores { public class HighscoreUserDto { diff --git a/Geekbot.net/Lib/Highscores/IHighscoreManager.cs b/src/Core/Highscores/IHighscoreManager.cs similarity index 89% rename from Geekbot.net/Lib/Highscores/IHighscoreManager.cs rename to src/Core/Highscores/IHighscoreManager.cs index a09b07e..83ba2da 100644 --- a/Geekbot.net/Lib/Highscores/IHighscoreManager.cs +++ b/src/Core/Highscores/IHighscoreManager.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace Geekbot.net.Lib.Highscores +namespace Geekbot.Core.Highscores { public interface IHighscoreManager { diff --git a/Geekbot.net/Lib/HttpAbstractions.cs b/src/Core/HttpAbstractions.cs similarity index 97% rename from Geekbot.net/Lib/HttpAbstractions.cs rename to src/Core/HttpAbstractions.cs index 2cde4cc..4fa287b 100644 --- a/Geekbot.net/Lib/HttpAbstractions.cs +++ b/src/Core/HttpAbstractions.cs @@ -4,7 +4,7 @@ using System.Net.Http.Headers; using System.Threading.Tasks; using Newtonsoft.Json; -namespace Geekbot.net.Lib +namespace Geekbot.Core { public static class HttpAbstractions { diff --git a/Geekbot.net/Lib/KvInMemoryStore/IKvInMemoryStore.cs b/src/Core/KvInMemoryStore/IKvInMemoryStore.cs similarity index 80% rename from Geekbot.net/Lib/KvInMemoryStore/IKvInMemoryStore.cs rename to src/Core/KvInMemoryStore/IKvInMemoryStore.cs index 88f3863..6281f4b 100644 --- a/Geekbot.net/Lib/KvInMemoryStore/IKvInMemoryStore.cs +++ b/src/Core/KvInMemoryStore/IKvInMemoryStore.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Lib.KvInMemoryStore +namespace Geekbot.Core.KvInMemoryStore { public interface IKvInMemoryStore { diff --git a/Geekbot.net/Lib/KvInMemoryStore/KvInMemoryStore.cs b/src/Core/KvInMemoryStore/KvInMemoryStore.cs similarity index 93% rename from Geekbot.net/Lib/KvInMemoryStore/KvInMemoryStore.cs rename to src/Core/KvInMemoryStore/KvInMemoryStore.cs index 33b7155..4a50546 100644 --- a/Geekbot.net/Lib/KvInMemoryStore/KvInMemoryStore.cs +++ b/src/Core/KvInMemoryStore/KvInMemoryStore.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace Geekbot.net.Lib.KvInMemoryStore +namespace Geekbot.Core.KvInMemoryStore { public class KvInInMemoryStore : IKvInMemoryStore { diff --git a/Geekbot.net/Lib/Levels/ILevelCalc.cs b/src/Core/Levels/ILevelCalc.cs similarity index 67% rename from Geekbot.net/Lib/Levels/ILevelCalc.cs rename to src/Core/Levels/ILevelCalc.cs index cc488e7..17413e6 100644 --- a/Geekbot.net/Lib/Levels/ILevelCalc.cs +++ b/src/Core/Levels/ILevelCalc.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Lib.Levels +namespace Geekbot.Core.Levels { public interface ILevelCalc { diff --git a/Geekbot.net/Lib/Levels/LevelCalc.cs b/src/Core/Levels/LevelCalc.cs similarity index 95% rename from Geekbot.net/Lib/Levels/LevelCalc.cs rename to src/Core/Levels/LevelCalc.cs index 74747b7..8203f97 100644 --- a/Geekbot.net/Lib/Levels/LevelCalc.cs +++ b/src/Core/Levels/LevelCalc.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; -namespace Geekbot.net.Lib.Levels +namespace Geekbot.Core.Levels { public class LevelCalc : ILevelCalc { diff --git a/Geekbot.net/Lib/Localization/ITranslationHandler.cs b/src/Core/Localization/ITranslationHandler.cs similarity index 91% rename from Geekbot.net/Lib/Localization/ITranslationHandler.cs rename to src/Core/Localization/ITranslationHandler.cs index 9cd0680..74b3e88 100644 --- a/Geekbot.net/Lib/Localization/ITranslationHandler.cs +++ b/src/Core/Localization/ITranslationHandler.cs @@ -2,7 +2,7 @@ using System.Threading.Tasks; using Discord.Commands; -namespace Geekbot.net.Lib.Localization +namespace Geekbot.Core.Localization { public interface ITranslationHandler { diff --git a/Geekbot.net/Lib/Localization/TranslationGuildContext.cs b/src/Core/Localization/TranslationGuildContext.cs similarity index 95% rename from Geekbot.net/Lib/Localization/TranslationGuildContext.cs rename to src/Core/Localization/TranslationGuildContext.cs index fb65aa6..25685da 100644 --- a/Geekbot.net/Lib/Localization/TranslationGuildContext.cs +++ b/src/Core/Localization/TranslationGuildContext.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; -namespace Geekbot.net.Lib.Localization +namespace Geekbot.Core.Localization { public class TranslationGuildContext { diff --git a/Geekbot.net/Lib/Localization/TranslationHandler.cs b/src/Core/Localization/TranslationHandler.cs similarity index 96% rename from Geekbot.net/Lib/Localization/TranslationHandler.cs rename to src/Core/Localization/TranslationHandler.cs index 6166e6a..e38d9a1 100644 --- a/Geekbot.net/Lib/Localization/TranslationHandler.cs +++ b/src/Core/Localization/TranslationHandler.cs @@ -4,12 +4,12 @@ using System.IO; using System.Linq; using System.Threading.Tasks; using Discord.Commands; -using Geekbot.net.Lib.GuildSettingsManager; -using Geekbot.net.Lib.Logger; +using Geekbot.Core.GuildSettingsManager; +using Geekbot.Core.Logger; using YamlDotNet.Core; using YamlDotNet.Serialization; -namespace Geekbot.net.Lib.Localization +namespace Geekbot.Core.Localization { public class TranslationHandler : ITranslationHandler { diff --git a/Geekbot.net/Lib/Localization/Translations.yml b/src/Core/Localization/Translations.yml similarity index 100% rename from Geekbot.net/Lib/Localization/Translations.yml rename to src/Core/Localization/Translations.yml diff --git a/Geekbot.net/Lib/Logger/DiscordLogger.cs b/src/Core/Logger/DiscordLogger.cs similarity index 95% rename from Geekbot.net/Lib/Logger/DiscordLogger.cs rename to src/Core/Logger/DiscordLogger.cs index 688e26b..f6fb95a 100644 --- a/Geekbot.net/Lib/Logger/DiscordLogger.cs +++ b/src/Core/Logger/DiscordLogger.cs @@ -2,7 +2,7 @@ using System.Threading.Tasks; using Discord; -namespace Geekbot.net.Lib.Logger +namespace Geekbot.Core.Logger { public class DiscordLogger : IDiscordLogger { diff --git a/Geekbot.net/Lib/Logger/GeekbotLogger.cs b/src/Core/Logger/GeekbotLogger.cs similarity index 96% rename from Geekbot.net/Lib/Logger/GeekbotLogger.cs rename to src/Core/Logger/GeekbotLogger.cs index e2a3714..8d4a8eb 100644 --- a/Geekbot.net/Lib/Logger/GeekbotLogger.cs +++ b/src/Core/Logger/GeekbotLogger.cs @@ -1,7 +1,7 @@ using System; using Newtonsoft.Json; -namespace Geekbot.net.Lib.Logger +namespace Geekbot.Core.Logger { public class GeekbotLogger : IGeekbotLogger { diff --git a/Geekbot.net/Lib/Logger/IDiscordLogger.cs b/src/Core/Logger/IDiscordLogger.cs similarity index 76% rename from Geekbot.net/Lib/Logger/IDiscordLogger.cs rename to src/Core/Logger/IDiscordLogger.cs index fdc8c7f..c127e0c 100644 --- a/Geekbot.net/Lib/Logger/IDiscordLogger.cs +++ b/src/Core/Logger/IDiscordLogger.cs @@ -1,7 +1,7 @@ using System.Threading.Tasks; using Discord; -namespace Geekbot.net.Lib.Logger +namespace Geekbot.Core.Logger { public interface IDiscordLogger { diff --git a/Geekbot.net/Lib/Logger/IGeekbotLogger.cs b/src/Core/Logger/IGeekbotLogger.cs similarity index 92% rename from Geekbot.net/Lib/Logger/IGeekbotLogger.cs rename to src/Core/Logger/IGeekbotLogger.cs index 944524a..1363629 100644 --- a/Geekbot.net/Lib/Logger/IGeekbotLogger.cs +++ b/src/Core/Logger/IGeekbotLogger.cs @@ -1,6 +1,6 @@ using System; -namespace Geekbot.net.Lib.Logger +namespace Geekbot.Core.Logger { public interface IGeekbotLogger { diff --git a/Geekbot.net/Lib/Logger/LogDto.cs b/src/Core/Logger/LogDto.cs similarity index 88% rename from Geekbot.net/Lib/Logger/LogDto.cs rename to src/Core/Logger/LogDto.cs index 8ccfcdf..9db0c65 100644 --- a/Geekbot.net/Lib/Logger/LogDto.cs +++ b/src/Core/Logger/LogDto.cs @@ -1,6 +1,6 @@ using System; -namespace Geekbot.net.Lib.Logger +namespace Geekbot.Core.Logger { public class GeekbotLoggerObject { diff --git a/Geekbot.net/Lib/Logger/LogSource.cs b/src/Core/Logger/LogSource.cs similarity index 87% rename from Geekbot.net/Lib/Logger/LogSource.cs rename to src/Core/Logger/LogSource.cs index 48ad7d0..4518327 100644 --- a/Geekbot.net/Lib/Logger/LogSource.cs +++ b/src/Core/Logger/LogSource.cs @@ -1,7 +1,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Converters; -namespace Geekbot.net.Lib.Logger +namespace Geekbot.Core.Logger { [JsonConverter(typeof(StringEnumConverter))] public enum LogSource diff --git a/Geekbot.net/Lib/Logger/LoggerFactory.cs b/src/Core/Logger/LoggerFactory.cs similarity index 98% rename from Geekbot.net/Lib/Logger/LoggerFactory.cs rename to src/Core/Logger/LoggerFactory.cs index e31686e..bc129fc 100644 --- a/Geekbot.net/Lib/Logger/LoggerFactory.cs +++ b/src/Core/Logger/LoggerFactory.cs @@ -5,7 +5,7 @@ using NLog.Config; using NLog.Targets; using SumoLogic.Logging.NLog; -namespace Geekbot.net.Lib.Logger +namespace Geekbot.Core.Logger { public class LoggerFactory { diff --git a/Geekbot.net/Lib/Logger/MessageDto.cs b/src/Core/Logger/MessageDto.cs similarity index 92% rename from Geekbot.net/Lib/Logger/MessageDto.cs rename to src/Core/Logger/MessageDto.cs index 011acf3..039024e 100644 --- a/Geekbot.net/Lib/Logger/MessageDto.cs +++ b/src/Core/Logger/MessageDto.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Lib.Logger +namespace Geekbot.Core.Logger { public class MessageDto { diff --git a/Geekbot.net/Lib/Logger/SimpleConextConverter.cs b/src/Core/Logger/SimpleConextConverter.cs similarity index 96% rename from Geekbot.net/Lib/Logger/SimpleConextConverter.cs rename to src/Core/Logger/SimpleConextConverter.cs index 1eef12c..23cee40 100644 --- a/Geekbot.net/Lib/Logger/SimpleConextConverter.cs +++ b/src/Core/Logger/SimpleConextConverter.cs @@ -1,7 +1,7 @@ using Discord.Commands; using Discord.WebSocket; -namespace Geekbot.net.Lib.Logger +namespace Geekbot.Core.Logger { public class SimpleConextConverter { diff --git a/Geekbot.net/Lib/MalClient/IMalClient.cs b/src/Core/MalClient/IMalClient.cs similarity index 83% rename from Geekbot.net/Lib/MalClient/IMalClient.cs rename to src/Core/MalClient/IMalClient.cs index 6aaab05..70851c1 100644 --- a/Geekbot.net/Lib/MalClient/IMalClient.cs +++ b/src/Core/MalClient/IMalClient.cs @@ -1,7 +1,7 @@ using System.Threading.Tasks; using MyAnimeListSharp.Core; -namespace Geekbot.net.Lib.MalClient +namespace Geekbot.Core.MalClient { public interface IMalClient { diff --git a/Geekbot.net/Lib/MalClient/MalClient.cs b/src/Core/MalClient/MalClient.cs similarity index 92% rename from Geekbot.net/Lib/MalClient/MalClient.cs rename to src/Core/MalClient/MalClient.cs index 3f121ea..3f5f165 100644 --- a/Geekbot.net/Lib/MalClient/MalClient.cs +++ b/src/Core/MalClient/MalClient.cs @@ -1,11 +1,11 @@ using System.Threading.Tasks; -using Geekbot.net.Lib.GlobalSettings; -using Geekbot.net.Lib.Logger; +using Geekbot.Core.GlobalSettings; +using Geekbot.Core.Logger; using MyAnimeListSharp.Auth; using MyAnimeListSharp.Core; using MyAnimeListSharp.Facade.Async; -namespace Geekbot.net.Lib.MalClient +namespace Geekbot.Core.MalClient { public class MalClient : IMalClient { diff --git a/Geekbot.net/Lib/Media/FortunesProvider.cs b/src/Core/Media/FortunesProvider.cs similarity index 85% rename from Geekbot.net/Lib/Media/FortunesProvider.cs rename to src/Core/Media/FortunesProvider.cs index 56b5ed6..1b0d87a 100644 --- a/Geekbot.net/Lib/Media/FortunesProvider.cs +++ b/src/Core/Media/FortunesProvider.cs @@ -1,10 +1,10 @@ using System; using System.IO; -using Geekbot.net.Lib.Logger; +using Geekbot.Core.Logger; -namespace Geekbot.net.Lib.Media +namespace Geekbot.Core.Media { - internal class FortunesProvider : IFortunesProvider + public class FortunesProvider : IFortunesProvider { private readonly string[] _fortuneArray; private readonly int _totalFortunes; diff --git a/Geekbot.net/Lib/Media/IFortunesProvider.cs b/src/Core/Media/IFortunesProvider.cs similarity index 68% rename from Geekbot.net/Lib/Media/IFortunesProvider.cs rename to src/Core/Media/IFortunesProvider.cs index c82e45c..a4ef0d9 100644 --- a/Geekbot.net/Lib/Media/IFortunesProvider.cs +++ b/src/Core/Media/IFortunesProvider.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Lib.Media +namespace Geekbot.Core.Media { public interface IFortunesProvider { diff --git a/Geekbot.net/Lib/Media/IMediaProvider.cs b/src/Core/Media/IMediaProvider.cs similarity index 69% rename from Geekbot.net/Lib/Media/IMediaProvider.cs rename to src/Core/Media/IMediaProvider.cs index 63c0f41..03e32cf 100644 --- a/Geekbot.net/Lib/Media/IMediaProvider.cs +++ b/src/Core/Media/IMediaProvider.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Lib.Media +namespace Geekbot.Core.Media { public interface IMediaProvider { diff --git a/Geekbot.net/Lib/Media/MediaProvider.cs b/src/Core/Media/MediaProvider.cs similarity index 92% rename from Geekbot.net/Lib/Media/MediaProvider.cs rename to src/Core/Media/MediaProvider.cs index 5a9a055..4c72ee0 100644 --- a/Geekbot.net/Lib/Media/MediaProvider.cs +++ b/src/Core/Media/MediaProvider.cs @@ -1,10 +1,8 @@ -using System; -using System.Collections.Generic; -using System.IO; -using Geekbot.net.Lib.Logger; -using Geekbot.net.Lib.RandomNumberGenerator; +using System.IO; +using Geekbot.Core.Logger; +using Geekbot.Core.RandomNumberGenerator; -namespace Geekbot.net.Lib.Media +namespace Geekbot.Core.Media { public class MediaProvider : IMediaProvider { diff --git a/Geekbot.net/Lib/Media/MediaType.cs b/src/Core/Media/MediaType.cs similarity index 84% rename from Geekbot.net/Lib/Media/MediaType.cs rename to src/Core/Media/MediaType.cs index aee317b..fa30164 100644 --- a/Geekbot.net/Lib/Media/MediaType.cs +++ b/src/Core/Media/MediaType.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Lib.Media +namespace Geekbot.Core.Media { public enum MediaType { diff --git a/Geekbot.net/Lib/Polyfills/UserPolyfillDto.cs b/src/Core/Polyfills/UserPolyfillDto.cs similarity index 90% rename from Geekbot.net/Lib/Polyfills/UserPolyfillDto.cs rename to src/Core/Polyfills/UserPolyfillDto.cs index 32ea663..3a8f43f 100644 --- a/Geekbot.net/Lib/Polyfills/UserPolyfillDto.cs +++ b/src/Core/Polyfills/UserPolyfillDto.cs @@ -3,9 +3,9 @@ using System.Collections.Immutable; using System.Threading.Tasks; using Discord; -namespace Geekbot.net.Lib.Polyfills +namespace Geekbot.Core.Polyfills { - internal class UserPolyfillDto : IUser + public class UserPolyfillDto : IUser { public ulong Id { get; set; } public DateTimeOffset CreatedAt { get; set; } diff --git a/Geekbot.net/Lib/RandomNumberGenerator/IRandomNumberGenerator.cs b/src/Core/RandomNumberGenerator/IRandomNumberGenerator.cs similarity index 67% rename from Geekbot.net/Lib/RandomNumberGenerator/IRandomNumberGenerator.cs rename to src/Core/RandomNumberGenerator/IRandomNumberGenerator.cs index 32c6285..f817248 100644 --- a/Geekbot.net/Lib/RandomNumberGenerator/IRandomNumberGenerator.cs +++ b/src/Core/RandomNumberGenerator/IRandomNumberGenerator.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Lib.RandomNumberGenerator +namespace Geekbot.Core.RandomNumberGenerator { public interface IRandomNumberGenerator { diff --git a/Geekbot.net/Lib/RandomNumberGenerator/RandomNumberGenerator.cs b/src/Core/RandomNumberGenerator/RandomNumberGenerator.cs similarity index 92% rename from Geekbot.net/Lib/RandomNumberGenerator/RandomNumberGenerator.cs rename to src/Core/RandomNumberGenerator/RandomNumberGenerator.cs index 79b4620..63381b5 100644 --- a/Geekbot.net/Lib/RandomNumberGenerator/RandomNumberGenerator.cs +++ b/src/Core/RandomNumberGenerator/RandomNumberGenerator.cs @@ -1,7 +1,7 @@ using System; using System.Security.Cryptography; -namespace Geekbot.net.Lib.RandomNumberGenerator +namespace Geekbot.Core.RandomNumberGenerator { public class RandomNumberGenerator : IRandomNumberGenerator { diff --git a/Geekbot.net/Lib/ReactionListener/IReactionListener.cs b/src/Core/ReactionListener/IReactionListener.cs similarity index 89% rename from Geekbot.net/Lib/ReactionListener/IReactionListener.cs rename to src/Core/ReactionListener/IReactionListener.cs index b2ab9fb..4909d68 100644 --- a/Geekbot.net/Lib/ReactionListener/IReactionListener.cs +++ b/src/Core/ReactionListener/IReactionListener.cs @@ -2,7 +2,7 @@ using Discord; using Discord.WebSocket; -namespace Geekbot.net.Lib.ReactionListener +namespace Geekbot.Core.ReactionListener { public interface IReactionListener { diff --git a/Geekbot.net/Lib/ReactionListener/ReactionListener.cs b/src/Core/ReactionListener/ReactionListener.cs similarity index 92% rename from Geekbot.net/Lib/ReactionListener/ReactionListener.cs rename to src/Core/ReactionListener/ReactionListener.cs index bd335af..84367c9 100644 --- a/Geekbot.net/Lib/ReactionListener/ReactionListener.cs +++ b/src/Core/ReactionListener/ReactionListener.cs @@ -2,11 +2,11 @@ using System.Threading.Tasks; using Discord; using Discord.WebSocket; -using Geekbot.net.Database; -using Geekbot.net.Database.Models; -using Geekbot.net.Lib.Extensions; +using Geekbot.Core.Database; +using Geekbot.Core.Database.Models; +using Geekbot.Core.Extensions; -namespace Geekbot.net.Lib.ReactionListener +namespace Geekbot.Core.ReactionListener { public class ReactionListener : IReactionListener { diff --git a/Geekbot.net/Lib/RunParameters.cs b/src/Core/RunParameters.cs similarity index 97% rename from Geekbot.net/Lib/RunParameters.cs rename to src/Core/RunParameters.cs index eb8c078..3210587 100644 --- a/Geekbot.net/Lib/RunParameters.cs +++ b/src/Core/RunParameters.cs @@ -1,7 +1,7 @@ using System; using CommandLine; -namespace Geekbot.net.Lib +namespace Geekbot.Core { public class RunParameters { diff --git a/Geekbot.net/Lib/UserRepository/IUserRepository.cs b/src/Core/UserRepository/IUserRepository.cs similarity index 68% rename from Geekbot.net/Lib/UserRepository/IUserRepository.cs rename to src/Core/UserRepository/IUserRepository.cs index b2f9a1f..32598f6 100644 --- a/Geekbot.net/Lib/UserRepository/IUserRepository.cs +++ b/src/Core/UserRepository/IUserRepository.cs @@ -1,8 +1,8 @@ using System.Threading.Tasks; using Discord.WebSocket; -using Geekbot.net.Database.Models; +using Geekbot.Core.Database.Models; -namespace Geekbot.net.Lib.UserRepository +namespace Geekbot.Core.UserRepository { public interface IUserRepository { diff --git a/Geekbot.net/Lib/UserRepository/UserRepository.cs b/src/Core/UserRepository/UserRepository.cs similarity index 88% rename from Geekbot.net/Lib/UserRepository/UserRepository.cs rename to src/Core/UserRepository/UserRepository.cs index 41e8e73..94d5df4 100644 --- a/Geekbot.net/Lib/UserRepository/UserRepository.cs +++ b/src/Core/UserRepository/UserRepository.cs @@ -1,14 +1,13 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Discord.WebSocket; -using Geekbot.net.Database; -using Geekbot.net.Database.Models; -using Geekbot.net.Lib.Extensions; -using Geekbot.net.Lib.Logger; +using Geekbot.Core.Database; +using Geekbot.Core.Database.Models; +using Geekbot.Core.Extensions; +using Geekbot.Core.Logger; -namespace Geekbot.net.Lib.UserRepository +namespace Geekbot.Core.UserRepository { public class UserRepository : IUserRepository { diff --git a/Geekbot.net/Lib/WikipediaClient/IWikipediaClient.cs b/src/Core/WikipediaClient/IWikipediaClient.cs similarity index 63% rename from Geekbot.net/Lib/WikipediaClient/IWikipediaClient.cs rename to src/Core/WikipediaClient/IWikipediaClient.cs index c6cdf3d..fdb1ae1 100644 --- a/Geekbot.net/Lib/WikipediaClient/IWikipediaClient.cs +++ b/src/Core/WikipediaClient/IWikipediaClient.cs @@ -1,7 +1,7 @@ using System.Threading.Tasks; -using Geekbot.net.Lib.WikipediaClient.Page; +using Geekbot.Core.WikipediaClient.Page; -namespace Geekbot.net.Lib.WikipediaClient +namespace Geekbot.Core.WikipediaClient { public interface IWikipediaClient { diff --git a/Geekbot.net/Lib/WikipediaClient/Page/PageApiUrls.cs b/src/Core/WikipediaClient/Page/PageApiUrls.cs similarity index 84% rename from Geekbot.net/Lib/WikipediaClient/Page/PageApiUrls.cs rename to src/Core/WikipediaClient/Page/PageApiUrls.cs index 803f4d7..6e3a1b6 100644 --- a/Geekbot.net/Lib/WikipediaClient/Page/PageApiUrls.cs +++ b/src/Core/WikipediaClient/Page/PageApiUrls.cs @@ -1,6 +1,6 @@ using System; -namespace Geekbot.net.Lib.WikipediaClient.Page +namespace Geekbot.Core.WikipediaClient.Page { public class PageApiUrls { diff --git a/Geekbot.net/Lib/WikipediaClient/Page/PageContentUrlCollection.cs b/src/Core/WikipediaClient/Page/PageContentUrlCollection.cs similarity index 73% rename from Geekbot.net/Lib/WikipediaClient/Page/PageContentUrlCollection.cs rename to src/Core/WikipediaClient/Page/PageContentUrlCollection.cs index 614aaa7..3b567a7 100644 --- a/Geekbot.net/Lib/WikipediaClient/Page/PageContentUrlCollection.cs +++ b/src/Core/WikipediaClient/Page/PageContentUrlCollection.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Lib.WikipediaClient.Page +namespace Geekbot.Core.WikipediaClient.Page { public class PageContentUrlCollection { diff --git a/Geekbot.net/Lib/WikipediaClient/Page/PageContentUrls.cs b/src/Core/WikipediaClient/Page/PageContentUrls.cs similarity index 79% rename from Geekbot.net/Lib/WikipediaClient/Page/PageContentUrls.cs rename to src/Core/WikipediaClient/Page/PageContentUrls.cs index faf7bb5..ca30b43 100644 --- a/Geekbot.net/Lib/WikipediaClient/Page/PageContentUrls.cs +++ b/src/Core/WikipediaClient/Page/PageContentUrls.cs @@ -1,6 +1,6 @@ using System; -namespace Geekbot.net.Lib.WikipediaClient.Page +namespace Geekbot.Core.WikipediaClient.Page { public class PageContentUrls { diff --git a/Geekbot.net/Lib/WikipediaClient/Page/PageCoordinates.cs b/src/Core/WikipediaClient/Page/PageCoordinates.cs similarity index 68% rename from Geekbot.net/Lib/WikipediaClient/Page/PageCoordinates.cs rename to src/Core/WikipediaClient/Page/PageCoordinates.cs index ce67f9b..52c31a4 100644 --- a/Geekbot.net/Lib/WikipediaClient/Page/PageCoordinates.cs +++ b/src/Core/WikipediaClient/Page/PageCoordinates.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Lib.WikipediaClient.Page +namespace Geekbot.Core.WikipediaClient.Page { public class PageCoordinates { diff --git a/Geekbot.net/Lib/WikipediaClient/Page/PageImage.cs b/src/Core/WikipediaClient/Page/PageImage.cs similarity index 76% rename from Geekbot.net/Lib/WikipediaClient/Page/PageImage.cs rename to src/Core/WikipediaClient/Page/PageImage.cs index cdcc2a9..8c4fb82 100644 --- a/Geekbot.net/Lib/WikipediaClient/Page/PageImage.cs +++ b/src/Core/WikipediaClient/Page/PageImage.cs @@ -1,6 +1,6 @@ using System; -namespace Geekbot.net.Lib.WikipediaClient.Page +namespace Geekbot.Core.WikipediaClient.Page { public class PageImage { diff --git a/Geekbot.net/Lib/WikipediaClient/Page/PageNamespace.cs b/src/Core/WikipediaClient/Page/PageNamespace.cs similarity index 68% rename from Geekbot.net/Lib/WikipediaClient/Page/PageNamespace.cs rename to src/Core/WikipediaClient/Page/PageNamespace.cs index 798e6b9..0691ac3 100644 --- a/Geekbot.net/Lib/WikipediaClient/Page/PageNamespace.cs +++ b/src/Core/WikipediaClient/Page/PageNamespace.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Lib.WikipediaClient.Page +namespace Geekbot.Core.WikipediaClient.Page { public class PageNamespace { diff --git a/Geekbot.net/Lib/WikipediaClient/Page/PagePreview.cs b/src/Core/WikipediaClient/Page/PagePreview.cs similarity index 94% rename from Geekbot.net/Lib/WikipediaClient/Page/PagePreview.cs rename to src/Core/WikipediaClient/Page/PagePreview.cs index 37434d3..1c1749d 100644 --- a/Geekbot.net/Lib/WikipediaClient/Page/PagePreview.cs +++ b/src/Core/WikipediaClient/Page/PagePreview.cs @@ -2,7 +2,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Converters; -namespace Geekbot.net.Lib.WikipediaClient.Page +namespace Geekbot.Core.WikipediaClient.Page { public class PagePreview { diff --git a/Geekbot.net/Lib/WikipediaClient/Page/PageTitles.cs b/src/Core/WikipediaClient/Page/PageTitles.cs similarity index 76% rename from Geekbot.net/Lib/WikipediaClient/Page/PageTitles.cs rename to src/Core/WikipediaClient/Page/PageTitles.cs index dcc2cea..ad83b27 100644 --- a/Geekbot.net/Lib/WikipediaClient/Page/PageTitles.cs +++ b/src/Core/WikipediaClient/Page/PageTitles.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.Lib.WikipediaClient.Page +namespace Geekbot.Core.WikipediaClient.Page { public class PageTitles { diff --git a/Geekbot.net/Lib/WikipediaClient/Page/PageTypes.cs b/src/Core/WikipediaClient/Page/PageTypes.cs similarity index 84% rename from Geekbot.net/Lib/WikipediaClient/Page/PageTypes.cs rename to src/Core/WikipediaClient/Page/PageTypes.cs index 63cd4d2..8bc9f64 100644 --- a/Geekbot.net/Lib/WikipediaClient/Page/PageTypes.cs +++ b/src/Core/WikipediaClient/Page/PageTypes.cs @@ -1,6 +1,6 @@ using System.Runtime.Serialization; -namespace Geekbot.net.Lib.WikipediaClient.Page +namespace Geekbot.Core.WikipediaClient.Page { public enum PageTypes { diff --git a/Geekbot.net/Lib/WikipediaClient/WikipediaClient.cs b/src/Core/WikipediaClient/WikipediaClient.cs similarity index 87% rename from Geekbot.net/Lib/WikipediaClient/WikipediaClient.cs rename to src/Core/WikipediaClient/WikipediaClient.cs index ed4902a..f577d92 100644 --- a/Geekbot.net/Lib/WikipediaClient/WikipediaClient.cs +++ b/src/Core/WikipediaClient/WikipediaClient.cs @@ -1,9 +1,9 @@ using System.Net.Http; using System.Threading.Tasks; -using Geekbot.net.Lib.WikipediaClient.Page; +using Geekbot.Core.WikipediaClient.Page; using Newtonsoft.Json; -namespace Geekbot.net.Lib.WikipediaClient +namespace Geekbot.Core.WikipediaClient { public class WikipediaClient : IWikipediaClient { diff --git a/Geekbot.net/WebApi/ApiError.cs b/src/Web/ApiError.cs similarity index 70% rename from Geekbot.net/WebApi/ApiError.cs rename to src/Web/ApiError.cs index 182518e..3708d2c 100644 --- a/Geekbot.net/WebApi/ApiError.cs +++ b/src/Web/ApiError.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.WebApi +namespace Geekbot.Web { public class ApiError { diff --git a/Geekbot.net/WebApi/Controllers/Callback/CallbackController.cs b/src/Web/Controllers/Callback/CallbackController.cs similarity index 96% rename from Geekbot.net/WebApi/Controllers/Callback/CallbackController.cs rename to src/Web/Controllers/Callback/CallbackController.cs index 78fb38d..b3927bc 100644 --- a/Geekbot.net/WebApi/Controllers/Callback/CallbackController.cs +++ b/src/Web/Controllers/Callback/CallbackController.cs @@ -4,11 +4,11 @@ using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; using Discord.WebSocket; -using Geekbot.net.Lib.GlobalSettings; +using Geekbot.Core.GlobalSettings; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; -namespace Geekbot.net.WebApi.Controllers.Callback +namespace Geekbot.Web.Controllers.Callback { public class CallbackController : Controller { diff --git a/Geekbot.net/WebApi/Controllers/Callback/CallbackTokenResponseDto.cs b/src/Web/Controllers/Callback/CallbackTokenResponseDto.cs similarity index 85% rename from Geekbot.net/WebApi/Controllers/Callback/CallbackTokenResponseDto.cs rename to src/Web/Controllers/Callback/CallbackTokenResponseDto.cs index 3c81592..37d2c32 100644 --- a/Geekbot.net/WebApi/Controllers/Callback/CallbackTokenResponseDto.cs +++ b/src/Web/Controllers/Callback/CallbackTokenResponseDto.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.WebApi.Controllers.Callback +namespace Geekbot.Web.Controllers.Callback { public class CallbackTokenResponseDto { diff --git a/Geekbot.net/WebApi/Controllers/Commands/CommandController.cs b/src/Web/Controllers/Commands/CommandController.cs similarity index 93% rename from Geekbot.net/WebApi/Controllers/Commands/CommandController.cs rename to src/Web/Controllers/Commands/CommandController.cs index 74f6e3c..e6c73e3 100644 --- a/Geekbot.net/WebApi/Controllers/Commands/CommandController.cs +++ b/src/Web/Controllers/Commands/CommandController.cs @@ -3,7 +3,7 @@ using Discord.Commands; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; -namespace Geekbot.net.WebApi.Controllers.Commands +namespace Geekbot.Web.Controllers.Commands { [EnableCors("AllowSpecificOrigin")] public class CommandController : Controller diff --git a/Geekbot.net/WebApi/Controllers/Commands/CommandDto.cs b/src/Web/Controllers/Commands/CommandDto.cs similarity index 83% rename from Geekbot.net/WebApi/Controllers/Commands/CommandDto.cs rename to src/Web/Controllers/Commands/CommandDto.cs index 981d0f2..7183a75 100644 --- a/Geekbot.net/WebApi/Controllers/Commands/CommandDto.cs +++ b/src/Web/Controllers/Commands/CommandDto.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace Geekbot.net.WebApi.Controllers.Commands +namespace Geekbot.Web.Controllers.Commands { public class CommandDto { diff --git a/Geekbot.net/WebApi/Controllers/Commands/CommandParamDto.cs b/src/Web/Controllers/Commands/CommandParamDto.cs similarity index 74% rename from Geekbot.net/WebApi/Controllers/Commands/CommandParamDto.cs rename to src/Web/Controllers/Commands/CommandParamDto.cs index 5f7519d..77c9da6 100644 --- a/Geekbot.net/WebApi/Controllers/Commands/CommandParamDto.cs +++ b/src/Web/Controllers/Commands/CommandParamDto.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.WebApi.Controllers.Commands +namespace Geekbot.Web.Controllers.Commands { public class CommandParamDto { diff --git a/Geekbot.net/WebApi/Controllers/Highscores/HighscoreController.cs b/src/Web/Controllers/Highscores/HighscoreController.cs similarity index 92% rename from Geekbot.net/WebApi/Controllers/Highscores/HighscoreController.cs rename to src/Web/Controllers/Highscores/HighscoreController.cs index 3cccb0e..e990431 100644 --- a/Geekbot.net/WebApi/Controllers/Highscores/HighscoreController.cs +++ b/src/Web/Controllers/Highscores/HighscoreController.cs @@ -1,9 +1,9 @@ using System.Collections.Generic; -using Geekbot.net.Lib.Highscores; +using Geekbot.Core.Highscores; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; -namespace Geekbot.net.WebApi.Controllers.Highscores +namespace Geekbot.Web.Controllers.Highscores { [EnableCors("AllowSpecificOrigin")] public class HighscoreController : Controller diff --git a/Geekbot.net/WebApi/Controllers/Highscores/HighscoreControllerPostBodyDto.cs b/src/Web/Controllers/Highscores/HighscoreControllerPostBodyDto.cs similarity index 76% rename from Geekbot.net/WebApi/Controllers/Highscores/HighscoreControllerPostBodyDto.cs rename to src/Web/Controllers/Highscores/HighscoreControllerPostBodyDto.cs index 6e7aec3..c3fe6a8 100644 --- a/Geekbot.net/WebApi/Controllers/Highscores/HighscoreControllerPostBodyDto.cs +++ b/src/Web/Controllers/Highscores/HighscoreControllerPostBodyDto.cs @@ -1,7 +1,7 @@ using System.ComponentModel.DataAnnotations; -using Geekbot.net.Lib.Highscores; +using Geekbot.Core.Highscores; -namespace Geekbot.net.WebApi.Controllers.Highscores +namespace Geekbot.Web.Controllers.Highscores { public class HighscoreControllerPostBodyDto { diff --git a/Geekbot.net/WebApi/Controllers/Highscores/HighscoreControllerReponseBody.cs b/src/Web/Controllers/Highscores/HighscoreControllerReponseBody.cs similarity index 66% rename from Geekbot.net/WebApi/Controllers/Highscores/HighscoreControllerReponseBody.cs rename to src/Web/Controllers/Highscores/HighscoreControllerReponseBody.cs index 0e59880..3cea17f 100644 --- a/Geekbot.net/WebApi/Controllers/Highscores/HighscoreControllerReponseBody.cs +++ b/src/Web/Controllers/Highscores/HighscoreControllerReponseBody.cs @@ -1,6 +1,6 @@ -using Geekbot.net.Lib.Highscores; +using Geekbot.Core.Highscores; -namespace Geekbot.net.WebApi.Controllers.Highscores +namespace Geekbot.Web.Controllers.Highscores { public class HighscoreControllerReponseBody { diff --git a/Geekbot.net/WebApi/Controllers/Status/ApiStatusDto.cs b/src/Web/Controllers/Status/ApiStatusDto.cs similarity index 75% rename from Geekbot.net/WebApi/Controllers/Status/ApiStatusDto.cs rename to src/Web/Controllers/Status/ApiStatusDto.cs index 0d5e6ad..cb2e5c7 100644 --- a/Geekbot.net/WebApi/Controllers/Status/ApiStatusDto.cs +++ b/src/Web/Controllers/Status/ApiStatusDto.cs @@ -1,4 +1,4 @@ -namespace Geekbot.net.WebApi.Controllers.Status +namespace Geekbot.Web.Controllers.Status { public class ApiStatusDto { diff --git a/Geekbot.net/WebApi/Controllers/Status/StatusController.cs b/src/Web/Controllers/Status/StatusController.cs similarity index 89% rename from Geekbot.net/WebApi/Controllers/Status/StatusController.cs rename to src/Web/Controllers/Status/StatusController.cs index c437e64..881462a 100644 --- a/Geekbot.net/WebApi/Controllers/Status/StatusController.cs +++ b/src/Web/Controllers/Status/StatusController.cs @@ -1,9 +1,9 @@ using System.Globalization; -using Geekbot.net.Lib; +using Geekbot.Core; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; -namespace Geekbot.net.WebApi.Controllers.Status +namespace Geekbot.Web.Controllers.Status { [EnableCors("AllowSpecificOrigin")] public class StatusController : Controller diff --git a/Geekbot.net/WebApi/Logging/AspLogProvider.cs b/src/Web/Logging/AspLogProvider.cs similarity index 88% rename from Geekbot.net/WebApi/Logging/AspLogProvider.cs rename to src/Web/Logging/AspLogProvider.cs index d35872d..25fdace 100644 --- a/Geekbot.net/WebApi/Logging/AspLogProvider.cs +++ b/src/Web/Logging/AspLogProvider.cs @@ -1,8 +1,8 @@ using System.Collections.Concurrent; -using Geekbot.net.Lib.Logger; +using Geekbot.Core.Logger; using Microsoft.Extensions.Logging; -namespace Geekbot.net.WebApi.Logging +namespace Geekbot.Web.Logging { public class AspLogProvider : ILoggerProvider { diff --git a/Geekbot.net/WebApi/Logging/AspLogger.cs b/src/Web/Logging/AspLogger.cs similarity index 95% rename from Geekbot.net/WebApi/Logging/AspLogger.cs rename to src/Web/Logging/AspLogger.cs index 5899b26..c18a7f3 100644 --- a/Geekbot.net/WebApi/Logging/AspLogger.cs +++ b/src/Web/Logging/AspLogger.cs @@ -1,8 +1,8 @@ using System; -using Geekbot.net.Lib.Logger; +using Geekbot.Core.Logger; using Microsoft.Extensions.Logging; -namespace Geekbot.net.WebApi.Logging +namespace Geekbot.Web.Logging { public class AspLogger : ILogger { diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj new file mode 100644 index 0000000..429165b --- /dev/null +++ b/src/Web/Web.csproj @@ -0,0 +1,26 @@ + + + + net5.0 + $(VersionSuffix) + $(VersionSuffix) + 0.0.0-DEV + Geekbot.Web + Geekbot.Web + NU1701 + + + + + + + + + + + + + + + + diff --git a/Geekbot.net/WebApi/WebApiStartup.cs b/src/Web/WebApiStartup.cs similarity index 86% rename from Geekbot.net/WebApi/WebApiStartup.cs rename to src/Web/WebApiStartup.cs index 7d3adc9..9aeedf9 100644 --- a/Geekbot.net/WebApi/WebApiStartup.cs +++ b/src/Web/WebApiStartup.cs @@ -2,19 +2,19 @@ using System.Reflection; using Discord.Commands; using Discord.WebSocket; -using Geekbot.net.Database; -using Geekbot.net.Lib; -using Geekbot.net.Lib.GlobalSettings; -using Geekbot.net.Lib.Highscores; -using Geekbot.net.Lib.Logger; -using Geekbot.net.WebApi.Logging; +using Geekbot.Core; +using Geekbot.Core.Database; +using Geekbot.Core.GlobalSettings; +using Geekbot.Core.Highscores; +using Geekbot.Core.Logger; +using Geekbot.Web.Logging; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -namespace Geekbot.net.WebApi +namespace Geekbot.Web { public static class WebApiStartup { @@ -51,7 +51,7 @@ namespace Geekbot.net.WebApi logging.SetMinimumLevel(LogLevel.Debug); logging.AddProvider(new AspLogProvider(logger)); }) - .UseSetting(WebHostDefaults.ApplicationKey, typeof(Program).GetTypeInfo().Assembly.FullName) + .UseSetting(WebHostDefaults.ApplicationKey, typeof(WebApiStartup).GetTypeInfo().Assembly.FullName) .Build().Run(); } } From 61ce14a61df972b644bcc214fb3ceae7cb4ef996 Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 8 Aug 2020 22:33:02 +0200 Subject: [PATCH 371/553] Change .gitlab-ci and dockerfile to fit the new project structure --- .gitlab-ci.yml | 4 ++-- Dockerfile | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3d362ce..410e380 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,7 +5,7 @@ stages: - ops variables: - VERSION: 4.2.0-$CI_COMMIT_SHORT_SHA + VERSION: 4.3.0-$CI_COMMIT_SHORT_SHA IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG Build: @@ -18,7 +18,7 @@ Build: script: - dotnet restore - dotnet test Tests - - dotnet publish --version-suffix $VERSION -r linux-x64 -c Release -o ./app ./Geekbot.net/ + - dotnet publish --version-suffix $VERSION -r linux-x64 -c Release -o ./app ./src/Bot/ Package: stage: docker diff --git a/Dockerfile b/Dockerfile index 822471d..479dd40 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,4 +4,4 @@ COPY ./app /app/ EXPOSE 12995/tcp WORKDIR /app -ENTRYPOINT ./Geekbot.net +ENTRYPOINT ./Geekbot From 97ad54df9e34c24638310158c941040827fc2250 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 13 Aug 2020 17:22:18 +0200 Subject: [PATCH 372/553] Rename the folder Tests to tests --- Geekbot.net.sln | 2 +- {Tests => tests}/Core/Converters/EmojiConverter.test.cs | 0 {Tests => tests}/Core/DiceParser/DiceParser.test.cs | 0 {Tests => tests}/Core/DiceParser/SingleDie.test.cs | 0 {Tests => tests}/Core/Levels/LevelCalc.test.cs | 0 .../Core/Localization/TranslationGuildContext.test.cs | 0 {Tests => tests}/Core/Localization/Translations.test.cs | 0 {Tests => tests}/TestData.cs | 0 {Tests => tests}/Tests.csproj | 0 9 files changed, 1 insertion(+), 1 deletion(-) rename {Tests => tests}/Core/Converters/EmojiConverter.test.cs (100%) rename {Tests => tests}/Core/DiceParser/DiceParser.test.cs (100%) rename {Tests => tests}/Core/DiceParser/SingleDie.test.cs (100%) rename {Tests => tests}/Core/Levels/LevelCalc.test.cs (100%) rename {Tests => tests}/Core/Localization/TranslationGuildContext.test.cs (100%) rename {Tests => tests}/Core/Localization/Translations.test.cs (100%) rename {Tests => tests}/TestData.cs (100%) rename {Tests => tests}/Tests.csproj (100%) diff --git a/Geekbot.net.sln b/Geekbot.net.sln index 5dc5e4b..4a5b912 100644 --- a/Geekbot.net.sln +++ b/Geekbot.net.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 VisualStudioVersion = 12.0.0.0 MinimumVisualStudioVersion = 10.0.0.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "tests\Tests.csproj", "{4CAF5F02-EFFE-4FDA-BD44-EEADDBA9600E}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "src\Core\Core.csproj", "{47671723-52A9-4668-BBC5-2BA76AE3B288}" EndProject diff --git a/Tests/Core/Converters/EmojiConverter.test.cs b/tests/Core/Converters/EmojiConverter.test.cs similarity index 100% rename from Tests/Core/Converters/EmojiConverter.test.cs rename to tests/Core/Converters/EmojiConverter.test.cs diff --git a/Tests/Core/DiceParser/DiceParser.test.cs b/tests/Core/DiceParser/DiceParser.test.cs similarity index 100% rename from Tests/Core/DiceParser/DiceParser.test.cs rename to tests/Core/DiceParser/DiceParser.test.cs diff --git a/Tests/Core/DiceParser/SingleDie.test.cs b/tests/Core/DiceParser/SingleDie.test.cs similarity index 100% rename from Tests/Core/DiceParser/SingleDie.test.cs rename to tests/Core/DiceParser/SingleDie.test.cs diff --git a/Tests/Core/Levels/LevelCalc.test.cs b/tests/Core/Levels/LevelCalc.test.cs similarity index 100% rename from Tests/Core/Levels/LevelCalc.test.cs rename to tests/Core/Levels/LevelCalc.test.cs diff --git a/Tests/Core/Localization/TranslationGuildContext.test.cs b/tests/Core/Localization/TranslationGuildContext.test.cs similarity index 100% rename from Tests/Core/Localization/TranslationGuildContext.test.cs rename to tests/Core/Localization/TranslationGuildContext.test.cs diff --git a/Tests/Core/Localization/Translations.test.cs b/tests/Core/Localization/Translations.test.cs similarity index 100% rename from Tests/Core/Localization/Translations.test.cs rename to tests/Core/Localization/Translations.test.cs diff --git a/Tests/TestData.cs b/tests/TestData.cs similarity index 100% rename from Tests/TestData.cs rename to tests/TestData.cs diff --git a/Tests/Tests.csproj b/tests/Tests.csproj similarity index 100% rename from Tests/Tests.csproj rename to tests/Tests.csproj From bd117e25956b5a5e4f822c42793014600182d59f Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 13 Aug 2020 17:42:33 +0200 Subject: [PATCH 373/553] Fix Translations file path --- src/Core/Localization/TranslationHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/Localization/TranslationHandler.cs b/src/Core/Localization/TranslationHandler.cs index e38d9a1..c7d35e9 100644 --- a/src/Core/Localization/TranslationHandler.cs +++ b/src/Core/Localization/TranslationHandler.cs @@ -32,7 +32,7 @@ namespace Geekbot.Core.Localization try { // Read the file - var translationFile = File.ReadAllText(Path.GetFullPath("./Lib/Localization/Translations.yml")); + var translationFile = File.ReadAllText(Path.GetFullPath("./Localization/Translations.yml")); // Deserialize var input = new StringReader(translationFile); From d68ce459ef5e9e54af3aff113c46df483ea98aa2 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 13 Aug 2020 17:47:28 +0200 Subject: [PATCH 374/553] Fix CI Pipeline: tests should be executed from the tests folder (with a lowercase t) --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 410e380..8efd1d1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -17,7 +17,7 @@ Build: - app script: - dotnet restore - - dotnet test Tests + - dotnet test tests - dotnet publish --version-suffix $VERSION -r linux-x64 -c Release -o ./app ./src/Bot/ Package: From 7942308059ada47dbd14cff9a7b630d00c624344 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 13 Aug 2020 18:22:09 +0200 Subject: [PATCH 375/553] Alias "!quote save" with "!quote add" --- src/Bot/Commands/Utils/Quote/Quote.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index 4022753..9fe1431 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -58,9 +58,10 @@ namespace Geekbot.Bot.Commands.Utils.Quote } } - [Command("save")] - [Summary("Save a quote from the last sent message by @user")] - public async Task SaveQuote([Summary("@someone")] IUser user) + [Command("add")] + [Alias("save")] + [Summary("Add a quote from the last sent message by @user")] + public async Task AddQuote([Summary("@someone")] IUser user) { try { @@ -94,9 +95,10 @@ namespace Geekbot.Bot.Commands.Utils.Quote } } - [Command("save")] - [Summary("Save a quote from a message id")] - public async Task SaveQuote([Summary("message-ID")] ulong messageId) + [Command("add")] + [Alias("save")] + [Summary("Add a quote from a message id")] + public async Task AddQuote([Summary("message-ID")] ulong messageId) { try { From ad086a5e0c43d0b7d1181e29d10b5d1e190f6d8e Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 13 Aug 2020 19:51:56 +0200 Subject: [PATCH 376/553] Make it possible to create quotes from message links --- src/Bot/Commands/Utils/Quote/MessageLink.cs | 47 ++++++++++ src/Bot/Commands/Utils/Quote/Quote.cs | 95 ++++++++++++++++++++- src/Core/Localization/Translations.yml | 6 ++ 3 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 src/Bot/Commands/Utils/Quote/MessageLink.cs diff --git a/src/Bot/Commands/Utils/Quote/MessageLink.cs b/src/Bot/Commands/Utils/Quote/MessageLink.cs new file mode 100644 index 0000000..d789d15 --- /dev/null +++ b/src/Bot/Commands/Utils/Quote/MessageLink.cs @@ -0,0 +1,47 @@ +using System; +using System.Data; +using System.Text.RegularExpressions; + +namespace Geekbot.Bot.Commands.Utils.Quote +{ + public class MessageLink + { + public readonly static Regex re = new Regex( + @"https:\/\/(canary|ptb)?.discord(app)?.com\/channels\/(?\d{16,20})\/(?\d{16,20})\/(?\d{16,20})", + RegexOptions.Compiled | RegexOptions.IgnoreCase, + new TimeSpan(0, 0, 2)); + + public ulong GuildId { get; set; } + public ulong ChannelId { get; set; } + public ulong MessageId { get; set; } + + public MessageLink(string url) + { + var matches = re.Matches(url); + + foreach (Match match in matches) + { + foreach (Group matchGroup in match.Groups) + { + switch (matchGroup.Name) + { + case "GuildId": + GuildId = ulong.Parse(matchGroup.Value); + break; + case "ChannelId": + ChannelId = ulong.Parse(matchGroup.Value); + break; + case "MessageId": + MessageId = ulong.Parse(matchGroup.Value); + break; + } + } + } + } + + public static bool IsValid(string link) + { + return re.IsMatch(link); + } + } +} \ No newline at end of file diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index 9fe1431..1e49a84 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -82,7 +82,7 @@ namespace Geekbot.Bot.Commands.Utils.Quote if (lastMessage == null) return; var quote = CreateQuoteObject(lastMessage); - _database.Quotes.Add(quote); + await _database.Quotes.AddAsync(quote); await _database.SaveChangesAsync(); var embed = QuoteBuilder(quote); @@ -117,7 +117,61 @@ namespace Geekbot.Bot.Commands.Utils.Quote } var quote = CreateQuoteObject(message); - _database.Quotes.Add(quote); + await _database.Quotes.AddAsync(quote); + await _database.SaveChangesAsync(); + + var embed = QuoteBuilder(quote); + await ReplyAsync(transContext.GetString("QuoteAdded"), false, embed.Build()); + } + catch (Exception e) + { + await _errorHandler.HandleCommandException(e, Context, + "I couldn't find a message with that id :disappointed:"); + } + } + + [Command("add")] + [Alias("save")] + [Summary("Add a quote from a message link")] + public async Task AddQuote([Summary("message-link")] string messageLink) + { + try + { + var transContext = await _translationHandler.GetGuildContext(Context); + + if (!MessageLink.IsValid(messageLink)) + { + await ReplyAsync(transContext.GetString("NotAValidMessageLink")); + return; + } + + var link = new MessageLink(messageLink); + if (link.GuildId != Context.Guild.Id) + { + await ReplyAsync(transContext.GetString("OnlyQuoteFromSameServer")); + return; + } + + var channel = link.ChannelId == Context.Channel.Id + ? Context.Channel + : await Context.Guild.GetTextChannelAsync(link.ChannelId); + + var message = await channel.GetMessageAsync(link.MessageId); + + if (message.Author.Id == Context.Message.Author.Id) + { + await ReplyAsync(transContext.GetString("CannotSaveOwnQuotes")); + return; + } + + if (message.Author.IsBot) + { + await ReplyAsync(transContext.GetString("CannotQuoteBots")); + return; + } + + var quote = CreateQuoteObject(message); + await _database.Quotes.AddAsync(quote); await _database.SaveChangesAsync(); var embed = QuoteBuilder(quote); @@ -167,6 +221,43 @@ namespace Geekbot.Bot.Commands.Utils.Quote } } + [Command("make")] + [Summary("Create a quote from a message link")] + public async Task ReturnSpecifiedQuote([Summary("message-link")] string messageLink) + { + try + { + var transContext = await _translationHandler.GetGuildContext(Context); + + if (!MessageLink.IsValid(messageLink)) + { + await ReplyAsync(transContext.GetString("NotAValidMessageLink")); + return; + } + + var link = new MessageLink(messageLink); + if (link.GuildId != Context.Guild.Id) + { + await ReplyAsync(transContext.GetString("OnlyQuoteFromSameServer")); + return; + } + + var channel = link.ChannelId == Context.Channel.Id + ? Context.Channel + : await Context.Guild.GetTextChannelAsync(link.ChannelId); + + var message = await channel.GetMessageAsync(link.MessageId); + var quote = CreateQuoteObject(message); + var embed = QuoteBuilder(quote); + await ReplyAsync("", false, embed.Build()); + } + catch (Exception e) + { + await _errorHandler.HandleCommandException(e, Context, + "I couldn't find that message :disappointed:"); + } + } + [Command("remove")] [RequireUserPermission(GuildPermission.ManageMessages)] [Summary("Remove a quote (user needs the 'ManageMessages' permission)")] diff --git a/src/Core/Localization/Translations.yml b/src/Core/Localization/Translations.yml index 3c59977..fbb55bf 100644 --- a/src/Core/Localization/Translations.yml +++ b/src/Core/Localization/Translations.yml @@ -169,6 +169,12 @@ quote: MostQuotesPerson: EN: "Most quoted person" CHDE: "Meist quoteti person" + NotAValidMessageLink: + EN: "That is not a valid message link" + CHDE: "Das isch kei korrete nachrichtelink" + OnlyQuoteFromSameServer: + EN: "You can only quote messages from the same server" + CHDE: "Du chasch numme nachrichte vom gliche server quote" rank: InvalidType: EN: "Valid types are '`messages`' '`karma`', '`rolls`' and '`cookies`'" From 726ee77ed4fb3e1fb6933ba2d421be96aaba0888 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 13 Aug 2020 20:04:54 +0200 Subject: [PATCH 377/553] Fix bug where message links from discord stable would be considered invalid --- src/Bot/Commands/Utils/Quote/MessageLink.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Bot/Commands/Utils/Quote/MessageLink.cs b/src/Bot/Commands/Utils/Quote/MessageLink.cs index d789d15..dff1273 100644 --- a/src/Bot/Commands/Utils/Quote/MessageLink.cs +++ b/src/Bot/Commands/Utils/Quote/MessageLink.cs @@ -7,7 +7,7 @@ namespace Geekbot.Bot.Commands.Utils.Quote public class MessageLink { public readonly static Regex re = new Regex( - @"https:\/\/(canary|ptb)?.discord(app)?.com\/channels\/(?\d{16,20})\/(?\d{16,20})\/(?\d{16,20})", + @"https:\/\/((canary|ptb)\.)?discord(app)?.com\/channels\/(?\d{16,20})\/(?\d{16,20})\/(?\d{16,20})", RegexOptions.Compiled | RegexOptions.IgnoreCase, new TimeSpan(0, 0, 2)); From 187fd6a04f95c59044c9369de4ef145576d64982 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 13 Aug 2020 22:46:53 +0200 Subject: [PATCH 378/553] Remove code duplication from !quote --- src/Bot/Commands/Utils/Quote/Quote.cs | 288 ++++++++++---------------- 1 file changed, 109 insertions(+), 179 deletions(-) diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index 1e49a84..a731273 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.CommandPreconditions; using Geekbot.Core.Database; using Geekbot.Core.Database.Models; @@ -22,6 +23,7 @@ namespace Geekbot.Bot.Commands.Utils.Quote private readonly DatabaseContext _database; private readonly IRandomNumberGenerator _randomNumberGenerator; private readonly ITranslationHandler _translationHandler; + private readonly bool _isDev; public Quote(IErrorHandler errorHandler, DatabaseContext database, IRandomNumberGenerator randomNumberGenerator, ITranslationHandler translationHandler) { @@ -29,6 +31,8 @@ namespace Geekbot.Bot.Commands.Utils.Quote _database = database; _randomNumberGenerator = randomNumberGenerator; _translationHandler = translationHandler; + // to remove restrictions when developing + _isDev = Constants.BotVersion() == "0.0.0-DEV"; } [Command] @@ -63,36 +67,15 @@ namespace Geekbot.Bot.Commands.Utils.Quote [Summary("Add a quote from the last sent message by @user")] public async Task AddQuote([Summary("@someone")] IUser user) { - try - { - var transContext = await _translationHandler.GetGuildContext(Context); - if (user.Id == Context.Message.Author.Id) - { - await ReplyAsync(transContext.GetString("CannotSaveOwnQuotes")); - return; - } - - if (user.IsBot) - { - await ReplyAsync(transContext.GetString("CannotQuoteBots")); - return; - } - - var lastMessage = await GetLastMessageByUser(user); - if (lastMessage == null) return; - - var quote = CreateQuoteObject(lastMessage); - await _database.Quotes.AddAsync(quote); - await _database.SaveChangesAsync(); - - var embed = QuoteBuilder(quote); - await ReplyAsync(transContext.GetString("QuoteAdded"), false, embed.Build()); - } - catch (Exception e) - { - await _errorHandler.HandleCommandException(e, Context, - "I counldn't find a quote from that user :disappointed:"); - } + await QuoteFromMention(user, true); + } + + [Command("make")] + [Alias("preview")] + [Summary("Preview a quote from the last sent message by @user")] + public async Task ReturnSpecifiedQuote([Summary("@someone")] IUser user) + { + await QuoteFromMention(user, false); } [Command("add")] @@ -100,34 +83,15 @@ namespace Geekbot.Bot.Commands.Utils.Quote [Summary("Add a quote from a message id")] public async Task AddQuote([Summary("message-ID")] ulong messageId) { - try - { - var transContext = await _translationHandler.GetGuildContext(Context); - var message = await Context.Channel.GetMessageAsync(messageId); - if (message.Author.Id == Context.Message.Author.Id) - { - await ReplyAsync(transContext.GetString("CannotSaveOwnQuotes")); - return; - } - - if (message.Author.IsBot) - { - await ReplyAsync(transContext.GetString("CannotQuoteBots")); - return; - } - - var quote = CreateQuoteObject(message); - await _database.Quotes.AddAsync(quote); - await _database.SaveChangesAsync(); - - var embed = QuoteBuilder(quote); - await ReplyAsync(transContext.GetString("QuoteAdded"), false, embed.Build()); - } - catch (Exception e) - { - await _errorHandler.HandleCommandException(e, Context, - "I couldn't find a message with that id :disappointed:"); - } + await QuoteFromMessageId(messageId, true); + } + + [Command("make")] + [Alias("preview")] + [Summary("Preview a quote from a message id")] + public async Task ReturnSpecifiedQuote([Summary("message-ID")] ulong messageId) + { + await QuoteFromMessageId(messageId, false); } [Command("add")] @@ -135,127 +99,15 @@ namespace Geekbot.Bot.Commands.Utils.Quote [Summary("Add a quote from a message link")] public async Task AddQuote([Summary("message-link")] string messageLink) { - try - { - var transContext = await _translationHandler.GetGuildContext(Context); - - if (!MessageLink.IsValid(messageLink)) - { - await ReplyAsync(transContext.GetString("NotAValidMessageLink")); - return; - } - - var link = new MessageLink(messageLink); - if (link.GuildId != Context.Guild.Id) - { - await ReplyAsync(transContext.GetString("OnlyQuoteFromSameServer")); - return; - } - - var channel = link.ChannelId == Context.Channel.Id - ? Context.Channel - : await Context.Guild.GetTextChannelAsync(link.ChannelId); - - var message = await channel.GetMessageAsync(link.MessageId); - - if (message.Author.Id == Context.Message.Author.Id) - { - await ReplyAsync(transContext.GetString("CannotSaveOwnQuotes")); - return; - } - - if (message.Author.IsBot) - { - await ReplyAsync(transContext.GetString("CannotQuoteBots")); - return; - } - - var quote = CreateQuoteObject(message); - await _database.Quotes.AddAsync(quote); - await _database.SaveChangesAsync(); - - var embed = QuoteBuilder(quote); - await ReplyAsync(transContext.GetString("QuoteAdded"), false, embed.Build()); - } - catch (Exception e) - { - await _errorHandler.HandleCommandException(e, Context, - "I couldn't find a message with that id :disappointed:"); - } - } - - [Command("make")] - [Summary("Create a quote from the last sent message by @user")] - public async Task ReturnSpecifiedQuote([Summary("@someone")] IUser user) - { - try - { - var lastMessage = await GetLastMessageByUser(user); - if (lastMessage == null) return; - var quote = CreateQuoteObject(lastMessage); - var embed = QuoteBuilder(quote); - await ReplyAsync("", false, embed.Build()); - } - catch (Exception e) - { - await _errorHandler.HandleCommandException(e, Context, - "I counldn't find a quote from that user :disappointed:"); - } - } - - [Command("make")] - [Summary("Create a quote from a message id")] - public async Task ReturnSpecifiedQuote([Summary("message-ID")] ulong messageId) - { - try - { - var message = await Context.Channel.GetMessageAsync(messageId); - var quote = CreateQuoteObject(message); - var embed = QuoteBuilder(quote); - await ReplyAsync("", false, embed.Build()); - } - catch (Exception e) - { - await _errorHandler.HandleCommandException(e, Context, - "I couldn't find a message with that id :disappointed:"); - } + await QuoteFromMessageLink(messageLink, true); } [Command("make")] - [Summary("Create a quote from a message link")] + [Alias("preview")] + [Summary("Preview a quote from a message link")] public async Task ReturnSpecifiedQuote([Summary("message-link")] string messageLink) { - try - { - var transContext = await _translationHandler.GetGuildContext(Context); - - if (!MessageLink.IsValid(messageLink)) - { - await ReplyAsync(transContext.GetString("NotAValidMessageLink")); - return; - } - - var link = new MessageLink(messageLink); - if (link.GuildId != Context.Guild.Id) - { - await ReplyAsync(transContext.GetString("OnlyQuoteFromSameServer")); - return; - } - - var channel = link.ChannelId == Context.Channel.Id - ? Context.Channel - : await Context.Guild.GetTextChannelAsync(link.ChannelId); - - var message = await channel.GetMessageAsync(link.MessageId); - var quote = CreateQuoteObject(message); - var embed = QuoteBuilder(quote); - await ReplyAsync("", false, embed.Build()); - } - catch (Exception e) - { - await _errorHandler.HandleCommandException(e, Context, - "I couldn't find that message :disappointed:"); - } + await QuoteFromMessageLink(messageLink, false); } [Command("remove")] @@ -340,22 +192,100 @@ namespace Geekbot.Bot.Commands.Utils.Quote } } - private async Task GetLastMessageByUser(IUser user) + private async Task QuoteFromMention(IUser user, bool saveToDb) { try { + var transContext = await _translationHandler.GetGuildContext(Context); + var list = Context.Channel.GetMessagesAsync().Flatten(); - return await list.FirstOrDefaultAsync(msg => + var message = await list.FirstOrDefaultAsync(msg => msg.Author.Id == user.Id && msg.Embeds.Count == 0 && msg.Id != Context.Message.Id && !msg.Content.ToLower().StartsWith("!")); + if (message == null) return; + + await ProcessQuote(message, saveToDb, transContext); } - catch + catch (Exception e) { - await ReplyAsync($"No quoteable message have been sent by {user.Username} in this channel"); - return null; + await _errorHandler.HandleCommandException(e, Context, $"No quoteable messages have been sent by {user.Username} in this channel"); } + + } + + private async Task QuoteFromMessageId(ulong messageId, bool saveToDb) + { + try + { + var transContext = await _translationHandler.GetGuildContext(Context); + var message = await Context.Channel.GetMessageAsync(messageId); + + await ProcessQuote(message, saveToDb, transContext); + } + catch (Exception e) + { + await _errorHandler.HandleCommandException(e, Context, "I couldn't find a message with that id :disappointed:"); + } + } + + private async Task QuoteFromMessageLink(string messageLink, bool saveToDb) + { + try + { + var transContext = await _translationHandler.GetGuildContext(Context); + + if (!MessageLink.IsValid(messageLink)) + { + await ReplyAsync(transContext.GetString("NotAValidMessageLink")); + return; + } + + var link = new MessageLink(messageLink); + if (link.GuildId != Context.Guild.Id) + { + await ReplyAsync(transContext.GetString("OnlyQuoteFromSameServer")); + return; + } + + var channel = link.ChannelId == Context.Channel.Id + ? Context.Channel + : await Context.Guild.GetTextChannelAsync(link.ChannelId); + + var message = await channel.GetMessageAsync(link.MessageId); + + await ProcessQuote(message, saveToDb, transContext); + } + catch (Exception e) + { + await _errorHandler.HandleCommandException(e, Context, "I couldn't find that message :disappointed:"); + } + } + + private async Task ProcessQuote(IMessage message, bool saveToDb, TranslationGuildContext transContext) + { + if (message.Author.Id == Context.Message.Author.Id && saveToDb && !_isDev) + { + await ReplyAsync(transContext.GetString("CannotSaveOwnQuotes")); + return; + } + + if (message.Author.IsBot && saveToDb && !_isDev) + { + await ReplyAsync(transContext.GetString("CannotQuoteBots")); + return; + } + + var quote = CreateQuoteObject(message); + if (saveToDb) + { + await _database.Quotes.AddAsync(quote); + await _database.SaveChangesAsync(); + } + + var embed = QuoteBuilder(quote); + await ReplyAsync(saveToDb ? transContext.GetString("QuoteAdded") : string.Empty, false, embed.Build()); } private EmbedBuilder QuoteBuilder(QuoteModel quote) From 12388fd7d04faff06c43371c922df337b5a4dead Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 14 Aug 2020 00:12:14 +0200 Subject: [PATCH 379/553] Curate Media Files --- src/Bot/Storage/croissant | 13 +++---------- src/Bot/Storage/foxes | 31 +++++++++++-------------------- src/Bot/Storage/pandas | 5 +++-- src/Bot/Storage/penguins | 22 ++++++++++++---------- src/Bot/Storage/pumpkin | 23 +++++++---------------- src/Bot/Storage/squirrel | 28 ++++------------------------ src/Bot/Storage/turtles | 13 ++++++------- 7 files changed, 46 insertions(+), 89 deletions(-) diff --git a/src/Bot/Storage/croissant b/src/Bot/Storage/croissant index 281b790..6b4897f 100644 --- a/src/Bot/Storage/croissant +++ b/src/Bot/Storage/croissant @@ -3,15 +3,8 @@ http://www.bakespace.com/images/large/5d79070cf21b2f33c3a1dd4336cb27d2.jpeg http://food.fnr.sndimg.com/content/dam/images/food/fullset/2015/5/7/1/SD1B43_croissants-recipe_s4x3.jpg.rend.hgtvcom.616.462.suffix/1431052139248.jpeg http://img.taste.com.au/u-Bwjfm_/taste/2016/11/mini-croissants-with-3-fillings-14692-1.jpeg https://media.newyorker.com/photos/590974702179605b11ad8096/16:9/w_1200,h_630,c_limit/Gopnik-TheMurkyMeaningsofStraightenedOutCroissants.jpg -http://bt.static-redmouse.ch/sites/bielertagblatt.ch/files/styles/bt_article_showroom_landscape/hash/84/c9/84c9aed08415265911ec05c46d25d3ef.jpg?itok=hP5PnHaT -https://www.dermann.at/wp-content/uploads/Schokocroissant_HPBild_1400x900px.jpeg -https://www.bettybossi.ch/static/rezepte/x/bb_bkxx060101_0360a_x.jpg -http://www.engel-beck.ch/uploads/pics/tete-de-moine-gipfel-.jpg https://storage.cpstatic.ch/storage/og_image/laugengipfel--425319.jpg -https://www.backhaus-kutzer.de/fileadmin/templates/Resources/Public/img/produkte/suesses-gebaeck/Milchhoernchen.png -https://www.kuechengoetter.de/uploads/media/1000x524/00/36390-vanillekipferl-0.jpg?v=1-0 https://c1.staticflickr.com/3/2835/10874180753_2b2916e3ce_b.jpg -http://www.mistercool.ch/wp-content/uploads/2017/02/Gipfel-mit-Cerealien-7168.png -https://scontent-sea1-1.cdninstagram.com/t51.2885-15/s480x480/e35/c40.0.999.999/15099604_105396696611384_2866237281000226816_n.jpg?ig_cache_key=MTM4MzQxOTU1MDc5NjUxNzcwMA%3D%3D.2.c -http://www.lecrobag.de/wp-content/uploads/2014/03/Wurst_2014_l.jpg -https://www.thecookierookie.com/wp-content/uploads/2017/02/sheet-pan-chocolate-croissants-collage1.jpeg \ No newline at end of file +https://www.spatz-dessert.ch/image_upload/Laugengipfel.jpg +http://www.baeckerei-meier.ch/images/p005_1_03.png +http://i.huffpost.com/gen/1278175/thumbs/o-CROISSANT-facebook.jpg \ No newline at end of file diff --git a/src/Bot/Storage/foxes b/src/Bot/Storage/foxes index 020c1cf..52fd9d2 100644 --- a/src/Bot/Storage/foxes +++ b/src/Bot/Storage/foxes @@ -1,29 +1,20 @@ https://i.ytimg.com/vi/qF6OOGuT_hI/maxresdefault.jpg -https://www.hd-wallpapersdownload.com/script/bulk-upload/desktop-funny-fox-wallpaper.jpg -http://moziru.com/images/drawn-fox-funny-18.jpg https://static.tumblr.com/bb34d8f163098ad1daafcffbdbb03975/rk23uap/Nwwp0rmi2/tumblr_static_tumblr_static__640.jpg -https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQoHUFOnZ3wJ2kT1skNdztFXXSvpU8bEoGS1alNZiuyLXvGJhcY -http://childrenstorytales.com/wp-content/uploads/2011/03/how-to-draw-a-red-fox-in-the-snow.jpg https://www.popsci.com/sites/popsci.com/files/styles/1000_1x_/public/import/2013/images/2013/09/redfoxyawn.jpg?itok=yRkSVe8T https://hdqwalls.com/wallpapers/wild-fox-art.jpg -https://ae01.alicdn.com/kf/HTB1Q9dpLpXXXXbhXpXXq6xXFXXXl/new-cute-fox-toy-lifelike-soft-long-yellow-fox-doll-gift-about-73cm.jpg_640x640.jpg https://i.imgur.com/ktK9yXX.jpg -https://res.cloudinary.com/teepublic/image/private/s--yTx2ncFA--/t_Preview/b_rgb:c8e0ec,c_limit,f_auto,h_313,q_90,w_313/v1506478249/production/designs/1932607_0 http://4.bp.blogspot.com/-Hz-o_KYj3Xk/Vlm2mwbztjI/AAAAAAAA8Ss/jbH5ovjmC9A/s1600/ScreenShot5502.jpg -https://i.pinimg.com/originals/1e/d5/2f/1ed52f70873a95ac02fa074e48edfb71.jpg -https://i.imgur.com/2vCrtap.jpg -https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfukWGu_IBaDeJOMBqOhVAwsDfqEPw0BFpCn5_-Iyr_xjd7zi9 -https://cdn.pixabay.com/photo/2017/01/31/18/36/animal-2026297_960_720.png -https://i.pinimg.com/originals/e2/63/67/e26367a0844633b2a697b0a9d69e8cc9.jpg -https://i.ebayimg.com/images/g/BvkAAOSwqxdTqrip/s-l300.jpg -https://res.cloudinary.com/teepublic/image/private/s--1R53bger--/t_Preview/b_rgb:eae0c7,c_limit,f_jpg,h_630,q_90,w_630/v1481013120/production/designs/914528_1.jpg -https://i.pinimg.com/originals/97/fe/69/97fe698462afde7b4209ccefeecbce71.jpg -https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT6G0ch6g-wG1TuDJ6BbkOFelMNnkgFXC6CxOw7qSNjoFkx-BCe https://wallpaperscraft.com/image/fox_forest_grass_117190_540x960.jpg -https://image.freepik.com/free-vector/cartoon-flat-illustration-funny-cute-fox_6317-1174.jpg https://orig00.deviantart.net/2feb/f/2013/137/a/f/fox_and_curious_squirrel_by_tamarar-d65ju8d.jpg -https://res.cloudinary.com/teepublic/image/private/s--dICeNmBx--/t_Preview/b_rgb:6e2229,c_limit,f_jpg,h_630,q_90,w_630/v1505243196/production/designs/1890493_1.jpg -https://vignette.wikia.nocookie.net/puppyinmypocketfanon/images/4/49/L-Baby-Fox.jpg/revision/latest?cb=20130421001806 -http://7-themes.com/data_images/out/69/7009194-fox-puppy.jpg http://www.tehcute.com/pics/201401/little-fox-big.jpg -https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR6QXB1APLdUsyzO39kPvhnC9cOvcwzEtsxown9QjWilWppia2mwg \ No newline at end of file +https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR6QXB1APLdUsyzO39kPvhnC9cOvcwzEtsxown9QjWilWppia2mwg +https://www.wildlifeaid.org.uk/wp-content/uploads/2016/03/FP9_July09.jpg +https://upload.wikimedia.org/wikipedia/commons/thumb/b/bb/Vulpes_vulpes_ssp_fulvus_6568085.jpg/1200px-Vulpes_vulpes_ssp_fulvus_6568085.jpg +http://images.hellogiggles.com/uploads/2017/06/10023347/fox1.jpg +https://i.ytimg.com/vi/mtroFou8Xb4/maxresdefault.jpg +http://wallpapers-best.com/uploads/posts/2015-09/20_fox.jpg +https://www.whats-your-sign.com/wp-content/uploads/2018/02/RedFoxSymbolism4.jpg +https://cdn.zmescience.com/wp-content/uploads/2016/09/8505162700_11394c3f6a_b.jpg +http://wallpapers-best.com/uploads/posts/2015-09/18_fox.jpg +https://s.abcnews.com/images/General/red-fox-new-jersey-gty-jt-191119_hpMain_16x9_992.jpg +https://i.ytimg.com/vi/ClNRWL_9L8s/maxresdefault.jpg \ No newline at end of file diff --git a/src/Bot/Storage/pandas b/src/Bot/Storage/pandas index 9d5046c..6c6d725 100644 --- a/src/Bot/Storage/pandas +++ b/src/Bot/Storage/pandas @@ -4,8 +4,9 @@ https://nationalzoo.si.edu/sites/default/files/styles/slide_1400x700/public/supp https://media4.s-nbcnews.com/j/newscms/2016_36/1685951/ss-160826-twip-05_8cf6d4cb83758449fd400c7c3d71aa1f.nbcnews-ux-2880-1000.jpg https://ichef-1.bbci.co.uk/news/660/cpsprodpb/169F6/production/_91026629_gettyimages-519508400.jpg https://cdn.history.com/sites/2/2017/03/GettyImages-157278376.jpg -https://www.pandasinternational.org/wptemp/wp-content/uploads/2012/10/slider1.jpg https://tctechcrunch2011.files.wordpress.com/2015/11/panda.jpg http://www.nationalgeographic.com/content/dam/magazine/rights-exempt/2016/08/departments/panda-mania-12.jpg http://animals.sandiegozoo.org/sites/default/files/2016-09/panda1_10.jpg -http://kids.nationalgeographic.com/content/dam/kids/photos/animals/Mammals/A-G/giant-panda-eating.adapt.945.1.jpg \ No newline at end of file +http://kids.nationalgeographic.com/content/dam/kids/photos/animals/Mammals/A-G/giant-panda-eating.adapt.945.1.jpg +https://static.independent.co.uk/s3fs-public/thumbnails/image/2015/10/08/15/Hong-Kong-pandas.jpg +https://3sn4dm1qd6i72l8a4r2ig7fl-wpengine.netdna-ssl.com/wp-content/uploads/2016/11/panda_lunlun_ZA_2083-b.jpg \ No newline at end of file diff --git a/src/Bot/Storage/penguins b/src/Bot/Storage/penguins index d38d853..95aa70d 100644 --- a/src/Bot/Storage/penguins +++ b/src/Bot/Storage/penguins @@ -1,13 +1,15 @@ -https://i.ytimg.com/vi/Qr6sULJnu2o/maxresdefault.jpg -https://www.apex-expeditions.com/wp-content/uploads/2015/08/newzealandSlider_Macquarie_ElephantSealKingPenguins_GRiehle_1366x601.jpg https://www.birdlife.org/sites/default/files/styles/1600/public/slide.jpg?itok=HRhQfA1S http://experimentexchange.com/wp-content/uploads/2016/07/penguins-fact.jpg -http://images.mentalfloss.com/sites/default/files/styles/mf_image_16x9/public/istock-511366776.jpg?itok=cWhdWNZ8&resize=1100x619 -https://www.thevaporplace.ch/media/catalog/product/cache/1/thumbnail/800x800/9df78eab33525d08d6e5fb8d27136e95/a/t/atopack_penguin-15.jpg -https://www.superfastbusiness.com/wp-content/uploads/2015/10/real-time-penguin-algorithm-featured.jpg http://www.antarctica.gov.au/__data/assets/image/0011/147737/varieties/antarctic.jpg -https://vignette.wikia.nocookie.net/robloxcreepypasta/images/1/11/AAEAAQAAAAAAAAdkAAAAJDc3YzkyYjJhLTYyZjctNDY2Mi04M2VjLTg4NjY4ZjgwYzRmNg.png/revision/latest?cb=20180207200526 -https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3xV0lhpZuhT8Nmm6LaITsppZ7VfWcWXuyu2cPHrlv_dt_M92K5g -http://goboiano.com/wp-content/uploads/2017/04/Penguin-Kemeno-Friends-Waifu.jpg -https://cdn.yoast.com/app/uploads/2015/10/Penguins_1200x628.png -https://images.justwatch.com/backdrop/8611153/s1440/pingu \ No newline at end of file +https://images.justwatch.com/backdrop/8611153/s1440/pingu +http://4.bp.blogspot.com/-VhmPPCcZnwA/TWR303DSAuI/AAAAAAAAABU/eSSokmd376s/s1600/2-Penguins-penguins-4234010-1280-1024.jpg +https://media.glamour.com/photos/56959e35d9dab9ff41b308a0/master/pass/inspired-2015-02-gentoo-penguin-main.jpg +https://indiansciencejournal.files.wordpress.com/2012/04/emperor-penguin-credit-british-antarctic-survey.jpg +https://fthmb.tqn.com/7cd9Q3LSapEShHq2mKvQgSPr_tc=/2250x1500/filters:fill(auto,1)/149267744-56a008755f9b58eba4ae8f46.jpg +https://blogs.voanews.com/science-world/files/2014/07/11240219084_941dfbf66e_b.jpg +https://blogs.biomedcentral.com/bmcseriesblog/wp-content/uploads/sites/9/2015/11/IMG_5391-2.jpg +https://i2-prod.mirror.co.uk/incoming/article11682518.ece/ALTERNATES/s615/Emperor-penguins-on-ice.jpg +https://www.gannett-cdn.com/presto/2019/04/15/PPHX/8dfe0433-c22c-4458-9ba8-3aab866774f8-Penguins5cad7bfd107a4.jpg?crop=5759,3224,x0,y0&width=3200&height=1680&fit=bounds +http://4.bp.blogspot.com/_FNQgkfCwYxs/S82jBAxMVEI/AAAAAAAAAns/_3lAuJhUfcs/s1600/311785583_af8f2d1ea7_o.jpg +http://wallsdesk.com/wp-content/uploads/2017/01/Pictures-of-Penguin-.jpg +http://2.bp.blogspot.com/_W90V87w3sr8/TP3RPYwrrjI/AAAAAAAAAXk/riN0GwRwhFM/s1600/leap-of-faith-adelie-penguin-pictures.jpg \ No newline at end of file diff --git a/src/Bot/Storage/pumpkin b/src/Bot/Storage/pumpkin index 4b8e6f2..3652397 100644 --- a/src/Bot/Storage/pumpkin +++ b/src/Bot/Storage/pumpkin @@ -1,23 +1,14 @@ https://i.pinimg.com/736x/0a/a7/8a/0aa78af25e114836e1a42585fb7b09ed--funny-pumpkins-pumkin-carving.jpg http://wdy.h-cdn.co/assets/16/31/980x1470/gallery-1470321728-shot-two-021.jpg -https://i.pinimg.com/736x/6c/62/bf/6c62bfa73a19ffd9fc6f2d720d5e9764--cool-pumpkin-carving-carving-pumpkins.jpg http://images6.fanpop.com/image/photos/38900000/Jack-o-Lantern-halloween-38991566-500-415.jpg http://ghk.h-cdn.co/assets/15/37/1441834730-pumpkin-carve-2.jpg http://diy.sndimg.com/content/dam/images/diy/fullset/2011/7/26/1/iStock-10761186_halloween-pumpkin-in-garden_s4x3.jpg.rend.hgtvcom.966.725.suffix/1420851319631.jpeg -http://ghk.h-cdn.co/assets/cm/15/11/54ffe537af882-snail-pumpkin-de.jpg https://www.digsdigs.com/photos/2009/10/100-halloween-pumpkin-carving-ideas-12.jpg -http://diy.sndimg.com/content/dam/images/diy/fullset/2010/6/4/0/CI-Kyle-Nishioka_big-teeth-Jack-O-Lantern_s4x3.jpg.rend.hgtvcom.966.725.suffix/1420699522718.jpeg -https://twistedsifter.files.wordpress.com/2011/10/most-amazing-pumpkin-carving-ray-villafane-10.jpg?w=521&h=739 -https://i.pinimg.com/736x/09/c4/b1/09c4b187b266c1f65332294f66009944--funny-pumpkins-halloween-pumpkins.jpg -http://www.evilmilk.com/pictures/The_Pumpkin_Man.jpg -http://cache.lovethispic.com/uploaded_images/blogs/13-Funny-Pumpkin-Carvings-5773-9.JPG -http://ihappyhalloweenpictures.com/wp-content/uploads/2016/10/funny-halloween-pumpkin.jpg -http://www.smallhomelove.com/wp-content/uploads/2012/08/leg-eating-pumpkin.jpg -https://cdn.shopify.com/s/files/1/0773/6789/articles/Halloween_Feature_8ff7a7c4-2cb3-4584-a85f-5d4d1e6ca26e.jpg?v=1476211360 -http://4vector.com/i/free-vector-pumpkin-boy-color-version-clip-art_107714_Pumpkin_Boy_Color_Version_clip_art_hight.png https://i.pinimg.com/736x/59/8a/0f/598a0fbf789631b76c1ffd4443194d8e--halloween-pumpkins-fall-halloween.jpg -https://i.pinimg.com/originals/8f/86/f9/8f86f95457467872b371ba697d341961.jpg -http://nerdist.com/wp-content/uploads/2015/08/taleshalloween1.jpg -http://www.designbolts.com/wp-content/uploads/2014/09/Scary-Pumpkin_Grin_stencil-Ideas.jpg -http://vignette2.wikia.nocookie.net/scoobydoo/images/7/75/Pumpkin_monsters_%28Witch%27s_Ghost%29.png/revision/latest?cb=20140520070213 -https://taholtorf.files.wordpress.com/2013/10/36307-1920x1280.jpg +http://i.huffpost.com/gen/1405530/images/o-PUMPKINS-facebook.jpg +https://www.reviewjournal.com/wp-content/uploads/2016/10/web1_thinkstockphotos-491684958_7239666.jpg +https://img.sunset02.com/sites/default/files/1494265591/pumpkins-growing-on-farm-getty-sun-0517.jpg +https://toronto.citynews.ca/wp-content/blogs.dir/sites/10/2015/10/06/pumpkin-patch.jpg +http://i.huffpost.com/gen/3494726/images/o-PUMPKIN-facebook.jpg +https://servingjoy.com/wp-content/uploads/2014/12/Beautiful-autumn-halloween-pumpkins.jpg +https://www.history.com/.image/t_share/MTU3ODc5MDg2NDI4OTg4NzQ1/still-life-of-a-jack-o-lantern.jpg \ No newline at end of file diff --git a/src/Bot/Storage/squirrel b/src/Bot/Storage/squirrel index 2216465..91fd240 100644 --- a/src/Bot/Storage/squirrel +++ b/src/Bot/Storage/squirrel @@ -1,45 +1,25 @@ -http://orig14.deviantart.net/6016/f/2010/035/c/b/first_squirrel_assassin_by_shotokanteddy.jpg -https://thumbs-prod.si-cdn.com/eoEYA_2Hau4795uKoecUZZgz-3w=/800x600/filters:no_upscale()/https://public-media.smithsonianmag.com/filer/52/f9/52f93262-c29b-4a4f-b031-0c7ad145ed5f/42-33051942.jpg +https://public-media.smithsonianmag.com/filer/52/f9/52f93262-c29b-4a4f-b031-0c7ad145ed5f/42-33051942.jpg http://images5.fanpop.com/image/photos/30700000/Squirrel-squirrels-30710732-400-300.jpg -https://www.lovethegarden.com/sites/default/files/files/Red%20%26%20Grey%20Squirrel%20picture%20side%20by%20side-LR.jpg http://i.dailymail.co.uk/i/pix/2016/02/24/16/158F7E7C000005DC-3462228-image-a-65_1456331226865.jpg http://2.bp.blogspot.com/-egfnMhUb8tg/T_dAIu1m6cI/AAAAAAAAPPU/v4x9q4WqWl8/s640/cute-squirrel-hey-watcha-thinkin-about.jpg https://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Squirrel_posing.jpg/287px-Squirrel_posing.jpg https://i.pinimg.com/736x/51/db/9b/51db9bad4a87d445d321923c7d56b501--red-squirrel-animal-kingdom.jpg -https://metrouk2.files.wordpress.com/2016/10/ad_223291521.jpg?w=620&h=949&crop=1 -http://www.redsquirrelsunited.org.uk/wp-content/uploads/2016/07/layer-slider.jpg -http://images.mentalfloss.com/sites/default/files/squirrel-hero.jpg?resize=1100x740 https://i.pinimg.com/736x/ce/9c/59/ce9c5990b193046400d98724595cdaf3--red-squirrel-chipmunks.jpg https://www.brooklynpaper.com/assets/photos/40/30/dtg-squirrel-attacks-prospect-park-patrons-2017-07-28-bk01_z.jpg -http://www.freakingnews.com/pictures/16000/Squirrel-Shark-16467.jpg -http://img09.deviantart.net/5c1c/i/2013/138/0/6/barbarian_squirel_by_coucoucmoa-d64r9m4.jpg https://i.pinimg.com/736x/b4/5c/0d/b45c0d00b1a57e9f84f27f13cb019001--baby-squirrel-red-squirrel.jpg https://i.pinimg.com/736x/0f/75/87/0f7587bb613ab524763afe8c9a532e5c--cute-squirrel-squirrels.jpg http://cdn.images.express.co.uk/img/dynamic/128/590x/Grey-squirrel-828838.jpg http://www.lovethispic.com/uploaded_images/79964-Squirrel-Smelling-A-Flower.jpg https://i.pinimg.com/736x/23/d5/f9/23d5f9868f7d76c79c49bef53ae08f7f--squirrel-funny-red-squirrel.jpg -http://stories.barkpost.com/wp-content/uploads/2016/01/squirrel-3-copy.jpg https://i.ytimg.com/vi/pzUs0DdzK3Y/hqdefault.jpg -https://www.askideas.com/media/41/I-Swear-It-Wasnt-Me-Funny-Squirrel-Meme-Picture-For-Facebook.jpg -https://i.pinimg.com/736x/2d/54/d8/2d54d8d2a9b3ab9d3e78544b75afd88e--funny-animal-pictures-humorous-pictures.jpg -http://www.funny-animalpictures.com/media/content/items/images/funnysquirrels0012_O.jpg -http://funny-pics.co/wp-content/uploads/funny-squirrel-and-coffee-picture.jpg -https://pbs.twimg.com/media/Bi4Ij6CIgAAgEdZ.jpg -http://www.funnyjunksite.com/pictures/wp-content/uploads/2015/06/Funny-Superman-Squirrels.jpg -https://i.pinimg.com/736x/bf/35/00/bf3500104f8394909d116259d1f0575e--funny-squirrel-squirrel-girl.jpg -http://quotespill.com/wp-content/uploads/2017/07/Squirrel-Meme-Draw-me-like-one-of-your-french-squirrrels-min.jpg https://i.pinimg.com/736x/e2/16/bb/e216bba53f80fc8e0111d371e9850159--funny-squirrels-cute-squirrel.jpg https://i.pinimg.com/736x/52/43/c9/5243c93377245be1f686218c266d775c--funny-squirrel-baby-squirrel.jpg https://i.pinimg.com/736x/0c/be/1d/0cbe1da8ad2c0cf3882a806b6fd88965--cute-pictures-funny-animal-pictures.jpg -https://i.pinimg.com/736x/e5/08/67/e508670aa00ca3c896eccb81c4f6e2a8--funny-squirrel-baby-squirrel.jpg https://i.pinimg.com/736x/1c/7d/4f/1c7d4f067a10066aad802ce5ac468d71--group-boards-a-squirrel.jpg -http://funny-pics.co/wp-content/uploads/funny-squirrel-on-a-branch.jpg -http://loldamn.com/wp-content/uploads/2016/06/funny-squirrel-playing-water-bending.jpg -https://cdn.trendhunterstatic.com/thumbs/squirrel-photography.jpeg https://i.pinimg.com/736x/d6/42/12/d64212cc6221916db4173962bf6c131a--cute-squirrel-baby-squirrel.jpg -https://i.pinimg.com/236x/10/13/58/101358f2afc2c7d6b6a668046e7b8382--funny-animal-pictures-funny-animals.jpg https://i.pinimg.com/736x/da/0d/fe/da0dfe93bb26887795f906e8fa97d68e--secret-squirrel-cute-squirrel.jpg http://2.bp.blogspot.com/-HLieBqEuQoM/UDkRmeyzB5I/AAAAAAAABHs/RtsEynn5t6Y/s1600/hd-squirrel-wallpaper-with-a-brown-squirrel-eating-watermelon-wallpapers-backgrounds-pictures-photos.jpg -http://www.city-data.com/forum/members/brenda-starz-328928-albums-brenda-s-funny-squirrel-comment-pic-s-pic5075-punk-squirrels.jpg http://img15.deviantart.net/9c50/i/2011/213/c/9/just_taking_it_easy_by_lou_in_canada-d42do3d.jpg -http://3.bp.blogspot.com/-AwsSk76R2Is/USQa3-dszKI/AAAAAAAABUQ/KF_F8HbtP1U/w1200-h630-p-k-no-nu/crazySquirrel.jpg +https://insider.si.edu/wp-content/uploads/2018/01/Chipmunk-Photo-Mark-Rounds.jpg +https://media.mnn.com/assets/images/2014/12/gray-squirrel-uc-berkeley.jpg.1080x0_q100_crop-scale.jpg +https://citywildlife.org/wp-content/uploads/Juvenile-squirrel.jpg \ No newline at end of file diff --git a/src/Bot/Storage/turtles b/src/Bot/Storage/turtles index 9dbbf72..aa0fbcf 100644 --- a/src/Bot/Storage/turtles +++ b/src/Bot/Storage/turtles @@ -1,21 +1,20 @@ https://i.guim.co.uk/img/media/6b9be13031738e642f93f9271f3592044726a9b1/0_0_2863_1610/2863.jpg?w=640&h=360&q=55&auto=format&usm=12&fit=max&s=85f3b33cc158b5aa120c143dae1916ed http://cf.ltkcdn.net/small-pets/images/std/212089-676x450-Turtle-feeding-on-leaf.jpg -https://static1.squarespace.com/static/5369465be4b0507a1fd05af0/53767a6be4b0ad0822345e52/57e40ba4893fc031e05a018f/1498243318058/solvin.jpg?format=1500w https://c402277.ssl.cf1.rackcdn.com/photos/419/images/story_full_width/HI_287338Hero.jpg?1433950119 https://www.cdc.gov/salmonella/agbeni-08-17/images/turtle.jpg https://cdn.arstechnica.net/wp-content/uploads/2017/08/GettyImages-524757168.jpg http://pmdvod.nationalgeographic.com/NG_Video/595/319/4504517_098_05_TOS_thumbnail_640x360_636296259676.jpg -http://cdn1.arkive.org/media/7D/7D46329A-6ED2-4F08-909E-7B596417994A/Presentation.Large/Big-headed-turtle-close-up.jpg http://s7d2.scene7.com/is/image/PetSmart/ARTHMB-CleaningYourTortoiseOrTurtlesHabitat-20160818?$AR1104$ https://fthmb.tqn.com/9VGWzK_GWlvrjxtdFPX6EJxOq24=/960x0/filters:no_upscale()/133605352-56a2bce53df78cf7727960db.jpg -https://i.imgur.com/46QmzgF.jpg https://www.wildgratitude.com/wp-content/uploads/2015/07/turtle-spirit-animal1.jpg http://www.backwaterreptiles.com/images/turtles/red-eared-slider-turtle-for-sale.jpg -https://i.pinimg.com/736x/f1/f4/13/f1f413d6d07912be6080c08b186630ac--happy-turtle-funny-stuff.jpg -http://www.dupageforest.org/uploadedImages/Content/District_News/Nature_Stories/2016/Snapping%20Turtle%20Scott%20Plantier%20STP4793.jpg http://turtlebackzoo.com/wp-content/uploads/2016/07/exhibit-headers_0008_SOUTH-AMERICA-600x400.jpg -https://i.ytimg.com/vi/_YfYHFM3Das/maxresdefault.jpg https://i.pinimg.com/736x/dd/4e/7f/dd4e7f2f921ac28b1d5a59174d477131--cute-baby-sea-turtles-adorable-turtles.jpg http://kids.nationalgeographic.com/content/dam/kids/photos/animals/Reptiles/A-G/green-sea-turtle-closeup-underwater.adapt.945.1.jpg -https://i.ytimg.com/vi/p4Jj9QZFJvw/hqdefault.jpg https://fthmb.tqn.com/nirxHkH3jBAe74ife6fJJu6k6q8=/2121x1414/filters:fill(auto,1)/Red-eared-sliders-GettyImages-617946009-58fae8835f9b581d59a5bab6.jpg +http://assets.worldwildlife.org/photos/167/images/original/MID_225023-circle-hawksbill-turtle.jpg?1345565600 +https://seaturtles.org/wp-content/uploads/2013/11/GRN-honuAnitaWintner2.jpg +https://images2.minutemediacdn.com/image/upload/c_crop,h_2549,w_4536,x_0,y_237/v1560186367/shape/mentalfloss/istock-687398754.jpg?itok=QsiF5yHP +https://c402277.ssl.cf1.rackcdn.com/photos/13028/images/story_full_width/seaturtle_spring2017.jpg?1485359391 +https://i2.wp.com/rangerrick.org/wp-content/uploads/2018/03/Turtle-Tale-RR-Jr-June-July-2017.jpg?fit=1156%2C650&ssl=1 +https://boyslifeorg.files.wordpress.com/2019/07/greenseaturtle.jpg \ No newline at end of file From 90af781c7ba5f484ba34ef714c84aab1d455f9d2 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 14 Aug 2020 03:30:54 +0200 Subject: [PATCH 380/553] Start Using resource files (.resx) for translations. Create GeekbotCommandBase to reduce command boilerplate. Convert admin, choose, cookies, karma, quote, rank, roll and ship to the new localization method. --- src/Bot/Bot.csproj | 88 ++++++++++ src/Bot/Commands/Admin/Admin.cs | 71 +++++--- src/Bot/Commands/Games/Roll/Roll.cs | 23 ++- src/Bot/Commands/Randomness/Ship.cs | 29 ++-- src/Bot/Commands/Rpg/Cookies.cs | 38 ++--- src/Bot/Commands/User/Karma.cs | 47 +++--- src/Bot/Commands/User/Ranking/Rank.cs | 40 ++--- src/Bot/Commands/Utils/Choose.cs | 15 +- src/Bot/Commands/Utils/Quote/Quote.cs | 61 +++---- src/Bot/Localization/Admin.Designer.cs | 81 ++++++++++ src/Bot/Localization/Admin.de-ch.resx | 20 +++ src/Bot/Localization/Admin.resx | 27 ++++ src/Bot/Localization/Choose.Designer.cs | 72 +++++++++ src/Bot/Localization/Choose.de-ch.resx | 17 ++ src/Bot/Localization/Choose.resx | 24 +++ src/Bot/Localization/Cookies.Designer.cs | 126 +++++++++++++++ src/Bot/Localization/Cookies.de-ch.resx | 35 ++++ src/Bot/Localization/Cookies.resx | 42 +++++ src/Bot/Localization/Internal.Designer.cs | 126 +++++++++++++++ src/Bot/Localization/Internal.de-ch.resx | 35 ++++ src/Bot/Localization/Internal.resx | 42 +++++ src/Bot/Localization/Karma.Designer.cs | 135 ++++++++++++++++ src/Bot/Localization/Karma.de-ch.resx | 38 +++++ src/Bot/Localization/Karma.resx | 45 ++++++ src/Bot/Localization/Quote.Designer.cs | 162 +++++++++++++++++++ src/Bot/Localization/Quote.de-ch.resx | 47 ++++++ src/Bot/Localization/Quote.resx | 54 +++++++ src/Bot/Localization/Rank.Designer.cs | 108 +++++++++++++ src/Bot/Localization/Rank.de-ch.resx | 29 ++++ src/Bot/Localization/Rank.resx | 36 +++++ src/Bot/Localization/Roll.Designer.cs | 99 ++++++++++++ src/Bot/Localization/Roll.de-ch.resx | 26 +++ src/Bot/Localization/Roll.resx | 33 ++++ src/Bot/Localization/Ship.Designer.cs | 117 ++++++++++++++ src/Bot/Localization/Ship.de-ch.resx | 32 ++++ src/Bot/Localization/Ship.resx | 39 +++++ src/Core/GeekbotCommandBase.cs | 27 ++++ src/Core/Localization/ITranslationHandler.cs | 1 + src/Core/Localization/TranslationHandler.cs | 16 +- src/Core/Localization/Translations.yml | 159 +----------------- 40 files changed, 1935 insertions(+), 327 deletions(-) create mode 100644 src/Bot/Localization/Admin.Designer.cs create mode 100644 src/Bot/Localization/Admin.de-ch.resx create mode 100644 src/Bot/Localization/Admin.resx create mode 100644 src/Bot/Localization/Choose.Designer.cs create mode 100644 src/Bot/Localization/Choose.de-ch.resx create mode 100644 src/Bot/Localization/Choose.resx create mode 100644 src/Bot/Localization/Cookies.Designer.cs create mode 100644 src/Bot/Localization/Cookies.de-ch.resx create mode 100644 src/Bot/Localization/Cookies.resx create mode 100644 src/Bot/Localization/Internal.Designer.cs create mode 100644 src/Bot/Localization/Internal.de-ch.resx create mode 100644 src/Bot/Localization/Internal.resx create mode 100644 src/Bot/Localization/Karma.Designer.cs create mode 100644 src/Bot/Localization/Karma.de-ch.resx create mode 100644 src/Bot/Localization/Karma.resx create mode 100644 src/Bot/Localization/Quote.Designer.cs create mode 100644 src/Bot/Localization/Quote.de-ch.resx create mode 100644 src/Bot/Localization/Quote.resx create mode 100644 src/Bot/Localization/Rank.Designer.cs create mode 100644 src/Bot/Localization/Rank.de-ch.resx create mode 100644 src/Bot/Localization/Rank.resx create mode 100644 src/Bot/Localization/Roll.Designer.cs create mode 100644 src/Bot/Localization/Roll.de-ch.resx create mode 100644 src/Bot/Localization/Roll.resx create mode 100644 src/Bot/Localization/Ship.Designer.cs create mode 100644 src/Bot/Localization/Ship.de-ch.resx create mode 100644 src/Bot/Localization/Ship.resx create mode 100644 src/Core/GeekbotCommandBase.cs diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index c7889ae..601766a 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -40,4 +40,92 @@ + + + ResXFileCodeGenerator + Ship.Designer.cs + + + ResXFileCodeGenerator + Rank.Designer.cs + + + ResXFileCodeGenerator + Karma.Designer.cs + + + ResXFileCodeGenerator + Internal.Designer.cs + + + ResXFileCodeGenerator + Cookies.Designer.cs + + + ResXFileCodeGenerator + Roll.Designer.cs + + + ResXFileCodeGenerator + Choose.Designer.cs + + + ResXFileCodeGenerator + Admin.Designer.cs + + + ResXFileCodeGenerator + Quote.Designer.cs + + + + + True + True + ship.resx + + + True + True + Rank.resx + + + Ship.resx + + + True + True + Karma.resx + + + True + True + Internal.resx + + + True + True + Cookies.resx + + + True + True + Roll.resx + + + True + True + Choose.resx + + + True + True + Admin.resx + + + True + True + Quote.resx + + diff --git a/src/Bot/Commands/Admin/Admin.cs b/src/Bot/Commands/Admin/Admin.cs index f6c4210..2627f86 100644 --- a/src/Bot/Commands/Admin/Admin.cs +++ b/src/Bot/Commands/Admin/Admin.cs @@ -1,9 +1,15 @@ using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Resources; using System.Text; +using System.Threading; using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.WebSocket; +using Geekbot.Core; using Geekbot.Core.CommandPreconditions; using Geekbot.Core.ErrorHandling; using Geekbot.Core.Extensions; @@ -15,19 +21,15 @@ namespace Geekbot.Bot.Commands.Admin [Group("admin")] [RequireUserPermission(GuildPermission.Administrator)] [DisableInDirectMessage] - public class Admin : ModuleBase + public class Admin : GeekbotCommandBase { private readonly DiscordSocketClient _client; - private readonly IErrorHandler _errorHandler; private readonly IGuildSettingsManager _guildSettingsManager; - private readonly ITranslationHandler _translation; - public Admin(DiscordSocketClient client, IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager, ITranslationHandler translationHandler) + public Admin(DiscordSocketClient client, IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager, ITranslationHandler translationHandler) : base(errorHandler, translationHandler) { _client = client; - _errorHandler = errorHandler; _guildSettingsManager = guildSettingsManager; - _translation = translationHandler; } [Command("welcome", RunMode = RunMode.Async)] @@ -60,7 +62,7 @@ namespace Geekbot.Bot.Commands.Admin } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context, "That channel doesn't seem to exist or i don't have write permissions"); + await ErrorHandler.HandleCommandException(e, Context, "That channel doesn't seem to exist or i don't have write permissions"); } } @@ -84,7 +86,7 @@ namespace Geekbot.Bot.Commands.Admin } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context, "That channel doesn't seem to exist or i don't have write permissions"); + await ErrorHandler.HandleCommandException(e, Context, "That channel doesn't seem to exist or i don't have write permissions"); } } @@ -107,7 +109,7 @@ namespace Geekbot.Bot.Commands.Admin } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } @@ -130,7 +132,7 @@ namespace Geekbot.Bot.Commands.Admin } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } @@ -141,24 +143,30 @@ namespace Geekbot.Bot.Commands.Admin try { var language = languageRaw.ToUpper(); - var success = await _translation.SetLanguage(Context.Guild.Id, language); + var success = await Translations.SetLanguage(Context.Guild.Id, language); if (success) { var guild = _guildSettingsManager.GetSettings(Context.Guild.Id); guild.Language = language; await _guildSettingsManager.UpdateSettings(guild); - var transContext = await _translation.GetGuildContext(Context); - await ReplyAsync(transContext.GetString("NewLanguageSet")); + if (language.ToLower() == "chde") + { + Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("de-ch"); + } + + await ReplyAsync(Localization.Admin.NewLanguageSet); return; } - await ReplyAsync( - $"That doesn't seem to be a supported language\r\nSupported Languages are {string.Join(", ", _translation.SupportedLanguages)}"); + var available = new List(); + available.Add("en-GB"); // default + available.AddRange(GetAvailableCultures().Select(culture => culture.Name)); + await ReplyAsync($"That doesn't seem to be a supported language\nSupported Languages are {string.Join(", ", available)}"); } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } @@ -177,7 +185,7 @@ namespace Geekbot.Bot.Commands.Admin } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } @@ -194,7 +202,7 @@ namespace Geekbot.Bot.Commands.Admin } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } @@ -211,7 +219,7 @@ namespace Geekbot.Bot.Commands.Admin } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } @@ -230,5 +238,30 @@ namespace Geekbot.Bot.Commands.Admin return null; } } + + private IEnumerable GetAvailableCultures() + { + var result = new List(); + var rm = new ResourceManager(typeof(Localization.Admin)); + var cultures = CultureInfo.GetCultures(CultureTypes.AllCultures); + foreach (var culture in cultures) + { + try + { + if (culture.Equals(CultureInfo.InvariantCulture)) continue; //do not use "==", won't work + + var rs = rm.GetResourceSet(culture, true, false); + if (rs != null) + { + result.Add(culture); + } + } + catch (CultureNotFoundException) + { + //NOP + } + } + return result; + } } } \ No newline at end of file diff --git a/src/Bot/Commands/Games/Roll/Roll.cs b/src/Bot/Commands/Games/Roll/Roll.cs index 6241ba1..244edbe 100644 --- a/src/Bot/Commands/Games/Roll/Roll.cs +++ b/src/Bot/Commands/Games/Roll/Roll.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.Database; using Geekbot.Core.Database.Models; using Geekbot.Core.ErrorHandling; @@ -12,21 +13,17 @@ using Geekbot.Core.RandomNumberGenerator; namespace Geekbot.Bot.Commands.Games.Roll { - public class Roll : ModuleBase + public class Roll : GeekbotCommandBase { - private readonly IErrorHandler _errorHandler; private readonly IKvInMemoryStore _kvInMemoryStore; - private readonly ITranslationHandler _translation; private readonly DatabaseContext _database; private readonly IRandomNumberGenerator _randomNumberGenerator; - public Roll(IKvInMemoryStore kvInMemoryStore,IErrorHandler errorHandler, ITranslationHandler translation, DatabaseContext database, IRandomNumberGenerator randomNumberGenerator) + public Roll(IKvInMemoryStore kvInMemoryStore,IErrorHandler errorHandler, ITranslationHandler translation, DatabaseContext database, IRandomNumberGenerator randomNumberGenerator) : base(errorHandler, translation) { _kvInMemoryStore = kvInMemoryStore; - _translation = translation; _database = database; _randomNumberGenerator = randomNumberGenerator; - _errorHandler = errorHandler; } [Command("roll", RunMode = RunMode.Async)] @@ -37,7 +34,7 @@ namespace Geekbot.Bot.Commands.Games.Roll { var number = _randomNumberGenerator.Next(1, 100); int.TryParse(stuff, out var guess); - var transContext = await _translation.GetGuildContext(Context); + var transContext = await Translations.GetGuildContext(Context); if (guess <= 100 && guess > 0) { var kvKey = $"{Context.Guild.Id}:{Context.User.Id}:RollsPrevious"; @@ -46,8 +43,8 @@ namespace Geekbot.Bot.Commands.Games.Roll if (prevRoll?.LastGuess == guess && prevRoll?.GuessedOn.AddDays(1) > DateTime.Now) { - await ReplyAsync(transContext.GetString( - "NoPrevGuess", + await ReplyAsync(string.Format( + Localization.Roll.NoPrevGuess, Context.Message.Author.Mention, transContext.FormatDateTimeAsRemaining(prevRoll.GuessedOn.AddDays(1)))); return; @@ -55,10 +52,10 @@ namespace Geekbot.Bot.Commands.Games.Roll _kvInMemoryStore.Set(kvKey, new RollTimeout { LastGuess = guess, GuessedOn = DateTime.Now }); - await ReplyAsync(transContext.GetString("Rolled", Context.Message.Author.Mention, number, guess)); + await ReplyAsync(string.Format(Localization.Roll.Rolled, Context.Message.Author.Mention, number, guess)); if (guess == number) { - await ReplyAsync(transContext.GetString("Gratz", Context.Message.Author)); + await ReplyAsync(string.Format(Localization.Roll.Gratz, Context.Message.Author)); var user = await GetUser(Context.User.Id); user.Rolls += 1; _database.Rolls.Update(user); @@ -67,12 +64,12 @@ namespace Geekbot.Bot.Commands.Games.Roll } else { - await ReplyAsync(transContext.GetString("RolledNoGuess", Context.Message.Author.Mention, number)); + await ReplyAsync(string.Format(Localization.Roll.RolledNoGuess, Context.Message.Author.Mention, number)); } } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } diff --git a/src/Bot/Commands/Randomness/Ship.cs b/src/Bot/Commands/Randomness/Ship.cs index d5d9eea..78f3c99 100644 --- a/src/Bot/Commands/Randomness/Ship.cs +++ b/src/Bot/Commands/Randomness/Ship.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.Database; using Geekbot.Core.Database.Models; using Geekbot.Core.ErrorHandling; @@ -12,19 +13,15 @@ using Geekbot.Core.RandomNumberGenerator; namespace Geekbot.Bot.Commands.Randomness { - public class Ship : ModuleBase + public class Ship : GeekbotCommandBase { - private readonly IErrorHandler _errorHandler; private readonly IRandomNumberGenerator _randomNumberGenerator; - private readonly ITranslationHandler _translation; private readonly DatabaseContext _database; - public Ship(DatabaseContext database, IErrorHandler errorHandler, IRandomNumberGenerator randomNumberGenerator, ITranslationHandler translation) + public Ship(DatabaseContext database, IErrorHandler errorHandler, IRandomNumberGenerator randomNumberGenerator, ITranslationHandler translations) : base(errorHandler, translations) { _database = database; - _errorHandler = errorHandler; _randomNumberGenerator = randomNumberGenerator; - _translation = translation; } [Command("Ship", RunMode = RunMode.Async)] @@ -58,28 +55,26 @@ namespace Geekbot.Bot.Commands.Randomness shippingRate = dbval.Strength; } - var transContext = await _translation.GetGuildContext(Context); - - var reply = $":heartpulse: **{transContext.GetString("Matchmaking")}** :heartpulse:\r\n"; + var reply = $":heartpulse: **{Localization.Ship.Matchmaking}** :heartpulse:\r\n"; reply += $":two_hearts: {user1.Mention} :heart: {user2.Mention} :two_hearts:\r\n"; - reply += $"0% [{BlockCounter(shippingRate)}] 100% - {DeterminateSuccess(shippingRate, transContext)}"; + reply += $"0% [{BlockCounter(shippingRate)}] 100% - {DeterminateSuccess(shippingRate)}"; await ReplyAsync(reply); } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } - private string DeterminateSuccess(int rate, TranslationGuildContext transContext) + private string DeterminateSuccess(int rate) { return (rate / 20) switch { - 0 => transContext.GetString("NotGonnaToHappen"), - 1 => transContext.GetString("NotSuchAGoodIdea"), - 2 => transContext.GetString("ThereMightBeAChance"), - 3 => transContext.GetString("CouldWork"), - 4 => transContext.GetString("ItsAMatch"), + 0 => Localization.Ship.NotGoingToHappen, + 1 => Localization.Ship.NotSuchAGoodIdea, + 2 => Localization.Ship.ThereMightBeAChance, + 3 => Localization.Ship.CouldWork, + 4 => Localization.Ship.ItsAMatch, _ => "nope" }; } diff --git a/src/Bot/Commands/Rpg/Cookies.cs b/src/Bot/Commands/Rpg/Cookies.cs index f581105..570f08a 100644 --- a/src/Bot/Commands/Rpg/Cookies.cs +++ b/src/Bot/Commands/Rpg/Cookies.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.CommandPreconditions; using Geekbot.Core.Database; using Geekbot.Core.Database.Models; @@ -16,18 +17,14 @@ namespace Geekbot.Bot.Commands.Rpg [DisableInDirectMessage] [Group("cookies")] [Alias("cookie")] - public class Cookies : ModuleBase + public class Cookies : GeekbotCommandBase { private readonly DatabaseContext _database; - private readonly IErrorHandler _errorHandler; - private readonly ITranslationHandler _translation; private readonly IRandomNumberGenerator _randomNumberGenerator; - public Cookies(DatabaseContext database, IErrorHandler errorHandler, ITranslationHandler translation , IRandomNumberGenerator randomNumberGenerator) + public Cookies(DatabaseContext database, IErrorHandler errorHandler, ITranslationHandler translations , IRandomNumberGenerator randomNumberGenerator) : base(errorHandler, translations) { _database = database; - _errorHandler = errorHandler; - _translation = translation; _randomNumberGenerator = randomNumberGenerator; } @@ -37,23 +34,23 @@ namespace Geekbot.Bot.Commands.Rpg { try { - var transContext = await _translation.GetGuildContext(Context); + var transContext = await Translations.GetGuildContext(Context); var actor = await GetUser(Context.User.Id); if (actor.LastPayout.Value.AddDays(1).Date > DateTime.Now.Date) { var formatedWaitTime = transContext.FormatDateTimeAsRemaining(DateTimeOffset.Now.AddDays(1).Date); - await ReplyAsync(transContext.GetString("WaitForMoreCookies", formatedWaitTime)); + await ReplyAsync(string.Format(Localization.Cookies.WaitForMoreCookies, formatedWaitTime)); return; } actor.Cookies += 10; actor.LastPayout = DateTimeOffset.Now; await SetUser(actor); - await ReplyAsync(transContext.GetString("GetCookies", 10, actor.Cookies)); + await ReplyAsync(string.Format(Localization.Cookies.GetCookies, 10, actor.Cookies)); } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } @@ -63,13 +60,12 @@ namespace Geekbot.Bot.Commands.Rpg { try { - var transContext = await _translation.GetGuildContext(Context); var actor = await GetUser(Context.User.Id); - await ReplyAsync(transContext.GetString("InYourJar", actor.Cookies)); + await ReplyAsync(string.Format(Localization.Cookies.InYourJar, actor.Cookies)); } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } @@ -79,12 +75,11 @@ namespace Geekbot.Bot.Commands.Rpg { try { - var transContext = await _translation.GetGuildContext(Context); var giver = await GetUser(Context.User.Id); if (giver.Cookies < amount) { - await ReplyAsync(transContext.GetString("NotEnoughToGive")); + await ReplyAsync(Localization.Cookies.NotEnoughToGive); return; } @@ -96,11 +91,11 @@ namespace Geekbot.Bot.Commands.Rpg await SetUser(giver); await SetUser(taker); - await ReplyAsync(transContext.GetString("Given", amount, user.Username)); + await ReplyAsync(string.Format(Localization.Cookies.Given, amount, user.Username)); } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } @@ -110,12 +105,11 @@ namespace Geekbot.Bot.Commands.Rpg { try { - var transContext = await _translation.GetGuildContext(Context); var actor = await GetUser(Context.User.Id); if (actor.Cookies < 5) { - await ReplyAsync(transContext.GetString("NotEnoughCookiesToEat")); + await ReplyAsync(Localization.Cookies.NotEnoughCookiesToEat); return; } @@ -124,14 +118,14 @@ namespace Geekbot.Bot.Commands.Rpg await SetUser(actor); - await ReplyAsync(transContext.GetString("AteCookies", amount, actor.Cookies)); + await ReplyAsync(string.Format(Localization.Cookies.AteCookies, amount, actor.Cookies)); } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } - + private async Task GetUser(ulong userId) { var user = _database.Cookies.FirstOrDefault(u =>u.GuildId.Equals(Context.Guild.Id.AsLong()) && u.UserId.Equals(userId.AsLong())) ?? await CreateNewRow(userId); diff --git a/src/Bot/Commands/User/Karma.cs b/src/Bot/Commands/User/Karma.cs index 3efc381..41a401c 100644 --- a/src/Bot/Commands/User/Karma.cs +++ b/src/Bot/Commands/User/Karma.cs @@ -1,8 +1,11 @@ using System; +using System.Globalization; using System.Linq; +using System.Threading; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.CommandPreconditions; using Geekbot.Core.Database; using Geekbot.Core.Database.Models; @@ -13,17 +16,15 @@ using Geekbot.Core.Localization; namespace Geekbot.Bot.Commands.User { [DisableInDirectMessage] - public class Karma : ModuleBase + public class Karma : GeekbotCommandBase { - private readonly IErrorHandler _errorHandler; private readonly DatabaseContext _database; - private readonly ITranslationHandler _translation; + private readonly ITranslationHandler _translations; - public Karma(DatabaseContext database, IErrorHandler errorHandler, ITranslationHandler translation) + public Karma(DatabaseContext database, IErrorHandler errorHandler, ITranslationHandler translations) : base(errorHandler, translations) { _database = database; - _errorHandler = errorHandler; - _translation = translation; + _translations = translations; } [Command("good", RunMode = RunMode.Async)] @@ -32,16 +33,17 @@ namespace Geekbot.Bot.Commands.User { try { - var transContext = await _translation.GetGuildContext(Context); + var transContext = await _translations.GetGuildContext(Context); + var actor = await GetUser(Context.User.Id); if (user.Id == Context.User.Id) { - await ReplyAsync(transContext.GetString("CannotChangeOwn", Context.User.Username)); + await ReplyAsync(string.Format(Localization.Karma.CannotChangeOwnUp, Context.User.Username)); } else if (TimeoutFinished(actor.TimeOut)) { var formatedWaitTime = transContext.FormatDateTimeAsRemaining(actor.TimeOut.AddMinutes(3)); - await ReplyAsync(transContext.GetString("WaitUntill", Context.User.Username, formatedWaitTime)); + await ReplyAsync(string.Format(Localization.Karma.WaitUntill, Context.User.Username, formatedWaitTime)); } else { @@ -60,16 +62,16 @@ namespace Geekbot.Bot.Commands.User .WithName(user.Username)); eb.WithColor(new Color(138, 219, 146)); - eb.Title = transContext.GetString("Increased"); - eb.AddInlineField(transContext.GetString("By"), Context.User.Username); - eb.AddInlineField(transContext.GetString("Amount"), "+1"); - eb.AddInlineField(transContext.GetString("Current"), target.Karma); + eb.Title = Localization.Karma.Increased; + eb.AddInlineField(Localization.Karma.By, Context.User.Username); + eb.AddInlineField(Localization.Karma.Amount, "+1"); + eb.AddInlineField(Localization.Karma.Current, target.Karma); await ReplyAsync("", false, eb.Build()); } } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } @@ -79,16 +81,17 @@ namespace Geekbot.Bot.Commands.User { try { - var transContext = await _translation.GetGuildContext(Context); + var transContext = await _translations.GetGuildContext(Context); + var actor = await GetUser(Context.User.Id); if (user.Id == Context.User.Id) { - await ReplyAsync(transContext.GetString("CannotChangeOwn", Context.User.Username)); + await ReplyAsync(string.Format(Localization.Karma.CannotChangeOwnDown, Context.User.Username)); } else if (TimeoutFinished(actor.TimeOut)) { var formatedWaitTime = transContext.FormatDateTimeAsRemaining(actor.TimeOut.AddMinutes(3)); - await ReplyAsync(transContext.GetString("WaitUntill", Context.User.Username, formatedWaitTime)); + await ReplyAsync(string.Format(Localization.Karma.WaitUntill, Context.User.Username, formatedWaitTime)); } else { @@ -107,16 +110,16 @@ namespace Geekbot.Bot.Commands.User .WithName(user.Username)); eb.WithColor(new Color(138, 219, 146)); - eb.Title = transContext.GetString("Decreased"); - eb.AddInlineField(transContext.GetString("By"), Context.User.Username); - eb.AddInlineField(transContext.GetString("Amount"), "-1"); - eb.AddInlineField(transContext.GetString("Current"), target.Karma); + eb.Title = Localization.Karma.Decreased; + eb.AddInlineField(Localization.Karma.By, Context.User.Username); + eb.AddInlineField(Localization.Karma.Amount, "-1"); + eb.AddInlineField(Localization.Karma.Current, target.Karma); await ReplyAsync("", false, eb.Build()); } } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } diff --git a/src/Bot/Commands/User/Ranking/Rank.cs b/src/Bot/Commands/User/Ranking/Rank.cs index ae1bec9..d73aacc 100644 --- a/src/Bot/Commands/User/Ranking/Rank.cs +++ b/src/Bot/Commands/User/Ranking/Rank.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.CommandPreconditions; using Geekbot.Core.Converters; using Geekbot.Core.Database; @@ -11,28 +12,20 @@ using Geekbot.Core.ErrorHandling; using Geekbot.Core.Extensions; using Geekbot.Core.Highscores; using Geekbot.Core.Localization; -using Geekbot.Core.UserRepository; namespace Geekbot.Bot.Commands.User.Ranking { - public class Rank : ModuleBase + public class Rank : GeekbotCommandBase { private readonly IEmojiConverter _emojiConverter; private readonly IHighscoreManager _highscoreManager; - private readonly ITranslationHandler _translationHandler; - private readonly IErrorHandler _errorHandler; private readonly DatabaseContext _database; - private readonly IUserRepository _userRepository; - public Rank(DatabaseContext database, IErrorHandler errorHandler, IUserRepository userRepository, - IEmojiConverter emojiConverter, IHighscoreManager highscoreManager, ITranslationHandler translationHandler) + public Rank(DatabaseContext database, IErrorHandler errorHandler, IEmojiConverter emojiConverter, IHighscoreManager highscoreManager, ITranslationHandler translations): base(errorHandler, translations) { _database = database; - _errorHandler = errorHandler; - _userRepository = userRepository; _emojiConverter = emojiConverter; _highscoreManager = highscoreManager; - _translationHandler = translationHandler; } [Command("rank", RunMode = RunMode.Async)] @@ -42,7 +35,6 @@ namespace Geekbot.Bot.Commands.User.Ranking { try { - var transContext = await _translationHandler.GetGuildContext(Context); HighscoreTypes type; try { @@ -51,14 +43,14 @@ namespace Geekbot.Bot.Commands.User.Ranking } catch { - await ReplyAsync(transContext.GetString("InvalidType")); + await ReplyAsync(Localization.Rank.InvalidType); return; } var replyBuilder = new StringBuilder(); if (amount > 20) { - await ReplyAsync(transContext.GetString("LimitingTo20Warning")); + await ReplyAsync(Localization.Rank.LimitingTo20Warning); amount = 20; } @@ -70,7 +62,7 @@ namespace Geekbot.Bot.Commands.User.Ranking } catch (HighscoreListEmptyException) { - await ReplyAsync(transContext.GetString("NoTypeFoundForServer", type)); + await ReplyAsync(string.Format(Localization.Rank.NoTypeFoundForServer, type)); return; } @@ -85,22 +77,24 @@ namespace Geekbot.Bot.Commands.User.Ranking var failedToRetrieveUser = highscoreUsers.Any(e => string.IsNullOrEmpty(e.Key.Username)); - if (failedToRetrieveUser) replyBuilder.AppendLine(transContext.GetString("FailedToResolveAllUsernames")); - replyBuilder.AppendLine(transContext.GetString("HighscoresFor", type.ToString().CapitalizeFirst(), Context.Guild.Name)); + if (failedToRetrieveUser) replyBuilder.AppendLine(Localization.Rank.FailedToResolveAllUsernames).AppendLine(); + + replyBuilder.AppendLine(string.Format(Localization.Rank.HighscoresFor, type.ToString().CapitalizeFirst(), Context.Guild.Name)); + var highscorePlace = 1; - foreach (var user in highscoreUsers) + foreach (var (user, value) in highscoreUsers) { replyBuilder.Append(highscorePlace < 11 ? $"{_emojiConverter.NumberToEmoji(highscorePlace)} " : $"`{highscorePlace}.` "); - replyBuilder.Append(user.Key.Username != null - ? $"**{user.Key.Username}#{user.Key.Discriminator}**" - : $"**{user.Key.Id}**"); + replyBuilder.Append(user.Username != null + ? $"**{user.Username}#{user.Discriminator}**" + : $"**{user.Id}**"); replyBuilder.Append(type == HighscoreTypes.messages - ? $" - {user.Value} {type} - {Math.Round((double) (100 * user.Value) / guildMessages, 2)}%\n" - : $" - {user.Value} {type}\n"); + ? $" - {value} {type} - {Math.Round((double) (100 * value) / guildMessages, 2)}%\n" + : $" - {value} {type}\n"); highscorePlace++; } @@ -109,7 +103,7 @@ namespace Geekbot.Bot.Commands.User.Ranking } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } } diff --git a/src/Bot/Commands/Utils/Choose.cs b/src/Bot/Commands/Utils/Choose.cs index d245bd2..ea239d7 100644 --- a/src/Bot/Commands/Utils/Choose.cs +++ b/src/Bot/Commands/Utils/Choose.cs @@ -1,20 +1,16 @@ using System; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.ErrorHandling; using Geekbot.Core.Localization; namespace Geekbot.Bot.Commands.Utils { - public class Choose : ModuleBase + public class Choose : GeekbotCommandBase { - private readonly IErrorHandler _errorHandler; - private readonly ITranslationHandler _translation; - - public Choose(IErrorHandler errorHandler, ITranslationHandler translation) + public Choose(IErrorHandler errorHandler, ITranslationHandler translation) : base(errorHandler, translation) { - _errorHandler = errorHandler; - _translation = translation; } [Command("choose", RunMode = RunMode.Async)] @@ -24,14 +20,13 @@ namespace Geekbot.Bot.Commands.Utils { try { - var transContext = await _translation.GetGuildContext(Context); var choicesArray = choices.Split(';'); var choice = new Random().Next(choicesArray.Length); - await ReplyAsync(transContext.GetString("Choice", choicesArray[choice].Trim())); + await ReplyAsync(string.Format(Localization.Choose.Choice, choicesArray[choice].Trim())); } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } } diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index a731273..5bb23a9 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -17,20 +17,16 @@ namespace Geekbot.Bot.Commands.Utils.Quote { [Group("quote")] [DisableInDirectMessage] - public class Quote : ModuleBase + public class Quote : GeekbotCommandBase { - private readonly IErrorHandler _errorHandler; private readonly DatabaseContext _database; private readonly IRandomNumberGenerator _randomNumberGenerator; - private readonly ITranslationHandler _translationHandler; private readonly bool _isDev; - public Quote(IErrorHandler errorHandler, DatabaseContext database, IRandomNumberGenerator randomNumberGenerator, ITranslationHandler translationHandler) + public Quote(IErrorHandler errorHandler, DatabaseContext database, IRandomNumberGenerator randomNumberGenerator, ITranslationHandler translationHandler) : base(errorHandler, translationHandler) { - _errorHandler = errorHandler; _database = database; _randomNumberGenerator = randomNumberGenerator; - _translationHandler = translationHandler; // to remove restrictions when developing _isDev = Constants.BotVersion() == "0.0.0-DEV"; } @@ -45,8 +41,7 @@ namespace Geekbot.Bot.Commands.Utils.Quote if (!s.Any()) { - var transContext = await _translationHandler.GetGuildContext(Context); - await ReplyAsync(transContext.GetString("NoQuotesFound")); + await ReplyAsync(Localization.Quote.NoQuotesFound); return; } @@ -58,7 +53,7 @@ namespace Geekbot.Bot.Commands.Utils.Quote } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context, "Whoops, seems like the quote was to edgy to return"); + await ErrorHandler.HandleCommandException(e, Context, "Whoops, seems like the quote was to edgy to return"); } } @@ -117,23 +112,22 @@ namespace Geekbot.Bot.Commands.Utils.Quote { try { - var transContext = await _translationHandler.GetGuildContext(Context); var quote = _database.Quotes.Where(e => e.GuildId == Context.Guild.Id.AsLong() && e.InternalId == id)?.FirstOrDefault(); if (quote != null) { _database.Quotes.Remove(quote); await _database.SaveChangesAsync(); var embed = QuoteBuilder(quote); - await ReplyAsync(transContext.GetString("Removed", id), false, embed.Build()); + await ReplyAsync(string.Format(Localization.Quote.Removed, id), false, embed.Build()); } else { - await ReplyAsync(transContext.GetString("NotFoundWithId")); + await ReplyAsync(Localization.Quote.NotFoundWithId); } } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context, "I couldn't find a quote with that id :disappointed:"); + await ErrorHandler.HandleCommandException(e, Context, "I couldn't find a quote with that id :disappointed:"); } } @@ -144,12 +138,11 @@ namespace Geekbot.Bot.Commands.Utils.Quote try { // setup - var transContext = await _translationHandler.GetGuildContext(Context); var eb = new EmbedBuilder(); eb.Author = new EmbedAuthorBuilder() { IconUrl = Context.Guild.IconUrl, - Name = $"{Context.Guild.Name} - {transContext.GetString("QuoteStats")}" + Name = $"{Context.Guild.Name} - {Localization.Quote.QuoteStats}" }; // gather data @@ -157,7 +150,7 @@ namespace Geekbot.Bot.Commands.Utils.Quote if (totalQuotes == 0) { // no quotes, no stats, end of the road - await ReplyAsync(transContext.GetString("NoQuotesFound")); + await ReplyAsync(Localization.Quote.NoQuotesFound); return; } @@ -176,8 +169,8 @@ namespace Geekbot.Bot.Commands.Utils.Quote .OrderBy(row => row.year); // add data to the embed - eb.AddField(transContext.GetString("MostQuotesPerson"), $"{mostQuotedPersonUser.Username} ({mostQuotedPerson.amount})"); - eb.AddInlineField(transContext.GetString("TotalQuotes"), totalQuotes); + eb.AddField(Localization.Quote.MostQuotesPerson, $"{mostQuotedPersonUser.Username} ({mostQuotedPerson.amount})"); + eb.AddInlineField(Localization.Quote.TotalQuotes, totalQuotes); foreach (var year in quotesByYear) { @@ -188,7 +181,7 @@ namespace Geekbot.Bot.Commands.Utils.Quote } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } @@ -196,8 +189,6 @@ namespace Geekbot.Bot.Commands.Utils.Quote { try { - var transContext = await _translationHandler.GetGuildContext(Context); - var list = Context.Channel.GetMessagesAsync().Flatten(); var message = await list.FirstOrDefaultAsync(msg => msg.Author.Id == user.Id && @@ -206,11 +197,11 @@ namespace Geekbot.Bot.Commands.Utils.Quote !msg.Content.ToLower().StartsWith("!")); if (message == null) return; - await ProcessQuote(message, saveToDb, transContext); + await ProcessQuote(message, saveToDb); } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context, $"No quoteable messages have been sent by {user.Username} in this channel"); + await ErrorHandler.HandleCommandException(e, Context, $"No quoteable messages have been sent by {user.Username} in this channel"); } } @@ -219,14 +210,14 @@ namespace Geekbot.Bot.Commands.Utils.Quote { try { - var transContext = await _translationHandler.GetGuildContext(Context); + // var transContext = await _translationHandler.GetGuildContext(Context); var message = await Context.Channel.GetMessageAsync(messageId); - await ProcessQuote(message, saveToDb, transContext); + await ProcessQuote(message, saveToDb); } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context, "I couldn't find a message with that id :disappointed:"); + await ErrorHandler.HandleCommandException(e, Context, "I couldn't find a message with that id :disappointed:"); } } @@ -234,18 +225,18 @@ namespace Geekbot.Bot.Commands.Utils.Quote { try { - var transContext = await _translationHandler.GetGuildContext(Context); + // var transContext = await _translationHandler.GetGuildContext(Context); if (!MessageLink.IsValid(messageLink)) { - await ReplyAsync(transContext.GetString("NotAValidMessageLink")); + await ReplyAsync(Localization.Quote.NotAValidMessageLink); return; } var link = new MessageLink(messageLink); if (link.GuildId != Context.Guild.Id) { - await ReplyAsync(transContext.GetString("OnlyQuoteFromSameServer")); + await ReplyAsync(Localization.Quote.OnlyQuoteFromSameServer); return; } @@ -255,25 +246,25 @@ namespace Geekbot.Bot.Commands.Utils.Quote var message = await channel.GetMessageAsync(link.MessageId); - await ProcessQuote(message, saveToDb, transContext); + await ProcessQuote(message, saveToDb); } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context, "I couldn't find that message :disappointed:"); + await ErrorHandler.HandleCommandException(e, Context, "I couldn't find that message :disappointed:"); } } - private async Task ProcessQuote(IMessage message, bool saveToDb, TranslationGuildContext transContext) + private async Task ProcessQuote(IMessage message, bool saveToDb) { if (message.Author.Id == Context.Message.Author.Id && saveToDb && !_isDev) { - await ReplyAsync(transContext.GetString("CannotSaveOwnQuotes")); + await ReplyAsync(Localization.Quote.CannotSaveOwnQuotes); return; } if (message.Author.IsBot && saveToDb && !_isDev) { - await ReplyAsync(transContext.GetString("CannotQuoteBots")); + await ReplyAsync(Localization.Quote.CannotQuoteBots); return; } @@ -285,7 +276,7 @@ namespace Geekbot.Bot.Commands.Utils.Quote } var embed = QuoteBuilder(quote); - await ReplyAsync(saveToDb ? transContext.GetString("QuoteAdded") : string.Empty, false, embed.Build()); + await ReplyAsync(saveToDb ? Localization.Quote.QuoteAdded : string.Empty, false, embed.Build()); } private EmbedBuilder QuoteBuilder(QuoteModel quote) diff --git a/src/Bot/Localization/Admin.Designer.cs b/src/Bot/Localization/Admin.Designer.cs new file mode 100644 index 0000000..c55adf1 --- /dev/null +++ b/src/Bot/Localization/Admin.Designer.cs @@ -0,0 +1,81 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Geekbot.Bot.Localization { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Admin { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Admin() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Geekbot.Bot.Localization.Admin", typeof(Admin).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to I'm talking english. + /// + internal static string GetLanguage { + get { + return ResourceManager.GetString("GetLanguage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I will reply in english from now on. + /// + internal static string NewLanguageSet { + get { + return ResourceManager.GetString("NewLanguageSet", resourceCulture); + } + } + } +} diff --git a/src/Bot/Localization/Admin.de-ch.resx b/src/Bot/Localization/Admin.de-ch.resx new file mode 100644 index 0000000..b89939b --- /dev/null +++ b/src/Bot/Localization/Admin.de-ch.resx @@ -0,0 +1,20 @@ + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + I werd ab jetzt uf schwiizerdüütsch antworte, äuuä + + + I red schwiizerdüütsch + + \ No newline at end of file diff --git a/src/Bot/Localization/Admin.resx b/src/Bot/Localization/Admin.resx new file mode 100644 index 0000000..6fd2c62 --- /dev/null +++ b/src/Bot/Localization/Admin.resx @@ -0,0 +1,27 @@ + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + I will reply in english from now on + + + I'm talking english + + \ No newline at end of file diff --git a/src/Bot/Localization/Choose.Designer.cs b/src/Bot/Localization/Choose.Designer.cs new file mode 100644 index 0000000..1319140 --- /dev/null +++ b/src/Bot/Localization/Choose.Designer.cs @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Geekbot.Bot.Localization { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Choose { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Choose() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Geekbot.Bot.Localization.Choose", typeof(Choose).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to I Choose **{0}**. + /// + internal static string Choice { + get { + return ResourceManager.GetString("Choice", resourceCulture); + } + } + } +} diff --git a/src/Bot/Localization/Choose.de-ch.resx b/src/Bot/Localization/Choose.de-ch.resx new file mode 100644 index 0000000..eedc39b --- /dev/null +++ b/src/Bot/Localization/Choose.de-ch.resx @@ -0,0 +1,17 @@ + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + I nimme **{0}** + + \ No newline at end of file diff --git a/src/Bot/Localization/Choose.resx b/src/Bot/Localization/Choose.resx new file mode 100644 index 0000000..052177b --- /dev/null +++ b/src/Bot/Localization/Choose.resx @@ -0,0 +1,24 @@ + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + I Choose **{0}** + + \ No newline at end of file diff --git a/src/Bot/Localization/Cookies.Designer.cs b/src/Bot/Localization/Cookies.Designer.cs new file mode 100644 index 0000000..5f2528f --- /dev/null +++ b/src/Bot/Localization/Cookies.Designer.cs @@ -0,0 +1,126 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Geekbot.Bot.Localization { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Cookies { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Cookies() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Geekbot.Bot.Localization.Cookies", typeof(Cookies).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to You ate {0} cookies, you've only got {1} cookies left. + /// + internal static string AteCookies { + get { + return ResourceManager.GetString("AteCookies", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You got {0} cookies, there are now {1} cookies in you cookie jar. + /// + internal static string GetCookies { + get { + return ResourceManager.GetString("GetCookies", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You gave {0} cookies to {1}. + /// + internal static string Given { + get { + return ResourceManager.GetString("Given", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There are {0} cookies in you cookie jar. + /// + internal static string InYourJar { + get { + return ResourceManager.GetString("InYourJar", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Your cookie jar looks almost empty, you should probably not eat a cookie. + /// + internal static string NotEnoughCookiesToEat { + get { + return ResourceManager.GetString("NotEnoughCookiesToEat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You don't have enough cookies. + /// + internal static string NotEnoughToGive { + get { + return ResourceManager.GetString("NotEnoughToGive", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You already got cookies today, you can have more cookies in {0}. + /// + internal static string WaitForMoreCookies { + get { + return ResourceManager.GetString("WaitForMoreCookies", resourceCulture); + } + } + } +} diff --git a/src/Bot/Localization/Cookies.de-ch.resx b/src/Bot/Localization/Cookies.de-ch.resx new file mode 100644 index 0000000..b53b588 --- /dev/null +++ b/src/Bot/Localization/Cookies.de-ch.resx @@ -0,0 +1,35 @@ + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Du häsch {0} guetzli becho, du häsch jetzt {1} guetzli ih dr büchse + + + Du hesch scho guetzli becho hüt, du chasch meh ha in {0} + + + Es hät {0} guetzli ih dineri büchs + + + Du hesch {1} {0} guetzli geh + + + Du hesch nid gnueg guetzli + + + Du hesch chuum no guetzli ih dineri büchs, du sötsch warschinli keini esse + + + Du hesch {0} guetzli gesse und hesch jezt no {1} übrig + + \ No newline at end of file diff --git a/src/Bot/Localization/Cookies.resx b/src/Bot/Localization/Cookies.resx new file mode 100644 index 0000000..53207fa --- /dev/null +++ b/src/Bot/Localization/Cookies.resx @@ -0,0 +1,42 @@ + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + You got {0} cookies, there are now {1} cookies in you cookie jar + + + You already got cookies today, you can have more cookies in {0} + + + There are {0} cookies in you cookie jar + + + You gave {0} cookies to {1} + + + You don't have enough cookies + + + Your cookie jar looks almost empty, you should probably not eat a cookie + + + You ate {0} cookies, you've only got {1} cookies left + + \ No newline at end of file diff --git a/src/Bot/Localization/Internal.Designer.cs b/src/Bot/Localization/Internal.Designer.cs new file mode 100644 index 0000000..e7c18af --- /dev/null +++ b/src/Bot/Localization/Internal.Designer.cs @@ -0,0 +1,126 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Geekbot.Bot.Localization { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Internal { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Internal() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Geekbot.Bot.Localization.Internal", typeof(Internal).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to and. + /// + internal static string And { + get { + return ResourceManager.GetString("And", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to day|days. + /// + internal static string Days { + get { + return ResourceManager.GetString("Days", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to hour|hours. + /// + internal static string Hours { + get { + return ResourceManager.GetString("Hours", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Seems like i don't have enough permission to that :confused:. + /// + internal static string Http403 { + get { + return ResourceManager.GetString("Http403", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to minute|minutes. + /// + internal static string Minutes { + get { + return ResourceManager.GetString("Minutes", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to second|seconds. + /// + internal static string Seconds { + get { + return ResourceManager.GetString("Seconds", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Something went wrong :confused:. + /// + internal static string SomethingWentWrong { + get { + return ResourceManager.GetString("SomethingWentWrong", resourceCulture); + } + } + } +} diff --git a/src/Bot/Localization/Internal.de-ch.resx b/src/Bot/Localization/Internal.de-ch.resx new file mode 100644 index 0000000..568bb1f --- /dev/null +++ b/src/Bot/Localization/Internal.de-ch.resx @@ -0,0 +1,35 @@ + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Öppis isch schief gange :confused: + + + Gseht danach us das ich nid gnueg recht han zum das mache :confused: + + + tag|täg + + + stund|stunde + + + minute|minute + + + sekunde|sekunde + + + und + + \ No newline at end of file diff --git a/src/Bot/Localization/Internal.resx b/src/Bot/Localization/Internal.resx new file mode 100644 index 0000000..a771d6b --- /dev/null +++ b/src/Bot/Localization/Internal.resx @@ -0,0 +1,42 @@ + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Something went wrong :confused: + + + Seems like i don't have enough permission to that :confused: + + + day|days + + + hour|hours + + + minute|minutes + + + second|seconds + + + and + + \ No newline at end of file diff --git a/src/Bot/Localization/Karma.Designer.cs b/src/Bot/Localization/Karma.Designer.cs new file mode 100644 index 0000000..4191fa2 --- /dev/null +++ b/src/Bot/Localization/Karma.Designer.cs @@ -0,0 +1,135 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Geekbot.Bot.Localization { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Karma { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Karma() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Geekbot.Bot.Localization.Karma", typeof(Karma).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Amount. + /// + internal static string Amount { + get { + return ResourceManager.GetString("Amount", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to By. + /// + internal static string By { + get { + return ResourceManager.GetString("By", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sorry {0}, but you can't lower your own karma. + /// + internal static string CannotChangeOwnDown { + get { + return ResourceManager.GetString("CannotChangeOwnDown", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sorry {0}, but you can't give yourself karma. + /// + internal static string CannotChangeOwnUp { + get { + return ResourceManager.GetString("CannotChangeOwnUp", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Current. + /// + internal static string Current { + get { + return ResourceManager.GetString("Current", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Karma lowered. + /// + internal static string Decreased { + get { + return ResourceManager.GetString("Decreased", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gained Karma. + /// + internal static string Increased { + get { + return ResourceManager.GetString("Increased", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sorry {0}, but you have to wait {1} before you can give karma again.... + /// + internal static string WaitUntill { + get { + return ResourceManager.GetString("WaitUntill", resourceCulture); + } + } + } +} diff --git a/src/Bot/Localization/Karma.de-ch.resx b/src/Bot/Localization/Karma.de-ch.resx new file mode 100644 index 0000000..294c105 --- /dev/null +++ b/src/Bot/Localization/Karma.de-ch.resx @@ -0,0 +1,38 @@ + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Sorry {0}, aber du chasch dr selber kei karma geh + + + Sorry {0}, aber du musch no {1} warte bisch d wieder karma chasch geh... + + + Karma becho + + + Vo + + + Mengi + + + Jetzt + + + Sorry {0}, aber du chasch dr din eigete karma nid weg neh + + + Karma gsenkt + + \ No newline at end of file diff --git a/src/Bot/Localization/Karma.resx b/src/Bot/Localization/Karma.resx new file mode 100644 index 0000000..3a8fe5a --- /dev/null +++ b/src/Bot/Localization/Karma.resx @@ -0,0 +1,45 @@ + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Sorry {0}, but you can't give yourself karma + + + Sorry {0}, but you have to wait {1} before you can give karma again... + + + Gained Karma + + + By + + + Amount + + + Current + + + Sorry {0}, but you can't lower your own karma + + + Karma lowered + + \ No newline at end of file diff --git a/src/Bot/Localization/Quote.Designer.cs b/src/Bot/Localization/Quote.Designer.cs new file mode 100644 index 0000000..342c181 --- /dev/null +++ b/src/Bot/Localization/Quote.Designer.cs @@ -0,0 +1,162 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Geekbot.Bot.Localization { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Quote { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Quote() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Geekbot.Bot.Localization.Quote", typeof(Quote).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to You can't save quotes by a bot.... + /// + internal static string CannotQuoteBots { + get { + return ResourceManager.GetString("CannotQuoteBots", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You can't save your own quotes.... + /// + internal static string CannotSaveOwnQuotes { + get { + return ResourceManager.GetString("CannotSaveOwnQuotes", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Most quoted person. + /// + internal static string MostQuotesPerson { + get { + return ResourceManager.GetString("MostQuotesPerson", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This server doesn't seem to have any quotes yet. You can add a quote with `!quote save @user` or `!quote save <messageId>`. + /// + internal static string NoQuotesFound { + get { + return ResourceManager.GetString("NoQuotesFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to That is not a valid message link. + /// + internal static string NotAValidMessageLink { + get { + return ResourceManager.GetString("NotAValidMessageLink", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I couldn't find a quote with that ID :disappointed:. + /// + internal static string NotFoundWithId { + get { + return ResourceManager.GetString("NotFoundWithId", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You can only quote messages from the same server. + /// + internal static string OnlyQuoteFromSameServer { + get { + return ResourceManager.GetString("OnlyQuoteFromSameServer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to **Quote Added**. + /// + internal static string QuoteAdded { + get { + return ResourceManager.GetString("QuoteAdded", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Quote Stats. + /// + internal static string QuoteStats { + get { + return ResourceManager.GetString("QuoteStats", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to **Removed #{0}**. + /// + internal static string Removed { + get { + return ResourceManager.GetString("Removed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Total. + /// + internal static string TotalQuotes { + get { + return ResourceManager.GetString("TotalQuotes", resourceCulture); + } + } + } +} diff --git a/src/Bot/Localization/Quote.de-ch.resx b/src/Bot/Localization/Quote.de-ch.resx new file mode 100644 index 0000000..99fd959 --- /dev/null +++ b/src/Bot/Localization/Quote.de-ch.resx @@ -0,0 +1,47 @@ + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Dä server het no kei quotes. Du chasch quotes hinzuefüege mit `!quote save @user` oder `!quote save <messageId>` + + + Du chasch kei quotes vo dir selber speichere... + + + Du chasch kei quotes vomne bot speichere... + + + **Quote hinzugfüegt** + + + **#{0} glöscht** + + + Ich chan kei quote finde mit därri ID :disappointed: + + + Quote statistike + + + Total + + + Meist quoteti person + + + Das isch kei korrete nachrichtelink + + + Du chasch numme nachrichte vom gliche server quote + + \ No newline at end of file diff --git a/src/Bot/Localization/Quote.resx b/src/Bot/Localization/Quote.resx new file mode 100644 index 0000000..b51d79c --- /dev/null +++ b/src/Bot/Localization/Quote.resx @@ -0,0 +1,54 @@ + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + This server doesn't seem to have any quotes yet. You can add a quote with `!quote save @user` or `!quote save <messageId>` + + + You can't save your own quotes... + + + You can't save quotes by a bot... + + + **Quote Added** + + + **Removed #{0}** + + + I couldn't find a quote with that ID :disappointed: + + + Quote Stats + + + Total + + + Most quoted person + + + That is not a valid message link + + + You can only quote messages from the same server + + \ No newline at end of file diff --git a/src/Bot/Localization/Rank.Designer.cs b/src/Bot/Localization/Rank.Designer.cs new file mode 100644 index 0000000..23f5e16 --- /dev/null +++ b/src/Bot/Localization/Rank.Designer.cs @@ -0,0 +1,108 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Geekbot.Bot.Localization { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Rank { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Rank() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Geekbot.Bot.Localization.Rank", typeof(Rank).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to :warning: I couldn't find all usernames. Maybe they left the server?. + /// + internal static string FailedToResolveAllUsernames { + get { + return ResourceManager.GetString("FailedToResolveAllUsernames", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to :bar_chart: **{0} Highscore for {1}**. + /// + internal static string HighscoresFor { + get { + return ResourceManager.GetString("HighscoresFor", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Valid types are '`messages`' '`karma`', '`rolls`' and '`cookies`'. + /// + internal static string InvalidType { + get { + return ResourceManager.GetString("InvalidType", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to :warning: Limiting to 20. + /// + internal static string LimitingTo20Warning { + get { + return ResourceManager.GetString("LimitingTo20Warning", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No {0} found on this server. + /// + internal static string NoTypeFoundForServer { + get { + return ResourceManager.GetString("NoTypeFoundForServer", resourceCulture); + } + } + } +} diff --git a/src/Bot/Localization/Rank.de-ch.resx b/src/Bot/Localization/Rank.de-ch.resx new file mode 100644 index 0000000..0b22fe4 --- /dev/null +++ b/src/Bot/Localization/Rank.de-ch.resx @@ -0,0 +1,29 @@ + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + :warning: Limitiert uf 20 + + + Kei {0} gfunde für dä server + + + :warning: Ich han nid alli benutzername gfunde. villiicht hend sie de server verlah? + + + :bar_chart: **{0} Highscore für {1}** + + + Gültigi paramenter sind '`messages`' '`karma`', '`rolls`' und '`cookies` + + \ No newline at end of file diff --git a/src/Bot/Localization/Rank.resx b/src/Bot/Localization/Rank.resx new file mode 100644 index 0000000..9598cf8 --- /dev/null +++ b/src/Bot/Localization/Rank.resx @@ -0,0 +1,36 @@ + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Valid types are '`messages`' '`karma`', '`rolls`' and '`cookies`' + + + :warning: Limiting to 20 + + + No {0} found on this server + + + :warning: I couldn't find all usernames. Maybe they left the server? + + + :bar_chart: **{0} Highscore for {1}** + + \ No newline at end of file diff --git a/src/Bot/Localization/Roll.Designer.cs b/src/Bot/Localization/Roll.Designer.cs new file mode 100644 index 0000000..fda0536 --- /dev/null +++ b/src/Bot/Localization/Roll.Designer.cs @@ -0,0 +1,99 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Geekbot.Bot.Localization { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Roll { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Roll() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Geekbot.Bot.Localization.Roll", typeof(Roll).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Congratulations {0}, your guess was correct!. + /// + internal static string Gratz { + get { + return ResourceManager.GetString("Gratz", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to :red_circle: {0}, you can't guess the same number again, guess another number or wait {1}. + /// + internal static string NoPrevGuess { + get { + return ResourceManager.GetString("NoPrevGuess", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}, you rolled {1}, your guess was {2}. + /// + internal static string Rolled { + get { + return ResourceManager.GetString("Rolled", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}, you rolled {1}. + /// + internal static string RolledNoGuess { + get { + return ResourceManager.GetString("RolledNoGuess", resourceCulture); + } + } + } +} diff --git a/src/Bot/Localization/Roll.de-ch.resx b/src/Bot/Localization/Roll.de-ch.resx new file mode 100644 index 0000000..ba73316 --- /dev/null +++ b/src/Bot/Localization/Roll.de-ch.resx @@ -0,0 +1,26 @@ + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + {0}, du hesch {1} grollt und hesch {2} grate + + + Gratuliere {0}, du hesch richtig grate! + + + {0}, du hesch {1} grollt + + + :red_circle: {0}, du chasch nid nomol es gliche rate, rate öppis anders oder warte {1} + + \ No newline at end of file diff --git a/src/Bot/Localization/Roll.resx b/src/Bot/Localization/Roll.resx new file mode 100644 index 0000000..822abb6 --- /dev/null +++ b/src/Bot/Localization/Roll.resx @@ -0,0 +1,33 @@ + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + {0}, you rolled {1}, your guess was {2} + + + Congratulations {0}, your guess was correct! + + + {0}, you rolled {1} + + + :red_circle: {0}, you can't guess the same number again, guess another number or wait {1} + + \ No newline at end of file diff --git a/src/Bot/Localization/Ship.Designer.cs b/src/Bot/Localization/Ship.Designer.cs new file mode 100644 index 0000000..d959693 --- /dev/null +++ b/src/Bot/Localization/Ship.Designer.cs @@ -0,0 +1,117 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Geekbot.Bot.Localization { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Ship { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Ship() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Geekbot.Bot.Localization.Ship", typeof(Ship).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Almost a match. + /// + internal static string CouldWork { + get { + return ResourceManager.GetString("CouldWork", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to It's a match. + /// + internal static string ItsAMatch { + get { + return ResourceManager.GetString("ItsAMatch", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Matchmaking. + /// + internal static string Matchmaking { + get { + return ResourceManager.GetString("Matchmaking", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Not going happen. + /// + internal static string NotGoingToHappen { + get { + return ResourceManager.GetString("NotGoingToHappen", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Not such a good idea. + /// + internal static string NotSuchAGoodIdea { + get { + return ResourceManager.GetString("NotSuchAGoodIdea", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There might be a chance. + /// + internal static string ThereMightBeAChance { + get { + return ResourceManager.GetString("ThereMightBeAChance", resourceCulture); + } + } + } +} diff --git a/src/Bot/Localization/Ship.de-ch.resx b/src/Bot/Localization/Ship.de-ch.resx new file mode 100644 index 0000000..ec2880b --- /dev/null +++ b/src/Bot/Localization/Ship.de-ch.resx @@ -0,0 +1,32 @@ + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Verkupple + + + Wird nöd klappe + + + Nöd so ä gueti idee + + + Es gid eventuel ä chance + + + Fasch en match + + + Es isch es traumpaar + + \ No newline at end of file diff --git a/src/Bot/Localization/Ship.resx b/src/Bot/Localization/Ship.resx new file mode 100644 index 0000000..611040f --- /dev/null +++ b/src/Bot/Localization/Ship.resx @@ -0,0 +1,39 @@ + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Matchmaking + + + Not going happen + + + Not such a good idea + + + There might be a chance + + + Almost a match + + + It's a match + + \ No newline at end of file diff --git a/src/Core/GeekbotCommandBase.cs b/src/Core/GeekbotCommandBase.cs new file mode 100644 index 0000000..8df5265 --- /dev/null +++ b/src/Core/GeekbotCommandBase.cs @@ -0,0 +1,27 @@ +using System.Globalization; +using System.Threading; +using Discord.Commands; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.Localization; + +namespace Geekbot.Core +{ + public class GeekbotCommandBase : ModuleBase + { + protected readonly IErrorHandler ErrorHandler; + protected readonly ITranslationHandler Translations; + + protected GeekbotCommandBase(IErrorHandler errorHandler, ITranslationHandler translations) + { + ErrorHandler = errorHandler; + Translations = translations; + } + + protected override void BeforeExecute(CommandInfo command) + { + base.BeforeExecute(command); + var language = Translations.GetServerLanguage(Context.Guild.Id); + Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(language == "CHDE" ? "de-ch" : language); + } + } +} \ No newline at end of file diff --git a/src/Core/Localization/ITranslationHandler.cs b/src/Core/Localization/ITranslationHandler.cs index 74b3e88..1cc06fa 100644 --- a/src/Core/Localization/ITranslationHandler.cs +++ b/src/Core/Localization/ITranslationHandler.cs @@ -12,5 +12,6 @@ namespace Geekbot.Core.Localization Task GetGuildContext(ICommandContext context); Task SetLanguage(ulong guildId, string language); List SupportedLanguages { get; } + string GetServerLanguage(ulong guildId); } } \ No newline at end of file diff --git a/src/Core/Localization/TranslationHandler.cs b/src/Core/Localization/TranslationHandler.cs index c7d35e9..1a46ada 100644 --- a/src/Core/Localization/TranslationHandler.cs +++ b/src/Core/Localization/TranslationHandler.cs @@ -89,7 +89,7 @@ namespace Geekbot.Core.Localization } } - private Task GetServerLanguage(ulong guildId) + public string GetServerLanguage(ulong guildId) { try { @@ -99,7 +99,7 @@ namespace Geekbot.Core.Localization lang = _serverLanguages[guildId]; if (!string.IsNullOrEmpty(lang)) { - return Task.FromResult(lang); + return lang; } throw new Exception(); } @@ -107,19 +107,19 @@ namespace Geekbot.Core.Localization { lang = _guildSettingsManager.GetSettings(guildId, false)?.Language ?? "EN"; _serverLanguages[guildId] = lang; - return Task.FromResult(lang); + return lang; } } catch (Exception e) { _logger.Error(LogSource.Geekbot, "Could not get guild language", e); - return Task.FromResult("EN"); + return "EN"; } } public async Task GetString(ulong guildId, string command, string stringName) { - var serverLang = await GetServerLanguage(guildId); + var serverLang = GetServerLanguage(guildId); return GetString(serverLang, command, stringName); } @@ -140,7 +140,7 @@ namespace Geekbot.Core.Localization try { var command = context.Message.Content.Split(' ').First().TrimStart('!').ToLower(); - var serverLanguage = await GetServerLanguage(context.Guild?.Id ?? 0); + var serverLanguage = GetServerLanguage(context.Guild?.Id ?? 0); return _translations[serverLanguage][command]; } catch (Exception e) @@ -153,7 +153,7 @@ namespace Geekbot.Core.Localization public async Task GetGuildContext(ICommandContext context) { var dict = await GetDict(context); - var language = await GetServerLanguage(context.Guild?.Id ?? 0); + var language = GetServerLanguage(context.Guild?.Id ?? 0); return new TranslationGuildContext(this, language, dict); } @@ -161,7 +161,7 @@ namespace Geekbot.Core.Localization { try { - var serverLanguage = await GetServerLanguage(context.Guild?.Id ?? 0); + var serverLanguage = GetServerLanguage(context.Guild?.Id ?? 0); return _translations[serverLanguage][command]; } catch (Exception e) diff --git a/src/Core/Localization/Translations.yml b/src/Core/Localization/Translations.yml index fbb55bf..678755d 100644 --- a/src/Core/Localization/Translations.yml +++ b/src/Core/Localization/Translations.yml @@ -15,13 +15,6 @@ dateTime: And: EN: "and" CHDE: "und" -admin: - NewLanguageSet: - EN: "I will reply in english from now on" - CHDE: "I werd ab jetzt uf schwiizerdüütsch antworte, äuuä" - GetLanguage: - EN: "I'm talking english" - CHDE: "I red schwiizerdüütsch" errorHandler: SomethingWentWrong: EN: "Something went wrong :confused:" @@ -30,86 +23,6 @@ httpErrors: 403: EN: "Seems like i don't have enough permission to that :confused:" CHDE: "Gseht danach us das ich nid gnueg recht han zum das mache :confused:" -choose: - Choice: - EN: "I Choose **{0}**" - CHDE: "I nimme **{0}**" -good: - CannotChangeOwn: - EN: "Sorry {0}, but you can't give yourself karma" - CHDE: "Sorry {0}, aber du chasch dr selber kei karma geh" - WaitUntill: - EN: "Sorry {0}, but you have to wait {1} before you can give karma again..." - CHDE: "Sorry {0}, aber du musch no {1} warte bisch d wieder karma chasch geh..." - Increased: - EN: "Karma gained" - CHDE: "Karma becho" - By: - EN: "By" - CHDE: "Vo" - Amount: - EN: "Amount" - CHDE: "Mengi" - Current: - EN: "Current" - CHDE: "Jetzt" -bad: - CannotChangeOwn: - EN: "Sorry {0}, but you can't lower your own karma" - CHDE: "Sorry {0}, aber du chasch dr din eigete karma nid weg neh" - WaitUntill: - EN: "Sorry {0}, but you have to wait {1} before you can lower karma again..." - CHDE: "Sorry {0}, aber du musch no {1} warte bisch d wieder karma chasch senke..." - Decreased: - EN: "Karma lowered" - CHDE: "Karma gsenkt" - By: - EN: "By" - CHDE: "Vo" - Amount: - EN: "Amount" - CHDE: "Mengi" - Current: - EN: "Current" - CHDE: "Jetzt" -roll: - Rolled: - EN: "{0}, you rolled {1}, your guess was {2}" - CHDE: "{0}, du hesch {1} grollt und hesch {2} grate" - Gratz: - EN: "Congratulations {0}, your guess was correct!" - CHDE: "Gratuliere {0}, du hesch richtig grate!" - RolledNoGuess: - EN: "{0}, you rolled {1}" - CHDE: "{0}, du hesch {1} grollt" - NoPrevGuess: - EN: ":red_circle: {0}, you can't guess the same number again, guess another number or wait {1}" - CHDE: ":red_circle: {0}, du chasch nid nomol es gliche rate, rate öppis anders oder warte {1}" -cookies: &cookiesAlias - GetCookies: - EN: "You got {0} cookies, there are now {1} cookies in you cookie jar" - CHDE: "Du häsch {0} guetzli becho, du häsch jetzt {1} guetzli ih dr büchse" - WaitForMoreCookies: - EN: "You already got cookies today, you can have more cookies in {0}" - CHDE: "Du hesch scho guetzli becho hüt, du chasch meh ha in {0}" - InYourJar: - EN: "There are {0} cookies in you cookie jar" - CHDE: "Es hät {0} guetzli ih dineri büchs" - Given: - EN: "You gave {0} cookies to {1}" - CHDE: "Du hesch {1} {0} guetzli geh" - NotEnoughToGive: - EN: "You don't have enough cookies" - CHDE: "Du hesch nid gnueg guetzli" - NotEnoughCookiesToEat: - EN: "Your cookie jar looks almost empty, you should probably not eat a cookie" - CHDE: "Du hesch chuum no guetzli ih dineri büchs, du sötsch warschinli keini esse" - AteCookies: - EN: "You ate {0} cookies, you've only got {1} cookies left" - CHDE: "Du hesch {0} guetzli gesse und hesch jezt no {1} übrig" -cookie: - # because command aliases are to hard to deal with... - <<: *cookiesAlias role: NoRolesConfigured: EN: "There are no roles configured for this server" @@ -140,74 +53,4 @@ role: CHDE: "{0} isch zur whitelist hinzuegfüegt" RemovedRoleFromWhitelist: EN: "Removed {0} from the whitelist" - CHDE: "{0} isch vo dr whitelist glöscht" -quote: - NoQuotesFound: - EN: "This server doesn't seem to have any quotes yet. You can add a quote with `!quote save @user` or `!quote save `" - CHDE: "Dä server het no kei quotes. Du chasch quotes hinzuefüege mit `!quote save @user` oder `!quote save `" - CannotSaveOwnQuotes: - EN: "You can't save your own quotes..." - CHDE: "Du chasch kei quotes vo dir selber speichere..." - CannotQuoteBots: - EN: "You can't save quotes by a bot..." - CHDE: "Du chasch kei quotes vomne bot speichere..." - QuoteAdded: - EN: "**Quote Added**" - CHDE: "**Quote hinzugfüegt**" - Removed: - EN: "**Removed #{0}**" - CHDE: "**#{0} glöscht**" - NotFoundWithId: - EN: "I couldn't find a quote with that ID :disappointed:" - CHDE: "Ich chan kei quote finde mit därri ID :disappointed:" - QuoteStats: - EN: "Quote Stats" - CHDE: "Quote statistike" - TotalQuotes: - EN: "Total" - CHDE: "Total" - MostQuotesPerson: - EN: "Most quoted person" - CHDE: "Meist quoteti person" - NotAValidMessageLink: - EN: "That is not a valid message link" - CHDE: "Das isch kei korrete nachrichtelink" - OnlyQuoteFromSameServer: - EN: "You can only quote messages from the same server" - CHDE: "Du chasch numme nachrichte vom gliche server quote" -rank: - InvalidType: - EN: "Valid types are '`messages`' '`karma`', '`rolls`' and '`cookies`'" - CHDE: "Gültigi paramenter sind '`messages`' '`karma`', '`rolls`' und '`cookies`'" - LimitingTo20Warning: - EN: ":warning: Limiting to 20\n" - CHDE: ":warning: Limitiert uf 20\n" - NoTypeFoundForServer: - EN: "No {0} found on this server" - CHDE: "Kei {0} gfunde für dä server" - FailedToResolveAllUsernames: - EN: ":warning: I couldn't find all usernames. Maybe they left the server?\n" - CHDE: ":warning: Ich han nid alli benutzername gfunde. villiicht hend sie de server verlah?\n" - HighscoresFor: - EN: ":bar_chart: **{0} Highscore for {1}**" - CHDE: ":bar_chart: **{0} Highscore für {1}**" -ship: - Matchmaking: - EN: "Matchmaking" - CHDE: "Verkupple" - NotGonnaToHappen: - EN: "Not gonna happen" - CHDE: "Wird nöd klappe" - NotSuchAGoodIdea: - EN: "Not such a good idea" - CHDE: "Nöd so ä gueti idee" - ThereMightBeAChance: - EN: "There might be a chance" - CHDE: "Es gid eventuel ä chance" - CouldWork: - EN: "Almost a match" - CHDE: "Fasch en match" - ItsAMatch: - EN: "It's a match" - CHDE: "Es isch es traumpaar" - \ No newline at end of file + CHDE: "{0} isch vo dr whitelist glöscht" \ No newline at end of file From 078c884df73c668aab75f916cd175deaaac7bd4c Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 14 Aug 2020 18:11:52 +0200 Subject: [PATCH 381/553] Convert Role command to new localization method --- src/Bot/Bot.csproj | 9 ++ src/Bot/Commands/Admin/Role.cs | 52 ++++----- src/Bot/Localization/Role.Designer.cs | 153 +++++++++++++++++++++++++ src/Bot/Localization/Role.de-ch.resx | 44 +++++++ src/Bot/Localization/Role.resx | 51 +++++++++ src/Core/Localization/Translations.yml | 33 +----- 6 files changed, 280 insertions(+), 62 deletions(-) create mode 100644 src/Bot/Localization/Role.Designer.cs create mode 100644 src/Bot/Localization/Role.de-ch.resx create mode 100644 src/Bot/Localization/Role.resx diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index 601766a..2d3cd2f 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -77,6 +77,10 @@ ResXFileCodeGenerator Quote.Designer.cs + + ResXFileCodeGenerator + Role.Designer.cs + @@ -127,5 +131,10 @@ True Quote.resx + + True + True + Role.resx + diff --git a/src/Bot/Commands/Admin/Role.cs b/src/Bot/Commands/Admin/Role.cs index e997fa8..c8459dd 100644 --- a/src/Bot/Commands/Admin/Role.cs +++ b/src/Bot/Commands/Admin/Role.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.Net; +using Geekbot.Core; using Geekbot.Core.CommandPreconditions; using Geekbot.Core.Database; using Geekbot.Core.Database.Models; @@ -17,19 +18,15 @@ namespace Geekbot.Bot.Commands.Admin { [Group("role")] [DisableInDirectMessage] - public class Role : ModuleBase + public class Role : GeekbotCommandBase { private readonly DatabaseContext _database; - private readonly IErrorHandler _errorHandler; private readonly IReactionListener _reactionListener; - private readonly ITranslationHandler _translationHandler; - public Role(DatabaseContext database, IErrorHandler errorHandler, IReactionListener reactionListener, ITranslationHandler translationHandler) + public Role(DatabaseContext database, IErrorHandler errorHandler, IReactionListener reactionListener, ITranslationHandler translationHandler) : base(errorHandler, translationHandler) { _database = database; - _errorHandler = errorHandler; _reactionListener = reactionListener; - _translationHandler = translationHandler; } [Command(RunMode = RunMode.Async)] @@ -38,23 +35,22 @@ namespace Geekbot.Bot.Commands.Admin { try { - var transContext = await _translationHandler.GetGuildContext(Context); var roles = _database.RoleSelfService.Where(g => g.GuildId.Equals(Context.Guild.Id.AsLong())).ToList(); if (roles.Count == 0) { - await ReplyAsync(transContext.GetString("NoRolesConfigured")); + await ReplyAsync(Localization.Role.NoRolesConfigured); return; } var sb = new StringBuilder(); - sb.AppendLine(transContext.GetString("ListHeader", Context.Guild.Name)); - sb.AppendLine(transContext.GetString("ListInstruction")); + sb.AppendLine(string.Format(Localization.Role.ListHeader, Context.Guild.Name)); + sb.AppendLine(Localization.Role.ListInstruction); foreach (var role in roles) sb.AppendLine($"- {role.WhiteListName}"); await ReplyAsync(sb.ToString()); } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } @@ -64,7 +60,6 @@ namespace Geekbot.Bot.Commands.Admin { try { - var transContext = await _translationHandler.GetGuildContext(Context); var roleName = roleNameRaw.ToLower(); var roleFromDb = _database.RoleSelfService.FirstOrDefault(e => e.GuildId.Equals(Context.Guild.Id.AsLong()) && e.WhiteListName.Equals(roleName)); @@ -74,31 +69,31 @@ namespace Geekbot.Bot.Commands.Admin var role = Context.Guild.Roles.First(r => r.Id == roleFromDb.RoleId.AsUlong()); if (role == null) { - await ReplyAsync(transContext.GetString("RoleNotFound")); + await ReplyAsync(Localization.Role.RoleNotFound); return; } if (guildUser.RoleIds.Contains(role.Id)) { await guildUser.RemoveRoleAsync(role); - await ReplyAsync(transContext.GetString("RemovedUserFromRole", role.Name)); + await ReplyAsync(string.Format(Localization.Role.RemovedUserFromRole, role.Name)); return; } await guildUser.AddRoleAsync(role); - await ReplyAsync(transContext.GetString("AddedUserFromRole", role.Name)); + await ReplyAsync(string.Format(Localization.Role.AddedUserFromRole, role.Name)); return; } - await ReplyAsync(transContext.GetString("RoleNotFound")); + await ReplyAsync(Localization.Role.RoleNotFound); } catch (HttpException e) { - await _errorHandler.HandleHttpException(e, Context); + await ErrorHandler.HandleHttpException(e, Context); } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } @@ -109,10 +104,9 @@ namespace Geekbot.Bot.Commands.Admin { try { - var transContext = await _translationHandler.GetGuildContext(Context); if (role.IsManaged) { - await ReplyAsync(transContext.GetString("CannotAddManagedRole")); + await ReplyAsync(Localization.Role.CannotAddManagedRole); return; } @@ -122,7 +116,7 @@ namespace Geekbot.Bot.Commands.Admin || role.Permissions.BanMembers || role.Permissions.KickMembers) { - await ReplyAsync(transContext.GetString("CannotAddDangerousRole")); + await ReplyAsync(Localization.Role.CannotAddDangerousRole); return; } @@ -133,11 +127,11 @@ namespace Geekbot.Bot.Commands.Admin WhiteListName = roleName }); await _database.SaveChangesAsync(); - await ReplyAsync(transContext.GetString("AddedRoleToWhitelist", role.Name)); + await ReplyAsync(string.Format(Localization.Role.AddedRoleToWhitelist, role.Name)); } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } @@ -148,22 +142,21 @@ namespace Geekbot.Bot.Commands.Admin { try { - var transContext = await _translationHandler.GetGuildContext(Context); var roleFromDb = _database.RoleSelfService.FirstOrDefault(e => e.GuildId.Equals(Context.Guild.Id.AsLong()) && e.WhiteListName.Equals(roleName)); if (roleFromDb != null) { _database.RoleSelfService.Remove(roleFromDb); await _database.SaveChangesAsync(); - await ReplyAsync(transContext.GetString("RemovedRoleFromWhitelist", roleName)); + await ReplyAsync(string.Format(Localization.Role.RemovedRoleFromWhitelist, roleName)); return; } - await ReplyAsync(transContext.GetString("RoleNotFound")); + await ReplyAsync(Localization.Role.RoleNotFound); } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } @@ -182,14 +175,13 @@ namespace Geekbot.Bot.Commands.Admin await _reactionListener.AddRoleToListener(messageId, Context.Guild.Id, emoji, role); await Context.Message.DeleteAsync(); } - catch (HttpException e) + catch (HttpException) { await Context.Channel.SendMessageAsync("Custom emojis from other servers are not supported"); - Console.WriteLine(e); } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } } diff --git a/src/Bot/Localization/Role.Designer.cs b/src/Bot/Localization/Role.Designer.cs new file mode 100644 index 0000000..9128e3d --- /dev/null +++ b/src/Bot/Localization/Role.Designer.cs @@ -0,0 +1,153 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Geekbot.Bot.Localization { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Role { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Role() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Geekbot.Bot.Localization.Role", typeof(Role).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Added {0} to the whitelist. + /// + internal static string AddedRoleToWhitelist { + get { + return ResourceManager.GetString("AddedRoleToWhitelist", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Added you to {0}. + /// + internal static string AddedUserFromRole { + get { + return ResourceManager.GetString("AddedUserFromRole", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You cannot add that role to self service because it contains one or more dangerous permissions. + /// + internal static string CannotAddDangerousRole { + get { + return ResourceManager.GetString("CannotAddDangerousRole", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You can't add a role that is managed by discord. + /// + internal static string CannotAddManagedRole { + get { + return ResourceManager.GetString("CannotAddManagedRole", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to **Self Service Roles on {0}**. + /// + internal static string ListHeader { + get { + return ResourceManager.GetString("ListHeader", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to To get a role, use `!role [name]`. + /// + internal static string ListInstruction { + get { + return ResourceManager.GetString("ListInstruction", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There are no roles configured for this server. + /// + internal static string NoRolesConfigured { + get { + return ResourceManager.GetString("NoRolesConfigured", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Removed {0} from the whitelist. + /// + internal static string RemovedRoleFromWhitelist { + get { + return ResourceManager.GetString("RemovedRoleFromWhitelist", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Removed you from {0}. + /// + internal static string RemovedUserFromRole { + get { + return ResourceManager.GetString("RemovedUserFromRole", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to That role doesn't exist or is not on the whitelist. + /// + internal static string RoleNotFound { + get { + return ResourceManager.GetString("RoleNotFound", resourceCulture); + } + } + } +} diff --git a/src/Bot/Localization/Role.de-ch.resx b/src/Bot/Localization/Role.de-ch.resx new file mode 100644 index 0000000..b0b3259 --- /dev/null +++ b/src/Bot/Localization/Role.de-ch.resx @@ -0,0 +1,44 @@ + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Es sind kei rolle für dä server konfiguriert + + + **Self Service Rollene uf {0}** + + + Zum ä rolle becho, schriib `!role [name]` + + + Die rolle gids nid or isch nid uf dr whitelist + + + Han di entfernt vo {0} + + + Han di hinzue gfüegt zu {0} + + + Du chasch kei rolle hinzuefüge wo verwalted wird vo discord + + + Du chasch die rolle nid hinzuefüge will er ein oder mehreri gföhrlichi berechtigunge het + + + {0} isch zur whitelist hinzuegfüegt + + + {0} isch vo dr whitelist glöscht + + \ No newline at end of file diff --git a/src/Bot/Localization/Role.resx b/src/Bot/Localization/Role.resx new file mode 100644 index 0000000..63b70d0 --- /dev/null +++ b/src/Bot/Localization/Role.resx @@ -0,0 +1,51 @@ + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + There are no roles configured for this server + + + **Self Service Roles on {0}** + + + To get a role, use `!role [name]` + + + That role doesn't exist or is not on the whitelist + + + Removed you from {0} + + + Added you to {0} + + + You can't add a role that is managed by discord + + + You cannot add that role to self service because it contains one or more dangerous permissions + + + Added {0} to the whitelist + + + Removed {0} from the whitelist + + \ No newline at end of file diff --git a/src/Core/Localization/Translations.yml b/src/Core/Localization/Translations.yml index 678755d..dc18c2b 100644 --- a/src/Core/Localization/Translations.yml +++ b/src/Core/Localization/Translations.yml @@ -22,35 +22,4 @@ errorHandler: httpErrors: 403: EN: "Seems like i don't have enough permission to that :confused:" - CHDE: "Gseht danach us das ich nid gnueg recht han zum das mache :confused:" -role: - NoRolesConfigured: - EN: "There are no roles configured for this server" - CHDE: "Es sind kei rolle für dä server konfiguriert" - ListHeader: - EN: "**Self Service Roles on {0}**" - CHDE: "**Self Service Rollene uf {0}**" - ListInstruction: - EN: "To get a role, use `!role [name]`" - CHDE: "Zum ä rolle becho, schriib `!role [name]`" - RoleNotFound: - EN: "That role doesn't exist or is not on the whitelist" - CHDE: "Die rolle gids nid or isch nid uf dr whitelist" - RemovedUserFromRole: - EN: "Removed you from {0}" - CHDE: "Han di entfernt vo {0}" - AddedUserFromRole: - EN: "Added you to {0}" - CHDE: "Han di hinzue gfüegt zu {0}" - CannotAddManagedRole: - EN: "You can't add a role that is managed by discord" - CHDE: "Du chasch kei rolle hinzuefüge wo verwalted wird vo discord" - CannotAddDangerousRole: - EN: "You cannot add that role to self service because it contains one or more dangerous permissions" - CHDE: "Du chasch die rolle nid hinzuefüge will er ein oder mehreri gföhrlichi berechtigunge het" - AddedRoleToWhitelist: - EN: "Added {0} to the whitelist" - CHDE: "{0} isch zur whitelist hinzuegfüegt" - RemovedRoleFromWhitelist: - EN: "Removed {0} from the whitelist" - CHDE: "{0} isch vo dr whitelist glöscht" \ No newline at end of file + CHDE: "Gseht danach us das ich nid gnueg recht han zum das mache :confused:" \ No newline at end of file From 33829e91bc2df8c1852c0c32d91c97dcc9f7c71f Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 14 Aug 2020 23:15:11 +0200 Subject: [PATCH 382/553] Delete the TranslationHandler and the old translations file. Refactor GeekbotCommandBase to get the server language from guild settings. Create DateLocalization to create a localized relative time remaining string. --- src/Bot/Commands/Admin/Admin.cs | 87 ++++---- src/Bot/Commands/Admin/Owner/Owner.cs | 19 +- src/Bot/Commands/Admin/Role.cs | 14 +- src/Bot/Commands/Games/Roll/Roll.cs | 19 +- src/Bot/Commands/Randomness/Ship.cs | 4 +- src/Bot/Commands/Rpg/Cookies.cs | 11 +- src/Bot/Commands/User/Karma.cs | 17 +- src/Bot/Commands/User/Ranking/Rank.cs | 13 +- src/Bot/Commands/Utils/Choose.cs | 4 +- src/Bot/Commands/Utils/Quote/Quote.cs | 5 +- src/Bot/Program.cs | 5 +- src/Bot/Utils/DateLocalization.cs | 49 +++++ src/Core/Core.csproj | 6 - src/Core/ErrorHandling/ErrorHandler.cs | 24 +-- src/Core/ErrorHandling/IErrorHandler.cs | 2 - src/Core/GeekbotCommandBase.cs | 13 +- src/Core/Localization/ITranslationHandler.cs | 17 -- .../Localization/TranslationGuildContext.cs | 90 -------- src/Core/Localization/TranslationHandler.cs | 194 ------------------ src/Core/Localization/Translations.yml | 25 --- .../TranslationGuildContext.test.cs | 71 ------- tests/Core/Localization/Translations.test.cs | 46 ----- 22 files changed, 156 insertions(+), 579 deletions(-) create mode 100644 src/Bot/Utils/DateLocalization.cs delete mode 100644 src/Core/Localization/ITranslationHandler.cs delete mode 100644 src/Core/Localization/TranslationGuildContext.cs delete mode 100644 src/Core/Localization/TranslationHandler.cs delete mode 100644 src/Core/Localization/Translations.yml delete mode 100644 tests/Core/Localization/TranslationGuildContext.test.cs delete mode 100644 tests/Core/Localization/Translations.test.cs diff --git a/src/Bot/Commands/Admin/Admin.cs b/src/Bot/Commands/Admin/Admin.cs index 2627f86..60ba8ac 100644 --- a/src/Bot/Commands/Admin/Admin.cs +++ b/src/Bot/Commands/Admin/Admin.cs @@ -14,7 +14,6 @@ using Geekbot.Core.CommandPreconditions; using Geekbot.Core.ErrorHandling; using Geekbot.Core.Extensions; using Geekbot.Core.GuildSettingsManager; -using Geekbot.Core.Localization; namespace Geekbot.Bot.Commands.Admin { @@ -24,21 +23,18 @@ namespace Geekbot.Bot.Commands.Admin public class Admin : GeekbotCommandBase { private readonly DiscordSocketClient _client; - private readonly IGuildSettingsManager _guildSettingsManager; - public Admin(DiscordSocketClient client, IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager, ITranslationHandler translationHandler) : base(errorHandler, translationHandler) + public Admin(DiscordSocketClient client, IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager) : base(errorHandler, guildSettingsManager) { _client = client; - _guildSettingsManager = guildSettingsManager; } [Command("welcome", RunMode = RunMode.Async)] [Summary("Set a Welcome Message (use '$user' to mention the new joined user).")] public async Task SetWelcomeMessage([Remainder, Summary("message")] string welcomeMessage) { - var guild = _guildSettingsManager.GetSettings(Context.Guild.Id); - guild.WelcomeMessage = welcomeMessage; - await _guildSettingsManager.UpdateSettings(guild); + GuildSettings.WelcomeMessage = welcomeMessage; + await GuildSettingsManager.UpdateSettings(GuildSettings); var formatedMessage = welcomeMessage.Replace("$user", Context.User.Mention); await ReplyAsync($"Welcome message has been changed\r\nHere is an example of how it would look:\r\n{formatedMessage}"); @@ -52,9 +48,8 @@ namespace Geekbot.Bot.Commands.Admin { var m = await channel.SendMessageAsync("..."); - var guild = _guildSettingsManager.GetSettings(Context.Guild.Id); - guild.WelcomeChannel = channel.Id.AsLong(); - await _guildSettingsManager.UpdateSettings(guild); + GuildSettings.WelcomeChannel = channel.Id.AsLong(); + await GuildSettingsManager.UpdateSettings(GuildSettings); await m.DeleteAsync(); @@ -74,9 +69,8 @@ namespace Geekbot.Bot.Commands.Admin { var m = await channel.SendMessageAsync("verifying..."); - var guild = _guildSettingsManager.GetSettings(Context.Guild.Id); - guild.ModChannel = channel.Id.AsLong(); - await _guildSettingsManager.UpdateSettings(guild); + GuildSettings.ModChannel = channel.Id.AsLong(); + await GuildSettingsManager.UpdateSettings(GuildSettings); var sb = new StringBuilder(); sb.AppendLine("Successfully saved mod channel, you can now do the following"); @@ -96,13 +90,12 @@ namespace Geekbot.Bot.Commands.Admin { try { - var guild = _guildSettingsManager.GetSettings(Context.Guild.Id); - var modChannel = await GetModChannel(guild.ModChannel.AsUlong()); + var modChannel = await GetModChannel(GuildSettings.ModChannel.AsUlong()); if (modChannel == null) return; - guild.ShowLeave = !guild.ShowLeave; - await _guildSettingsManager.UpdateSettings(guild); - await modChannel.SendMessageAsync(guild.ShowLeave + GuildSettings.ShowLeave = !GuildSettings.ShowLeave; + await GuildSettingsManager.UpdateSettings(GuildSettings); + await modChannel.SendMessageAsync(GuildSettings.ShowLeave ? "Saved - now sending messages here when someone leaves" : "Saved - stopping sending messages here when someone leaves" ); @@ -119,13 +112,12 @@ namespace Geekbot.Bot.Commands.Admin { try { - var guild = _guildSettingsManager.GetSettings(Context.Guild.Id); - var modChannel = await GetModChannel(guild.ModChannel.AsUlong()); + var modChannel = await GetModChannel(GuildSettings.ModChannel.AsUlong()); if (modChannel == null) return; - guild.ShowDelete = !guild.ShowDelete; - await _guildSettingsManager.UpdateSettings(guild); - await modChannel.SendMessageAsync(guild.ShowDelete + GuildSettings.ShowDelete = !GuildSettings.ShowDelete; + await GuildSettingsManager.UpdateSettings(GuildSettings); + await modChannel.SendMessageAsync(GuildSettings.ShowDelete ? "Saved - now sending messages here when someone deletes a message" : "Saved - stopping sending messages here when someone deletes a message" ); @@ -138,31 +130,25 @@ namespace Geekbot.Bot.Commands.Admin [Command("setlang", RunMode = RunMode.Async)] [Summary("Change the bots language")] - public async Task SetLanguage([Summary("language")] string languageRaw) + public async Task SetLanguage([Summary("language")] string language) { try { - var language = languageRaw.ToUpper(); - var success = await Translations.SetLanguage(Context.Guild.Id, language); - if (success) + var availableLanguages = new List(); + availableLanguages.Add("en-GB"); // default + availableLanguages.AddRange(GetAvailableCultures().Select(culture => culture.Name)); + if (availableLanguages.Contains(language)) { - var guild = _guildSettingsManager.GetSettings(Context.Guild.Id); - guild.Language = language; - await _guildSettingsManager.UpdateSettings(guild); + GuildSettings.Language = language; + await GuildSettingsManager.UpdateSettings(GuildSettings); + + Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(language.ToLower() == "chde" ? "de-CH" : language); - if (language.ToLower() == "chde") - { - Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("de-ch"); - } - await ReplyAsync(Localization.Admin.NewLanguageSet); return; } - - var available = new List(); - available.Add("en-GB"); // default - available.AddRange(GetAvailableCultures().Select(culture => culture.Name)); - await ReplyAsync($"That doesn't seem to be a supported language\nSupported Languages are {string.Join(", ", available)}"); + + await ReplyAsync($"That doesn't seem to be a supported language\nSupported Languages are {string.Join(", ", availableLanguages)}"); } catch (Exception e) { @@ -177,9 +163,8 @@ namespace Geekbot.Bot.Commands.Admin try { var language = languageRaw.ToLower(); - var guild = _guildSettingsManager.GetSettings(Context.Guild.Id); - guild.WikiLang = language; - await _guildSettingsManager.UpdateSettings(guild); + GuildSettings.WikiLang = language; + await GuildSettingsManager.UpdateSettings(GuildSettings); await ReplyAsync($"Now using the {language} wikipedia"); } @@ -195,10 +180,10 @@ namespace Geekbot.Bot.Commands.Admin { try { - var guild = _guildSettingsManager.GetSettings(Context.Guild.Id); - guild.Ping = !guild.Ping; - await _guildSettingsManager.UpdateSettings(guild); - await ReplyAsync(guild.Ping ? "i will reply to ping now" : "No more pongs..."); + // var guild = _guildSettingsManager.GetSettings(Context.Guild.Id); + GuildSettings.Ping = !GuildSettings.Ping; + await GuildSettingsManager.UpdateSettings(GuildSettings); + await ReplyAsync(GuildSettings.Ping ? "i will reply to ping now" : "No more pongs..."); } catch (Exception e) { @@ -212,10 +197,10 @@ namespace Geekbot.Bot.Commands.Admin { try { - var guild = _guildSettingsManager.GetSettings(Context.Guild.Id); - guild.Hui = !guild.Hui; - await _guildSettingsManager.UpdateSettings(guild); - await ReplyAsync(guild.Hui ? "i will reply to hui now" : "No more hui's..."); + // var guild = _guildSettingsManager.GetSettings(Context.Guild.Id); + GuildSettings.Hui = !GuildSettings.Hui; + await GuildSettingsManager.UpdateSettings(GuildSettings); + await ReplyAsync(GuildSettings.Hui ? "i will reply to hui now" : "No more hui's..."); } catch (Exception e) { diff --git a/src/Bot/Commands/Admin/Owner/Owner.cs b/src/Bot/Commands/Admin/Owner/Owner.cs index 5fa3976..64292e9 100644 --- a/src/Bot/Commands/Admin/Owner/Owner.cs +++ b/src/Bot/Commands/Admin/Owner/Owner.cs @@ -3,8 +3,10 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.WebSocket; +using Geekbot.Core; using Geekbot.Core.ErrorHandling; using Geekbot.Core.GlobalSettings; +using Geekbot.Core.GuildSettingsManager; using Geekbot.Core.Logger; using Geekbot.Core.UserRepository; @@ -12,20 +14,19 @@ namespace Geekbot.Bot.Commands.Admin.Owner { [Group("owner")] [RequireOwner] - public class Owner : ModuleBase + public class Owner : GeekbotCommandBase { private readonly DiscordSocketClient _client; - private readonly IErrorHandler _errorHandler; private readonly IGlobalSettings _globalSettings; private readonly IGeekbotLogger _logger; private readonly IUserRepository _userRepository; - public Owner(DiscordSocketClient client, IGeekbotLogger logger, IUserRepository userRepositry, IErrorHandler errorHandler, IGlobalSettings globalSettings) + public Owner(DiscordSocketClient client, IGeekbotLogger logger, IUserRepository userRepositry, IErrorHandler errorHandler, IGlobalSettings globalSettings, + IGuildSettingsManager guildSettingsManager) : base(errorHandler, guildSettingsManager) { _client = client; _logger = logger; _userRepository = userRepositry; - _errorHandler = errorHandler; _globalSettings = globalSettings; } @@ -73,7 +74,7 @@ namespace Geekbot.Bot.Commands.Admin.Owner } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context, + await ErrorHandler.HandleCommandException(e, Context, "Couldn't complete User Repository, see console for more info"); } } @@ -89,10 +90,10 @@ namespace Geekbot.Bot.Commands.Admin.Owner } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } - + [Command("refreshuser", RunMode = RunMode.Async)] [Summary("Refresh a user in the user cache")] public async Task PopUserRepoCommand([Summary("user-id")] ulong userId) @@ -105,7 +106,7 @@ namespace Geekbot.Bot.Commands.Admin.Owner } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } @@ -119,7 +120,7 @@ namespace Geekbot.Bot.Commands.Admin.Owner } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } } diff --git a/src/Bot/Commands/Admin/Role.cs b/src/Bot/Commands/Admin/Role.cs index c8459dd..efec7bd 100644 --- a/src/Bot/Commands/Admin/Role.cs +++ b/src/Bot/Commands/Admin/Role.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Net; using System.Text; using System.Threading.Tasks; using Discord; @@ -11,7 +12,7 @@ using Geekbot.Core.Database; using Geekbot.Core.Database.Models; using Geekbot.Core.ErrorHandling; using Geekbot.Core.Extensions; -using Geekbot.Core.Localization; +using Geekbot.Core.GuildSettingsManager; using Geekbot.Core.ReactionListener; namespace Geekbot.Bot.Commands.Admin @@ -23,7 +24,7 @@ namespace Geekbot.Bot.Commands.Admin private readonly DatabaseContext _database; private readonly IReactionListener _reactionListener; - public Role(DatabaseContext database, IErrorHandler errorHandler, IReactionListener reactionListener, ITranslationHandler translationHandler) : base(errorHandler, translationHandler) + public Role(DatabaseContext database, IErrorHandler errorHandler, IReactionListener reactionListener, IGuildSettingsManager guildSettingsManager) : base(errorHandler, guildSettingsManager) { _database = database; _reactionListener = reactionListener; @@ -89,7 +90,14 @@ namespace Geekbot.Bot.Commands.Admin } catch (HttpException e) { - await ErrorHandler.HandleHttpException(e, Context); + if (e.HttpCode == HttpStatusCode.Forbidden) + { + await ReplyAsync(Localization.Internal.Http403); + } + else + { + await ErrorHandler.HandleCommandException(e, Context); + } } catch (Exception e) { diff --git a/src/Bot/Commands/Games/Roll/Roll.cs b/src/Bot/Commands/Games/Roll/Roll.cs index 244edbe..6ef9322 100644 --- a/src/Bot/Commands/Games/Roll/Roll.cs +++ b/src/Bot/Commands/Games/Roll/Roll.cs @@ -2,13 +2,14 @@ using System.Linq; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.Bot.Utils; using Geekbot.Core; using Geekbot.Core.Database; using Geekbot.Core.Database.Models; using Geekbot.Core.ErrorHandling; using Geekbot.Core.Extensions; +using Geekbot.Core.GuildSettingsManager; using Geekbot.Core.KvInMemoryStore; -using Geekbot.Core.Localization; using Geekbot.Core.RandomNumberGenerator; namespace Geekbot.Bot.Commands.Games.Roll @@ -19,7 +20,8 @@ namespace Geekbot.Bot.Commands.Games.Roll private readonly DatabaseContext _database; private readonly IRandomNumberGenerator _randomNumberGenerator; - public Roll(IKvInMemoryStore kvInMemoryStore,IErrorHandler errorHandler, ITranslationHandler translation, DatabaseContext database, IRandomNumberGenerator randomNumberGenerator) : base(errorHandler, translation) + public Roll(IKvInMemoryStore kvInMemoryStore, IErrorHandler errorHandler, DatabaseContext database, IRandomNumberGenerator randomNumberGenerator, IGuildSettingsManager guildSettingsManager) + : base(errorHandler, guildSettingsManager) { _kvInMemoryStore = kvInMemoryStore; _database = database; @@ -34,10 +36,9 @@ namespace Geekbot.Bot.Commands.Games.Roll { var number = _randomNumberGenerator.Next(1, 100); int.TryParse(stuff, out var guess); - var transContext = await Translations.GetGuildContext(Context); if (guess <= 100 && guess > 0) { - var kvKey = $"{Context.Guild.Id}:{Context.User.Id}:RollsPrevious"; + var kvKey = $"{Context?.Guild?.Id ?? 0}:{Context.User.Id}:RollsPrevious"; var prevRoll = _kvInMemoryStore.Get(kvKey); @@ -46,11 +47,11 @@ namespace Geekbot.Bot.Commands.Games.Roll await ReplyAsync(string.Format( Localization.Roll.NoPrevGuess, Context.Message.Author.Mention, - transContext.FormatDateTimeAsRemaining(prevRoll.GuessedOn.AddDays(1)))); + DateLocalization.FormatDateTimeAsRemaining(prevRoll.GuessedOn.AddDays(1)))); return; } - _kvInMemoryStore.Set(kvKey, new RollTimeout { LastGuess = guess, GuessedOn = DateTime.Now }); + _kvInMemoryStore.Set(kvKey, new RollTimeout {LastGuess = guess, GuessedOn = DateTime.Now}); await ReplyAsync(string.Format(Localization.Roll.Rolled, Context.Message.Author.Mention, number, guess)); if (guess == number) @@ -72,13 +73,13 @@ namespace Geekbot.Bot.Commands.Games.Roll await ErrorHandler.HandleCommandException(e, Context); } } - + private async Task GetUser(ulong userId) { - var user = _database.Rolls.FirstOrDefault(u =>u.GuildId.Equals(Context.Guild.Id.AsLong()) && u.UserId.Equals(userId.AsLong())) ?? await CreateNewRow(userId); + var user = _database.Rolls.FirstOrDefault(u => u.GuildId.Equals(Context.Guild.Id.AsLong()) && u.UserId.Equals(userId.AsLong())) ?? await CreateNewRow(userId); return user; } - + private async Task CreateNewRow(ulong userId) { var user = new RollsModel() diff --git a/src/Bot/Commands/Randomness/Ship.cs b/src/Bot/Commands/Randomness/Ship.cs index 78f3c99..f48713e 100644 --- a/src/Bot/Commands/Randomness/Ship.cs +++ b/src/Bot/Commands/Randomness/Ship.cs @@ -8,7 +8,7 @@ using Geekbot.Core.Database; using Geekbot.Core.Database.Models; using Geekbot.Core.ErrorHandling; using Geekbot.Core.Extensions; -using Geekbot.Core.Localization; +using Geekbot.Core.GuildSettingsManager; using Geekbot.Core.RandomNumberGenerator; namespace Geekbot.Bot.Commands.Randomness @@ -18,7 +18,7 @@ namespace Geekbot.Bot.Commands.Randomness private readonly IRandomNumberGenerator _randomNumberGenerator; private readonly DatabaseContext _database; - public Ship(DatabaseContext database, IErrorHandler errorHandler, IRandomNumberGenerator randomNumberGenerator, ITranslationHandler translations) : base(errorHandler, translations) + public Ship(DatabaseContext database, IErrorHandler errorHandler, IRandomNumberGenerator randomNumberGenerator, IGuildSettingsManager guildSettingsManager) : base(errorHandler, guildSettingsManager) { _database = database; _randomNumberGenerator = randomNumberGenerator; diff --git a/src/Bot/Commands/Rpg/Cookies.cs b/src/Bot/Commands/Rpg/Cookies.cs index 570f08a..a51d652 100644 --- a/src/Bot/Commands/Rpg/Cookies.cs +++ b/src/Bot/Commands/Rpg/Cookies.cs @@ -3,13 +3,14 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.Bot.Utils; using Geekbot.Core; using Geekbot.Core.CommandPreconditions; using Geekbot.Core.Database; using Geekbot.Core.Database.Models; using Geekbot.Core.ErrorHandling; using Geekbot.Core.Extensions; -using Geekbot.Core.Localization; +using Geekbot.Core.GuildSettingsManager; using Geekbot.Core.RandomNumberGenerator; namespace Geekbot.Bot.Commands.Rpg @@ -22,7 +23,8 @@ namespace Geekbot.Bot.Commands.Rpg private readonly DatabaseContext _database; private readonly IRandomNumberGenerator _randomNumberGenerator; - public Cookies(DatabaseContext database, IErrorHandler errorHandler, ITranslationHandler translations , IRandomNumberGenerator randomNumberGenerator) : base(errorHandler, translations) + public Cookies(DatabaseContext database, IErrorHandler errorHandler, IRandomNumberGenerator randomNumberGenerator, IGuildSettingsManager guildSettingsManager) + : base(errorHandler, guildSettingsManager) { _database = database; _randomNumberGenerator = randomNumberGenerator; @@ -34,12 +36,11 @@ namespace Geekbot.Bot.Commands.Rpg { try { - var transContext = await Translations.GetGuildContext(Context); var actor = await GetUser(Context.User.Id); if (actor.LastPayout.Value.AddDays(1).Date > DateTime.Now.Date) { - var formatedWaitTime = transContext.FormatDateTimeAsRemaining(DateTimeOffset.Now.AddDays(1).Date); - await ReplyAsync(string.Format(Localization.Cookies.WaitForMoreCookies, formatedWaitTime)); + var formattedWaitTime = DateLocalization.FormatDateTimeAsRemaining(DateTimeOffset.Now.AddDays(1).Date); + await ReplyAsync(string.Format(Localization.Cookies.WaitForMoreCookies, formattedWaitTime)); return; } actor.Cookies += 10; diff --git a/src/Bot/Commands/User/Karma.cs b/src/Bot/Commands/User/Karma.cs index 41a401c..4778bce 100644 --- a/src/Bot/Commands/User/Karma.cs +++ b/src/Bot/Commands/User/Karma.cs @@ -1,17 +1,16 @@ using System; -using System.Globalization; using System.Linq; -using System.Threading; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.Bot.Utils; using Geekbot.Core; using Geekbot.Core.CommandPreconditions; using Geekbot.Core.Database; using Geekbot.Core.Database.Models; using Geekbot.Core.ErrorHandling; using Geekbot.Core.Extensions; -using Geekbot.Core.Localization; +using Geekbot.Core.GuildSettingsManager; namespace Geekbot.Bot.Commands.User { @@ -19,12 +18,10 @@ namespace Geekbot.Bot.Commands.User public class Karma : GeekbotCommandBase { private readonly DatabaseContext _database; - private readonly ITranslationHandler _translations; - public Karma(DatabaseContext database, IErrorHandler errorHandler, ITranslationHandler translations) : base(errorHandler, translations) + public Karma(DatabaseContext database, IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager) : base(errorHandler, guildSettingsManager) { _database = database; - _translations = translations; } [Command("good", RunMode = RunMode.Async)] @@ -33,8 +30,6 @@ namespace Geekbot.Bot.Commands.User { try { - var transContext = await _translations.GetGuildContext(Context); - var actor = await GetUser(Context.User.Id); if (user.Id == Context.User.Id) { @@ -42,7 +37,7 @@ namespace Geekbot.Bot.Commands.User } else if (TimeoutFinished(actor.TimeOut)) { - var formatedWaitTime = transContext.FormatDateTimeAsRemaining(actor.TimeOut.AddMinutes(3)); + var formatedWaitTime = DateLocalization.FormatDateTimeAsRemaining(actor.TimeOut.AddMinutes(3)); await ReplyAsync(string.Format(Localization.Karma.WaitUntill, Context.User.Username, formatedWaitTime)); } else @@ -81,8 +76,6 @@ namespace Geekbot.Bot.Commands.User { try { - var transContext = await _translations.GetGuildContext(Context); - var actor = await GetUser(Context.User.Id); if (user.Id == Context.User.Id) { @@ -90,7 +83,7 @@ namespace Geekbot.Bot.Commands.User } else if (TimeoutFinished(actor.TimeOut)) { - var formatedWaitTime = transContext.FormatDateTimeAsRemaining(actor.TimeOut.AddMinutes(3)); + var formatedWaitTime = DateLocalization.FormatDateTimeAsRemaining(actor.TimeOut.AddMinutes(3)); await ReplyAsync(string.Format(Localization.Karma.WaitUntill, Context.User.Username, formatedWaitTime)); } else diff --git a/src/Bot/Commands/User/Ranking/Rank.cs b/src/Bot/Commands/User/Ranking/Rank.cs index d73aacc..20749a8 100644 --- a/src/Bot/Commands/User/Ranking/Rank.cs +++ b/src/Bot/Commands/User/Ranking/Rank.cs @@ -10,8 +10,8 @@ using Geekbot.Core.Converters; using Geekbot.Core.Database; using Geekbot.Core.ErrorHandling; using Geekbot.Core.Extensions; +using Geekbot.Core.GuildSettingsManager; using Geekbot.Core.Highscores; -using Geekbot.Core.Localization; namespace Geekbot.Bot.Commands.User.Ranking { @@ -21,7 +21,8 @@ namespace Geekbot.Bot.Commands.User.Ranking private readonly IHighscoreManager _highscoreManager; private readonly DatabaseContext _database; - public Rank(DatabaseContext database, IErrorHandler errorHandler, IEmojiConverter emojiConverter, IHighscoreManager highscoreManager, ITranslationHandler translations): base(errorHandler, translations) + public Rank(DatabaseContext database, IErrorHandler errorHandler, IEmojiConverter emojiConverter, IHighscoreManager highscoreManager, IGuildSettingsManager guildSettingsManager) + : base(errorHandler, guildSettingsManager) { _database = database; _emojiConverter = emojiConverter; @@ -53,7 +54,7 @@ namespace Geekbot.Bot.Commands.User.Ranking await ReplyAsync(Localization.Rank.LimitingTo20Warning); amount = 20; } - + var guildId = Context.Guild.Id; Dictionary highscoreUsers; try @@ -78,9 +79,9 @@ namespace Geekbot.Bot.Commands.User.Ranking var failedToRetrieveUser = highscoreUsers.Any(e => string.IsNullOrEmpty(e.Key.Username)); if (failedToRetrieveUser) replyBuilder.AppendLine(Localization.Rank.FailedToResolveAllUsernames).AppendLine(); - + replyBuilder.AppendLine(string.Format(Localization.Rank.HighscoresFor, type.ToString().CapitalizeFirst(), Context.Guild.Name)); - + var highscorePlace = 1; foreach (var (user, value) in highscoreUsers) { @@ -91,7 +92,7 @@ namespace Geekbot.Bot.Commands.User.Ranking replyBuilder.Append(user.Username != null ? $"**{user.Username}#{user.Discriminator}**" : $"**{user.Id}**"); - + replyBuilder.Append(type == HighscoreTypes.messages ? $" - {value} {type} - {Math.Round((double) (100 * value) / guildMessages, 2)}%\n" : $" - {value} {type}\n"); diff --git a/src/Bot/Commands/Utils/Choose.cs b/src/Bot/Commands/Utils/Choose.cs index ea239d7..731bee6 100644 --- a/src/Bot/Commands/Utils/Choose.cs +++ b/src/Bot/Commands/Utils/Choose.cs @@ -3,13 +3,13 @@ using System.Threading.Tasks; using Discord.Commands; using Geekbot.Core; using Geekbot.Core.ErrorHandling; -using Geekbot.Core.Localization; +using Geekbot.Core.GuildSettingsManager; namespace Geekbot.Bot.Commands.Utils { public class Choose : GeekbotCommandBase { - public Choose(IErrorHandler errorHandler, ITranslationHandler translation) : base(errorHandler, translation) + public Choose(IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager) : base(errorHandler, guildSettingsManager) { } diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index 5bb23a9..a7d3ff1 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -9,7 +9,7 @@ using Geekbot.Core.Database; using Geekbot.Core.Database.Models; using Geekbot.Core.ErrorHandling; using Geekbot.Core.Extensions; -using Geekbot.Core.Localization; +using Geekbot.Core.GuildSettingsManager; using Geekbot.Core.Polyfills; using Geekbot.Core.RandomNumberGenerator; @@ -23,7 +23,8 @@ namespace Geekbot.Bot.Commands.Utils.Quote private readonly IRandomNumberGenerator _randomNumberGenerator; private readonly bool _isDev; - public Quote(IErrorHandler errorHandler, DatabaseContext database, IRandomNumberGenerator randomNumberGenerator, ITranslationHandler translationHandler) : base(errorHandler, translationHandler) + public Quote(IErrorHandler errorHandler, DatabaseContext database, IRandomNumberGenerator randomNumberGenerator, IGuildSettingsManager guildSettingsManager) + : base(errorHandler, guildSettingsManager) { _database = database; _randomNumberGenerator = randomNumberGenerator; diff --git a/src/Bot/Program.cs b/src/Bot/Program.cs index 04b1450..5a4b456 100644 --- a/src/Bot/Program.cs +++ b/src/Bot/Program.cs @@ -17,7 +17,6 @@ using Geekbot.Core.GuildSettingsManager; using Geekbot.Core.Highscores; using Geekbot.Core.KvInMemoryStore; using Geekbot.Core.Levels; -using Geekbot.Core.Localization; using Geekbot.Core.Logger; using Geekbot.Core.MalClient; using Geekbot.Core.Media; @@ -168,8 +167,7 @@ namespace Geekbot.Bot var randomNumberGenerator = new RandomNumberGenerator(); var mediaProvider = new MediaProvider(_logger, randomNumberGenerator); var kvMemoryStore = new KvInInMemoryStore(); - var translationHandler = new TranslationHandler(_logger, _guildSettingsManager); - var errorHandler = new ErrorHandler(_logger, translationHandler, _runParameters); + var errorHandler = new ErrorHandler(_logger, _runParameters, () => Localization.Internal.SomethingWentWrong); var diceParser = new DiceParser(randomNumberGenerator); services.AddSingleton(_userRepository); @@ -186,7 +184,6 @@ namespace Geekbot.Bot services.AddSingleton(_globalSettings); services.AddSingleton(errorHandler); services.AddSingleton(diceParser); - services.AddSingleton(translationHandler); services.AddSingleton(_reactionListener); services.AddSingleton(_guildSettingsManager); services.AddSingleton(_client); diff --git a/src/Bot/Utils/DateLocalization.cs b/src/Bot/Utils/DateLocalization.cs new file mode 100644 index 0000000..eea40fb --- /dev/null +++ b/src/Bot/Utils/DateLocalization.cs @@ -0,0 +1,49 @@ +using System; +using System.Text; + +namespace Geekbot.Bot.Utils +{ + public class DateLocalization + { + public static string FormatDateTimeAsRemaining(DateTimeOffset dateTime) + { + var remaining = dateTime - DateTimeOffset.Now; + const string formattable = "{0} {1}"; + var sb = new StringBuilder(); + + if (remaining.Days > 0) + { + sb.AppendFormat(formattable, remaining.Days, GetSingularOrPlural(remaining.Days, Localization.Internal.Days)); + } + + if (remaining.Hours > 0) + { + if (sb.Length > 0) sb.Append(", "); + sb.AppendFormat(formattable, remaining.Hours, GetSingularOrPlural(remaining.Hours, Localization.Internal.Hours)); + } + + if (remaining.Minutes > 0) + { + if (sb.Length > 0) sb.Append(", "); + sb.AppendFormat(formattable, remaining.Minutes, GetSingularOrPlural(remaining.Minutes, Localization.Internal.Minutes)); + } + + if (remaining.Seconds > 0) + { + if (sb.Length > 0) + { + sb.AppendFormat(" {0} ", Localization.Internal.And); + } + sb.AppendFormat(formattable, remaining.Seconds, GetSingularOrPlural(remaining.Seconds, Localization.Internal.Seconds)); + } + + return sb.ToString().Trim(); + } + + private static string GetSingularOrPlural(int number, string rawString) + { + var versions = rawString.Split('|'); + return number == 1 ? versions[0] : versions[1]; + } + } +} \ No newline at end of file diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index fcbce09..fd44a95 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -31,10 +31,4 @@ - - - PreserveNewest - - - diff --git a/src/Core/ErrorHandling/ErrorHandler.cs b/src/Core/ErrorHandling/ErrorHandler.cs index 02402f2..47ed22d 100644 --- a/src/Core/ErrorHandling/ErrorHandler.cs +++ b/src/Core/ErrorHandling/ErrorHandler.cs @@ -1,9 +1,6 @@ using System; -using System.Net; using System.Threading.Tasks; using Discord.Commands; -using Discord.Net; -using Geekbot.Core.Localization; using Geekbot.Core.Logger; using SharpRaven; using SharpRaven.Data; @@ -14,14 +11,14 @@ namespace Geekbot.Core.ErrorHandling public class ErrorHandler : IErrorHandler { private readonly IGeekbotLogger _logger; - private readonly ITranslationHandler _translation; + private readonly Func _getDefaultErrorText; private readonly IRavenClient _raven; private readonly bool _errorsInChat; - public ErrorHandler(IGeekbotLogger logger, ITranslationHandler translation, RunParameters runParameters) + public ErrorHandler(IGeekbotLogger logger, RunParameters runParameters, Func getDefaultErrorText) { _logger = logger; - _translation = translation; + _getDefaultErrorText = getDefaultErrorText; _errorsInChat = runParameters.ExposeErrors; var sentryDsn = runParameters.SentryEndpoint; @@ -40,7 +37,9 @@ namespace Geekbot.Core.ErrorHandling { try { - var errorString = errorMessage == "def" ? await _translation.GetString(context.Guild?.Id ?? 0, "errorHandler", "SomethingWentWrong") : errorMessage; + var errorString = errorMessage == "def" + ? _getDefaultErrorText() + : errorMessage; var errorObj = SimpleConextConverter.ConvertContext(context); if (e.Message.Contains("50007")) return; if (e.Message.Contains("50013")) return; @@ -76,17 +75,6 @@ namespace Geekbot.Core.ErrorHandling } } - public async Task HandleHttpException(HttpException e, ICommandContext context) - { - var errorStrings = await _translation.GetDict(context, "httpErrors"); - switch(e.HttpCode) - { - case HttpStatusCode.Forbidden: - await context.Channel.SendMessageAsync(errorStrings["403"]); - break; - } - } - private void ReportExternal(Exception e, MessageDto errorObj) { if (_raven == null) return; diff --git a/src/Core/ErrorHandling/IErrorHandler.cs b/src/Core/ErrorHandling/IErrorHandler.cs index c012b82..d0e1d20 100644 --- a/src/Core/ErrorHandling/IErrorHandler.cs +++ b/src/Core/ErrorHandling/IErrorHandler.cs @@ -1,13 +1,11 @@ using System; using System.Threading.Tasks; using Discord.Commands; -using Discord.Net; namespace Geekbot.Core.ErrorHandling { public interface IErrorHandler { Task HandleCommandException(Exception e, ICommandContext context, string errorMessage = "def"); - Task HandleHttpException(HttpException e, ICommandContext context); } } \ No newline at end of file diff --git a/src/Core/GeekbotCommandBase.cs b/src/Core/GeekbotCommandBase.cs index 8df5265..43ced95 100644 --- a/src/Core/GeekbotCommandBase.cs +++ b/src/Core/GeekbotCommandBase.cs @@ -1,26 +1,29 @@ using System.Globalization; using System.Threading; using Discord.Commands; +using Geekbot.Core.Database.Models; using Geekbot.Core.ErrorHandling; -using Geekbot.Core.Localization; +using Geekbot.Core.GuildSettingsManager; namespace Geekbot.Core { public class GeekbotCommandBase : ModuleBase { + protected readonly IGuildSettingsManager GuildSettingsManager; + protected GuildSettingsModel GuildSettings; protected readonly IErrorHandler ErrorHandler; - protected readonly ITranslationHandler Translations; - protected GeekbotCommandBase(IErrorHandler errorHandler, ITranslationHandler translations) + protected GeekbotCommandBase(IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager) { + GuildSettingsManager = guildSettingsManager; ErrorHandler = errorHandler; - Translations = translations; } protected override void BeforeExecute(CommandInfo command) { base.BeforeExecute(command); - var language = Translations.GetServerLanguage(Context.Guild.Id); + GuildSettings = GuildSettingsManager.GetSettings(Context?.Guild?.Id ?? 0); + var language = GuildSettings.Language; Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(language == "CHDE" ? "de-ch" : language); } } diff --git a/src/Core/Localization/ITranslationHandler.cs b/src/Core/Localization/ITranslationHandler.cs deleted file mode 100644 index 1cc06fa..0000000 --- a/src/Core/Localization/ITranslationHandler.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Discord.Commands; - -namespace Geekbot.Core.Localization -{ - public interface ITranslationHandler - { - Task GetString(ulong guildId, string command, string stringName); - string GetString(string language, string command, string stringName); - Task> GetDict(ICommandContext context, string command); - Task GetGuildContext(ICommandContext context); - Task SetLanguage(ulong guildId, string language); - List SupportedLanguages { get; } - string GetServerLanguage(ulong guildId); - } -} \ No newline at end of file diff --git a/src/Core/Localization/TranslationGuildContext.cs b/src/Core/Localization/TranslationGuildContext.cs deleted file mode 100644 index 25685da..0000000 --- a/src/Core/Localization/TranslationGuildContext.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading.Tasks; - -namespace Geekbot.Core.Localization -{ - public class TranslationGuildContext - { - public ITranslationHandler TranslationHandler { get; } - public string Language { get; } - public Dictionary Dict { get; } - - public TranslationGuildContext(ITranslationHandler translationHandler, string language, Dictionary dict) - { - TranslationHandler = translationHandler; - Language = language; - Dict = dict; - } - - public string GetString(string stringToFormat, params object[] args) - { - return string.Format(Dict[stringToFormat] ?? "", args); - } - - public string FormatDateTimeAsRemaining(DateTimeOffset dateTime) - { - var remaining = dateTime - DateTimeOffset.Now; - const string formattable = "{0} {1}"; - var sb = new StringBuilder(); - - if (remaining.Days > 0) - { - var s = GetTimeString(TimeTypes.Days); - sb.AppendFormat(formattable, remaining.Days, GetSingOrPlur(remaining.Days, s)); - } - - if (remaining.Hours > 0) - { - if (sb.Length > 0) sb.Append(", "); - var s = GetTimeString(TimeTypes.Hours); - sb.AppendFormat(formattable, remaining.Hours, GetSingOrPlur(remaining.Hours, s)); - } - - if (remaining.Minutes > 0) - { - if (sb.Length > 0) sb.Append(", "); - var s = GetTimeString(TimeTypes.Minutes); - sb.AppendFormat(formattable, remaining.Minutes, GetSingOrPlur(remaining.Minutes, s)); - } - - if (remaining.Seconds > 0) - { - if (sb.Length > 0) - { - var and = TranslationHandler.GetString(Language, "dateTime", "And"); - sb.AppendFormat(" {0} ", and); - } - var s = GetTimeString(TimeTypes.Seconds); - sb.AppendFormat(formattable, remaining.Seconds, GetSingOrPlur(remaining.Seconds, s)); - } - - return sb.ToString().Trim(); - } - - public Task SetLanguage(ulong guildId, string language) - { - return TranslationHandler.SetLanguage(guildId, language); - } - - private string GetTimeString(TimeTypes type) - { - return TranslationHandler.GetString(Language, "dateTime", type.ToString()); - } - - private string GetSingOrPlur(int number, string rawString) - { - var versions = rawString.Split('|'); - return number == 1 ? versions[0] : versions[1]; - } - - private enum TimeTypes - { - Days, - Hours, - Minutes, - Seconds - } - } -} \ No newline at end of file diff --git a/src/Core/Localization/TranslationHandler.cs b/src/Core/Localization/TranslationHandler.cs deleted file mode 100644 index 1a46ada..0000000 --- a/src/Core/Localization/TranslationHandler.cs +++ /dev/null @@ -1,194 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Discord.Commands; -using Geekbot.Core.GuildSettingsManager; -using Geekbot.Core.Logger; -using YamlDotNet.Core; -using YamlDotNet.Serialization; - -namespace Geekbot.Core.Localization -{ - public class TranslationHandler : ITranslationHandler - { - private readonly IGeekbotLogger _logger; - private readonly IGuildSettingsManager _guildSettingsManager; - private readonly Dictionary _serverLanguages; - private Dictionary>> _translations; - - public TranslationHandler(IGeekbotLogger logger, IGuildSettingsManager guildSettingsManager) - { - _logger = logger; - _guildSettingsManager = guildSettingsManager; - _logger.Information(LogSource.Geekbot, "Loading Translations"); - LoadTranslations(); - _serverLanguages = new Dictionary(); - } - - private void LoadTranslations() - { - try - { - // Read the file - var translationFile = File.ReadAllText(Path.GetFullPath("./Localization/Translations.yml")); - - // Deserialize - var input = new StringReader(translationFile); - var mergingParser = new MergingParser(new Parser(input)); - var deserializer = new DeserializerBuilder().Build(); - var rawTranslations = deserializer.Deserialize>>>(mergingParser); - - // Sort - var sortedPerLanguage = new Dictionary>>(); - foreach (var command in rawTranslations) - { - foreach (var str in command.Value) - { - foreach (var lang in str.Value) - { - if (!sortedPerLanguage.ContainsKey(lang.Key)) - { - var commandDict = new Dictionary>(); - var strDict = new Dictionary - { - {str.Key, lang.Value} - }; - commandDict.Add(command.Key, strDict); - sortedPerLanguage.Add(lang.Key, commandDict); - } - if (!sortedPerLanguage[lang.Key].ContainsKey(command.Key)) - { - var strDict = new Dictionary - { - {str.Key, lang.Value} - }; - sortedPerLanguage[lang.Key].Add(command.Key, strDict); - } - if (!sortedPerLanguage[lang.Key][command.Key].ContainsKey(str.Key)) - { - sortedPerLanguage[lang.Key][command.Key].Add(str.Key, lang.Value); - } - } - } - } - _translations = sortedPerLanguage; - - // Find Languages - SupportedLanguages = new List(); - foreach (var lang in sortedPerLanguage) - { - SupportedLanguages.Add(lang.Key); - } - } - catch (Exception e) - { - _logger.Error(LogSource.Geekbot, "Failed to load Translations", e); - Environment.Exit(GeekbotExitCode.TranslationsFailed.GetHashCode()); - } - } - - public string GetServerLanguage(ulong guildId) - { - try - { - string lang; - try - { - lang = _serverLanguages[guildId]; - if (!string.IsNullOrEmpty(lang)) - { - return lang; - } - throw new Exception(); - } - catch - { - lang = _guildSettingsManager.GetSettings(guildId, false)?.Language ?? "EN"; - _serverLanguages[guildId] = lang; - return lang; - } - } - catch (Exception e) - { - _logger.Error(LogSource.Geekbot, "Could not get guild language", e); - return "EN"; - } - } - - public async Task GetString(ulong guildId, string command, string stringName) - { - var serverLang = GetServerLanguage(guildId); - return GetString(serverLang, command, stringName); - } - - public string GetString(string language, string command, string stringName) - { - var translation = _translations[language][command][stringName]; - if (!string.IsNullOrWhiteSpace(translation)) return translation; - translation = _translations[command][stringName]["EN"]; - if (string.IsNullOrWhiteSpace(translation)) - { - _logger.Warning(LogSource.Geekbot, $"No translation found for {command} - {stringName}"); - } - return translation; - } - - private async Task> GetDict(ICommandContext context) - { - try - { - var command = context.Message.Content.Split(' ').First().TrimStart('!').ToLower(); - var serverLanguage = GetServerLanguage(context.Guild?.Id ?? 0); - return _translations[serverLanguage][command]; - } - catch (Exception e) - { - _logger.Error(LogSource.Geekbot, "No translations for command found", e); - return new Dictionary(); - } - } - - public async Task GetGuildContext(ICommandContext context) - { - var dict = await GetDict(context); - var language = GetServerLanguage(context.Guild?.Id ?? 0); - return new TranslationGuildContext(this, language, dict); - } - - public async Task> GetDict(ICommandContext context, string command) - { - try - { - var serverLanguage = GetServerLanguage(context.Guild?.Id ?? 0); - return _translations[serverLanguage][command]; - } - catch (Exception e) - { - _logger.Error(LogSource.Geekbot, "No translations for command found", e); - return new Dictionary(); - } - } - - public async Task SetLanguage(ulong guildId, string language) - { - try - { - if (!SupportedLanguages.Contains(language)) return false; - var guild = _guildSettingsManager.GetSettings(guildId); - guild.Language = language; - await _guildSettingsManager.UpdateSettings(guild); - _serverLanguages[guildId] = language; - return true; - } - catch (Exception e) - { - _logger.Error(LogSource.Geekbot, "Error while changing language", e); - return false; - } - } - - public List SupportedLanguages { get; private set; } - } -} \ No newline at end of file diff --git a/src/Core/Localization/Translations.yml b/src/Core/Localization/Translations.yml deleted file mode 100644 index dc18c2b..0000000 --- a/src/Core/Localization/Translations.yml +++ /dev/null @@ -1,25 +0,0 @@ ---- -dateTime: - Days: - EN: "day|days" - CHDE: "tag|täg" - Hours: - EN: "hour|hours" - CHDE: "stund|stunde" - Minutes: - EN: "minute|minutes" - CHDE: "minute|minute" - Seconds: - EN: "second|seconds" - CHDE: "sekunde|sekunde" - And: - EN: "and" - CHDE: "und" -errorHandler: - SomethingWentWrong: - EN: "Something went wrong :confused:" - CHDE: "Öppis isch schief gange :confused:" -httpErrors: - 403: - EN: "Seems like i don't have enough permission to that :confused:" - CHDE: "Gseht danach us das ich nid gnueg recht han zum das mache :confused:" \ No newline at end of file diff --git a/tests/Core/Localization/TranslationGuildContext.test.cs b/tests/Core/Localization/TranslationGuildContext.test.cs deleted file mode 100644 index 4aaca16..0000000 --- a/tests/Core/Localization/TranslationGuildContext.test.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using System.Collections.Generic; -using Geekbot.Core.Localization; -using Moq; -using Xunit; - -namespace Tests.Core.Localization -{ - public class TranslationGuildContext_test - { - public class FormatDateTimeAsRemainingTestDto - { - public DateTimeOffset DateTime { get; set; } - public string Expected { get; set; } - } - - public static TestData FormatDateTimeAsRemainingData => - new TestData - { - { - "Wait for days", - new FormatDateTimeAsRemainingTestDto - { - DateTime = DateTimeOffset.Now.AddDays(5), - Expected = "4 days, 23 hours, 59 minutes and 59 seconds" - } - }, - { - "Wait for minutes", - new FormatDateTimeAsRemainingTestDto - { - DateTime = DateTimeOffset.Now.AddMinutes(5), - Expected = "4 minutes and 59 seconds" - } - }, - { - "Wait for seconds", - new FormatDateTimeAsRemainingTestDto - { - DateTime = DateTimeOffset.Now.AddSeconds(5), - Expected = "4 seconds" - } - } - }; - - [Theory, MemberData(nameof(FormatDateTimeAsRemainingData))] - public void FormatDateTimeAsRemaining(string testName, FormatDateTimeAsRemainingTestDto testData) - { - var translationHandlerMock = new Mock(MockBehavior.Loose); - translationHandlerMock - .Setup(thm => thm.GetString("EN", "dateTime", "Days")) - .Returns("day|days"); - translationHandlerMock - .Setup(thm => thm.GetString("EN", "dateTime", "Hours")) - .Returns("hour|hours"); - translationHandlerMock - .Setup(thm => thm.GetString("EN", "dateTime", "Minutes")) - .Returns("minute|minutes"); - translationHandlerMock - .Setup(thm => thm.GetString("EN", "dateTime", "Seconds")) - .Returns("second|seconds"); - translationHandlerMock - .Setup(thm => thm.GetString("EN", "dateTime", "And")) - .Returns("and"); - - var context = new TranslationGuildContext(translationHandlerMock.Object, "EN", new Dictionary()); - var result = context.FormatDateTimeAsRemaining(testData.DateTime); - Assert.Equal(result, testData.Expected); - } - } -} \ No newline at end of file diff --git a/tests/Core/Localization/Translations.test.cs b/tests/Core/Localization/Translations.test.cs deleted file mode 100644 index d8a0879..0000000 --- a/tests/Core/Localization/Translations.test.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; -using FluentAssertions; -using Xunit; -using YamlDotNet.Core; -using YamlDotNet.Serialization; - -namespace Tests.Core.Localization -{ - public class Translations_test - { - [Fact] - public void TranslationsYamlIsValid() - { - // Read the file - var translationFile = File.ReadAllText(Path.GetFullPath("./../../../../src/Core/Localization/Translations.yml")); - - // Deserialize - var input = new StringReader(translationFile); - var mergingParser = new MergingParser(new Parser(input)); - var deserializer = new DeserializerBuilder().Build(); - var rawTranslations = deserializer.Deserialize>>>(mergingParser); - - // These languages must be supported - var supportedLanguages = new List - { - "EN", - "CHDE" - }; - - // Iterate every single key to make sure it's populated - foreach (var command in rawTranslations) - { - foreach (var str in command.Value) - { - str.Value.Select(e => e.Key).ToList().Should().BeEquivalentTo(supportedLanguages, str.Key); - foreach (var lang in str.Value) - { - lang.Value.Should().NotBeNullOrEmpty($"{command.Key} / {str.Key} / {lang.Key}"); - } - } - } - } - } -} \ No newline at end of file From 60e36daaec4a587e48d716e307c9652d7b064723 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 14 Aug 2020 23:34:02 +0200 Subject: [PATCH 383/553] Translate !stats --- src/Bot/Bot.csproj | 9 ++ src/Bot/Commands/User/Stats.cs | 26 ++--- src/Bot/Localization/Stats.Designer.cs | 135 +++++++++++++++++++++++++ src/Bot/Localization/Stats.de-ch.resx | 38 +++++++ src/Bot/Localization/Stats.resx | 45 +++++++++ 5 files changed, 240 insertions(+), 13 deletions(-) create mode 100644 src/Bot/Localization/Stats.Designer.cs create mode 100644 src/Bot/Localization/Stats.de-ch.resx create mode 100644 src/Bot/Localization/Stats.resx diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index 2d3cd2f..49f0b16 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -81,6 +81,10 @@ ResXFileCodeGenerator Role.Designer.cs + + ResXFileCodeGenerator + Stats.Designer.cs + @@ -136,5 +140,10 @@ True Role.resx + + True + True + Stats.resx + diff --git a/src/Bot/Commands/User/Stats.cs b/src/Bot/Commands/User/Stats.cs index 70f6247..a2a54a2 100644 --- a/src/Bot/Commands/User/Stats.cs +++ b/src/Bot/Commands/User/Stats.cs @@ -3,24 +3,24 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.CommandPreconditions; using Geekbot.Core.Database; using Geekbot.Core.ErrorHandling; using Geekbot.Core.Extensions; +using Geekbot.Core.GuildSettingsManager; using Geekbot.Core.Levels; namespace Geekbot.Bot.Commands.User { - public class Stats : ModuleBase + public class Stats : GeekbotCommandBase { - private readonly IErrorHandler _errorHandler; private readonly ILevelCalc _levelCalc; private readonly DatabaseContext _database; - public Stats(DatabaseContext database, IErrorHandler errorHandler, ILevelCalc levelCalc) + public Stats(DatabaseContext database, IErrorHandler errorHandler, ILevelCalc levelCalc, IGuildSettingsManager guildSettingsManager) : base(errorHandler, guildSettingsManager) { _database = database; - _errorHandler = errorHandler; _levelCalc = levelCalc; } @@ -67,23 +67,23 @@ namespace Geekbot.Bot.Commands.User e.GuildId.Equals(Context.Guild.Id.AsLong()) && e.UserId.Equals(userInfo.Id.AsLong())); - eb.AddInlineField("Discordian Since", + eb.AddInlineField(Localization.Stats.OnDiscordSince, $"{createdAt.Day}.{createdAt.Month}.{createdAt.Year} ({age} days)") - .AddInlineField("Joined Server", + .AddInlineField(Localization.Stats.JoinedServer, $"{joinedAt.Day}.{joinedAt.Month}.{joinedAt.Year} ({joinedDayAgo} days)") - .AddInlineField("Karma", karma?.Karma ?? 0) - .AddInlineField("Level", level) - .AddInlineField("Messages Sent", messages) - .AddInlineField("Server Total", $"{percent}%"); + .AddInlineField(Localization.Stats.Karma, karma?.Karma ?? 0) + .AddInlineField(Localization.Stats.Level, level) + .AddInlineField(Localization.Stats.MessagesSent, messages) + .AddInlineField(Localization.Stats.ServerTotal, $"{percent}%"); - if (correctRolls != null) eb.AddInlineField("Guessed Rolls", correctRolls.Rolls); - if (cookies > 0) eb.AddInlineField("Cookies", cookies); + if (correctRolls != null) eb.AddInlineField(Localization.Stats.GuessedRolls, correctRolls.Rolls); + if (cookies > 0) eb.AddInlineField(Localization.Stats.Cookies, cookies); await ReplyAsync("", false, eb.Build()); } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } } diff --git a/src/Bot/Localization/Stats.Designer.cs b/src/Bot/Localization/Stats.Designer.cs new file mode 100644 index 0000000..d05f937 --- /dev/null +++ b/src/Bot/Localization/Stats.Designer.cs @@ -0,0 +1,135 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Geekbot.Bot.Localization { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Stats { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Stats() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Geekbot.Bot.Localization.Stats", typeof(Stats).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Cookies. + /// + internal static string Cookies { + get { + return ResourceManager.GetString("Cookies", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Guessed Rolls. + /// + internal static string GuessedRolls { + get { + return ResourceManager.GetString("GuessedRolls", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Joined Server. + /// + internal static string JoinedServer { + get { + return ResourceManager.GetString("JoinedServer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Karma. + /// + internal static string Karma { + get { + return ResourceManager.GetString("Karma", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Level. + /// + internal static string Level { + get { + return ResourceManager.GetString("Level", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Messages Sent. + /// + internal static string MessagesSent { + get { + return ResourceManager.GetString("MessagesSent", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to On Discord Since. + /// + internal static string OnDiscordSince { + get { + return ResourceManager.GetString("OnDiscordSince", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Server Total. + /// + internal static string ServerTotal { + get { + return ResourceManager.GetString("ServerTotal", resourceCulture); + } + } + } +} diff --git a/src/Bot/Localization/Stats.de-ch.resx b/src/Bot/Localization/Stats.de-ch.resx new file mode 100644 index 0000000..ab44a2e --- /dev/null +++ b/src/Bot/Localization/Stats.de-ch.resx @@ -0,0 +1,38 @@ + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Server Total + + + Uf Discord siit + + + Nachrichte versendet + + + Level + + + Karma + + + Server Bitrette + + + Grateni Rolls + + + Guetzli + + \ No newline at end of file diff --git a/src/Bot/Localization/Stats.resx b/src/Bot/Localization/Stats.resx new file mode 100644 index 0000000..3b8303a --- /dev/null +++ b/src/Bot/Localization/Stats.resx @@ -0,0 +1,45 @@ + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + On Discord Since + + + Joined Server + + + Karma + + + Level + + + Messages Sent + + + Server Total + + + Guessed Rolls + + + Cookies + + \ No newline at end of file From a78e92d230acbb90322bc572a603ce57f122d79d Mon Sep 17 00:00:00 2001 From: runebaas Date: Sat, 15 Aug 2020 00:40:59 +0200 Subject: [PATCH 384/553] Remove YamlDotNet --- src/Core/Core.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index fd44a95..7f278cf 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -28,7 +28,6 @@ - From 3c4a5c638b887833c6414170c0e2455ea365d838 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 26 Aug 2020 23:15:57 +0200 Subject: [PATCH 385/553] Upgrade Microsoft.Extensions.* to .NET5 preview 8 --- src/Core/Core.csproj | 6 +++--- tests/Tests.csproj | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 7f278cf..28729a7 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -18,9 +18,9 @@ - - - + + + diff --git a/tests/Tests.csproj b/tests/Tests.csproj index b8d1fc4..75a5f9c 100644 --- a/tests/Tests.csproj +++ b/tests/Tests.csproj @@ -12,7 +12,6 @@ - From 546b5450e7d10b325461bf7cfea1d750de5c2270 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 26 Aug 2020 23:28:03 +0200 Subject: [PATCH 386/553] Deal with MTG Gatherer downtime --- src/Bot/Commands/Integrations/MagicTheGathering.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Bot/Commands/Integrations/MagicTheGathering.cs b/src/Bot/Commands/Integrations/MagicTheGathering.cs index 66a87fe..b179d6e 100644 --- a/src/Bot/Commands/Integrations/MagicTheGathering.cs +++ b/src/Bot/Commands/Integrations/MagicTheGathering.cs @@ -28,7 +28,7 @@ namespace Geekbot.Bot.Commands.Integrations { try { - var message = await Context.Channel.SendMessageAsync($":mag: Looking up\"{cardName}\", please wait..."); + var message = await Context.Channel.SendMessageAsync($":mag: Looking up \"{cardName}\", please wait..."); var service = new CardService(); var result = service @@ -36,7 +36,15 @@ namespace Geekbot.Bot.Commands.Integrations // fewer cards less risk of deserialization problems, don't need more than one anyways... .Where(x => x.PageSize, 1); - var card = result.All().Value.FirstOrDefault(); + var cards = await result.AllAsync(); + if (!cards.IsSuccess) + { + await message.ModifyAsync(properties => properties.Content = $":warning: The Gatherer reacted in an unexpected way: {cards.Exception.Message}"); + return; + } + + var card = cards.Value.FirstOrDefault(); + if (card == null) { await message.ModifyAsync(properties => properties.Content = ":red_circle: I couldn't find a card with that name..."); From 8246c7a862128f7161aa798eac26fe6716db9ae8 Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 31 Aug 2020 18:46:00 +0200 Subject: [PATCH 387/553] When json logging is enabled, log it to the console without color or additional timestamp, also log the messages with the correct log level. Remove the logs folder. --- src/Bot/Logs/.keep | 0 src/Core/Logger/GeekbotLogger.cs | 49 ++++++++++---------------------- src/Core/Logger/LoggerFactory.cs | 44 ++++++++++++++-------------- 3 files changed, 36 insertions(+), 57 deletions(-) delete mode 100644 src/Bot/Logs/.keep diff --git a/src/Bot/Logs/.keep b/src/Bot/Logs/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/src/Core/Logger/GeekbotLogger.cs b/src/Core/Logger/GeekbotLogger.cs index 8d4a8eb..652faef 100644 --- a/src/Core/Logger/GeekbotLogger.cs +++ b/src/Core/Logger/GeekbotLogger.cs @@ -20,44 +20,25 @@ namespace Geekbot.Core.Logger }; Information(LogSource.Geekbot, "Using GeekbotLogger"); } - + public void Trace(LogSource source, string message, object extra = null) - { - _logger.Trace(CreateLogString("Trace", source, message, null, extra)); - } - + => _logger.Trace(CreateLogString("Trace", source, message, null, extra)); + public void Debug(LogSource source, string message, object extra = null) - { - if (_logAsJson) _logger.Info(CreateLogString("Debug", source, message, null, extra)); - else _logger.Debug(CreateLogString("Debug", source, message, null, extra)); - } - + => _logger.Debug(CreateLogString("Debug", source, message, null, extra)); + public void Information(LogSource source, string message, object extra = null) - { - _logger.Info(CreateLogString("Information", source, message, null, extra)); - } - + => _logger.Info(CreateLogString("Information", source, message, null, extra)); + public void Warning(LogSource source, string message, Exception stackTrace = null, object extra = null) - { - if (_logAsJson) _logger.Info(CreateLogString("Warning", source, message, stackTrace, extra)); - else _logger.Warn(CreateLogString("Warning", source, message, stackTrace, extra)); - } - + => _logger.Warn(CreateLogString("Warning", source, message, stackTrace, extra)); + public void Error(LogSource source, string message, Exception stackTrace, object extra = null) - { - if (_logAsJson) _logger.Info(CreateLogString("Error", source, message, stackTrace, extra)); - else _logger.Error(stackTrace, CreateLogString("Error", source, message, stackTrace, extra)); - } + => _logger.Error(stackTrace, CreateLogString("Error", source, message, stackTrace, extra)); - public NLog.Logger GetNLogger() - { - return _logger; - } + public NLog.Logger GetNLogger() => _logger; - public bool LogAsJson() - { - return _logAsJson; - } + public bool LogAsJson() => _logAsJson; private string CreateLogString(string type, LogSource source, string message, Exception stackTrace = null, object extra = null) { @@ -74,10 +55,10 @@ namespace Geekbot.Core.Logger }; return JsonConvert.SerializeObject(logObject, Formatting.None, _serializerSettings); } - + if (source != LogSource.Message) return $"[{source}] - {message}"; - - var m = (MessageDto) extra; + + var m = (MessageDto) extra; return $"[{source}] - [{m?.Guild.Name} - {m?.Channel.Name}] {m?.User.Name}: {m?.Message.Content}"; } } diff --git a/src/Core/Logger/LoggerFactory.cs b/src/Core/Logger/LoggerFactory.cs index bc129fc..bf3d926 100644 --- a/src/Core/Logger/LoggerFactory.cs +++ b/src/Core/Logger/LoggerFactory.cs @@ -12,12 +12,13 @@ namespace Geekbot.Core.Logger public static NLog.Logger CreateNLog(RunParameters runParameters) { var config = new LoggingConfiguration(); + var minLevel = runParameters.Verbose ? LogLevel.Trace : LogLevel.Info; if (!string.IsNullOrEmpty(runParameters.SumologicEndpoint)) { Console.WriteLine("Logging Geekbot Logs to Sumologic"); config.LoggingRules.Add( - new LoggingRule("*", LogLevel.Debug, LogLevel.Fatal, + new LoggingRule("*", minLevel, LogLevel.Fatal, new SumoLogicTarget() { Url = runParameters.SumologicEndpoint, @@ -27,11 +28,23 @@ namespace Geekbot.Core.Logger OptimizeBufferReuse = true, Name = "Geekbot" }) - ); + ); + } + else if (runParameters.LogJson) + { + config.LoggingRules.Add( + new LoggingRule("*", minLevel, LogLevel.Fatal, + new ConsoleTarget + { + Name = "Console", + Encoding = Encoding.UTF8, + Layout = "${message}" + } + ) + ); } else { - var minLevel = runParameters.Verbose ? LogLevel.Trace : LogLevel.Info; config.LoggingRules.Add( new LoggingRule("*", minLevel, LogLevel.Fatal, new ColoredConsoleTarget @@ -39,27 +52,12 @@ namespace Geekbot.Core.Logger Name = "Console", Encoding = Encoding.UTF8, Layout = "[${longdate} ${level:format=FirstCharacter}] ${message} ${exception:format=toString}" - }) - ); - - config.LoggingRules.Add( - new LoggingRule("*", minLevel, LogLevel.Fatal, - new FileTarget - { - Name = "File", - Layout = "[${longdate} ${level}] ${message}", - Encoding = Encoding.UTF8, - LineEnding = LineEndingMode.Default, - MaxArchiveFiles = 30, - ArchiveNumbering = ArchiveNumberingMode.Date, - ArchiveEvery = FileArchivePeriod.Day, - ArchiveFileName = "./Logs/Archive/{#####}.log", - FileName = "./Logs/Geekbot.log" - }) - ); + } + ) + ); } - - var loggerConfig = new LogFactory { Configuration = config }; + + var loggerConfig = new LogFactory {Configuration = config}; return loggerConfig.GetCurrentClassLogger(); } } From ce1153a0e2c843b91d5ed716a4ee460554449023 Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 31 Aug 2020 19:29:03 +0200 Subject: [PATCH 388/553] Upgrade Entity Framework to preview 8 --- src/Core/Core.csproj | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 28729a7..5ad67b3 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -13,11 +13,11 @@ - - - - - + + + + + @@ -25,7 +25,7 @@ - + From 81373b76144f9acf231c76e75c564d19a86d12c1 Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 31 Aug 2020 21:50:01 +0200 Subject: [PATCH 389/553] Make the ErrorHandler more resilient in case an exception is thrown during the error handling --- src/Core/ErrorHandling/ErrorHandler.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Core/ErrorHandling/ErrorHandler.cs b/src/Core/ErrorHandling/ErrorHandler.cs index 47ed22d..60d97e9 100644 --- a/src/Core/ErrorHandling/ErrorHandler.cs +++ b/src/Core/ErrorHandling/ErrorHandler.cs @@ -70,8 +70,14 @@ namespace Geekbot.Core.ErrorHandling } catch (Exception ex) { - await context.Channel.SendMessageAsync("Something went really really wrong here"); - _logger.Error(LogSource.Geekbot, "Errorception", ex); + try + { + await context.Channel.SendMessageAsync("Something went really really wrong here"); + } + finally + { + _logger.Error(LogSource.Geekbot, "Errorception", ex); + } } } From f71349b3780145ded0f685eaa5efe74ea34bac2a Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 8 Sep 2020 20:20:09 +0200 Subject: [PATCH 390/553] Reduce logging by making the user repo update message a debug log message --- src/Core/UserRepository/UserRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/UserRepository/UserRepository.cs b/src/Core/UserRepository/UserRepository.cs index 94d5df4..31fe2e2 100644 --- a/src/Core/UserRepository/UserRepository.cs +++ b/src/Core/UserRepository/UserRepository.cs @@ -48,7 +48,7 @@ namespace Geekbot.Core.UserRepository await _database.SaveChangesAsync(); - _logger.Information(LogSource.UserRepository, "Updated User", savedUser); + _logger.Debug(LogSource.UserRepository, "Updated User", savedUser); await Task.Delay(500); return true; } From d3c284102b5c674e5eb5def62fe08c6d250f126e Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 15 Sep 2020 00:14:27 +0200 Subject: [PATCH 391/553] Add an api endpoint to shutdown the bot from the browser --- src/Core/GeekbotExitCode.cs | 1 + src/Web/Controllers/KillController.cs | 64 +++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 src/Web/Controllers/KillController.cs diff --git a/src/Core/GeekbotExitCode.cs b/src/Core/GeekbotExitCode.cs index 5598f48..51006e1 100644 --- a/src/Core/GeekbotExitCode.cs +++ b/src/Core/GeekbotExitCode.cs @@ -8,6 +8,7 @@ // Geekbot Internals TranslationsFailed = 201, + KilledByApiCall = 210, // Dependent Services /* 301 not in use anymore (redis) */ diff --git a/src/Web/Controllers/KillController.cs b/src/Web/Controllers/KillController.cs new file mode 100644 index 0000000..2492b0d --- /dev/null +++ b/src/Web/Controllers/KillController.cs @@ -0,0 +1,64 @@ +using System; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Geekbot.Core; +using Geekbot.Core.GlobalSettings; +using Microsoft.AspNetCore.Mvc; + +namespace Geekbot.Web.Controllers +{ + /* + * Sometimes for some unknown reason command responses may become incredibly slow. + * Because i don't have time to debug it and may not always know directly when it happens, + * i want to give some trusted people the possibility to restart the bot. + * The kill code must be set manually in the db, it should end it `---1' + * + * ToDo: Actually fix the underlying issue + */ + public class KillController : Controller + { + private readonly IGlobalSettings _globalSettings; + private const string KillCodeDbKey = "KillCode"; + + public KillController(IGlobalSettings globalSettings) + { + _globalSettings = globalSettings; + } + + [HttpGet("/v1/kill/{providedKillCode}")] + public async Task KillTheBot([FromRoute] string providedKillCode) + { + var killCode = _globalSettings.GetKey(KillCodeDbKey); + if (providedKillCode != killCode) + { + return Unauthorized(new ApiError { Message = $"Go Away ({GetKillCodeInt(killCode)})" }); + } + + await UpdateKillCode(killCode); +#pragma warning disable CS4014 + Kill(); +#pragma warning restore CS4014 + return Ok(); + } + + private int GetKillCodeInt(string code) + { + var group = Regex.Match(code, @".+(\-\-\-(?\d+))").Groups["int"]; + return group.Success ? int.Parse(group.Value) : 0; + } + + private async Task UpdateKillCode(string oldCode) + { + var newKillCodeInt = new Random().Next(1, 100); + var newCode = oldCode.Replace($"---{GetKillCodeInt(oldCode)}", $"---{newKillCodeInt}"); + await _globalSettings.SetKey(KillCodeDbKey, newCode); + } + + private async Task Kill() + { + // wait a second so the http response can still be sent successfully + await Task.Delay(1000); + Environment.Exit(GeekbotExitCode.KilledByApiCall.GetHashCode()); + } + } +} \ No newline at end of file From cbe2aa23c955d01dcf31455a45cf448f922d95dc Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 15 Sep 2020 23:25:40 +0200 Subject: [PATCH 392/553] Make sure that examples in the !urban command are not longer than 1024 characters. --- .../Integrations/UbranDictionary/UrbanDictionary.cs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/Bot/Commands/Integrations/UbranDictionary/UrbanDictionary.cs b/src/Bot/Commands/Integrations/UbranDictionary/UrbanDictionary.cs index bc1f478..72bc8cd 100644 --- a/src/Bot/Commands/Integrations/UbranDictionary/UrbanDictionary.cs +++ b/src/Bot/Commands/Integrations/UbranDictionary/UrbanDictionary.cs @@ -33,12 +33,6 @@ namespace Geekbot.Bot.Commands.Integrations.UbranDictionary var definition = definitions.List.First(e => !string.IsNullOrWhiteSpace(e.Example)); - var description = definition.Definition; - if (description.Length > 1801) - { - description = description.Substring(0, 1800) + " [...]"; - } - var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder { @@ -46,8 +40,11 @@ namespace Geekbot.Bot.Commands.Integrations.UbranDictionary Url = definition.Permalink }); eb.WithColor(new Color(239, 255, 0)); - if (!string.IsNullOrEmpty(definition.Definition)) eb.Description = description; - if (!string.IsNullOrEmpty(definition.Example)) eb.AddField("Example", definition.Example ?? "(no example given...)"); + + static string ShortenIfToLong(string str, int maxLength) => str.Length > maxLength ? $"{str.Substring(0, maxLength - 5)}[...]" : str; + + if (!string.IsNullOrEmpty(definition.Definition)) eb.Description = ShortenIfToLong(definition.Definition, 1800); + if (!string.IsNullOrEmpty(definition.Example)) eb.AddField("Example", ShortenIfToLong(definition.Example, 1024)); if (!string.IsNullOrEmpty(definition.ThumbsUp)) eb.AddInlineField("Upvotes", definition.ThumbsUp); if (!string.IsNullOrEmpty(definition.ThumbsDown)) eb.AddInlineField("Downvotes", definition.ThumbsDown); if (definitions.Tags?.Length > 0) eb.AddField("Tags", string.Join(", ", definitions.Tags)); From 482a74839ac6edb07bbcd784df46e2f58755ace8 Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 22 Sep 2020 12:24:12 +0200 Subject: [PATCH 393/553] Fix some swiss german grammar (never heard of it either) in the !quote command --- src/Bot/Localization/Karma.de-ch.resx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Bot/Localization/Karma.de-ch.resx b/src/Bot/Localization/Karma.de-ch.resx index 294c105..5605f8b 100644 --- a/src/Bot/Localization/Karma.de-ch.resx +++ b/src/Bot/Localization/Karma.de-ch.resx @@ -30,7 +30,7 @@ Jetzt - Sorry {0}, aber du chasch dr din eigete karma nid weg neh + Sorry {0}, aber du chasch dis eigete karma nid senke Karma gsenkt From b743539c749dd19fe74fa6d6633cd2f7a3be9006 Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 22 Sep 2020 13:06:57 +0200 Subject: [PATCH 394/553] Upgrade to .net5 rc1 and fix all breaking changes in the web api since .net core 2.2 --- .gitlab-ci.yml | 2 +- Dockerfile | 2 +- src/Bot/Bot.csproj | 1 - src/Core/Core.csproj | 18 +++++++++--------- src/Web/Web.csproj | 11 +---------- src/Web/WebApiStartup.cs | 22 +++++++++++++++------- 6 files changed, 27 insertions(+), 29 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8efd1d1..c4d8b15 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,7 +10,7 @@ variables: Build: stage: build - image: mcr.microsoft.com/dotnet/core/sdk:5.0-focal + image: mcr.microsoft.com/dotnet/sdk:5.0 artifacts: expire_in: 1h paths: diff --git a/Dockerfile b/Dockerfile index 479dd40..245e06b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/core/aspnet:5.0-focal +FROM mcr.microsoft.com/dotnet/aspnet:5.0 COPY ./app /app/ diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index 49f0b16..60f6473 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -22,7 +22,6 @@ - diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 5ad67b3..7b273fd 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -13,19 +13,19 @@ - - - - - - - - + + + + + + + + - + diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index 429165b..5080a3d 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -1,4 +1,4 @@ - + net5.0 @@ -10,15 +10,6 @@ NU1701 - - - - - - - - - diff --git a/src/Web/WebApiStartup.cs b/src/Web/WebApiStartup.cs index 9aeedf9..0c18886 100644 --- a/src/Web/WebApiStartup.cs +++ b/src/Web/WebApiStartup.cs @@ -18,6 +18,9 @@ namespace Geekbot.Web { public static class WebApiStartup { + // Using the "Microsoft.NET.Sdk.Web" SDK requires a static main function... + public static void Main() {} + public static void StartWebApi(IGeekbotLogger logger, RunParameters runParameters, CommandService commandService, DatabaseContext databaseContext, DiscordSocketClient client, IGlobalSettings globalSettings, IHighscoreManager highscoreManager) { @@ -28,22 +31,27 @@ namespace Geekbot.Web }) .ConfigureServices(services => { - services.AddMvc(); - services.AddSingleton(commandService); - services.AddSingleton(databaseContext); - services.AddSingleton(client); - services.AddSingleton(globalSettings); - services.AddSingleton(highscoreManager); + services.AddControllers(); services.AddCors(options => { options.AddPolicy("AllowSpecificOrigin", builder => builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()); }); + + services.AddSingleton(commandService); + services.AddSingleton(databaseContext); + services.AddSingleton(client); + services.AddSingleton(globalSettings); + services.AddSingleton(highscoreManager); }) .Configure(app => { - app.UseMvc(); + app.UseRouting(); app.UseCors(builder => builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod().Build()); + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); }) .ConfigureLogging(logging => { From ae9b9caeb90451c860e5be7fe19e51f81267c9f8 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 23 Sep 2020 16:05:43 +0200 Subject: [PATCH 395/553] Add random.org for random number generation. --- src/Bot/Commands/Utils/Quote/Quote.cs | 2 +- src/Bot/Program.cs | 2 +- src/Core/Core.csproj | 1 + .../RandomNumberGenerator.cs | 57 +++++++++++++++++-- tests/Core/DiceParser/DiceParser.test.cs | 6 +- tests/Core/DiceParser/SingleDie.test.cs | 6 +- 6 files changed, 62 insertions(+), 12 deletions(-) diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index a7d3ff1..6f4cd1c 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -46,7 +46,7 @@ namespace Geekbot.Bot.Commands.Utils.Quote return; } - var random = _randomNumberGenerator.Next(0, s.Count); + var random = _randomNumberGenerator.Next(0, s.Count - 1); var quote = s[random]; var embed = QuoteBuilder(quote); diff --git a/src/Bot/Program.cs b/src/Bot/Program.cs index 5a4b456..5994f8c 100644 --- a/src/Bot/Program.cs +++ b/src/Bot/Program.cs @@ -164,7 +164,7 @@ namespace Geekbot.Bot var emojiConverter = new EmojiConverter(); var mtgManaConverter = new MtgManaConverter(); var wikipediaClient = new WikipediaClient(); - var randomNumberGenerator = new RandomNumberGenerator(); + var randomNumberGenerator = new RandomNumberGenerator(_globalSettings); var mediaProvider = new MediaProvider(_logger, randomNumberGenerator); var kvMemoryStore = new KvInInMemoryStore(); var errorHandler = new ErrorHandler(_logger, _runParameters, () => Localization.Internal.SomethingWentWrong); diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 7b273fd..0b3ff44 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -11,6 +11,7 @@ + diff --git a/src/Core/RandomNumberGenerator/RandomNumberGenerator.cs b/src/Core/RandomNumberGenerator/RandomNumberGenerator.cs index 63381b5..db990a7 100644 --- a/src/Core/RandomNumberGenerator/RandomNumberGenerator.cs +++ b/src/Core/RandomNumberGenerator/RandomNumberGenerator.cs @@ -1,25 +1,69 @@ using System; using System.Security.Cryptography; +using Anemonis.RandomOrg; +using Geekbot.Core.GlobalSettings; namespace Geekbot.Core.RandomNumberGenerator { public class RandomNumberGenerator : IRandomNumberGenerator { - readonly RNGCryptoServiceProvider csp; + private readonly RNGCryptoServiceProvider csp; + private readonly bool _canUseRandomOrg; + private readonly RandomOrgClient _randomOrgClient; - public RandomNumberGenerator() + public RandomNumberGenerator(IGlobalSettings globalSettings) { csp = new RNGCryptoServiceProvider(); + + var randomOrgApiKey = globalSettings.GetKey("RandomOrgApiKey"); + if (!string.IsNullOrEmpty(randomOrgApiKey)) + { + _canUseRandomOrg = true; + _randomOrgClient = new RandomOrgClient(randomOrgApiKey); + } } - public int Next(int minValue, int maxExclusiveValue) + public int Next(int minValue, int maxInclusiveValue) { - if (minValue >= maxExclusiveValue) + if (minValue == maxInclusiveValue) + { + return maxInclusiveValue; + } + + if (minValue >= maxInclusiveValue) { throw new ArgumentOutOfRangeException("minValue must be lower than maxExclusiveValue"); } + + if (_canUseRandomOrg) + { + try + { + return GetFromRandomOrg(minValue, maxInclusiveValue); + } + catch + { + // ignore + } + } - var diff = (long)maxExclusiveValue - minValue; + return GetFromCrypto(minValue, maxInclusiveValue); + } + + private int GetFromRandomOrg(int minValue, int maxInclusiveValue) + { + return _randomOrgClient + .GenerateIntegersAsync(1, minValue, maxInclusiveValue, false) + .Result + .Random + .Data[0]; + } + + private int GetFromCrypto(int minValue, int maxInclusiveValue) + { + var maxExclusiveValue = maxInclusiveValue + 1; + + var diff = (long) maxExclusiveValue - minValue; var upperBound = uint.MaxValue / diff * diff; uint ui; @@ -27,7 +71,8 @@ namespace Geekbot.Core.RandomNumberGenerator { ui = GetRandomUInt(); } while (ui >= upperBound); - return (int)(minValue + (ui % diff)); + + return (int) (minValue + (ui % diff)); } private uint GetRandomUInt() diff --git a/tests/Core/DiceParser/DiceParser.test.cs b/tests/Core/DiceParser/DiceParser.test.cs index 8a9163a..ed9425f 100644 --- a/tests/Core/DiceParser/DiceParser.test.cs +++ b/tests/Core/DiceParser/DiceParser.test.cs @@ -1,15 +1,17 @@ using System.Collections.Generic; using System.Text.Json; using Geekbot.Core.DiceParser; +using Geekbot.Core.GlobalSettings; using Geekbot.Core.RandomNumberGenerator; +using Moq; using Xunit; namespace Tests.Core.DiceParser { public class DiceParserTest { - private static readonly RandomNumberGenerator _randomNumberGenerator = new RandomNumberGenerator(); - + private static readonly RandomNumberGenerator _randomNumberGenerator = new RandomNumberGenerator(new Mock().Object); + public struct DiceParserTestDto { public string Input { get; set; } diff --git a/tests/Core/DiceParser/SingleDie.test.cs b/tests/Core/DiceParser/SingleDie.test.cs index 813a33b..5173902 100644 --- a/tests/Core/DiceParser/SingleDie.test.cs +++ b/tests/Core/DiceParser/SingleDie.test.cs @@ -1,5 +1,7 @@ using Geekbot.Core.DiceParser; +using Geekbot.Core.GlobalSettings; using Geekbot.Core.RandomNumberGenerator; +using Moq; using Xunit; namespace Tests.Core.DiceParser @@ -43,7 +45,7 @@ namespace Tests.Core.DiceParser [Theory, MemberData(nameof(SingleDieNameTestData))] public void SingleDieNameTestFunc(string testName, SingleDieNameTestDto testData) { - var die = new SingleDie(new RandomNumberGenerator()) {AdvantageType = testData.AdvantageType}; + var die = new SingleDie(new RandomNumberGenerator(new Mock().Object)) {AdvantageType = testData.AdvantageType}; Assert.Equal(die.DiceName, testData.Expected); } @@ -106,7 +108,7 @@ namespace Tests.Core.DiceParser [Theory, MemberData(nameof(SingleDieValidationTestData))] public void SingleDieValidationTestFunc(string testName, SingleDieValidationTestDto testData) { - var die = new SingleDie(new RandomNumberGenerator()) + var die = new SingleDie(new RandomNumberGenerator(new Mock().Object)) { Amount = testData.Amount, Sides = testData.Sides From 58bd4d17d0ecaa09ca0d64219c601cae021a6163 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 23 Sep 2020 16:28:50 +0200 Subject: [PATCH 396/553] Optimize the !quote database query --- src/Bot/Commands/Utils/Quote/Quote.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index 6f4cd1c..db6b1ac 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -33,23 +33,23 @@ namespace Geekbot.Bot.Commands.Utils.Quote } [Command] - [Summary("Return a random quoute from the database")] + [Summary("Return a random quote from the database")] public async Task GetRandomQuote() { try { - var s = _database.Quotes.Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())).ToList(); + var totalQuotes = await _database.Quotes.CountAsync(e => e.GuildId.Equals(Context.Guild.Id.AsLong())); - if (!s.Any()) + if (totalQuotes == 0) { await ReplyAsync(Localization.Quote.NoQuotesFound); return; } - var random = _randomNumberGenerator.Next(0, s.Count - 1); - var quote = s[random]; - - var embed = QuoteBuilder(quote); + var random = _randomNumberGenerator.Next(0, totalQuotes - 1); + var quote = _database.Quotes.Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())).Skip(random).Take(1); + + var embed = QuoteBuilder(quote.FirstOrDefault()); await ReplyAsync("", false, embed.Build()); } catch (Exception e) From 216188f61fc05bdd255980f076d44f2904539d51 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 23 Sep 2020 16:46:13 +0200 Subject: [PATCH 397/553] Add a deprecation warning for quoting by message ID --- src/Bot/Commands/Utils/Quote/Quote.cs | 15 +++++++++------ src/Bot/Localization/Quote.Designer.cs | 9 +++++++++ src/Bot/Localization/Quote.de-ch.resx | 3 +++ src/Bot/Localization/Quote.resx | 3 +++ 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index db6b1ac..0b197cd 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; @@ -211,10 +212,9 @@ namespace Geekbot.Bot.Commands.Utils.Quote { try { - // var transContext = await _translationHandler.GetGuildContext(Context); var message = await Context.Channel.GetMessageAsync(messageId); - await ProcessQuote(message, saveToDb); + await ProcessQuote(message, saveToDb, true); } catch (Exception e) { @@ -226,8 +226,6 @@ namespace Geekbot.Bot.Commands.Utils.Quote { try { - // var transContext = await _translationHandler.GetGuildContext(Context); - if (!MessageLink.IsValid(messageLink)) { await ReplyAsync(Localization.Quote.NotAValidMessageLink); @@ -255,7 +253,7 @@ namespace Geekbot.Bot.Commands.Utils.Quote } } - private async Task ProcessQuote(IMessage message, bool saveToDb) + private async Task ProcessQuote(IMessage message, bool saveToDb, bool showMessageIdWarning = false) { if (message.Author.Id == Context.Message.Author.Id && saveToDb && !_isDev) { @@ -277,7 +275,12 @@ namespace Geekbot.Bot.Commands.Utils.Quote } var embed = QuoteBuilder(quote); - await ReplyAsync(saveToDb ? Localization.Quote.QuoteAdded : string.Empty, false, embed.Build()); + + var sb = new StringBuilder(); + if (saveToDb) sb.AppendLine(Localization.Quote.QuoteAdded); + if (showMessageIdWarning) sb.AppendLine(Localization.Quote.MessageIdDeprecation); + + await ReplyAsync(sb.ToString(), false, embed.Build()); } private EmbedBuilder QuoteBuilder(QuoteModel quote) diff --git a/src/Bot/Localization/Quote.Designer.cs b/src/Bot/Localization/Quote.Designer.cs index 342c181..d0926ae 100644 --- a/src/Bot/Localization/Quote.Designer.cs +++ b/src/Bot/Localization/Quote.Designer.cs @@ -78,6 +78,15 @@ namespace Geekbot.Bot.Localization { } } + /// + /// Looks up a localized string similar to :warning: Creating quotes by message ID is deprecated in favour of message links and will be removed on 1 December 2020. + /// + internal static string MessageIdDeprecation { + get { + return ResourceManager.GetString("MessageIdDeprecation", resourceCulture); + } + } + /// /// Looks up a localized string similar to Most quoted person. /// diff --git a/src/Bot/Localization/Quote.de-ch.resx b/src/Bot/Localization/Quote.de-ch.resx index 99fd959..c7e3b8b 100644 --- a/src/Bot/Localization/Quote.de-ch.resx +++ b/src/Bot/Localization/Quote.de-ch.resx @@ -44,4 +44,7 @@ Du chasch numme nachrichte vom gliche server quote + + :warning: Es mache vo quotes mit message-IDs isch zgunste vo message-links veraltet und wird am 1. dezember 2020 entfernt + \ No newline at end of file diff --git a/src/Bot/Localization/Quote.resx b/src/Bot/Localization/Quote.resx index b51d79c..215f0ea 100644 --- a/src/Bot/Localization/Quote.resx +++ b/src/Bot/Localization/Quote.resx @@ -51,4 +51,7 @@ You can only quote messages from the same server + + :warning: Creating quotes by message ID is deprecated in favour of message links and will be removed on 1 December 2020 + \ No newline at end of file From 7ef0b6a3195a379f06ca7f33056131dbd192aea5 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 24 Sep 2020 12:21:21 +0200 Subject: [PATCH 398/553] Swap the my anime list wrapper for the !anime and !manga commands --- src/Bot/Bot.csproj | 2 +- src/Bot/Commands/Integrations/Mal.cs | 116 +++++++++++---------------- src/Bot/Program.cs | 3 - src/Core/Core.csproj | 1 - src/Core/MalClient/IMalClient.cs | 12 --- src/Core/MalClient/MalClient.cs | 63 --------------- 6 files changed, 47 insertions(+), 150 deletions(-) delete mode 100644 src/Core/MalClient/IMalClient.cs delete mode 100644 src/Core/MalClient/MalClient.cs diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index 60f6473..4cd5b39 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -24,8 +24,8 @@ + - diff --git a/src/Bot/Commands/Integrations/Mal.cs b/src/Bot/Commands/Integrations/Mal.cs index ae30493..ab8c021 100644 --- a/src/Bot/Commands/Integrations/Mal.cs +++ b/src/Bot/Commands/Integrations/Mal.cs @@ -1,23 +1,23 @@ using System; +using System.Linq; using System.Threading.Tasks; using System.Web; -using System.Xml; using Discord; using Discord.Commands; using Geekbot.Core.ErrorHandling; using Geekbot.Core.Extensions; -using Geekbot.Core.MalClient; +using JikanDotNet; namespace Geekbot.Bot.Commands.Integrations { public class Mal : ModuleBase { private readonly IErrorHandler _errorHandler; - private readonly IMalClient _malClient; + private readonly IJikan _client; - public Mal(IMalClient malClient, IErrorHandler errorHandler) + public Mal(IErrorHandler errorHandler) { - _malClient = malClient; + _client = new Jikan(); _errorHandler = errorHandler; } @@ -27,46 +27,34 @@ namespace Geekbot.Bot.Commands.Integrations { try { - if (_malClient.IsLoggedIn()) + var results = await _client.SearchAnime(animeName); + var anime = results.Results.FirstOrDefault(); + if (anime != null) { - var anime = await _malClient.GetAnime(animeName); - if (anime != null) - { - var eb = new EmbedBuilder(); + var eb = new EmbedBuilder(); - var description = HttpUtility.HtmlDecode(anime.Synopsis) - .Replace("
", "") - .Replace("[i]", "*") - .Replace("[/i]", "*"); + var description = HttpUtility.HtmlDecode(anime.Description) + .Replace("
", "") + .Replace("[i]", "*") + .Replace("[/i]", "*"); - eb.Title = anime.Title; - eb.Description = description; - eb.ImageUrl = anime.Image; - eb.AddInlineField("Premiered", $"{anime.StartDate}"); - eb.AddInlineField("Ended", anime.EndDate == "0000-00-00" ? "???" : anime.EndDate); - eb.AddInlineField("Status", anime.Status); - eb.AddInlineField("Episodes", anime.Episodes); - eb.AddInlineField("MAL Score", anime.Score); - eb.AddInlineField("Type", anime.Type); - eb.AddField("MAL Link", $"https://myanimelist.net/anime/{anime.Id}"); + eb.Title = anime.Title; + eb.Description = description; + eb.ImageUrl = anime.ImageURL; + eb.AddInlineField("Premiered", $"{anime.StartDate.Value.ToShortDateString()}"); + eb.AddInlineField("Ended", anime.Airing ? "Present" : anime.EndDate.Value.ToShortDateString()); + eb.AddInlineField("Episodes", anime.Episodes); + eb.AddInlineField("MAL Score", anime.Score); + eb.AddInlineField("Type", anime.Type); + eb.AddField("MAL Link", $"https://myanimelist.net/anime/{anime.MalId}"); - await ReplyAsync("", false, eb.Build()); - } - else - { - await ReplyAsync("No anime found with that name..."); - } + await ReplyAsync("", false, eb.Build()); } else { - await ReplyAsync( - "Unfortunally i'm not connected to MyAnimeList.net, please tell my senpai to connect me"); + await ReplyAsync("No anime found with that name..."); } } - catch (XmlException e) - { - await _errorHandler.HandleCommandException(e, Context, "The MyAnimeList.net API refused to answer"); - } catch (Exception e) { await _errorHandler.HandleCommandException(e, Context); @@ -79,46 +67,34 @@ namespace Geekbot.Bot.Commands.Integrations { try { - if (_malClient.IsLoggedIn()) + var results = await _client.SearchManga(mangaName); + var manga = results.Results.FirstOrDefault(); + if (manga != null) { - var manga = await _malClient.GetManga(mangaName); - if (manga != null) - { - var eb = new EmbedBuilder(); - - var description = HttpUtility.HtmlDecode(manga.Synopsis) - .Replace("
", "") - .Replace("[i]", "*") - .Replace("[/i]", "*"); - - eb.Title = manga.Title; - eb.Description = description; - eb.ImageUrl = manga.Image; - eb.AddInlineField("Premiered", $"{manga.StartDate}"); - eb.AddInlineField("Ended", manga.EndDate == "0000-00-00" ? "???" : manga.EndDate); - eb.AddInlineField("Status", manga.Status); - eb.AddInlineField("Volumes", manga.Volumes); - eb.AddInlineField("Chapters", manga.Chapters); - eb.AddInlineField("MAL Score", manga.Score); - eb.AddField("MAL Link", $"https://myanimelist.net/manga/{manga.Id}"); - - await ReplyAsync("", false, eb.Build()); - } - else - { - await ReplyAsync("No manga found with that name..."); - } + var eb = new EmbedBuilder(); + + var description = HttpUtility.HtmlDecode(manga.Description) + .Replace("
", "") + .Replace("[i]", "*") + .Replace("[/i]", "*"); + + eb.Title = manga.Title; + eb.Description = description; + eb.ImageUrl = manga.ImageURL; + eb.AddInlineField("Premiered", $"{manga.StartDate.Value.ToShortDateString()}"); + eb.AddInlineField("Ended", manga.Publishing ? "Present" : manga.EndDate.Value.ToShortDateString()); + eb.AddInlineField("Volumes", manga.Volumes); + eb.AddInlineField("Chapters", manga.Chapters); + eb.AddInlineField("MAL Score", manga.Score); + eb.AddField("MAL Link", $"https://myanimelist.net/manga/{manga.MalId}"); + + await ReplyAsync("", false, eb.Build()); } else { - await ReplyAsync( - "Unfortunally i'm not connected to MyAnimeList.net, please tell my senpai to connect me"); + await ReplyAsync("No manga found with that name..."); } } - catch (XmlException e) - { - await _errorHandler.HandleCommandException(e, Context, "The MyAnimeList.net API refused to answer"); - } catch (Exception e) { await _errorHandler.HandleCommandException(e, Context); diff --git a/src/Bot/Program.cs b/src/Bot/Program.cs index 5994f8c..dee6ec3 100644 --- a/src/Bot/Program.cs +++ b/src/Bot/Program.cs @@ -18,7 +18,6 @@ using Geekbot.Core.Highscores; using Geekbot.Core.KvInMemoryStore; using Geekbot.Core.Levels; using Geekbot.Core.Logger; -using Geekbot.Core.MalClient; using Geekbot.Core.Media; using Geekbot.Core.RandomNumberGenerator; using Geekbot.Core.ReactionListener; @@ -159,7 +158,6 @@ namespace Geekbot.Bot _reactionListener = new ReactionListener(_databaseInitializer.Initialize()); _guildSettingsManager = new GuildSettingsManager(_databaseInitializer.Initialize()); var fortunes = new FortunesProvider(_logger); - var malClient = new MalClient(_globalSettings, _logger); var levelCalc = new LevelCalc(); var emojiConverter = new EmojiConverter(); var mtgManaConverter = new MtgManaConverter(); @@ -176,7 +174,6 @@ namespace Geekbot.Bot services.AddSingleton(emojiConverter); services.AddSingleton(fortunes); services.AddSingleton(mediaProvider); - services.AddSingleton(malClient); services.AddSingleton(mtgManaConverter); services.AddSingleton(wikipediaClient); services.AddSingleton(randomNumberGenerator); diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 0b3ff44..780d0e2 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -22,7 +22,6 @@ - diff --git a/src/Core/MalClient/IMalClient.cs b/src/Core/MalClient/IMalClient.cs deleted file mode 100644 index 70851c1..0000000 --- a/src/Core/MalClient/IMalClient.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Threading.Tasks; -using MyAnimeListSharp.Core; - -namespace Geekbot.Core.MalClient -{ - public interface IMalClient - { - bool IsLoggedIn(); - Task GetAnime(string query); - Task GetManga(string query); - } -} \ No newline at end of file diff --git a/src/Core/MalClient/MalClient.cs b/src/Core/MalClient/MalClient.cs deleted file mode 100644 index 3f5f165..0000000 --- a/src/Core/MalClient/MalClient.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System.Threading.Tasks; -using Geekbot.Core.GlobalSettings; -using Geekbot.Core.Logger; -using MyAnimeListSharp.Auth; -using MyAnimeListSharp.Core; -using MyAnimeListSharp.Facade.Async; - -namespace Geekbot.Core.MalClient -{ - public class MalClient : IMalClient - { - private readonly IGlobalSettings _globalSettings; - private readonly IGeekbotLogger _logger; - private ICredentialContext _credentials; - private AnimeSearchMethodsAsync _animeSearch; - private MangaSearchMethodsAsync _mangaSearch; - - public MalClient(IGlobalSettings globalSettings, IGeekbotLogger logger) - { - _globalSettings = globalSettings; - _logger = logger; - ReloadClient(); - } - - private bool ReloadClient() - { - var malCredentials = _globalSettings.GetKey("MalCredentials"); - if (!string.IsNullOrEmpty(malCredentials)) - { - var credSplit = malCredentials.Split('|'); - _credentials = new CredentialContext() - { - UserName = credSplit[0], - Password = credSplit[1] - }; - _animeSearch = new AnimeSearchMethodsAsync(_credentials); - _mangaSearch = new MangaSearchMethodsAsync(_credentials); - _logger.Debug(LogSource.Geekbot, "Logged in to MAL"); - return true; - } - _logger.Debug(LogSource.Geekbot, "No MAL Credentials Set!"); - return false; - - } - - public bool IsLoggedIn() - { - return _credentials != null; - } - - public async Task GetAnime(string query) - { - var response = await _animeSearch.SearchDeserializedAsync(query); - return response.Entries.Count == 0 ? null : response.Entries[0]; - } - - public async Task GetManga(string query) - { - var response = await _mangaSearch.SearchDeserializedAsync(query); - return response.Entries.Count == 0 ? null : response.Entries[0]; - } - } -} \ No newline at end of file From ed7748833aa499e8a19778f81a575e8a052c41f0 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 24 Sep 2020 12:49:55 +0200 Subject: [PATCH 399/553] Format dates in the !anime and !manga commands with the correct culture info --- src/Bot/Commands/Integrations/Mal.cs | 31 +++++++++++++++++++--------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/Bot/Commands/Integrations/Mal.cs b/src/Bot/Commands/Integrations/Mal.cs index ab8c021..f44d04e 100644 --- a/src/Bot/Commands/Integrations/Mal.cs +++ b/src/Bot/Commands/Integrations/Mal.cs @@ -1,24 +1,25 @@ using System; using System.Linq; +using System.Threading; using System.Threading.Tasks; using System.Web; using Discord; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.ErrorHandling; using Geekbot.Core.Extensions; +using Geekbot.Core.GuildSettingsManager; using JikanDotNet; namespace Geekbot.Bot.Commands.Integrations { - public class Mal : ModuleBase + public class Mal : GeekbotCommandBase { - private readonly IErrorHandler _errorHandler; private readonly IJikan _client; - public Mal(IErrorHandler errorHandler) + public Mal(IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager) : base(errorHandler, guildSettingsManager) { _client = new Jikan(); - _errorHandler = errorHandler; } [Command("anime", RunMode = RunMode.Async)] @@ -41,8 +42,8 @@ namespace Geekbot.Bot.Commands.Integrations eb.Title = anime.Title; eb.Description = description; eb.ImageUrl = anime.ImageURL; - eb.AddInlineField("Premiered", $"{anime.StartDate.Value.ToShortDateString()}"); - eb.AddInlineField("Ended", anime.Airing ? "Present" : anime.EndDate.Value.ToShortDateString()); + eb.AddInlineField("Premiered", FormatDate(anime.StartDate)); + eb.AddInlineField("Ended", anime.Airing ? "Present" : FormatDate(anime.EndDate)); eb.AddInlineField("Episodes", anime.Episodes); eb.AddInlineField("MAL Score", anime.Score); eb.AddInlineField("Type", anime.Type); @@ -57,7 +58,7 @@ namespace Geekbot.Bot.Commands.Integrations } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } @@ -81,8 +82,8 @@ namespace Geekbot.Bot.Commands.Integrations eb.Title = manga.Title; eb.Description = description; eb.ImageUrl = manga.ImageURL; - eb.AddInlineField("Premiered", $"{manga.StartDate.Value.ToShortDateString()}"); - eb.AddInlineField("Ended", manga.Publishing ? "Present" : manga.EndDate.Value.ToShortDateString()); + eb.AddInlineField("Premiered", FormatDate(manga.StartDate)); + eb.AddInlineField("Ended", manga.Publishing ? "Present" : FormatDate(manga.EndDate)); eb.AddInlineField("Volumes", manga.Volumes); eb.AddInlineField("Chapters", manga.Chapters); eb.AddInlineField("MAL Score", manga.Score); @@ -97,8 +98,18 @@ namespace Geekbot.Bot.Commands.Integrations } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } + + private string FormatDate(DateTime? dateTime) + { + if (!dateTime.HasValue) + { + return DateTime.MinValue.ToString("d", Thread.CurrentThread.CurrentUICulture); + } + + return dateTime.Value.ToString("d", Thread.CurrentThread.CurrentUICulture); + } } } \ No newline at end of file From 41795aa13f0a806caf8cb7acb6e29d7653fb1d51 Mon Sep 17 00:00:00 2001 From: runebaas Date: Thu, 24 Sep 2020 18:29:21 +0200 Subject: [PATCH 400/553] Small wording tweaks to the !anime and !manga commands. They also no long need their description html decoded. --- src/Bot/Commands/Integrations/Mal.cs | 63 +++++++++++++--------------- 1 file changed, 28 insertions(+), 35 deletions(-) diff --git a/src/Bot/Commands/Integrations/Mal.cs b/src/Bot/Commands/Integrations/Mal.cs index f44d04e..ffc8dd7 100644 --- a/src/Bot/Commands/Integrations/Mal.cs +++ b/src/Bot/Commands/Integrations/Mal.cs @@ -2,7 +2,6 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using System.Web; using Discord; using Discord.Commands; using Geekbot.Core; @@ -32,22 +31,19 @@ namespace Geekbot.Bot.Commands.Integrations var anime = results.Results.FirstOrDefault(); if (anime != null) { - var eb = new EmbedBuilder(); - - var description = HttpUtility.HtmlDecode(anime.Description) - .Replace("
", "") - .Replace("[i]", "*") - .Replace("[/i]", "*"); - - eb.Title = anime.Title; - eb.Description = description; - eb.ImageUrl = anime.ImageURL; - eb.AddInlineField("Premiered", FormatDate(anime.StartDate)); - eb.AddInlineField("Ended", anime.Airing ? "Present" : FormatDate(anime.EndDate)); - eb.AddInlineField("Episodes", anime.Episodes); - eb.AddInlineField("MAL Score", anime.Score); - eb.AddInlineField("Type", anime.Type); - eb.AddField("MAL Link", $"https://myanimelist.net/anime/{anime.MalId}"); + var eb = new EmbedBuilder + { + Title = anime.Title, + Description = anime.Description, + ImageUrl = anime.ImageURL + }; + + eb.AddInlineField("Premiere", FormatDate(anime.StartDate)) + .AddInlineField("Ended", anime.Airing ? "-" : FormatDate(anime.EndDate)) + .AddInlineField("Episodes", anime.Episodes) + .AddInlineField("MAL Score", anime.Score) + .AddInlineField("Type", anime.Type) + .AddField("MAL Link", $"https://myanimelist.net/anime/{anime.MalId}"); await ReplyAsync("", false, eb.Build()); } @@ -72,23 +68,20 @@ namespace Geekbot.Bot.Commands.Integrations var manga = results.Results.FirstOrDefault(); if (manga != null) { - var eb = new EmbedBuilder(); - - var description = HttpUtility.HtmlDecode(manga.Description) - .Replace("
", "") - .Replace("[i]", "*") - .Replace("[/i]", "*"); - - eb.Title = manga.Title; - eb.Description = description; - eb.ImageUrl = manga.ImageURL; - eb.AddInlineField("Premiered", FormatDate(manga.StartDate)); - eb.AddInlineField("Ended", manga.Publishing ? "Present" : FormatDate(manga.EndDate)); - eb.AddInlineField("Volumes", manga.Volumes); - eb.AddInlineField("Chapters", manga.Chapters); - eb.AddInlineField("MAL Score", manga.Score); - eb.AddField("MAL Link", $"https://myanimelist.net/manga/{manga.MalId}"); - + var eb = new EmbedBuilder + { + Title = manga.Title, + Description = manga.Description, + ImageUrl = manga.ImageURL + }; + + eb.AddInlineField("Premiere", FormatDate(manga.StartDate)) + .AddInlineField("Ended", manga.Publishing ? "-" : FormatDate(manga.EndDate)) + .AddInlineField("Volumes", manga.Volumes) + .AddInlineField("Chapters", manga.Chapters) + .AddInlineField("MAL Score", manga.Score) + .AddField("MAL Link", $"https://myanimelist.net/manga/{manga.MalId}"); + await ReplyAsync("", false, eb.Build()); } else @@ -108,7 +101,7 @@ namespace Geekbot.Bot.Commands.Integrations { return DateTime.MinValue.ToString("d", Thread.CurrentThread.CurrentUICulture); } - + return dateTime.Value.ToString("d", Thread.CurrentThread.CurrentUICulture); } } From 28a5b9322e831517f87e8cb08d85bf6a364bcecd Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 9 Oct 2020 17:10:49 +0200 Subject: [PATCH 401/553] Allow Rune#0007 to bypass the ignored servers restriction --- src/Bot/Handlers/CommandHandler.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Bot/Handlers/CommandHandler.cs b/src/Bot/Handlers/CommandHandler.cs index 52e9a52..3c072fe 100644 --- a/src/Bot/Handlers/CommandHandler.cs +++ b/src/Bot/Handlers/CommandHandler.cs @@ -58,7 +58,8 @@ namespace Geekbot.Bot.Handlers _ => 0 // DM Channel }; - if (IsIgnoredGuild(guildId, message.Author.Id)) return Task.CompletedTask; + // temp hack, will fix later + if (IsIgnoredGuild(guildId, message.Author.Id) || messageParam.Author.Id == 93061333972455424) return Task.CompletedTask; var lowCaseMsg = message.ToString().ToLower(); if (ShouldHui(lowCaseMsg, guildId)) From fe51dfe540d9dfae1ff9a2d5c15067adf65c0942 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 9 Oct 2020 17:25:53 +0200 Subject: [PATCH 402/553] Revert last commit --- src/Bot/Handlers/CommandHandler.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Bot/Handlers/CommandHandler.cs b/src/Bot/Handlers/CommandHandler.cs index 3c072fe..52e9a52 100644 --- a/src/Bot/Handlers/CommandHandler.cs +++ b/src/Bot/Handlers/CommandHandler.cs @@ -58,8 +58,7 @@ namespace Geekbot.Bot.Handlers _ => 0 // DM Channel }; - // temp hack, will fix later - if (IsIgnoredGuild(guildId, message.Author.Id) || messageParam.Author.Id == 93061333972455424) return Task.CompletedTask; + if (IsIgnoredGuild(guildId, message.Author.Id)) return Task.CompletedTask; var lowCaseMsg = message.ToString().ToLower(); if (ShouldHui(lowCaseMsg, guildId)) From ffab56d4a5e893aac0416ef75283fbb9f2b53129 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 23 Oct 2020 21:46:59 +0200 Subject: [PATCH 403/553] Delete original message from user after using !emojify --- src/Bot/Commands/Utils/Emojify.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Bot/Commands/Utils/Emojify.cs b/src/Bot/Commands/Utils/Emojify.cs index c8328ee..8bb880e 100644 --- a/src/Bot/Commands/Utils/Emojify.cs +++ b/src/Bot/Commands/Utils/Emojify.cs @@ -32,6 +32,14 @@ namespace Geekbot.Bot.Commands.Utils await ReplyAsync($"{Context.User.Username}#{Context.User.Discriminator} said:"); await ReplyAsync(emojis); + try + { + await Context.Message.DeleteAsync(); + } + catch + { + // bot may not have enough permission, doesn't matter if it fails + } } catch (Exception e) { From 2fb815bc97356d274d7f7edc80d380f97d634019 Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 2 Nov 2020 18:01:57 +0100 Subject: [PATCH 404/553] Don't use embeds for !dog --- src/Bot/Commands/Randomness/Dog/Dog.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Bot/Commands/Randomness/Dog/Dog.cs b/src/Bot/Commands/Randomness/Dog/Dog.cs index 2a8a3f1..051dbf3 100644 --- a/src/Bot/Commands/Randomness/Dog/Dog.cs +++ b/src/Bot/Commands/Randomness/Dog/Dog.cs @@ -23,11 +23,7 @@ namespace Geekbot.Bot.Commands.Randomness.Dog try { var response = await HttpAbstractions.Get(new Uri("http://random.dog/woof.json")); - var eb = new EmbedBuilder - { - ImageUrl = response.Url - }; - await ReplyAsync("", false, eb.Build()); + await ReplyAsync(response.Url); } catch (Exception e) { From 4c3b7044ce6543bc7cbfd9fc80fd71bee19a449d Mon Sep 17 00:00:00 2001 From: runebaas Date: Mon, 2 Nov 2020 18:33:05 +0100 Subject: [PATCH 405/553] Don't count 1 to many sides in the !dice command --- src/Core/DiceParser/SingleDie.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/DiceParser/SingleDie.cs b/src/Core/DiceParser/SingleDie.cs index f13dbcd..4e0f474 100644 --- a/src/Core/DiceParser/SingleDie.cs +++ b/src/Core/DiceParser/SingleDie.cs @@ -32,7 +32,7 @@ namespace Geekbot.Core.DiceParser { var result = new DieResult { - Roll1 = _random.Next(1, Sides + 1), + Roll1 = _random.Next(1, Sides), AdvantageType = AdvantageType }; From 09dbeb97667d12adcfd9fab69fc14b2811a6abdb Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 24 Nov 2020 21:40:33 +0100 Subject: [PATCH 406/553] Fix a stupid bug with the !avatar command --- src/Bot/Commands/Utils/AvatarGetter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bot/Commands/Utils/AvatarGetter.cs b/src/Bot/Commands/Utils/AvatarGetter.cs index 6585a75..2aa6b07 100644 --- a/src/Bot/Commands/Utils/AvatarGetter.cs +++ b/src/Bot/Commands/Utils/AvatarGetter.cs @@ -21,8 +21,8 @@ namespace Geekbot.Bot.Commands.Utils { try { - if (user == null) user = Context.User; - var url = user.GetAvatarUrl().Replace("128", "1024"); + user ??= Context.User; + var url = user.GetAvatarUrl(ImageFormat.Auto, 1024); await ReplyAsync(url); } catch (Exception e) From baf09e2f3807c9aa3fbd652f344399fee835eb89 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 25 Nov 2020 15:21:55 +0100 Subject: [PATCH 407/553] Remove the ability to create quotes from message ids --- src/Bot/Commands/Utils/Quote/Quote.cs | 35 ++------------------------ src/Bot/Localization/Quote.Designer.cs | 9 ------- src/Bot/Localization/Quote.de-ch.resx | 3 --- src/Bot/Localization/Quote.resx | 3 --- 4 files changed, 2 insertions(+), 48 deletions(-) diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index 0b197cd..a5f2e3c 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -74,22 +74,6 @@ namespace Geekbot.Bot.Commands.Utils.Quote { await QuoteFromMention(user, false); } - - [Command("add")] - [Alias("save")] - [Summary("Add a quote from a message id")] - public async Task AddQuote([Summary("message-ID")] ulong messageId) - { - await QuoteFromMessageId(messageId, true); - } - - [Command("make")] - [Alias("preview")] - [Summary("Preview a quote from a message id")] - public async Task ReturnSpecifiedQuote([Summary("message-ID")] ulong messageId) - { - await QuoteFromMessageId(messageId, false); - } [Command("add")] [Alias("save")] @@ -208,21 +192,7 @@ namespace Geekbot.Bot.Commands.Utils.Quote } - private async Task QuoteFromMessageId(ulong messageId, bool saveToDb) - { - try - { - var message = await Context.Channel.GetMessageAsync(messageId); - - await ProcessQuote(message, saveToDb, true); - } - catch (Exception e) - { - await ErrorHandler.HandleCommandException(e, Context, "I couldn't find a message with that id :disappointed:"); - } - } - - private async Task QuoteFromMessageLink(string messageLink, bool saveToDb) + private async Task QuoteFromMessageLink(string messageLink, bool saveToDb) { try { @@ -253,7 +223,7 @@ namespace Geekbot.Bot.Commands.Utils.Quote } } - private async Task ProcessQuote(IMessage message, bool saveToDb, bool showMessageIdWarning = false) + private async Task ProcessQuote(IMessage message, bool saveToDb) { if (message.Author.Id == Context.Message.Author.Id && saveToDb && !_isDev) { @@ -278,7 +248,6 @@ namespace Geekbot.Bot.Commands.Utils.Quote var sb = new StringBuilder(); if (saveToDb) sb.AppendLine(Localization.Quote.QuoteAdded); - if (showMessageIdWarning) sb.AppendLine(Localization.Quote.MessageIdDeprecation); await ReplyAsync(sb.ToString(), false, embed.Build()); } diff --git a/src/Bot/Localization/Quote.Designer.cs b/src/Bot/Localization/Quote.Designer.cs index d0926ae..342c181 100644 --- a/src/Bot/Localization/Quote.Designer.cs +++ b/src/Bot/Localization/Quote.Designer.cs @@ -78,15 +78,6 @@ namespace Geekbot.Bot.Localization { } } - /// - /// Looks up a localized string similar to :warning: Creating quotes by message ID is deprecated in favour of message links and will be removed on 1 December 2020. - /// - internal static string MessageIdDeprecation { - get { - return ResourceManager.GetString("MessageIdDeprecation", resourceCulture); - } - } - /// /// Looks up a localized string similar to Most quoted person. /// diff --git a/src/Bot/Localization/Quote.de-ch.resx b/src/Bot/Localization/Quote.de-ch.resx index c7e3b8b..99fd959 100644 --- a/src/Bot/Localization/Quote.de-ch.resx +++ b/src/Bot/Localization/Quote.de-ch.resx @@ -44,7 +44,4 @@ Du chasch numme nachrichte vom gliche server quote - - :warning: Es mache vo quotes mit message-IDs isch zgunste vo message-links veraltet und wird am 1. dezember 2020 entfernt - \ No newline at end of file diff --git a/src/Bot/Localization/Quote.resx b/src/Bot/Localization/Quote.resx index 215f0ea..b51d79c 100644 --- a/src/Bot/Localization/Quote.resx +++ b/src/Bot/Localization/Quote.resx @@ -51,7 +51,4 @@ You can only quote messages from the same server - - :warning: Creating quotes by message ID is deprecated in favour of message links and will be removed on 1 December 2020 - \ No newline at end of file From 714b0008bc480ebb1ac56f9f397d5591dc066df9 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 11 Dec 2020 22:38:43 +0100 Subject: [PATCH 408/553] Allow a die to have 145 sides --- src/Core/DiceParser/SingleDie.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Core/DiceParser/SingleDie.cs b/src/Core/DiceParser/SingleDie.cs index 4e0f474..7c1ae41 100644 --- a/src/Core/DiceParser/SingleDie.cs +++ b/src/Core/DiceParser/SingleDie.cs @@ -63,9 +63,9 @@ namespace Geekbot.Core.DiceParser throw new DiceException("Die must have at least 2 sides") { DiceName = DiceName }; } - if (Sides > 144) + if (Sides > 145) { - throw new DiceException("Die can not have more than 144 sides") { DiceName = DiceName }; + throw new DiceException("Die can not have more than 145 sides") { DiceName = DiceName }; } } } From 7e792bd7821ada737086c3b8a5171cc82ffc55b4 Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 29 Dec 2020 17:12:03 +0100 Subject: [PATCH 409/553] Fallback to user repo when retrieving a user via the discord gateway fails or times out --- src/Bot/Commands/Utils/Quote/Quote.cs | 16 ++++++++++++++-- src/Core/Polyfills/UserPolyfillDto.cs | 3 ++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index a5f2e3c..47986a0 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -13,6 +13,7 @@ using Geekbot.Core.Extensions; using Geekbot.Core.GuildSettingsManager; using Geekbot.Core.Polyfills; using Geekbot.Core.RandomNumberGenerator; +using Geekbot.Core.UserRepository; namespace Geekbot.Bot.Commands.Utils.Quote { @@ -22,13 +23,15 @@ namespace Geekbot.Bot.Commands.Utils.Quote { private readonly DatabaseContext _database; private readonly IRandomNumberGenerator _randomNumberGenerator; + private readonly IUserRepository _userRepository; private readonly bool _isDev; - public Quote(IErrorHandler errorHandler, DatabaseContext database, IRandomNumberGenerator randomNumberGenerator, IGuildSettingsManager guildSettingsManager) + public Quote(IErrorHandler errorHandler, DatabaseContext database, IRandomNumberGenerator randomNumberGenerator, IGuildSettingsManager guildSettingsManager, IUserRepository userRepository) : base(errorHandler, guildSettingsManager) { _database = database; _randomNumberGenerator = randomNumberGenerator; + _userRepository = userRepository; // to remove restrictions when developing _isDev = Constants.BotVersion() == "0.0.0-DEV"; } @@ -254,7 +257,16 @@ namespace Geekbot.Bot.Commands.Utils.Quote private EmbedBuilder QuoteBuilder(QuoteModel quote) { - var user = Context.Client.GetUserAsync(quote.UserId.AsUlong()).Result ?? new UserPolyfillDto { Username = "Unknown User" }; + var user = Context.Client.GetUserAsync(quote.UserId.AsUlong()).Result; + if (user == null) + { + var fallbackUserFromRepo = _userRepository.Get(quote.UserId.AsUlong()); + user = new UserPolyfillDto() + { + Username = fallbackUserFromRepo?.Username ?? "Unknown User", + AvatarUrl = fallbackUserFromRepo?.AvatarUrl + }; + } var eb = new EmbedBuilder(); eb.WithColor(new Color(143, 167, 232)); if (quote.InternalId == 0) diff --git a/src/Core/Polyfills/UserPolyfillDto.cs b/src/Core/Polyfills/UserPolyfillDto.cs index 3a8f43f..1d3a54b 100644 --- a/src/Core/Polyfills/UserPolyfillDto.cs +++ b/src/Core/Polyfills/UserPolyfillDto.cs @@ -14,6 +14,7 @@ namespace Geekbot.Core.Polyfills public UserStatus Status { get; set; } public IImmutableSet ActiveClients { get; } public string AvatarId { get; set; } + public string AvatarUrl { get; set; } public string Discriminator { get; set; } public ushort DiscriminatorValue { get; set; } public bool IsBot { get; set; } @@ -22,7 +23,7 @@ namespace Geekbot.Core.Polyfills public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) { - return "https://discordapp.com/assets/6debd47ed13483642cf09e832ed0bc1b.png"; + return AvatarUrl ?? "https://discordapp.com/assets/6debd47ed13483642cf09e832ed0bc1b.png"; } public string GetDefaultAvatarUrl() From 29c0def713fb668cdbd1d3bc7a74d94e0738a23c Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 29 Dec 2020 22:33:19 +0100 Subject: [PATCH 410/553] Start counting messages per quarter starting 1 january 2021 --- src/Bot/Handlers/StatsHandler.cs | 88 +++++++++++++++---- src/Core/Database/DatabaseContext.cs | 1 + .../Database/Models/MessageSeasonsModel.cs | 21 +++++ 3 files changed, 95 insertions(+), 15 deletions(-) create mode 100644 src/Core/Database/Models/MessageSeasonsModel.cs diff --git a/src/Bot/Handlers/StatsHandler.cs b/src/Bot/Handlers/StatsHandler.cs index 197bbb8..e5962a9 100644 --- a/src/Bot/Handlers/StatsHandler.cs +++ b/src/Bot/Handlers/StatsHandler.cs @@ -1,5 +1,7 @@ using System; +using System.Globalization; using System.Threading.Tasks; +using System.Timers; using Discord.WebSocket; using Geekbot.Core.Database; using Geekbot.Core.Database.Models; @@ -13,11 +15,28 @@ namespace Geekbot.Bot.Handlers { private readonly IGeekbotLogger _logger; private readonly DatabaseContext _database; + private string _season; + // ToDo: Clean up in 2021 + private bool _seasonsStarted; public StatsHandler(IGeekbotLogger logger, DatabaseContext database) { _logger = logger; _database = database; + _season = GetSeason(); + _seasonsStarted = DateTime.Now.Year == 2021; + + var timer = new Timer() + { + Enabled = true, + AutoReset = true, + Interval = TimeSpan.FromHours(1).TotalMilliseconds + }; + timer.Elapsed += (sender, args) => + { + _season = GetSeason(); + _seasonsStarted = DateTime.Now.Year == 2021; + }; } public async Task UpdateStats(SocketMessage message) @@ -32,23 +51,12 @@ namespace Geekbot.Bot.Handlers } var channel = (SocketGuildChannel) message.Channel; - - var rowId = await _database.Database.ExecuteSqlRawAsync( - "UPDATE \"Messages\" SET \"MessageCount\" = \"MessageCount\" + 1 WHERE \"GuildId\" = {0} AND \"UserId\" = {1}", - channel.Guild.Id.AsLong(), - message.Author.Id.AsLong() - ); - - if (rowId == 0) + await UpdateTotalTable(message, channel); + if (_seasonsStarted) { - await _database.Messages.AddAsync(new MessagesModel - { - UserId = message.Author.Id.AsLong(), - GuildId = channel.Guild.Id.AsLong(), - MessageCount = 1 - }); - await _database.SaveChangesAsync(); + await UpdateSeasonsTable(message, channel); } + if (message.Author.IsBot) return; _logger.Information(LogSource.Message, message.Content, SimpleConextConverter.ConvertSocketMessage(message)); @@ -58,5 +66,55 @@ namespace Geekbot.Bot.Handlers _logger.Error(LogSource.Message, "Could not process message stats", e); } } + + private async Task UpdateTotalTable(SocketMessage message, SocketGuildChannel channel) + { + var rowId = await _database.Database.ExecuteSqlRawAsync( + "UPDATE \"Messages\" SET \"MessageCount\" = \"MessageCount\" + 1 WHERE \"GuildId\" = {0} AND \"UserId\" = {1}", + channel.Guild.Id.AsLong(), + message.Author.Id.AsLong() + ); + + if (rowId == 0) + { + await _database.Messages.AddAsync(new MessagesModel + { + UserId = message.Author.Id.AsLong(), + GuildId = channel.Guild.Id.AsLong(), + MessageCount = 1 + }); + await _database.SaveChangesAsync(); + } + } + + private async Task UpdateSeasonsTable(SocketMessage message, SocketGuildChannel channel) + { + var rowId = await _database.Database.ExecuteSqlRawAsync( + "UPDATE \"MessagesSeasons\" SET \"MessageCount\" = \"MessageCount\" + 1 WHERE \"GuildId\" = {0} AND \"UserId\" = {1} AND \"Season\" = {2}", + channel.Guild.Id.AsLong(), + message.Author.Id.AsLong(), + _season + ); + + if (rowId == 0) + { + await _database.MessagesSeasons.AddAsync(new MessageSeasonsModel() + { + UserId = message.Author.Id.AsLong(), + GuildId = channel.Guild.Id.AsLong(), + Season = _season, + MessageCount = 1 + }); + await _database.SaveChangesAsync(); + } + } + + private static string GetSeason() + { + var now = DateTime.Now; + var year = (now.Year - 2000).ToString(CultureInfo.InvariantCulture); + var quarter = Math.Ceiling(now.Month / 3.0).ToString(CultureInfo.InvariantCulture); + return $"{year}Q{quarter}"; + } } } \ No newline at end of file diff --git a/src/Core/Database/DatabaseContext.cs b/src/Core/Database/DatabaseContext.cs index 93d46d3..14a1275 100644 --- a/src/Core/Database/DatabaseContext.cs +++ b/src/Core/Database/DatabaseContext.cs @@ -11,6 +11,7 @@ namespace Geekbot.Core.Database public DbSet Karma { get; set; } public DbSet Ships { get; set; } public DbSet Rolls { get; set; } + public DbSet MessagesSeasons { get; set; } public DbSet Messages { get; set; } public DbSet Slaps { get; set; } public DbSet Globals { get; set; } diff --git a/src/Core/Database/Models/MessageSeasonsModel.cs b/src/Core/Database/Models/MessageSeasonsModel.cs new file mode 100644 index 0000000..5a4252c --- /dev/null +++ b/src/Core/Database/Models/MessageSeasonsModel.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.DataAnnotations; + +namespace Geekbot.Core.Database.Models +{ + public class MessageSeasonsModel + { + [Key] + public int Id { get; set; } + + [Required] + public long GuildId { get; set; } + + [Required] + public long UserId { get; set; } + + [Required] + public string Season { get; set; } + + public int MessageCount { get; set; } + } +} \ No newline at end of file From 29bb8035fe14f4f9a2b34c60f91548433fd82535 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Wed, 30 Dec 2020 23:17:00 +0100 Subject: [PATCH 411/553] add !rank seasons to the rank command --- src/Bot/Commands/User/Ranking/Rank.cs | 22 ++++++++++++++++++---- src/Bot/Handlers/StatsHandler.cs | 16 +++++----------- src/Core/Highscores/HighscoreManager.cs | 16 +++++++++++++++- src/Core/Highscores/HighscoreTypes.cs | 3 ++- src/Core/Highscores/IHighscoreManager.cs | 3 ++- src/Core/Highscores/SeasonsUtils.cs | 16 ++++++++++++++++ 6 files changed, 58 insertions(+), 18 deletions(-) create mode 100644 src/Core/Highscores/SeasonsUtils.cs diff --git a/src/Bot/Commands/User/Ranking/Rank.cs b/src/Bot/Commands/User/Ranking/Rank.cs index 20749a8..14a7650 100644 --- a/src/Bot/Commands/User/Ranking/Rank.cs +++ b/src/Bot/Commands/User/Ranking/Rank.cs @@ -30,9 +30,12 @@ namespace Geekbot.Bot.Commands.User.Ranking } [Command("rank", RunMode = RunMode.Async)] - [Summary("get user top 10 in messages or karma")] + [Summary("Get the highscore for various stats like message count, karma, correctly guessed roles, etc...")] [DisableInDirectMessage] - public async Task RankCmd([Summary("type")] string typeUnformated = "messages", [Summary("amount")] int amount = 10) + public async Task RankCmd( + [Summary("type")] string typeUnformated = "messages", + [Summary("amount")] int amount = 10, + [Summary("season")] string season = null) { try { @@ -59,7 +62,7 @@ namespace Geekbot.Bot.Commands.User.Ranking Dictionary highscoreUsers; try { - highscoreUsers = _highscoreManager.GetHighscoresWithUserData(type, guildId, amount); + highscoreUsers = _highscoreManager.GetHighscoresWithUserData(type, guildId, amount, season); } catch (HighscoreListEmptyException) { @@ -80,7 +83,18 @@ namespace Geekbot.Bot.Commands.User.Ranking if (failedToRetrieveUser) replyBuilder.AppendLine(Localization.Rank.FailedToResolveAllUsernames).AppendLine(); - replyBuilder.AppendLine(string.Format(Localization.Rank.HighscoresFor, type.ToString().CapitalizeFirst(), Context.Guild.Name)); + if (type == HighscoreTypes.seasons) + { + if (string.IsNullOrEmpty(season)) + { + season = SeasonsUtils.GetCurrentSeason(); + } + replyBuilder.AppendLine(string.Format(Localization.Rank.HighscoresFor, $"{type.ToString().CapitalizeFirst()} ({season})", Context.Guild.Name)); + } + else + { + replyBuilder.AppendLine(string.Format(Localization.Rank.HighscoresFor, type.ToString().CapitalizeFirst(), Context.Guild.Name)); + } var highscorePlace = 1; foreach (var (user, value) in highscoreUsers) diff --git a/src/Bot/Handlers/StatsHandler.cs b/src/Bot/Handlers/StatsHandler.cs index e5962a9..669be0f 100644 --- a/src/Bot/Handlers/StatsHandler.cs +++ b/src/Bot/Handlers/StatsHandler.cs @@ -1,11 +1,11 @@ using System; -using System.Globalization; using System.Threading.Tasks; using System.Timers; using Discord.WebSocket; using Geekbot.Core.Database; using Geekbot.Core.Database.Models; using Geekbot.Core.Extensions; +using Geekbot.Core.Highscores; using Geekbot.Core.Logger; using Microsoft.EntityFrameworkCore; @@ -23,7 +23,7 @@ namespace Geekbot.Bot.Handlers { _logger = logger; _database = database; - _season = GetSeason(); + _season = SeasonsUtils.GetCurrentSeason(); _seasonsStarted = DateTime.Now.Year == 2021; var timer = new Timer() @@ -34,7 +34,9 @@ namespace Geekbot.Bot.Handlers }; timer.Elapsed += (sender, args) => { - _season = GetSeason(); + var current = SeasonsUtils.GetCurrentSeason(); + if (current == _season) return; + _season = SeasonsUtils.GetCurrentSeason(); _seasonsStarted = DateTime.Now.Year == 2021; }; } @@ -108,13 +110,5 @@ namespace Geekbot.Bot.Handlers await _database.SaveChangesAsync(); } } - - private static string GetSeason() - { - var now = DateTime.Now; - var year = (now.Year - 2000).ToString(CultureInfo.InvariantCulture); - var quarter = Math.Ceiling(now.Month / 3.0).ToString(CultureInfo.InvariantCulture); - return $"{year}Q{quarter}"; - } } } \ No newline at end of file diff --git a/src/Core/Highscores/HighscoreManager.cs b/src/Core/Highscores/HighscoreManager.cs index ac8580b..7379e5e 100644 --- a/src/Core/Highscores/HighscoreManager.cs +++ b/src/Core/Highscores/HighscoreManager.cs @@ -18,7 +18,7 @@ namespace Geekbot.Core.Highscores } - public Dictionary GetHighscoresWithUserData(HighscoreTypes type, ulong guildId, int amount) + public Dictionary GetHighscoresWithUserData(HighscoreTypes type, ulong guildId, int amount, string season = null) { var list = type switch { @@ -26,6 +26,7 @@ namespace Geekbot.Core.Highscores HighscoreTypes.karma => GetKarmaList(guildId, amount), HighscoreTypes.rolls => GetRollsList(guildId, amount), HighscoreTypes.cookies => GetCookiesList(guildId, amount), + HighscoreTypes.seasons => GetMessageSeasonList(guildId, amount, season), _ => new Dictionary() }; @@ -75,6 +76,19 @@ namespace Geekbot.Core.Highscores .ToDictionary(key => key.UserId.AsUlong(), key => key.MessageCount); } + public Dictionary GetMessageSeasonList(ulong guildId, int amount, string season) + { + if (string.IsNullOrEmpty(season)) + { + season = SeasonsUtils.GetCurrentSeason(); + } + return _database.MessagesSeasons + .Where(k => k.GuildId.Equals(guildId.AsLong()) && k.Season.Equals(season)) + .OrderByDescending(o => o.MessageCount) + .Take(amount) + .ToDictionary(key => key.UserId.AsUlong(), key => key.MessageCount); + } + public Dictionary GetKarmaList(ulong guildId, int amount) { return _database.Karma diff --git a/src/Core/Highscores/HighscoreTypes.cs b/src/Core/Highscores/HighscoreTypes.cs index b577642..9901c98 100644 --- a/src/Core/Highscores/HighscoreTypes.cs +++ b/src/Core/Highscores/HighscoreTypes.cs @@ -5,6 +5,7 @@ messages, karma, rolls, - cookies + cookies, + seasons } } \ No newline at end of file diff --git a/src/Core/Highscores/IHighscoreManager.cs b/src/Core/Highscores/IHighscoreManager.cs index 83ba2da..9c2d6f0 100644 --- a/src/Core/Highscores/IHighscoreManager.cs +++ b/src/Core/Highscores/IHighscoreManager.cs @@ -4,8 +4,9 @@ namespace Geekbot.Core.Highscores { public interface IHighscoreManager { - Dictionary GetHighscoresWithUserData(HighscoreTypes type, ulong guildId, int amount); + Dictionary GetHighscoresWithUserData(HighscoreTypes type, ulong guildId, int amount, string season = null); Dictionary GetMessageList(ulong guildId, int amount); + Dictionary GetMessageSeasonList(ulong guildId, int amount, string season); Dictionary GetKarmaList(ulong guildId, int amount); Dictionary GetRollsList(ulong guildId, int amount); } diff --git a/src/Core/Highscores/SeasonsUtils.cs b/src/Core/Highscores/SeasonsUtils.cs new file mode 100644 index 0000000..d2a8e3e --- /dev/null +++ b/src/Core/Highscores/SeasonsUtils.cs @@ -0,0 +1,16 @@ +using System; +using System.Globalization; + +namespace Geekbot.Core.Highscores +{ + public class SeasonsUtils + { + public static string GetCurrentSeason() + { + var now = DateTime.Now; + var year = (now.Year - 2000).ToString(CultureInfo.InvariantCulture); + var quarter = Math.Ceiling(now.Month / 3.0).ToString(CultureInfo.InvariantCulture); + return $"{year}Q{quarter}"; + } + } +} \ No newline at end of file From 01f0d2f43b613d07b9a5be365c6274f2f9dbd983 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Wed, 30 Dec 2020 23:19:15 +0100 Subject: [PATCH 412/553] Check every 5 minutes if it's 2021 instead of every hour in the stats handler --- src/Bot/Handlers/StatsHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Bot/Handlers/StatsHandler.cs b/src/Bot/Handlers/StatsHandler.cs index 669be0f..137842c 100644 --- a/src/Bot/Handlers/StatsHandler.cs +++ b/src/Bot/Handlers/StatsHandler.cs @@ -30,7 +30,7 @@ namespace Geekbot.Bot.Handlers { Enabled = true, AutoReset = true, - Interval = TimeSpan.FromHours(1).TotalMilliseconds + Interval = TimeSpan.FromMinutes(5).TotalMilliseconds }; timer.Elapsed += (sender, args) => { From 17f62d76079f48c49e9943a6f11f73adb15970ca Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Wed, 30 Dec 2020 23:23:40 +0100 Subject: [PATCH 413/553] Ignore the discord bots server when updating stats --- src/Bot/Handlers/StatsHandler.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Bot/Handlers/StatsHandler.cs b/src/Bot/Handlers/StatsHandler.cs index 137842c..5ee7871 100644 --- a/src/Bot/Handlers/StatsHandler.cs +++ b/src/Bot/Handlers/StatsHandler.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Threading.Tasks; using System.Timers; using Discord.WebSocket; @@ -25,7 +26,7 @@ namespace Geekbot.Bot.Handlers _database = database; _season = SeasonsUtils.GetCurrentSeason(); _seasonsStarted = DateTime.Now.Year == 2021; - + var timer = new Timer() { Enabled = true, @@ -53,6 +54,14 @@ namespace Geekbot.Bot.Handlers } var channel = (SocketGuildChannel) message.Channel; + + // ignore the discord bots server + // ToDo: create a clean solution for this... + if (channel.Guild.Id == 110373943822540800) + { + return; + } + await UpdateTotalTable(message, channel); if (_seasonsStarted) { From 8bdf2e96818c2ef2ad5acb6906ca8200e7851e77 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Wed, 30 Dec 2020 23:31:15 +0100 Subject: [PATCH 414/553] Add support for !rank quote --- src/Bot/Commands/Utils/Quote/Quote.cs | 4 ++-- src/Core/Highscores/HighscoreManager.cs | 12 ++++++++++++ src/Core/Highscores/HighscoreTypes.cs | 3 ++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index 47986a0..6a94309 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -147,8 +147,8 @@ namespace Geekbot.Bot.Commands.Utils.Quote .Where(row => row.GuildId == Context.Guild.Id.AsLong()) .GroupBy(row => row.UserId) .Select(row => new { userId = row.Key, amount = row.Count()}) - .OrderBy(row => row.amount) - .Last(); + .OrderByDescending(row => row.amount) + .First(); var mostQuotedPersonUser = Context.Client.GetUserAsync(mostQuotedPerson.userId.AsUlong()).Result ?? new UserPolyfillDto {Username = "Unknown User"}; var quotesByYear = _database.Quotes diff --git a/src/Core/Highscores/HighscoreManager.cs b/src/Core/Highscores/HighscoreManager.cs index 7379e5e..c839b39 100644 --- a/src/Core/Highscores/HighscoreManager.cs +++ b/src/Core/Highscores/HighscoreManager.cs @@ -27,6 +27,7 @@ namespace Geekbot.Core.Highscores HighscoreTypes.rolls => GetRollsList(guildId, amount), HighscoreTypes.cookies => GetCookiesList(guildId, amount), HighscoreTypes.seasons => GetMessageSeasonList(guildId, amount, season), + HighscoreTypes.quotes => GetQuotesList(guildId, amount), _ => new Dictionary() }; @@ -115,5 +116,16 @@ namespace Geekbot.Core.Highscores .Take(amount) .ToDictionary(key => key.UserId.AsUlong(), key => key.Cookies); } + + private Dictionary GetQuotesList(ulong guildId, int amount) + { + return _database.Quotes + .Where(row => row.GuildId == guildId.AsLong()) + .GroupBy(row => row.UserId) + .Select(row => new { userId = row.Key, amount = row.Count()}) + .OrderByDescending(row => row.amount) + .Take(amount) + .ToDictionary(key => key.userId.AsUlong(), key => key.amount); + } } } \ No newline at end of file diff --git a/src/Core/Highscores/HighscoreTypes.cs b/src/Core/Highscores/HighscoreTypes.cs index 9901c98..3aa396e 100644 --- a/src/Core/Highscores/HighscoreTypes.cs +++ b/src/Core/Highscores/HighscoreTypes.cs @@ -6,6 +6,7 @@ karma, rolls, cookies, - seasons + seasons, + quotes } } \ No newline at end of file From d477a4b056e209c4462fc369e311ec7044afb3e7 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Wed, 30 Dec 2020 23:33:27 +0100 Subject: [PATCH 415/553] Update the translations for !rank with the new rank types --- src/Bot/Localization/Rank.Designer.cs | 2 +- src/Bot/Localization/Rank.de-ch.resx | 2 +- src/Bot/Localization/Rank.resx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Bot/Localization/Rank.Designer.cs b/src/Bot/Localization/Rank.Designer.cs index 23f5e16..6d54030 100644 --- a/src/Bot/Localization/Rank.Designer.cs +++ b/src/Bot/Localization/Rank.Designer.cs @@ -79,7 +79,7 @@ namespace Geekbot.Bot.Localization { } /// - /// Looks up a localized string similar to Valid types are '`messages`' '`karma`', '`rolls`' and '`cookies`'. + /// Looks up a localized string similar to Valid types are '`messages`' '`karma`', '`rolls`', '`cookies`', '`seasons`' and '`quotes`'. /// internal static string InvalidType { get { diff --git a/src/Bot/Localization/Rank.de-ch.resx b/src/Bot/Localization/Rank.de-ch.resx index 0b22fe4..743b8cd 100644 --- a/src/Bot/Localization/Rank.de-ch.resx +++ b/src/Bot/Localization/Rank.de-ch.resx @@ -24,6 +24,6 @@ :bar_chart: **{0} Highscore für {1}**
- Gültigi paramenter sind '`messages`' '`karma`', '`rolls`' und '`cookies` + Gültigi paramenter sind '`messages`' '`karma`', '`rolls`', '`cookies`', '`seasons`' und '`quotes`' \ No newline at end of file diff --git a/src/Bot/Localization/Rank.resx b/src/Bot/Localization/Rank.resx index 9598cf8..606a34e 100644 --- a/src/Bot/Localization/Rank.resx +++ b/src/Bot/Localization/Rank.resx @@ -19,7 +19,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Valid types are '`messages`' '`karma`', '`rolls`' and '`cookies`' + Valid types are '`messages`' '`karma`', '`rolls`', '`cookies`', '`seasons`' and '`quotes`' :warning: Limiting to 20 From e495e2df17178bf0f444fe5a9bc0c73ad19dc920 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 1 Jan 2021 02:48:28 +0100 Subject: [PATCH 416/553] Use the correct unit when listing messages in a season --- src/Bot/Commands/User/Ranking/Rank.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Bot/Commands/User/Ranking/Rank.cs b/src/Bot/Commands/User/Ranking/Rank.cs index 14a7650..2f5f841 100644 --- a/src/Bot/Commands/User/Ranking/Rank.cs +++ b/src/Bot/Commands/User/Ranking/Rank.cs @@ -106,10 +106,13 @@ namespace Geekbot.Bot.Commands.User.Ranking replyBuilder.Append(user.Username != null ? $"**{user.Username}#{user.Discriminator}**" : $"**{user.Id}**"); - - replyBuilder.Append(type == HighscoreTypes.messages - ? $" - {value} {type} - {Math.Round((double) (100 * value) / guildMessages, 2)}%\n" - : $" - {value} {type}\n"); + + replyBuilder.Append(type switch + { + HighscoreTypes.messages => $" - {value} {HighscoreTypes.messages} - {Math.Round((double) (100 * value) / guildMessages, 2)}%\n", + HighscoreTypes.seasons => $" - {value} {HighscoreTypes.messages}\n", + _ => $" - {value} {type}\n" + }); highscorePlace++; } From 21303bfca81015af03e02d3a92f15e86f98d00ba Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 1 Jan 2021 18:06:40 +0100 Subject: [PATCH 417/553] Remove code in the stats handler that checks if 2021 has started --- src/Bot/Handlers/StatsHandler.cs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/Bot/Handlers/StatsHandler.cs b/src/Bot/Handlers/StatsHandler.cs index 5ee7871..d1384cd 100644 --- a/src/Bot/Handlers/StatsHandler.cs +++ b/src/Bot/Handlers/StatsHandler.cs @@ -17,15 +17,12 @@ namespace Geekbot.Bot.Handlers private readonly IGeekbotLogger _logger; private readonly DatabaseContext _database; private string _season; - // ToDo: Clean up in 2021 - private bool _seasonsStarted; public StatsHandler(IGeekbotLogger logger, DatabaseContext database) { _logger = logger; _database = database; _season = SeasonsUtils.GetCurrentSeason(); - _seasonsStarted = DateTime.Now.Year == 2021; var timer = new Timer() { @@ -38,7 +35,6 @@ namespace Geekbot.Bot.Handlers var current = SeasonsUtils.GetCurrentSeason(); if (current == _season) return; _season = SeasonsUtils.GetCurrentSeason(); - _seasonsStarted = DateTime.Now.Year == 2021; }; } @@ -62,11 +58,8 @@ namespace Geekbot.Bot.Handlers return; } - await UpdateTotalTable(message, channel); - if (_seasonsStarted) - { - await UpdateSeasonsTable(message, channel); - } + await UpdateTotalTable(message, channel); + await UpdateSeasonsTable(message, channel); if (message.Author.IsBot) return; From 04343352395a6f015e2acf919f64e5de2f5aca92 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Sun, 24 Jan 2021 22:15:15 +0100 Subject: [PATCH 418/553] Fix !corona by changing data source to covid19-api.org, added a country code parameter as well --- .../Corona/CoronaApiCountryResponseDto.cs | 19 +++++ src/Bot/Commands/Utils/Corona/CoronaStats.cs | 72 +++++++++++++++---- .../Commands/Utils/Corona/CoronaSummaryDto.cs | 9 --- .../Commands/Utils/Corona/CoronaTotalDto.cs | 9 +++ 4 files changed, 87 insertions(+), 22 deletions(-) create mode 100644 src/Bot/Commands/Utils/Corona/CoronaApiCountryResponseDto.cs delete mode 100644 src/Bot/Commands/Utils/Corona/CoronaSummaryDto.cs create mode 100644 src/Bot/Commands/Utils/Corona/CoronaTotalDto.cs diff --git a/src/Bot/Commands/Utils/Corona/CoronaApiCountryResponseDto.cs b/src/Bot/Commands/Utils/Corona/CoronaApiCountryResponseDto.cs new file mode 100644 index 0000000..84da7f0 --- /dev/null +++ b/src/Bot/Commands/Utils/Corona/CoronaApiCountryResponseDto.cs @@ -0,0 +1,19 @@ +using Newtonsoft.Json; + +namespace Geekbot.Bot.Commands.Utils.Corona +{ + public record CoronaApiCountryResponseDto + { + [JsonProperty("country")] + public string Country { get; init; } + + [JsonProperty("cases")] + public decimal Cases { get; init; } + + [JsonProperty("deaths")] + public decimal Deaths { get; init; } + + [JsonProperty("recovered")] + public decimal Recovered { get; init; } + } +} \ No newline at end of file diff --git a/src/Bot/Commands/Utils/Corona/CoronaStats.cs b/src/Bot/Commands/Utils/Corona/CoronaStats.cs index 3f9f3ea..5880030 100644 --- a/src/Bot/Commands/Utils/Corona/CoronaStats.cs +++ b/src/Bot/Commands/Utils/Corona/CoronaStats.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; @@ -11,7 +13,7 @@ namespace Geekbot.Bot.Commands.Utils.Corona public class CoronaStats : ModuleBase { private readonly IErrorHandler _errorHandler; - + public CoronaStats(IErrorHandler errorHandler) { _errorHandler = errorHandler; @@ -19,24 +21,30 @@ namespace Geekbot.Bot.Commands.Utils.Corona [Command("corona", RunMode = RunMode.Async)] [Summary("Get the latest worldwide corona statistics")] - public async Task Summary() + public async Task Summary([Summary("CountryCode")] string countryCode = null) { try { - var summary = await HttpAbstractions.Get(new Uri("https://api.covid19api.com/world/total")); - var activeCases = summary.TotalConfirmed - (summary.TotalRecovered + summary.TotalDeaths); + var summary = await GetCoronaInfo(countryCode); + if (summary == null) + { + await Context.Channel.SendMessageAsync($"`{countryCode}` is not a valid country code"); + return; + } + + var activeCases = summary.Cases - (summary.Recovered + summary.Deaths); - string CalculatePercentage(decimal i) => (i / summary.TotalConfirmed).ToString("#0.##%"); + string CalculatePercentage(decimal i) => (i / summary.Cases).ToString("#0.##%"); var activePercent = CalculatePercentage(activeCases); - var recoveredPercentage = CalculatePercentage(summary.TotalRecovered); - var deathsPercentage = CalculatePercentage(summary.TotalDeaths); + var recoveredPercentage = CalculatePercentage(summary.Recovered); + var deathsPercentage = CalculatePercentage(summary.Deaths); var numberFormat = "#,#"; - var totalFormatted = summary.TotalConfirmed.ToString(numberFormat); + var totalFormatted = summary.Cases.ToString(numberFormat); var activeFormatted = activeCases.ToString(numberFormat); - var recoveredFormatted = summary.TotalRecovered.ToString(numberFormat); - var deathsFormatted = summary.TotalDeaths.ToString(numberFormat); - + var recoveredFormatted = summary.Recovered.ToString(numberFormat); + var deathsFormatted = summary.Deaths.ToString(numberFormat); + var eb = new EmbedBuilder { Author = new EmbedAuthorBuilder @@ -46,7 +54,7 @@ namespace Geekbot.Bot.Commands.Utils.Corona }, Footer = new EmbedFooterBuilder { - Text = "Source: covid19api.com", + Text = "Source: covid19-api.org", }, Color = Color.Red }; @@ -54,7 +62,7 @@ namespace Geekbot.Bot.Commands.Utils.Corona eb.AddInlineField("Active", $"{activeFormatted} ({activePercent})"); eb.AddInlineField("Recovered", $"{recoveredFormatted} ({recoveredPercentage})"); eb.AddInlineField("Deaths", $"{deathsFormatted} ({deathsPercentage})"); - + await Context.Channel.SendMessageAsync(String.Empty, false, eb.Build()); } catch (Exception e) @@ -62,5 +70,43 @@ namespace Geekbot.Bot.Commands.Utils.Corona await _errorHandler.HandleCommandException(e, Context); } } + + private async Task GetCoronaInfo(string countryCode = null) + { + var allCountries = await HttpAbstractions.Get>(new Uri("https://covid19-api.org/api/status")); + + if (string.IsNullOrEmpty(countryCode)) + { + return allCountries.Aggregate( + new CoronaTotalDto(), + (accumulate, source) => + { + accumulate.Cases += source.Cases; + accumulate.Deaths += source.Deaths; + accumulate.Recovered += source.Recovered; + return accumulate; + } + ); + } + + if (countryCode.Length != 2) + { + return null; + } + + var upcasedCountryCode = countryCode.ToUpper(); + var countryStats = allCountries.Find(x => x.Country == upcasedCountryCode); + if (countryStats == null) + { + return null; + } + + return new CoronaTotalDto() + { + Cases = countryStats.Cases, + Deaths = countryStats.Deaths, + Recovered = countryStats.Recovered, + }; + } } } \ No newline at end of file diff --git a/src/Bot/Commands/Utils/Corona/CoronaSummaryDto.cs b/src/Bot/Commands/Utils/Corona/CoronaSummaryDto.cs deleted file mode 100644 index 3f6a820..0000000 --- a/src/Bot/Commands/Utils/Corona/CoronaSummaryDto.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Geekbot.Bot.Commands.Utils.Corona -{ - public class CoronaSummaryDto - { - public decimal TotalConfirmed { get; set; } - public decimal TotalDeaths { get; set; } - public decimal TotalRecovered { get; set; } - } -} \ No newline at end of file diff --git a/src/Bot/Commands/Utils/Corona/CoronaTotalDto.cs b/src/Bot/Commands/Utils/Corona/CoronaTotalDto.cs new file mode 100644 index 0000000..c135927 --- /dev/null +++ b/src/Bot/Commands/Utils/Corona/CoronaTotalDto.cs @@ -0,0 +1,9 @@ +namespace Geekbot.Bot.Commands.Utils.Corona +{ + public record CoronaTotalDto + { + public decimal Cases { get; set; } + public decimal Deaths { get; set; } + public decimal Recovered { get; set; } + } +} \ No newline at end of file From 4fd62e9184145db1f76f33ebc3762c782e7fcde5 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Sun, 24 Jan 2021 22:20:59 +0100 Subject: [PATCH 419/553] Make sure that the build version suffix is not a number --- .gitlab-ci.yml | 4 ++-- src/Bot/Bot.csproj | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c4d8b15..20b1c84 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,7 +5,7 @@ stages: - ops variables: - VERSION: 4.3.0-$CI_COMMIT_SHORT_SHA + VERSION: 4.3.0-V$CI_COMMIT_SHORT_SHA IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG Build: @@ -18,7 +18,7 @@ Build: script: - dotnet restore - dotnet test tests - - dotnet publish --version-suffix $VERSION -r linux-x64 -c Release -o ./app ./src/Bot/ + - dotnet publish --version-suffix "$VERSION" -r linux-x64 -c Release -o ./app ./src/Bot/ Package: stage: docker diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index 4cd5b39..ec32e8f 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -7,7 +7,7 @@ $(VersionSuffix) Geekbot.Bot Geekbot - $(VersionSuffix) + $(VersionSuffix) 0.0.0-DEV Pizza and Coffee Studios Pizza and Coffee Studios From bbb9b894227f6f136bddfa1f8b418166d623d82d Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Mon, 25 Jan 2021 00:48:42 +0100 Subject: [PATCH 420/553] Add Support for emoji flags in the emoji converter --- src/Core/Converters/EmojiConverter.cs | 166 ++++++++++++++++--------- src/Core/Converters/IEmojiConverter.cs | 1 + 2 files changed, 107 insertions(+), 60 deletions(-) diff --git a/src/Core/Converters/EmojiConverter.cs b/src/Core/Converters/EmojiConverter.cs index 327aab8..7527321 100644 --- a/src/Core/Converters/EmojiConverter.cs +++ b/src/Core/Converters/EmojiConverter.cs @@ -1,90 +1,136 @@ using System.Collections; +using System.Net.NetworkInformation; using System.Text; namespace Geekbot.Core.Converters { public class EmojiConverter : IEmojiConverter { + private readonly string[] NumberEmojiMap = + { + ":zero:", + ":one:", + ":two:", + ":three:", + ":four:", + ":five:", + ":six:", + ":seven:", + ":eight:", + ":nine:" + }; + public string NumberToEmoji(int number) { if (number == 10) { return "🔟"; } - var emojiMap = new[] - { - ":zero:", - ":one:", - ":two:", - ":three:", - ":four:", - ":five:", - ":six:", - ":seven:", - ":eight:", - ":nine:" - }; + var numbers = number.ToString().ToCharArray(); var returnString = new StringBuilder(); foreach (var n in numbers) { - returnString.Append(emojiMap[int.Parse(n.ToString())]); + returnString.Append(NumberEmojiMap[int.Parse(n.ToString())]); } return returnString.ToString(); } + private readonly Hashtable TextEmojiMap = new Hashtable + { + ['A'] = ":regional_indicator_a: ", + ['B'] = ":b: ", + ['C'] = ":regional_indicator_c: ", + ['D'] = ":regional_indicator_d: ", + ['E'] = ":regional_indicator_e: ", + ['F'] = ":regional_indicator_f: ", + ['G'] = ":regional_indicator_g: ", + ['H'] = ":regional_indicator_h: ", + ['I'] = ":regional_indicator_i: ", + ['J'] = ":regional_indicator_j: ", + ['K'] = ":regional_indicator_k: ", + ['L'] = ":regional_indicator_l: ", + ['M'] = ":regional_indicator_m: ", + ['N'] = ":regional_indicator_n: ", + ['O'] = ":regional_indicator_o: ", + ['P'] = ":regional_indicator_p: ", + ['Q'] = ":regional_indicator_q: ", + ['R'] = ":regional_indicator_r: ", + ['S'] = ":regional_indicator_s: ", + ['T'] = ":regional_indicator_t: ", + ['U'] = ":regional_indicator_u: ", + ['V'] = ":regional_indicator_v: ", + ['W'] = ":regional_indicator_w: ", + ['X'] = ":regional_indicator_x: ", + ['Y'] = ":regional_indicator_y: ", + ['Z'] = ":regional_indicator_z: ", + ['!'] = ":exclamation: ", + ['?'] = ":question: ", + ['#'] = ":hash: ", + ['*'] = ":star2: ", + ['+'] = ":heavy_plus_sign: ", + ['0'] = ":zero: ", + ['1'] = ":one: ", + ['2'] = ":two: ", + ['3'] = ":three: ", + ['4'] = ":four: ", + ['5'] = ":five: ", + ['6'] = ":six: ", + ['7'] = ":seven: ", + ['8'] = ":eight: ", + ['9'] = ":nine: ", + [' '] = " " + }; + public string TextToEmoji(string text) { - var emojiMap = new Hashtable - { - ['A'] = ":regional_indicator_a: ", - ['B'] = ":b: ", - ['C'] = ":regional_indicator_c: ", - ['D'] = ":regional_indicator_d: ", - ['E'] = ":regional_indicator_e: ", - ['F'] = ":regional_indicator_f: ", - ['G'] = ":regional_indicator_g: ", - ['H'] = ":regional_indicator_h: ", - ['I'] = ":regional_indicator_i: ", - ['J'] = ":regional_indicator_j: ", - ['K'] = ":regional_indicator_k: ", - ['L'] = ":regional_indicator_l: ", - ['M'] = ":regional_indicator_m: ", - ['N'] = ":regional_indicator_n: ", - ['O'] = ":regional_indicator_o: ", - ['P'] = ":regional_indicator_p: ", - ['Q'] = ":regional_indicator_q: ", - ['R'] = ":regional_indicator_r: ", - ['S'] = ":regional_indicator_s: ", - ['T'] = ":regional_indicator_t: ", - ['U'] = ":regional_indicator_u: ", - ['V'] = ":regional_indicator_v: ", - ['W'] = ":regional_indicator_w: ", - ['X'] = ":regional_indicator_x: ", - ['Y'] = ":regional_indicator_y: ", - ['Z'] = ":regional_indicator_z: ", - ['!'] = ":exclamation: ", - ['?'] = ":question: ", - ['#'] = ":hash: ", - ['*'] = ":star2: ", - ['+'] = ":heavy_plus_sign: ", - ['0'] = ":zero: ", - ['1'] = ":one: ", - ['2'] = ":two: ", - ['3'] = ":three: ", - ['4'] = ":four: ", - ['5'] = ":five: ", - ['6'] = ":six: ", - ['7'] = ":seven: ", - ['8'] = ":eight: ", - ['9'] = ":nine: ", - [' '] = " " - }; var letters = text.ToUpper().ToCharArray(); var returnString = new StringBuilder(); foreach (var n in letters) { - var emoji = emojiMap[n] ?? n; + var emoji = TextEmojiMap[n] ?? n; + returnString.Append(emoji); + } + return returnString.ToString(); + } + + private readonly Hashtable RegionalIndicatorMap = new Hashtable() + { + ['A'] = new Rune(0x1F1E6), + ['B'] = new Rune(0x1F1E7), + ['C'] = new Rune(0x1F1E8), + ['D'] = new Rune(0x1F1E9), + ['E'] = new Rune(0x1F1EA), + ['F'] = new Rune(0x1F1EB), + ['G'] = new Rune(0x1F1EC), + ['H'] = new Rune(0x1F1ED), + ['I'] = new Rune(0x1F1EE), + ['J'] = new Rune(0x1F1EF), + ['K'] = new Rune(0x1F1F0), + ['L'] = new Rune(0x1F1F1), + ['M'] = new Rune(0x1F1F2), + ['N'] = new Rune(0x1F1F3), + ['O'] = new Rune(0x1F1F4), + ['P'] = new Rune(0x1F1F5), + ['Q'] = new Rune(0x1F1F6), + ['R'] = new Rune(0x1F1F7), + ['S'] = new Rune(0x1F1F8), + ['T'] = new Rune(0x1F1F9), + ['U'] = new Rune(0x1F1FA), + ['V'] = new Rune(0x1F1FB), + ['W'] = new Rune(0x1F1FC), + ['X'] = new Rune(0x1F1FD), + ['Y'] = new Rune(0x1F1FE), + ['Z'] = new Rune(0x1F1FF) + }; + + public string CountryCodeToEmoji(string countryCode) + { + var letters = countryCode.ToUpper().ToCharArray(); + var returnString = new StringBuilder(); + foreach (var n in letters) + { + var emoji = RegionalIndicatorMap[n]; returnString.Append(emoji); } return returnString.ToString(); diff --git a/src/Core/Converters/IEmojiConverter.cs b/src/Core/Converters/IEmojiConverter.cs index 79ca0a7..0c364ea 100644 --- a/src/Core/Converters/IEmojiConverter.cs +++ b/src/Core/Converters/IEmojiConverter.cs @@ -4,5 +4,6 @@ { string NumberToEmoji(int number); string TextToEmoji(string text); + string CountryCodeToEmoji(string countryCode); } } \ No newline at end of file From 644d877e29adda6752be60578281572ca648138b Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Mon, 25 Jan 2021 00:49:18 +0100 Subject: [PATCH 421/553] Show country flag when !corona has a country code parameter --- src/Bot/Commands/Utils/Corona/CoronaStats.cs | 17 +++++++++++++++-- src/Bot/Commands/Utils/Corona/CoronaTotalDto.cs | 1 + 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/Bot/Commands/Utils/Corona/CoronaStats.cs b/src/Bot/Commands/Utils/Corona/CoronaStats.cs index 5880030..15431d2 100644 --- a/src/Bot/Commands/Utils/Corona/CoronaStats.cs +++ b/src/Bot/Commands/Utils/Corona/CoronaStats.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.Core; +using Geekbot.Core.Converters; using Geekbot.Core.ErrorHandling; using Geekbot.Core.Extensions; @@ -13,10 +15,12 @@ namespace Geekbot.Bot.Commands.Utils.Corona public class CoronaStats : ModuleBase { private readonly IErrorHandler _errorHandler; + private readonly IEmojiConverter _emojiConverter; - public CoronaStats(IErrorHandler errorHandler) + public CoronaStats(IErrorHandler errorHandler, IEmojiConverter emojiConverter) { _errorHandler = errorHandler; + _emojiConverter = emojiConverter; } [Command("corona", RunMode = RunMode.Async)] @@ -45,11 +49,19 @@ namespace Geekbot.Bot.Commands.Utils.Corona var recoveredFormatted = summary.Recovered.ToString(numberFormat); var deathsFormatted = summary.Deaths.ToString(numberFormat); + var embedTitleBuilder = new StringBuilder(); + embedTitleBuilder.Append("Confirmed Corona Cases"); + if (!string.IsNullOrEmpty(summary.Country)) + { + embedTitleBuilder.Append(" - "); + embedTitleBuilder.Append(_emojiConverter.CountryCodeToEmoji(summary.Country)); + } + var eb = new EmbedBuilder { Author = new EmbedAuthorBuilder { - Name = "Confirmed Corona Cases", + Name = embedTitleBuilder.ToString(), IconUrl = "https://www.redcross.org/content/dam/icons/disasters/virus/Virus-1000x1000-R-Pl.png" }, Footer = new EmbedFooterBuilder @@ -103,6 +115,7 @@ namespace Geekbot.Bot.Commands.Utils.Corona return new CoronaTotalDto() { + Country = upcasedCountryCode, Cases = countryStats.Cases, Deaths = countryStats.Deaths, Recovered = countryStats.Recovered, diff --git a/src/Bot/Commands/Utils/Corona/CoronaTotalDto.cs b/src/Bot/Commands/Utils/Corona/CoronaTotalDto.cs index c135927..58e5ac9 100644 --- a/src/Bot/Commands/Utils/Corona/CoronaTotalDto.cs +++ b/src/Bot/Commands/Utils/Corona/CoronaTotalDto.cs @@ -2,6 +2,7 @@ namespace Geekbot.Bot.Commands.Utils.Corona { public record CoronaTotalDto { + public string Country { get; set; } public decimal Cases { get; set; } public decimal Deaths { get; set; } public decimal Recovered { get; set; } From eddd005d34159ab7890c2795707157d4bef5d6c4 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Mon, 25 Jan 2021 01:40:51 +0100 Subject: [PATCH 422/553] Add translations for !corona --- src/Bot/Bot.csproj | 9 ++ src/Bot/Commands/Utils/Corona/CoronaStats.cs | 21 ++-- src/Bot/Localization/Corona.Designer.cs | 117 +++++++++++++++++++ src/Bot/Localization/Corona.de-ch.resx | 32 +++++ src/Bot/Localization/Corona.resx | 39 +++++++ 5 files changed, 207 insertions(+), 11 deletions(-) create mode 100644 src/Bot/Localization/Corona.Designer.cs create mode 100644 src/Bot/Localization/Corona.de-ch.resx create mode 100644 src/Bot/Localization/Corona.resx diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index ec32e8f..6c6f56f 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -84,6 +84,10 @@ ResXFileCodeGenerator Stats.Designer.cs + + ResXFileCodeGenerator + Corona.Designer.cs +
@@ -144,5 +148,10 @@ True Stats.resx + + True + True + Corona.resx +
diff --git a/src/Bot/Commands/Utils/Corona/CoronaStats.cs b/src/Bot/Commands/Utils/Corona/CoronaStats.cs index 15431d2..e39be0a 100644 --- a/src/Bot/Commands/Utils/Corona/CoronaStats.cs +++ b/src/Bot/Commands/Utils/Corona/CoronaStats.cs @@ -9,17 +9,16 @@ using Geekbot.Core; using Geekbot.Core.Converters; using Geekbot.Core.ErrorHandling; using Geekbot.Core.Extensions; +using Geekbot.Core.GuildSettingsManager; namespace Geekbot.Bot.Commands.Utils.Corona { - public class CoronaStats : ModuleBase + public class CoronaStats : GeekbotCommandBase { - private readonly IErrorHandler _errorHandler; private readonly IEmojiConverter _emojiConverter; - public CoronaStats(IErrorHandler errorHandler, IEmojiConverter emojiConverter) + public CoronaStats(IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager, IEmojiConverter emojiConverter) : base(errorHandler, guildSettingsManager) { - _errorHandler = errorHandler; _emojiConverter = emojiConverter; } @@ -50,7 +49,7 @@ namespace Geekbot.Bot.Commands.Utils.Corona var deathsFormatted = summary.Deaths.ToString(numberFormat); var embedTitleBuilder = new StringBuilder(); - embedTitleBuilder.Append("Confirmed Corona Cases"); + embedTitleBuilder.Append(Localization.Corona.ConfirmedCases); if (!string.IsNullOrEmpty(summary.Country)) { embedTitleBuilder.Append(" - "); @@ -66,20 +65,20 @@ namespace Geekbot.Bot.Commands.Utils.Corona }, Footer = new EmbedFooterBuilder { - Text = "Source: covid19-api.org", + Text = $"{Localization.Corona.Source}: covid19-api.org", }, Color = Color.Red }; - eb.AddField("Total", totalFormatted); - eb.AddInlineField("Active", $"{activeFormatted} ({activePercent})"); - eb.AddInlineField("Recovered", $"{recoveredFormatted} ({recoveredPercentage})"); - eb.AddInlineField("Deaths", $"{deathsFormatted} ({deathsPercentage})"); + eb.AddField(Localization.Corona.Total, totalFormatted); + eb.AddInlineField(Localization.Corona.Active, $"{activeFormatted} ({activePercent})"); + eb.AddInlineField(Localization.Corona.Recovered, $"{recoveredFormatted} ({recoveredPercentage})"); + eb.AddInlineField(Localization.Corona.Deaths, $"{deathsFormatted} ({deathsPercentage})"); await Context.Channel.SendMessageAsync(String.Empty, false, eb.Build()); } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } diff --git a/src/Bot/Localization/Corona.Designer.cs b/src/Bot/Localization/Corona.Designer.cs new file mode 100644 index 0000000..b243bfc --- /dev/null +++ b/src/Bot/Localization/Corona.Designer.cs @@ -0,0 +1,117 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Geekbot.Bot.Localization { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Corona { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Corona() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Geekbot.Bot.Localization.Corona", typeof(Corona).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Active. + /// + internal static string Active { + get { + return ResourceManager.GetString("Active", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Confirmed Corona Cases. + /// + internal static string ConfirmedCases { + get { + return ResourceManager.GetString("ConfirmedCases", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Deaths. + /// + internal static string Deaths { + get { + return ResourceManager.GetString("Deaths", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Recovered. + /// + internal static string Recovered { + get { + return ResourceManager.GetString("Recovered", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Source. + /// + internal static string Source { + get { + return ResourceManager.GetString("Source", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Total. + /// + internal static string Total { + get { + return ResourceManager.GetString("Total", resourceCulture); + } + } + } +} diff --git a/src/Bot/Localization/Corona.de-ch.resx b/src/Bot/Localization/Corona.de-ch.resx new file mode 100644 index 0000000..3c4180c --- /dev/null +++ b/src/Bot/Localization/Corona.de-ch.resx @@ -0,0 +1,32 @@ + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bstätigti Corona Fallzahle + + + Total + + + Aktiv + + + Erholt + + + Gstorbe + + + Quelle + + \ No newline at end of file diff --git a/src/Bot/Localization/Corona.resx b/src/Bot/Localization/Corona.resx new file mode 100644 index 0000000..44bf85e --- /dev/null +++ b/src/Bot/Localization/Corona.resx @@ -0,0 +1,39 @@ + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Confirmed Corona Cases + + + Total + + + Active + + + Recovered + + + Deaths + + + Source + + \ No newline at end of file From c1b8394e1b092d9d7b459f2969cad5ebb21e1b24 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Thu, 18 Mar 2021 12:06:41 +0100 Subject: [PATCH 423/553] Add a !neutral command for karma, it does nothing. --- src/Bot/Commands/User/Karma.cs | 41 ++++++++++++++++++++++++++ src/Bot/Localization/Karma.Designer.cs | 9 ++++++ src/Bot/Localization/Karma.de-ch.resx | 3 ++ src/Bot/Localization/Karma.resx | 3 ++ 4 files changed, 56 insertions(+) diff --git a/src/Bot/Commands/User/Karma.cs b/src/Bot/Commands/User/Karma.cs index 4778bce..3ba8650 100644 --- a/src/Bot/Commands/User/Karma.cs +++ b/src/Bot/Commands/User/Karma.cs @@ -115,6 +115,47 @@ namespace Geekbot.Bot.Commands.User await ErrorHandler.HandleCommandException(e, Context); } } + + [Command("neutral", RunMode = RunMode.Async)] + [Summary("Do nothing to someones karma")] + public async Task Neutral([Summary("@someone")] IUser user) + { + try + { + var actor = await GetUser(Context.User.Id); + if (user.Id == Context.User.Id) + { + await ReplyAsync(string.Format(Localization.Karma.CannotChangeOwnDown, Context.User.Username)); + return; + } + + if (TimeoutFinished(actor.TimeOut)) + { + var formatedWaitTime = DateLocalization.FormatDateTimeAsRemaining(actor.TimeOut.AddMinutes(3)); + await ReplyAsync(string.Format(Localization.Karma.WaitUntill, Context.User.Username, formatedWaitTime)); + return; + } + + var target = await GetUser(user.Id); + + var eb = new EmbedBuilder(); + eb.WithAuthor(new EmbedAuthorBuilder() + .WithIconUrl(user.GetAvatarUrl()) + .WithName(user.Username)); + + eb.WithColor(new Color(138, 219, 146)); + eb.Title = Localization.Karma.Neutral; + eb.AddInlineField(Localization.Karma.By, Context.User.Username); + eb.AddInlineField(Localization.Karma.Amount, "0"); + eb.AddInlineField(Localization.Karma.Current, target.Karma); + await ReplyAsync("", false, eb.Build()); + + } + catch (Exception e) + { + await ErrorHandler.HandleCommandException(e, Context); + } + } private bool TimeoutFinished(DateTimeOffset lastKarma) { diff --git a/src/Bot/Localization/Karma.Designer.cs b/src/Bot/Localization/Karma.Designer.cs index 4191fa2..71cab3b 100644 --- a/src/Bot/Localization/Karma.Designer.cs +++ b/src/Bot/Localization/Karma.Designer.cs @@ -123,6 +123,15 @@ namespace Geekbot.Bot.Localization { } } + /// + /// Looks up a localized string similar to Neutral Karma. + /// + internal static string Neutral { + get { + return ResourceManager.GetString("Neutral", resourceCulture); + } + } + /// /// Looks up a localized string similar to Sorry {0}, but you have to wait {1} before you can give karma again.... /// diff --git a/src/Bot/Localization/Karma.de-ch.resx b/src/Bot/Localization/Karma.de-ch.resx index 5605f8b..7b739b7 100644 --- a/src/Bot/Localization/Karma.de-ch.resx +++ b/src/Bot/Localization/Karma.de-ch.resx @@ -35,4 +35,7 @@ Karma gsenkt + + Neutral Karma + \ No newline at end of file diff --git a/src/Bot/Localization/Karma.resx b/src/Bot/Localization/Karma.resx index 3a8fe5a..2ebea1d 100644 --- a/src/Bot/Localization/Karma.resx +++ b/src/Bot/Localization/Karma.resx @@ -42,4 +42,7 @@ Karma lowered + + Neutral Karma + \ No newline at end of file From 6c142f41d3b16582cd5bcaa4dd871ca522b43698 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Thu, 18 Mar 2021 12:23:18 +0100 Subject: [PATCH 424/553] Upgrade discord.net --- src/Core/Core.csproj | 2 +- src/Core/Polyfills/UserPolyfillDto.cs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 780d0e2..0a4e989 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/Core/Polyfills/UserPolyfillDto.cs b/src/Core/Polyfills/UserPolyfillDto.cs index 1d3a54b..385a30d 100644 --- a/src/Core/Polyfills/UserPolyfillDto.cs +++ b/src/Core/Polyfills/UserPolyfillDto.cs @@ -13,6 +13,7 @@ namespace Geekbot.Core.Polyfills public IActivity Activity { get; } public UserStatus Status { get; set; } public IImmutableSet ActiveClients { get; } + public IImmutableList Activities { get; } public string AvatarId { get; set; } public string AvatarUrl { get; set; } public string Discriminator { get; set; } @@ -20,7 +21,8 @@ namespace Geekbot.Core.Polyfills public bool IsBot { get; set; } public bool IsWebhook { get; set; } public string Username { get; set; } - + public UserProperties? PublicFlags { get; } + public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) { return AvatarUrl ?? "https://discordapp.com/assets/6debd47ed13483642cf09e832ed0bc1b.png"; From c77b501b6c6d6fd3492a881686fca4c801311921 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Thu, 18 Mar 2021 12:27:26 +0100 Subject: [PATCH 425/553] Fix message sent when user is trying give themselves !neutral karma --- src/Bot/Commands/User/Karma.cs | 2 +- src/Bot/Localization/Karma.Designer.cs | 9 +++++++++ src/Bot/Localization/Karma.de-ch.resx | 3 +++ src/Bot/Localization/Karma.resx | 3 +++ 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Bot/Commands/User/Karma.cs b/src/Bot/Commands/User/Karma.cs index 3ba8650..61e381e 100644 --- a/src/Bot/Commands/User/Karma.cs +++ b/src/Bot/Commands/User/Karma.cs @@ -125,7 +125,7 @@ namespace Geekbot.Bot.Commands.User var actor = await GetUser(Context.User.Id); if (user.Id == Context.User.Id) { - await ReplyAsync(string.Format(Localization.Karma.CannotChangeOwnDown, Context.User.Username)); + await ReplyAsync(string.Format(Localization.Karma.CannotChangeOwnSame, Context.User.Username)); return; } diff --git a/src/Bot/Localization/Karma.Designer.cs b/src/Bot/Localization/Karma.Designer.cs index 71cab3b..041fec4 100644 --- a/src/Bot/Localization/Karma.Designer.cs +++ b/src/Bot/Localization/Karma.Designer.cs @@ -87,6 +87,15 @@ namespace Geekbot.Bot.Localization { } } + /// + /// Looks up a localized string similar to Sorry {0}, but you can't give yourself neutral karma. + /// + internal static string CannotChangeOwnSame { + get { + return ResourceManager.GetString("CannotChangeOwnSame", resourceCulture); + } + } + /// /// Looks up a localized string similar to Sorry {0}, but you can't give yourself karma. /// diff --git a/src/Bot/Localization/Karma.de-ch.resx b/src/Bot/Localization/Karma.de-ch.resx index 7b739b7..5805a27 100644 --- a/src/Bot/Localization/Karma.de-ch.resx +++ b/src/Bot/Localization/Karma.de-ch.resx @@ -38,4 +38,7 @@ Neutral Karma + + Sorry {0}, aber du chasch dr selber kei neutrals karma geh + \ No newline at end of file diff --git a/src/Bot/Localization/Karma.resx b/src/Bot/Localization/Karma.resx index 2ebea1d..a16e14a 100644 --- a/src/Bot/Localization/Karma.resx +++ b/src/Bot/Localization/Karma.resx @@ -45,4 +45,7 @@ Neutral Karma + + Sorry {0}, but you can't give yourself neutral karma + \ No newline at end of file From d1d57ba7144e497c9fcf7991060e7bfcee6d5d6c Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Thu, 18 Mar 2021 23:53:56 +0100 Subject: [PATCH 426/553] Refactor karma commands --- src/Bot/Commands/User/Karma.cs | 190 --------------------- src/Bot/Commands/User/Karma/Karma.cs | 137 +++++++++++++++ src/Bot/Commands/User/Karma/KarmaChange.cs | 9 + 3 files changed, 146 insertions(+), 190 deletions(-) delete mode 100644 src/Bot/Commands/User/Karma.cs create mode 100644 src/Bot/Commands/User/Karma/Karma.cs create mode 100644 src/Bot/Commands/User/Karma/KarmaChange.cs diff --git a/src/Bot/Commands/User/Karma.cs b/src/Bot/Commands/User/Karma.cs deleted file mode 100644 index 61e381e..0000000 --- a/src/Bot/Commands/User/Karma.cs +++ /dev/null @@ -1,190 +0,0 @@ -using System; -using System.Linq; -using System.Threading.Tasks; -using Discord; -using Discord.Commands; -using Geekbot.Bot.Utils; -using Geekbot.Core; -using Geekbot.Core.CommandPreconditions; -using Geekbot.Core.Database; -using Geekbot.Core.Database.Models; -using Geekbot.Core.ErrorHandling; -using Geekbot.Core.Extensions; -using Geekbot.Core.GuildSettingsManager; - -namespace Geekbot.Bot.Commands.User -{ - [DisableInDirectMessage] - public class Karma : GeekbotCommandBase - { - private readonly DatabaseContext _database; - - public Karma(DatabaseContext database, IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager) : base(errorHandler, guildSettingsManager) - { - _database = database; - } - - [Command("good", RunMode = RunMode.Async)] - [Summary("Increase Someones Karma")] - public async Task Good([Summary("@someone")] IUser user) - { - try - { - var actor = await GetUser(Context.User.Id); - if (user.Id == Context.User.Id) - { - await ReplyAsync(string.Format(Localization.Karma.CannotChangeOwnUp, Context.User.Username)); - } - else if (TimeoutFinished(actor.TimeOut)) - { - var formatedWaitTime = DateLocalization.FormatDateTimeAsRemaining(actor.TimeOut.AddMinutes(3)); - await ReplyAsync(string.Format(Localization.Karma.WaitUntill, Context.User.Username, formatedWaitTime)); - } - else - { - var target = await GetUser(user.Id); - target.Karma += 1; - SetUser(target); - - actor.TimeOut = DateTimeOffset.Now; - SetUser(actor); - - await _database.SaveChangesAsync(); - - var eb = new EmbedBuilder(); - eb.WithAuthor(new EmbedAuthorBuilder() - .WithIconUrl(user.GetAvatarUrl()) - .WithName(user.Username)); - - eb.WithColor(new Color(138, 219, 146)); - eb.Title = Localization.Karma.Increased; - eb.AddInlineField(Localization.Karma.By, Context.User.Username); - eb.AddInlineField(Localization.Karma.Amount, "+1"); - eb.AddInlineField(Localization.Karma.Current, target.Karma); - await ReplyAsync("", false, eb.Build()); - } - } - catch (Exception e) - { - await ErrorHandler.HandleCommandException(e, Context); - } - } - - [Command("bad", RunMode = RunMode.Async)] - [Summary("Decrease Someones Karma")] - public async Task Bad([Summary("@someone")] IUser user) - { - try - { - var actor = await GetUser(Context.User.Id); - if (user.Id == Context.User.Id) - { - await ReplyAsync(string.Format(Localization.Karma.CannotChangeOwnDown, Context.User.Username)); - } - else if (TimeoutFinished(actor.TimeOut)) - { - var formatedWaitTime = DateLocalization.FormatDateTimeAsRemaining(actor.TimeOut.AddMinutes(3)); - await ReplyAsync(string.Format(Localization.Karma.WaitUntill, Context.User.Username, formatedWaitTime)); - } - else - { - var target = await GetUser(user.Id); - target.Karma -= 1; - SetUser(target); - - actor.TimeOut = DateTimeOffset.Now; - SetUser(actor); - - await _database.SaveChangesAsync(); - - var eb = new EmbedBuilder(); - eb.WithAuthor(new EmbedAuthorBuilder() - .WithIconUrl(user.GetAvatarUrl()) - .WithName(user.Username)); - - eb.WithColor(new Color(138, 219, 146)); - eb.Title = Localization.Karma.Decreased; - eb.AddInlineField(Localization.Karma.By, Context.User.Username); - eb.AddInlineField(Localization.Karma.Amount, "-1"); - eb.AddInlineField(Localization.Karma.Current, target.Karma); - await ReplyAsync("", false, eb.Build()); - } - } - catch (Exception e) - { - await ErrorHandler.HandleCommandException(e, Context); - } - } - - [Command("neutral", RunMode = RunMode.Async)] - [Summary("Do nothing to someones karma")] - public async Task Neutral([Summary("@someone")] IUser user) - { - try - { - var actor = await GetUser(Context.User.Id); - if (user.Id == Context.User.Id) - { - await ReplyAsync(string.Format(Localization.Karma.CannotChangeOwnSame, Context.User.Username)); - return; - } - - if (TimeoutFinished(actor.TimeOut)) - { - var formatedWaitTime = DateLocalization.FormatDateTimeAsRemaining(actor.TimeOut.AddMinutes(3)); - await ReplyAsync(string.Format(Localization.Karma.WaitUntill, Context.User.Username, formatedWaitTime)); - return; - } - - var target = await GetUser(user.Id); - - var eb = new EmbedBuilder(); - eb.WithAuthor(new EmbedAuthorBuilder() - .WithIconUrl(user.GetAvatarUrl()) - .WithName(user.Username)); - - eb.WithColor(new Color(138, 219, 146)); - eb.Title = Localization.Karma.Neutral; - eb.AddInlineField(Localization.Karma.By, Context.User.Username); - eb.AddInlineField(Localization.Karma.Amount, "0"); - eb.AddInlineField(Localization.Karma.Current, target.Karma); - await ReplyAsync("", false, eb.Build()); - - } - catch (Exception e) - { - await ErrorHandler.HandleCommandException(e, Context); - } - } - - private bool TimeoutFinished(DateTimeOffset lastKarma) - { - return lastKarma.AddMinutes(3) > DateTimeOffset.Now; - } - - private async Task GetUser(ulong userId) - { - var user = _database.Karma.FirstOrDefault(u =>u.GuildId.Equals(Context.Guild.Id.AsLong()) && u.UserId.Equals(userId.AsLong())) ?? await CreateNewRow(userId); - return user; - } - - private void SetUser(KarmaModel user) - { - _database.Karma.Update(user); - } - - private async Task CreateNewRow(ulong userId) - { - var user = new KarmaModel() - { - GuildId = Context.Guild.Id.AsLong(), - UserId = userId.AsLong(), - Karma = 0, - TimeOut = DateTimeOffset.MinValue - }; - var newUser = _database.Karma.Add(user).Entity; - await _database.SaveChangesAsync(); - return newUser; - } - } -} \ No newline at end of file diff --git a/src/Bot/Commands/User/Karma/Karma.cs b/src/Bot/Commands/User/Karma/Karma.cs new file mode 100644 index 0000000..a248422 --- /dev/null +++ b/src/Bot/Commands/User/Karma/Karma.cs @@ -0,0 +1,137 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Geekbot.Bot.Utils; +using Geekbot.Core; +using Geekbot.Core.CommandPreconditions; +using Geekbot.Core.Database; +using Geekbot.Core.Database.Models; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.Extensions; +using Geekbot.Core.GuildSettingsManager; + +namespace Geekbot.Bot.Commands.User.Karma +{ + [DisableInDirectMessage] + public class Karma : GeekbotCommandBase + { + private readonly DatabaseContext _database; + + public Karma(DatabaseContext database, IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager) : base(errorHandler, guildSettingsManager) + { + _database = database; + } + + [Command("good", RunMode = RunMode.Async)] + [Summary("Increase Someones Karma")] + public async Task Good([Summary("@someone")] IUser user) + { + await ChangeKarma(user, KarmaChange.Up); + } + + [Command("bad", RunMode = RunMode.Async)] + [Summary("Decrease Someones Karma")] + public async Task Bad([Summary("@someone")] IUser user) + { + await ChangeKarma(user, KarmaChange.Down); + } + + [Command("neutral", RunMode = RunMode.Async)] + [Summary("Do nothing to someones Karma")] + public async Task Neutral([Summary("@someone")] IUser user) + { + await ChangeKarma(user, KarmaChange.Same); + } + + private async Task ChangeKarma(IUser user, KarmaChange change) + { + try + { + // Get the user + var actor = await GetUser(Context.User.Id); + + // Check if the user can change karma + if (user.Id == Context.User.Id) + { + var message = change switch + { + KarmaChange.Up => Localization.Karma.CannotChangeOwnUp, + KarmaChange.Same => Localization.Karma.CannotChangeOwnSame, + KarmaChange.Down => Localization.Karma.CannotChangeOwnDown, + _ => throw new ArgumentOutOfRangeException(nameof(change), change, null) + }; + await ReplyAsync(string.Format(message, Context.User.Username)); + return; + } + + if (actor.TimeOut.AddMinutes(3) > DateTimeOffset.Now) + { + var formatedWaitTime = DateLocalization.FormatDateTimeAsRemaining(actor.TimeOut.AddMinutes(3)); + await ReplyAsync(string.Format(Localization.Karma.WaitUntill, Context.User.Username, formatedWaitTime)); + return; + } + + // Get the values for the change direction + var (title, amount) = change switch + { + KarmaChange.Up => (Localization.Karma.Increased, 1), + KarmaChange.Same => (Localization.Karma.Neutral, 0), + KarmaChange.Down => (Localization.Karma.Decreased, -1), + _ => throw new ArgumentOutOfRangeException(nameof(change), change, null) + }; + + // Change it + var target = await GetUser(user.Id); + target.Karma += amount; + _database.Karma.Update(target); + + actor.TimeOut = DateTimeOffset.Now; + _database.Karma.Update(actor); + + await _database.SaveChangesAsync(); + + // Respond + var eb = new EmbedBuilder() + { + Author = new EmbedAuthorBuilder() + { + Name = user.Username, + IconUrl = user.GetAvatarUrl() + }, + Title = title, + Color = new Color(138, 219, 146) + }; + eb.AddInlineField(Localization.Karma.By, Context.User.Username); + eb.AddInlineField(Localization.Karma.Amount, amount.ToString()); + eb.AddInlineField(Localization.Karma.Current, target.Karma.ToString()); + await ReplyAsync("", false, eb.Build()); + } + catch (Exception e) + { + await ErrorHandler.HandleCommandException(e, Context); + } + } + + private async Task GetUser(ulong userId) + { + var user = _database.Karma.FirstOrDefault(u => u.GuildId.Equals(Context.Guild.Id.AsLong()) && u.UserId.Equals(userId.AsLong())) ?? await CreateNewRow(userId); + return user; + } + + private async Task CreateNewRow(ulong userId) + { + var user = new KarmaModel() + { + GuildId = Context.Guild.Id.AsLong(), + UserId = userId.AsLong(), + Karma = 0, + TimeOut = DateTimeOffset.MinValue + }; + var newUser = _database.Karma.Add(user).Entity; + await _database.SaveChangesAsync(); + return newUser; + } + } +} \ No newline at end of file diff --git a/src/Bot/Commands/User/Karma/KarmaChange.cs b/src/Bot/Commands/User/Karma/KarmaChange.cs new file mode 100644 index 0000000..01dafc1 --- /dev/null +++ b/src/Bot/Commands/User/Karma/KarmaChange.cs @@ -0,0 +1,9 @@ +namespace Geekbot.Bot.Commands.User.Karma +{ + public enum KarmaChange + { + Up, + Same, + Down + } +} \ No newline at end of file From 1c643285874df4a92b633cf3dd2c63a2559084f5 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 19 Mar 2021 00:21:35 +0100 Subject: [PATCH 427/553] Upgrade to .net6 preview --- .gitlab-ci.yml | 2 +- Dockerfile | 2 +- src/Bot/Bot.csproj | 2 +- src/Bot/Commands/Utils/Quote/Quote.cs | 1 + src/Core/Core.csproj | 26 ++++++++++++++++---------- src/Web/Web.csproj | 2 +- tests/Tests.csproj | 6 +++--- 7 files changed, 24 insertions(+), 17 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 20b1c84..967def1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,7 +10,7 @@ variables: Build: stage: build - image: mcr.microsoft.com/dotnet/sdk:5.0 + image: mcr.microsoft.com/dotnet/sdk:6.0 artifacts: expire_in: 1h paths: diff --git a/Dockerfile b/Dockerfile index 245e06b..39529ff 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/aspnet:5.0 +FROM mcr.microsoft.com/dotnet/aspnet:6.0 COPY ./app /app/ diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index 6c6f56f..86ab9a3 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -1,7 +1,7 @@ Exe - net5.0 + net6.0 win-x64;linux-x64 derp.ico $(VersionSuffix) diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index 6a94309..e79663c 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -14,6 +14,7 @@ using Geekbot.Core.GuildSettingsManager; using Geekbot.Core.Polyfills; using Geekbot.Core.RandomNumberGenerator; using Geekbot.Core.UserRepository; +using Microsoft.EntityFrameworkCore; namespace Geekbot.Bot.Commands.Utils.Quote { diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 0a4e989..474478e 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 $(VersionSuffix) $(VersionSuffix) 0.0.0-DEV @@ -14,18 +14,24 @@ - - - - - - - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + - + diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index 5080a3d..744cadf 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 $(VersionSuffix) $(VersionSuffix) 0.0.0-DEV diff --git a/tests/Tests.csproj b/tests/Tests.csproj index 75a5f9c..6b9b84f 100644 --- a/tests/Tests.csproj +++ b/tests/Tests.csproj @@ -1,13 +1,13 @@  - net5.0 + net6.0 false NU1701 xUnit1026 - - + + From f25c9250ec109485e05f366f32fb18f5f9c2b309 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 19 Mar 2021 01:10:22 +0100 Subject: [PATCH 428/553] Switch to an alpine container and single file, self-contained deployments --- .gitlab-ci.yml | 2 +- Dockerfile | 2 +- src/Bot/Bot.csproj | 2 +- src/Core/Core.csproj | 1 + src/Web/Web.csproj | 1 + tests/Tests.csproj | 1 + 6 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 967def1..f92ba14 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,7 +18,7 @@ Build: script: - dotnet restore - dotnet test tests - - dotnet publish --version-suffix "$VERSION" -r linux-x64 -c Release -o ./app ./src/Bot/ + - dotnet publish --version-suffix "$VERSION" -r linux-musl-x64 -p:PublishSingleFile=true --self-contained true -c Release -o ./app ./src/Bot/ Package: stage: docker diff --git a/Dockerfile b/Dockerfile index 39529ff..6e81339 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/aspnet:6.0 +FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine COPY ./app /app/ diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index 86ab9a3..9312ac1 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -2,7 +2,7 @@ Exe net6.0 - win-x64;linux-x64 + win10-x64;linux-x64;linux-musl-x64 derp.ico $(VersionSuffix) Geekbot.Bot diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 474478e..17b4a26 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -2,6 +2,7 @@ net6.0 + win10-x64;linux-x64;linux-musl-x64 $(VersionSuffix) $(VersionSuffix) 0.0.0-DEV diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index 744cadf..d57c63c 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -2,6 +2,7 @@ net6.0 + win10-x64;linux-x64;linux-musl-x64 $(VersionSuffix) $(VersionSuffix) 0.0.0-DEV diff --git a/tests/Tests.csproj b/tests/Tests.csproj index 6b9b84f..4823e0b 100644 --- a/tests/Tests.csproj +++ b/tests/Tests.csproj @@ -1,6 +1,7 @@  net6.0 + win10-x64;linux-x64;linux-musl-x64 false NU1701 xUnit1026 From 52fe5bdec11dc2327f4703e83bd1b6eb7ff2c646 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Sat, 20 Mar 2021 04:06:10 +0100 Subject: [PATCH 429/553] Switch back to a debian container, alpine is missing locale info --- .gitlab-ci.yml | 2 +- Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f92ba14..b0135b6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,7 +18,7 @@ Build: script: - dotnet restore - dotnet test tests - - dotnet publish --version-suffix "$VERSION" -r linux-musl-x64 -p:PublishSingleFile=true --self-contained true -c Release -o ./app ./src/Bot/ + - dotnet publish --version-suffix "$VERSION" -r linux-x64 -p:PublishSingleFile=true --self-contained true -c Release -o ./app ./src/Bot/ Package: stage: docker diff --git a/Dockerfile b/Dockerfile index 6e81339..39529ff 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine +FROM mcr.microsoft.com/dotnet/aspnet:6.0 COPY ./app /app/ From 49870b6b91da13fdb7ec3b9b4a53696eafc2e058 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Sat, 20 Mar 2021 04:17:14 +0100 Subject: [PATCH 430/553] Stop using single-file deployments due to missing locale data --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b0135b6..967def1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,7 +18,7 @@ Build: script: - dotnet restore - dotnet test tests - - dotnet publish --version-suffix "$VERSION" -r linux-x64 -p:PublishSingleFile=true --self-contained true -c Release -o ./app ./src/Bot/ + - dotnet publish --version-suffix "$VERSION" -r linux-x64 -c Release -o ./app ./src/Bot/ Package: stage: docker From 41e0a9f8d72c24766019a4e7844337cab62ce281 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 26 Mar 2021 00:11:15 +0100 Subject: [PATCH 431/553] Add !evergiven to see if the ship is still stuck in the suez canal --- src/Bot/Bot.csproj | 9 +++ src/Bot/Commands/Utils/Evergiven.cs | 50 +++++++++++++ src/Bot/Localization/Evergiven.Designer.cs | 81 ++++++++++++++++++++++ src/Bot/Localization/Evergiven.de-ch.resx | 20 ++++++ src/Bot/Localization/Evergiven.resx | 27 ++++++++ src/Bot/Utils/DateLocalization.cs | 6 +- 6 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 src/Bot/Commands/Utils/Evergiven.cs create mode 100644 src/Bot/Localization/Evergiven.Designer.cs create mode 100644 src/Bot/Localization/Evergiven.de-ch.resx create mode 100644 src/Bot/Localization/Evergiven.resx diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index 9312ac1..2b1cdae 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -88,6 +88,10 @@ ResXFileCodeGenerator Corona.Designer.cs + + ResXFileCodeGenerator + Evergiven.Designer.cs + @@ -153,5 +157,10 @@ True Corona.resx + + True + True + Evergiven.resx + diff --git a/src/Bot/Commands/Utils/Evergiven.cs b/src/Bot/Commands/Utils/Evergiven.cs new file mode 100644 index 0000000..663fb0a --- /dev/null +++ b/src/Bot/Commands/Utils/Evergiven.cs @@ -0,0 +1,50 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Discord.Commands; +using Geekbot.Bot.Utils; +using Geekbot.Core; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.GuildSettingsManager; +using HtmlAgilityPack; + +namespace Geekbot.Bot.Commands.Utils +{ + public class Evergiven : GeekbotCommandBase + { + public Evergiven(IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager) : base(errorHandler, guildSettingsManager) + { + } + + [Command("evergiven", RunMode = RunMode.Async)] + [Summary("Check if the evergiven ship is still stuck in the suez canal")] + public async Task GetStatus() + { + try + { + var httpClient = HttpAbstractions.CreateDefaultClient(); + var response = await httpClient.GetAsync("https://istheshipstillstuck.com/"); + response.EnsureSuccessStatusCode(); + var stringResponse = await response.Content.ReadAsStringAsync(); + + var doc = new HtmlDocument(); + doc.LoadHtml(stringResponse); + var yesOrNoNode = doc.DocumentNode.SelectNodes("//a").FirstOrDefault(); + + if (yesOrNoNode?.InnerHtml == "Yes.") + { + var stuckSince = DateTime.Now - new DateTime(2021, 03, 23, 10, 39, 0); + var formatted = DateLocalization.FormatDateTimeAsRemaining(stuckSince); + await ReplyAsync(string.Format(Localization.Evergiven.StillStuck, formatted));// $"Ever Given is **still stuck** in the suez canal! It has been stuck for {formatted}"); + return; + } + + await ReplyAsync(Localization.Evergiven.NotStuckAnymore); + } + catch (Exception e) + { + await ErrorHandler.HandleCommandException(e, Context); + } + } + } +} \ No newline at end of file diff --git a/src/Bot/Localization/Evergiven.Designer.cs b/src/Bot/Localization/Evergiven.Designer.cs new file mode 100644 index 0000000..7f66fed --- /dev/null +++ b/src/Bot/Localization/Evergiven.Designer.cs @@ -0,0 +1,81 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Geekbot.Bot.Localization { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Evergiven { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Evergiven() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Geekbot.Bot.Localization.Evergiven", typeof(Evergiven).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Seems like Ever Given has moved on, check https://istheshipstillstuck.com/. + /// + internal static string NotStuckAnymore { + get { + return ResourceManager.GetString("NotStuckAnymore", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ever Given is **still stuck** in the suez canal! It has been stuck for {0}. + /// + internal static string StillStuck { + get { + return ResourceManager.GetString("StillStuck", resourceCulture); + } + } + } +} diff --git a/src/Bot/Localization/Evergiven.de-ch.resx b/src/Bot/Localization/Evergiven.de-ch.resx new file mode 100644 index 0000000..b1563fc --- /dev/null +++ b/src/Bot/Localization/Evergiven.de-ch.resx @@ -0,0 +1,20 @@ + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Ever Given **steckt immer no fescht** im Suez Kanal! Es isch derte siit {0} + + + Es gseht danach us das Ever Given wiiter gange isch, gsehne https://istheshipstillstuck.com/ + + \ No newline at end of file diff --git a/src/Bot/Localization/Evergiven.resx b/src/Bot/Localization/Evergiven.resx new file mode 100644 index 0000000..36fb012 --- /dev/null +++ b/src/Bot/Localization/Evergiven.resx @@ -0,0 +1,27 @@ + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Seems like Ever Given has moved on, check https://istheshipstillstuck.com/ + + + Ever Given is **still stuck** in the suez canal! It has been stuck for {0} + + \ No newline at end of file diff --git a/src/Bot/Utils/DateLocalization.cs b/src/Bot/Utils/DateLocalization.cs index eea40fb..ee52d73 100644 --- a/src/Bot/Utils/DateLocalization.cs +++ b/src/Bot/Utils/DateLocalization.cs @@ -7,7 +7,11 @@ namespace Geekbot.Bot.Utils { public static string FormatDateTimeAsRemaining(DateTimeOffset dateTime) { - var remaining = dateTime - DateTimeOffset.Now; + return FormatDateTimeAsRemaining(dateTime - DateTimeOffset.Now); + } + + public static string FormatDateTimeAsRemaining(TimeSpan remaining) + { const string formattable = "{0} {1}"; var sb = new StringBuilder(); From 9ad39058ac71a2a1e19091dcc4d910d8fa92d70e Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Mon, 29 Mar 2021 11:39:50 +0200 Subject: [PATCH 432/553] Update the !evergiven command to directly reflect what istheshipstillstuck.com says --- src/Bot/Bot.csproj | 9 --- src/Bot/Commands/Utils/Evergiven.cs | 28 ++++++-- src/Bot/Localization/Evergiven.Designer.cs | 81 ---------------------- src/Bot/Localization/Evergiven.de-ch.resx | 20 ------ src/Bot/Localization/Evergiven.resx | 27 -------- 5 files changed, 21 insertions(+), 144 deletions(-) delete mode 100644 src/Bot/Localization/Evergiven.Designer.cs delete mode 100644 src/Bot/Localization/Evergiven.de-ch.resx delete mode 100644 src/Bot/Localization/Evergiven.resx diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index 2b1cdae..9312ac1 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -88,10 +88,6 @@ ResXFileCodeGenerator Corona.Designer.cs - - ResXFileCodeGenerator - Evergiven.Designer.cs -
@@ -157,10 +153,5 @@ True Corona.resx - - True - True - Evergiven.resx -
diff --git a/src/Bot/Commands/Utils/Evergiven.cs b/src/Bot/Commands/Utils/Evergiven.cs index 663fb0a..1115eaf 100644 --- a/src/Bot/Commands/Utils/Evergiven.cs +++ b/src/Bot/Commands/Utils/Evergiven.cs @@ -1,8 +1,9 @@ using System; using System.Linq; +using System.Text; using System.Threading.Tasks; +using System.Web; using Discord.Commands; -using Geekbot.Bot.Utils; using Geekbot.Core; using Geekbot.Core.ErrorHandling; using Geekbot.Core.GuildSettingsManager; @@ -29,17 +30,30 @@ namespace Geekbot.Bot.Commands.Utils var doc = new HtmlDocument(); doc.LoadHtml(stringResponse); - var yesOrNoNode = doc.DocumentNode.SelectNodes("//a").FirstOrDefault(); + var statusNode = doc.DocumentNode.SelectNodes("//a").FirstOrDefault(); - if (yesOrNoNode?.InnerHtml == "Yes.") + if (statusNode == null) { - var stuckSince = DateTime.Now - new DateTime(2021, 03, 23, 10, 39, 0); - var formatted = DateLocalization.FormatDateTimeAsRemaining(stuckSince); - await ReplyAsync(string.Format(Localization.Evergiven.StillStuck, formatted));// $"Ever Given is **still stuck** in the suez canal! It has been stuck for {formatted}"); + await ReplyAsync("Maybe, check "); return; } - await ReplyAsync(Localization.Evergiven.NotStuckAnymore); + var sb = new StringBuilder(); + + sb.Append($"Is that ship still stuck? {statusNode.InnerHtml}"); + if (statusNode.Attributes.Contains("href")) + { + sb.Append($" {statusNode.Attributes["href"].Value}"); + } + + var stuckTimer = doc.DocumentNode.SelectNodes("//p")?.First(node => node.Attributes.First(attr => attr.Name == "style")?.Value == "text-align:center"); + if (stuckTimer != null) + { + sb.AppendLine(); + sb.AppendLine(HttpUtility.HtmlDecode(stuckTimer.InnerText)); + } + + await ReplyAsync(sb.ToString()); } catch (Exception e) { diff --git a/src/Bot/Localization/Evergiven.Designer.cs b/src/Bot/Localization/Evergiven.Designer.cs deleted file mode 100644 index 7f66fed..0000000 --- a/src/Bot/Localization/Evergiven.Designer.cs +++ /dev/null @@ -1,81 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Geekbot.Bot.Localization { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Evergiven { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Evergiven() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Geekbot.Bot.Localization.Evergiven", typeof(Evergiven).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to Seems like Ever Given has moved on, check https://istheshipstillstuck.com/. - /// - internal static string NotStuckAnymore { - get { - return ResourceManager.GetString("NotStuckAnymore", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Ever Given is **still stuck** in the suez canal! It has been stuck for {0}. - /// - internal static string StillStuck { - get { - return ResourceManager.GetString("StillStuck", resourceCulture); - } - } - } -} diff --git a/src/Bot/Localization/Evergiven.de-ch.resx b/src/Bot/Localization/Evergiven.de-ch.resx deleted file mode 100644 index b1563fc..0000000 --- a/src/Bot/Localization/Evergiven.de-ch.resx +++ /dev/null @@ -1,20 +0,0 @@ - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Ever Given **steckt immer no fescht** im Suez Kanal! Es isch derte siit {0} - - - Es gseht danach us das Ever Given wiiter gange isch, gsehne https://istheshipstillstuck.com/ - - \ No newline at end of file diff --git a/src/Bot/Localization/Evergiven.resx b/src/Bot/Localization/Evergiven.resx deleted file mode 100644 index 36fb012..0000000 --- a/src/Bot/Localization/Evergiven.resx +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Seems like Ever Given has moved on, check https://istheshipstillstuck.com/ - - - Ever Given is **still stuck** in the suez canal! It has been stuck for {0} - - \ No newline at end of file From 5b99ee951bc6ea45a09347f5840154b7a92f0258 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Mon, 29 Mar 2021 17:45:43 +0200 Subject: [PATCH 433/553] Evergiven is free once again --- src/Bot/Commands/Utils/Evergiven.cs | 31 ++++------------------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/src/Bot/Commands/Utils/Evergiven.cs b/src/Bot/Commands/Utils/Evergiven.cs index 1115eaf..c7c4335 100644 --- a/src/Bot/Commands/Utils/Evergiven.cs +++ b/src/Bot/Commands/Utils/Evergiven.cs @@ -23,35 +23,12 @@ namespace Geekbot.Bot.Commands.Utils { try { - var httpClient = HttpAbstractions.CreateDefaultClient(); - var response = await httpClient.GetAsync("https://istheshipstillstuck.com/"); - response.EnsureSuccessStatusCode(); - var stringResponse = await response.Content.ReadAsStringAsync(); - - var doc = new HtmlDocument(); - doc.LoadHtml(stringResponse); - var statusNode = doc.DocumentNode.SelectNodes("//a").FirstOrDefault(); - - if (statusNode == null) - { - await ReplyAsync("Maybe, check "); - return; - } - var sb = new StringBuilder(); - sb.Append($"Is that ship still stuck? {statusNode.InnerHtml}"); - if (statusNode.Attributes.Contains("href")) - { - sb.Append($" {statusNode.Attributes["href"].Value}"); - } - - var stuckTimer = doc.DocumentNode.SelectNodes("//p")?.First(node => node.Attributes.First(attr => attr.Name == "style")?.Value == "text-align:center"); - if (stuckTimer != null) - { - sb.AppendLine(); - sb.AppendLine(HttpUtility.HtmlDecode(stuckTimer.InnerText)); - } + sb.AppendLine("Is that ship still stuck?"); + sb.AppendLine("**No!**"); + sb.AppendLine("It was stuck for 6 days, 3 hours and 38 minutes. It (probably) cost \"us\" $59 billion."); + sb.AppendLine("You can follow it here: "); await ReplyAsync(sb.ToString()); } From 153ce3dca4b408a32dbfbdd12bfbcfd8c02acf27 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Mon, 29 Mar 2021 19:02:31 +0200 Subject: [PATCH 434/553] Translate !8ball --- src/Bot/Bot.csproj | 9 + src/Bot/Commands/Randomness/EightBall.cs | 41 +--- src/Bot/Localization/EightBall.Designer.cs | 243 +++++++++++++++++++++ src/Bot/Localization/EightBall.de-ch.resx | 94 ++++++++ src/Bot/Localization/EightBall.resx | 200 +++++++++++++++++ 5 files changed, 558 insertions(+), 29 deletions(-) create mode 100644 src/Bot/Localization/EightBall.Designer.cs create mode 100644 src/Bot/Localization/EightBall.de-ch.resx create mode 100644 src/Bot/Localization/EightBall.resx diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index 9312ac1..cd04530 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -88,6 +88,10 @@ ResXFileCodeGenerator Corona.Designer.cs + + ResXFileCodeGenerator + EightBall.Designer.cs +
@@ -153,5 +157,10 @@ True Corona.resx + + True + True + EightBall.resx + diff --git a/src/Bot/Commands/Randomness/EightBall.cs b/src/Bot/Commands/Randomness/EightBall.cs index e1a3a71..207afe3 100644 --- a/src/Bot/Commands/Randomness/EightBall.cs +++ b/src/Bot/Commands/Randomness/EightBall.cs @@ -1,18 +1,18 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.ErrorHandling; +using Geekbot.Core.GuildSettingsManager; namespace Geekbot.Bot.Commands.Randomness { - public class EightBall : ModuleBase + public class EightBall : GeekbotCommandBase { - private readonly IErrorHandler _errorHandler; - - public EightBall(IErrorHandler errorHandler) + public EightBall(IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager) : base(errorHandler, guildSettingsManager) { - _errorHandler = errorHandler; } [Command("8ball", RunMode = RunMode.Async)] @@ -21,36 +21,19 @@ namespace Geekbot.Bot.Commands.Randomness { try { - var replies = new List + var enumerator = Localization.EightBall.ResourceManager.GetResourceSet(CultureInfo.CurrentUICulture, true, true).GetEnumerator(); + var replies = new List(); + while (enumerator.MoveNext()) { - "It is certain", - "It is decidedly so", - "Without a doubt", - "Yes, definitely", - "You may rely on it", - "As I see it, yes", - "Most likely", - "Outlook good", - "Yes", - "Signs point to yes", - "Reply hazy try again", - "Ask again later", - "Better not tell you now", - "Cannot predict now", - "Concentrate and ask again", - "Don't count on it", - "My reply is no", - "My sources say no", - "Outlook not so good", - "Very doubtful" - }; - + replies.Add(enumerator.Value?.ToString()); + } + var answer = new Random().Next(replies.Count); await ReplyAsync(replies[answer]); } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } } diff --git a/src/Bot/Localization/EightBall.Designer.cs b/src/Bot/Localization/EightBall.Designer.cs new file mode 100644 index 0000000..8214825 --- /dev/null +++ b/src/Bot/Localization/EightBall.Designer.cs @@ -0,0 +1,243 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Geekbot.Bot.Localization { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class EightBall { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal EightBall() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Geekbot.Bot.Localization.EightBall", typeof(EightBall).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to As I see it, yes. + /// + internal static string AsISeeItYes { + get { + return ResourceManager.GetString("AsISeeItYes", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ask again later. + /// + internal static string AskAgainLater { + get { + return ResourceManager.GetString("AskAgainLater", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Better not tell you now. + /// + internal static string BetterNotTellYouNow { + get { + return ResourceManager.GetString("BetterNotTellYouNow", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot predict now. + /// + internal static string CannotPredictNow { + get { + return ResourceManager.GetString("CannotPredictNow", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Concentrate and ask again. + /// + internal static string ConcentrateAndAskAgain { + get { + return ResourceManager.GetString("ConcentrateAndAskAgain", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Don't count on it. + /// + internal static string DontCountOnIt { + get { + return ResourceManager.GetString("DontCountOnIt", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to It is certain. + /// + internal static string ItIsCertain { + get { + return ResourceManager.GetString("ItIsCertain", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to It is decidedly so. + /// + internal static string ItIsDecidedlySo { + get { + return ResourceManager.GetString("ItIsDecidedlySo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Most likely. + /// + internal static string MostLikely { + get { + return ResourceManager.GetString("MostLikely", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to My reply is no. + /// + internal static string MyReplyIsNo { + get { + return ResourceManager.GetString("MyReplyIsNo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to My sources say no. + /// + internal static string MySourcesSayNo { + get { + return ResourceManager.GetString("MySourcesSayNo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Outlook good. + /// + internal static string OutlookGood { + get { + return ResourceManager.GetString("OutlookGood", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Outlook not so good. + /// + internal static string OutlookNotSoGood { + get { + return ResourceManager.GetString("OutlookNotSoGood", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reply hazy try again. + /// + internal static string ReplyHazyTryAgain { + get { + return ResourceManager.GetString("ReplyHazyTryAgain", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Signs point to yes. + /// + internal static string SignsPointToYes { + get { + return ResourceManager.GetString("SignsPointToYes", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Very doubtful. + /// + internal static string VeryDoubtful { + get { + return ResourceManager.GetString("VeryDoubtful", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Without a doubt. + /// + internal static string WithoutADoubt { + get { + return ResourceManager.GetString("WithoutADoubt", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Yes. + /// + internal static string Yes { + get { + return ResourceManager.GetString("Yes", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Yes, definitely. + /// + internal static string YesDefinitely { + get { + return ResourceManager.GetString("YesDefinitely", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You may rely on it. + /// + internal static string YouMayRelyOnIt { + get { + return ResourceManager.GetString("YouMayRelyOnIt", resourceCulture); + } + } + } +} diff --git a/src/Bot/Localization/EightBall.de-ch.resx b/src/Bot/Localization/EightBall.de-ch.resx new file mode 100644 index 0000000..89d7a60 --- /dev/null +++ b/src/Bot/Localization/EightBall.de-ch.resx @@ -0,0 +1,94 @@ + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Es isch sicher + + + + So isch es entschiede worde + + + + Ohni zwifel + + + + Ja, absolut + + + + Chasch davo usgoh + + + + Wie ich es gsehn, ja + + + + Sehr waschinli + + + + Ussicht isch guet + + + + Ja + + + + Ahzeiche zeigend uf ja + + + + Antwort isch verschwumme, versuechs nomol + + + + Frög spöter nomol + + + + Segs dir jetzt besser nid + + + + Im mommnet chani das nid vorussege + + + + Konzentrier di und frog nomol + + + + Zähl nid druf + + + + Mini antwort isch nei + + + + Mini quellene seged nei + + + + Ussicht isch ned so guet + + + + Sehr froglich + + + \ No newline at end of file diff --git a/src/Bot/Localization/EightBall.resx b/src/Bot/Localization/EightBall.resx new file mode 100644 index 0000000..6eba369 --- /dev/null +++ b/src/Bot/Localization/EightBall.resx @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + It is certain + + + + It is decidedly so + + + + Without a doubt + + + + Yes, definitely + + + + You may rely on it + + + + As I see it, yes + + + + Most likely + + + + Outlook good + + + + Yes + + + + Signs point to yes + + + + Reply hazy try again + + + + Ask again later + + + + Better not tell you now + + + + Cannot predict now + + + + Concentrate and ask again + + + + Don't count on it + + + + My reply is no + + + + My sources say no + + + + Outlook not so good + + + + Very doubtful + + + \ No newline at end of file From 8bd8efa66a70f9769ee53b2d574ba03879b9a8cb Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Wed, 7 Apr 2021 22:49:13 +0200 Subject: [PATCH 435/553] Remove the !evergiven command --- src/Bot/Commands/Utils/Evergiven.cs | 41 ----------------------------- 1 file changed, 41 deletions(-) delete mode 100644 src/Bot/Commands/Utils/Evergiven.cs diff --git a/src/Bot/Commands/Utils/Evergiven.cs b/src/Bot/Commands/Utils/Evergiven.cs deleted file mode 100644 index c7c4335..0000000 --- a/src/Bot/Commands/Utils/Evergiven.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Web; -using Discord.Commands; -using Geekbot.Core; -using Geekbot.Core.ErrorHandling; -using Geekbot.Core.GuildSettingsManager; -using HtmlAgilityPack; - -namespace Geekbot.Bot.Commands.Utils -{ - public class Evergiven : GeekbotCommandBase - { - public Evergiven(IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager) : base(errorHandler, guildSettingsManager) - { - } - - [Command("evergiven", RunMode = RunMode.Async)] - [Summary("Check if the evergiven ship is still stuck in the suez canal")] - public async Task GetStatus() - { - try - { - var sb = new StringBuilder(); - - sb.AppendLine("Is that ship still stuck?"); - sb.AppendLine("**No!**"); - sb.AppendLine("It was stuck for 6 days, 3 hours and 38 minutes. It (probably) cost \"us\" $59 billion."); - sb.AppendLine("You can follow it here: "); - - await ReplyAsync(sb.ToString()); - } - catch (Exception e) - { - await ErrorHandler.HandleCommandException(e, Context); - } - } - } -} \ No newline at end of file From 5a50ba58206e4fcfd85a2f55af909be9d7291cdb Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Tue, 20 Apr 2021 22:25:33 +0200 Subject: [PATCH 436/553] Add total quotes of a user to !stats --- src/Bot/Commands/User/Stats.cs | 7 +++++-- src/Bot/Localization/Stats.Designer.cs | 18 ++++++++++++++++++ src/Bot/Localization/Stats.de-ch.resx | 6 ++++++ src/Bot/Localization/Stats.resx | 6 ++++++ 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/Bot/Commands/User/Stats.cs b/src/Bot/Commands/User/Stats.cs index a2a54a2..aad2657 100644 --- a/src/Bot/Commands/User/Stats.cs +++ b/src/Bot/Commands/User/Stats.cs @@ -54,6 +54,8 @@ namespace Geekbot.Bot.Commands.User ?.FirstOrDefault(e => e.GuildId.Equals(Context.Guild.Id.AsLong()) && e.UserId.Equals(userInfo.Id.AsLong())) ?.Cookies ?? 0; + var quotes = _database.Quotes.Count(e => e.GuildId.Equals(Context.Guild.Id.AsLong()) && e.UserId.Equals(userInfo.Id.AsLong())); + var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder() .WithIconUrl(userInfo.GetAvatarUrl()) @@ -68,9 +70,9 @@ namespace Geekbot.Bot.Commands.User e.UserId.Equals(userInfo.Id.AsLong())); eb.AddInlineField(Localization.Stats.OnDiscordSince, - $"{createdAt.Day}.{createdAt.Month}.{createdAt.Year} ({age} days)") + $"{createdAt.Day}.{createdAt.Month}.{createdAt.Year} ({age} {Localization.Stats.Days})") .AddInlineField(Localization.Stats.JoinedServer, - $"{joinedAt.Day}.{joinedAt.Month}.{joinedAt.Year} ({joinedDayAgo} days)") + $"{joinedAt.Day}.{joinedAt.Month}.{joinedAt.Year} ({joinedDayAgo} {Localization.Stats.Days})") .AddInlineField(Localization.Stats.Karma, karma?.Karma ?? 0) .AddInlineField(Localization.Stats.Level, level) .AddInlineField(Localization.Stats.MessagesSent, messages) @@ -78,6 +80,7 @@ namespace Geekbot.Bot.Commands.User if (correctRolls != null) eb.AddInlineField(Localization.Stats.GuessedRolls, correctRolls.Rolls); if (cookies > 0) eb.AddInlineField(Localization.Stats.Cookies, cookies); + if (quotes > 0) eb.AddInlineField(Localization.Stats.Quotes, quotes); await ReplyAsync("", false, eb.Build()); } diff --git a/src/Bot/Localization/Stats.Designer.cs b/src/Bot/Localization/Stats.Designer.cs index d05f937..6f650e2 100644 --- a/src/Bot/Localization/Stats.Designer.cs +++ b/src/Bot/Localization/Stats.Designer.cs @@ -69,6 +69,15 @@ namespace Geekbot.Bot.Localization { } } + /// + /// Looks up a localized string similar to Days. + /// + internal static string Days { + get { + return ResourceManager.GetString("Days", resourceCulture); + } + } + /// /// Looks up a localized string similar to Guessed Rolls. /// @@ -123,6 +132,15 @@ namespace Geekbot.Bot.Localization { } } + /// + /// Looks up a localized string similar to Quotes. + /// + internal static string Quotes { + get { + return ResourceManager.GetString("Quotes", resourceCulture); + } + } + /// /// Looks up a localized string similar to Server Total. /// diff --git a/src/Bot/Localization/Stats.de-ch.resx b/src/Bot/Localization/Stats.de-ch.resx index ab44a2e..0af0477 100644 --- a/src/Bot/Localization/Stats.de-ch.resx +++ b/src/Bot/Localization/Stats.de-ch.resx @@ -35,4 +35,10 @@ Guetzli + + Täg + + + Quotes + \ No newline at end of file diff --git a/src/Bot/Localization/Stats.resx b/src/Bot/Localization/Stats.resx index 3b8303a..6eb3a92 100644 --- a/src/Bot/Localization/Stats.resx +++ b/src/Bot/Localization/Stats.resx @@ -42,4 +42,10 @@ Cookies + + Days + + + Quotes + \ No newline at end of file From 611b179d628aa56db4f5503c004814f1dde4bb3e Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 9 Jul 2021 20:21:17 +0200 Subject: [PATCH 437/553] Add a piece of low fat mozzarella to the !slap command --- src/Bot/Commands/Randomness/Slap.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Bot/Commands/Randomness/Slap.cs b/src/Bot/Commands/Randomness/Slap.cs index b512e73..7a858b1 100644 --- a/src/Bot/Commands/Randomness/Slap.cs +++ b/src/Bot/Commands/Randomness/Slap.cs @@ -76,7 +76,8 @@ namespace Geekbot.Bot.Commands.Randomness "teapot", "candle", "dictionary", - "powerless banhammer" + "powerless banhammer", + "piece of low fat mozzarella" }; await ReplyAsync($"{Context.User.Username} slapped {user.Username} with a {things[new Random().Next(things.Count - 1)]}"); @@ -127,4 +128,4 @@ namespace Geekbot.Bot.Commands.Randomness e.UserId.Equals(userId.AsLong())); } } -} \ No newline at end of file +} From 8fcc6291065e9becd2e5f9ada1955dba7e83ad99 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 9 Jul 2021 20:39:04 +0200 Subject: [PATCH 438/553] Disable MSBuildEnableWorkloadResolver in gitlab ci --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 967def1..fc1cd0e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,6 +7,8 @@ stages: variables: VERSION: 4.3.0-V$CI_COMMIT_SHORT_SHA IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG + # ToDo: Remove when .net6 is released + MSBuildEnableWorkloadResolver: false Build: stage: build From 86068ecc443dd18d709dcf1f52d6d291ce06c500 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 9 Jul 2021 20:48:42 +0200 Subject: [PATCH 439/553] Disable self contained publishing for the test, web and bot dlls --- .gitlab-ci.yml | 2 +- src/Bot/Bot.csproj | 1 + src/Web/Web.csproj | 1 + tests/Tests.csproj | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fc1cd0e..7da242b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -8,7 +8,7 @@ variables: VERSION: 4.3.0-V$CI_COMMIT_SHORT_SHA IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG # ToDo: Remove when .net6 is released - MSBuildEnableWorkloadResolver: false + MSBuildEnableWorkloadResolver: 'false' Build: stage: build diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index cd04530..ff10a94 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -3,6 +3,7 @@ Exe net6.0 win10-x64;linux-x64;linux-musl-x64 + false derp.ico $(VersionSuffix) Geekbot.Bot diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index d57c63c..a9ffcc4 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -3,6 +3,7 @@ net6.0 win10-x64;linux-x64;linux-musl-x64 + false $(VersionSuffix) $(VersionSuffix) 0.0.0-DEV diff --git a/tests/Tests.csproj b/tests/Tests.csproj index 4823e0b..786164e 100644 --- a/tests/Tests.csproj +++ b/tests/Tests.csproj @@ -2,6 +2,7 @@ net6.0 win10-x64;linux-x64;linux-musl-x64 + false false NU1701 xUnit1026 From 8d037c786ea5b916add8b1219e1d3e2836ed91f6 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Sat, 10 Jul 2021 00:41:22 +0200 Subject: [PATCH 440/553] Reenable MSBuildEnableWorkloadResolver --- .gitlab-ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7da242b..967def1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,8 +7,6 @@ stages: variables: VERSION: 4.3.0-V$CI_COMMIT_SHORT_SHA IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG - # ToDo: Remove when .net6 is released - MSBuildEnableWorkloadResolver: 'false' Build: stage: build From 90668b6aac1bb728eba9d1a4b924743e3503a1d0 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Sat, 10 Jul 2021 00:49:03 +0200 Subject: [PATCH 441/553] Add padding at the end of things for the !slap command --- src/Bot/Commands/Randomness/Slap.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Bot/Commands/Randomness/Slap.cs b/src/Bot/Commands/Randomness/Slap.cs index 7a858b1..f5d21b8 100644 --- a/src/Bot/Commands/Randomness/Slap.cs +++ b/src/Bot/Commands/Randomness/Slap.cs @@ -77,10 +77,13 @@ namespace Geekbot.Bot.Commands.Randomness "candle", "dictionary", "powerless banhammer", - "piece of low fat mozzarella" + "piece of low fat mozzarella", + // For some reason it never picks the last one + // Adding this workaround, because i'm to lazy to actually fix it at the time of writing this + "padding" }; - await ReplyAsync($"{Context.User.Username} slapped {user.Username} with a {things[new Random().Next(things.Count - 1)]}"); + await ReplyAsync($"{Context.User.Username} slapped {user.Username} with a {things[new Random().Next(0, things.Count - 1)]}"); await UpdateRecieved(user.Id); await UpdateGiven(Context.User.Id); From 9a55d8447fef227f5b69790125651767bd92fb82 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Wed, 11 Aug 2021 17:58:06 +0200 Subject: [PATCH 442/553] Upgrade discord.net to version 2.4.0 --- src/Core/Core.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 17b4a26..629233a 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -14,7 +14,7 @@ - + all From f22956368b3a165a3cbe9135ff829cffa6ba8187 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Wed, 11 Aug 2021 17:58:45 +0200 Subject: [PATCH 443/553] Remove !gdq --- src/Bot/Commands/Randomness/Gdq.cs | 36 ------------------------------ 1 file changed, 36 deletions(-) delete mode 100644 src/Bot/Commands/Randomness/Gdq.cs diff --git a/src/Bot/Commands/Randomness/Gdq.cs b/src/Bot/Commands/Randomness/Gdq.cs deleted file mode 100644 index c6d9fa8..0000000 --- a/src/Bot/Commands/Randomness/Gdq.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Net; -using System.Threading.Tasks; -using Discord.Commands; -using Geekbot.Core.ErrorHandling; - -namespace Geekbot.Bot.Commands.Randomness -{ - public class Gdq : ModuleBase - { - private readonly IErrorHandler _errorHandler; - - public Gdq(IErrorHandler errorHandler) - { - _errorHandler = errorHandler; - } - - [Command("gdq", RunMode = RunMode.Async)] - [Summary("Get a quote from the GDQ donation generator.")] - public async Task GetQuote() - { - try - { - using var client = new WebClient(); - var url = new Uri("http://taskinoz.com/gdq/api/"); - var response = client.DownloadString(url); - - await ReplyAsync(response); - } - catch (Exception e) - { - await _errorHandler.HandleCommandException(e, Context); - } - } - } -} \ No newline at end of file From 18ece35ffe88aaa8e5aa0204b499d72f5615ece4 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Wed, 11 Aug 2021 23:08:00 +0200 Subject: [PATCH 444/553] Remove System.Timers.Timer ambiguity for .net6-preview7 --- src/Bot/Handlers/StatsHandler.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Bot/Handlers/StatsHandler.cs b/src/Bot/Handlers/StatsHandler.cs index d1384cd..b089515 100644 --- a/src/Bot/Handlers/StatsHandler.cs +++ b/src/Bot/Handlers/StatsHandler.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Threading.Tasks; -using System.Timers; using Discord.WebSocket; using Geekbot.Core.Database; using Geekbot.Core.Database.Models; @@ -24,7 +22,7 @@ namespace Geekbot.Bot.Handlers _database = database; _season = SeasonsUtils.GetCurrentSeason(); - var timer = new Timer() + var timer = new System.Timers.Timer() { Enabled = true, AutoReset = true, From e712403dd96d824688cc0077b5394397b5b233f2 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 11:21:42 +0200 Subject: [PATCH 445/553] Upgrade Sumologic, jikan and HtmlAgilityPack --- src/Bot/Bot.csproj | 4 ++-- src/Core/Core.csproj | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index ff10a94..c64eecb 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -24,8 +24,8 @@ - - + + diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 629233a..463c4e9 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -34,7 +34,7 @@ - + From f19ddb30b285352282722bc868f67827e029bddd Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 11:23:20 +0200 Subject: [PATCH 446/553] Replace RNGCryptoServiceProvider with System.Security.Cryptography.RandomNumberGenerator --- src/Core/RandomNumberGenerator/RandomNumberGenerator.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Core/RandomNumberGenerator/RandomNumberGenerator.cs b/src/Core/RandomNumberGenerator/RandomNumberGenerator.cs index db990a7..1b7178b 100644 --- a/src/Core/RandomNumberGenerator/RandomNumberGenerator.cs +++ b/src/Core/RandomNumberGenerator/RandomNumberGenerator.cs @@ -1,5 +1,4 @@ using System; -using System.Security.Cryptography; using Anemonis.RandomOrg; using Geekbot.Core.GlobalSettings; @@ -7,13 +6,13 @@ namespace Geekbot.Core.RandomNumberGenerator { public class RandomNumberGenerator : IRandomNumberGenerator { - private readonly RNGCryptoServiceProvider csp; + private readonly System.Security.Cryptography.RandomNumberGenerator rng; private readonly bool _canUseRandomOrg; private readonly RandomOrgClient _randomOrgClient; public RandomNumberGenerator(IGlobalSettings globalSettings) { - csp = new RNGCryptoServiceProvider(); + rng = System.Security.Cryptography.RandomNumberGenerator.Create(); var randomOrgApiKey = globalSettings.GetKey("RandomOrgApiKey"); if (!string.IsNullOrEmpty(randomOrgApiKey)) @@ -32,7 +31,7 @@ namespace Geekbot.Core.RandomNumberGenerator if (minValue >= maxInclusiveValue) { - throw new ArgumentOutOfRangeException("minValue must be lower than maxExclusiveValue"); + throw new ArgumentOutOfRangeException("minValue", "must be lower than maxExclusiveValue"); } if (_canUseRandomOrg) @@ -84,7 +83,7 @@ namespace Geekbot.Core.RandomNumberGenerator private byte[] GenerateRandomBytes(int bytesNumber) { var buffer = new byte[bytesNumber]; - csp.GetBytes(buffer); + rng.GetBytes(buffer); return buffer; } } From 989057a0b06c034658bf83d73ea16a289d480803 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 12:22:26 +0200 Subject: [PATCH 447/553] Migrate from RavenSharp to the SentrySDK --- src/Bot/Bot.csproj | 2 +- src/Core/Core.csproj | 2 +- src/Core/ErrorHandling/ErrorHandler.cs | 38 +++++++++++++------------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index c64eecb..998456c 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -29,7 +29,7 @@ - + diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 463c4e9..dfce63b 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -33,7 +33,7 @@ - + diff --git a/src/Core/ErrorHandling/ErrorHandler.cs b/src/Core/ErrorHandling/ErrorHandler.cs index 60d97e9..a5ccc8e 100644 --- a/src/Core/ErrorHandling/ErrorHandler.cs +++ b/src/Core/ErrorHandling/ErrorHandler.cs @@ -1,9 +1,9 @@ using System; +using System.Collections.Generic; using System.Threading.Tasks; using Discord.Commands; using Geekbot.Core.Logger; -using SharpRaven; -using SharpRaven.Data; +using Sentry; using Exception = System.Exception; namespace Geekbot.Core.ErrorHandling @@ -12,7 +12,6 @@ namespace Geekbot.Core.ErrorHandling { private readonly IGeekbotLogger _logger; private readonly Func _getDefaultErrorText; - private readonly IRavenClient _raven; private readonly bool _errorsInChat; public ErrorHandler(IGeekbotLogger logger, RunParameters runParameters, Func getDefaultErrorText) @@ -22,15 +21,15 @@ namespace Geekbot.Core.ErrorHandling _errorsInChat = runParameters.ExposeErrors; var sentryDsn = runParameters.SentryEndpoint; - if (!string.IsNullOrEmpty(sentryDsn)) + if (string.IsNullOrEmpty(sentryDsn)) return; + + SentrySdk.Init(o => { - _raven = new RavenClient(sentryDsn) { Release = Constants.BotVersion(), Environment = "Production" }; - _logger.Information(LogSource.Geekbot, $"Command Errors will be logged to Sentry: {sentryDsn}"); - } - else - { - _raven = null; - } + o.Dsn = sentryDsn; + o.Release = Constants.BotVersion(); + o.Environment = "Production"; + }); + _logger.Information(LogSource.Geekbot, $"Command Errors will be logged to Sentry: {sentryDsn}"); } public async Task HandleCommandException(Exception e, ICommandContext context, string errorMessage = "def") @@ -83,18 +82,19 @@ namespace Geekbot.Core.ErrorHandling private void ReportExternal(Exception e, MessageDto errorObj) { - if (_raven == null) return; + if (!SentrySdk.IsEnabled) return; + var sentryEvent = new SentryEvent(e) { - Tags = - { - ["discord_server"] = errorObj.Guild.Name, - ["discord_user"] = errorObj.User.Name - }, Message = errorObj.Message.Content, - Extra = errorObj }; - _raven.Capture(sentryEvent); + sentryEvent.SetTag("discord_server", errorObj.Guild.Name); + sentryEvent.SetExtra("Channel", errorObj.Channel); + sentryEvent.SetExtra("Guild", errorObj.Guild); + sentryEvent.SetExtra("Message", errorObj.Message); + sentryEvent.SetExtra("User", errorObj.User); + + SentrySdk.CaptureEvent(sentryEvent); } } } \ No newline at end of file From 5c507b026cc3f8bb94bc4cb8f92d77595c609a5c Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 14:03:35 +0200 Subject: [PATCH 448/553] Remove random.org integration --- src/Bot/Program.cs | 2 +- src/Core/Core.csproj | 1 - .../RandomNumberGenerator.cs | 34 +------------------ tests/Core/DiceParser/DiceParser.test.cs | 2 +- tests/Core/DiceParser/SingleDie.test.cs | 4 +-- 5 files changed, 5 insertions(+), 38 deletions(-) diff --git a/src/Bot/Program.cs b/src/Bot/Program.cs index dee6ec3..3429fbc 100644 --- a/src/Bot/Program.cs +++ b/src/Bot/Program.cs @@ -162,7 +162,7 @@ namespace Geekbot.Bot var emojiConverter = new EmojiConverter(); var mtgManaConverter = new MtgManaConverter(); var wikipediaClient = new WikipediaClient(); - var randomNumberGenerator = new RandomNumberGenerator(_globalSettings); + var randomNumberGenerator = new RandomNumberGenerator(); var mediaProvider = new MediaProvider(_logger, randomNumberGenerator); var kvMemoryStore = new KvInInMemoryStore(); var errorHandler = new ErrorHandler(_logger, _runParameters, () => Localization.Internal.SomethingWentWrong); diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index dfce63b..6d1b89b 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -12,7 +12,6 @@ - diff --git a/src/Core/RandomNumberGenerator/RandomNumberGenerator.cs b/src/Core/RandomNumberGenerator/RandomNumberGenerator.cs index 1b7178b..7460677 100644 --- a/src/Core/RandomNumberGenerator/RandomNumberGenerator.cs +++ b/src/Core/RandomNumberGenerator/RandomNumberGenerator.cs @@ -1,25 +1,14 @@ using System; -using Anemonis.RandomOrg; -using Geekbot.Core.GlobalSettings; namespace Geekbot.Core.RandomNumberGenerator { public class RandomNumberGenerator : IRandomNumberGenerator { private readonly System.Security.Cryptography.RandomNumberGenerator rng; - private readonly bool _canUseRandomOrg; - private readonly RandomOrgClient _randomOrgClient; - public RandomNumberGenerator(IGlobalSettings globalSettings) + public RandomNumberGenerator() { rng = System.Security.Cryptography.RandomNumberGenerator.Create(); - - var randomOrgApiKey = globalSettings.GetKey("RandomOrgApiKey"); - if (!string.IsNullOrEmpty(randomOrgApiKey)) - { - _canUseRandomOrg = true; - _randomOrgClient = new RandomOrgClient(randomOrgApiKey); - } } public int Next(int minValue, int maxInclusiveValue) @@ -33,31 +22,10 @@ namespace Geekbot.Core.RandomNumberGenerator { throw new ArgumentOutOfRangeException("minValue", "must be lower than maxExclusiveValue"); } - - if (_canUseRandomOrg) - { - try - { - return GetFromRandomOrg(minValue, maxInclusiveValue); - } - catch - { - // ignore - } - } return GetFromCrypto(minValue, maxInclusiveValue); } - private int GetFromRandomOrg(int minValue, int maxInclusiveValue) - { - return _randomOrgClient - .GenerateIntegersAsync(1, minValue, maxInclusiveValue, false) - .Result - .Random - .Data[0]; - } - private int GetFromCrypto(int minValue, int maxInclusiveValue) { var maxExclusiveValue = maxInclusiveValue + 1; diff --git a/tests/Core/DiceParser/DiceParser.test.cs b/tests/Core/DiceParser/DiceParser.test.cs index ed9425f..fd9e5c5 100644 --- a/tests/Core/DiceParser/DiceParser.test.cs +++ b/tests/Core/DiceParser/DiceParser.test.cs @@ -10,7 +10,7 @@ namespace Tests.Core.DiceParser { public class DiceParserTest { - private static readonly RandomNumberGenerator _randomNumberGenerator = new RandomNumberGenerator(new Mock().Object); + private static readonly RandomNumberGenerator _randomNumberGenerator = new RandomNumberGenerator(); public struct DiceParserTestDto { diff --git a/tests/Core/DiceParser/SingleDie.test.cs b/tests/Core/DiceParser/SingleDie.test.cs index 5173902..fdba5e7 100644 --- a/tests/Core/DiceParser/SingleDie.test.cs +++ b/tests/Core/DiceParser/SingleDie.test.cs @@ -45,7 +45,7 @@ namespace Tests.Core.DiceParser [Theory, MemberData(nameof(SingleDieNameTestData))] public void SingleDieNameTestFunc(string testName, SingleDieNameTestDto testData) { - var die = new SingleDie(new RandomNumberGenerator(new Mock().Object)) {AdvantageType = testData.AdvantageType}; + var die = new SingleDie(new RandomNumberGenerator()) {AdvantageType = testData.AdvantageType}; Assert.Equal(die.DiceName, testData.Expected); } @@ -108,7 +108,7 @@ namespace Tests.Core.DiceParser [Theory, MemberData(nameof(SingleDieValidationTestData))] public void SingleDieValidationTestFunc(string testName, SingleDieValidationTestDto testData) { - var die = new SingleDie(new RandomNumberGenerator(new Mock().Object)) + var die = new SingleDie(new RandomNumberGenerator()) { Amount = testData.Amount, Sides = testData.Sides From 1f518e980c323b728e43b85d9f829738bd18754e Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 14:04:30 +0200 Subject: [PATCH 449/553] Move Sentry SDK init to the main init process --- src/Bot/Program.cs | 20 +++++++++++++++++++- src/Core/ErrorHandling/ErrorHandler.cs | 12 ------------ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/Bot/Program.cs b/src/Bot/Program.cs index 3429fbc..4d7526b 100644 --- a/src/Bot/Program.cs +++ b/src/Bot/Program.cs @@ -26,6 +26,8 @@ using Geekbot.Core.WikipediaClient; using Geekbot.Web; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; +using Sentry; +using Constants = Geekbot.Core.Constants; namespace Geekbot.Bot { @@ -90,7 +92,9 @@ namespace Geekbot.Bot _logger.Information(LogSource.Api, "Starting Web API"); StartWebApi(); - + + RegisterSentry(); + _logger.Information(LogSource.Geekbot, "Done and ready for use"); await Task.Delay(-1); @@ -224,5 +228,19 @@ namespace Geekbot.Bot var highscoreManager = new HighscoreManager(_databaseInitializer.Initialize(), _userRepository); WebApiStartup.StartWebApi(_logger, _runParameters, _commands, _databaseInitializer.Initialize(), _client, _globalSettings, highscoreManager); } + + private void RegisterSentry() + { + var sentryDsn = _runParameters.SentryEndpoint; + if (string.IsNullOrEmpty(sentryDsn)) return; + SentrySdk.Init(o => + { + o.Dsn = sentryDsn; + o.Release = Constants.BotVersion(); + o.Environment = "Production"; + o.TracesSampleRate = 1.0; + }); + _logger.Information(LogSource.Geekbot, $"Command Errors will be logged to Sentry: {sentryDsn}"); + } } } \ No newline at end of file diff --git a/src/Core/ErrorHandling/ErrorHandler.cs b/src/Core/ErrorHandling/ErrorHandler.cs index a5ccc8e..0b55bd8 100644 --- a/src/Core/ErrorHandling/ErrorHandler.cs +++ b/src/Core/ErrorHandling/ErrorHandler.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Threading.Tasks; using Discord.Commands; using Geekbot.Core.Logger; @@ -19,17 +18,6 @@ namespace Geekbot.Core.ErrorHandling _logger = logger; _getDefaultErrorText = getDefaultErrorText; _errorsInChat = runParameters.ExposeErrors; - - var sentryDsn = runParameters.SentryEndpoint; - if (string.IsNullOrEmpty(sentryDsn)) return; - - SentrySdk.Init(o => - { - o.Dsn = sentryDsn; - o.Release = Constants.BotVersion(); - o.Environment = "Production"; - }); - _logger.Information(LogSource.Geekbot, $"Command Errors will be logged to Sentry: {sentryDsn}"); } public async Task HandleCommandException(Exception e, ICommandContext context, string errorMessage = "def") From 3299ac4eabafdb4c053ca0887aad73d0518c9635 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 14:06:10 +0200 Subject: [PATCH 450/553] Add generic sentry tracing to the main command module --- src/Core/GeekbotCommandBase.cs | 40 +++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/Core/GeekbotCommandBase.cs b/src/Core/GeekbotCommandBase.cs index 43ced95..ae964e7 100644 --- a/src/Core/GeekbotCommandBase.cs +++ b/src/Core/GeekbotCommandBase.cs @@ -1,9 +1,13 @@ +using System.Collections.Generic; using System.Globalization; using System.Threading; +using System.Threading.Tasks; +using Discord; using Discord.Commands; using Geekbot.Core.Database.Models; using Geekbot.Core.ErrorHandling; using Geekbot.Core.GuildSettingsManager; +using Sentry; namespace Geekbot.Core { @@ -12,6 +16,7 @@ namespace Geekbot.Core protected readonly IGuildSettingsManager GuildSettingsManager; protected GuildSettingsModel GuildSettings; protected readonly IErrorHandler ErrorHandler; + protected ITransaction Transaction; protected GeekbotCommandBase(IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager) { @@ -22,9 +27,42 @@ namespace Geekbot.Core protected override void BeforeExecute(CommandInfo command) { base.BeforeExecute(command); + + // Transaction Setup + Transaction = SentrySdk.StartTransaction(new Transaction(command.Name, "Exec")); + Transaction.SetTags(new [] + { + new KeyValuePair("GuildId", Context.Guild.Id.ToString()), + new KeyValuePair("Guild", Context.Guild.Name), + }); + Transaction.User = new User() + { + Id = Context.User.Id.ToString(), + Username = Context.User.Username, + }; + + // Command Setup + var setupSpan = Transaction.StartChild("Setup"); + GuildSettings = GuildSettingsManager.GetSettings(Context?.Guild?.Id ?? 0); var language = GuildSettings.Language; - Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(language == "CHDE" ? "de-ch" : language); + Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(language); + + setupSpan.Finish(); + } + + protected override void AfterExecute(CommandInfo command) + { + base.AfterExecute(command); + Transaction.Finish(); + } + + protected override Task ReplyAsync(string message = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null) + { + var replySpan = Transaction.StartChild("Reply"); + var msg = base.ReplyAsync(message, isTTS, embed, options, allowedMentions, messageReference); + replySpan.Finish(); + return msg; } } } \ No newline at end of file From aa826f962d8715f2579a0c9ee79bee8776c74a4e Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 14:06:34 +0200 Subject: [PATCH 451/553] Add traces to the !roll command --- src/Bot/Commands/Games/Roll/Roll.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Bot/Commands/Games/Roll/Roll.cs b/src/Bot/Commands/Games/Roll/Roll.cs index 6ef9322..0361cbd 100644 --- a/src/Bot/Commands/Games/Roll/Roll.cs +++ b/src/Bot/Commands/Games/Roll/Roll.cs @@ -11,6 +11,7 @@ using Geekbot.Core.Extensions; using Geekbot.Core.GuildSettingsManager; using Geekbot.Core.KvInMemoryStore; using Geekbot.Core.RandomNumberGenerator; +using Sentry; namespace Geekbot.Bot.Commands.Games.Roll { @@ -34,43 +35,54 @@ namespace Geekbot.Bot.Commands.Games.Roll { try { + var inputSpan = Transaction.StartChild("CommandInput"); var number = _randomNumberGenerator.Next(1, 100); int.TryParse(stuff, out var guess); + inputSpan.Finish(); + if (guess <= 100 && guess > 0) { + var prevRollCheckSpan = Transaction.StartChild("PrevRollCheck"); var kvKey = $"{Context?.Guild?.Id ?? 0}:{Context.User.Id}:RollsPrevious"; - + var prevRoll = _kvInMemoryStore.Get(kvKey); - + if (prevRoll?.LastGuess == guess && prevRoll?.GuessedOn.AddDays(1) > DateTime.Now) { await ReplyAsync(string.Format( Localization.Roll.NoPrevGuess, Context.Message.Author.Mention, DateLocalization.FormatDateTimeAsRemaining(prevRoll.GuessedOn.AddDays(1)))); + Transaction.Status = SpanStatus.InvalidArgument; return; } _kvInMemoryStore.Set(kvKey, new RollTimeout {LastGuess = guess, GuessedOn = DateTime.Now}); + prevRollCheckSpan.Finish(); await ReplyAsync(string.Format(Localization.Roll.Rolled, Context.Message.Author.Mention, number, guess)); if (guess == number) { + var correctGuessSpan = Transaction.StartChild("CorrectGuess"); await ReplyAsync(string.Format(Localization.Roll.Gratz, Context.Message.Author)); var user = await GetUser(Context.User.Id); user.Rolls += 1; _database.Rolls.Update(user); await _database.SaveChangesAsync(); + correctGuessSpan.Finish(); } } else { await ReplyAsync(string.Format(Localization.Roll.RolledNoGuess, Context.Message.Author.Mention, number)); } + + Transaction.Status = SpanStatus.Ok; } catch (Exception e) { await ErrorHandler.HandleCommandException(e, Context); + Transaction.Status = SpanStatus.InternalError; } } From d708525a2f59711599311782d1c663e7f4f65441 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 14:07:19 +0200 Subject: [PATCH 452/553] Add traces to the !quote command --- src/Bot/Commands/Utils/Quote/Quote.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index e79663c..fdf1030 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -15,6 +15,8 @@ using Geekbot.Core.Polyfills; using Geekbot.Core.RandomNumberGenerator; using Geekbot.Core.UserRepository; using Microsoft.EntityFrameworkCore; +using Sentry; +using Constants = Geekbot.Core.Constants; namespace Geekbot.Bot.Commands.Utils.Quote { @@ -43,23 +45,32 @@ namespace Geekbot.Bot.Commands.Utils.Quote { try { + var getTotalSpan = Transaction.StartChild("TotalQuotes"); var totalQuotes = await _database.Quotes.CountAsync(e => e.GuildId.Equals(Context.Guild.Id.AsLong())); + getTotalSpan.Finish(); if (totalQuotes == 0) { await ReplyAsync(Localization.Quote.NoQuotesFound); + Transaction.Status = SpanStatus.NotFound; return; } + var getQuoteFromDbSpan = Transaction.StartChild("GetQuoteFromDB"); var random = _randomNumberGenerator.Next(0, totalQuotes - 1); var quote = _database.Quotes.Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())).Skip(random).Take(1); + getQuoteFromDbSpan.Finish(); + var replySpan = Transaction.StartChild("Reply"); var embed = QuoteBuilder(quote.FirstOrDefault()); await ReplyAsync("", false, embed.Build()); + replySpan.Finish(); + Transaction.Status = SpanStatus.Ok; } catch (Exception e) { await ErrorHandler.HandleCommandException(e, Context, "Whoops, seems like the quote was to edgy to return"); + Transaction.Status = SpanStatus.InternalError; } } From 833a8a0dd8dfea3fa29019584cf448c41c4cc469 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 14:27:46 +0200 Subject: [PATCH 453/553] Split Transactions from the GeekbotCommandBase --- src/Core/GeekbotCommandBase.cs | 35 +----------------------- src/Core/TransactionModuleBase.cs | 45 +++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 34 deletions(-) create mode 100644 src/Core/TransactionModuleBase.cs diff --git a/src/Core/GeekbotCommandBase.cs b/src/Core/GeekbotCommandBase.cs index ae964e7..801c53c 100644 --- a/src/Core/GeekbotCommandBase.cs +++ b/src/Core/GeekbotCommandBase.cs @@ -1,22 +1,17 @@ -using System.Collections.Generic; using System.Globalization; using System.Threading; -using System.Threading.Tasks; -using Discord; using Discord.Commands; using Geekbot.Core.Database.Models; using Geekbot.Core.ErrorHandling; using Geekbot.Core.GuildSettingsManager; -using Sentry; namespace Geekbot.Core { - public class GeekbotCommandBase : ModuleBase + public class GeekbotCommandBase : TransactionModuleBase { protected readonly IGuildSettingsManager GuildSettingsManager; protected GuildSettingsModel GuildSettings; protected readonly IErrorHandler ErrorHandler; - protected ITransaction Transaction; protected GeekbotCommandBase(IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager) { @@ -28,20 +23,6 @@ namespace Geekbot.Core { base.BeforeExecute(command); - // Transaction Setup - Transaction = SentrySdk.StartTransaction(new Transaction(command.Name, "Exec")); - Transaction.SetTags(new [] - { - new KeyValuePair("GuildId", Context.Guild.Id.ToString()), - new KeyValuePair("Guild", Context.Guild.Name), - }); - Transaction.User = new User() - { - Id = Context.User.Id.ToString(), - Username = Context.User.Username, - }; - - // Command Setup var setupSpan = Transaction.StartChild("Setup"); GuildSettings = GuildSettingsManager.GetSettings(Context?.Guild?.Id ?? 0); @@ -50,19 +31,5 @@ namespace Geekbot.Core setupSpan.Finish(); } - - protected override void AfterExecute(CommandInfo command) - { - base.AfterExecute(command); - Transaction.Finish(); - } - - protected override Task ReplyAsync(string message = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null) - { - var replySpan = Transaction.StartChild("Reply"); - var msg = base.ReplyAsync(message, isTTS, embed, options, allowedMentions, messageReference); - replySpan.Finish(); - return msg; - } } } \ No newline at end of file diff --git a/src/Core/TransactionModuleBase.cs b/src/Core/TransactionModuleBase.cs new file mode 100644 index 0000000..111ae18 --- /dev/null +++ b/src/Core/TransactionModuleBase.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Sentry; + +namespace Geekbot.Core +{ + public class TransactionModuleBase : ModuleBase + { + protected ITransaction Transaction; + + protected override void BeforeExecute(CommandInfo command) + { + base.BeforeExecute(command); + + // Transaction Setup + Transaction = SentrySdk.StartTransaction(new Transaction(command.Name, "Exec")); + Transaction.SetTags(new [] + { + new KeyValuePair("GuildId", Context.Guild.Id.ToString()), + new KeyValuePair("Guild", Context.Guild.Name), + }); + Transaction.User = new User() + { + Id = Context.User.Id.ToString(), + Username = Context.User.Username, + }; + } + + protected override void AfterExecute(CommandInfo command) + { + base.AfterExecute(command); + Transaction.Finish(); + } + + protected override Task ReplyAsync(string message = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null) + { + var replySpan = Transaction.StartChild("Reply"); + var msg = base.ReplyAsync(message, isTTS, embed, options, allowedMentions, messageReference); + replySpan.Finish(); + return msg; + } + } +} \ No newline at end of file From f02c30e66028930798a3146a188fc1f1ecf8f990 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 14:30:50 +0200 Subject: [PATCH 454/553] Remove the mod command class --- src/Bot/Commands/Admin/Mod.cs | 38 ----------------------------------- 1 file changed, 38 deletions(-) delete mode 100644 src/Bot/Commands/Admin/Mod.cs diff --git a/src/Bot/Commands/Admin/Mod.cs b/src/Bot/Commands/Admin/Mod.cs deleted file mode 100644 index b642680..0000000 --- a/src/Bot/Commands/Admin/Mod.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Threading.Tasks; -using Discord; -using Discord.Commands; -using Geekbot.Core.CommandPreconditions; -using Geekbot.Core.ErrorHandling; - -namespace Geekbot.Bot.Commands.Admin -{ - [Group("mod")] - [RequireUserPermission(GuildPermission.KickMembers)] - [RequireUserPermission(GuildPermission.ManageMessages)] - [RequireUserPermission(GuildPermission.ManageRoles)] - [DisableInDirectMessage] - public class Mod : ModuleBase - { - private readonly IErrorHandler _errorHandler; - - public Mod(IErrorHandler errorHandler) - { - _errorHandler = errorHandler; - } - - [Command("namehistory", RunMode = RunMode.Async)] - [Summary("See past usernames of an user")] - public async Task UsernameHistory([Summary("@someone")] IUser user) - { - try - { - await Context.Channel.SendMessageAsync("This command has been removed due to low usage and excessively high database usage"); - } - catch (Exception e) - { - await _errorHandler.HandleCommandException(e, Context); - } - } - } -} \ No newline at end of file From a1f8d033c28e97b7963825f7492b423d21b62f2a Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 14:31:24 +0200 Subject: [PATCH 455/553] Use the TransactionModuleBase for all commands that haven't implemented GeekbotCommandBase --- src/Bot/Commands/Games/Pokedex.cs | 3 ++- src/Bot/Commands/Integrations/LolMmr/LolMmr.cs | 2 +- src/Bot/Commands/Integrations/MagicTheGathering.cs | 3 ++- .../Commands/Integrations/UbranDictionary/UrbanDictionary.cs | 2 +- src/Bot/Commands/Integrations/Wikipedia.cs | 3 ++- src/Bot/Commands/Integrations/Youtube.cs | 3 ++- .../Commands/Randomness/BenedictCumberbatchNameGenerator.cs | 3 ++- src/Bot/Commands/Randomness/Cat/Cat.cs | 2 +- src/Bot/Commands/Randomness/Chuck/ChuckNorrisJokes.cs | 2 +- src/Bot/Commands/Randomness/Dad/DadJokes.cs | 2 +- src/Bot/Commands/Randomness/Dog/Dog.cs | 2 +- src/Bot/Commands/Randomness/Fortune.cs | 3 ++- src/Bot/Commands/Randomness/Greetings/Greetings.cs | 2 +- src/Bot/Commands/Randomness/Kanye/Kanye.cs | 2 +- src/Bot/Commands/Randomness/RandomAnimals.cs | 3 ++- src/Bot/Commands/Randomness/Slap.cs | 3 ++- src/Bot/Commands/User/GuildInfo.cs | 3 ++- src/Bot/Commands/Utils/AvatarGetter.cs | 3 ++- src/Bot/Commands/Utils/Changelog/Changelog.cs | 2 +- src/Bot/Commands/Utils/Dice.cs | 3 ++- src/Bot/Commands/Utils/Emojify.cs | 3 ++- src/Bot/Commands/Utils/Help.cs | 3 ++- src/Bot/Commands/Utils/Info.cs | 2 +- src/Bot/Commands/Utils/Lmgtfy.cs | 3 ++- src/Bot/Commands/Utils/Ping.cs | 3 ++- 25 files changed, 40 insertions(+), 25 deletions(-) diff --git a/src/Bot/Commands/Games/Pokedex.cs b/src/Bot/Commands/Games/Pokedex.cs index 426761c..325ee8c 100644 --- a/src/Bot/Commands/Games/Pokedex.cs +++ b/src/Bot/Commands/Games/Pokedex.cs @@ -3,13 +3,14 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.ErrorHandling; using Geekbot.Core.Extensions; using PokeAPI; namespace Geekbot.Bot.Commands.Games { - public class Pokedex : ModuleBase + public class Pokedex : TransactionModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Integrations/LolMmr/LolMmr.cs b/src/Bot/Commands/Integrations/LolMmr/LolMmr.cs index 4e75034..3049617 100644 --- a/src/Bot/Commands/Integrations/LolMmr/LolMmr.cs +++ b/src/Bot/Commands/Integrations/LolMmr/LolMmr.cs @@ -10,7 +10,7 @@ using Geekbot.Core.ErrorHandling; namespace Geekbot.Bot.Commands.Integrations.LolMmr { - public class LolMmr : ModuleBase + public class LolMmr : TransactionModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Integrations/MagicTheGathering.cs b/src/Bot/Commands/Integrations/MagicTheGathering.cs index b179d6e..359b41e 100644 --- a/src/Bot/Commands/Integrations/MagicTheGathering.cs +++ b/src/Bot/Commands/Integrations/MagicTheGathering.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.Converters; using Geekbot.Core.ErrorHandling; using Geekbot.Core.Extensions; @@ -11,7 +12,7 @@ using MtgApiManager.Lib.Service; namespace Geekbot.Bot.Commands.Integrations { - public class MagicTheGathering : ModuleBase + public class MagicTheGathering : TransactionModuleBase { private readonly IErrorHandler _errorHandler; private readonly IMtgManaConverter _manaConverter; diff --git a/src/Bot/Commands/Integrations/UbranDictionary/UrbanDictionary.cs b/src/Bot/Commands/Integrations/UbranDictionary/UrbanDictionary.cs index 72bc8cd..9060b91 100644 --- a/src/Bot/Commands/Integrations/UbranDictionary/UrbanDictionary.cs +++ b/src/Bot/Commands/Integrations/UbranDictionary/UrbanDictionary.cs @@ -9,7 +9,7 @@ using Geekbot.Core.Extensions; namespace Geekbot.Bot.Commands.Integrations.UbranDictionary { - public class UrbanDictionary : ModuleBase + public class UrbanDictionary : TransactionModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Integrations/Wikipedia.cs b/src/Bot/Commands/Integrations/Wikipedia.cs index 709f974..82f42a0 100644 --- a/src/Bot/Commands/Integrations/Wikipedia.cs +++ b/src/Bot/Commands/Integrations/Wikipedia.cs @@ -5,6 +5,7 @@ using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.Database; using Geekbot.Core.ErrorHandling; using Geekbot.Core.Extensions; @@ -14,7 +15,7 @@ using HtmlAgilityPack; namespace Geekbot.Bot.Commands.Integrations { - public class Wikipedia : ModuleBase + public class Wikipedia : TransactionModuleBase { private readonly IErrorHandler _errorHandler; private readonly IWikipediaClient _wikipediaClient; diff --git a/src/Bot/Commands/Integrations/Youtube.cs b/src/Bot/Commands/Integrations/Youtube.cs index 60ebdaa..74fcf52 100644 --- a/src/Bot/Commands/Integrations/Youtube.cs +++ b/src/Bot/Commands/Integrations/Youtube.cs @@ -1,6 +1,7 @@ using System; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.ErrorHandling; using Geekbot.Core.GlobalSettings; using Google.Apis.Services; @@ -8,7 +9,7 @@ using Google.Apis.YouTube.v3; namespace Geekbot.Bot.Commands.Integrations { - public class Youtube : ModuleBase + public class Youtube : TransactionModuleBase { private readonly IGlobalSettings _globalSettings; private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Randomness/BenedictCumberbatchNameGenerator.cs b/src/Bot/Commands/Randomness/BenedictCumberbatchNameGenerator.cs index 995c921..23187bd 100644 --- a/src/Bot/Commands/Randomness/BenedictCumberbatchNameGenerator.cs +++ b/src/Bot/Commands/Randomness/BenedictCumberbatchNameGenerator.cs @@ -2,12 +2,13 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.ErrorHandling; using Geekbot.Core.RandomNumberGenerator; namespace Geekbot.Bot.Commands.Randomness { - public class BenedictCumberbatchNameGenerator : ModuleBase + public class BenedictCumberbatchNameGenerator : TransactionModuleBase { private readonly IErrorHandler _errorHandler; private readonly IRandomNumberGenerator _randomNumberGenerator; diff --git a/src/Bot/Commands/Randomness/Cat/Cat.cs b/src/Bot/Commands/Randomness/Cat/Cat.cs index 7bd7e57..1198113 100644 --- a/src/Bot/Commands/Randomness/Cat/Cat.cs +++ b/src/Bot/Commands/Randomness/Cat/Cat.cs @@ -7,7 +7,7 @@ using Geekbot.Core.ErrorHandling; namespace Geekbot.Bot.Commands.Randomness.Cat { - public class Cat : ModuleBase + public class Cat : TransactionModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Randomness/Chuck/ChuckNorrisJokes.cs b/src/Bot/Commands/Randomness/Chuck/ChuckNorrisJokes.cs index be328b4..e2b1f16 100644 --- a/src/Bot/Commands/Randomness/Chuck/ChuckNorrisJokes.cs +++ b/src/Bot/Commands/Randomness/Chuck/ChuckNorrisJokes.cs @@ -7,7 +7,7 @@ using Geekbot.Core.ErrorHandling; namespace Geekbot.Bot.Commands.Randomness.Chuck { - public class ChuckNorrisJokes : ModuleBase + public class ChuckNorrisJokes : TransactionModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Randomness/Dad/DadJokes.cs b/src/Bot/Commands/Randomness/Dad/DadJokes.cs index 136650c..67f9679 100644 --- a/src/Bot/Commands/Randomness/Dad/DadJokes.cs +++ b/src/Bot/Commands/Randomness/Dad/DadJokes.cs @@ -6,7 +6,7 @@ using Geekbot.Core.ErrorHandling; namespace Geekbot.Bot.Commands.Randomness.Dad { - public class DadJokes : ModuleBase + public class DadJokes : TransactionModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Randomness/Dog/Dog.cs b/src/Bot/Commands/Randomness/Dog/Dog.cs index 051dbf3..39e57c7 100644 --- a/src/Bot/Commands/Randomness/Dog/Dog.cs +++ b/src/Bot/Commands/Randomness/Dog/Dog.cs @@ -7,7 +7,7 @@ using Geekbot.Core.ErrorHandling; namespace Geekbot.Bot.Commands.Randomness.Dog { - public class Dog : ModuleBase + public class Dog : TransactionModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Randomness/Fortune.cs b/src/Bot/Commands/Randomness/Fortune.cs index cc31536..1157603 100644 --- a/src/Bot/Commands/Randomness/Fortune.cs +++ b/src/Bot/Commands/Randomness/Fortune.cs @@ -1,10 +1,11 @@ using System.Threading.Tasks; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.Media; namespace Geekbot.Bot.Commands.Randomness { - public class Fortune : ModuleBase + public class Fortune : TransactionModuleBase { private readonly IFortunesProvider _fortunes; diff --git a/src/Bot/Commands/Randomness/Greetings/Greetings.cs b/src/Bot/Commands/Randomness/Greetings/Greetings.cs index cd69010..c32ee6d 100644 --- a/src/Bot/Commands/Randomness/Greetings/Greetings.cs +++ b/src/Bot/Commands/Randomness/Greetings/Greetings.cs @@ -8,7 +8,7 @@ using Geekbot.Core.Extensions; namespace Geekbot.Bot.Commands.Randomness.Greetings { - public class Greetings : ModuleBase + public class Greetings : TransactionModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Randomness/Kanye/Kanye.cs b/src/Bot/Commands/Randomness/Kanye/Kanye.cs index 6ad67cb..e5d2e95 100644 --- a/src/Bot/Commands/Randomness/Kanye/Kanye.cs +++ b/src/Bot/Commands/Randomness/Kanye/Kanye.cs @@ -6,7 +6,7 @@ using Geekbot.Core.ErrorHandling; namespace Geekbot.Bot.Commands.Randomness.Kanye { - public class Kanye : ModuleBase + public class Kanye : TransactionModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Randomness/RandomAnimals.cs b/src/Bot/Commands/Randomness/RandomAnimals.cs index b9c1bdd..5493485 100644 --- a/src/Bot/Commands/Randomness/RandomAnimals.cs +++ b/src/Bot/Commands/Randomness/RandomAnimals.cs @@ -1,11 +1,12 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.Media; namespace Geekbot.Bot.Commands.Randomness { - public class RandomAnimals : ModuleBase + public class RandomAnimals : TransactionModuleBase { private readonly IMediaProvider _mediaProvider; diff --git a/src/Bot/Commands/Randomness/Slap.cs b/src/Bot/Commands/Randomness/Slap.cs index f5d21b8..c99c325 100644 --- a/src/Bot/Commands/Randomness/Slap.cs +++ b/src/Bot/Commands/Randomness/Slap.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.Database; using Geekbot.Core.Database.Models; using Geekbot.Core.ErrorHandling; @@ -11,7 +12,7 @@ using Geekbot.Core.Extensions; namespace Geekbot.Bot.Commands.Randomness { - public class Slap : ModuleBase + public class Slap : TransactionModuleBase { private readonly IErrorHandler _errorHandler; private readonly DatabaseContext _database; diff --git a/src/Bot/Commands/User/GuildInfo.cs b/src/Bot/Commands/User/GuildInfo.cs index c596186..c7a3b27 100644 --- a/src/Bot/Commands/User/GuildInfo.cs +++ b/src/Bot/Commands/User/GuildInfo.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.CommandPreconditions; using Geekbot.Core.Database; using Geekbot.Core.ErrorHandling; @@ -11,7 +12,7 @@ using Geekbot.Core.Levels; namespace Geekbot.Bot.Commands.User { - public class GuildInfo : ModuleBase + public class GuildInfo : TransactionModuleBase { private readonly IErrorHandler _errorHandler; private readonly DatabaseContext _database; diff --git a/src/Bot/Commands/Utils/AvatarGetter.cs b/src/Bot/Commands/Utils/AvatarGetter.cs index 2aa6b07..458eec8 100644 --- a/src/Bot/Commands/Utils/AvatarGetter.cs +++ b/src/Bot/Commands/Utils/AvatarGetter.cs @@ -2,11 +2,12 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.ErrorHandling; namespace Geekbot.Bot.Commands.Utils { - public class AvatarGetter : ModuleBase + public class AvatarGetter : TransactionModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Utils/Changelog/Changelog.cs b/src/Bot/Commands/Utils/Changelog/Changelog.cs index 92d5ddd..989ac0d 100644 --- a/src/Bot/Commands/Utils/Changelog/Changelog.cs +++ b/src/Bot/Commands/Utils/Changelog/Changelog.cs @@ -11,7 +11,7 @@ using Geekbot.Core.ErrorHandling; namespace Geekbot.Bot.Commands.Utils.Changelog { - public class Changelog : ModuleBase + public class Changelog : TransactionModuleBase { private readonly DiscordSocketClient _client; private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Utils/Dice.cs b/src/Bot/Commands/Utils/Dice.cs index 0668493..c57001f 100644 --- a/src/Bot/Commands/Utils/Dice.cs +++ b/src/Bot/Commands/Utils/Dice.cs @@ -3,12 +3,13 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.DiceParser; using Geekbot.Core.ErrorHandling; namespace Geekbot.Bot.Commands.Utils { - public class Dice : ModuleBase + public class Dice : TransactionModuleBase { private readonly IErrorHandler _errorHandler; private readonly IDiceParser _diceParser; diff --git a/src/Bot/Commands/Utils/Emojify.cs b/src/Bot/Commands/Utils/Emojify.cs index 8bb880e..63b5456 100644 --- a/src/Bot/Commands/Utils/Emojify.cs +++ b/src/Bot/Commands/Utils/Emojify.cs @@ -1,12 +1,13 @@ using System; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.Converters; using Geekbot.Core.ErrorHandling; namespace Geekbot.Bot.Commands.Utils { - public class Emojify : ModuleBase + public class Emojify : TransactionModuleBase { private readonly IEmojiConverter _emojiConverter; private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Utils/Help.cs b/src/Bot/Commands/Utils/Help.cs index 58630fe..7377bfa 100644 --- a/src/Bot/Commands/Utils/Help.cs +++ b/src/Bot/Commands/Utils/Help.cs @@ -3,11 +3,12 @@ using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.ErrorHandling; namespace Geekbot.Bot.Commands.Utils { - public class Help : ModuleBase + public class Help : TransactionModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Utils/Info.cs b/src/Bot/Commands/Utils/Info.cs index 663dd07..912528d 100644 --- a/src/Bot/Commands/Utils/Info.cs +++ b/src/Bot/Commands/Utils/Info.cs @@ -11,7 +11,7 @@ using Geekbot.Core.Extensions; namespace Geekbot.Bot.Commands.Utils { - public class Info : ModuleBase + public class Info : TransactionModuleBase { private readonly DiscordSocketClient _client; private readonly CommandService _commands; diff --git a/src/Bot/Commands/Utils/Lmgtfy.cs b/src/Bot/Commands/Utils/Lmgtfy.cs index 6063cf9..76fa6fa 100644 --- a/src/Bot/Commands/Utils/Lmgtfy.cs +++ b/src/Bot/Commands/Utils/Lmgtfy.cs @@ -2,11 +2,12 @@ using System; using System.Threading.Tasks; using System.Web; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.ErrorHandling; namespace Geekbot.Bot.Commands.Utils { - public class Lmgtfy : ModuleBase + public class Lmgtfy : TransactionModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Utils/Ping.cs b/src/Bot/Commands/Utils/Ping.cs index d4faa53..ee751cd 100644 --- a/src/Bot/Commands/Utils/Ping.cs +++ b/src/Bot/Commands/Utils/Ping.cs @@ -1,9 +1,10 @@ using System.Threading.Tasks; using Discord.Commands; +using Geekbot.Core; namespace Geekbot.Bot.Commands.Utils { - public class Ping : ModuleBase + public class Ping : TransactionModuleBase { [Command("👀", RunMode = RunMode.Async)] [Summary("Look at the bot.")] From d16828077d5098a807027857ab5871d4c85668bf Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 14:33:55 +0200 Subject: [PATCH 456/553] Set Transaction Status to OK by default --- src/Bot/Commands/Games/Roll/Roll.cs | 2 -- src/Bot/Commands/Utils/Quote/Quote.cs | 1 - src/Core/TransactionModuleBase.cs | 1 + 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Bot/Commands/Games/Roll/Roll.cs b/src/Bot/Commands/Games/Roll/Roll.cs index 0361cbd..172126b 100644 --- a/src/Bot/Commands/Games/Roll/Roll.cs +++ b/src/Bot/Commands/Games/Roll/Roll.cs @@ -76,8 +76,6 @@ namespace Geekbot.Bot.Commands.Games.Roll { await ReplyAsync(string.Format(Localization.Roll.RolledNoGuess, Context.Message.Author.Mention, number)); } - - Transaction.Status = SpanStatus.Ok; } catch (Exception e) { diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index fdf1030..8fbecbc 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -65,7 +65,6 @@ namespace Geekbot.Bot.Commands.Utils.Quote var embed = QuoteBuilder(quote.FirstOrDefault()); await ReplyAsync("", false, embed.Build()); replySpan.Finish(); - Transaction.Status = SpanStatus.Ok; } catch (Exception e) { diff --git a/src/Core/TransactionModuleBase.cs b/src/Core/TransactionModuleBase.cs index 111ae18..c35800b 100644 --- a/src/Core/TransactionModuleBase.cs +++ b/src/Core/TransactionModuleBase.cs @@ -26,6 +26,7 @@ namespace Geekbot.Core Id = Context.User.Id.ToString(), Username = Context.User.Username, }; + Transaction.Status = SpanStatus.Ok; } protected override void AfterExecute(CommandInfo command) From 0a9099a6d28ad99a5696f8c5548341ba666d1f00 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 14:53:24 +0200 Subject: [PATCH 457/553] Move Sentry Init priority between the discord connection and dependency registration --- src/Bot/Program.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bot/Program.cs b/src/Bot/Program.cs index 4d7526b..883d92b 100644 --- a/src/Bot/Program.cs +++ b/src/Bot/Program.cs @@ -85,6 +85,8 @@ namespace Geekbot.Bot await Login(); _logger.Information(LogSource.Geekbot, $"Now Connected as {_client.CurrentUser.Username} to {_client.Guilds.Count} Servers"); await _client.SetGameAsync(_globalSettings.GetKey("Game")); + + RegisterSentry(); _logger.Information(LogSource.Geekbot, "Loading Dependencies and Handlers"); RegisterDependencies(); @@ -93,8 +95,6 @@ namespace Geekbot.Bot _logger.Information(LogSource.Api, "Starting Web API"); StartWebApi(); - RegisterSentry(); - _logger.Information(LogSource.Geekbot, "Done and ready for use"); await Task.Delay(-1); From 3d117aebe1d8007ed644fcdfcc57d912cffcb140 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 15:12:22 +0200 Subject: [PATCH 458/553] Split reply and quote embed building trace apart in !quote --- src/Bot/Commands/Utils/Quote/Quote.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index 8fbecbc..835cdcf 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -61,10 +61,10 @@ namespace Geekbot.Bot.Commands.Utils.Quote var quote = _database.Quotes.Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())).Skip(random).Take(1); getQuoteFromDbSpan.Finish(); - var replySpan = Transaction.StartChild("Reply"); + var buildQuoteEmbedSpan = Transaction.StartChild("BuildQuoteEmbed"); var embed = QuoteBuilder(quote.FirstOrDefault()); + buildQuoteEmbedSpan.Finish(); await ReplyAsync("", false, embed.Build()); - replySpan.Finish(); } catch (Exception e) { From 954c6c2be30ef93c96f3fdef8f61f25cdac718f3 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 15:55:13 +0200 Subject: [PATCH 459/553] Remove Guild ID from the tracing tags --- src/Core/TransactionModuleBase.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Core/TransactionModuleBase.cs b/src/Core/TransactionModuleBase.cs index c35800b..726c355 100644 --- a/src/Core/TransactionModuleBase.cs +++ b/src/Core/TransactionModuleBase.cs @@ -18,7 +18,6 @@ namespace Geekbot.Core Transaction = SentrySdk.StartTransaction(new Transaction(command.Name, "Exec")); Transaction.SetTags(new [] { - new KeyValuePair("GuildId", Context.Guild.Id.ToString()), new KeyValuePair("Guild", Context.Guild.Name), }); Transaction.User = new User() From 1b9d8732d5c9cb50c42e40312e719b6466a0500c Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Sun, 19 Sep 2021 00:57:10 +0200 Subject: [PATCH 460/553] Add tracing to the !quote embed builder --- src/Bot/Commands/Utils/Quote/Quote.cs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index 835cdcf..372bed7 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -268,29 +268,32 @@ namespace Geekbot.Bot.Commands.Utils.Quote private EmbedBuilder QuoteBuilder(QuoteModel quote) { + var getEmbedUserSpan = Transaction.StartChild("GetEmbedUser"); var user = Context.Client.GetUserAsync(quote.UserId.AsUlong()).Result; if (user == null) { + var getEmbedUserFromRepoSpan = Transaction.StartChild("GetEmbedUserFromRepo"); var fallbackUserFromRepo = _userRepository.Get(quote.UserId.AsUlong()); user = new UserPolyfillDto() { Username = fallbackUserFromRepo?.Username ?? "Unknown User", AvatarUrl = fallbackUserFromRepo?.AvatarUrl }; + getEmbedUserFromRepoSpan.Finish(); } + getEmbedUserSpan.Finish(); + + var embedBuilderSpan = Transaction.StartChild("EmbedBuilder"); var eb = new EmbedBuilder(); eb.WithColor(new Color(143, 167, 232)); - if (quote.InternalId == 0) - { - eb.Title = $"{user.Username} @ {quote.Time.Day}.{quote.Time.Month}.{quote.Time.Year}"; - } - else - { - eb.Title = $"#{quote.InternalId} | {user.Username} @ {quote.Time.Day}.{quote.Time.Month}.{quote.Time.Year}"; - } + eb.Title = quote.InternalId == 0 + ? $"{user.Username} @ {quote.Time.Day}.{quote.Time.Month}.{quote.Time.Year}" + : $"#{quote.InternalId} | {user.Username} @ {quote.Time.Day}.{quote.Time.Month}.{quote.Time.Year}"; eb.Description = quote.Quote; eb.ThumbnailUrl = user.GetAvatarUrl(); if (quote.Image != null) eb.ImageUrl = quote.Image; + embedBuilderSpan.Finish(); + return eb; } From 447c6d80422237959dfb7867118c37e888b1b243 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Sun, 19 Sep 2021 00:58:00 +0200 Subject: [PATCH 461/553] Remove a database call from !quote by delegating the randomness to the database. --- src/Bot/Commands/Utils/Quote/Quote.cs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index 372bed7..e85c6fa 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -45,22 +45,17 @@ namespace Geekbot.Bot.Commands.Utils.Quote { try { - var getTotalSpan = Transaction.StartChild("TotalQuotes"); - var totalQuotes = await _database.Quotes.CountAsync(e => e.GuildId.Equals(Context.Guild.Id.AsLong())); - getTotalSpan.Finish(); - - if (totalQuotes == 0) + var getQuoteFromDbSpan = Transaction.StartChild("GetQuoteFromDB"); + var quote = _database.Quotes.FromSqlInterpolated($"select * from \"Quotes\" where \"GuildId\" = {Context.Guild.Id} order by random() limit 1"); + getQuoteFromDbSpan.Finish(); + + if (!quote.Any()) { await ReplyAsync(Localization.Quote.NoQuotesFound); Transaction.Status = SpanStatus.NotFound; return; } - var getQuoteFromDbSpan = Transaction.StartChild("GetQuoteFromDB"); - var random = _randomNumberGenerator.Next(0, totalQuotes - 1); - var quote = _database.Quotes.Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())).Skip(random).Take(1); - getQuoteFromDbSpan.Finish(); - var buildQuoteEmbedSpan = Transaction.StartChild("BuildQuoteEmbed"); var embed = QuoteBuilder(quote.FirstOrDefault()); buildQuoteEmbedSpan.Finish(); From 85d06b76e009b9542acba34d3bed6f2b1a328c8c Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Sun, 19 Sep 2021 16:06:11 +0200 Subject: [PATCH 462/553] Add --disable-gateway parameter to the run parameters to stop the bot from connecting to discord. Useful when working on the web-api --- src/Bot/Program.cs | 17 ++++++++++------- src/Core/RunParameters.cs | 3 +++ src/Web/WebApiStartup.cs | 8 +++++--- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/Bot/Program.cs b/src/Bot/Program.cs index 883d92b..31b67e0 100644 --- a/src/Bot/Program.cs +++ b/src/Bot/Program.cs @@ -80,17 +80,20 @@ namespace Geekbot.Bot var database = ConnectToDatabase(); _globalSettings = new GlobalSettings(database); - logger.Information(LogSource.Geekbot, "Connecting to Discord"); - SetupDiscordClient(); - await Login(); - _logger.Information(LogSource.Geekbot, $"Now Connected as {_client.CurrentUser.Username} to {_client.Guilds.Count} Servers"); - await _client.SetGameAsync(_globalSettings.GetKey("Game")); + if (!runParameters.DisableGateway) + { + logger.Information(LogSource.Geekbot, "Connecting to Discord"); + SetupDiscordClient(); + await Login(); + _logger.Information(LogSource.Geekbot, $"Now Connected as {_client.CurrentUser.Username} to {_client.Guilds.Count} Servers"); + await _client.SetGameAsync(_globalSettings.GetKey("Game")); + } RegisterSentry(); _logger.Information(LogSource.Geekbot, "Loading Dependencies and Handlers"); RegisterDependencies(); - await RegisterHandlers(); + if (!runParameters.DisableGateway) await RegisterHandlers(); _logger.Information(LogSource.Api, "Starting Web API"); StartWebApi(); @@ -187,9 +190,9 @@ namespace Geekbot.Bot services.AddSingleton(diceParser); services.AddSingleton(_reactionListener); services.AddSingleton(_guildSettingsManager); - services.AddSingleton(_client); services.AddTransient(e => new HighscoreManager(_databaseInitializer.Initialize(), _userRepository)); services.AddTransient(e => _databaseInitializer.Initialize()); + if (!_runParameters.DisableGateway) services.AddSingleton(_client); _servicesProvider = services.BuildServiceProvider(); } diff --git a/src/Core/RunParameters.cs b/src/Core/RunParameters.cs index 3210587..a886a98 100644 --- a/src/Core/RunParameters.cs +++ b/src/Core/RunParameters.cs @@ -20,6 +20,9 @@ namespace Geekbot.Core [Option('e', "expose-errors", HelpText = "Shows internal errors in the chat (default: false) (env: EXPOSE_ERRORS)")] public bool ExposeErrors { get; set; } = ParamFallback("EXPOSE_ERRORS", false); + + [Option("disable-gateway", HelpText = "Disables the Discord Gateway (default: false) (env: GATEWAY_DISABLE)")] + public bool DisableGateway { get; set; } = ParamFallback("GATEWAY_DISABLE", false); /************************************ * Database * diff --git a/src/Web/WebApiStartup.cs b/src/Web/WebApiStartup.cs index 0c18886..9c8a805 100644 --- a/src/Web/WebApiStartup.cs +++ b/src/Web/WebApiStartup.cs @@ -37,12 +37,14 @@ namespace Geekbot.Web options.AddPolicy("AllowSpecificOrigin", builder => builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()); }); - - services.AddSingleton(commandService); + services.AddSingleton(databaseContext); - services.AddSingleton(client); services.AddSingleton(globalSettings); services.AddSingleton(highscoreManager); + + if (runParameters.DisableGateway) return; + services.AddSingleton(commandService); + services.AddSingleton(client); }) .Configure(app => { From d81fb2a3d977786079a69525f1d17357fb520ea0 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Sun, 19 Sep 2021 16:11:06 +0200 Subject: [PATCH 463/553] Add initial interaction support --- .../Interactions/InteractionController.cs | 90 +++++++++++++++++++ .../Model/ApplicationCommandOption.cs | 16 ++++ .../Interactions/Model/Interaction.cs | 22 +++++ .../Interactions/Model/InteractionData.cs | 14 +++ .../Interactions/Model/InteractionOption.cs | 12 +++ .../Model/InteractionResolvedData.cs | 15 ++++ .../Interactions/Model/InteractionResponse.cs | 13 +++ .../Model/InteractionResponseData.cs | 16 ++++ .../Model/InteractionResponseType.cs | 11 +++ .../Interactions/Model/InteractionType.cs | 9 ++ .../Model/MessageComponents/Component.cs | 7 ++ .../Interactions/Model/Resolved/Channel.cs | 12 +++ .../Model/Resolved/ChannelType.cs | 17 ++++ .../Interactions/Model/Resolved/Member.cs | 16 ++++ .../Interactions/Model/Resolved/RoleTag.cs | 9 ++ .../Interactions/Model/Resolved/Roles.cs | 15 ++++ .../Model/Resolved/ThreadMetadata.cs | 13 +++ .../Interactions/Model/Resolved/User.cs | 21 +++++ src/Web/Web.csproj | 4 + src/Web/WebApiStartup.cs | 5 +- 20 files changed, 336 insertions(+), 1 deletion(-) create mode 100644 src/Web/Controllers/Interactions/InteractionController.cs create mode 100644 src/Web/Controllers/Interactions/Model/ApplicationCommandOption.cs create mode 100644 src/Web/Controllers/Interactions/Model/Interaction.cs create mode 100644 src/Web/Controllers/Interactions/Model/InteractionData.cs create mode 100644 src/Web/Controllers/Interactions/Model/InteractionOption.cs create mode 100644 src/Web/Controllers/Interactions/Model/InteractionResolvedData.cs create mode 100644 src/Web/Controllers/Interactions/Model/InteractionResponse.cs create mode 100644 src/Web/Controllers/Interactions/Model/InteractionResponseData.cs create mode 100644 src/Web/Controllers/Interactions/Model/InteractionResponseType.cs create mode 100644 src/Web/Controllers/Interactions/Model/InteractionType.cs create mode 100644 src/Web/Controllers/Interactions/Model/MessageComponents/Component.cs create mode 100644 src/Web/Controllers/Interactions/Model/Resolved/Channel.cs create mode 100644 src/Web/Controllers/Interactions/Model/Resolved/ChannelType.cs create mode 100644 src/Web/Controllers/Interactions/Model/Resolved/Member.cs create mode 100644 src/Web/Controllers/Interactions/Model/Resolved/RoleTag.cs create mode 100644 src/Web/Controllers/Interactions/Model/Resolved/Roles.cs create mode 100644 src/Web/Controllers/Interactions/Model/Resolved/ThreadMetadata.cs create mode 100644 src/Web/Controllers/Interactions/Model/Resolved/User.cs diff --git a/src/Web/Controllers/Interactions/InteractionController.cs b/src/Web/Controllers/Interactions/InteractionController.cs new file mode 100644 index 0000000..3501c06 --- /dev/null +++ b/src/Web/Controllers/Interactions/InteractionController.cs @@ -0,0 +1,90 @@ +using System; +using System.IO; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; +using Geekbot.Core.GlobalSettings; +using Geekbot.Web.Controllers.Interactions.Model; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Sodium; + +namespace Geekbot.Web.Controllers.Interactions +{ + public class InteractionController : Controller + { + private readonly byte[] publicKeyBytes; + + public InteractionController(IGlobalSettings globalSettings) + { + var publicKey = globalSettings.GetKey("DiscordPublicKey"); + publicKeyBytes = Convert.FromHexString(publicKey.AsSpan()); + } + + [HttpPost] + [Route("/interactions")] + public async Task HandleInteraction( + [FromHeader(Name = "X-Signature-Ed25519")] string signature, + [FromHeader(Name = "X-Signature-Timestamp")] string timestamp + ) + { + if (string.IsNullOrEmpty(signature) || string.IsNullOrEmpty(timestamp)) + { + return BadRequest(); + } + + Request.EnableBuffering(); + if (!(await HasValidSignature(signature, timestamp))) + { + return Unauthorized(); + } + + if (Request.Body.CanSeek) Request.Body.Seek(0, SeekOrigin.Begin); + var interaction = await JsonSerializer.DeserializeAsync(Request.Body, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }).ConfigureAwait(false); + if (interaction is null) throw new JsonException("Failed to deserialize JSON body"); + + return (interaction.Type, interaction.Version) switch + { + (InteractionType.Ping, 1) => Ping(), + (InteractionType.ApplicationCommand, 1) => ApplicationCommand(interaction), + (InteractionType.MessageComponent, 1) => MessageComponent(interaction), + _ => StatusCode(501) + }; + } + + private IActionResult Ping() + { + var response = new InteractionResponse() + { + Type = InteractionResponseType.Pong, + }; + return Ok(response); + } + + private IActionResult ApplicationCommand(Interaction interaction) + { + return StatusCode(501); + } + + private IActionResult MessageComponent(Interaction interaction) + { + return StatusCode(501); + } + + private async Task HasValidSignature(string signature, string timestamp) + { + var timestampBytes = Encoding.Default.GetBytes(timestamp); + var signatureBytes = Convert.FromHexString(signature.AsSpan()); + + var memoryStream = new MemoryStream(); + await Request.Body.CopyToAsync(memoryStream).ConfigureAwait(false); + var body = memoryStream.ToArray(); + + var timestampLength = timestampBytes.Length; + Array.Resize(ref timestampBytes, timestampLength + body.Length); + Array.Copy(body, 0, timestampBytes, timestampLength, body.Length); + + return PublicKeyAuth.VerifyDetached(signatureBytes, timestampBytes, publicKeyBytes); + } + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/ApplicationCommandOption.cs b/src/Web/Controllers/Interactions/Model/ApplicationCommandOption.cs new file mode 100644 index 0000000..794102b --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/ApplicationCommandOption.cs @@ -0,0 +1,16 @@ +namespace Geekbot.Web.Controllers.Interactions.Model +{ + public enum ApplicationCommandOption + { + SubCommand = 1, + SubCommandGroup = 2, + String = 3, + Integer = 4, + Boolean = 5, + User = 6, + Channel = 7, + Role = 8, + Mentionable = 9, + Number = 10, + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/Interaction.cs b/src/Web/Controllers/Interactions/Model/Interaction.cs new file mode 100644 index 0000000..6045504 --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/Interaction.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; + +namespace Geekbot.Web.Controllers.Interactions.Model +{ + public record Interaction + { + public string Id { get; set; } + public string ApplicationId { get; init; } + [Required] + public InteractionType Type { get; set; } + public InteractionData Data { get; init; } + public string GuildId { get; init; } + public string Name { get; init; } + public string Description { get; init; } + public List Options { get; init; } + public bool DefaultPermission { get; init; } + [Required] + public int Version { get; set; } + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/InteractionData.cs b/src/Web/Controllers/Interactions/Model/InteractionData.cs new file mode 100644 index 0000000..cb0f594 --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/InteractionData.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace Geekbot.Web.Controllers.Interactions.Model +{ + public record InteractionData + { + public string Id { get; set; } + public string Name { get; set; } + public int Type { get; set;} + public InteractionResolvedData Resolved { get; set; } + public List Options { get; set; } + public string TargetId { get; set; } + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/InteractionOption.cs b/src/Web/Controllers/Interactions/Model/InteractionOption.cs new file mode 100644 index 0000000..c5acfa7 --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/InteractionOption.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; + +namespace Geekbot.Web.Controllers.Interactions.Model +{ + public record InteractionOption + { + public string Name { get; set; } + public ApplicationCommandOption Type { get; set; } + public string Value { get; set; } + public List Options { get; set; } + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/InteractionResolvedData.cs b/src/Web/Controllers/Interactions/Model/InteractionResolvedData.cs new file mode 100644 index 0000000..ee90f48 --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/InteractionResolvedData.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using Discord; +using Geekbot.Web.Controllers.Interactions.Model.Resolved; + +namespace Geekbot.Web.Controllers.Interactions.Model +{ + public class InteractionResolvedData + { + public Dictionary Users { get; set; } + public Dictionary Members { get; set; } + public Dictionary Roles { get; set; } + public Dictionary Channels { get; set; } + // public Dictionary Messages { get; set; } + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/InteractionResponse.cs b/src/Web/Controllers/Interactions/Model/InteractionResponse.cs new file mode 100644 index 0000000..c3a2a1e --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/InteractionResponse.cs @@ -0,0 +1,13 @@ +using System.Text.Json.Serialization; + +namespace Geekbot.Web.Controllers.Interactions.Model +{ + public record InteractionResponse + { + [JsonPropertyName("type")] + public InteractionResponseType Type { get; set; } + + [JsonPropertyName("data")] + public InteractionData Data { get; set; } + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/InteractionResponseData.cs b/src/Web/Controllers/Interactions/Model/InteractionResponseData.cs new file mode 100644 index 0000000..146e812 --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/InteractionResponseData.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using Discord; +using Geekbot.Web.Controllers.Interactions.Model.MessageComponents; + +namespace Geekbot.Web.Controllers.Interactions.Model +{ + public record InteractionResponseData + { + public bool Tts { get; set; } = false; + public string Content { get; set; } + public List Embeds { get; set; } + public AllowedMentions AllowedMentions { get; set; } + public int Flags { get; set; } + public List Components { get; set; } + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/InteractionResponseType.cs b/src/Web/Controllers/Interactions/Model/InteractionResponseType.cs new file mode 100644 index 0000000..5bc85dc --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/InteractionResponseType.cs @@ -0,0 +1,11 @@ +namespace Geekbot.Web.Controllers.Interactions.Model +{ + public enum InteractionResponseType + { + Pong = 1, + ChannelMessageWithSource = 4, + DeferredChannelMessageWithSource = 5, + DeferredUpdateMessage = 6, + UpdateMessage = 7, + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/InteractionType.cs b/src/Web/Controllers/Interactions/Model/InteractionType.cs new file mode 100644 index 0000000..a8421c5 --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/InteractionType.cs @@ -0,0 +1,9 @@ +namespace Geekbot.Web.Controllers.Interactions.Model +{ + public enum InteractionType + { + Ping = 1, + ApplicationCommand = 2, + MessageComponent = 3, + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/MessageComponents/Component.cs b/src/Web/Controllers/Interactions/Model/MessageComponents/Component.cs new file mode 100644 index 0000000..72097a4 --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/MessageComponents/Component.cs @@ -0,0 +1,7 @@ +namespace Geekbot.Web.Controllers.Interactions.Model.MessageComponents +{ + public record Component + { + + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/Resolved/Channel.cs b/src/Web/Controllers/Interactions/Model/Resolved/Channel.cs new file mode 100644 index 0000000..4b280d9 --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/Resolved/Channel.cs @@ -0,0 +1,12 @@ +namespace Geekbot.Web.Controllers.Interactions.Model.Resolved +{ + public record Channel + { + public string Id { get; set; } + public ChannelType Type { get; set; } + public string Name { get; set; } + public string ParentId { get; set; } + public ThreadMetadata ThreadMetadata { get; set; } + public string Permissions { get; set; } + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/Resolved/ChannelType.cs b/src/Web/Controllers/Interactions/Model/Resolved/ChannelType.cs new file mode 100644 index 0000000..1fbc0af --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/Resolved/ChannelType.cs @@ -0,0 +1,17 @@ +namespace Geekbot.Web.Controllers.Interactions.Model.Resolved +{ + public enum ChannelType + { + GuildText = 0, + Dm = 1, + GuildVoice = 2, + GroupDm = 3, + GuildCategory = 4, + GuildNews = 5, + GuildStore = 6, + GuildNewsThread = 10, + GuildPublicThread = 11, + GuildPrivateThread = 12, + GuildStageVoice = 13, + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/Resolved/Member.cs b/src/Web/Controllers/Interactions/Model/Resolved/Member.cs new file mode 100644 index 0000000..e95a09a --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/Resolved/Member.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; + +namespace Geekbot.Web.Controllers.Interactions.Model.Resolved +{ + public record Member + { + // public User User { get; set; } + public string Nick { get; set; } + public List Roles { get; set; } + public DateTime JoinedAt { get; set; } + public DateTime PremiumSince { get; set; } + public bool Pending { get; set; } + public string Permissions { get; set; } + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/Resolved/RoleTag.cs b/src/Web/Controllers/Interactions/Model/Resolved/RoleTag.cs new file mode 100644 index 0000000..4f35ae1 --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/Resolved/RoleTag.cs @@ -0,0 +1,9 @@ +namespace Geekbot.Web.Controllers.Interactions.Model.Resolved +{ + public record RoleTag + { + public string BotId { get; set; } + public string IntegrationId { get; set; } + public bool PremiumSubscriber { get; set; } + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/Resolved/Roles.cs b/src/Web/Controllers/Interactions/Model/Resolved/Roles.cs new file mode 100644 index 0000000..aab5d7c --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/Resolved/Roles.cs @@ -0,0 +1,15 @@ +namespace Geekbot.Web.Controllers.Interactions.Model.Resolved +{ + public record Roles + { + public string Id { get; set; } + public string Name { get; set; } + public int Color { get; set; } + public bool Hoist { get; set; } + public int Position { get; set; } + public string Permissions { get; set; } + public bool Managed { get; set; } + public bool Mentionable { get; set; } + public RoleTag Tags { get; set; } + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/Resolved/ThreadMetadata.cs b/src/Web/Controllers/Interactions/Model/Resolved/ThreadMetadata.cs new file mode 100644 index 0000000..e43ad89 --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/Resolved/ThreadMetadata.cs @@ -0,0 +1,13 @@ +using System; + +namespace Geekbot.Web.Controllers.Interactions.Model.Resolved +{ + public record ThreadMetadata + { + public bool Archived { get; set; } + public int AutoArchiveDuration { get; set; } + public DateTime ArchiveTimestamp { get; set; } + public bool Locked { get; set; } + public bool Invitable { get; set; } + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/Resolved/User.cs b/src/Web/Controllers/Interactions/Model/Resolved/User.cs new file mode 100644 index 0000000..4ef1f8d --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/Resolved/User.cs @@ -0,0 +1,21 @@ +namespace Geekbot.Web.Controllers.Interactions.Model.Resolved +{ + public record User + { + public string Id { get; set; } + public string Username { get; set; } + public string Discriminator { get; set; } + public string Avatar { get; set; } + public bool Bot { get; set; } + public bool System { get; set; } + public bool MfaEnabled { get; set; } + public string Banner { get; set; } + public int AccentColor { get; set; } + public string Locale { get; set; } + public bool Verified { get; set; } + public string Email { get; set; } + public int Flags { get; set; } + public int PremiumType { get; set; } + public int PublicFlags { get; set; } + } +} \ No newline at end of file diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index a9ffcc4..dc6b09a 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -16,4 +16,8 @@ + + + + diff --git a/src/Web/WebApiStartup.cs b/src/Web/WebApiStartup.cs index 9c8a805..34090d3 100644 --- a/src/Web/WebApiStartup.cs +++ b/src/Web/WebApiStartup.cs @@ -31,7 +31,10 @@ namespace Geekbot.Web }) .ConfigureServices(services => { - services.AddControllers(); + services.AddControllers().AddJsonOptions(options => + { + options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; + }); services.AddCors(options => { options.AddPolicy("AllowSpecificOrigin", From 209887e237847fa9d49c1fd60d59e4e65a16adb7 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Sun, 19 Sep 2021 16:19:40 +0200 Subject: [PATCH 464/553] Add sentry support to the webapi --- src/Web/Web.csproj | 1 + src/Web/WebApiStartup.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index dc6b09a..48fcf86 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -17,6 +17,7 @@
+ diff --git a/src/Web/WebApiStartup.cs b/src/Web/WebApiStartup.cs index 34090d3..f62dd58 100644 --- a/src/Web/WebApiStartup.cs +++ b/src/Web/WebApiStartup.cs @@ -40,6 +40,7 @@ namespace Geekbot.Web options.AddPolicy("AllowSpecificOrigin", builder => builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()); }); + services.AddSentry(); services.AddSingleton(databaseContext); services.AddSingleton(globalSettings); From 60547140ea5838106c58bd61952ae5bc11be671c Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Mon, 20 Sep 2021 01:28:26 +0200 Subject: [PATCH 465/553] Create all interaction models --- .../ApplicationCommand/Command.cs | 73 ++++++++++++ .../ApplicationCommand/CommandType.cs | 21 ++++ .../Interactions/ApplicationCommand/Option.cs | 51 ++++++++ .../ApplicationCommand/OptionChoice.cs | 17 +++ .../ApplicationCommand/OptionChoiceDouble.cs | 14 +++ .../ApplicationCommand/OptionChoiceInteger.cs | 14 +++ .../ApplicationCommand/OptionChoiceString.cs | 14 +++ .../ApplicationCommand/OptionType.cs | 38 ++++++ src/Core/Interactions/Embed/Embed.cs | 88 ++++++++++++++ src/Core/Interactions/Embed/EmbedAuthor.cs | 32 +++++ src/Core/Interactions/Embed/EmbedField.cs | 26 ++++ src/Core/Interactions/Embed/EmbedFooter.cs | 27 +++++ src/Core/Interactions/Embed/EmbedImage.cs | 32 +++++ src/Core/Interactions/Embed/EmbedProvider.cs | 20 ++++ src/Core/Interactions/Embed/EmbedThumbnail.cs | 33 ++++++ src/Core/Interactions/Embed/EmbedTypes.cs | 49 ++++++++ src/Core/Interactions/Embed/EmbedVideo.cs | 32 +++++ .../MessageComponents/ButtonStyle.cs | 31 +++++ .../MessageComponents/Component.cs | 111 ++++++++++++++++++ .../MessageComponents/ComponentEmoji.cs | 33 ++++++ .../MessageComponents/ComponentType.cs | 21 ++++ .../MessageComponents/SelectOption.cs | 38 ++++++ src/Core/Interactions/Request/Interaction.cs | 77 ++++++++++++ .../Interactions/Request/InteractionData.cs | 109 +++++++++++++++++ .../Interactions/Request/InteractionOption.cs | 34 ++++++ .../Request/InteractionResolvedData.cs | 24 ++++ .../Interactions/Request/InteractionType.cs | 10 ++ src/Core/Interactions/Resolved/Attachment.cs | 34 ++++++ src/Core/Interactions/Resolved/Channel.cs | 25 ++++ .../Interactions}/Resolved/ChannelType.cs | 2 +- src/Core/Interactions/Resolved/Emoji.cs | 32 +++++ src/Core/Interactions/Resolved/Member.cs | 27 +++++ src/Core/Interactions/Resolved/Message.cs | 103 ++++++++++++++++ .../Resolved/MessageInteraction.cs | 20 ++++ src/Core/Interactions/Resolved/MessageType.cs | 29 +++++ src/Core/Interactions/Resolved/Reaction.cs | 16 +++ src/Core/Interactions/Resolved/Role.cs | 34 ++++++ src/Core/Interactions/Resolved/RoleTag.cs | 16 +++ .../Interactions/Resolved/ThreadMetadata.cs | 23 ++++ src/Core/Interactions/Resolved/User.cs | 52 ++++++++ .../Response/InteractionResponse.cs | 23 ++++ .../Response/InteractionResponseData.cs | 51 ++++++++ .../Response/InteractionResponseType.cs | 34 ++++++ .../Model/ApplicationCommandOption.cs | 16 --- .../Interactions/Model/Interaction.cs | 22 ---- .../Interactions/Model/InteractionData.cs | 14 --- .../Interactions/Model/InteractionOption.cs | 12 -- .../Model/InteractionResolvedData.cs | 15 --- .../Interactions/Model/InteractionResponse.cs | 13 -- .../Model/InteractionResponseData.cs | 16 --- .../Model/InteractionResponseType.cs | 11 -- .../Interactions/Model/InteractionType.cs | 9 -- .../Model/MessageComponents/Component.cs | 7 -- .../Interactions/Model/Resolved/Channel.cs | 12 -- .../Interactions/Model/Resolved/Member.cs | 16 --- .../Interactions/Model/Resolved/RoleTag.cs | 9 -- .../Interactions/Model/Resolved/Roles.cs | 15 --- .../Model/Resolved/ThreadMetadata.cs | 13 -- .../Interactions/Model/Resolved/User.cs | 21 ---- 59 files changed, 1589 insertions(+), 222 deletions(-) create mode 100644 src/Core/Interactions/ApplicationCommand/Command.cs create mode 100644 src/Core/Interactions/ApplicationCommand/CommandType.cs create mode 100644 src/Core/Interactions/ApplicationCommand/Option.cs create mode 100644 src/Core/Interactions/ApplicationCommand/OptionChoice.cs create mode 100644 src/Core/Interactions/ApplicationCommand/OptionChoiceDouble.cs create mode 100644 src/Core/Interactions/ApplicationCommand/OptionChoiceInteger.cs create mode 100644 src/Core/Interactions/ApplicationCommand/OptionChoiceString.cs create mode 100644 src/Core/Interactions/ApplicationCommand/OptionType.cs create mode 100644 src/Core/Interactions/Embed/Embed.cs create mode 100644 src/Core/Interactions/Embed/EmbedAuthor.cs create mode 100644 src/Core/Interactions/Embed/EmbedField.cs create mode 100644 src/Core/Interactions/Embed/EmbedFooter.cs create mode 100644 src/Core/Interactions/Embed/EmbedImage.cs create mode 100644 src/Core/Interactions/Embed/EmbedProvider.cs create mode 100644 src/Core/Interactions/Embed/EmbedThumbnail.cs create mode 100644 src/Core/Interactions/Embed/EmbedTypes.cs create mode 100644 src/Core/Interactions/Embed/EmbedVideo.cs create mode 100644 src/Core/Interactions/MessageComponents/ButtonStyle.cs create mode 100644 src/Core/Interactions/MessageComponents/Component.cs create mode 100644 src/Core/Interactions/MessageComponents/ComponentEmoji.cs create mode 100644 src/Core/Interactions/MessageComponents/ComponentType.cs create mode 100644 src/Core/Interactions/MessageComponents/SelectOption.cs create mode 100644 src/Core/Interactions/Request/Interaction.cs create mode 100644 src/Core/Interactions/Request/InteractionData.cs create mode 100644 src/Core/Interactions/Request/InteractionOption.cs create mode 100644 src/Core/Interactions/Request/InteractionResolvedData.cs create mode 100644 src/Core/Interactions/Request/InteractionType.cs create mode 100644 src/Core/Interactions/Resolved/Attachment.cs create mode 100644 src/Core/Interactions/Resolved/Channel.cs rename src/{Web/Controllers/Interactions/Model => Core/Interactions}/Resolved/ChannelType.cs (80%) create mode 100644 src/Core/Interactions/Resolved/Emoji.cs create mode 100644 src/Core/Interactions/Resolved/Member.cs create mode 100644 src/Core/Interactions/Resolved/Message.cs create mode 100644 src/Core/Interactions/Resolved/MessageInteraction.cs create mode 100644 src/Core/Interactions/Resolved/MessageType.cs create mode 100644 src/Core/Interactions/Resolved/Reaction.cs create mode 100644 src/Core/Interactions/Resolved/Role.cs create mode 100644 src/Core/Interactions/Resolved/RoleTag.cs create mode 100644 src/Core/Interactions/Resolved/ThreadMetadata.cs create mode 100644 src/Core/Interactions/Resolved/User.cs create mode 100644 src/Core/Interactions/Response/InteractionResponse.cs create mode 100644 src/Core/Interactions/Response/InteractionResponseData.cs create mode 100644 src/Core/Interactions/Response/InteractionResponseType.cs delete mode 100644 src/Web/Controllers/Interactions/Model/ApplicationCommandOption.cs delete mode 100644 src/Web/Controllers/Interactions/Model/Interaction.cs delete mode 100644 src/Web/Controllers/Interactions/Model/InteractionData.cs delete mode 100644 src/Web/Controllers/Interactions/Model/InteractionOption.cs delete mode 100644 src/Web/Controllers/Interactions/Model/InteractionResolvedData.cs delete mode 100644 src/Web/Controllers/Interactions/Model/InteractionResponse.cs delete mode 100644 src/Web/Controllers/Interactions/Model/InteractionResponseData.cs delete mode 100644 src/Web/Controllers/Interactions/Model/InteractionResponseType.cs delete mode 100644 src/Web/Controllers/Interactions/Model/InteractionType.cs delete mode 100644 src/Web/Controllers/Interactions/Model/MessageComponents/Component.cs delete mode 100644 src/Web/Controllers/Interactions/Model/Resolved/Channel.cs delete mode 100644 src/Web/Controllers/Interactions/Model/Resolved/Member.cs delete mode 100644 src/Web/Controllers/Interactions/Model/Resolved/RoleTag.cs delete mode 100644 src/Web/Controllers/Interactions/Model/Resolved/Roles.cs delete mode 100644 src/Web/Controllers/Interactions/Model/Resolved/ThreadMetadata.cs delete mode 100644 src/Web/Controllers/Interactions/Model/Resolved/User.cs diff --git a/src/Core/Interactions/ApplicationCommand/Command.cs b/src/Core/Interactions/ApplicationCommand/Command.cs new file mode 100644 index 0000000..aaf1e74 --- /dev/null +++ b/src/Core/Interactions/ApplicationCommand/Command.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Geekbot.Core.Interactions.ApplicationCommand +{ + /// + public record Command + { + /// + /// unique id of the command + /// + [JsonPropertyName("id")] + public string Id { get; set; } + + /// + /// the type of command, defaults 1 if not set + /// + [JsonPropertyName("type")] + public CommandType Type { get; set; } + + /// + /// unique id of the parent application + /// + [JsonPropertyName("application_id")] + public string ApplicationId { get; set; } + + /// + /// guild id of the command, if not global + /// + [JsonPropertyName("guild_id")] + public string GuildId { get; set; } + + /// + /// 1-32 character name + /// + /// + /// CHAT_INPUT command names and command option names must match the following regex ^[\w-]{1,32}$ with the unicode flag set. If there is a lowercase variant of any letters used, you must use those. + /// Characters with no lowercase variants and/or uncased letters are still allowed. USER and MESSAGE commands may be mixed case and can include spaces. + /// + [JsonPropertyName("name")] + public string Name { get; set; } + + /// + /// 1-100 character description for CHAT_INPUT commands, empty string for USER and MESSAGE commands + /// + /// + /// Exclusive: CHAT_INPUT + /// + [JsonPropertyName("description")] + public string Description { get; set; } + + /// + /// the parameters for the command, max 25 + /// + /// + /// Exclusive: CHAT_INPUT + /// + [JsonPropertyName("options")] + public List