using LinqToDB; using LinqToDB.EntityFrameworkCore; using NadekoBot.Db.Models; using Nadeko.Bot.Db.Models; namespace NadekoBot.Services.Currency; public class DefaultWallet : IWallet { private readonly DbService _db; public ulong UserId { get; } public DefaultWallet(ulong userId, DbService db) { UserId = userId; _db = db; } public async Task GetBalance() { await using var ctx = _db.GetDbContext(); var userId = UserId; return await ctx .GetTable() .Where(x => x.UserId == userId) .Select(x => x.CurrencyAmount) .FirstOrDefaultAsync(); } public async Task Take(long amount, TxData? txData) { if (amount < 0) throw new ArgumentOutOfRangeException(nameof(amount), "Amount to take must be non negative."); await using var ctx = _db.GetDbContext(); var userId = UserId; var changed = await ctx .GetTable() .Where(x => x.UserId == userId && x.CurrencyAmount >= amount) .UpdateAsync(x => new() { CurrencyAmount = x.CurrencyAmount - amount }); if (changed == 0) return false; if (txData is not null) { await ctx .GetTable() .InsertAsync(() => new() { Amount = -amount, Note = txData.Note, UserId = userId, Type = txData.Type, Extra = txData.Extra, OtherId = txData.OtherId, DateAdded = DateTime.UtcNow }); } return true; } public async Task Add(long amount, TxData? txData) { if (amount <= 0) throw new ArgumentOutOfRangeException(nameof(amount), "Amount must be greater than 0."); await using var ctx = _db.GetDbContext(); var userId = UserId; await using (var tran = await ctx.Database.BeginTransactionAsync()) { var changed = await ctx .GetTable() .Where(x => x.UserId == userId) .UpdateAsync(x => new() { CurrencyAmount = x.CurrencyAmount + amount }); if (changed == 0) { await ctx .GetTable() .Value(x => x.UserId, userId) .Value(x => x.Username, "Unknown") .Value(x => x.Discriminator, "????") .Value(x => x.CurrencyAmount, amount) .InsertAsync(); } await tran.CommitAsync(); } if (txData is not null) { await ctx.GetTable() .InsertAsync(() => new() { Amount = amount, UserId = userId, Note = txData.Note, Type = txData.Type, Extra = txData.Extra, OtherId = txData.OtherId, DateAdded = DateTime.UtcNow }); } } }