* Removed OpenRouter from BotServices and converted it into a static class

* Moved hostess from MemeCommands.cs to KasinoUserCommands.cs
* Added missing KasinoCommand attribute. Also added WagerCommand so it'll do the exclusion check before running
This commit is contained in:
barelyprofessional
2025-12-19 01:05:39 -06:00
parent a88045c63d
commit 8503636a29
4 changed files with 100 additions and 115 deletions

View File

@@ -8,6 +8,8 @@ using KfChatDotNetBot.Settings;
using KfChatDotNetWsClient.Models.Events;
using Microsoft.EntityFrameworkCore;
using NLog;
using RandN;
using RandN.Compat;
namespace KfChatDotNetBot.Commands.Kasino;
@@ -299,4 +301,84 @@ public class PocketWatchCommand : ICommand
await botInstance.SendChatMessageAsync($"{user.FormatUsername()}, {targetUser.KfUsername} has {await targetGambler.Balance.FormatKasinoCurrencyAsync()}", true);
}
}
[KasinoCommand]
[WagerCommand]
public class HostessCommand : ICommand
{
public List<Regex> Patterns => [
new Regex("^hostess", RegexOptions.IgnoreCase),
];
public string? HelpText => "Ask the hostess for help";
public UserRight RequiredRight => UserRight.Loser;
public TimeSpan Timeout => TimeSpan.FromSeconds(60);
public RateLimitOptionsModel? RateLimitOptions => new()
{
MaxInvocations = 1,
Window = TimeSpan.FromSeconds(30)
};
private static readonly string[] StaticResponses = [
"For questions regarding your current contract please contact us at contact@bossmanjack.com",
"Unspecified error",
"Have you considered giving us a review on TrustPilot?",
"We are sincerely sorry to hear that you are not having a positive experience on our platform. Please be assured that we take matters of fairness and transparency very seriously.",
"At the Kasino, we prioritize strict adherence to regulatory requirements to maintain the security and integrity of our platform.",
"There are currently no hosts online to serve your request.",
"We would like to assist you further and understand better the issue. Due to that, we have requested further information.",
"When it comes to RTP, it is important to understand that this number is calculated based on at least 1 million bets. So, over a session of a few thousand bets, anything can happen, which is exactly what makes gambling exciting.",
"We understand that gambling involves risks, and while some players may experience periods of winning and losing, we strive to provide resources and tools to support responsible gambling practices.",
"Thank you for taking the time to leave a 5-star review! We're thrilled to have provided you with a great experience.",
"Please rest assured that our platform operates with certified random number generators to ensure fairness and transparency in all gaming outcomes. We do not manipulate the odds or monitor games to favor any particular outcome.",
"We would like to inform you that we have responded to your recent post.",
"All of our Kasino originals are 100% probably fair and each and every single bet placed at our any games are verifiable.",
"We want to emphasize that our games are developed with the highest standards of integrity and fairness.",
"Stop harrassing me",
];
private static readonly string[] LlmPrompts = [
"You are a hostess for a virtual casino. You've just gotten a message from a customer with cripling gambling addiction issues. Respond in a smug and condescending manner.",
"You are an overworked fastfood worker at a drive-thru. A confused gambling addict just arrived. Respond with at most two sentences."
];
public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx)
{
var random = RandomShim.Create(StandardRng.Create());
if (random.NextDouble() < 0.06)
{
// ignore 6% of requests like the old hostess command
return;
}
var orKeySet = await SettingsProvider.GetValueAsync(BuiltIn.Keys.OpenrouterApiKey);
if (orKeySet.Value == null || random.NextDouble() < 0.3)
{
var response = StaticResponses[random.Next(0, StaticResponses.Length)];
await botInstance.SendChatMessageAsync(response, true);
return;
}
var msg = message.MessageRaw.Replace("hostess", "").Trim();
if (string.IsNullOrWhiteSpace(msg))
{
msg = "I need help with my gambling addiction.";
}
var llmResponse = await OpenRouter.GetResponseAsync(
LlmPrompts[random.Next(0, LlmPrompts.Length)],
msg,
model: "deepseek/deepseek-v3.2",
Temperature: 1.0f + (float)((random.NextDouble() - 0.3) * 0.5)
);
if (llmResponse == null)
{
var fallback = StaticResponses[random.Next(0, StaticResponses.Length)];
await botInstance.SendChatMessageAsync(fallback, true);
return;
}
await botInstance.SendChatMessageAsync(llmResponse, true, ChatBot.LengthLimitBehavior.TruncateExactly);
}
}

View File

@@ -321,92 +321,4 @@ public class JuiceSportsCommand : ICommand
"[img]https://i.ddos.lgbt/u/KAwWMW.webp[/img][br]" +
"[img]https://i.ddos.lgbt/u/uCuSOw.gif[/img][br]", true);
}
}
public class HostessCommand : ICommand
{
public List<Regex> Patterns => [
new Regex("^hostess", RegexOptions.IgnoreCase),
];
public string? HelpText => "Ask the hostess for help";
public UserRight RequiredRight => UserRight.Loser;
public TimeSpan Timeout => TimeSpan.FromSeconds(10);
public RateLimitOptionsModel? RateLimitOptions => new RateLimitOptionsModel
{
MaxInvocations = 1,
Window = TimeSpan.FromSeconds(30)
};
private static string[] StaticResponses = [
"For questions regarding your current contract please contact us at contact@bossmanjack.com",
"Unspecified error",
"Have you considered giving us a review on TrustPilot?",
"We are sincerely sorry to hear that you are not having a positive experience on our platform. Please be assured that we take matters of fairness and transparency very seriously.",
"At the Kasino, we prioritize strict adherence to regulatory requirements to maintain the security and integrity of our platform.",
"There are currently no hosts online to serve your request.",
"We would like to assist you further and understand better the issue. Due to that, we have requested further information.",
"When it comes to RTP, it is important to understand that this number is calculated based on at least 1 million bets. So, over a session of a few thousand bets, anything can happen, which is exactly what makes gambling exciting.",
"We understand that gambling involves risks, and while some players may experience periods of winning and losing, we strive to provide resources and tools to support responsible gambling practices.",
"Thank you for taking the time to leave a 5-star review! We're thrilled to have provided you with a great experience.",
"Please rest assured that our platform operates with certified random number generators to ensure fairness and transparency in all gaming outcomes. We do not manipulate the odds or monitor games to favor any particular outcome.",
"We would like to inform you that we have responded to your recent post.",
"All of our Kasino originals are 100% probably fair and each and every single bet placed at our any games are verifiable.",
"We want to emphasize that our games are developed with the highest standards of integrity and fairness.",
"Stop harrassing me",
];
private static string[] LLMPrompts = [
"You are a hostess for a virtual casino. You've just gotten a message from a customer with cripling gambling addiction issues. Respond in a smug and condescending manner.",
"You are an overworked fastfood worker at a drive-thru. A confused gambling addict just arrived. Respond with at most two sentences."
];
public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx)
{
await using var db = new ApplicationDbContext();
var activeExclusion = await Money.GetActiveExclusionAsync(user.Id, ctx);
if (db.Exclusions.Any(e => e.Id == user.Id))
{
await botInstance.SendChatMessageAsync("You are currently excluded from using hostess service.", true);
return;
}
var random = new Random();
if (random.NextDouble() < 0.06)
{
// ignore 6% of requests like the old hostess command
return;
}
if (botInstance.BotServices.OpenRouter == null || random.NextDouble() < 0.3)
{
var response = StaticResponses[random.Next(0, StaticResponses.Length)];
await botInstance.SendChatMessageAsync(response, true);
}
else
{
var msg = message.MessageRaw.Replace("hostess", "").Trim();
if (string.IsNullOrWhiteSpace(msg))
{
msg = "I need help with my gambling addiction.";
}
var llmResponse = await botInstance.BotServices.OpenRouter.GetResponseAsync(
LLMPrompts[random.Next(0, LLMPrompts.Length)],
msg,
model: "deepseek/deepseek-v3.2",
Temperature: 1.0f + (float)((random.NextDouble() - 0.3) * 0.5)
);
if (llmResponse == null)
{
var fallback = StaticResponses[random.Next(0, StaticResponses.Length)];
await botInstance.SendChatMessageAsync(fallback, true);
}
else
{
await botInstance.SendChatMessageAsync(llmResponse, true, ChatBot.LengthLimitBehavior.TruncateExactly);
}
}
}
}

View File

@@ -40,7 +40,6 @@ public class BotServices
private Owncast? _owncastStatusCheck;
private ShuffleDotUs? _shuffleDotUs;
private YouTubePubSub? _youTubePubSub;
public OpenRouter? OpenRouter;
private Task? _websocketWatchdog;
private Task? _howlggGetUserTimer;
@@ -91,8 +90,7 @@ public class BotServices
BuildDLiveStatusCheck(),
BuildPeerTubeLiveStatusCheck(),
BuildOwncastLiveStatusCheck(),
BuildShuffleDotUs(),
BuildOpenRouter()
BuildShuffleDotUs()
];
try
{
@@ -108,13 +106,6 @@ public class BotServices
_websocketWatchdog = WebsocketWatchdog();
_howlggGetUserTimer = HowlggGetUserTimer();
}
private async Task BuildOpenRouter()
{
_logger.Debug("Building OpenRouter client");
var proxySetting = await SettingsProvider.GetValueAsync(BuiltIn.Keys.Proxy);
OpenRouter = new OpenRouter(proxySetting.Value);
}
private async Task BuildShuffle()
{

View File

@@ -1,14 +1,15 @@
using System.Net;
using NLog;
using System.Text.Json.Serialization;
using System.Text.Json;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using KfChatDotNetBot.Settings;
using NLog;
public class OpenRouter(string? proxy = null)
namespace KfChatDotNetBot.Services;
public static class OpenRouter
{
class OrResponse
{
[JsonPropertyName("id")] public string Id { get; set; } = string.Empty;
@@ -45,19 +46,18 @@ public class OpenRouter(string? proxy = null)
}
private Logger _logger = LogManager.GetCurrentClassLogger();
private Uri _orEndpoint = new Uri("https://openrouter.ai/api/v1/chat/completions");
private string? _proxy = proxy;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public async Task<string?> GetResponseAsync(string prompt, string question, string model = "openrouter-gpt4-1106", float Temperature = 0.7f)
public static async Task<string?> GetResponseAsync(string prompt, string question, string model = "openrouter-gpt4-1106", float Temperature = 0.7f)
{
_logger.Info("Sending request to OpenRouter");
Logger.Info("Sending request to OpenRouter");
var proxy = await SettingsProvider.GetValueAsync(BuiltIn.Keys.Proxy);
var handler = new HttpClientHandler { AutomaticDecompression = DecompressionMethods.All };
if (_proxy != null)
if (proxy.Value != null)
{
handler.UseProxy = true;
handler.Proxy = new WebProxy(_proxy);
_logger.Debug($"Configured to use proxy {_proxy}");
handler.Proxy = new WebProxy(proxy.Value);
Logger.Debug($"Configured to use proxy {proxy.Value}");
}
using var client = new HttpClient(handler);
@@ -65,9 +65,9 @@ public class OpenRouter(string? proxy = null)
{
List<(string role, string content)> msg = [("system", prompt), ("user", question)];
var keySetting = await SettingsProvider.GetValueAsync(BuiltIn.Keys.OpenrouterApiKey);
if (keySetting == null || string.IsNullOrWhiteSpace(keySetting.Value))
if (string.IsNullOrEmpty(keySetting.Value))
{
_logger.Error("OpenRouter API key is not set in settings.");
Logger.Error("OpenRouter API key is not set in settings.");
return null;
}
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", keySetting.Value);
@@ -89,7 +89,7 @@ public class OpenRouter(string? proxy = null)
if (responseData == null || responseData.Choices.Count == 0)
{
_logger.Error("No response from OpenRouter.");
Logger.Error("No response from OpenRouter.");
return null;
}
return responseData.Choices[0].Message.Content;
@@ -97,7 +97,7 @@ public class OpenRouter(string? proxy = null)
}
catch (Exception ex)
{
_logger.Error(ex, "Error while communicating with OpenRouter.");
Logger.Error(ex, "Error while communicating with OpenRouter.");
}
return null;