Big update introducing ghetto command interface, settings, database and howl.gg bet feed scraping

This commit is contained in:
barelyprofessional
2024-07-18 01:37:15 +10:00
parent 936bf743a5
commit d61a171e54
46 changed files with 2198 additions and 218 deletions

View File

@@ -1,7 +1,7 @@
using System.Net;
using System.Text.Json;
using KfChatDotNetKickBot.Models;
using KfChatDotNetKickBot.Models;
using KfChatDotNetKickBot.Models.DbModels;
using KfChatDotNetKickBot.Services;
using KfChatDotNetKickBot.Settings;
using KfChatDotNetWsClient;
using KfChatDotNetWsClient.Models;
using KfChatDotNetWsClient.Models.Events;
@@ -14,12 +14,11 @@ namespace KfChatDotNetKickBot;
public class KickBot
{
private readonly ChatClient _kfClient;
internal readonly ChatClient KfClient;
private readonly KickWsClient.KickWsClient _kickClient;
private readonly Logger _logger = LogManager.GetCurrentClassLogger();
private readonly ConfigModel _config;
private readonly bool _pingEnabled = true;
private bool _gambaSeshPresent;
internal bool GambaSeshPresent;
private string _xfSessionToken = null!;
// Oh no it's an ever expanding list that may never get cleaned up!
// BUY MORE RAM
@@ -32,43 +31,51 @@ public class KickBot
private DiscordService _discord;
private TwitchChat _twitchChat;
private string? _lastDiscordStatus;
private bool _isBmjLive = false;
internal bool IsBmjLive = false;
private bool _isBmjLiveSynced = false;
private Dictionary<string, int> _userIdMapping = new();
private DateTime _lastKfEvent = DateTime.Now;
private BotCommands _botCommands;
private string _bmjTwitchUsername;
private Howlgg _howlgg;
public KickBot()
{
_logger.Info("Bot starting!");
const string configPath = "config.json";
if (!Path.Exists(configPath))
{
_logger.Error($"{configPath} is missing! Exiting");
Environment.Exit(1);
}
_config = JsonSerializer.Deserialize<Models.ConfigModel>(File.ReadAllText(configPath)) ??
throw new InvalidOperationException();
RefreshXfToken().Wait(_cancellationToken);
_kfClient = new ChatClient(new ChatClientConfigModel
var settings = Helpers.GetMultipleValues([
BuiltIn.Keys.KiwiFarmsWsEndpoint, BuiltIn.Keys.KiwiFarmsDomain, BuiltIn.Keys.PusherEndpoint,
BuiltIn.Keys.Proxy, BuiltIn.Keys.PusherReconnectTimeout, BuiltIn.Keys.PusherChannels,
BuiltIn.Keys.TwitchBossmanJackId, BuiltIn.Keys.DiscordToken, BuiltIn.Keys.KiwiFarmsWsReconnectTimeout,
BuiltIn.Keys.KiwiFarmsToken
]).Result;
_xfSessionToken = settings[BuiltIn.Keys.KiwiFarmsToken].Value ?? "unset";
if (_xfSessionToken == "unset")
{
WsUri = _config.KfWsEndpoint,
RefreshXfToken().Wait(_cancellationToken);
}
KfClient = new ChatClient(new ChatClientConfigModel
{
WsUri = new Uri(settings[BuiltIn.Keys.KiwiFarmsWsEndpoint].Value ?? throw new InvalidOperationException($"{BuiltIn.Keys.KiwiFarmsWsEndpoint} cannot be null")),
XfSessionToken = _xfSessionToken,
CookieDomain = _config.KfWsEndpoint.Host,
Proxy = _config.Proxy,
ReconnectTimeout = _config.KfReconnectTimeout
CookieDomain = settings[BuiltIn.Keys.KiwiFarmsDomain].Value ?? throw new InvalidOperationException($"{BuiltIn.Keys.KiwiFarmsDomain} cannot be null"),
Proxy = settings[BuiltIn.Keys.Proxy].Value,
ReconnectTimeout = Convert.ToInt32(settings[BuiltIn.Keys.KiwiFarmsWsReconnectTimeout].Value)
});
_kickClient = new KickWsClient.KickWsClient(_config.PusherEndpoint.ToString(),
_config.Proxy, _config.PusherReconnectTimeout);
_kickClient = new KickWsClient.KickWsClient(settings[BuiltIn.Keys.PusherEndpoint].Value!,
settings[BuiltIn.Keys.Proxy].Value, Convert.ToInt32(settings[BuiltIn.Keys.PusherReconnectTimeout].Value));
_logger.Debug("Creating bot command instance");
_botCommands = new BotCommands(this, _cancellationToken);
_kfClient.OnMessages += OnKfChatMessage;
_kfClient.OnUsersParted += OnUsersParted;
_kfClient.OnUsersJoined += OnUsersJoined;
_kfClient.OnWsDisconnection += OnKfWsDisconnected;
_kfClient.OnWsReconnect += OnKfWsReconnected;
_kfClient.OnFailedToJoinRoom += OnFailedToJoinRoom;
KfClient.OnMessages += OnKfChatMessage;
KfClient.OnUsersParted += OnUsersParted;
KfClient.OnUsersJoined += OnUsersJoined;
KfClient.OnWsDisconnection += OnKfWsDisconnected;
KfClient.OnWsReconnect += OnKfWsReconnected;
KfClient.OnFailedToJoinRoom += OnFailedToJoinRoom;
_kickClient.OnStreamerIsLive += OnStreamerIsLive;
_kickClient.OnChatMessage += OnKickChatMessage;
@@ -76,10 +83,11 @@ public class KickBot
_kickClient.OnPusherSubscriptionSucceeded += OnPusherSubscriptionSucceeded;
_kickClient.OnStopStreamBroadcast += OnStopStreamBroadcast;
_kfClient.StartWsClient().Wait(_cancellationToken);
KfClient.StartWsClient().Wait(_cancellationToken);
_kickClient.StartWsClient().Wait(_cancellationToken);
foreach (var channel in _config.PusherChannels)
var pusherChannels = settings[BuiltIn.Keys.PusherChannels].Value ?? "";
foreach (var channel in pusherChannels.Split(','))
{
_kickClient.SendPusherSubscribe(channel);
}
@@ -88,47 +96,78 @@ public class KickBot
var pingThread = new Thread(PingThread);
pingThread.Start();
if (_config.BossmanJackTwitchId != null)
if (settings[BuiltIn.Keys.TwitchBossmanJackId].Value != null)
{
_logger.Debug("Creating Twitch live stream notification client");
_twitch = new Twitch([_config.BossmanJackTwitchId.Value], _config.Proxy, _cancellationToken);
_twitch = new Twitch([Convert.ToInt32(settings[BuiltIn.Keys.TwitchBossmanJackId].Value)], settings[BuiltIn.Keys.Proxy].Value, _cancellationToken);
_twitch.OnStreamStateUpdated += OnTwitchStreamStateUpdated;
_twitch.StartWsClient().Wait(_cancellationToken);
}
else
{
_logger.Debug("Ignoring Twitch client as TwitchChannels is not defined");
_logger.Debug($"Ignoring Twitch client as {BuiltIn.Keys.TwitchBossmanJackId} is not defined");
}
BuildShuffle();
BuildDiscord();
BuildTwitchChat();
_howlgg = new Howlgg(settings[BuiltIn.Keys.Proxy].Value, _cancellationToken);
_howlgg.OnHowlggBetHistory += OnHowlggBetHistory;
_howlgg.StartWsClient().Wait(_cancellationToken);
_logger.Debug("Blocking the main thread");
var exitEvent = new ManualResetEvent(false);
exitEvent.WaitOne();
}
private void OnHowlggBetHistory(object sender, HowlggBetHistoryResponseModel data)
{
_logger.Debug("Received bet history from Howl.gg");
using var db = new ApplicationDbContext();
foreach (var bets in data.History.Data)
{
if (db.HowlggBets.Any(b => b.GameId == bets.GameId))
{
_logger.Trace("Bet already exists in DB");
continue;
}
db.HowlggBets.Add(new HowlggBetsDbModel
{
UserId = data.User.Id,
BetId = bets.Id,
GameId = bets.GameId,
Bet = bets.Bet,
Profit = bets.Profit,
Date = bets.Date,
Game = bets.Game
});
_logger.Debug("Added bet to DB");
}
db.SaveChanges();
}
private void BuildShuffle()
{
_logger.Debug("Building Shuffle");
_shuffle = new Shuffle(_config.Proxy, _cancellationToken);
_shuffle = new Shuffle(Helpers.GetValue(BuiltIn.Keys.Proxy).Result.Value, _cancellationToken);
_shuffle.OnLatestBetUpdated += ShuffleOnLatestBetUpdated;
_shuffle.OnWsDisconnection += ShuffleOnWsDisconnection;
_shuffle.StartWsClient().Wait(_cancellationToken);
}
private void BuildDiscord()
{
var settings = Helpers.GetMultipleValues([BuiltIn.Keys.DiscordToken, BuiltIn.Keys.Proxy]).Result;
_logger.Debug("Building Discord");
if (_config.DiscordToken == null)
if (settings[BuiltIn.Keys.DiscordToken].Value == null)
{
_logger.Info("Not building Discord as the token is not configured");
return;
}
_discord = new DiscordService(_config.DiscordToken, _config.Proxy, _cancellationToken);
_discord = new DiscordService(settings[BuiltIn.Keys.DiscordToken].Value!, settings[BuiltIn.Keys.Proxy].Value, _cancellationToken);
_discord.OnInvalidCredentials += DiscordOnInvalidCredentials;
_discord.OnWsDisconnection += DiscordOnWsDisconnection;
_discord.OnMessageReceived += DiscordOnMessageReceived;
_discord.OnPresenceUpdated += DiscordOnPresenceUpdated;
_discord.StartWsClient().Wait(_cancellationToken);
@@ -136,105 +175,81 @@ public class KickBot
private void BuildTwitchChat()
{
var settings = Helpers.GetMultipleValues([BuiltIn.Keys.TwitchBossmanJackUsername, BuiltIn.Keys.Proxy]).Result;
_logger.Debug("Building Twitch Chat");
if (_config.BossmanJackTwitchUsername == null)
if (settings[BuiltIn.Keys.TwitchBossmanJackUsername].Value == null)
{
_logger.Info("Not building Twitch Chat client as BMJ's username is not configured");
return;
}
_twitchChat = new TwitchChat($"#{_config.BossmanJackTwitchUsername}", _config.Proxy, _cancellationToken);
_bmjTwitchUsername = settings[BuiltIn.Keys.TwitchBossmanJackUsername].Value!;
_twitchChat = new TwitchChat($"#{settings[BuiltIn.Keys.TwitchBossmanJackUsername].Value}", settings[BuiltIn.Keys.Proxy].Value, _cancellationToken);
_twitchChat.OnMessageReceived += TwitchChatOnMessageReceived;
_twitchChat.OnWsDisconnection += TwitchChatOnWsDisconnection;
_twitchChat.StartWsClient().Wait(_cancellationToken);
}
private void TwitchChatOnWsDisconnection(object sender, DisconnectionInfo e)
{
if (e.Type == DisconnectionType.ByServer)
{
_twitchChat.Dispose();
BuildTwitchChat();
}
}
private void TwitchChatOnMessageReceived(object sender, string nick, string target, string message)
{
if (nick != _config.BossmanJackTwitchUsername)
if (nick != _bmjTwitchUsername)
{
return;
}
_sendChatMessage($"[img]https://i.postimg.cc/QMFVV2Xk/twitch16.png[/img] {nick}: {message}", true);
// Not caching this value as it won't harm it to have to look this up in even the worst spergout sesh
var twitchIcon = Helpers.GetValue(BuiltIn.Keys.TwitchIcon).Result.Value;
SendChatMessage($"[img]{twitchIcon}[/img] {nick}: {message}", true);
}
private void DiscordOnPresenceUpdated(object sender, DiscordPresenceUpdateModel presence)
{
if (presence.User.Id != _config.DiscordBmjId)
var settings = Helpers.GetMultipleValues([BuiltIn.Keys.DiscordBmjId, BuiltIn.Keys.DiscordIcon]).Result;
if (presence.User.Id != settings[BuiltIn.Keys.DiscordBmjId].Value)
{
return;
}
if (_lastDiscordStatus == presence.Status)
{
_logger.Debug("Ignoring status update as it's the same as the last one");
return;
}
_lastDiscordStatus = presence.Status;
// if (_lastDiscordStatus == presence.Status)
// {
// _logger.Debug("Ignoring status update as it's the same as the last one");
// return;
// }
// _lastDiscordStatus = presence.Status;
var clientStatus = presence.ClientStatus.Keys.Aggregate(string.Empty, (current, device) => current + $"{device} is {presence.ClientStatus[device]}; ");
_sendChatMessage($"[img]https://i.postimg.cc/cLmQrp89/discord16.png[/img] BossmanJack has updated his Discord presence: {clientStatus}");
SendChatMessage($"[img]{settings[BuiltIn.Keys.DiscordIcon].Value}[/img] BossmanJack has updated his Discord presence: {clientStatus}");
}
private void DiscordOnMessageReceived(object sender, DiscordMessageModel message)
{
if (message.Author.Id != _config.DiscordBmjId)
var settings = Helpers.GetMultipleValues([BuiltIn.Keys.DiscordBmjId, BuiltIn.Keys.DiscordIcon]).Result;
if (message.Author.Id != settings[BuiltIn.Keys.DiscordBmjId].Value)
{
return;
}
var result = $"[img]https://i.postimg.cc/cLmQrp89/discord16.png[/img] BossmanJack: {message.Content}";
var result = $"[img]{settings[BuiltIn.Keys.DiscordIcon].Value}[/img] BossmanJack: {message.Content}";
foreach (var attachment in message.Attachments ?? [])
{
result += $"[br]Attachment: {attachment.GetProperty("filename").GetString()} {attachment.GetProperty("url").GetString()}";
}
_sendChatMessage(result);
}
private void DiscordOnWsDisconnection(object sender, DisconnectionInfo e)
{
_logger.Error($"Discord dropped, reason {e.Type}");
// This is raised when the Websocket client is disposed
// Attempting to dispose it again while it is being disposed causes a loop and probably eventually a stack overflow
if (e.Type == DisconnectionType.Exit)
{
return;
}
_discord.Dispose();
BuildDiscord();
SendChatMessage(result);
}
private void DiscordOnInvalidCredentials(object sender, DiscordPacketReadModel packet)
{
_logger.Error("Credentials failed to validate. Killing service.");
_discord.Dispose();
}
private void ShuffleOnWsDisconnection(object sender, DisconnectionInfo e)
{
if (e.Type == DisconnectionType.ByServer)
{
_shuffle.Dispose();
BuildShuffle();
}
_logger.Error("Credentials failed to validate.");
}
private void ShuffleOnLatestBetUpdated(object sender, ShuffleLatestBetModel bet)
{
_logger.Debug("Shuffle bet has arrived");
if (bet.Username != "TheBossmanJack")
var settings = Helpers
.GetMultipleValues([BuiltIn.Keys.ShuffleBmjUsername, BuiltIn.Keys.TwitchBossmanJackUsername]).Result;
_logger.Trace("Shuffle bet has arrived");
if (bet.Username != settings[BuiltIn.Keys.ShuffleBmjUsername].Value)
{
return;
}
_logger.Info("ALERT BMJ IS BETTING");
if (_isBmjLive)
if (IsBmjLive)
{
_logger.Info("Ignoring as BMJ is live");
return;
@@ -245,10 +260,10 @@ public class KickBot
// He was schizo betting on Dice, so I want to avoid a lot of API requests to Twitch in case they rate limit
if (!_isBmjLiveSynced)
{
_isBmjLive = _twitch.IsStreamLive("thebossmanjack").Result;
IsBmjLive = _twitch.IsStreamLive(settings[BuiltIn.Keys.TwitchBossmanJackUsername].Value!).Result;
_isBmjLiveSynced = true;
}
if (_isBmjLive)
if (IsBmjLive)
{
_logger.Info("Double checked and he is really online");
return;
@@ -257,7 +272,7 @@ public class KickBot
var payoutColor = "green";
if (float.Parse(bet.Payout) < float.Parse(bet.Amount)) payoutColor = "red";
// There will be a check for live status but ignoring that while we deal with an emergency dice situation
_sendChatMessage($"🚨🚨 {bet.Username} just bet {bet.Amount} {bet.Currency} which paid out [color={payoutColor}]{bet.Payout} {bet.Currency}[/color] ({bet.Multiplier}x) on {bet.GameName} 💰💰", true);
SendChatMessage($"🚨🚨 {bet.Username} just bet {bet.Amount} {bet.Currency} which paid out [color={payoutColor}]{bet.Payout} {bet.Currency}[/color] ({bet.Multiplier}x) on {bet.GameName} 💰💰", true);
}
private void OnTwitchStreamStateUpdated(object sender, int channelId, bool isLive)
@@ -265,13 +280,13 @@ public class KickBot
_logger.Info($"BossmanJack stream event came in. isLive => {isLive}");
if (isLive)
{
_sendChatMessage("BossmanJack just went live on Twitch! https://www.twitch.tv/thebossmanjack\r\n" +
SendChatMessage("BossmanJack just went live on Twitch! https://www.twitch.tv/thebossmanjack\r\n" +
"Ad-free re-stream at https://bossmanjack.tv courtesy of @Kees H");
_isBmjLive = true;
IsBmjLive = true;
return;
}
_sendChatMessage("BossmanJack is no longer live! :lossmanjack:");
_isBmjLive = false;
SendChatMessage("BossmanJack is no longer live! :lossmanjack:");
IsBmjLive = false;
}
private void OnFailedToJoinRoom(object sender, string message)
@@ -279,10 +294,10 @@ public class KickBot
_logger.Error($"Couldn't join the room. KF returned: {message}");
_logger.Error("This is likely due to the session cookie expiring. Retrieving a new one.");
RefreshXfToken().Wait(_cancellationToken);
_kfClient.UpdateToken(_xfSessionToken);
KfClient.UpdateToken(_xfSessionToken);
_logger.Info("Retrieved fresh token. Reconnecting.");
_kfClient.Disconnect();
_kfClient.StartWsClient().Wait(_cancellationToken);
KfClient.Disconnect();
KfClient.StartWsClient().Wait(_cancellationToken);
_logger.Info("Client should be reconnecting now");
}
@@ -291,8 +306,8 @@ public class KickBot
while (_pingEnabled)
{
Thread.Sleep(TimeSpan.FromSeconds(15));
_logger.Debug("Pinging KF and Pusher");
_kfClient.SendMessage("/ping");
_logger.Debug("Pinging KF");
KfClient.SendMessage("/ping");
_kickClient.SendPusherPing();
if (_initialStartCooldown) _initialStartCooldown = false;
var inactivityTime = DateTime.Now - _lastKfEvent;
@@ -300,80 +315,55 @@ public class KickBot
if (inactivityTime.TotalMinutes > 10)
{
_logger.Error("Forcing reconnection as bot is completely dead");
_kfClient.Reconnect().Wait(_cancellationToken);
KfClient.Reconnect().Wait(_cancellationToken);
}
_logger.Debug("Polling Bossman's Howl.gg stats");
_howlgg.GetUserInfo("951905");
}
}
private async Task RefreshXfToken()
{
var cookie = await KfTokenService.FetchSessionTokenAsync(_config.KfDomain, _config.KfUsername, _config.KfPassword,
_config.ChromiumPath, _config.Proxy);
var settings = Helpers.GetMultipleValues([BuiltIn.Keys.KiwiFarmsDomain,
BuiltIn.Keys.KiwiFarmsUsername, BuiltIn.Keys.KiwiFarmsPassword, BuiltIn.Keys.KiwiFarmsChromiumPath,
BuiltIn.Keys.Proxy]).Result;
var cookie = await KfTokenService.FetchSessionTokenAsync(settings[BuiltIn.Keys.KiwiFarmsDomain].Value!,
settings[BuiltIn.Keys.KiwiFarmsUsername].Value!, settings[BuiltIn.Keys.KiwiFarmsPassword].Value!,
settings[BuiltIn.Keys.KiwiFarmsChromiumPath].Value!, settings[BuiltIn.Keys.Proxy].Value);
_logger.Debug($"FetchSessionTokenAsync returned {cookie}");
_xfSessionToken = cookie;
await Helpers.SetValue(BuiltIn.Keys.KiwiFarmsToken, _xfSessionToken);
}
private void OnStreamerIsLive(object sender, KickModels.StreamerIsLiveEventModel? e)
{
if (e == null) return;
_sendChatMessage($"Dirt Devils LFG! @Juhlonduss is live! {e.Livestream.SessionTitle} https://kick.com/dirtdevil-enjoyer", true);
SendChatMessage($"Dirt Devils LFG! @Juhlonduss is live! {e.Livestream.SessionTitle} https://kick.com/dirtdevil-enjoyer", true);
}
private void OnStopStreamBroadcast(object sender, KickModels.StopStreamBroadcastEventModel? e)
{
_sendChatMessage("Dirt Devils felted. Stream is over. :lossmanjack:", true);
SendChatMessage("Dirt Devils felted. Stream is over. :lossmanjack:", true);
}
private void OnKfChatMessage(object sender, List<MessageModel> messages, MessagesJsonModel jsonPayload)
{
var settings = Helpers.GetMultipleValues([BuiltIn.Keys.GambaSeshDetectEnabled, BuiltIn.Keys.GambaSeshUserId])
.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 (_config.EnableGambaSeshDetect && !_initialStartCooldown && message.Author.Id == _config.GambaSeshUserId && !_gambaSeshPresent)
if (settings[BuiltIn.Keys.GambaSeshDetectEnabled].Value == "true" && !_initialStartCooldown && message.Author.Id == Convert.ToInt32(settings[BuiltIn.Keys.GambaSeshUserId].Value) && !GambaSeshPresent)
{
_logger.Info("Received a GambaSesh message after cooldown and while thinking he's not here. Setting the presence flag to avoid spamming chat");
_gambaSeshPresent = true;
GambaSeshPresent = true;
}
if (!_seenMsgIds.Contains(message.MessageId) && !_initialStartCooldown)
{
if (message.MessageRaw.StartsWith("!time"))
{
var bmt = new DateTimeOffset(TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow,
TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time")), TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time").BaseUtcOffset);
_sendChatMessage($"It's currently {bmt:h:mm:ss tt} BMT");
}
else if (message.MessageRaw.StartsWith("!twisted"))
{
_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 🤯");
}
else if (message.MessageRaw.StartsWith("!insanity"))
{
// ReSharper disable once StringLiteralTypo
_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");
}
else if (message.MessageRaw.StartsWith("!helpme"))
{
_sendChatMessage("[img]https://i.postimg.cc/fTw6tGWZ/ineedmoneydumbfuck.png[/img]", true);
}
else if (message.MessageRaw.StartsWith("!whois"))
{
var lookup = WebUtility.HtmlDecode(message.MessageRaw.Replace("!whois ", string.Empty)
.TrimStart('@').TrimEnd(' ').TrimEnd(','));
if (_userIdMapping.ContainsKey(lookup))
{
_sendChatMessage($"{lookup}'s ID is {_userIdMapping[lookup]}", true);
}
else
{
_sendChatMessage("Don't know they who they are.", true);
}
}
else if (message.MessageRaw == "!sent")
{
_sendChatMessage("[img]https://i.ibb.co/GHq7hb1/4373-g-N5-HEH2-Hkc.png[/img]", true);
}
_logger.Debug("Passing message to command interface");
_botCommands.ProcessMessage(message);
}
else
{
@@ -383,21 +373,24 @@ public class KickBot
}
}
private void _sendChatMessage(string message, bool bypassSeshDetect = false)
public void SendChatMessage(string message, bool bypassSeshDetect = false)
{
if (_config.SuppressChatMessages)
var settings = Helpers
.GetMultipleValues([BuiltIn.Keys.KiwiFarmsSuppressChatMessages, BuiltIn.Keys.GambaSeshDetectEnabled])
.Result;
if (settings[BuiltIn.Keys.KiwiFarmsSuppressChatMessages].Value == "true")
{
_logger.Info("Not sending message as SuppressChatMessages is enabled");
_logger.Info($"Message was: {message}");
return;
}
if (_gambaSeshPresent && _config.EnableGambaSeshDetect && !bypassSeshDetect)
if (GambaSeshPresent && settings[BuiltIn.Keys.GambaSeshDetectEnabled].Value == "true" && !bypassSeshDetect)
{
_logger.Info($"Not sending message '{message}' as GambaSesh is present");
return;
}
_kfClient.SendMessage(message);
KfClient.SendMessage(message);
}
private void OnKickChatMessage(object sender, KickModels.ChatMessageEventModel? e)
@@ -407,59 +400,81 @@ public class KickBot
_logger.Debug($"BB Code Translation: {e.Content.TranslateKickEmotes()}");
if (e.Sender.Slug != "bossmanjack") return;
var kickIcon = Helpers.GetValue(BuiltIn.Keys.KickIcon).Result;
_logger.Debug("Message from BossmanJack");
_sendChatMessage($"[img]{_config.KickIcon}[/img] BossmanJack: {e.Content.TranslateKickEmotes()}");
SendChatMessage($"[img]{kickIcon.Value}[/img] BossmanJack: {e.Content.TranslateKickEmotes()}");
}
private void OnUsersJoined(object sender, List<UserModel> users, UsersJsonModel jsonPayload)
{
var settings = Helpers.GetMultipleValues([BuiltIn.Keys.GambaSeshUserId, BuiltIn.Keys.GambaSeshDetectEnabled])
.Result;
_lastKfEvent = DateTime.Now;
_logger.Debug($"Received {users.Count} user join events");
using var db = new ApplicationDbContext();
foreach (var user in users)
{
if (user.Id == _config.GambaSeshUserId && _config.EnableGambaSeshDetect)
if (user.Id == Convert.ToInt32(settings[BuiltIn.Keys.GambaSeshUserId].Value) && settings[BuiltIn.Keys.GambaSeshDetectEnabled].Value == "true")
{
_logger.Info("GambaSesh is now present");
_gambaSeshPresent = true;
GambaSeshPresent = true;
}
_logger.Info($"{user.Username} joined!");
if (!_userIdMapping.ContainsKey(user.Username))
var userDb = db.Users.FirstOrDefault(u => u.KfId == user.Id);
if (userDb == null)
{
_userIdMapping.Add(user.Username, user.Id);
db.Users.Add(new UserDbModel { KfId = user.Id, KfUsername = user.Username });
_logger.Debug("Adding user to DB");
continue;
}
// Detect a username change
if (userDb.KfUsername != user.Username)
{
_logger.Debug("Username has updated, updating DB");
userDb.KfUsername = user.Username;
db.SaveChanges();
}
}
db.SaveChanges();
}
private void OnUsersParted(object sender, List<int> userIds)
{
var settings = Helpers.GetMultipleValues([BuiltIn.Keys.GambaSeshUserId, BuiltIn.Keys.GambaSeshDetectEnabled])
.Result;
_lastKfEvent = DateTime.Now;
if (userIds.Contains(_config.GambaSeshUserId) && _config.EnableGambaSeshDetect)
if (userIds.Contains(Convert.ToInt32(settings[BuiltIn.Keys.GambaSeshUserId].Value)) && settings[BuiltIn.Keys.GambaSeshDetectEnabled].Value == "true")
{
_logger.Info("GambaSesh is no longer present");
_gambaSeshPresent = false;
GambaSeshPresent = false;
}
}
private void OnKfWsDisconnected(object sender, DisconnectionInfo disconnectionInfo)
{
_logger.Error($"Sneedchat disconnected due to {disconnectionInfo.Type}");
_logger.Error(JsonSerializer.Serialize(disconnectionInfo));
_logger.Error($"Close Status => {disconnectionInfo.CloseStatus}; Close Status Description => {disconnectionInfo.CloseStatusDescription}");
_logger.Error(disconnectionInfo.Exception);
}
private void OnKfWsReconnected(object sender, ReconnectionInfo reconnectionInfo)
{
var roomId = Convert.ToInt32(Helpers.GetValue(BuiltIn.Keys.KiwiFarmsRoomId).Result.Value);
_logger.Error($"Sneedchat reconnected due to {reconnectionInfo.Type}");
_logger.Info("Resetting GambaSesh presence so it can resync if he crashed while the bot was DC'd");
_gambaSeshPresent = false;
_logger.Info($"Rejoining {_config.KfChatRoomId}");
_kfClient.JoinRoom(_config.KfChatRoomId);
GambaSeshPresent = false;
_logger.Info($"Rejoining {roomId}");
KfClient.JoinRoom(roomId);
}
private void OnPusherWsReconnected(object sender, ReconnectionInfo reconnectionInfo)
{
_logger.Error($"Pusher reconnected due to {reconnectionInfo.Type}");
foreach (var channel in _config.PusherChannels)
var channels = Helpers.GetValue(BuiltIn.Keys.PusherChannels).Result.Value ?? "";
foreach (var channel in channels.Split(','))
{
_logger.Info($"Rejoining {channel}");
_kickClient.SendPusherSubscribe(channel);