mirror of
https://github.com/barelyprofessional/KfChatDotNet.git
synced 2026-05-03 04:52:04 -04:00
- Methods are now suffixed async - Extension methods moved to the actual class and class renamed from SettingValue to Setting - "Helpers" renamed to "SettingsProvider" - Removed the ghetto CSV list method. Only setting using it was Pusher Channels which was orphaned by the new Kick channel feature. The call to ToList in the Chips.gg integration was incorrect and just proves lists should be consistently based around JSON objects instead of randomly string splitting
127 lines
5.8 KiB
C#
127 lines
5.8 KiB
C#
using System.Text.RegularExpressions;
|
|
using Humanizer;
|
|
using Humanizer.Localisation;
|
|
using KfChatDotNetBot.Models;
|
|
using KfChatDotNetBot.Models.DbModels;
|
|
using KfChatDotNetBot.Settings;
|
|
using KfChatDotNetWsClient.Models.Events;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace KfChatDotNetBot.Commands;
|
|
|
|
public class JuiceCommand : ICommand
|
|
{
|
|
public List<Regex> Patterns => [new Regex("^juiceme")];
|
|
public string HelpText => "Get juice!";
|
|
public bool HideFromHelp => false;
|
|
public UserRight RequiredRight => UserRight.Loser;
|
|
public TimeSpan Timeout => TimeSpan.FromSeconds(60);
|
|
public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx)
|
|
{
|
|
await using var db = new ApplicationDbContext();
|
|
// Have to attach the entity because it is coming from another DB context
|
|
// https://stackoverflow.com/questions/52718652/ef-core-sqlite-sqlite-error-19-unique-constraint-failed
|
|
db.Users.Attach(user);
|
|
var juicerSettings = await SettingsProvider.GetMultipleValuesAsync([
|
|
BuiltIn.Keys.JuiceAmount, BuiltIn.Keys.JuiceCooldown, BuiltIn.Keys.JuiceLoserDivision,
|
|
BuiltIn.Keys.GambaSeshDetectEnabled, BuiltIn.Keys.JuiceAllowedWhileStreaming,
|
|
BuiltIn.Keys.TwitchBossmanJackUsername, BuiltIn.Keys.JuiceAutoDeleteMsgDelay
|
|
]);
|
|
var cooldown = juicerSettings[BuiltIn.Keys.JuiceCooldown].ToType<int>();
|
|
var amount = juicerSettings[BuiltIn.Keys.JuiceAmount].ToType<int>();
|
|
if (user.UserRight == UserRight.Loser) amount /= juicerSettings[BuiltIn.Keys.JuiceLoserDivision].ToType<int>();
|
|
var lastJuicer = (await db.Juicers.Where(j => j.User == user).ToListAsync(ctx)).OrderByDescending(j => j.JuicedAt).Take(1).ToList();
|
|
if (!botInstance.GambaSeshPresent && juicerSettings[BuiltIn.Keys.GambaSeshDetectEnabled].ToBoolean())
|
|
{
|
|
await botInstance.SendChatMessageAsync("Looks like GambaSesh isn't here. If he is, get him to say something then try again.", true);
|
|
return;
|
|
}
|
|
|
|
if (!juicerSettings[BuiltIn.Keys.JuiceAllowedWhileStreaming].ToBoolean() && botInstance.BotServices.IsBmjLive)
|
|
{
|
|
await botInstance.SendChatMessageAsync(
|
|
$"No juicers permitted while {juicerSettings[BuiltIn.Keys.TwitchBossmanJackUsername].Value} is live!", true);
|
|
return;
|
|
}
|
|
|
|
if (lastJuicer.Count == 0)
|
|
{
|
|
var sentMsg = await botInstance.SendChatMessageAsync($"!juice {message.Author.Id} {amount}", true);
|
|
await db.Juicers.AddAsync(new JuicerDbModel
|
|
{ Amount = amount, User = user, JuicedAt = DateTimeOffset.UtcNow }, ctx);
|
|
await db.SaveChangesAsync(ctx);
|
|
if (juicerSettings[BuiltIn.Keys.JuiceAutoDeleteMsgDelay].Value == null) return;
|
|
var delay = juicerSettings[BuiltIn.Keys.JuiceAutoDeleteMsgDelay].ToType<int>();
|
|
if (delay <= 0) return;
|
|
while (sentMsg.ChatMessageId == null)
|
|
{
|
|
if (sentMsg.Status is SentMessageTrackerStatus.Lost or SentMessageTrackerStatus.NotSending) return;
|
|
await Task.Delay(500, ctx);
|
|
}
|
|
|
|
await Task.Delay(delay, ctx);
|
|
await botInstance.KfClient.DeleteMessageAsync(sentMsg.ChatMessageId.Value);
|
|
return;
|
|
}
|
|
|
|
var secondsRemaining = lastJuicer[0].JuicedAt.AddSeconds(cooldown) - DateTimeOffset.UtcNow;
|
|
if (secondsRemaining.TotalSeconds <= 0)
|
|
{
|
|
await botInstance.SendChatMessageAsync($"!juice {message.Author.Id} {amount}", true);
|
|
await db.Juicers.AddAsync(new JuicerDbModel
|
|
{ Amount = amount, User = user, JuicedAt = DateTimeOffset.UtcNow }, ctx);
|
|
await db.SaveChangesAsync(ctx);
|
|
return;
|
|
}
|
|
|
|
await botInstance.SendChatMessageAsync($"You gotta wait {secondsRemaining.Humanize(precision: 2, minUnit: TimeUnit.Second)} for another juicer", true);
|
|
}
|
|
}
|
|
|
|
public class JuiceStatsCommand : ICommand
|
|
{
|
|
public List<Regex> Patterns => [
|
|
new Regex("^juice stats$"),
|
|
new Regex(@"^juice stats (?<top>\d+)$")
|
|
];
|
|
public string HelpText => "Get juice stats!";
|
|
public bool HideFromHelp => false;
|
|
public UserRight RequiredRight => UserRight.Guest;
|
|
public TimeSpan Timeout => TimeSpan.FromSeconds(10);
|
|
public async Task RunCommand(ChatBot botInstance, MessageModel message, UserDbModel user, GroupCollection arguments, CancellationToken ctx)
|
|
{
|
|
int top;
|
|
if (arguments.TryGetValue("top", out var argument))
|
|
{
|
|
top = Convert.ToInt32(argument.Value);
|
|
if (top > 10)
|
|
{
|
|
await botInstance.SendChatMessageAsync($"'{top}' exceeds the limit on the amount of leeches you can return", true);
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
top = 3;
|
|
}
|
|
|
|
await using var db = new ApplicationDbContext();
|
|
var topLeeches = await db.Juicers.GroupBy(u => u.User).Select(l => new
|
|
{
|
|
User = l.Key.KfUsername,
|
|
Amount = l.Sum(a => a.Amount)
|
|
}).OrderByDescending(x => x.Amount).Take(top).ToListAsync(ctx);
|
|
var sum = await db.Juicers.SumAsync(s => s.Amount, cancellationToken: ctx);
|
|
var count = await db.Juicers.CountAsync(ctx);
|
|
var totalUsers = await db.Juicers.Select(j => j.User).Distinct().CountAsync(ctx);
|
|
var msg = $"Total Juicers: {count:N0}; Total Handed Out: {sum:C0}; Total Users Juiced: {totalUsers:N0}; Average Juicers / User: {count / totalUsers:N0}[br]Top Leeches: ";
|
|
var i = 0;
|
|
foreach (var leech in topLeeches)
|
|
{
|
|
i++;
|
|
msg += $"[b]{i}.[/b] {leech.User} with {leech.Amount:C0} juiced; ";
|
|
}
|
|
|
|
await botInstance.SendChatMessageAsync(msg.TrimEnd().TrimEnd(';'), true);
|
|
}
|
|
} |