Converted send message method to async (also created a synchronous method that shadows the async method). Added a method to send multiple messages at once and message truncation with a choice of strategies

This commit is contained in:
barelyprofessional
2024-09-17 00:57:11 +08:00
parent 4753783c41
commit 5b3f394c29
14 changed files with 152 additions and 49 deletions

View File

@@ -1,5 +1,6 @@
using System.Net; using System.Net;
using System.Text.Json; using System.Text.Json;
using Humanizer;
using KfChatDotNetBot.Models; using KfChatDotNetBot.Models;
using KfChatDotNetBot.Models.DbModels; using KfChatDotNetBot.Models.DbModels;
using KfChatDotNetBot.Services; using KfChatDotNetBot.Services;
@@ -181,8 +182,8 @@ public class ChatBot
{ {
_logger.Error("Received message from Sneedchat that I sent but have no idea about. Message Data Follows:"); _logger.Error("Received message from Sneedchat that I sent but have no idea about. Message Data Follows:");
_logger.Error(JsonSerializer.Serialize(message)); _logger.Error(JsonSerializer.Serialize(message));
_logger.Error("Last item inserted into the sent messages collection:"); _logger.Error("Last item inserted into the sent messages collection waiting for response:");
_logger.Error(JsonSerializer.Serialize(_sentMessages.LastOrDefault())); _logger.Error(JsonSerializer.Serialize(_sentMessages.LastOrDefault(msg => msg.Status == SentMessageTrackerStatus.WaitingForResponse)));
} }
else else
{ {
@@ -218,11 +219,12 @@ public class ChatBot
if (InitialStartCooldown) InitialStartCooldown = false; if (InitialStartCooldown) InitialStartCooldown = false;
} }
public SentMessageTrackerModel SendChatMessage(string message, bool bypassSeshDetect = false) public async Task<SentMessageTrackerModel> SendChatMessageAsync(string message, bool bypassSeshDetect = false, LengthLimitBehavior lengthLimitBehavior = LengthLimitBehavior.TruncateNicely, int lengthLimit = 500)
{ {
var settings = Helpers var settings = await Helpers
.GetMultipleValues([BuiltIn.Keys.KiwiFarmsSuppressChatMessages, BuiltIn.Keys.GambaSeshDetectEnabled]) .GetMultipleValues([
.Result; BuiltIn.Keys.KiwiFarmsSuppressChatMessages, BuiltIn.Keys.GambaSeshDetectEnabled
]);
var reference = Guid.NewGuid().ToString(); var reference = Guid.NewGuid().ToString();
var messageTracker = new SentMessageTrackerModel var messageTracker = new SentMessageTrackerModel
{ {
@@ -253,13 +255,57 @@ public class ChatBot
_sentMessages.Add(messageTracker); _sentMessages.Add(messageTracker);
return messageTracker; return messageTracker;
} }
if (messageTracker.Message.Length > lengthLimit && lengthLimitBehavior != LengthLimitBehavior.DoNothing)
{
if (lengthLimitBehavior == LengthLimitBehavior.RefuseToSend)
{
_logger.Info("Refusing to send message as it exceeds the length limit and LengthLimitBehavior is RefuseToSend");
messageTracker.Status = SentMessageTrackerStatus.NotSending;
_sentMessages.Add(messageTracker);
return messageTracker;
}
if (lengthLimitBehavior == LengthLimitBehavior.TruncateNicely)
{
messageTracker.Message = messageTracker.Message.Truncate(lengthLimit);
}
if (lengthLimitBehavior == LengthLimitBehavior.TruncateExactly)
{
// ReSharper disable once ReplaceSubstringWithRangeIndexer
// The range indexer is a fucking piece of shit that does not work.
// TrimEnd in case you end up truncating on a space (happened during testing) as Sneedchat will trim it
messageTracker.Message = messageTracker.Message.Substring(0, lengthLimit).TrimEnd();
}
}
messageTracker.Status = SentMessageTrackerStatus.WaitingForResponse; messageTracker.Status = SentMessageTrackerStatus.WaitingForResponse;
messageTracker.SentAt = DateTimeOffset.UtcNow; messageTracker.SentAt = DateTimeOffset.UtcNow;
_sentMessages.Add(messageTracker); _sentMessages.Add(messageTracker);
KfClient.SendMessage(message); await KfClient.SendMessageInstantAsync(messageTracker.Message);
return messageTracker; return messageTracker;
} }
public SentMessageTrackerModel SendChatMessage(string message, bool bypassSeshDetect = false,
LengthLimitBehavior lengthLimitBehavior = LengthLimitBehavior.TruncateNicely, int lengthLimit = 500)
{
return SendChatMessageAsync(message, bypassSeshDetect, lengthLimitBehavior, lengthLimit).Result;
}
// If you feed this long ass messages they will be eaten, don't be retarded.
public async Task<List<SentMessageTrackerModel>> SendChatMessagesAsync(List<string> messages,
bool bypassSeshDetect = false)
{
List<SentMessageTrackerModel> sentMessages = [];
foreach (var message in messages)
{
sentMessages.Add(await SendChatMessageAsync(message, bypassSeshDetect, LengthLimitBehavior.RefuseToSend));
}
return sentMessages;
}
public SentMessageTrackerModel GetSentMessageStatus(string reference) public SentMessageTrackerModel GetSentMessageStatus(string reference)
{ {
var message = _sentMessages.FirstOrDefault(m => m.Reference == reference); var message = _sentMessages.FirstOrDefault(m => m.Reference == reference);
@@ -334,4 +380,16 @@ public class ChatBot
_logger.Info($"Rejoining {roomId}"); _logger.Info($"Rejoining {roomId}");
KfClient.JoinRoom(roomId); KfClient.JoinRoom(roomId);
} }
public enum LengthLimitBehavior
{
// Append …
TruncateNicely,
// Truncate regardless of whether it's mid-word and don't add a ...
TruncateExactly,
// Set status to NotSending
RefuseToSend,
// Try to send the message anyway, even though Sneedchat will just silently eat it
DoNothing
}
} }

View File

@@ -26,13 +26,13 @@ public class SetRoleCommand : ICommand
var targetUser = await db.Users.FirstOrDefaultAsync(u => u.KfId == targetUserId, cancellationToken: ctx); var targetUser = await db.Users.FirstOrDefaultAsync(u => u.KfId == targetUserId, cancellationToken: ctx);
if (targetUser == null) if (targetUser == null)
{ {
botInstance.SendChatMessage($"User '{targetUserId}' does not exist", true); await botInstance.SendChatMessageAsync($"User '{targetUserId}' does not exist", true);
return; return;
} }
targetUser.UserRight = role; targetUser.UserRight = role;
await db.SaveChangesAsync(ctx); await db.SaveChangesAsync(ctx);
botInstance.SendChatMessage($"@{message.Author.Username}, {targetUser.KfUsername}'s role set to {role.Humanize()}", true); await botInstance.SendChatMessageAsync($"@{message.Author.Username}, {targetUser.KfUsername}'s role set to {role.Humanize()}", true);
} }
} }
@@ -50,19 +50,19 @@ public class GmKasinoAddCommand : ICommand
var images = (await Helpers.GetValue(BuiltIn.Keys.BotGmKasinoImageRotation)).JsonDeserialize<List<string>>(); var images = (await Helpers.GetValue(BuiltIn.Keys.BotGmKasinoImageRotation)).JsonDeserialize<List<string>>();
if (images == null) if (images == null)
{ {
botInstance.SendChatMessage("Images list was null", true); await botInstance.SendChatMessageAsync("Images list was null", true);
return; return;
} }
var newImage = arguments["image"].Value; var newImage = arguments["image"].Value;
if (images.Contains(newImage)) if (images.Contains(newImage))
{ {
botInstance.SendChatMessage("Image is already in the list", true); await botInstance.SendChatMessageAsync("Image is already in the list", true);
return; return;
} }
images.Add(newImage); images.Add(newImage);
await Helpers.SetValueAsJsonObject(BuiltIn.Keys.BotGmKasinoImageRotation, images); await Helpers.SetValueAsJsonObject(BuiltIn.Keys.BotGmKasinoImageRotation, images);
botInstance.SendChatMessage("Updated list of images", true); await botInstance.SendChatMessageAsync("Updated list of images", true);
} }
} }
@@ -80,19 +80,19 @@ public class GmKasinoRemoveCommand : ICommand
var images = (await Helpers.GetValue(BuiltIn.Keys.BotGmKasinoImageRotation)).JsonDeserialize<List<string>>(); var images = (await Helpers.GetValue(BuiltIn.Keys.BotGmKasinoImageRotation)).JsonDeserialize<List<string>>();
if (images == null) if (images == null)
{ {
botInstance.SendChatMessage("Images list was null", true); await botInstance.SendChatMessageAsync("Images list was null", true);
return; return;
} }
var targetImage = arguments["image"].Value; var targetImage = arguments["image"].Value;
if (!images.Contains(targetImage)) if (!images.Contains(targetImage))
{ {
botInstance.SendChatMessage("Image is not in the list", true); await botInstance.SendChatMessageAsync("Image is not in the list", true);
return; return;
} }
images.Remove(targetImage); images.Remove(targetImage);
await Helpers.SetValueAsJsonObject(BuiltIn.Keys.BotGmKasinoImageRotation, images); await Helpers.SetValueAsJsonObject(BuiltIn.Keys.BotGmKasinoImageRotation, images);
botInstance.SendChatMessage("Updated list of images", true); await botInstance.SendChatMessageAsync("Updated list of images", true);
} }
} }
@@ -110,7 +110,7 @@ public class GmKasinoListCommand : ICommand
var images = (await Helpers.GetValue(BuiltIn.Keys.BotGmKasinoImageRotation)).JsonDeserialize<List<string>>(); var images = (await Helpers.GetValue(BuiltIn.Keys.BotGmKasinoImageRotation)).JsonDeserialize<List<string>>();
if (images == null) if (images == null)
{ {
botInstance.SendChatMessage("Images list was null", true); await botInstance.SendChatMessageAsync("Images list was null", true);
return; return;
} }
@@ -122,7 +122,7 @@ public class GmKasinoListCommand : ICommand
result += $"[br]{i}: {image}"; result += $"[br]{i}: {image}";
} }
botInstance.SendChatMessage(result, true); await botInstance.SendChatMessageAsync(result, true);
} }
} }
@@ -139,7 +139,7 @@ public class ToggleLiveStatusAdminCommand : ICommand
{ {
botInstance.BotServices.IsBmjLive = !botInstance.BotServices.IsBmjLive; botInstance.BotServices.IsBmjLive = !botInstance.BotServices.IsBmjLive;
botInstance.SendChatMessage($"IsBmjLive => {botInstance.BotServices.IsBmjLive}", true); await botInstance.SendChatMessageAsync($"IsBmjLive => {botInstance.BotServices.IsBmjLive}", true);
} }
} }
@@ -160,6 +160,6 @@ public class CacheClearAdminCommand : ICommand
{ {
MemoryCache.Default.Remove(cacheKey); MemoryCache.Default.Remove(cacheKey);
} }
botInstance.SendChatMessage("Cache wiped", true); await botInstance.SendChatMessageAsync("Cache wiped", true);
} }
} }

View File

@@ -25,12 +25,12 @@ public class HowlggStatsCommand : ICommand
var bets = (await db.HowlggBets.ToListAsync(ctx)).Where(b => b.Date.UtcDateTime > start).ToList(); var bets = (await db.HowlggBets.ToListAsync(ctx)).Where(b => b.Date.UtcDateTime > start).ToList();
if (bets.Count == 0) if (bets.Count == 0)
{ {
botInstance.SendChatMessage("No bets captured during this window", true); await botInstance.SendChatMessageAsync("No bets captured during this window", true);
return; return;
} }
var output = $"Howl.gg stats for the last {window} hours:[br]" + var output = $"Howl.gg stats for the last {window} hours:[br]" +
$"Bets: {bets.Count:N0}; Profit: {bets.Sum(b => b.Profit) / division:C}; Wagered: {bets.Sum(b => b.Bet) / division:C}"; $"Bets: {bets.Count:N0}; Profit: {bets.Sum(b => b.Profit) / division:C}; Wagered: {bets.Sum(b => b.Bet) / division:C}";
botInstance.SendChatMessage(output, true); await botInstance.SendChatMessageAsync(output, true);
} }
} }
@@ -58,6 +58,6 @@ public class HowlggRecentBetCommand : ICommand
if (bet.Profit < 0) color = settings[BuiltIn.Keys.KiwiFarmsRedColor].Value; if (bet.Profit < 0) color = settings[BuiltIn.Keys.KiwiFarmsRedColor].Value;
output += $"[br]Bet: {bet.Bet / division:C}; Profit: [color={color}]{bet.Profit / division:C}[/color]; Game: {bet.Game.Humanize()}; {(DateTimeOffset.UtcNow - bet.Date).Humanize(precision: 1)} ago"; output += $"[br]Bet: {bet.Bet / division:C}; Profit: [color={color}]{bet.Profit / division:C}[/color]; Game: {bet.Game.Humanize()}; {(DateTimeOffset.UtcNow - bet.Date).Humanize(precision: 1)} ago";
} }
botInstance.SendChatMessage(output, true); await botInstance.SendChatMessageAsync(output, true);
} }
} }

View File

@@ -28,7 +28,7 @@ public class JuiceCommand : ICommand
var lastJuicer = (await db.Juicers.Where(j => j.User == user).ToListAsync(ctx)).OrderByDescending(j => j.JuicedAt).Take(1).ToList(); var lastJuicer = (await db.Juicers.Where(j => j.User == user).ToListAsync(ctx)).OrderByDescending(j => j.JuicedAt).Take(1).ToList();
if (lastJuicer.Count == 0) if (lastJuicer.Count == 0)
{ {
botInstance.SendChatMessage($"!juice {message.Author.Id} {amount}", true); await botInstance.SendChatMessageAsync($"!juice {message.Author.Id} {amount}", true);
await db.Juicers.AddAsync(new JuicerDbModel await db.Juicers.AddAsync(new JuicerDbModel
{ Amount = amount, User = user, JuicedAt = DateTimeOffset.UtcNow }, ctx); { Amount = amount, User = user, JuicedAt = DateTimeOffset.UtcNow }, ctx);
await db.SaveChangesAsync(ctx); await db.SaveChangesAsync(ctx);
@@ -38,14 +38,14 @@ public class JuiceCommand : ICommand
var secondsRemaining = lastJuicer[0].JuicedAt.AddSeconds(cooldown) - DateTimeOffset.UtcNow; var secondsRemaining = lastJuicer[0].JuicedAt.AddSeconds(cooldown) - DateTimeOffset.UtcNow;
if (secondsRemaining.TotalSeconds <= 0) if (secondsRemaining.TotalSeconds <= 0)
{ {
botInstance.SendChatMessage($"!juice {message.Author.Id} {amount}", true); await botInstance.SendChatMessageAsync($"!juice {message.Author.Id} {amount}", true);
await db.Juicers.AddAsync(new JuicerDbModel await db.Juicers.AddAsync(new JuicerDbModel
{ Amount = amount, User = user, JuicedAt = DateTimeOffset.UtcNow }, ctx); { Amount = amount, User = user, JuicedAt = DateTimeOffset.UtcNow }, ctx);
await db.SaveChangesAsync(ctx); await db.SaveChangesAsync(ctx);
return; return;
} }
botInstance.SendChatMessage($"You gotta wait {secondsRemaining.Humanize(precision: 2, minUnit: TimeUnit.Second)} for another juicer", true); await botInstance.SendChatMessageAsync($"You gotta wait {secondsRemaining.Humanize(precision: 2, minUnit: TimeUnit.Second)} for another juicer", true);
} }
} }
@@ -67,7 +67,7 @@ public class JuiceStatsCommand : ICommand
top = Convert.ToInt32(argument.Value); top = Convert.ToInt32(argument.Value);
if (top > 10) if (top > 10)
{ {
botInstance.SendChatMessage($"'{top}' exceeds the limit on the amount of leeches you can return", true); await botInstance.SendChatMessageAsync($"'{top}' exceeds the limit on the amount of leeches you can return", true);
return; return;
} }
} }
@@ -93,6 +93,6 @@ public class JuiceStatsCommand : ICommand
msg += $"[b]{i}.[/b] {leech.User} with {leech.Amount:C0} juiced; "; msg += $"[b]{i}.[/b] {leech.User} with {leech.Amount:C0} juiced; ";
} }
botInstance.SendChatMessage(msg.TrimEnd().TrimEnd(';'), true); await botInstance.SendChatMessageAsync(msg.TrimEnd().TrimEnd(';'), true);
} }
} }

View File

@@ -2,6 +2,7 @@ using System.Text.RegularExpressions;
using KfChatDotNetBot.Models.DbModels; using KfChatDotNetBot.Models.DbModels;
using KfChatDotNetBot.Settings; using KfChatDotNetBot.Settings;
using KfChatDotNetWsClient.Models.Events; using KfChatDotNetWsClient.Models.Events;
using NLog;
using Zalgo; using Zalgo;
namespace KfChatDotNetBot.Commands; namespace KfChatDotNetBot.Commands;
@@ -15,7 +16,7 @@ public class InsanityCommand : ICommand
public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx) public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx)
{ {
// ReSharper disable once StringLiteralTypo // ReSharper disable once StringLiteralTypo
botInstance.SendChatMessage("definition of insanity = doing the same thing over and over and over excecting a different result, and heres my dumbass trying to get rich every day and losing everythign i fucking touch every fucking time FUCK this bullshit FUCK MY LIEFdefinition of insanity = doing the same thing over and over and over excecting a different result, and heres my dumbass trying to get rich every day and losing everythign i fucking touch every fucking time FUCK this bullshit FUCK MY LIEF"); await botInstance.SendChatMessageAsync("definition of insanity = doing the same thing over and over and over excecting a different result, and heres my dumbass trying to get rich every day and losing everythign i fucking touch every fucking time FUCK this bullshit FUCK MY LIEFdefinition of insanity = doing the same thing over and over and over excecting a different result, and heres my dumbass trying to get rich every day and losing everythign i fucking touch every fucking time FUCK this bullshit FUCK MY LIEF");
} }
} }
@@ -28,7 +29,7 @@ public class TwistedCommand : ICommand
public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx) public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx)
{ {
// ReSharper disable once StringLiteralTypo // ReSharper disable once StringLiteralTypo
botInstance.SendChatMessage("🦍 🗣 GET IT TWISTED 🌪 , GAMBLE ✅ . PLEASE START GAMBLING 👍 . GAMBLING IS AN INVESTMENT 🎰 AND AN INVESTMENT ONLY 👍 . YOU WILL PROFIT 💰 , YOU WILL WIN ❗ . YOU WILL DO ALL OF THAT 💯 , YOU UNDERSTAND ⁉ YOU WILL BECOME A BILLIONAIRE 💵 📈 AND REBUILD YOUR FUCKING LIFE 🤯"); await botInstance.SendChatMessageAsync("🦍 🗣 GET IT TWISTED 🌪 , GAMBLE ✅ . PLEASE START GAMBLING 👍 . GAMBLING IS AN INVESTMENT 🎰 AND AN INVESTMENT ONLY 👍 . YOU WILL PROFIT 💰 , YOU WILL WIN ❗ . YOU WILL DO ALL OF THAT 💯 , YOU UNDERSTAND ⁉ YOU WILL BECOME A BILLIONAIRE 💵 📈 AND REBUILD YOUR FUCKING LIFE 🤯");
} }
} }
@@ -41,7 +42,7 @@ public class HelpMeCommand : ICommand
public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx) public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx)
{ {
// ReSharper disable once StringLiteralTypo // ReSharper disable once StringLiteralTypo
botInstance.SendChatMessage("[img]https://i.postimg.cc/fTw6tGWZ/ineedmoneydumbfuck.png[/img]", true); await botInstance.SendChatMessageAsync("[img]https://i.postimg.cc/fTw6tGWZ/ineedmoneydumbfuck.png[/img]", true);
} }
} }
@@ -54,7 +55,7 @@ public class SentCommand : ICommand
public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx) public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx)
{ {
// ReSharper disable once StringLiteralTypo // ReSharper disable once StringLiteralTypo
botInstance.SendChatMessage("[img]https://i.ibb.co/GHq7hb1/4373-g-N5-HEH2-Hkc.png[/img]", true); await botInstance.SendChatMessageAsync("[img]https://i.ibb.co/GHq7hb1/4373-g-N5-HEH2-Hkc.png[/img]", true);
} }
} }
@@ -70,7 +71,7 @@ public class GmKasinoCommand : ICommand
if (images == null) return; if (images == null) return;
var random = new Random(); var random = new Random();
var image = images[random.Next(images.Count)]; var image = images[random.Next(images.Count)];
botInstance.SendChatMessage($"[img]{image}[/img]", true); await botInstance.SendChatMessageAsync($"[img]{image}[/img]", true);
} }
} }
@@ -85,13 +86,15 @@ public class CrackedCommand : ICommand
public TimeSpan Timeout => TimeSpan.FromSeconds(10); public TimeSpan Timeout => TimeSpan.FromSeconds(10);
public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx) public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx)
{ {
var logger = LogManager.GetCurrentClassLogger();
var msg = arguments["msg"].Value.TrimStart('/'); var msg = arguments["msg"].Value.TrimStart('/');
var settings = await Helpers.GetMultipleValues([ var settings = await Helpers.GetMultipleValues([
BuiltIn.Keys.CrackedZalgoFuckUpMode, BuiltIn.Keys.CrackedZalgoFuckUpPosition BuiltIn.Keys.CrackedZalgoFuckUpMode, BuiltIn.Keys.CrackedZalgoFuckUpPosition
]); ]);
var zalgo = new ZalgoString(msg, (FuckUpMode)settings[BuiltIn.Keys.CrackedZalgoFuckUpMode].ToType<int>(), var zalgo = new ZalgoString(msg, (FuckUpMode)settings[BuiltIn.Keys.CrackedZalgoFuckUpMode].ToType<int>(),
(FuckUpPosition)settings[BuiltIn.Keys.CrackedZalgoFuckUpPosition].ToType<int>()); (FuckUpPosition)settings[BuiltIn.Keys.CrackedZalgoFuckUpPosition].ToType<int>());
botInstance.SendChatMessage(zalgo.ToString(), true); logger.Info($"Zalgo length: {zalgo.ToString().Length}");
await botInstance.SendChatMessageAsync(zalgo.ToString(), true, ChatBot.LengthLimitBehavior.TruncateExactly);
} }
} }
@@ -106,6 +109,6 @@ public class WinmanjackCommand : ICommand
public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx) public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx)
{ {
var image = await Helpers.GetValue(BuiltIn.Keys.WinmanjackImgUrl); var image = await Helpers.GetValue(BuiltIn.Keys.WinmanjackImgUrl);
botInstance.SendChatMessage($"[img]{image.Value}[/img]", true); await botInstance.SendChatMessageAsync($"[img]{image.Value}[/img]", true);
} }
} }

View File

@@ -24,12 +24,12 @@ public class RainbetStatsCommand : ICommand
var bets = (await db.RainbetBets.ToListAsync(ctx)).Where(b => b.UpdatedAt.UtcDateTime > start).ToList(); var bets = (await db.RainbetBets.ToListAsync(ctx)).Where(b => b.UpdatedAt.UtcDateTime > start).ToList();
if (bets.Count == 0) if (bets.Count == 0)
{ {
botInstance.SendChatMessage("No bets captured during this window", true); await botInstance.SendChatMessageAsync("No bets captured during this window", true);
return; return;
} }
var output = $"Rainbet stats for the last {window} hours (as seen on the bet feed):[br]" + var output = $"Rainbet stats for the last {window} hours (as seen on the bet feed):[br]" +
$"Bets: {bets.Count:N0}; Payout: {bets.Sum(b => b.Payout):C}; Wagered: {bets.Sum(b => b.Value):C}"; $"Bets: {bets.Count:N0}; Payout: {bets.Sum(b => b.Payout):C}; Wagered: {bets.Sum(b => b.Value):C}";
botInstance.SendChatMessage(output, true); await botInstance.SendChatMessageAsync(output, true);
} }
} }
@@ -56,6 +56,6 @@ public class RainbetRecentBetCommand : ICommand
if (bet.Payout < bet.Value) color = settings[BuiltIn.Keys.KiwiFarmsRedColor].Value; if (bet.Payout < bet.Value) color = settings[BuiltIn.Keys.KiwiFarmsRedColor].Value;
output += $"[br]Value: {bet.Value:C}; Payout: [color={color}]{bet.Payout:C}[/color]; Multi: {bet.Multiplier:N2}x; Game: {bet.GameName}; {(DateTimeOffset.UtcNow - bet.UpdatedAt).Humanize(precision: 1)} ago"; output += $"[br]Value: {bet.Value:C}; Payout: [color={color}]{bet.Payout:C}[/color]; Multi: {bet.Multiplier:N2}x; Game: {bet.GameName}; {(DateTimeOffset.UtcNow - bet.UpdatedAt).Humanize(precision: 1)} ago";
} }
botInstance.SendChatMessage(output, true); await botInstance.SendChatMessageAsync(output, true);
} }
} }

View File

@@ -19,7 +19,7 @@ public class GetRestreamCommand : ICommand
CancellationToken ctx) CancellationToken ctx)
{ {
var url = await Helpers.GetValue(BuiltIn.Keys.RestreamUrl); var url = await Helpers.GetValue(BuiltIn.Keys.RestreamUrl);
botInstance.SendChatMessage($"@{message.Author.Username}, restream URL: {url.Value}", true); await botInstance.SendChatMessageAsync($"@{message.Author.Username}, restream URL: {url.Value}", true);
} }
} }
@@ -38,7 +38,7 @@ public class SetRestreamCommand : ICommand
CancellationToken ctx) CancellationToken ctx)
{ {
await Helpers.SetValue(BuiltIn.Keys.RestreamUrl, arguments["url"].Value); await Helpers.SetValue(BuiltIn.Keys.RestreamUrl, arguments["url"].Value);
botInstance.SendChatMessage($"@{message.Author.Username}, updated URL", true); await botInstance.SendChatMessageAsync($"@{message.Author.Username}, updated URL", true);
} }
} }

View File

@@ -24,7 +24,7 @@ public class EditTestCommand : ICommand
var iterations = 3; var iterations = 3;
var i = 0; var i = 0;
var delay = 1000; var delay = 1000;
var reference = botInstance.SendChatMessage($"{msg} {i}", true); var reference = await botInstance.SendChatMessageAsync($"{msg} {i}", true);
while (reference.Status == SentMessageTrackerStatus.WaitingForResponse) while (reference.Status == SentMessageTrackerStatus.WaitingForResponse)
{ {
await Task.Delay(100, ctx); await Task.Delay(100, ctx);
@@ -84,3 +84,39 @@ public class ExceptionTestCommand : ICommand
throw new Exception("Caused by the test exception command"); throw new Exception("Caused by the test exception command");
} }
} }
public class LengthLimitTestCommand : ICommand
{
public List<Regex> Patterns => [
new Regex("^test lengthlimit$")
];
public string? HelpText => null;
public UserRight RequiredRight => UserRight.Admin;
// Increased timeout as it has to wait for Sneedchat to echo the message and that can be slow sometimes
public TimeSpan Timeout => TimeSpan.FromSeconds(15);
public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx)
{
var logger = LogManager.GetCurrentClassLogger();
var niceTruncation = await botInstance.SendChatMessageAsync("The quick brown fox jumps over the lazy dog.",
true, ChatBot.LengthLimitBehavior.TruncateNicely, 20);
var exactTruncation = await botInstance.SendChatMessageAsync("The quick brown fox jumps over the lazy dog.",
true, ChatBot.LengthLimitBehavior.TruncateExactly, 20);
// Would normally get eaten but because we artificially lowered the length limit, it should get sent as-is
var doNothing = await botInstance.SendChatMessageAsync("The quick brown fox jumps over the lazy dog.",
true, ChatBot.LengthLimitBehavior.DoNothing, 20);
var refuseToSend = await botInstance.SendChatMessageAsync("The quick brown fox jumps over the lazy dog.",
true, ChatBot.LengthLimitBehavior.RefuseToSend, 20);
await Task.Delay(TimeSpan.FromSeconds(5), ctx);
logger.Info($"niceTruncation => {niceTruncation.Status}; exactTruncation => {exactTruncation.Status}; doNothing => {doNothing.Status}; refuseToSend => {refuseToSend.Status}");
if (niceTruncation.ChatMessageId != null)
botInstance.KfClient.DeleteMessage(niceTruncation.ChatMessageId.Value);
if (exactTruncation.ChatMessageId != null)
botInstance.KfClient.DeleteMessage(exactTruncation.ChatMessageId.Value);
if (doNothing.ChatMessageId != null)
botInstance.KfClient.DeleteMessage(doNothing.ChatMessageId.Value);
// Should never happen
if (refuseToSend.ChatMessageId != null)
botInstance.KfClient.DeleteMessage(refuseToSend.ChatMessageId.Value);
}
}

View File

@@ -14,6 +14,6 @@ public class TimeCommand : ICommand
{ {
var bmt = new DateTimeOffset(TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, var bmt = new DateTimeOffset(TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow,
TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time")), TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time").BaseUtcOffset); TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time")), TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time").BaseUtcOffset);
botInstance.SendChatMessage($"It's currently {bmt:h:mm:ss tt} BMT"); await botInstance.SendChatMessageAsync($"It's currently {bmt:h:mm:ss tt} BMT");
} }
} }

View File

@@ -16,7 +16,7 @@ public class TempEnableDiscordRelayingCommand : ICommand
public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx) public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx)
{ {
botInstance.BotServices.TemporarilyBypassGambaSeshForDiscord = true; botInstance.BotServices.TemporarilyBypassGambaSeshForDiscord = true;
botInstance.SendChatMessage("Enjoy Discord messages, stalker child", true); await botInstance.SendChatMessageAsync("Enjoy Discord messages, stalker child", true);
} }
} }
@@ -32,7 +32,7 @@ public class TempSuppressGambaMessages : ICommand
public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx) public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx)
{ {
botInstance.BotServices.TemporarilySuppressGambaMessages = true; botInstance.BotServices.TemporarilySuppressGambaMessages = true;
botInstance.SendChatMessage("No more gamba notifs", true); await botInstance.SendChatMessageAsync("No more gamba notifs", true);
} }
} }
@@ -48,6 +48,6 @@ public class EnableGambaMessages : ICommand
public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx) public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx)
{ {
botInstance.BotServices.TemporarilySuppressGambaMessages = false; botInstance.BotServices.TemporarilySuppressGambaMessages = false;
botInstance.SendChatMessage("Gamba notifs back on the menu", true); await botInstance.SendChatMessageAsync("Gamba notifs back on the menu", true);
} }
} }

View File

@@ -22,13 +22,13 @@ public class WhoisCommand : ICommand
var queryUser = await db.Users.FirstOrDefaultAsync(u => u.KfUsername == query, cancellationToken: ctx); var queryUser = await db.Users.FirstOrDefaultAsync(u => u.KfUsername == query, cancellationToken: ctx);
if (queryUser != null) if (queryUser != null)
{ {
botInstance.SendChatMessage($"@{message.Author.Username}, {queryUser.KfUsername}'s ID is {queryUser.KfId}", true); await botInstance.SendChatMessageAsync($"@{message.Author.Username}, {queryUser.KfUsername}'s ID is {queryUser.KfId}", true);
return; return;
} }
var users = await db.Users.Select(u => u.KfUsername).Distinct().ToListAsync(ctx); var users = await db.Users.Select(u => u.KfUsername).Distinct().ToListAsync(ctx);
var result = Process.ExtractOne(query, users); var result = Process.ExtractOne(query, users);
queryUser = await db.Users.FirstOrDefaultAsync(u => u.KfUsername == result.Value, cancellationToken: ctx); queryUser = await db.Users.FirstOrDefaultAsync(u => u.KfUsername == result.Value, cancellationToken: ctx);
botInstance.SendChatMessage($"@{message.Author.Username}, my guess is you're looking for {queryUser!.KfUsername} whose ID is {queryUser.KfId}", true); await botInstance.SendChatMessageAsync($"@{message.Author.Username}, my guess is you're looking for {queryUser!.KfUsername} whose ID is {queryUser.KfId}", true);
} }
} }

View File

@@ -16,9 +16,9 @@ public enum SentMessageTrackerStatus
{ {
WaitingForResponse, WaitingForResponse,
ResponseReceived, ResponseReceived,
// If the bot is blocked from sending the message, e.g. due to suppress chat messages being enabled // If the bot is blocked from sending the message, e.g. due to suppress chat messages being enabled or length limit
NotSending, NotSending,
// Shouldn't happen normally, it's just set before the bot has made a decision on whether to send or not, // Shouldn't happen normally, it's just set before the bot has made a decision on whether to send or not
Unknown, Unknown,
// Means the chat was disconnected when you attempted to send the message // Means the chat was disconnected when you attempted to send the message
ChatDisconnected, ChatDisconnected,

View File

@@ -38,7 +38,7 @@ public class BotServices
private bool _isBmjLiveSynced = false; private bool _isBmjLiveSynced = false;
// lol // lol
internal bool TemporarilyBypassGambaSeshForDiscord = true; internal bool TemporarilyBypassGambaSeshForDiscord = false;
internal bool TemporarilySuppressGambaMessages = false; internal bool TemporarilySuppressGambaMessages = false;
public BotServices(ChatBot botInstance, CancellationToken ctx) public BotServices(ChatBot botInstance, CancellationToken ctx)

View File

@@ -202,6 +202,12 @@ public class ChatClient
_wsClient.Send(message); _wsClient.Send(message);
} }
public async Task SendMessageInstantAsync(string message)
{
_logger.Debug($"Sending '{message}', bypassing the queue");
await _wsClient.SendInstant(message);
}
public void DeleteMessage(int messageId) public void DeleteMessage(int messageId)
{ {
_logger.Debug($"Deleting {messageId}"); _logger.Debug($"Deleting {messageId}");