Files
nadekobot/src/NadekoBot/Services/Currency/DefaultWallet.cs

104 lines
3.0 KiB
C#

using LinqToDB;
using LinqToDB.EntityFrameworkCore;
using NadekoBot.Services.Database;
using NadekoBot.Services.Database.Models;
namespace NadekoBot.Services.Currency;
public class DefaultWallet : IWallet
{
public ulong UserId { get; }
private readonly NadekoContext _ctx;
public DefaultWallet(ulong userId, NadekoContext ctx)
{
UserId = userId;
_ctx = ctx;
}
public Task<long> GetBalance()
=> _ctx.DiscordUser
.ToLinqToDBTable()
.Where(x => x.UserId == UserId)
.Select(x => x.CurrencyAmount)
.FirstOrDefaultAsync();
public async Task<bool> Take(long amount, Extra extra)
{
if (amount < 0)
throw new ArgumentOutOfRangeException(nameof(amount), "Amount to take must be non negative.");
var changed = await _ctx.DiscordUser
.Where(x => x.UserId == UserId && x.CurrencyAmount >= amount)
.UpdateAsync(x => new()
{
CurrencyAmount = x.CurrencyAmount - amount
});
if (changed == 0)
return false;
// todo type, subtype
// todo from? by?
await _ctx.CreateLinqToDbContext()
.InsertAsync(new CurrencyTransaction()
{
Amount = -amount,
Reason = extra.Note,
UserId = UserId,
});
return true;
}
public async Task Add(long amount, Extra extra)
{
if (amount <= 0)
throw new ArgumentOutOfRangeException(nameof(amount), "Amount must be greater than 0.");
await using (var tran = await _ctx.Database.BeginTransactionAsync())
{
var changed = await _ctx.DiscordUser
.UpdateAsync(x => new()
{
CurrencyAmount = x.CurrencyAmount + amount
});
if (changed == 0)
{
await _ctx.DiscordUser
.ToLinqToDBTable()
.Value(x => x.UserId, UserId)
.Value(x => x.Username, "Unknown")
.Value(x => x.Discriminator, "????")
.Value(x => x.CurrencyAmount, amount)
.InsertAsync();
}
await tran.CommitAsync();
}
var ct = new CurrencyTransaction()
{
Amount = amount,
Reason = extra.Note,
UserId = UserId,
};
await _ctx.CreateLinqToDbContext()
.InsertAsync(ct);
}
public void Dispose()
{
_ctx.SaveChanges();
_ctx.Dispose();
}
public async ValueTask DisposeAsync()
{
await _ctx.SaveChangesAsync();
await _ctx.DisposeAsync();
}
}