mirror of
				https://gitlab.com/Kwoth/nadekobot.git
				synced 2025-11-03 16:24:27 -05:00 
			
		
		
		
	Fixed bugs when users update their patreon pledge. Updated some packages
This commit is contained in:
		@@ -35,4 +35,14 @@ public class PatronUser
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    // Date Only component
 | 
					    // Date Only component
 | 
				
			||||||
    public DateTime ValidThru { get; set; }
 | 
					    public DateTime ValidThru { get; set; }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public PatronUser Clone()
 | 
				
			||||||
 | 
					        => new PatronUser()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            UniquePlatformUserId = this.UniquePlatformUserId,
 | 
				
			||||||
 | 
					            UserId = this.UserId,
 | 
				
			||||||
 | 
					            AmountCents = this.AmountCents,
 | 
				
			||||||
 | 
					            LastCharge = this.LastCharge,
 | 
				
			||||||
 | 
					            ValidThru = this.ValidThru
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -75,19 +75,4 @@ public sealed class BankService : IBankService, INService
 | 
				
			|||||||
               ?.Balance
 | 
					               ?.Balance
 | 
				
			||||||
               ?? 0;
 | 
					               ?? 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    public async Task<long> BurnAllAsync(ulong userId)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        await using var ctx = _db.GetDbContext();
 | 
					 | 
				
			||||||
        var output = await ctx.GetTable<BankUser>()
 | 
					 | 
				
			||||||
                              .Where(x => x.UserId == userId)
 | 
					 | 
				
			||||||
                              .UpdateWithOutputAsync(old => new()
 | 
					 | 
				
			||||||
                              {
 | 
					 | 
				
			||||||
                                  Balance = 0
 | 
					 | 
				
			||||||
                              });
 | 
					 | 
				
			||||||
        if (output.Length == 0)
 | 
					 | 
				
			||||||
            return 0;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        return output[0].Deleted.Balance;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -5,5 +5,4 @@ public interface IBankService
 | 
				
			|||||||
    Task<bool> DepositAsync(ulong userId, long amount);
 | 
					    Task<bool> DepositAsync(ulong userId, long amount);
 | 
				
			||||||
    Task<bool> WithdrawAsync(ulong userId, long amount);
 | 
					    Task<bool> WithdrawAsync(ulong userId, long amount);
 | 
				
			||||||
    Task<long> GetBalanceAsync(ulong userId);
 | 
					    Task<long> GetBalanceAsync(ulong userId);
 | 
				
			||||||
    Task<long> BurnAllAsync(ulong userId);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -50,67 +50,91 @@ public class CurrencyRewardService : INService, IDisposable
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private async Task OnPatronUpdate(Patron oldPatron, Patron newPatron)
 | 
					    private async Task OnPatronUpdate(Patron oldPatron, Patron newPatron)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (oldPatron.Amount != newPatron.Amount)
 | 
					        // if pledge was increased
 | 
				
			||||||
 | 
					        if (oldPatron.Amount < newPatron.Amount)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var conf = _config.Data;
 | 
					            var conf = _config.Data;
 | 
				
			||||||
 | 
					            var newAmount = (long)(newPatron.Amount * conf.PatreonCurrencyPerCent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var newAmount = (long)(Math.Max(newPatron.Amount, oldPatron.Amount) * conf.PatreonCurrencyPerCent);
 | 
					            RewardedUser old;
 | 
				
			||||||
            UpdateOutput<RewardedUser>[] output;
 | 
					 | 
				
			||||||
            await using (var ctx = _db.GetDbContext())
 | 
					            await using (var ctx = _db.GetDbContext())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                output = await ctx.GetTable<RewardedUser>()
 | 
					                old = await ctx.GetTable<RewardedUser>()
 | 
				
			||||||
                                  .Where(x => x.PlatformUserId == newPatron.UnqiuePlatformUserId)
 | 
					                         .Where(x => x.PlatformUserId == newPatron.UniquePlatformUserId)
 | 
				
			||||||
                                  .UpdateWithOutputAsync(old => new()
 | 
					                         .FirstOrDefaultAsync();
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                if (old is null)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    await OnNewPayment(newPatron);
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                // no action as the amount is the same or lower
 | 
				
			||||||
 | 
					                if (old.AmountRewardedThisMonth >= newAmount)
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                var count = await ctx.GetTable<RewardedUser>()
 | 
				
			||||||
 | 
					                                  .Where(x => x.PlatformUserId == newPatron.UniquePlatformUserId)
 | 
				
			||||||
 | 
					                                  .UpdateAsync(_ => new()
 | 
				
			||||||
                                  {
 | 
					                                  {
 | 
				
			||||||
                                      PlatformUserId = newPatron.UnqiuePlatformUserId,
 | 
					                                      PlatformUserId = newPatron.UniquePlatformUserId,
 | 
				
			||||||
                                      UserId = newPatron.UserId,
 | 
					                                      UserId = newPatron.UserId,
 | 
				
			||||||
                                      // amount before bonuses
 | 
					                                      // amount before bonuses
 | 
				
			||||||
                                      AmountRewardedThisMonth = newAmount,
 | 
					                                      AmountRewardedThisMonth = newAmount,
 | 
				
			||||||
                                      LastReward = newPatron.PaidAt
 | 
					                                      LastReward = newPatron.PaidAt
 | 
				
			||||||
                                  });
 | 
					                                  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // shouldn't ever happen
 | 
				
			||||||
 | 
					                if (count == 0)
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // if the user wasn't previously in the db for some reason,
 | 
					            var oldAmount = old.AmountRewardedThisMonth;
 | 
				
			||||||
            // we will treat him as a new patron
 | 
					 | 
				
			||||||
            if (output.Length == 0)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                await OnNewPayment(newPatron);
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var oldAmount = output[0].Deleted.AmountRewardedThisMonth;
 | 
					            var realNewAmount = GetRealCurrencyReward(
 | 
				
			||||||
 | 
					                (int)(newAmount / conf.PatreonCurrencyPerCent),
 | 
				
			||||||
 | 
					                newAmount,
 | 
				
			||||||
 | 
					                out var percentBonus);
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            var diff = newAmount - oldAmount;
 | 
					            var realOldAmount = GetRealCurrencyReward(
 | 
				
			||||||
 | 
					                (int)(oldAmount / conf.PatreonCurrencyPerCent),
 | 
				
			||||||
 | 
					                oldAmount,
 | 
				
			||||||
 | 
					                out _);
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            var diff = realNewAmount - realOldAmount;
 | 
				
			||||||
            if (diff <= 0)
 | 
					            if (diff <= 0)
 | 
				
			||||||
                return; // no action if new is lower
 | 
					                return; // no action if new is lower
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // if the user pledges 5$ or more, they will get X % more flowers where X is amount in dollars,
 | 
					            // if the user pledges 5$ or more, they will get X % more flowers where X is amount in dollars,
 | 
				
			||||||
            // up to 100%
 | 
					            // up to 100%
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            var realAmount = GetRealCurrencyReward(newPatron.Amount, diff, out var percentBonus);
 | 
					            await _cs.AddAsync(newPatron.UserId, diff, new TxData("patron","update"));
 | 
				
			||||||
            await _cs.AddAsync(newPatron.UserId, realAmount, new TxData("patron","update"));
 | 
					 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            _ = SendMessageToUser(newPatron.UserId,
 | 
					            _ = SendMessageToUser(newPatron.UserId,
 | 
				
			||||||
                $"You've received an additional **{realAmount}**{_config.Data.Currency.Sign} as a currency reward (+{percentBonus}%)!");
 | 
					                $"You've received an additional **{diff}**{_config.Data.Currency.Sign} as a currency reward (+{percentBonus}%)!");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private long GetRealCurrencyReward(int fullPledge, long currentAmount, out int percentBonus)
 | 
					    private long GetRealCurrencyReward(int pledgeCents, long modifiedAmount, out int percentBonus)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // needs at least 5$ to be eligible for a bonus
 | 
					        // needs at least 5$ to be eligible for a bonus
 | 
				
			||||||
        if (fullPledge < 500)
 | 
					        if (pledgeCents < 500)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            percentBonus = 0;
 | 
					            percentBonus = 0;
 | 
				
			||||||
            return currentAmount;
 | 
					            return modifiedAmount;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var dollarValue = fullPledge / 100;
 | 
					        var dollarValue = pledgeCents / 100;
 | 
				
			||||||
        percentBonus = dollarValue switch
 | 
					        percentBonus = dollarValue switch
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            > 100 => 100,
 | 
					            >= 100 => 100,
 | 
				
			||||||
            _ => dollarValue
 | 
					            >= 50 => 50,
 | 
				
			||||||
 | 
					            >= 20 => 20,
 | 
				
			||||||
 | 
					            >= 10 => 10,
 | 
				
			||||||
 | 
					            >= 5 => 5,
 | 
				
			||||||
 | 
					            _ => 0
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        return (long)(currentAmount * (1 + (percentBonus / 100.0f)));
 | 
					        return (long)(modifiedAmount * (1 + (percentBonus / 100.0f)));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // on a new payment, always give the full amount.
 | 
					    // on a new payment, always give the full amount.
 | 
				
			||||||
@@ -121,7 +145,7 @@ public class CurrencyRewardService : INService, IDisposable
 | 
				
			|||||||
        await ctx.GetTable<RewardedUser>()
 | 
					        await ctx.GetTable<RewardedUser>()
 | 
				
			||||||
                 .InsertOrUpdateAsync(() => new()
 | 
					                 .InsertOrUpdateAsync(() => new()
 | 
				
			||||||
                     {
 | 
					                     {
 | 
				
			||||||
                         PlatformUserId = patron.UnqiuePlatformUserId,
 | 
					                         PlatformUserId = patron.UniquePlatformUserId,
 | 
				
			||||||
                         UserId = patron.UserId,
 | 
					                         UserId = patron.UserId,
 | 
				
			||||||
                         AmountRewardedThisMonth = amount,
 | 
					                         AmountRewardedThisMonth = amount,
 | 
				
			||||||
                         LastReward = patron.PaidAt,
 | 
					                         LastReward = patron.PaidAt,
 | 
				
			||||||
@@ -134,7 +158,7 @@ public class CurrencyRewardService : INService, IDisposable
 | 
				
			|||||||
                     },
 | 
					                     },
 | 
				
			||||||
                     () => new()
 | 
					                     () => new()
 | 
				
			||||||
                     {
 | 
					                     {
 | 
				
			||||||
                         PlatformUserId = patron.UnqiuePlatformUserId
 | 
					                         PlatformUserId = patron.UniquePlatformUserId
 | 
				
			||||||
                     });
 | 
					                     });
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        var realAmount = GetRealCurrencyReward(patron.Amount, amount, out var percentBonus);
 | 
					        var realAmount = GetRealCurrencyReward(patron.Amount, amount, out var percentBonus);
 | 
				
			||||||
@@ -167,24 +191,9 @@ public class CurrencyRewardService : INService, IDisposable
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        await using var ctx = _db.GetDbContext();
 | 
					        await using var ctx = _db.GetDbContext();
 | 
				
			||||||
        _ = await ctx.GetTable<RewardedUser>()
 | 
					        _ = await ctx.GetTable<RewardedUser>()
 | 
				
			||||||
                     .UpdateWithOutputAsync(old => new()
 | 
					                     .UpdateAsync(old => new()
 | 
				
			||||||
                     {
 | 
					                     {
 | 
				
			||||||
                         AmountRewardedThisMonth = old.AmountRewardedThisMonth * 2
 | 
					                         AmountRewardedThisMonth = old.AmountRewardedThisMonth * 2
 | 
				
			||||||
                     });
 | 
					                     });
 | 
				
			||||||
 | 
					 | 
				
			||||||
        // var toTake = old.Length == 0
 | 
					 | 
				
			||||||
        //     ? patron.Amount
 | 
					 | 
				
			||||||
        //     : old[0].Inserted.AmountRewardedThisMonth;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // if (toTake > 0)
 | 
					 | 
				
			||||||
        // {
 | 
					 | 
				
			||||||
        //     Log.Warning("Wiping the wallet and bank of the user {UserId} due to a refund/fraud...",
 | 
					 | 
				
			||||||
        //         patron.UserId);
 | 
					 | 
				
			||||||
        //     await _cs.RemoveAsync(patron.UserId, patron.Amount, new("patreon", "refund"));
 | 
					 | 
				
			||||||
        //     await _bs.BurnAllAsync(patron.UserId);
 | 
					 | 
				
			||||||
        //     Log.Warning("Burned {Amount} currency from the bank of the user {UserId} due to a refund/fraud.",
 | 
					 | 
				
			||||||
        //         patron.Amount,
 | 
					 | 
				
			||||||
        //         patron.UserId);
 | 
					 | 
				
			||||||
        // }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -5,10 +5,10 @@ public readonly struct Patron
 | 
				
			|||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Unique id assigned to this patron by the payment platform
 | 
					    /// Unique id assigned to this patron by the payment platform
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    public string UnqiuePlatformUserId { get; init; }
 | 
					    public string UniquePlatformUserId { get; init; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Discord UserId to which this <see cref="UnqiuePlatformUserId"/> is connected to
 | 
					    /// Discord UserId to which this <see cref="UniquePlatformUserId"/> is connected to
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    public ulong UserId { get; init; }
 | 
					    public ulong UserId { get; init; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -173,7 +173,7 @@ public sealed class PatronageService
 | 
				
			|||||||
        
 | 
					        
 | 
				
			||||||
            var lastChargeUtc = subscriber.LastCharge.Value.ToUniversalTime();
 | 
					            var lastChargeUtc = subscriber.LastCharge.Value.ToUniversalTime();
 | 
				
			||||||
            var dateInOneMonth = lastChargeUtc.Date.AddMonths(1);
 | 
					            var dateInOneMonth = lastChargeUtc.Date.AddMonths(1);
 | 
				
			||||||
            await using var tran = await ctx.Database.BeginTransactionAsync();
 | 
					            // await using var tran = await ctx.Database.BeginTransactionAsync();
 | 
				
			||||||
            try
 | 
					            try
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var dbPatron = await ctx.GetTable<PatronUser>()
 | 
					                var dbPatron = await ctx.GetTable<PatronUser>()
 | 
				
			||||||
@@ -193,7 +193,7 @@ public sealed class PatronageService
 | 
				
			|||||||
                                            ValidThru = dateInOneMonth,
 | 
					                                            ValidThru = dateInOneMonth,
 | 
				
			||||||
                                        });
 | 
					                                        });
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
                    await tran.CommitAsync();
 | 
					                    // await tran.CommitAsync();
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
                    var newPatron = PatronUserToPatron(dbPatron);
 | 
					                    var newPatron = PatronUserToPatron(dbPatron);
 | 
				
			||||||
                    _ = SendWelcomeMessage(newPatron);
 | 
					                    _ = SendWelcomeMessage(newPatron);
 | 
				
			||||||
@@ -222,45 +222,38 @@ public sealed class PatronageService
 | 
				
			|||||||
                        // this should never happen
 | 
					                        // this should never happen
 | 
				
			||||||
                        if (count == 0)
 | 
					                        if (count == 0)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            await tran.RollbackAsync();
 | 
					                            // await tran.RollbackAsync();
 | 
				
			||||||
                            continue;
 | 
					                            continue;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
                        await tran.CommitAsync();
 | 
					                        // await tran.CommitAsync();
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
                        await OnNewPatronPayment(PatronUserToPatron(dbPatron));
 | 
					                        await OnNewPatronPayment(PatronUserToPatron(dbPatron));
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    else if (dbPatron.AmountCents != subscriber.Cents // if user changed the amount 
 | 
					                    else if (dbPatron.AmountCents != subscriber.Cents // if user changed the amount 
 | 
				
			||||||
                             || dbPatron.UserId != subscriber.UserId) // if user updated user id)
 | 
					                             || dbPatron.UserId != subscriber.UserId) // if user updated user id)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
 | 
					                        var cents = subscriber.Cents;
 | 
				
			||||||
                        // the user updated the pledge or changed the connected discord account
 | 
					                        // the user updated the pledge or changed the connected discord account
 | 
				
			||||||
                        var count = await ctx.GetTable<PatronUser>()
 | 
					                        await ctx.GetTable<PatronUser>()
 | 
				
			||||||
                                             .Where(x => x.UniquePlatformUserId == subscriber.UniquePlatformUserId
 | 
					                                 .Where(x => x.UniquePlatformUserId == subscriber.UniquePlatformUserId)
 | 
				
			||||||
                                                         && x.LastCharge < lastChargeUtc)
 | 
					                                 .UpdateAsync(old => new()
 | 
				
			||||||
                                             .UpdateAsync(old => new()
 | 
					                                 {
 | 
				
			||||||
                                             {
 | 
					                                     UserId = subscriber.UserId,
 | 
				
			||||||
                                                 UserId = subscriber.UserId,
 | 
					                                     AmountCents = cents,
 | 
				
			||||||
                                                 AmountCents = subscriber.Cents,
 | 
					                                     LastCharge = lastChargeUtc,
 | 
				
			||||||
                                                 LastCharge = lastChargeUtc,
 | 
					                                     ValidThru = old.ValidThru,
 | 
				
			||||||
                                                 ValidThru = old.ValidThru,
 | 
					                                 });
 | 
				
			||||||
                                             });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        if (count == 0)
 | 
					                        var newPatron = dbPatron.Clone();
 | 
				
			||||||
                        {
 | 
					                        newPatron.AmountCents = cents;
 | 
				
			||||||
                            await tran.RollbackAsync();
 | 
					                        newPatron.UserId = subscriber.UserId;
 | 
				
			||||||
                            continue;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        
 | 
					                        
 | 
				
			||||||
                        var newData = await ctx.GetTable<PatronUser>()
 | 
					                        // idk what's going on but UpdateWithOutputAsync doesn't work properly here
 | 
				
			||||||
                                               .FirstAsync(x => x.UniquePlatformUserId 
 | 
					                        // nor does firstordefault after update. I'm not seeing something obvious
 | 
				
			||||||
                                                                == subscriber.UniquePlatformUserId);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        await tran.CommitAsync();
 | 
					 | 
				
			||||||
                        await OnPatronUpdated(
 | 
					                        await OnPatronUpdated(
 | 
				
			||||||
                            PatronUserToPatron(dbPatron),
 | 
					                            PatronUserToPatron(dbPatron),
 | 
				
			||||||
                            PatronUserToPatron(newData));
 | 
					                            PatronUserToPatron(newPatron));
 | 
				
			||||||
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -745,7 +738,7 @@ public sealed class PatronageService
 | 
				
			|||||||
    private Patron PatronUserToPatron(PatronUser user)
 | 
					    private Patron PatronUserToPatron(PatronUser user)
 | 
				
			||||||
        => new Patron()
 | 
					        => new Patron()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            UnqiuePlatformUserId = user.UniquePlatformUserId,
 | 
					            UniquePlatformUserId = user.UniquePlatformUserId,
 | 
				
			||||||
            UserId = user.UserId,
 | 
					            UserId = user.UserId,
 | 
				
			||||||
            Amount = user.AmountCents,
 | 
					            Amount = user.AmountCents,
 | 
				
			||||||
            Tier = CalculateTier(user),
 | 
					            Tier = CalculateTier(user),
 | 
				
			||||||
@@ -798,7 +791,7 @@ public sealed class PatronageService
 | 
				
			|||||||
*- Any user in any of your servers can use Patron-only commands, but they will spend **your quota**, which is why it's recommended to use Nadeko's command cooldown system (.h .cmdcd) or permission system to limit the command usage for your server members.*
 | 
					*- Any user in any of your servers can use Patron-only commands, but they will spend **your quota**, which is why it's recommended to use Nadeko's command cooldown system (.h .cmdcd) or permission system to limit the command usage for your server members.*
 | 
				
			||||||
*- Permission guide can be found here if you're not familiar with it: <https://nadekobot.readthedocs.io/en/latest/permissions-system/>*",
 | 
					*- Permission guide can be found here if you're not familiar with it: <https://nadekobot.readthedocs.io/en/latest/permissions-system/>*",
 | 
				
			||||||
                            isInline: false)
 | 
					                            isInline: false)
 | 
				
			||||||
                        .WithFooter($"platform id: {patron.UnqiuePlatformUserId}");
 | 
					                        .WithFooter($"platform id: {patron.UniquePlatformUserId}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            await user.EmbedAsync(eb);
 | 
					            await user.EmbedAsync(eb);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -69,15 +69,15 @@
 | 
				
			|||||||
        <PackageReference Include="JetBrains.Annotations" Version="2022.1.0" />
 | 
					        <PackageReference Include="JetBrains.Annotations" Version="2022.1.0" />
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        <!-- Db-related packages -->
 | 
					        <!-- Db-related packages -->
 | 
				
			||||||
        <PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.5" />
 | 
					        <PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.6" />
 | 
				
			||||||
        <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.5">
 | 
					        <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.5">
 | 
				
			||||||
            <PrivateAssets>all</PrivateAssets>
 | 
					            <PrivateAssets>all</PrivateAssets>
 | 
				
			||||||
            <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
 | 
					            <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
 | 
				
			||||||
        </PackageReference>
 | 
					        </PackageReference>
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        <PackageReference Include="linq2db.EntityFrameworkCore" Version="6.7.1" />
 | 
					        <PackageReference Include="linq2db.EntityFrameworkCore" Version="6.8.0" />
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.5" />        
 | 
					        <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.6" />        
 | 
				
			||||||
        <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.4" />
 | 
					        <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.4" />
 | 
				
			||||||
        <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="6.0.1" />
 | 
					        <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="6.0.1" />
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,6 +23,8 @@ quotas:
 | 
				
			|||||||
      C: 100000
 | 
					      C: 100000
 | 
				
			||||||
  # Dictionary of commands with their respective quota data
 | 
					  # Dictionary of commands with their respective quota data
 | 
				
			||||||
  commands:
 | 
					  commands:
 | 
				
			||||||
 | 
					    cleverbot:
 | 
				
			||||||
 | 
					      V: null
 | 
				
			||||||
    prune:
 | 
					    prune:
 | 
				
			||||||
      X:
 | 
					      X:
 | 
				
			||||||
        PerHour: 1
 | 
					        PerHour: 1
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user