public async Task CreateDebt(IUser user, decimal amount, string unit, [Remainder] string?note = null) { if (amount < 0) { await TypingReplyAsync("You cannot owe a negative amount!"); } else { await _transactions.CreateTransaction(user.Id, Context.User.Id, amount, unit, note, DateTime.UtcNow); await ReplyAsync( $"{Context.User.Mention} owes {TransactionFormatting.FormatCurrency(amount, unit)} to {user.Mention}"); } }
private async Task PaginatedPending(IAsyncEnumerable <IPendingTransaction> pending, string none, string paginatedHeader, bool mentionReceiver) { async Task <string> FormatSinglePending(IPendingTransaction p, bool longForm) { var receiver = await _users.Name(p.ToId, mention : mentionReceiver); var payer = await _users.Name(p.FromId); var note = string.IsNullOrEmpty(p.Note) ? "" : $"'{p.Note}'"; var amount = TransactionFormatting.FormatCurrency(p.Amount, p.Unit); var fid = new BalderHash32(p.Id).ToString(); if (longForm) { return($"{receiver} Type `!confirm {fid}` or `!deny {fid}` to confirm/deny transaction of {amount} from {payer} {note}"); } else { return($"`{fid}`: {payer} paid {amount} to {receiver} {note}"); } } var pendingArr = await pending.ToListAsync(); var formatted = new List <string>(); var longForm = pendingArr.Count < 5; foreach (var item in pendingArr) { formatted.Add(await FormatSinglePending(item, longForm)); } if (pendingArr.Count == 0) { await TypingReplyAsync(none); } else if (longForm) { await ReplyAsync(string.Join("\n", formatted)); } else { await TypingReplyAsync(string.Format(paginatedHeader, pendingArr.Count)); await PagedReplyAsync(new PaginatedMessage { Pages = formatted.Batch(7).Select(d => string.Join("\n", d)) }); } }
private async Task DisplayBalances(IReadOnlyCollection <IBalance> balances) { async Task DebtTotalsPerUnit() { if (balances.Count > 1) { var totals = balances.GroupBy(a => a.Unit) .Select(a => (a.Key, a.Sum(o => o.Amount))) .OrderByDescending(a => a.Item2) .ToArray(); var r = new StringBuilder("```\nTotals:\n"); foreach (var(key, amount) in totals) { r.AppendLine($" => {TransactionFormatting.FormatCurrency(amount, key)}"); } r.AppendLine("```"); await ReplyAsync(r.ToString()); } } var balancesList = new List <string>(balances.Count); foreach (var balance in balances) { balancesList.Add(await balance.Format(_users)); } //If the number of transactions is small, display them all. //Otherwise batch and show them in pages if (balancesList.Count < 10) { await ReplyAsync(string.Join("\n", balancesList)); } else { await PagedReplyAsync(new PaginatedMessage { Pages = balancesList.Batch(7).Select(d => string.Join("\n", d)) }); } await DebtTotalsPerUnit(); }
private async Task PaginatedPending([NotNull] IAsyncEnumerable <IPendingTransaction> pending, string none, string paginatedHeader, bool mentionReceiver) { string FormatSinglePending(IPendingTransaction p, bool longForm) { var receiver = Name(p.ToId, mentionReceiver); var payer = Name(p.FromId); var note = string.IsNullOrEmpty(p.Note) ? "" : $"'{p.Note}'"; var amount = TransactionFormatting.FormatCurrency(p.Amount, p.Unit); var fid = new FriendlyId32(p.Id).ToString(); if (longForm) { return($"{receiver} Type `!confirm {fid}` or `!deny {fid}` to confirm/deny transaction of {amount} from {payer} {note}"); } else { return($"`{fid}`: {payer} paid {amount} to {receiver} {note}"); } } var pendingArr = await pending.ToArray(); if (pendingArr.Length == 0) { await TypingReplyAsync(none); } else if (pendingArr.Length < 5) { await ReplyAsync(string.Join("\n", pendingArr.Select(p => FormatSinglePending(p, true)))); } else { await TypingReplyAsync(string.Format(paginatedHeader, pendingArr.Length)); await PagedReplyAsync(new PaginatedMessage { Pages = pendingArr.Batch(7).Select(d => string.Join("\n", d.Select(p => FormatSinglePending(p, false)))) }); } }
public async Task Confirm([NotNull] string input) { var fid = FriendlyId32.Parse(input); if (!fid.HasValue) { await TypingReplyAsync("Invalid ID `{id}`"); return; } var transactions = await(await _pending.Get(debtId: fid.Value.Value)).ToArray(); if (transactions.Length == 0) { await TypingReplyAsync($"Cannot find a transaction with ID `{fid}`"); return; } if (transactions.Length > 1) { await TypingReplyAsync($"Found multiple transactions with ID `{fid}`! This is probably an error, please report it."); return; } var transaction = transactions[0]; if (transaction.ToId != Context.User.Id) { await TypingReplyAsync("You cannot confirm this transaction"); return; } var result = await _pending.ConfirmPending(fid.Value.Value); switch (result) { case ConfirmResult.Confirmed: await TypingReplyAsync($"Confirmed {TransactionFormatting.FormatTransaction(this, transaction)}"); break; case ConfirmResult.AlreadyDenied: await TypingReplyAsync("This transaction has already been denied and cannot be confirmed"); break; case ConfirmResult.AlreadyConfirmed: await TypingReplyAsync("This transaction has already been confirmed"); break; case ConfirmResult.IdNotFound: await TypingReplyAsync($"Cannot find a transaction with ID `{fid}`! This is probably an error, please report it."); break; default: await TypingReplyAsync($"Unknown transaction state `{result}`! This is probably an error, please report it."); throw new ArgumentOutOfRangeException(); } }
[NotNull] private string FormatBalance([NotNull] IBalance bal) { return(TransactionFormatting.FormatBalance(this, bal)); }
[NotNull] private string FormatTransaction([NotNull] ITransaction tsx) { return(TransactionFormatting.FormatTransaction(this, tsx)); }