mirror of
https://github.com/barelyprofessional/KfChatDotNet.git
synced 2026-04-30 03:22:04 -04:00
* Update KasinoMines.cs * Update SlotsCommand.cs * Update MinesCommand.cs * Update PlinkoCommand.cs * Update PlinkoCommand.cs * Update PlinkoCommand.cs * Update PlanesCommand.cs * Update LimboCommand.cs * Update KenoCommand.cs * Update KasinoUserCommands.cs * Update KasinoRain.cs * Create KasinoShop.cs * Create ShopCommands.cs * Update BotServices.cs * Update MoneyDbModels.cs
158 lines
6.5 KiB
C#
158 lines
6.5 KiB
C#
using System.Text.Json;
|
|
using KfChatDotNetBot.Commands.Kasino;
|
|
using KfChatDotNetBot.Extensions;
|
|
using KfChatDotNetBot.Models.DbModels;
|
|
using KfChatDotNetBot.Settings;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using NLog;
|
|
using StackExchange.Redis;
|
|
|
|
namespace KfChatDotNetBot.Services;
|
|
|
|
public class KasinoRain : IDisposable
|
|
{
|
|
private readonly Logger _logger = LogManager.GetCurrentClassLogger();
|
|
private Task? _rainTimerTask;
|
|
private IDatabase? _redisDb;
|
|
private ChatBot _kfChatBot;
|
|
private CancellationToken _ct;
|
|
private CancellationTokenSource _rainCts = new();
|
|
|
|
public KasinoRain(ChatBot kfChatBot, CancellationToken ct = default)
|
|
{
|
|
_kfChatBot = kfChatBot;
|
|
_ct = ct;
|
|
var connectionString = SettingsProvider.GetValueAsync(BuiltIn.Keys.BotRedisConnectionString).Result;
|
|
if (string.IsNullOrEmpty(connectionString.Value))
|
|
{
|
|
_logger.Error($"Can't initialize the Kasino Rain service as Redis isn't configured in {BuiltIn.Keys.BotRedisConnectionString}");
|
|
return;
|
|
}
|
|
|
|
var redis = ConnectionMultiplexer.Connect(connectionString.Value);
|
|
_redisDb = redis.GetDatabase();
|
|
_rainTimerTask = Task.Run(RainTimerTask, ct);
|
|
}
|
|
|
|
public bool IsInitialized()
|
|
{
|
|
return _redisDb != null;
|
|
}
|
|
|
|
public async Task AddParticipant(int userId)
|
|
{
|
|
var data = await GetRainState();
|
|
if (data == null) throw new InvalidOperationException("Failed to retrieve state or no rain is in progress");
|
|
if (data.Participants.Contains(userId)) return;
|
|
data.Participants.Add(userId);
|
|
await SaveRainState(data);
|
|
}
|
|
|
|
public async Task RemoveRainState()
|
|
{
|
|
if (_redisDb == null) throw new InvalidOperationException("Kasino Rain service isn't initialized");
|
|
await _redisDb.KeyDeleteAsync("Rain.State");
|
|
}
|
|
|
|
public async Task<KasinoRainModel?> GetRainState()
|
|
{
|
|
if (_redisDb == null) throw new InvalidOperationException("Kasino Rain service isn't initialized");
|
|
var json = await _redisDb.StringGetAsync("Rain.State");
|
|
if (string.IsNullOrEmpty(json)) return null;
|
|
var data = JsonSerializer.Deserialize<KasinoRainModel>(json.ToString());
|
|
return data;
|
|
}
|
|
|
|
public async Task SaveRainState(KasinoRainModel rain)
|
|
{
|
|
if (_redisDb == null) throw new InvalidOperationException("Kasino Rain service isn't initialized");
|
|
var json = JsonSerializer.Serialize(rain);
|
|
await _redisDb.StringSetAsync("Rain.State", json, null, When.Always);
|
|
}
|
|
|
|
private async Task RainTimerTask()
|
|
{
|
|
var interval = TimeSpan.FromSeconds(1);
|
|
using var timer = new PeriodicTimer(interval);
|
|
while (await timer.WaitForNextTickAsync(_ct))
|
|
{
|
|
var rain = await GetRainState();
|
|
if (rain == null) continue;
|
|
if (DateTimeOffset.UtcNow < rain.PayoutWhen) continue;
|
|
var creator = await Money.GetGamblerEntityAsync(rain.Creator, ct: _ct);
|
|
if (creator == null)
|
|
{
|
|
_logger.Error($"Somehow this rain was created by a non-existent (or banned) gambler with user ID {rain.Creator}? Wiping this fucked up state");
|
|
await RemoveRainState();
|
|
continue;
|
|
}
|
|
|
|
if (rain.Participants.Count == 0)
|
|
{
|
|
await _kfChatBot.SendChatMessageAsync(
|
|
$"Nobody participated in {creator.User.FormatUsername()}'s rain!",
|
|
true, autoDeleteAfter: TimeSpan.FromSeconds(30));
|
|
await RemoveRainState();
|
|
continue;
|
|
}
|
|
|
|
if (rain.RainAmount > creator.Balance)
|
|
{
|
|
await _kfChatBot.SendChatMessageAsync(
|
|
$"{creator.User.FormatUsername()} lost it all before he could bless everyone! The giveaway is canceled! :lossmanjack:",
|
|
true, autoDeleteAfter: TimeSpan.FromSeconds(30));
|
|
await RemoveRainState();
|
|
continue;
|
|
}
|
|
|
|
List<string> participantNames = [];
|
|
var payout = rain.RainAmount / rain.Participants.Count;
|
|
decimal failedPayoutAmount = 0;
|
|
foreach (var participant in rain.Participants)
|
|
{
|
|
var gambler = await Money.GetGamblerEntityAsync(participant, ct: _ct);
|
|
if (gambler == null)
|
|
{
|
|
_logger.Error($"Somehow this participant ({participant}) does not have a gambler entity or has been banned");
|
|
failedPayoutAmount += payout;
|
|
continue;
|
|
}
|
|
participantNames.Add(gambler.User.FormatUsername());
|
|
await Money.ModifyBalanceAsync(gambler.Id, payout, TransactionSourceEventType.Rain,
|
|
"Payout from rain event", creator.Id, _ct);
|
|
//KasinoShop stuff -------------------------------------------------------------------------
|
|
if (_kfChatBot.BotServices.KasinoShop != null)
|
|
{
|
|
await GlobalShopFunctions.CheckProfile(_kfChatBot, gambler.User, gambler);
|
|
await using var db = new ApplicationDbContext();
|
|
var creatorGambler = await db.Gamblers.FirstOrDefaultAsync(x => x.Id == creator.Id, _ct);
|
|
await _kfChatBot.BotServices.KasinoShop.ProcessJuicerOrRainTracking(creatorGambler!, gambler,
|
|
payout);
|
|
}
|
|
//-----------------------------------------------------------------------------------------
|
|
}
|
|
|
|
await Money.ModifyBalanceAsync(creator.Id, -rain.RainAmount + failedPayoutAmount, TransactionSourceEventType.Rain,
|
|
$"Rained on {participantNames.Count} people", ct: _ct);
|
|
await _kfChatBot.SendChatMessageAsync(
|
|
$"{creator.User.FormatUsername()} made it rain {await payout.FormatKasinoCurrencyAsync()} on {string.Join(' ', participantNames)}",
|
|
true, autoDeleteAfter: TimeSpan.FromSeconds(30));
|
|
await RemoveRainState();
|
|
}
|
|
}
|
|
public void Dispose()
|
|
{
|
|
_rainTimerTask?.Dispose();
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
}
|
|
|
|
public class KasinoRainModel
|
|
{
|
|
public required List<int> Participants { get; set; } = [];
|
|
public required int Creator { get; set; }
|
|
public required DateTimeOffset Started { get; set; }
|
|
public required decimal RainAmount { get; set; }
|
|
public required DateTimeOffset PayoutWhen { get; set; }
|
|
}
|