From c0d7f62c619c69e9165a9ca71aeafb68b75a048c Mon Sep 17 00:00:00 2001 From: barelyprofessional <150058423+barelyprofessional@users.noreply.github.com> Date: Sun, 11 Aug 2024 21:11:37 +0800 Subject: [PATCH] Added feature to track messages sent by the bot by reference so they can be edited --- KfChatDotNetBot/ChatBot.cs | 61 +++++++++++++++++-- KfChatDotNetBot/Commands/TestCommands.cs | 51 ++++++++++++++++ .../Models/SentMessageTrackerModel.cs | 23 +++++++ 3 files changed, 129 insertions(+), 6 deletions(-) create mode 100644 KfChatDotNetBot/Commands/TestCommands.cs create mode 100644 KfChatDotNetBot/Models/SentMessageTrackerModel.cs diff --git a/KfChatDotNetBot/ChatBot.cs b/KfChatDotNetBot/ChatBot.cs index 7928881..ad6a9e5 100644 --- a/KfChatDotNetBot/ChatBot.cs +++ b/KfChatDotNetBot/ChatBot.cs @@ -1,4 +1,6 @@ -using KfChatDotNetBot.Models; +using System.Net; +using System.Text.Json; +using KfChatDotNetBot.Models; using KfChatDotNetBot.Models.DbModels; using KfChatDotNetBot.Services; using KfChatDotNetBot.Settings; @@ -42,6 +44,7 @@ public class ChatBot private Task _websocketWatchdog; private Jackpot _jackpot; private Rainbet _rainbet; + private List _sentMessages = []; public ChatBot() { @@ -544,13 +547,32 @@ public class ChatBot private void OnKfChatMessage(object sender, List messages, MessagesJsonModel jsonPayload) { - var settings = Helpers.GetMultipleValues([BuiltIn.Keys.GambaSeshDetectEnabled, BuiltIn.Keys.GambaSeshUserId]) + var settings = Helpers.GetMultipleValues([BuiltIn.Keys.GambaSeshDetectEnabled, + BuiltIn.Keys.GambaSeshUserId, BuiltIn.Keys.KiwiFarmsUsername]) .Result; _lastKfEvent = DateTime.Now; _logger.Debug($"Received {messages.Count} message(s)"); foreach (var message in messages) { _logger.Info($"KF ({message.MessageDate.ToLocalTime():HH:mm:ss}) <{message.Author.Username}> {message.Message}"); + if (message.Author.Username == settings[BuiltIn.Keys.KiwiFarmsUsername].Value && message.MessageEditDate == null) + { + // MessageRaw is not actually REAL and RAW. The messages are still HTML encoded + var decodedMessage = WebUtility.HtmlDecode(message.MessageRaw); + var sentMessage = _sentMessages.FirstOrDefault(sent => + sent.Message == decodedMessage && sent.Status == SentMessageTrackerStatus.WaitingForResponse); + if (sentMessage == null) + { + _logger.Info("Received message from Sneedchat that I sent but have no idea about. Bot restart? Ignoring it."); + _logger.Info(JsonSerializer.Serialize(message)); + } + else + { + sentMessage.ChatMessageId = message.MessageId; + sentMessage.Delay = DateTimeOffset.UtcNow - sentMessage.SentAt; + sentMessage.Status = SentMessageTrackerStatus.ResponseReceived; + } + } if (settings[BuiltIn.Keys.GambaSeshDetectEnabled].ToBoolean() && !_initialStartCooldown && message.Author.Id == settings[BuiltIn.Keys.GambaSeshUserId].ToType() && !GambaSeshPresent) { _logger.Info("Received a GambaSesh message after cooldown and while thinking he's not here. Setting the presence flag to avoid spamming chat"); @@ -569,26 +591,53 @@ public class ChatBot } } - public void SendChatMessage(string message, bool bypassSeshDetect = false) + public string SendChatMessage(string message, bool bypassSeshDetect = false) { var settings = Helpers .GetMultipleValues([BuiltIn.Keys.KiwiFarmsSuppressChatMessages, BuiltIn.Keys.GambaSeshDetectEnabled]) .Result; + var reference = Guid.NewGuid().ToString(); + var messageTracker = new SentMessageTrackerModel + { + Reference = reference, + Message = message, + Status = SentMessageTrackerStatus.Unknown, + }; if (settings[BuiltIn.Keys.KiwiFarmsSuppressChatMessages].ToBoolean()) { _logger.Info("Not sending message as SuppressChatMessages is enabled"); _logger.Info($"Message was: {message}"); - return; + messageTracker.Status = SentMessageTrackerStatus.NotSending; + _sentMessages.Add(messageTracker); + return reference; } if (GambaSeshPresent && settings[BuiltIn.Keys.GambaSeshDetectEnabled].ToBoolean() && !bypassSeshDetect) { _logger.Info($"Not sending message '{message}' as GambaSesh is present"); - return; + messageTracker.Status = SentMessageTrackerStatus.NotSending; + _sentMessages.Add(messageTracker); + return reference; + } + messageTracker.Status = SentMessageTrackerStatus.WaitingForResponse; + messageTracker.SentAt = DateTimeOffset.UtcNow; + _sentMessages.Add(messageTracker); + KfClient.SendMessage(message); + return reference; + } + + public SentMessageTrackerModel GetSentMessageStatus(string reference) + { + var message = _sentMessages.FirstOrDefault(m => m.Reference == reference); + if (message == null) + { + throw new SentMessageNotFoundException(); } - KfClient.SendMessage(message); + return message; } + public class SentMessageNotFoundException : Exception; + private void OnKickChatMessage(object sender, KickModels.ChatMessageEventModel? e) { if (e == null) return; diff --git a/KfChatDotNetBot/Commands/TestCommands.cs b/KfChatDotNetBot/Commands/TestCommands.cs new file mode 100644 index 0000000..5a57a85 --- /dev/null +++ b/KfChatDotNetBot/Commands/TestCommands.cs @@ -0,0 +1,51 @@ +using System.Text.RegularExpressions; +using KfChatDotNetBot.Models; +using KfChatDotNetBot.Models.DbModels; +using KfChatDotNetWsClient.Models.Events; +using NLog; + +namespace KfChatDotNetBot.Commands; + +public class EditTestCommand : ICommand +{ + public List Patterns => [ + new Regex("^test edit (?.+)") + ]; + + public string HelpText => "Test the editing functionality"; + public bool HideFromHelp => true; + public UserRight RequiredRight => UserRight.Admin; + + public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx) + { + var logger = LogManager.GetCurrentClassLogger(); + var msg = arguments["msg"].Value; + var iterations = 3; + var i = 0; + var delay = 1000; + var reference = botInstance.SendChatMessage($"{msg} {i}"); + while (botInstance.GetSentMessageStatus(reference).Status == SentMessageTrackerStatus.WaitingForResponse) + { + await Task.Delay(100, ctx); + } + + var status = botInstance.GetSentMessageStatus(reference); + if (status.Status == SentMessageTrackerStatus.NotSending || status.Status == SentMessageTrackerStatus.Unknown || + status.ChatMessageId == null) + { + logger.Error("Either message refused to send due to bot settings or something fucked up getting the message ID"); + return; + } + while (i < iterations) + { + i++; + await Task.Delay(delay, ctx); + botInstance.KfClient.EditMessage(status.ChatMessageId!.Value, $"{msg} {i}"); + } + + await Task.Delay(delay, ctx); + botInstance.KfClient.EditMessage(status.ChatMessageId!.Value, "This message will self destruct in 1 second"); + await Task.Delay(delay, ctx); + botInstance.KfClient.DeleteMessage(status.ChatMessageId!.Value); + } +} \ No newline at end of file diff --git a/KfChatDotNetBot/Models/SentMessageTrackerModel.cs b/KfChatDotNetBot/Models/SentMessageTrackerModel.cs new file mode 100644 index 0000000..f6c858a --- /dev/null +++ b/KfChatDotNetBot/Models/SentMessageTrackerModel.cs @@ -0,0 +1,23 @@ +namespace KfChatDotNetBot.Models; + +public class SentMessageTrackerModel +{ + // Unique GUID for each message + public required string Reference { get; set; } + public required string Message { get; set; } + public required SentMessageTrackerStatus Status { get; set; } + public int? ChatMessageId { get; set; } + // Timespan from when the message was sent until we saw it come back + public TimeSpan? Delay { get; set; } + public DateTimeOffset? SentAt { get; set; } +} + +public enum SentMessageTrackerStatus +{ + WaitingForResponse, + ResponseReceived, + // If the bot is blocked from sending the message, e.g. due to suppress chat messages being enabled + NotSending, + // Shouldn't happen normally, it's just set before the bot has made a decision on whether to send or not, + Unknown +} \ No newline at end of file