public async Task Random(string taxonName)
        {
            // Get the taxon.

            Taxon taxon = await BotUtils.GetTaxonFromDb(taxonName);

            if (taxon is null)
            {
                await BotUtils.ReplyAsync_Error(Context, "No such taxon exists.");

                return;
            }

            // Get all species under that taxon.

            List <Species> species = new List <Species>();

            species.AddRange(await BotUtils.GetSpeciesInTaxonFromDb(taxon));
            species.RemoveAll(x => x.IsExtinct);

            if (species.Count() <= 0)
            {
                await BotUtils.ReplyAsync_Info(Context, string.Format("{0} **{1}** does not contain any extant species.", StringUtils.ToTitleCase(taxon.GetTypeName()), taxon.GetName()));
            }
            else
            {
                await SpeciesCommands.ShowSpeciesInfoAsync(Context, species[BotUtils.RandomInteger(species.Count())]);
            }
        }
        public async Task Gallery(string speciesOrTaxon)
        {
            // Prioritize species galleries first.

            Species[] species = await BotUtils.GetSpeciesFromDb("", speciesOrTaxon);

            if (species is null || species.Count() <= 0)
            {
                // No such species exists, so check if a taxon exists.

                Taxon taxon = await BotUtils.GetTaxonFromDb(speciesOrTaxon);

                if (taxon is null)
                {
                    // If no such taxon exists, show species recommendations to the user.
                    await BotUtils.ReplyAsync_SpeciesSuggestions(Context, "", speciesOrTaxon);
                }
                else
                {
                    // The taxon does exist, so we'll generate a gallery from this taxon.
                    // First, images for this taxon will be added, followed by the galleries for all species under it.

                    List <Picture> pictures = new List <Picture>();

                    if (!string.IsNullOrEmpty(taxon.pics))
                    {
                        pictures.Add(new Picture(taxon.pics));
                    }

                    foreach (Species sp in await BotUtils.GetSpeciesInTaxonFromDb(taxon))
                    {
                        pictures.AddRange(await SpeciesUtils.GetPicturesAsync(sp));
                    }

                    await ShowGalleryAsync(Context, taxon.GetName(), pictures.ToArray());
                }
            }
        public async Task ListSpecies(string taxonName)
        {
            // Get the taxon.

            Taxon taxon = await BotUtils.GetTaxonFromDb(taxonName);

            if (taxon is null)
            {
                await BotUtils.ReplyAsync_Error(Context, "No such taxon exists.");

                return;
            }

            // Get all species under that taxon.

            List <Species> species = new List <Species>();

            species.AddRange(await BotUtils.GetSpeciesInTaxonFromDb(taxon));

            species.Sort((lhs, rhs) => lhs.FullName.CompareTo(rhs.FullName));

            // We might get a lot of species, which may not fit in one embed.
            // We'll need to use a paginated embed to reliably display the full list.

            // Create embed pages.

            List <EmbedBuilder> pages = EmbedUtils.SpeciesListToEmbedPages(species, fieldName: string.Format("Species in this {0} ({1}):", taxon.GetTypeName(), species.Count()));

            if (pages.Count <= 0)
            {
                pages.Add(new EmbedBuilder());
            }

            // Add description to the first page.

            StringBuilder description_builder = new StringBuilder();

            description_builder.AppendLine(taxon.GetDescriptionOrDefault());

            if (species.Count() <= 0)
            {
                description_builder.AppendLine();
                description_builder.AppendLine(string.Format("This {0} contains no species.", Taxon.GetRankName(taxon.type)));
            }

            // Add title to all pages.

            foreach (EmbedBuilder page in pages)
            {
                page.WithTitle(string.IsNullOrEmpty(taxon.CommonName) ? taxon.GetName() : string.Format("{0} ({1})", taxon.GetName(), taxon.GetCommonName()));
                page.WithDescription(description_builder.ToString());
                page.WithThumbnailUrl(taxon.pics);
            }

            // Send the result.

            Bot.PaginatedMessage reply = new Bot.PaginatedMessage();

            foreach (EmbedBuilder page in pages)
            {
                reply.Pages.Add(page.Build());
            }

            await Bot.DiscordUtils.SendMessageAsync(Context, reply);
        }