#nullable disable using NadekoBot.Services.Database; using NadekoBot.Services.Database.Models; using NadekoBot.Db; using NadekoBot.Modules.Gambling.Services; namespace NadekoBot.Services; public class CurrencyService : ICurrencyService, INService { private readonly DbService _db; private readonly GamblingConfigService _gss; private readonly IEmbedBuilderService _eb; private readonly IUser _bot; public CurrencyService(DbService db, DiscordSocketClient c, GamblingConfigService gss, IEmbedBuilderService eb) { _db = db; _gss = gss; _eb = eb; _bot = c.CurrentUser; } private CurrencyTransaction GetCurrencyTransaction(ulong userId, string reason, long amount) => new() { Amount = amount, UserId = userId, Reason = reason ?? "-", }; private bool InternalChange(ulong userId, string userName, string discrim, string avatar, string reason, long amount, bool gamble, NadekoContext uow) { var result = uow.TryUpdateCurrencyState(userId, userName, discrim, avatar, amount); if (result) { var t = GetCurrencyTransaction(userId, reason, amount); uow.CurrencyTransactions.Add(t); if (gamble) { var t2 = GetCurrencyTransaction(_bot.Id, reason, -amount); uow.CurrencyTransactions.Add(t2); uow.TryUpdateCurrencyState(_bot.Id, _bot.Username, _bot.Discriminator, _bot.AvatarId, -amount, true); } } return result; } private async Task InternalAddAsync(ulong userId, string userName, string discrim, string avatar, string reason, long amount, bool gamble) { if (amount < 0) { throw new ArgumentException("You can't add negative amounts. Use RemoveAsync method for that.", nameof(amount)); } await using var uow = _db.GetDbContext(); InternalChange(userId, userName, discrim, avatar, reason, amount, gamble, uow); await uow.SaveChangesAsync(); } public Task AddAsync(ulong userId, string reason, long amount, bool gamble = false) => InternalAddAsync(userId, null, null, null, reason, amount, gamble); public async Task AddAsync(IUser user, string reason, long amount, bool sendMessage = false, bool gamble = false) { await InternalAddAsync(user.Id, user.Username, user.Discriminator, user.AvatarId, reason, amount, gamble); if (sendMessage) { try { var sign = _gss.Data.Currency.Sign; await user .EmbedAsync(_eb.Create() .WithOkColor() .WithTitle($"Received Currency") .AddField("Amount", amount + sign) .AddField("Reason", reason)); } catch { // ignored } } } public async Task AddBulkAsync(IEnumerable userIds, IEnumerable reasons, IEnumerable amounts, bool gamble = false) { var idArray = userIds as ulong[] ?? userIds.ToArray(); var reasonArray = reasons as string[] ?? reasons.ToArray(); var amountArray = amounts as long[] ?? amounts.ToArray(); if (idArray.Length != reasonArray.Length || reasonArray.Length != amountArray.Length) throw new ArgumentException("Cannot perform bulk operation. Arrays are not of equal length."); var userIdHashSet = new HashSet(idArray.Length); await using var uow = _db.GetDbContext(); for (var i = 0; i < idArray.Length; i++) { // i have to prevent same user changing more than once as it will cause db error if (userIdHashSet.Add(idArray[i])) InternalChange(idArray[i], null, null, null, reasonArray[i], amountArray[i], gamble, uow); } await uow.SaveChangesAsync(); } public async Task RemoveBulkAsync(IEnumerable userIds, IEnumerable reasons, IEnumerable amounts, bool gamble = false) { var idArray = userIds as ulong[] ?? userIds.ToArray(); var reasonArray = reasons as string[] ?? reasons.ToArray(); var amountArray = amounts as long[] ?? amounts.ToArray(); if (idArray.Length != reasonArray.Length || reasonArray.Length != amountArray.Length) throw new ArgumentException("Cannot perform bulk operation. Arrays are not of equal length."); var userIdHashSet = new HashSet(idArray.Length); await using var uow = _db.GetDbContext(); for (var i = 0; i < idArray.Length; i++) { // i have to prevent same user changing more than once as it will cause db error if (userIdHashSet.Add(idArray[i])) InternalChange(idArray[i], null, null, null, reasonArray[i], -amountArray[i], gamble, uow); } await uow.SaveChangesAsync(); } private async Task InternalRemoveAsync(ulong userId, string userName, string userDiscrim, string avatar, string reason, long amount, bool gamble = false) { if (amount < 0) { throw new ArgumentException("You can't remove negative amounts. Use AddAsync method for that.", nameof(amount)); } bool result; await using var uow = _db.GetDbContext(); result = InternalChange(userId, userName, userDiscrim, avatar, reason, -amount, gamble, uow); await uow.SaveChangesAsync(); return result; } public Task RemoveAsync(ulong userId, string reason, long amount, bool gamble = false) => InternalRemoveAsync(userId, null, null, null, reason, amount, gamble); public Task RemoveAsync(IUser user, string reason, long amount, bool sendMessage = false, bool gamble = false) => InternalRemoveAsync(user.Id, user.Username, user.Discriminator, user.AvatarId, reason, amount, gamble); }