// Private members

        public async Task _plusZone(Species species, string zoneList, string notes, bool onlyShowErrors = false)
        {
            // Get the zones from user input.
            ZoneListResult zones = await ZoneUtils.GetZonesByZoneListAsync(zoneList);

            // Add the zones to the species.
            await SpeciesUtils.AddZonesAsync(species, zones.Zones, notes);

            if (zones.InvalidZones.Count() > 0)
            {
                // Show a warning if the user provided any invalid zones.

                await BotUtils.ReplyAsync_Warning(Context, string.Format("{0} {1} not exist.",
                                                                         StringUtils.ConjunctiveJoin(", ", zones.InvalidZones.Select(x => string.Format("**{0}**", ZoneUtils.FormatZoneName(x))).ToArray()),
                                                                         zones.InvalidZones.Count() == 1 ? "does" : "do"));
            }

            if (zones.Zones.Count() > 0 && !onlyShowErrors)
            {
                // Show a confirmation of all valid zones.

                await BotUtils.ReplyAsync_Success(Context, string.Format("**{0}** now inhabits {1}.",
                                                                         species.ShortName,
                                                                         StringUtils.ConjunctiveJoin(", ", zones.Zones.Select(x => string.Format("**{0}**", x.GetFullName())).ToArray())));
            }
        }
        public async Task MinusZone(string genus, string species, string zoneList)
        {
            // Ensure that the user has necessary privileges to use this command.
            if (!await BotUtils.ReplyHasPrivilegeAsync(Context, PrivilegeLevel.ServerModerator))
            {
                return;
            }

            // Get the specified species.

            Species sp = await BotUtils.ReplyFindSpeciesAsync(Context, genus, species);

            if (sp is null)
            {
                return;
            }

            // Get the zones that the species currently resides in.
            // These will be used to show warning messages (e.g., doesn't exist in the given zone).

            long[] current_zone_ids = (await BotUtils.GetZonesFromDb(sp.Id)).Select(x => x.Id).ToArray();

            // Get the zones from user input.
            ZoneListResult zones = await ZoneUtils.GetZonesByZoneListAsync(zoneList);

            // Remove the zones from the species.
            await SpeciesUtils.RemoveZonesAsync(sp, zones.Zones);

            if (zones.InvalidZones.Count() > 0)
            {
                // Show a warning if the user provided any invalid zones.

                await BotUtils.ReplyAsync_Warning(Context, string.Format("{0} {1} not exist.",
                                                                         StringUtils.ConjunctiveJoin(", ", zones.InvalidZones.Select(x => string.Format("**{0}**", ZoneUtils.FormatZoneName(x))).ToArray()),
                                                                         zones.InvalidZones.Count() == 1 ? "does" : "do"));
            }

            if (zones.Zones.Any(x => !current_zone_ids.Contains(x.Id)))
            {
                // Show a warning if the species wasn't in one or more of the zones provided.

                await BotUtils.ReplyAsync_Warning(Context, string.Format("**{0}** is already absent from {1}.",
                                                                         sp.ShortName,
                                                                         StringUtils.ConjunctiveJoin(", ", zones.Zones.Where(x => !current_zone_ids.Contains(x.Id)).Select(x => string.Format("**{0}**", x.GetFullName())).ToArray())));
            }

            if (zones.Zones.Any(x => current_zone_ids.Contains(x.Id)))
            {
                // Show a confirmation of all valid zones.

                await BotUtils.ReplyAsync_Success(Context, string.Format("**{0}** no longer inhabits {1}.",
                                                                         sp.ShortName,
                                                                         StringUtils.DisjunctiveJoin(", ", zones.Zones.Where(x => current_zone_ids.Contains(x.Id)).Select(x => string.Format("**{0}**", x.GetFullName())).ToArray())));
            }
        }