diff --git a/KfChatDotNetBot/Commands/KasinoUserCommands.cs b/KfChatDotNetBot/Commands/KasinoUserCommands.cs index db22272..b3ed15e 100644 --- a/KfChatDotNetBot/Commands/KasinoUserCommands.cs +++ b/KfChatDotNetBot/Commands/KasinoUserCommands.cs @@ -4,6 +4,7 @@ using Humanizer.Localisation; using KfChatDotNetBot.Extensions; using KfChatDotNetBot.Models.DbModels; using KfChatDotNetBot.Services; +using KfChatDotNetBot.Settings; using KfChatDotNetWsClient.Models.Events; using Microsoft.EntityFrameworkCore; @@ -104,4 +105,52 @@ public class SendJuiceCommand : ICommand gambler, ctx); await botInstance.SendChatMessageAsync($"@{user.KfUsername}, {await amount.FormatKasinoCurrencyAsync()} has been sent to {targetUser.KfUsername}", true); } +} + +[KasinoCommand] +public class RakebackCommand : ICommand +{ + public List Patterns => [ + new Regex(@"^rakeback", RegexOptions.IgnoreCase), + new Regex(@"^rapeback", RegexOptions.IgnoreCase) + ]; + public string? HelpText => "Collect your rakeback"; + public UserRight RequiredRight => UserRight.Loser; + public TimeSpan Timeout => TimeSpan.FromSeconds(10); + + public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, + CancellationToken ctx) + { + await using var db = new ApplicationDbContext(); + var gambler = await user.GetGamblerEntity(ct: ctx); + var settings = await SettingsProvider.GetMultipleValuesAsync([ + BuiltIn.Keys.MoneyRakebackPercentage, BuiltIn.Keys.MoneyRakebackMinimumAmount + ]); + var mostRecentRakeback = await db.Transactions.LastOrDefaultAsync(tx => + tx.EventSource == TransactionSourceEventType.Rakeback && tx.Gambler == gambler, cancellationToken: ctx); + long offset = 0; + if (mostRecentRakeback != null) + { + offset = mostRecentRakeback.TimeUnixEpochSeconds; + } + + var wagers = db.Wagers.Where(w => w.Gambler == gambler && w.TimeUnixEpochSeconds > offset); + if (!await wagers.AnyAsync(ctx)) + { + await botInstance.SendChatMessageAsync( + $"@{user.KfUsername}, you haven't wagered since your last rakeback.", true); + return; + } + + var wagered = await wagers.SumAsync(w => w.WagerAmount, ctx); + var rakeback = wagered * (decimal)(settings[BuiltIn.Keys.MoneyRakebackPercentage].ToType() / 100.0); + var minimumRakeback = settings[BuiltIn.Keys.MoneyRakebackMinimumAmount].ToType(); + if (rakeback < minimumRakeback) + { + await botInstance.SendChatMessageAsync($"@{user.KfUsername}, your rakeback payout of {await rakeback.FormatKasinoCurrencyAsync()} is below the minimum amount of {await minimumRakeback.FormatKasinoCurrencyAsync()}", true); + return; + } + await gambler!.ModifyBalance(rakeback, TransactionSourceEventType.Rakeback, "Rakeback claimed by gambler", + ct: ctx); + } } \ No newline at end of file diff --git a/KfChatDotNetBot/Settings/BuiltIn.cs b/KfChatDotNetBot/Settings/BuiltIn.cs index 0cefcb3..dc1697f 100644 --- a/KfChatDotNetBot/Settings/BuiltIn.cs +++ b/KfChatDotNetBot/Settings/BuiltIn.cs @@ -993,6 +993,21 @@ public static class BuiltIn ValueType = SettingValueType.Boolean, Regex = BooleanRegex }, + new BuiltInSettingsModel + { + Key = Keys.MoneyRakebackPercentage, + Description = "Percentage of total wagered amount that should be returned for rakeback.", + Default = "2.5", + ValueType = SettingValueType.Text + }, + new BuiltInSettingsModel + { + Key = Keys.MoneyRakebackMinimumAmount, + Description = "Minimum rakeback to pay out. Anything below this will tell the user to go away.", + Default = "10", + ValueType = SettingValueType.Text, + Regex = WholeNumberRegex + }, ]; public static class Keys @@ -1105,5 +1120,7 @@ public static class BuiltIn public static string TwitchGraphQlPersistedCurrentlyLive = "TwitchGraphQl.PersistedCurrentlyLive"; public static string OwncastCheckInterval = "Owncast.CheckInterval"; public static string OwncastPersistedCurrentlyLive = "Owncast.PersistedCurrentlyLive"; + public static string MoneyRakebackPercentage = "Money.Rakeback.Percentage"; + public static string MoneyRakebackMinimumAmount = "Money.Rakeback.MinimumAmount"; } } \ No newline at end of file