Beispiel #1
0
 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}");
     }
 }
Beispiel #2
0
        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)) });
            }
        }
Beispiel #3
0
        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();
        }
Beispiel #4
0
        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)))) });
            }
        }
Beispiel #5
0
        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();
            }
        }
Beispiel #6
0
 [NotNull] private string FormatBalance([NotNull] IBalance bal)
 {
     return(TransactionFormatting.FormatBalance(this, bal));
 }
Beispiel #7
0
 [NotNull] private string FormatTransaction([NotNull] ITransaction tsx)
 {
     return(TransactionFormatting.FormatTransaction(this, tsx));
 }