Update for new chyat

This commit is contained in:
barelyprofessional
2026-02-28 15:34:36 -06:00
parent 8a827a17de
commit c8016b4fc6
23 changed files with 178 additions and 104 deletions

View File

@@ -193,7 +193,7 @@ public class ChatBot
foreach (var deletion in _scheduledDeletions)
{
if (deletion.DeleteAt > now) continue;
if (deletion.Message.ChatMessageId == null)
if (deletion.Message.ChatMessageUuid == null)
{
_logger.Error($"Can't clean up {deletion.Message.Reference} as it doesn't have a chat message ID");
if (failures.TryGetValue(deletion.Message.Reference, out var failure))
@@ -213,7 +213,7 @@ public class ChatBot
}
continue;
}
await KfClient.DeleteMessageAsync(deletion.Message.ChatMessageId.Value);
await KfClient.DeleteMessageAsync(deletion.Message.ChatMessageUuid);
removals.Add(deletion);
}
foreach (var removal in removals)
@@ -295,7 +295,7 @@ public class ChatBot
// Update last edit timestamp
if (message.Author.Username == settings[BuiltIn.Keys.KiwiFarmsUsername].Value && message.MessageEditDate != null)
{
var sentMessage = SentMessages.FirstOrDefault(x => x.ChatMessageId == message.MessageId);
var sentMessage = SentMessages.FirstOrDefault(x => x.ChatMessageUuid == message.MessageUuid);
if (sentMessage != null)
{
sentMessage.LastEdited = message.MessageEditDate.Value;
@@ -321,14 +321,14 @@ public class ChatBot
// back to you. So this fallback should be generally correct and will account for the occasional
// mismatch due to messages not being 1:1 with what we thought we sent
_logger.Info("Just going to lazily associate it with the latest message");
latest.ChatMessageId = message.MessageId;
latest.ChatMessageUuid = message.MessageUuid;
latest.Delay = DateTimeOffset.UtcNow - latest.SentAt;
latest.Status = SentMessageTrackerStatus.ResponseReceived;
}
}
else
{
sentMessage.ChatMessageId = message.MessageId;
sentMessage.ChatMessageUuid = message.MessageUuid;
sentMessage.Delay = DateTimeOffset.UtcNow - sentMessage.SentAt;
sentMessage.Status = SentMessageTrackerStatus.ResponseReceived;
}
@@ -350,7 +350,7 @@ public class ChatBot
// So this avoids reprocessing messages on reconnect while being able to handle edits, even if the edit came
// during a disconnect / reconnect event
if (!_seenMessages.Any(msg =>
msg.MessageId == message.MessageId && msg.LastEdited == message.MessageEditDate) &&
msg.MessageUuid == message.MessageUuid && msg.LastEdited == message.MessageEditDate) &&
!InitialStartCooldown)
{
_logger.Debug("Passing message to command interface");
@@ -366,14 +366,14 @@ public class ChatBot
}
// Update or add the element to keep it in sync
var existingMsg = _seenMessages.FirstOrDefault(msg => msg.MessageId == message.MessageId);
var existingMsg = _seenMessages.FirstOrDefault(msg => msg.MessageUuid == message.MessageUuid);
if (existingMsg != null)
{
existingMsg.LastEdited = message.MessageEditDate;
}
else
{
_seenMessages.Add(new SeenMessageMetadataModel {MessageId = message.MessageId, LastEdited = message.MessageEditDate});
_seenMessages.Add(new SeenMessageMetadataModel {MessageUuid = message.MessageUuid, LastEdited = message.MessageEditDate});
}
UpdateUserLastActivityAsync(message.Author.Id, WhoWasActivityType.Message).Wait(_cancellationToken);
// Strip weird control characters and just allow basic punctuation + whitespace
@@ -546,7 +546,7 @@ public class ChatBot
}
var patienceEnds = DateTimeOffset.UtcNow.Add(patience.Value);
while (message.ChatMessageId == null)
while (message.ChatMessageUuid == null)
{
if (DateTimeOffset.UtcNow > patienceEnds) return false;
if (message.Status is SentMessageTrackerStatus.Lost or SentMessageTrackerStatus.NotSending) return false;

View File

@@ -337,12 +337,12 @@ public class DeleteMessagesCommand : ICommand
.TakeLast(amount);
foreach (var msg in messages)
{
if (msg.ChatMessageId == null)
if (msg.ChatMessageUuid == null)
{
continue;
}
await botInstance.KfClient.DeleteMessageAsync(msg.ChatMessageId.Value);
await botInstance.KfClient.DeleteMessageAsync(msg.ChatMessageUuid);
}
}
}

View File

@@ -153,7 +153,7 @@ public class KasinoEventStart : ICommand
var msg = $":!: :!: A Keno Kasino event has started! :!: :!:[br]{targetEvent.EventText}[br]{guide}";
var msgIds = await botInstance.SendChatMessagesAsync(msg.FancySplitMessage(partSeparator: "[br]"), true);
var i = 0;
while (msgIds[0].ChatMessageId != null)
while (msgIds[0].ChatMessageUuid != null)
{
i++;
await Task.Delay(TimeSpan.FromMilliseconds(100), ctx);

View File

@@ -227,7 +227,7 @@ public class KenoCommand : ICommand
_kenoTable = await botInstance.SendChatMessageAsync(displayMessage, true);
var i = 0;
while (_kenoTable.ChatMessageId == null)
while (_kenoTable.ChatMessageUuid == null)
{
i++;
if (_kenoTable.Status is SentMessageTrackerStatus.NotSending or SentMessageTrackerStatus.Lost) return;
@@ -235,7 +235,7 @@ public class KenoCommand : ICommand
await Task.Delay(100);
}
if (_kenoTable.ChatMessageId == null)
if (_kenoTable.ChatMessageUuid == null)
{
throw new Exception($"_kenoTable chat message ID never got populated. Tracker status is: {_kenoTable?.Status}");
}
@@ -269,7 +269,7 @@ public class KenoCommand : ICommand
}
displayMessage += "[br]";
}
await botInstance.KfClient.EditMessageAsync(_kenoTable.ChatMessageId!.Value, displayMessage);
await botInstance.KfClient.EditMessageAsync(_kenoTable.ChatMessageUuid, displayMessage);
await Task.Delay(frameDelay);
if (displayMessage.Length <= 79 && displayMessage.Contains(BlankSpaceDisplay) &&
(displayMessage.Contains(CasinoNumberDisplay) || displayMessage.Contains(MatchRevealDisplay) ||

View File

@@ -145,7 +145,7 @@ public class LambchopCommand : ICommand
var lambChopDisplayMessage =
await botInstance.SendChatMessageAsync(ConvertLambchopFieldToString(tiles, hazards, true), true,
autoDeleteAfter: cleanupDelay);
while (lambChopDisplayMessage.ChatMessageId == null)
while (lambChopDisplayMessage.ChatMessageUuid == null)
{
await Task.Delay(50, ctx); // wait until first message is fully sent
if (lambChopDisplayMessage.Status is SentMessageTrackerStatus.Lost or SentMessageTrackerStatus.NotSending)
@@ -307,7 +307,7 @@ public class LambchopCommand : ICommand
async Task UpdateGameAsync(string? updateText = null)
{
updateText ??= ConvertLambchopFieldToString(tiles, hazards, false);
await botInstance.KfClient.EditMessageAsync(lambChopDisplayMessage.ChatMessageId!.Value, updateText);
await botInstance.KfClient.EditMessageAsync(lambChopDisplayMessage.ChatMessageUuid, updateText);
await Task.Delay(TimeSpan.FromMilliseconds(FRAME_DELAY), ctx);
}
}

View File

@@ -269,11 +269,11 @@ public class MinesCommand : ICommand
var lastmsg = KasinoMines.ActiveGames[gambler.Id].LastMessageId;
SentMessageTrackerModel msg;
if (lastmsg == 0)
if (lastmsg == null)
{
msg = (await botInstance.SendChatMessageAsync($"{KasinoMines.ActiveGames[gambler.Id].ToString()}", true));
await botInstance.WaitForChatMessageAsync(msg, ct: ctx);
if (msg.ChatMessageId == null) throw new InvalidOperationException("Timed out waiting for the message");
if (msg.ChatMessageUuid == null) throw new InvalidOperationException("Timed out waiting for the message");
}
else
{

View File

@@ -119,7 +119,7 @@ public class Planes : ICommand
var planesDisplay = GetPreGameBoard(-3, planesBoard2, plane, CarrierCount, noseUp);
var msgId = await botInstance.SendChatMessageAsync(planesDisplay, true);
var num = 0;
while (msgId.ChatMessageId == null)
while (msgId.ChatMessageUuid == null)
{
num++;
if (msgId.Status is SentMessageTrackerStatus.NotSending or SentMessageTrackerStatus.Lost) return;
@@ -148,7 +148,7 @@ public class Planes : ICommand
}
var winnings = plane.MultiTracker * wager;
planesDisplay += $"Winnings: {await winnings.FormatKasinoCurrencyAsync()}";
await botInstance.KfClient.EditMessageAsync(msgId.ChatMessageId!.Value, planesDisplay);
await botInstance.KfClient.EditMessageAsync(msgId.ChatMessageUuid, planesDisplay);
}
var neutral = false;
@@ -159,7 +159,7 @@ public class Planes : ICommand
{
counter = (fullCounter - 3) % 24;
planesDisplay = GetPreGameBoard(fullCounter, planesBoard2, plane, CarrierCount, noseUp);
await botInstance.KfClient.EditMessageAsync(msgId.ChatMessageId!.Value, planesDisplay);
await botInstance.KfClient.EditMessageAsync(msgId.ChatMessageUuid, planesDisplay);
await Task.Delay(TimeSpan.FromMilliseconds(frameLength), ctx);
fullCounter++;
}
@@ -236,7 +236,7 @@ public class Planes : ICommand
var winnings = plane.MultiTracker * wager;
planesDisplay += $"Winnings: {await winnings.FormatKasinoCurrencyAsync()}";
await botInstance.KfClient.EditMessageAsync(msgId.ChatMessageId!.Value, planesDisplay);
await botInstance.KfClient.EditMessageAsync(msgId.ChatMessageUuid, planesDisplay);
if (plane.Height > 5)
{
break;
@@ -264,7 +264,7 @@ public class Planes : ICommand
var win = plane.MultiTracker * wager;
newBalance = await Money.NewWagerAsync(gambler.Id, wager, win, WagerGame.Planes, ct: ctx);
planesDisplay = GetGameBoard(fullCounter, planesBoards, plane, CarrierCount, noseUp);
await botInstance.KfClient.EditMessageAsync(msgId.ChatMessageId!.Value, planesDisplay);
await botInstance.KfClient.EditMessageAsync(msgId.ChatMessageUuid, planesDisplay);
await botInstance.SendChatMessageAsync(
$"{user.FormatUsername()}, you [color={colors[BuiltIn.Keys.KiwiFarmsGreenColor].Value}]successfully landed with {await win.FormatKasinoCurrencyAsync()} from a total {plane.MultiTracker:N2}x multi![/color]. Your balance is now: {await newBalance.FormatKasinoCurrencyAsync()}",
true, autoDeleteAfter: cleanupDelay);
@@ -275,7 +275,7 @@ public class Planes : ICommand
newBalance = await Money.NewWagerAsync(gambler.Id, wager, -wager, WagerGame.Planes, ct: ctx);
planesDisplay = GetGameBoard(fullCounter, planesBoards, plane, CarrierCount, noseUp);
await Task.Delay(TimeSpan.FromMilliseconds(frameLength), ctx);
await botInstance.KfClient.EditMessageAsync(msgId.ChatMessageId!.Value, planesDisplay);
await botInstance.KfClient.EditMessageAsync(msgId.ChatMessageUuid, planesDisplay);
await botInstance.SendChatMessageAsync(
$"{user.FormatUsername()}, you [color={colors[BuiltIn.Keys.KiwiFarmsRedColor].Value}]crashed![/color] Your balance is now: {await newBalance.FormatKasinoCurrencyAsync()}",
true, autoDeleteAfter: cleanupDelay);

View File

@@ -173,7 +173,7 @@ public class PlinkoCommand : ICommand
//game starts here
int breakCounter = 0;
var plinkoMessageID = await botInstance.SendChatMessageAsync(PlinkoBoardDisplay(ballsInPlay), true, autoDeleteAfter: cleanupDelay);
while (plinkoMessageID.ChatMessageId == null && breakCounter < 1000) {
while (plinkoMessageID.ChatMessageUuid == null && breakCounter < 1000) {
await Task.Delay(100, ctx);
breakCounter++;
}
@@ -195,7 +195,7 @@ public class PlinkoCommand : ICommand
ballsNotInPlay.RemoveAt(0);
}
PlinkoMessage = PlinkoBoardDisplay(ballsInPlay) + "[br]" + lastPayoutMessage;
await botInstance.KfClient.EditMessageAsync(plinkoMessageID.ChatMessageId!.Value,PlinkoMessage);
await botInstance.KfClient.EditMessageAsync(plinkoMessageID.ChatMessageUuid!, PlinkoMessage);
if (ballsInPlay[0].POSITION.row == DIFFICULTY - 1) //once your ball has reached the bottom calculate the payout
{
currentPayout = wager * PlinkoPayoutBoard[ballsInPlay[0].POSITION.col];
@@ -219,7 +219,7 @@ public class PlinkoCommand : ICommand
await Task.Delay(300, ctx);
PlinkoMessage = PlinkoBoardDisplay(ballsInPlay) + "[br]" + lastPayoutMessage;
await botInstance.KfClient.EditMessageAsync(plinkoMessageID.ChatMessageId!.Value, PlinkoMessage);
await botInstance.KfClient.EditMessageAsync(plinkoMessageID.ChatMessageUuid!, PlinkoMessage);
await Task.Delay(300, ctx);
}

View File

@@ -128,10 +128,12 @@ public class RainCommand : ICommand
{
timer--;
await Task.Delay(1000, ctx);
await botInstance.KfClient.EditMessageAsync(msg.ChatMessageId!.Value,
await botInstance.KfClient.EditMessageAsync(msg.ChatMessageUuid!,
$"{user.FormatUsername()} is making it rain with {await decAmount.FormatKasinoCurrencyAsync()}! Type !rain in the next {timer} seconds to join.");
}
await botInstance.KfClient.DeleteMessageAsync(msg.ChatMessageId!.Value);
await Task.Delay(100, ctx);
await botInstance.KfClient.DeleteMessageAsync(msg.ChatMessageUuid!);
// At this point the timer should take care of things but truthfully it's a disaster and probably won't work
}
}

View File

@@ -262,7 +262,7 @@ public class RouletteCommand : ICommand
if (activeRound != null)
{
activeRound.CountdownMessageId = countdownMessage.ChatMessageId;
activeRound.CountdownMessageId = countdownMessage.ChatMessageUuid;
await SaveRound(activeRound);
}
@@ -291,7 +291,7 @@ public class RouletteCommand : ICommand
try
{
var updatedMessage = await FormatCountdownMessage(endTime);
await botInstance.KfClient.EditMessageAsync(countdownMessage.ChatMessageId!.Value, updatedMessage);
await botInstance.KfClient.EditMessageAsync(countdownMessage.ChatMessageUuid!, updatedMessage);
var timeSinceLastUpdate = DateTimeOffset.UtcNow - lastUpdate;
logger.Debug($"Countdown updated (elapsed: {timeSinceLastUpdate.TotalSeconds:F1}s, remaining: {remaining.TotalSeconds:F0}s)");
@@ -414,12 +414,12 @@ public class RouletteCommand : ICommand
logger.Info($"Animation uploaded: {animationUrl}");
// Update countdown message to show it's spinning
if (round.CountdownMessageId.HasValue)
if (round.CountdownMessageId != null)
{
var spinningMessage = $"🎰 [B]SPINNING THE WHEEL...[/B] 🎰[br][br]" +
"Watch the animation below!";
await botInstance.KfClient.EditMessageAsync(
round.CountdownMessageId.Value,
round.CountdownMessageId,
spinningMessage);
}
@@ -486,10 +486,10 @@ public class RouletteCommand : ICommand
$"All {round.Bets.Count} bet(s) have been refunded (total: {await totalRefunded.FormatKasinoCurrencyAsync()}).[br]" +
$"Please try again.";
if (round.CountdownMessageId.HasValue)
if (round.CountdownMessageId != null)
{
await botInstance.KfClient.EditMessageAsync(
round.CountdownMessageId.Value,
round.CountdownMessageId,
cancelMessage);
}
else
@@ -707,10 +707,10 @@ public class RouletteCommand : ICommand
$"Cancelled by {user.FormatUsername()}[br]" +
$"Refunded {round.Bets.Count} bet(s) totaling {await totalRefunded.FormatKasinoCurrencyAsync()}";
if (round.CountdownMessageId.HasValue)
if (round.CountdownMessageId != null)
{
await botInstance.KfClient.EditMessageAsync(
round.CountdownMessageId.Value,
round.CountdownMessageId,
cancelMessage);
}
else
@@ -884,7 +884,7 @@ public class RouletteCommand : ICommand
{
public required int RoundId { get; init; }
public required DateTimeOffset StartTime { get; init; }
public int? CountdownMessageId { get; set; }
public string? CountdownMessageId { get; set; }
public required List<RouletteBetInfo> Bets { get; init; }
}

View File

@@ -156,7 +156,7 @@ public class WheelCommand : ICommand
int delay = (int)(MIN_WHEELSPIN_DELAY + easeOut * (MAX_WHEELSPIN_DELAY - MIN_WHEELSPIN_DELAY));
await Task.Delay(delay, ctx);
wheel.RotateWheelOnce();
await botInstance.KfClient.EditMessageAsync(wheelDisplayMessage.ChatMessageId!.Value,
await botInstance.KfClient.EditMessageAsync(wheelDisplayMessage.ChatMessageUuid!,
wheel.ConvertWheelToOvalString());
}

View File

@@ -156,16 +156,14 @@ public class NextPoVisitCommand : ICommand
return;
}
var sent = await botInstance.SendChatMessageAsync($"Austin's next PO visit will be in roughly {timespan.Humanize(precision: 10, minUnit: TimeUnit.Millisecond)}", true);
while (sent.Status != SentMessageTrackerStatus.ResponseReceived)
{
await Task.Delay(250, ctx);
}
var success = await botInstance.WaitForChatMessageAsync(sent, TimeSpan.FromSeconds(30), ctx);
if (!success) throw new InvalidOperationException();
var i = 0;
while (i < 60)
{
await Task.Delay(1000, ctx);
timespan = DateTimeOffset.Parse(time.Value) - DateTimeOffset.UtcNow;
await botInstance.KfClient.EditMessageAsync(sent.ChatMessageId!.Value,
await botInstance.KfClient.EditMessageAsync(sent.ChatMessageUuid!,
$"Austin's next PO visit will be in roughly {timespan.Humanize(precision: 10, minUnit: TimeUnit.Millisecond)}");
i++;
}
@@ -197,15 +195,13 @@ public class NextCourtHearingCommand : ICommand
}
var sent = await botInstance.SendChatMessageAsync(RenderHearings(hearings),true);
while (sent.Status != SentMessageTrackerStatus.ResponseReceived)
{
await Task.Delay(250, ctx);
}
var success = await botInstance.WaitForChatMessageAsync(sent, TimeSpan.FromSeconds(15), ctx);
if (!success) throw new InvalidOperationException();
var i = 0;
while (i < 60)
{
await Task.Delay(1000, ctx);
await botInstance.KfClient.EditMessageAsync(sent.ChatMessageId!.Value, RenderHearings(hearings));
await botInstance.KfClient.EditMessageAsync(sent.ChatMessageUuid!, RenderHearings(hearings));
i++;
}
}

View File

@@ -35,7 +35,7 @@ public class EditTestCommand : ICommand
reference.Status == SentMessageTrackerStatus.Unknown ||
reference.Status == SentMessageTrackerStatus.ChatDisconnected ||
reference.Status == SentMessageTrackerStatus.Lost ||
reference.ChatMessageId == null)
reference.ChatMessageUuid == null)
{
logger.Error("Either message refused to send due to bot settings or something fucked up getting the message ID");
return;
@@ -44,13 +44,13 @@ public class EditTestCommand : ICommand
{
i++;
await Task.Delay(delay, ctx);
await botInstance.KfClient.EditMessageAsync(reference.ChatMessageId!.Value, $"{msg} {i}");
await botInstance.KfClient.EditMessageAsync(reference.ChatMessageUuid, $"{msg} {i}");
}
await Task.Delay(delay, ctx);
await botInstance.KfClient.EditMessageAsync(reference.ChatMessageId!.Value, "This message will self destruct in 1 second");
await botInstance.KfClient.EditMessageAsync(reference.ChatMessageUuid, "This message will self destruct in 1 second");
await Task.Delay(delay, ctx);
await botInstance.KfClient.DeleteMessageAsync(reference.ChatMessageId!.Value);
await botInstance.KfClient.DeleteMessageAsync(reference.ChatMessageUuid);
}
}
@@ -113,15 +113,15 @@ public class LengthLimitTestCommand : ICommand
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)
await botInstance.KfClient.DeleteMessageAsync(niceTruncation.ChatMessageId.Value);
if (exactTruncation.ChatMessageId != null)
await botInstance.KfClient.DeleteMessageAsync(exactTruncation.ChatMessageId.Value);
if (doNothing.ChatMessageId != null)
await botInstance.KfClient.DeleteMessageAsync(doNothing.ChatMessageId.Value);
if (niceTruncation.ChatMessageUuid != null)
await botInstance.KfClient.DeleteMessageAsync(niceTruncation.ChatMessageUuid);
if (exactTruncation.ChatMessageUuid != null)
await botInstance.KfClient.DeleteMessageAsync(exactTruncation.ChatMessageUuid);
if (doNothing.ChatMessageUuid != null)
await botInstance.KfClient.DeleteMessageAsync(doNothing.ChatMessageUuid);
// Should never happen
if (refuseToSend.ChatMessageId != null)
await botInstance.KfClient.DeleteMessageAsync(refuseToSend.ChatMessageId.Value);
if (refuseToSend.ChatMessageUuid != null)
await botInstance.KfClient.DeleteMessageAsync(refuseToSend.ChatMessageUuid);
}
}

View File

@@ -2,6 +2,6 @@
public class SeenMessageMetadataModel
{
public int MessageId { get; set; }
public string MessageUuid { get; set; }
public DateTimeOffset? LastEdited { get; set; }
}

View File

@@ -6,7 +6,7 @@ public class SentMessageTrackerModel
public required string Reference { get; set; }
public required string Message { get; set; }
public required SentMessageTrackerStatus Status { get; set; }
public int? ChatMessageId { get; set; }
public string? ChatMessageUuid { 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; }

View File

@@ -736,19 +736,19 @@ public class BotServices
private async Task OnYeetWinEditTaskAsync(SentMessageTrackerModel oldMsg, string newMsg)
{
var i = 0;
while (oldMsg.ChatMessageId == null && i < 50)
while (oldMsg.ChatMessageUuid == null && i < 50)
{
await Task.Delay(100, _cancellationToken);
i++;
}
if (oldMsg.ChatMessageId == null)
if (oldMsg.ChatMessageUuid == null)
{
_logger.Error($"Timed out waiting to figure out our message ID");
return;
}
await _chatBot.KfClient.EditMessageAsync(oldMsg.ChatMessageId.Value, newMsg);
await _chatBot.KfClient.EditMessageAsync(oldMsg.ChatMessageUuid, newMsg);
}
private void OnHowlggBetHistory(object sender, HowlggBetHistoryResponseModel data)
@@ -918,7 +918,7 @@ public class BotServices
BuiltIn.Keys.KiwiFarmsRedColor, BuiltIn.Keys.KiwiFarmsGreenColor
]);
var patience = 0;
while (msg.ChatMessageId == null)
while (msg.ChatMessageUuid == null)
{
patience++;
if (msg.Status is SentMessageTrackerStatus.Lost or SentMessageTrackerStatus.NotSending || patience > 50)
@@ -935,11 +935,11 @@ public class BotServices
{
if (seconds % 2 == 0)
{
await _chatBot.KfClient.EditMessageAsync(msg.ChatMessageId.Value, $"[color={settings[BuiltIn.Keys.KiwiFarmsGreenColor].Value}]{msg.Message}[/color]");
await _chatBot.KfClient.EditMessageAsync(msg.ChatMessageUuid, $"[color={settings[BuiltIn.Keys.KiwiFarmsGreenColor].Value}]{msg.Message}[/color]");
}
else
{
await _chatBot.KfClient.EditMessageAsync(msg.ChatMessageId.Value, $"[color={settings[BuiltIn.Keys.KiwiFarmsRedColor].Value}]{msg.Message}[/color]");
await _chatBot.KfClient.EditMessageAsync(msg.ChatMessageUuid, $"[color={settings[BuiltIn.Keys.KiwiFarmsRedColor].Value}]{msg.Message}[/color]");
}
await Task.Delay(1000, _cancellationToken);

View File

@@ -26,7 +26,7 @@ public class KasinoMines
public int Size { get; set; }
public int Mines { get; set; }
public List<(int r, int c)> BetsPlaced;
public int LastMessageId = 0;
public string? LastMessageId;
public string LastMessageReference = "";
@@ -44,12 +44,12 @@ public class KasinoMines
{
_logger.Info("Resetting message");
// 0 is the default for int
if (LastMessageId != 0)
if (LastMessageId != null)
{
await _kfChatBot.KfClient.DeleteMessageAsync(LastMessageId);
}
if (msg.ChatMessageId == null) throw new InvalidOperationException($"ChatMessageId was null for {msg.Reference}");
LastMessageId = msg.ChatMessageId.Value;
LastMessageId = msg.ChatMessageUuid ?? throw new InvalidOperationException($"ChatMessageId was null for {msg.Reference}");
LastMessageReference = msg.Reference;
}
@@ -83,7 +83,7 @@ public class KasinoMines
}
public async Task Explode((int r, int c) mineLocation, SentMessageTrackerModel msg)
{
if (LastMessageId == 0 || LastMessageId != msg.ChatMessageId)
if (LastMessageId == null || LastMessageId != msg.ChatMessageUuid)
{
await ResetMessage(msg);
}
@@ -154,8 +154,8 @@ public class KasinoMines
}
await Task.Delay(TimeSpan.FromSeconds(10));
await _kfChatBot.KfClient.DeleteMessageAsync(msg.ChatMessageId!.Value);
LastMessageId = 0;
await _kfChatBot.KfClient.DeleteMessageAsync(msg.ChatMessageUuid);
LastMessageId = null;
(int vertical, int horizontal) DistanceFromMine((int r, int c) coord)
{
@@ -298,8 +298,8 @@ public class KasinoMines
{
await GetSavedGames(gamblerId);
//attempt to delete the message if its there
if (ActiveGames[gamblerId].LastMessageId != 0) await _kfChatBot.KfClient.DeleteMessageAsync(ActiveGames[gamblerId].LastMessageId);
ActiveGames?.Remove(gamblerId);
if (ActiveGames[gamblerId].LastMessageId != null) await _kfChatBot.KfClient.DeleteMessageAsync(ActiveGames[gamblerId].LastMessageId!);
ActiveGames.Remove(gamblerId);
await SaveActiveGames(gamblerId);
}
@@ -345,7 +345,7 @@ public class KasinoMines
await GetSavedGames(gamblerId);
var game = ActiveGames[gamblerId];
game.LastInteracted = DateTimeOffset.UtcNow;
if (game.LastMessageId == 0 || game.LastMessageId != msg.ChatMessageId)
if (game.LastMessageId == null || game.LastMessageId != msg.ChatMessageUuid)
{
await game.ResetMessage(msg);
@@ -405,7 +405,7 @@ public class KasinoMines
await GetSavedGames(gamblerId);
var game = ActiveGames[gamblerId];
game.LastInteracted = DateTimeOffset.UtcNow;
if (game.LastMessageId == 0 || game.LastMessageId != msg.ChatMessageId)
if (game.LastMessageId == null || game.LastMessageId != msg.ChatMessageUuid)
{
await game.ResetMessage(msg);
}
@@ -435,7 +435,7 @@ public class KasinoMines
{
if (!validBets.Contains(bet) || game.BetsPlaced.Contains(bet) || bets.Contains(bet))
{
await _kfChatBot.KfClient.EditMessageAsync(invalidBetMsg.ChatMessageId!.Value,
await _kfChatBot.KfClient.EditMessageAsync(invalidBetMsg.ChatMessageUuid!,
$"{game.Creator.User.FormatUsername()}, invalid bet of {bet.r},{bet.c} removed (already placed, duplicate, or invalid coordinate)");
await Task.Delay(5);
}
@@ -446,20 +446,20 @@ public class KasinoMines
if (bets.Count > numGems)
{
await _kfChatBot.KfClient.EditMessageAsync(invalidBetMsg.ChatMessageId!.Value,
await _kfChatBot.KfClient.EditMessageAsync(invalidBetMsg.ChatMessageUuid!,
$"{game.Creator.User.FormatUsername()}, you bet on {bets.Count} gems, but there are only {numGems} left. Your list of bets was automatically truncated, and the game will automatically cash out if you win.");
bets.RemoveRange(numGems, bets.Count - numGems);
cashOut = true;
}
else if (bets.Count == numGems)
{
await _kfChatBot.KfClient.EditMessageAsync(invalidBetMsg.ChatMessageId!.Value,
await _kfChatBot.KfClient.EditMessageAsync(invalidBetMsg.ChatMessageUuid!,
$"{game.Creator.User.FormatUsername()}, you bet on all gems, so you will automatically cash out if you win.");
cashOut = true;
}
await Task.Delay(50);
_ = _kfChatBot.KfClient.DeleteMessageAsync(invalidBetMsg.ChatMessageId!.Value);
_ = _kfChatBot.KfClient.DeleteMessageAsync(invalidBetMsg.ChatMessageUuid!);
}
else bets = coords;
@@ -469,7 +469,7 @@ public class KasinoMines
if (game.MinesBoard[coord.r][ coord.c] == 'M')
{
game.BetsPlaced.Add(coord);
await _kfChatBot.KfClient.EditMessageAsync(msg.ChatMessageId!.Value, game.ToString());
await _kfChatBot.KfClient.EditMessageAsync(msg.ChatMessageUuid!, game.ToString());
_ = game.Explode((coord.r, coord.c), msg);
var newBalance = await Money.NewWagerAsync(game.Creator.Id, game.Wager, -game.Wager, WagerGame.Mines);
var net = -game.Wager;
@@ -483,10 +483,10 @@ public class KasinoMines
if (Money.GetRandomNumber(game.Creator, 0, 100) > 100 * HOUSE_EDGE)//if you didn't lose, check to see if the switch was flipped
{
game.BetsPlaced.Add(coord);
await _kfChatBot.KfClient.EditMessageAsync(msg.ChatMessageId!.Value, game.ToString());
await _kfChatBot.KfClient.EditMessageAsync(msg.ChatMessageUuid!, game.ToString());
await game.RigBoard(coord);
await Task.Delay(50);
await _kfChatBot.KfClient.EditMessageAsync(msg.ChatMessageId!.Value, game.ToString());
await _kfChatBot.KfClient.EditMessageAsync(msg.ChatMessageUuid!, game.ToString());
_ = game.Explode(coord, msg);
var newBalance = await Money.NewWagerAsync(game.Creator.Id, game.Wager, -game.Wager, WagerGame.Mines);
var net = -game.Wager;
@@ -500,7 +500,7 @@ public class KasinoMines
{
game.BetsPlaced.Add(coord);
}
await _kfChatBot.KfClient.EditMessageAsync(msg.ChatMessageId!.Value, game.ToString());
await _kfChatBot.KfClient.EditMessageAsync(msg.ChatMessageUuid!, game.ToString());
}

View File

@@ -24,6 +24,8 @@ public class ChatClient
public event EventHandlers.OnWsDisconnectionEventHandler? OnWsDisconnection;
public event EventHandlers.OnFailedToJoinRoom? OnFailedToJoinRoom;
public event EventHandlers.OnUnknownCommand? OnUnknownCommand;
public event EventHandlers.OnPermissionsEventHandler? OnPermissions;
public event EventHandlers.OnSystemMessage? OnSystemMessage;
private WebsocketClient? _wsClient;
private readonly Logger _logger = LogManager.GetCurrentClassLogger();
private ChatClientConfigModel _config;
@@ -188,6 +190,20 @@ public class ChatClient
return;
}
if (packetType.ContainsKey("permissions"))
{
_logger.Debug("Looks like we got permissions");
WsPermissions(message);
return;
}
if (packetType.ContainsKey("system"))
{
_logger.Debug("Looks like a system message");
WsSystemMessage(message);
return;
}
if (packetType.ContainsKey("delete"))
{
_logger.Debug($"Looks like this is a message deletion packet");
@@ -226,22 +242,22 @@ public class ChatClient
_wsClient.Send($"/delete {messageId}");
}
public async Task DeleteMessageAsync(int messageId)
public async Task DeleteMessageAsync(string messageUuid)
{
_logger.Debug($"Deleting {messageId}");
_logger.Debug($"Deleting {messageUuid}");
if (_wsClient == null) throw new WebSocketNotInitializedException();
await _wsClient.SendInstant($"/delete {messageId}");
await _wsClient.SendInstant($"/delete {messageUuid}");
}
public void EditMessage(int messageId, string newMessage)
public void EditMessage(string messageUuid, string newMessage)
{
var payload = JsonSerializer.Serialize(new EditMessageJsonModel {Id = messageId, Message = newMessage});
_logger.Debug($"Editing {messageId} with '{newMessage}'");
var payload = JsonSerializer.Serialize(new EditMessageJsonModel {Uuid = messageUuid, Message = newMessage});
_logger.Debug($"Editing {messageUuid} with '{newMessage}'");
if (_wsClient == null) throw new WebSocketNotInitializedException();
_wsClient.Send($"/edit {payload}");
}
public async Task EditMessageAsync(int messageId, string newMessage)
public async Task EditMessageAsync(string messageUuid, string newMessage)
{
var settings = new TextEncoderSettings();
settings.AllowRange(UnicodeRanges.All);
@@ -249,8 +265,8 @@ public class ChatClient
{
Encoder = JavaScriptEncoder.Create(settings)
};
var payload = JsonSerializer.Serialize(new EditMessageJsonModel {Id = messageId, Message = newMessage}, options);
_logger.Debug($"Editing {messageId} with '{newMessage}'");
var payload = JsonSerializer.Serialize(new EditMessageJsonModel {Uuid = messageUuid, Message = newMessage}, options);
_logger.Debug($"Editing {messageUuid} with '{newMessage}'");
if (_wsClient == null) throw new WebSocketNotInitializedException();
var msg = $"/edit {payload}";
var length = Encoding.UTF8.GetByteCount(msg);
@@ -285,7 +301,7 @@ public class ChatClient
LastActivity = null
},
Message = chatMessage.Message,
MessageId = chatMessage.MessageId,
MessageUuid = chatMessage.MessageUuid,
MessageRaw = chatMessage.MessageRaw,
RoomId = chatMessage.RoomId,
MessageRawHtmlDecoded = WebUtility.HtmlDecode(chatMessage.MessageRaw),
@@ -347,6 +363,35 @@ public class ChatClient
_logger.Debug($"Following users have parted: {string.Join(',', usersParted)}");
OnUsersParted?.Invoke(this, usersParted);
}
private void WsPermissions(ResponseMessage message)
{
var data = JsonSerializer.Deserialize<JsonElement>(message.Text);
var permissions = data.GetProperty("permissions").Deserialize<PermissionsJsonModel>();
try
{
OnPermissions?.Invoke(this, permissions);
}
catch (Exception e)
{
_logger.Error("Caught error when invoking OnPermissions");
_logger.Error(e);
}
}
private void WsSystemMessage(ResponseMessage message)
{
var msg = JsonSerializer.Deserialize<JsonElement>(message.Text).GetProperty("system").GetString();
try
{
OnSystemMessage?.Invoke(this, msg);
}
catch (Exception e)
{
_logger.Error("Caught error when invoking OnSystemMessage");
_logger.Error(e);
}
}
}
public class WebSocketNotInitializedException : Exception;

View File

@@ -25,4 +25,8 @@ public class EventHandlers
public delegate void OnFailedToJoinRoom(object sender, string message);
public delegate void OnUnknownCommand(object sender, string message);
public delegate void OnPermissionsEventHandler(object sender, PermissionsJsonModel permissions);
public delegate void OnSystemMessage(object sender, string message);
}

View File

@@ -7,7 +7,7 @@ public class MessageModel
/// HTML formatted message
/// </summary>
public required string Message { get; set; }
public required int MessageId { get; set; }
public required string MessageUuid { get; set; }
public DateTimeOffset? MessageEditDate { get; set; }
public required DateTimeOffset MessageDate { get; set; }
/// <summary>

View File

@@ -4,8 +4,8 @@ namespace KfChatDotNetWsClient.Models.Json;
public class EditMessageJsonModel
{
[JsonPropertyName("id")]
public required int Id { get; set; }
[JsonPropertyName("uuid")]
public required string Uuid { get; set; }
[JsonPropertyName("message")]
public required string Message { get; set; }

View File

@@ -41,8 +41,8 @@ public class MessagesJsonModel
public required AuthorModel Author { get; set; }
[JsonPropertyName("message")]
public required string Message { get; set; }
[JsonPropertyName("message_id")]
public int MessageId { get; set; }
[JsonPropertyName("message_uuid")]
public required string MessageUuid { get; set; }
[JsonPropertyName("message_edit_date")]
public int MessageEditDate { get; set; }
[JsonPropertyName("message_date")]

View File

@@ -0,0 +1,27 @@
using System.Text.Json.Serialization;
namespace KfChatDotNetWsClient.Models.Json;
public class PermissionsJsonModel
{
[JsonPropertyName("can_view")]
public required bool CanView { get; set; }
[JsonPropertyName("can_send")]
public required bool CanSend { get; set; }
[JsonPropertyName("can_edit_own")]
public required bool CanEditOwn { get; set; }
[JsonPropertyName("can_edit_other")]
public required bool CanEditOther { get; set; }
[JsonPropertyName("can_delete_own")]
public required bool CanDeleteOwn { get; set; }
[JsonPropertyName("can_delete_other")]
public required bool CanDeleteOther { get; set; }
[JsonPropertyName("can_report")]
public required bool CanReport { get; set; }
[JsonPropertyName("can_view_deleted")]
public required bool CanViewDeleted { get; set; }
[JsonPropertyName("can_undelete")]
public required bool CanUndelete { get; set; }
[JsonPropertyName("can_motd")]
public required bool CanMotd { get; set; }
}