From 501673ba975e1448f1774dbb7737ff8dadf9c1d3 Mon Sep 17 00:00:00 2001 From: Jeroen Heijster Date: Wed, 25 May 2022 01:13:51 +0200 Subject: [PATCH 1/8] Attempts to detect a dead chat. --- SharedCode/Settings/BotSettings.cs | 8 +++++- StatBot/Handlers/ConnectionHandler.cs | 30 +++++++++++++++++++--- StatBot/Handlers/MessageHandler.cs | 2 ++ StatBot/Handlers/PushoverMessageHandler.cs | 30 ++++++++++++++-------- StatBot/Worker.cs | 2 +- StatBot/appsettings.dev.json | 2 +- StatBot/appsettings.json | 3 ++- StatBotConfiguration/MainWindow.xaml | 5 ++++ StatBotConfiguration/MainWindow.xaml.cs | 2 ++ 9 files changed, 66 insertions(+), 18 deletions(-) diff --git a/SharedCode/Settings/BotSettings.cs b/SharedCode/Settings/BotSettings.cs index e9cb270..d3eb929 100644 --- a/SharedCode/Settings/BotSettings.cs +++ b/SharedCode/Settings/BotSettings.cs @@ -81,6 +81,7 @@ public Application(IConfiguration configuration) ShowDiscrim = configuration.GetValue("Application:ShowDiscrim"); ShowAvatar = configuration.GetValue("Application:ShowAvatar"); NicksFileManual = configuration.GetValue("Application:NicksFileManual"); + DeadChatAfter = configuration.GetValue("Application.DeadChatAfter"); } /// @@ -118,6 +119,11 @@ public Application(IConfiguration configuration) /// /// The nicks file manual. public string NicksFileManual { get; set; } + /// + /// Gets or sets the time after which the chat is considered dead. + /// + /// The time after which the chat is considered dead. + public int DeadChatAfter { get; set; } } /// @@ -289,7 +295,7 @@ public PushOver(IConfiguration configuration) /// /// true if [use pushover]; otherwise, false. - [JsonIgnore] + [JsonIgnore] public bool UsePushover { get; set; } } diff --git a/StatBot/Handlers/ConnectionHandler.cs b/StatBot/Handlers/ConnectionHandler.cs index d13f90c..01d417f 100644 --- a/StatBot/Handlers/ConnectionHandler.cs +++ b/StatBot/Handlers/ConnectionHandler.cs @@ -15,6 +15,7 @@ using Discord.WebSocket; using StatBot.Settings; using System; +using System.Threading; using System.Threading.Tasks; namespace StatBot.Handlers @@ -44,16 +45,25 @@ internal class ConnectionHandler /// BotSettings _botSettings; /// + /// The message handler + /// + MessageHandler _messageHandler; + /// + /// The disconnect date time + /// + DateTime _disconnectDateTime; + /// /// Initializes a new instance of the class. /// /// The client. /// The log handler. /// The bot settings. - public ConnectionHandler(DiscordSocketClient client, LogHandler logHandler, BotSettings botSettings) + public ConnectionHandler(DiscordSocketClient client, LogHandler logHandler, BotSettings botSettings, MessageHandler messageHandler) { _client = client; _logHandler = logHandler; _botSettings = botSettings; + _messageHandler = messageHandler; } /// @@ -66,6 +76,7 @@ public async Task Client_Disconnected(Exception arg) { isReconnecting = true; var disconnectTime = DateTime.Now; + _disconnectDateTime = disconnectTime; _ = Task.Run(() => LogDisconnect(disconnectTime)).ConfigureAwait(false); while (_client.ConnectionState == ConnectionState.Disconnected || _client.ConnectionState == ConnectionState.Disconnecting) @@ -87,6 +98,19 @@ public async Task Client_Disconnected(Exception arg) } System.Threading.Thread.Sleep(5000); } + CheckDeadChat(); + } + } + + /// + /// Checks if the chat has gone dead after a disconnect. + /// + public async void CheckDeadChat() + { + Thread.Sleep(_botSettings.Application.DeadChatAfter); + if (_messageHandler.LastMessage < _disconnectDateTime.AddMilliseconds(_botSettings.Application.DeadChatAfter)) + { + _logHandler.LogMessage("Dead chat after disconnect detected.", _client); } } @@ -102,7 +126,7 @@ public void LogDisconnect(DateTime disconnectTime) } else { - System.Threading.Thread.Sleep(_botSettings.Application.NotificationDelay); + Thread.Sleep(_botSettings.Application.NotificationDelay); if ((_client.ConnectionState != ConnectionState.Connected)) { _logHandler.LogMessage($"The connection to the server has been lost at {disconnectTime}.", _client); @@ -119,7 +143,7 @@ public async Task ReConnect() await _client.LoginAsync(TokenType.Bot, _botSettings.Discord.Token); await _client.StartAsync(); - System.Threading.Thread.Sleep(10000); + Thread.Sleep(10000); } } } diff --git a/StatBot/Handlers/MessageHandler.cs b/StatBot/Handlers/MessageHandler.cs index dc9a3d7..f44b2fa 100644 --- a/StatBot/Handlers/MessageHandler.cs +++ b/StatBot/Handlers/MessageHandler.cs @@ -85,6 +85,7 @@ public class MessageHandler /// The file handler /// private FileHandler _fileHandler; + public DateTime LastMessage; /// @@ -110,6 +111,7 @@ public MessageHandler(DiscordSocketClient client, BotSettings botSettings) public Task MessageReceived(SocketMessage message) { var file = _fileHandler.CheckAndGetFilePath(message); + LastMessage = DateTime.Now; if (!message.Author.IsBot) { var user = new User(message.Author); diff --git a/StatBot/Handlers/PushoverMessageHandler.cs b/StatBot/Handlers/PushoverMessageHandler.cs index 689d581..23fc84b 100644 --- a/StatBot/Handlers/PushoverMessageHandler.cs +++ b/StatBot/Handlers/PushoverMessageHandler.cs @@ -45,23 +45,31 @@ public PushoverMessageHandler(string pushoverApi, string pushoverUserKey) /// The message. public async void PushMessage(string message) { - using (HttpClient httpClient = new HttpClient()) + try { - //specify to use TLS 1.2 as default connection - ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + using (HttpClient httpClient = new HttpClient()) + { + //specify to use TLS 1.2 as default connection + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; - MultipartFormDataContent form = new MultipartFormDataContent(); - form.Add(new StringContent(PushoverApi), "\"token\""); - form.Add(new StringContent(PushoverUserKey), "\"user\""); - form.Add(new StringContent(message), "\"message\""); - // Remove content type that is not in the docs - foreach (var param in form) - param.Headers.ContentType = null; + MultipartFormDataContent form = new MultipartFormDataContent(); + form.Add(new StringContent(PushoverApi), "\"token\""); + form.Add(new StringContent(PushoverUserKey), "\"user\""); + form.Add(new StringContent(message), "\"message\""); + // Remove content type that is not in the docs + foreach (var param in form) + param.Headers.ContentType = null; - await httpClient.PostAsync("https://api.pushover.net/1/messages.json", form); + await httpClient.PostAsync("https://api.pushover.net/1/messages.json", form); + } + } + catch + { + //Doesn't work? Too bad. } } + } } diff --git a/StatBot/Worker.cs b/StatBot/Worker.cs index 5ba6d2e..90ddd64 100644 --- a/StatBot/Worker.cs +++ b/StatBot/Worker.cs @@ -78,8 +78,8 @@ public void DoWork() _botSettings.VerifySettings(); _client = new DiscordSocketClient(); _logHandler = new LogHandler(_botSettings); - _connectionHandler = new ConnectionHandler(_client, _logHandler, _botSettings); _messageHandler = new MessageHandler(_client, _botSettings); + _connectionHandler = new ConnectionHandler(_client, _logHandler, _botSettings, _messageHandler); _client.MessageReceived += _messageHandler.MessageReceived; _client.Disconnected += _connectionHandler.Client_Disconnected; _client.LoginAsync(TokenType.Bot, _botSettings.Discord.Token); diff --git a/StatBot/appsettings.dev.json b/StatBot/appsettings.dev.json index 785ace3..589ed62 100644 --- a/StatBot/appsettings.dev.json +++ b/StatBot/appsettings.dev.json @@ -1,6 +1,5 @@ { "Discord": { - "Token": "", "DebugChannelId": "", "Commands": { "Prefix": "!", @@ -31,6 +30,7 @@ // single "LoggingFileName": "single", "NotificationDelay": 30000, + "DeadChatAfter": 3600000, "PushOver": { //Leave values empty if you don't want to use it. "ApiKey": "", diff --git a/StatBot/appsettings.json b/StatBot/appsettings.json index 8d9d3e0..ea9f7b6 100644 --- a/StatBot/appsettings.json +++ b/StatBot/appsettings.json @@ -31,12 +31,13 @@ // single "LoggingFileName": "channelid", "NotificationDelay": 30000, + "DeadChatAfter": 3600000, "PushOver": { //Leave values empty if you don't want to use it. "ApiKey": "", "UserKey": "" }, - //If true, will generate the nicks file automatically before generating the stats, if StatBot isn't handling generating the stats, it will do it every 30 minutes. + //If true, will generate the nicks file automatically before generating the stats, if StatBot isn't handling generating the stats, it will do it every 30 minutes. "CreateNicksFileAutomatically": true, "ShowDiscrim": false, "ShowAvatar": true, diff --git a/StatBotConfiguration/MainWindow.xaml b/StatBotConfiguration/MainWindow.xaml index 76d1ea7..fc7afb0 100644 --- a/StatBotConfiguration/MainWindow.xaml +++ b/StatBotConfiguration/MainWindow.xaml @@ -130,6 +130,7 @@ + public bool IsExcludedFromStats; /// + /// The override name + /// + public string OverrideName; + /// /// The old users /// public List OldUsers; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The author. public User(SocketUser author) @@ -67,7 +71,7 @@ public User(SocketUser author) } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The identifier. /// The username. @@ -75,8 +79,9 @@ public User(SocketUser author) /// The avatar URI. /// The is bot. /// The is excluded from stats. + /// The name to use as an override. /// The old users. - public User(object id, object username, object discrim, object avatarUri, object isBot, object isExcludedFromStats, List oldUsers = null) + public User(object id, object username, object discrim, object avatarUri, object isBot, object isExcludedFromStats, object overrideName, List oldUsers = null) { Id = Convert.ToUInt64(id); Username = (string)username; @@ -84,6 +89,7 @@ public User(object id, object username, object discrim, object avatarUri, object AvatarUri = (string)avatarUri; IsBot = (Int64)isBot == 1; IsExcludedFromStats = (Int64)isExcludedFromStats == 1; + OverrideName = overrideName == null ? (string)OverrideName : null; OldUsers = oldUsers; } } diff --git a/StatBot/Database/Statbot.db b/StatBot/Database/Statbot.db index 9fb48458f735758a0e3384512c20a7e0560432bf..855e9494181cbe0fcd804670fe83e8a3ce267174 100644 GIT binary patch delta 451 zcmZo@U};#uGC^9}*`H1t;#))Cf zTAD zXc|nu!mhz6xcM*pBu2)0lP7Qn1vwh9iHGVlGGykZq*eg!%`8ccPb@9T2lL}G91@S| zHbI^ghWpZu;fCzes^T0?wUhO^jAghS-9lW06g=~aQ;SLz{QVR{fsA42(%VrF!nEX=2F)Fh(M4i12Du!rH+Hr4>e#l;z$A>v>|zy#0aCcZtwSb|}* zHUCKg4o3bz3_!%RS#ZGzeikN1CXPi04Vw%&1U7RV_`%Nu4h;qdMj*`#RPvdB^Z)yd N3XEKv83q3H0|2G8gPs5Y delta 436 zcmZozz|zpbGC^8UpMilv0El^jm=TC8Ch8b7>Q78i;Nr_*zr@PU&BCR+Sx{gtvl07Y zhM(g4`i#xeC5cHnsl|mkN%1AAxdriHZoCnO0RLn$7CAB1s}l{02wbpjHXJMO`F+Sk1%oSumK&&z@Vu) z`3k!RBj4t~?2{N7XHK5L8N|WM<>cz_>Bl>{nahg1u`x!E9c&x>omriOTpgRZG}yteaxO`1 ztb?+(VGe@?L1P+FTwI*786plgA7aVm9KJo1zp#jG4&vV=zyS_v1_mZzfWGIS7{I#8 rfm>iRx5L-`%?bh!_$Mw--WZC@xKBEEvqkDaT diff --git a/StatBot/Database/Statbot.db-journal b/StatBot/Database/Statbot.db-journal new file mode 100644 index 0000000000000000000000000000000000000000..b844ed3fd3dc34dee5319842c38d44d29ebc0766 GIT binary patch literal 4616 zcmeI$F%AF_429vR7K`8_?tcM```8R>atHaFCfaoB*Nya|&o#VjlKE5Lfa+&~n0>oY iwmk3Q2?P*8009ILKmY**5I_I{1Q7U4z=Eaw?{ff-R|mcT literal 0 HcmV?d00001 diff --git a/StatBot/Database/UpdateScripts/1.sql b/StatBot/Database/UpdateScripts/1.sql new file mode 100644 index 0000000..30792ee --- /dev/null +++ b/StatBot/Database/UpdateScripts/1.sql @@ -0,0 +1,4 @@ +ALTER TABLE Users +Add OverrideName varchar(max) +UPDATE [Database] +SET Version = 1; \ No newline at end of file diff --git a/StatBot/Handlers/CommandHandler.cs b/StatBot/Handlers/CommandHandler.cs index 87818a5..cecfc2c 100644 --- a/StatBot/Handlers/CommandHandler.cs +++ b/StatBot/Handlers/CommandHandler.cs @@ -4,7 +4,7 @@ // Created : 01-13-2018 // // Last Modified By : Jeroen Heijster -// Last Modified On : 17-05-2022 +// Last Modified On : 04-06-2022 // *********************************************************************** // // Copyright © 2022 @@ -55,77 +55,224 @@ public class CommandHandler /// The nick section /// private readonly string nickSection; + + /// + /// The client + /// + internal DiscordSocketClient _client; /// /// The bot settings /// private readonly BotSettings _botSettings; /// + /// Gets or sets the admin user identifier. + /// + /// The admin user identifier. + private readonly ulong adminUserId; + /// + /// Gets or sets a value indicating whether [server admins are allowed to use these commands]. + /// + /// true if [server admins are allowed to use these commands]; otherwise, false. + private readonly bool allowServerAdmins; + /// + /// Gets or sets the link user command. + /// + /// The link user command. + private readonly string linkUserCommand; + /// + /// Gets or sets the override username command. + /// + /// The override username command. + private readonly string overrideUsernameCommand; + /// + /// The remove override username command + /// + private readonly string removeOverrideUsernameCommand; + /// + /// The use command include + /// + private readonly bool useCommandInclude; + /// + /// The use command exclude + /// + private readonly bool useCommandExclude; + /// + /// The use command stats + /// + private readonly bool useCommandStats; + /// + /// The use link user command + /// + private readonly bool useLinkUserCommand; + /// + /// The use override username command + /// + private readonly bool useOverrideUsernameCommand; + /// + /// The use remove override username command + /// + private readonly bool useRemoveOverrideUsernameCommand; + /// /// Initializes a new instance of the class. /// + /// The client. /// The bot settings. - public CommandHandler(BotSettings botSettings) + public CommandHandler(DiscordSocketClient client, BotSettings botSettings) { _botSettings = botSettings; + _client = client; commandExclude = botSettings.Discord.Commands.Exclude; commandInclude = botSettings.Discord.Commands.Include; statsCommand = botSettings.Discord.Commands.Stats.Command; statsUrl = botSettings.Discord.Commands.Stats.Url; + adminUserId = botSettings.Discord.Commands.AdminCommands.AdminUserId; + allowServerAdmins = botSettings.Discord.Commands.AdminCommands.AllowServerAdmins; + linkUserCommand = botSettings.Discord.Commands.AdminCommands.LinkUserCommand; + overrideUsernameCommand = botSettings.Discord.Commands.AdminCommands.OverrideUsernameCommand; + removeOverrideUsernameCommand = botSettings.Discord.Commands.AdminCommands.RemoveOverrideUsernameCommand; commandPrefix = botSettings.Discord.Commands.Prefix; nickFile = $"{botSettings.mIRCStats.Path}\\{botSettings.mIRCStats.NicksFile}"; nickSection = botSettings.mIRCStats.NickSection; + useCommandInclude = !string.IsNullOrEmpty(commandInclude); + useCommandExclude = !string.IsNullOrEmpty(commandExclude); + useCommandStats = !string.IsNullOrEmpty(statsCommand) && !string.IsNullOrEmpty(statsUrl); + useLinkUserCommand = !string.IsNullOrEmpty(linkUserCommand); + useOverrideUsernameCommand = !string.IsNullOrEmpty(overrideUsernameCommand); + useRemoveOverrideUsernameCommand = !string.IsNullOrEmpty(removeOverrideUsernameCommand); } /// /// Handles the commands that are available. /// /// The command. + /// The full command. /// The user who initiated the command. /// The channel. - /// The userid. - public void HandleCommand(string command, string user, ISocketMessageChannel channel, ulong userid) + /// The author. + public void HandleCommand(string command, string[] fullCommand, string user, ISocketMessageChannel channel, SocketUser author) { string excludeString = $"{user}; MODE=ISEXCLUDED"; string includeString = $"{user};"; if (!string.IsNullOrEmpty(commandPrefix)) { - if (!string.IsNullOrEmpty(commandExclude) && command == $"{commandPrefix}{commandExclude}") + if (useCommandInclude && command == $"{commandPrefix}{commandInclude}") + HandleIncludeCommand(command, user, channel, author.Id, excludeString, includeString); + else if (useCommandExclude && command == $"{commandPrefix}{commandExclude}") + HandleExcludeCommand(command, user, channel, author.Id, excludeString, includeString); + else if (useCommandStats && command == $"{commandPrefix}{statsCommand}") + channel.SendMessageAsync(statsUrl); + else if (useLinkUserCommand && command == $"{commandPrefix}{linkUserCommand}") + HandleLinkUserCommand(author.Id, user); + else if (useOverrideUsernameCommand && command == $"{commandPrefix}{overrideUsernameCommand}") + HandleOverrideUsernameCommand(fullCommand, author.Id, user, author); + else if (useRemoveOverrideUsernameCommand && command == $"{commandPrefix}{removeOverrideUsernameCommand}") + HandleRemoveOverrideUsernameCommand(fullCommand, user, channel, author.Id, excludeString, includeString, author); + } + } + + /// + /// Handles the remove override username command. + /// + /// The full command. + /// The user. + /// The channel. + /// The userid. + /// The exclude string. + /// The include string. + /// The author. + private void HandleRemoveOverrideUsernameCommand(string[] fullCommand, string user, ISocketMessageChannel channel, ulong userid, string excludeString, string includeString, SocketUser author) + { + var guildUser = (_client.GetUser(author.Id) as SocketGuildUser); + if (_botSettings.Application.CreateNicksFileAutomatically && + ((guildUser.GuildPermissions.Administrator && _botSettings.Discord.Commands.AdminCommands.AllowServerAdmins) || + _botSettings.Discord.Commands.AdminCommands.AdminUserId == author.Id)) + { + Database.DatabaseHandlers.UserHandler.OverrideUsername(Convert.ToUInt64(fullCommand[1]), null); + } + } + + /// + /// Handles the override username command. + /// + /// The full command. + /// The userid. + /// The user. + /// The author. + private void HandleOverrideUsernameCommand(string[] fullCommand, ulong userid, string user, SocketUser author) + { + var guildUser = (_client.GetUser(author.Id) as SocketGuildUser); + if (_botSettings.Application.CreateNicksFileAutomatically && + ((guildUser.GuildPermissions.Administrator && _botSettings.Discord.Commands.AdminCommands.AllowServerAdmins) || + _botSettings.Discord.Commands.AdminCommands.AdminUserId == author.Id)) + { + Database.DatabaseHandlers.UserHandler.OverrideUsername(Convert.ToUInt64(fullCommand[1]), user); + } + } + + /// + /// Handles the link user command. + /// + /// The userid. + /// The user. + private void HandleLinkUserCommand(ulong userid, string user) + { + if (_botSettings.Application.CreateNicksFileAutomatically) + { + Database.DatabaseHandlers.UserHandler.AddOldUsername(userid, user); + } + } + + /// + /// Handles the exclude command. + /// + /// The command. + /// The user. + /// The channel. + /// The userid. + /// The exclude string. + /// The include string. + private void HandleExcludeCommand(string command, string user, ISocketMessageChannel channel, ulong userid, string excludeString, string includeString) + { + if (_botSettings.Application.CreateNicksFileAutomatically) + { + Database.DatabaseHandlers.UserHandler.ExcludeFromStats(userid, true); + } + else + { + if (!File.ReadLines(nickFile).Any(line => line.Contains(excludeString))) { - if (_botSettings.Application.CreateNicksFileAutomatically) - { - Database.DatabaseHandlers.UserHandler.ExcludeFromStats(userid, true); - } - else - { - if (!File.ReadLines(nickFile).Any(line => line.Contains(excludeString))) - { - File.WriteAllText(nickFile, File.ReadAllText(nickFile).Replace(nickSection, $"{nickSection}{Environment.NewLine}{excludeString}")); - } - if (!File.ReadLines(nickFile).Any(line => line.Contains(includeString))) - { - File.WriteAllText(nickFile, File.ReadAllText(nickFile).Replace(includeString, string.Empty)); - } - } + File.WriteAllText(nickFile, File.ReadAllText(nickFile).Replace(nickSection, $"{nickSection}{Environment.NewLine}{excludeString}")); } - if (!string.IsNullOrEmpty(commandInclude) && command == $"{commandPrefix}{commandInclude}") + if (!File.ReadLines(nickFile).Any(line => line.Contains(includeString))) { - if (_botSettings.Application.CreateNicksFileAutomatically) - { - Database.DatabaseHandlers.UserHandler.ExcludeFromStats(userid, false); - } - else - { - if (!File.ReadLines(nickFile).Any(line => line.Contains(includeString))) - { - File.WriteAllText(nickFile, File.ReadAllText(nickFile).Replace(nickSection, $"{nickSection}{Environment.NewLine}{includeString}")); - } - if (File.ReadLines(nickFile).Any(line => line.Contains(excludeString))) - { - File.WriteAllText(nickFile, File.ReadAllText(nickFile).Replace(excludeString, string.Empty)); - } - } + File.WriteAllText(nickFile, File.ReadAllText(nickFile).Replace(includeString, string.Empty)); } - if (!string.IsNullOrEmpty(statsCommand) && !string.IsNullOrEmpty(statsUrl) && command == $"{commandPrefix}{statsCommand}") + } + } + + /// + /// Handles the include command. + /// + /// The command. + /// The user. + /// The channel. + /// The userid. + /// The exclude string. + /// The include string. + private void HandleIncludeCommand(string command, string user, ISocketMessageChannel channel, ulong userid, string excludeString, string includeString) + { + if (_botSettings.Application.CreateNicksFileAutomatically) + { + Database.DatabaseHandlers.UserHandler.ExcludeFromStats(userid, false); + } + else + { + if (!File.ReadLines(nickFile).Any(line => line.Contains(includeString))) { - channel.SendMessageAsync(statsUrl); + File.WriteAllText(nickFile, File.ReadAllText(nickFile).Replace(nickSection, $"{nickSection}{Environment.NewLine}{includeString}")); + } + if (File.ReadLines(nickFile).Any(line => line.Contains(excludeString))) + { + File.WriteAllText(nickFile, File.ReadAllText(nickFile).Replace(excludeString, string.Empty)); } } } diff --git a/StatBot/Handlers/ConnectionHandler.cs b/StatBot/Handlers/ConnectionHandler.cs index 01d417f..e07f568 100644 --- a/StatBot/Handlers/ConnectionHandler.cs +++ b/StatBot/Handlers/ConnectionHandler.cs @@ -4,7 +4,7 @@ // Created : 13-05-2022 // // Last Modified By : Jeroen Heijster -// Last Modified On : 15-05-2022 +// Last Modified On : 25-05-2022 // *********************************************************************** // // Copyright © 2022 @@ -53,11 +53,16 @@ internal class ConnectionHandler /// DateTime _disconnectDateTime; /// + /// The dead chat thread + /// + Thread deadChatThread; + /// /// Initializes a new instance of the class. /// /// The client. /// The log handler. /// The bot settings. + /// The message handler. public ConnectionHandler(DiscordSocketClient client, LogHandler logHandler, BotSettings botSettings, MessageHandler messageHandler) { _client = client; @@ -74,6 +79,15 @@ public async Task Client_Disconnected(Exception arg) { if (!isReconnecting) { + try + { + if (deadChatThread != null) + { + deadChatThread.Interrupt(); + deadChatThread.Join(); + } + } + catch { } isReconnecting = true; var disconnectTime = DateTime.Now; _disconnectDateTime = disconnectTime; @@ -98,7 +112,7 @@ public async Task Client_Disconnected(Exception arg) } System.Threading.Thread.Sleep(5000); } - CheckDeadChat(); + deadChatThread = new Thread(new ThreadStart(CheckDeadChat)); } } @@ -107,10 +121,17 @@ public async Task Client_Disconnected(Exception arg) /// public async void CheckDeadChat() { - Thread.Sleep(_botSettings.Application.DeadChatAfter); - if (_messageHandler.LastMessage < _disconnectDateTime.AddMilliseconds(_botSettings.Application.DeadChatAfter)) + + try + { + Thread.Sleep(_botSettings.Application.DeadChatAfter); + if (_messageHandler.LastMessage < _disconnectDateTime.AddMilliseconds(_botSettings.Application.DeadChatAfter)) + { + _logHandler.LogMessage("Dead chat after disconnect detected.", _client); + } + } + catch (ThreadInterruptedException e) { - _logHandler.LogMessage("Dead chat after disconnect detected.", _client); } } diff --git a/StatBot/Handlers/FileHandler.cs b/StatBot/Handlers/FileHandler.cs index beba131..61e092d 100644 --- a/StatBot/Handlers/FileHandler.cs +++ b/StatBot/Handlers/FileHandler.cs @@ -4,7 +4,7 @@ // Created : 12-11-2017 // // Last Modified By : Jeroen Heijster -// Last Modified On : 15-05-2022 +// Last Modified On : 20-05-2022 // *********************************************************************** // // Copyright © 2022 diff --git a/StatBot/Handlers/LogHandler.cs b/StatBot/Handlers/LogHandler.cs index 1ef023e..557f7ef 100644 --- a/StatBot/Handlers/LogHandler.cs +++ b/StatBot/Handlers/LogHandler.cs @@ -4,7 +4,7 @@ // Created : 13-05-2022 // // Last Modified By : Jeroen Heijster -// Last Modified On : 16-05-2022 +// Last Modified On : 18-05-2022 // *********************************************************************** // // Copyright © 2022 diff --git a/StatBot/Handlers/MessageHandler.cs b/StatBot/Handlers/MessageHandler.cs index f44b2fa..61a0ada 100644 --- a/StatBot/Handlers/MessageHandler.cs +++ b/StatBot/Handlers/MessageHandler.cs @@ -4,7 +4,7 @@ // Created : 12-12-2017 // // Last Modified By : Jeroen Heijster -// Last Modified On : 17-05-2022 +// Last Modified On : 01-06-2022 // *********************************************************************** // // Copyright © 2022 @@ -85,6 +85,9 @@ public class MessageHandler /// The file handler /// private FileHandler _fileHandler; + /// + /// The last message + /// public DateTime LastMessage; @@ -97,7 +100,7 @@ public MessageHandler(DiscordSocketClient client, BotSettings botSettings) { _client = client; _botSettings = botSettings; - _commandHandler = new CommandHandler(botSettings); + _commandHandler = new CommandHandler(_client, botSettings); _fileHandler = new FileHandler(botSettings); commandPrefix = _botSettings.Discord.Commands.Prefix; commandExpression = new VerbalExpressions().StartOfLine().Then(commandPrefix).Anything(); @@ -125,11 +128,11 @@ public Task MessageReceived(SocketMessage message) if (string.IsNullOrEmpty(message.Content) || message.Content == message.Embeds.FirstOrDefault().Url) { - textMessage = $"[{DateTime.Now.ToString("yyyy-MM-dd HH':'mm':'ss")}] <{message.Author.Username.Replace(' ', '_')}#{message.Author.Discriminator}> {message.Embeds.FirstOrDefault().Url}"; + textMessage = $"[{message.Timestamp.ToString("yyyy-MM-dd HH':'mm':'ss")}] <{message.Author.Username.Replace(' ', '_')}#{message.Author.Discriminator}> {message.Embeds.FirstOrDefault().Url}"; } else { - textMessage = $"[{DateTime.Now.ToString("yyyy-MM-dd HH':'mm':'ss")}] <{message.Author.Username.Replace(' ', '_')}#{message.Author.Discriminator}> {HandleMessage(message.Content, $"{message.Author.Username}#{message.Author.Discriminator}", message.Channel, message.Author.Id)} - {message.Embeds.FirstOrDefault().Url}"; + textMessage = $"[{message.Timestamp.ToString("yyyy-MM-dd HH':'mm':'ss")}] <{message.Author.Username.Replace(' ', '_')}#{message.Author.Discriminator}> {HandleMessage(message.Content, $"{message.Author.Username}#{message.Author.Discriminator}", message.Channel, message.Author)} - {message.Embeds.FirstOrDefault().Url}"; } } else if (message.Attachments != null && @@ -138,11 +141,11 @@ public Task MessageReceived(SocketMessage message) if ((string.IsNullOrEmpty(message.Content) || message.Content == message.Attachments.FirstOrDefault().Url) && message.Embeds.Any()) { - textMessage = $"[{DateTime.Now.ToString("yyyy-MM-dd HH':'mm':'ss")}] <{message.Author.Username.Replace(' ', '_')}#{message.Author.Discriminator}> {message.Embeds.FirstOrDefault().Url}"; + textMessage = $"[{message.Timestamp.ToString("yyyy-MM-dd HH':'mm':'ss")}] <{message.Author.Username.Replace(' ', '_')}#{message.Author.Discriminator}> {message.Embeds.FirstOrDefault().Url}"; } else { - textMessage = $"[{DateTime.Now.ToString("yyyy-MM-dd HH':'mm':'ss")}] <{message.Author.Username.Replace(' ', '_')}#{message.Author.Discriminator}> {HandleMessage(message.Content, $"{message.Author.Username}#{message.Author.Discriminator}", message.Channel, message.Author.Id)} - {message.Attachments.FirstOrDefault().Url}"; + textMessage = $"[{message.Timestamp.ToString("yyyy-MM-dd HH':'mm':'ss")}] <{message.Author.Username.Replace(' ', '_')}#{message.Author.Discriminator}> {HandleMessage(message.Content, $"{message.Author.Username}#{message.Author.Discriminator}", message.Channel, message.Author)} - {message.Attachments.FirstOrDefault().Url}"; } } else if (message.Stickers != null && @@ -151,16 +154,16 @@ public Task MessageReceived(SocketMessage message) if (string.IsNullOrEmpty(message.Content) || message.Content == message.Stickers.FirstOrDefault().GetStickerUrl()) { - textMessage = $"[{DateTime.Now.ToString("yyyy-MM-dd HH':'mm':'ss")}] <{message.Author.Username.Replace(' ', '_')}#{message.Author.Discriminator}> {message.Stickers.FirstOrDefault().GetStickerUrl()}"; + textMessage = $"[{message.Timestamp.ToString("yyyy-MM-dd HH':'mm':'ss")}] <{message.Author.Username.Replace(' ', '_')}#{message.Author.Discriminator}> {message.Stickers.FirstOrDefault().GetStickerUrl()}"; } else { - textMessage = $"[{DateTime.Now.ToString("yyyy-MM-dd HH':'mm':'ss")}] <{message.Author.Username.Replace(' ', '_')}#{message.Author.Discriminator}> {HandleMessage(message.Content, $"{message.Author.Username}#{message.Author.Discriminator}", message.Channel, message.Author.Id)} - {message.Stickers.FirstOrDefault().GetStickerUrl()}"; + textMessage = $"[{message.Timestamp.ToString("yyyy-MM-dd HH':'mm':'ss")}] <{message.Author.Username.Replace(' ', '_')}#{message.Author.Discriminator}> {HandleMessage(message.Content, $"{message.Author.Username}#{message.Author.Discriminator}", message.Channel, message.Author)} - {message.Stickers.FirstOrDefault().GetStickerUrl()}"; } } else { - textMessage = $"[{DateTime.Now.ToString("yyyy-MM-dd HH':'mm':'ss")}] <{message.Author.Username.Replace(' ', '_')}#{message.Author.Discriminator}> {HandleMessage(message.Content, $"{message.Author.Username}#{message.Author.Discriminator}", message.Channel, message.Author.Id)}"; + textMessage = $"[{message.Timestamp.ToString("yyyy-MM-dd HH':'mm':'ss")}] <{message.Author.Username.Replace(' ', '_')}#{message.Author.Discriminator}> {HandleMessage(message.Content, $"{message.Author.Username}#{message.Author.Discriminator}", message.Channel, message.Author)}"; } text.WriteLine(textMessage); Console.WriteLine($"#{message.Channel} - {textMessage}"); @@ -175,9 +178,9 @@ public Task MessageReceived(SocketMessage message) /// The message. /// Name of the user. /// The channel. - /// The userid. + /// The author. /// The parsed message. - public string HandleMessage(string message, string userName, ISocketMessageChannel channel, ulong userid) + public string HandleMessage(string message, string userName, ISocketMessageChannel channel, SocketUser author) { message = Regex.Replace(message, @"\r\n?|\n", " "); StringBuilder returnMessage = new StringBuilder(); @@ -194,7 +197,7 @@ public string HandleMessage(string message, string userName, ISocketMessageChann if (firstPart && commandExpression.IsMatch(messagePart)) { - _commandHandler.HandleCommand(messagePart, userName.Replace(' ', '_'), channel, userid); + _commandHandler.HandleCommand(messagePart, messageParts, userName.Replace(' ', '_'), channel, author); } if (emojiExpression.IsMatch(messagePart) || animatedEmojiExpression.IsMatch(messagePart)) diff --git a/StatBot/Handlers/PushoverMessageHandler.cs b/StatBot/Handlers/PushoverMessageHandler.cs index 23fc84b..b94b179 100644 --- a/StatBot/Handlers/PushoverMessageHandler.cs +++ b/StatBot/Handlers/PushoverMessageHandler.cs @@ -4,7 +4,7 @@ // Created : 12-05-2022 // // Last Modified By : Jeroen Heijster -// Last Modified On : 16-05-2022 +// Last Modified On : 24-05-2022 // *********************************************************************** // // Copyright © 2022 diff --git a/StatBot/Handlers/mIRCStatsHandler.cs b/StatBot/Handlers/mIRCStatsHandler.cs index 7f948c9..8180a00 100644 --- a/StatBot/Handlers/mIRCStatsHandler.cs +++ b/StatBot/Handlers/mIRCStatsHandler.cs @@ -4,7 +4,7 @@ // Created : 15-05-2022 // // Last Modified By : Jeroen Heijster -// Last Modified On : 17-05-2022 +// Last Modified On : 25-05-2022 // *********************************************************************** // // Copyright © 2022 @@ -100,7 +100,12 @@ private void GenerateNicksFile() sb.Append("; "); sb.Append($"IMAGE={user.AvatarUri.Replace("?size=128", "")}"); } - if (!_botSettings.Application.ShowDiscrim) + if (!string.IsNullOrEmpty(user.OverrideName)) + { + sb.Append("; "); + sb.Append($"NAME={user.OverrideName.Replace(' ', '_')}"); + } + else if (!_botSettings.Application.ShowDiscrim) { sb.Append("; "); sb.Append($"NAME={user.Username.Replace(' ', '_')}"); diff --git a/StatBot/Program.cs b/StatBot/Program.cs index f172d93..bb077b2 100644 --- a/StatBot/Program.cs +++ b/StatBot/Program.cs @@ -4,7 +4,7 @@ // Created : 12-11-2017 // // Last Modified By : Jeroen Heijster -// Last Modified On : 15-05-2022 +// Last Modified On : 18-05-2022 // *********************************************************************** // // Copyright © 2022 diff --git a/StatBot/Properties/AssemblyInfo.cs b/StatBot/Properties/AssemblyInfo.cs index 7ca1bba..a8a96ed 100644 --- a/StatBot/Properties/AssemblyInfo.cs +++ b/StatBot/Properties/AssemblyInfo.cs @@ -4,7 +4,7 @@ // Created : 05-11-2022 // // Last Modified By : Jeroen Heijster -// Last Modified On : 15-05-2022 +// Last Modified On : 18-05-2022 // *********************************************************************** // // Copyright © 2022 diff --git a/StatBot/StatBot.csproj b/StatBot/StatBot.csproj index 65ba01f..5a74b60 100644 --- a/StatBot/StatBot.csproj +++ b/StatBot/StatBot.csproj @@ -30,6 +30,7 @@ + @@ -47,6 +48,9 @@ Always + + Always + diff --git a/StatBot/Worker.cs b/StatBot/Worker.cs index 90ddd64..1737d56 100644 --- a/StatBot/Worker.cs +++ b/StatBot/Worker.cs @@ -4,7 +4,7 @@ // Created : 05-13-2022 // // Last Modified By : Jeroen Heijster -// Last Modified On : 17-05-2022 +// Last Modified On : 30-05-2022 // *********************************************************************** // // Copyright © 2022 @@ -73,11 +73,12 @@ public Worker(IConfiguration configuration) /// public void DoWork() { - DatabaseHandler.CreateDatabase(); _botSettings = new BotSettings(_configuration); _botSettings.VerifySettings(); - _client = new DiscordSocketClient(); _logHandler = new LogHandler(_botSettings); + _client = new DiscordSocketClient(); + DatabaseHandler.CreateDatabase(); + DatabaseHandler.UpdateDatabase(_logHandler, _client); _messageHandler = new MessageHandler(_client, _botSettings); _connectionHandler = new ConnectionHandler(_client, _logHandler, _botSettings, _messageHandler); _client.MessageReceived += _messageHandler.MessageReceived; diff --git a/StatBot/appsettings.dev.json b/StatBot/appsettings.dev.json index 589ed62..9a0efb5 100644 --- a/StatBot/appsettings.dev.json +++ b/StatBot/appsettings.dev.json @@ -1,5 +1,6 @@ { "Discord": { + "Token": "", "DebugChannelId": "", "Commands": { "Prefix": "!", @@ -8,6 +9,12 @@ "Stats": { "Command": "stats", "Url": "" + }, + "AdminCommands": { + "AdminUserId": 1, + "AllowServerAdmins": false, + "LinkUserCommand": "linkuser", + "OverrideUsernameCommand": "overrideuser" } } }, @@ -30,7 +37,7 @@ // single "LoggingFileName": "single", "NotificationDelay": 30000, - "DeadChatAfter": 3600000, + "DeadChatAfter": 60000, "PushOver": { //Leave values empty if you don't want to use it. "ApiKey": "", diff --git a/StatBot/appsettings.json b/StatBot/appsettings.json index ea9f7b6..857a7cb 100644 --- a/StatBot/appsettings.json +++ b/StatBot/appsettings.json @@ -8,7 +8,13 @@ "Include": "includeinstats", "Stats": { "Command": "stats", - "Url": "" + "Url": "", + "AdminCommands": { + "AdminUserId": 0, + "AllowServerAdmins": false, + "LinkUserCommand": "linkuser", + "OverrideUsernameCommand": "overrideuser" + } } } }, diff --git a/StatBot/mIRCStatsGenerator.cs b/StatBot/mIRCStatsGenerator.cs index ede5e2b..5dc9d56 100644 --- a/StatBot/mIRCStatsGenerator.cs +++ b/StatBot/mIRCStatsGenerator.cs @@ -4,7 +4,7 @@ // Created : 15-05-2022 // // Last Modified By : Jeroen Heijster -// Last Modified On : 15-05-2022 +// Last Modified On : 22-05-2022 // *********************************************************************** // // Copyright © 2022 diff --git a/StatBotConfiguration/MainWindow.xaml b/StatBotConfiguration/MainWindow.xaml index fc7afb0..8a60359 100644 --- a/StatBotConfiguration/MainWindow.xaml +++ b/StatBotConfiguration/MainWindow.xaml @@ -40,6 +40,11 @@ + + + + +