public static async Task <ChickenUpgrade> GetChickenUpgradeAsync(this DBService db, int wid)
        {
            ChickenUpgrade upgrade = null;

            await db.ExecuteCommandAsync(async (cmd) => {
                cmd.CommandText = "SELECT name, modifier, price, upgrades_stat FROM gf.chicken_upgrades WHERE wid = @wid LIMIT 1;";
                cmd.Parameters.Add(new NpgsqlParameter <int>("wid", wid));

                using (var reader = await cmd.ExecuteReaderAsync().ConfigureAwait(false)) {
                    if (await reader.ReadAsync().ConfigureAwait(false))
                    {
                        upgrade = new ChickenUpgrade()
                        {
                            Id           = wid,
                            Modifier     = (int)reader["modifier"],
                            Name         = (string)reader["name"],
                            Price        = (long)reader["price"],
                            UpgradesStat = (ChickenStatUpgrade)(short)reader["upgrades_stat"]
                        };
                    }
                }
            });

            return(upgrade);
        }
            public async Task ExecuteGroupAsync(CommandContext ctx,
                                                [Description("ID of the upgrade to buy.")] int id)
            {
                if (this.Shared.GetEventInChannel(ctx.Channel.Id) is ChickenWar)
                {
                    throw new CommandFailedException("There is a chicken war running in this channel. No sells are allowed before the war finishes.");
                }

                Chicken chicken = await this.Database.GetChickenAsync(ctx.User.Id, ctx.Guild.Id);

                if (chicken == null)
                {
                    throw new CommandFailedException($"You do not own a chicken in this guild! Use command {Formatter.InlineCode("chicken buy")} to buy a chicken (requires atleast 1000 {this.Shared.GetGuildConfig(ctx.Guild.Id).Currency ?? "credits"}).");
                }

                if (chicken.Stats.Upgrades.Any(u => u.Id == id))
                {
                    throw new CommandFailedException("Your chicken already has that upgrade!");
                }

                ChickenUpgrade upgrade = await this.Database.GetChickenUpgradeAsync(id);

                if (upgrade == null)
                {
                    throw new CommandFailedException($"An upgrade with ID {Formatter.InlineCode(id.ToString())} does not exist! Use command {Formatter.InlineCode("chicken upgrades")} to view all available upgrades.");
                }

                if (!await ctx.WaitForBoolReplyAsync($"{ctx.User.Mention}, are you sure you want to buy {Formatter.Bold(upgrade.Name)} for {Formatter.Bold($"{upgrade.Price:n0}")} {this.Shared.GetGuildConfig(ctx.Guild.Id).Currency ?? "credits"}?"))
                {
                    return;
                }

                if (!await this.Database.DecreaseBankAccountBalanceAsync(ctx.User.Id, ctx.Guild.Id, upgrade.Price))
                {
                    throw new CommandFailedException($"You do not have enought {this.Shared.GetGuildConfig(ctx.Guild.Id).Currency ?? "credits"} to buy that upgrade!");
                }

                await this.Database.AddChickenUpgradeAsync(ctx.User.Id, ctx.Guild.Id, upgrade);

                await this.InformAsync(ctx, StaticDiscordEmoji.Chicken, $"{ctx.User.Mention} bought upgraded his chicken with {Formatter.Bold(upgrade.Name)} (+{upgrade.Modifier}) {upgrade.UpgradesStat.ToShortString()}!");
            }
        public static Task AddChickenUpgradeAsync(this DBService db, ulong uid, ulong gid, ChickenUpgrade upgrade)
        {
            return(db.ExecuteCommandAsync(cmd => {
                cmd.CommandText = "INSERT INTO gf.chicken_active_upgrades VALUES (@uid, @gid, @wid) ON CONFLICT DO NOTHING;";
                cmd.Parameters.Add(new NpgsqlParameter <long>("uid", (long)uid));
                cmd.Parameters.Add(new NpgsqlParameter <long>("gid", (long)gid));
                cmd.Parameters.Add(new NpgsqlParameter <int>("wid", upgrade.Id));

                return cmd.ExecuteNonQueryAsync();
            }));
        }