public async Task GetZone([Remainder] string arg0) { arg0 = StringUtilities.StripOuterQuotes(arg0); // Show either the given zone, or all zones of the given type. IZone zone = await Db.GetZoneAsync(arg0); if (zone.IsValid()) { // The user passed in a valid zone, so show information about that zone. await ShowZoneAsync(zone); } else { // The user passed in an invalid zone, so check if it's a valid zone type. IZoneType zoneType = await Db.GetZoneTypeAsync(arg0); if (zoneType.IsValid()) { // The user passed in a valid zone type, so show all zones with that type. IEnumerable <IZone> zones = (await Db.GetZonesAsync(zoneType)); await ShowZonesAsync(zones, zoneType); } else { await this.ReplyValidateZoneAsync(zone, arg0); } } }
public async Task AddZone(string zoneName, string arg1 = "", string arg2 = "") { // Cases: // 1. <zoneName> // 2. <zoneName> <zoneTypeName> // 3. <zoneName> <zoneTypeName> <description> // 4. <zoneName> <description> string zoneTypeName = arg1; string description = arg2; if (string.IsNullOrEmpty(zoneName)) { // The user must specify a non-empty zone name. await ReplyErrorAsync("Zone name cannot be empty."); } else { // Allow the user to specify zones with numbers (e.g. "1") or single letters (e.g. "A"). // Otherwise, the name is taken as-is. zoneName = ZoneUtilities.GetFullName(zoneName).ToLowerInvariant(); IZoneType zoneType = await Db.GetZoneTypeAsync(arg1); if (!zoneType.IsValid()) { // If an invalid type was provided, assume the user meant it as a description instead (4). description = zoneTypeName; // Attempt to determine the zone type automatically based on the zome name. // This is currently only possible for default zones ("aquatic" or "terrestrial"). zoneType = await Db.GetDefaultZoneTypeAsync(zoneName); } if (await Db.GetZoneAsync(zoneName) != null) { // Don't attempt to create the zone if it already exists. await ReplyWarningAsync($"A zone named {ZoneUtilities.GetFullName(zoneName).ToBold()} already exists."); } else { // Add the new zone. await Db.AddZoneAsync(new Zone { Name = zoneName, Description = description, TypeId = zoneType.Id }); await ReplySuccessAsync($"Successfully created new {zoneType.Name.ToLowerInvariant()} zone, {ZoneUtilities.GetFullName(zoneName).ToBold()}."); } } }
public static bool SetColor(this IZoneType zoneType, string hexColor) { if (StringUtilities.TryParseColor(hexColor, out Color result)) { zoneType.Color = result; return(true); } return(false); }
public async Task GetZoneType(string arg0) { if (!string.IsNullOrEmpty(arg0)) { // If the given argument is a zone type, display information for that type. // If the given argument is a zone name, display information for the type corresponding to that zone. IZoneType type = await Db.GetZoneTypeAsync(arg0); if (!type.IsValid()) { // If no zone type exists with this name, attempt to get the type of the zone with this name. IZone zone = await Db.GetZoneAsync(arg0); if (zone != null) { type = await Db.GetZoneTypeAsync(zone.TypeId); } } if (type.IsValid()) { // We got a valid zone type, so show information about the zone type. IEnumerable <IZone> zones = await Db.GetZonesAsync(type); string embedTitle = string.Format("{0} {1} Zones ({2})", type.Icon, type.Name, zones.Count()).ToTitle(); string embedDescription = type.Description + "\n\n"; IEnumerable <IEmbed> pages = await BotUtils.ZonesToEmbedPagesAsync(embedTitle.Length + embedDescription.Length, zones, Db, showIcon : false); foreach (IEmbed page in pages) { page.Description = embedDescription + page.Description; } IPaginatedMessage message = new PaginatedMessage(pages); message.SetTitle(embedTitle); message.SetColor(type.Color); await ReplyAsync(message); } else { await ReplyErrorAsync("No such zone type exists."); } } else { await GetZoneTypes(); } }
public static async Task AddZoneTypeAsync(this SQLiteDatabase database, IZoneType type) { using (SQLiteCommand cmd = new SQLiteCommand("INSERT OR REPLACE INTO ZoneTypes(name, icon, color, description) VALUES($name, $icon, $color, $description)")) { cmd.Parameters.AddWithValue("$name", type.Name.ToLowerInvariant()); cmd.Parameters.AddWithValue("$icon", type.Icon); cmd.Parameters.AddWithValue("$color", ColorTranslator.ToHtml(type.Color).ToLowerInvariant()); cmd.Parameters.AddWithValue("$description", type.Description); await database.ExecuteNonQueryAsync(cmd); } }
public async Task SetZoneType(string zoneName, string zoneType) { IZone zone = await Db.GetZoneAsync(zoneName); IZoneType type = await Db.GetZoneTypeAsync(zoneType); if (await BotUtils.ReplyValidateZoneAsync(Context, zone) && await BotUtils.ReplyValidateZoneTypeAsync(Context, type)) { zone.TypeId = type.Id; await Db.UpdateZoneAsync(zone); await BotUtils.ReplyAsync_Success(Context, string.Format("Successfully set the type of {0}**{1}** to **{2}**.", zone.GetFullName().StartsWith("Zone") ? string.Empty : "zone ", zone.GetFullName(), type.Name)); } }
public static async Task <IEnumerable <Discord.Messaging.IEmbed> > ZonesToEmbedPagesAsync(int existingLength, IEnumerable <IZone> zones, SQLiteDatabase database, bool showIcon = true) { List <string> lines = new List <string>(); int zones_per_page = 20; int maxLineLength = Math.Min(showIcon ? 78 : 80, (DiscordUtils.MaxEmbedLength - existingLength) / zones_per_page); foreach (IZone zone in zones) { IZoneType type = await database.GetZoneTypeAsync(zone.TypeId); StringBuilder lineBuilder = new StringBuilder(); if (showIcon) { lineBuilder.Append((type ?? new ZoneType()).Icon); lineBuilder.Append(" "); } lineBuilder.Append(zone.GetFullName().ToBold()); if (!string.IsNullOrWhiteSpace(zone.Description)) { lineBuilder.Append("\t—\t"); lineBuilder.Append(zone.Description.GetFirstSentence()); } string line = lineBuilder.ToString(); if (line.Length > maxLineLength) { line = line.Substring(0, maxLineLength - 3) + "..."; } lines.Add(line); } return(EmbedUtilities.CreateEmbedPages(string.Empty, lines, itemsPerPage: 20, columnsPerPage: 1, options: EmbedPaginationOptions.AddPageNumbers)); }
// Private members private async Task ShowZonesAsync(IEnumerable <IZone> zones, IZoneType type) { if (zones.Count() > 0) { // We need to make sure that even if the "short" description is actually long, we can show n zones per page. string embedTitle = string.Format("{0} zones ({1})", type.IsValid() ? type.Name : "All", zones.Count()).ToTitle(); string embedDescription = string.Format("For detailed zone information, use `{0}zone <zone>` (e.g. `{0}zone {1}`).\n\n", Config.Prefix, zones.First().GetShortName().Contains(" ") ? string.Format("\"{0}\"", zones.First().GetShortName().ToLowerInvariant()) : zones.First().GetShortName().ToLowerInvariant()); // Build paginated message. IEnumerable <IEmbed> pages = await BotUtils.ZonesToEmbedPagesAsync(embedTitle.Length + embedDescription.Length, zones, Db); foreach (IEmbed page in pages) { page.Description = embedDescription + page.Description; } IPaginatedMessage message = new PaginatedMessage(pages); message.SetTitle(embedTitle); if (type.IsValid()) { message.SetColor(type.Color); } await ReplyAsync(message); } else { await ReplyInfoAsync("No zones have been added yet."); } }
public static bool IsValid(this IZoneType zoneType) { return(zoneType != null && zoneType.Id.HasValue && zoneType.Id >= 0); }
public static void SetColor(this IZoneType zoneType, Color color) { zoneType.Color = color; }
private async Task ShowZoneAsync(IZone zone) { if (await this.ReplyValidateZoneAsync(zone)) { // Get all species living in this zone. List <ISpecies> speciesList = new List <ISpecies>((await Db.GetSpeciesAsync(zone)).Where(species => !species.IsExtinct())); speciesList.Sort((lhs, rhs) => TaxonFormatter.GetString(lhs, false).CompareTo(TaxonFormatter.GetString(rhs, false))); // Starting building a paginated message. // The message will have a paginated species list, and a toggle button to display the species sorted by role. string description = zone.GetDescriptionOrDefault(); if (!speciesList.Any()) { description += "\n\nThis zone does not contain any species."; } List <IEmbed> embedPages = new List <IEmbed>(); if (zone.Fields.Any()) { embedPages.Add(new Embed()); foreach (IZoneField field in zone.Fields) { if (!string.IsNullOrWhiteSpace(field.GetName()) && !string.IsNullOrWhiteSpace(field.GetValue())) { embedPages.Last().AddField(field.GetName(), field.GetValue(), true); } } embedPages.Last().Description = description; } embedPages.AddRange(EmbedUtilities.CreateEmbedPages(string.Format("Extant species in this zone ({0}):", speciesList.Count()), speciesList, formatter: TaxonFormatter)); // Add title, decription, etc., to all pages. if (!embedPages.Any()) { embedPages.Add(new Embed()); } IZoneType type = await Db.GetZoneTypeAsync(zone.TypeId) ?? new ZoneType(); string aliases = zone.Aliases.Any() ? string.Format("({0})", string.Join(", ", zone.Aliases.Select(alias => alias.ToTitle()))) : string.Empty; string title = string.Format("{0} {1} {2}", type.Icon, zone.GetFullName(), aliases).Trim(); System.Drawing.Color color = type.Color; foreach (IEmbed page in embedPages) { page.Title = title; page.ThumbnailUrl = zone.Pictures.FirstOrDefault()?.Url; page.Color = color; // Add the zone description to all pages if the zone doesn't have any fields (because the info page will be missing). if (!zone.Fields.Any()) { page.Description = description; } } IPaginatedMessage message = new PaginatedMessage(embedPages); message.AddPageNumbers(); // This page will have species organized by role. // Only bother with the role page if species actually exist in this zone. if (speciesList.Count() > 0) { IEmbed rolesPage = new Embed { Title = title, ThumbnailUrl = zone.GetPictureUrl(), Color = color }; Dictionary <string, List <ISpecies> > rolesMap = new Dictionary <string, List <ISpecies> >(); foreach (ISpecies species in speciesList) { IEnumerable <Common.Roles.IRole> roles_list = await Db.GetRolesAsync(species); if (roles_list.Count() <= 0) { if (!rolesMap.ContainsKey("no role")) { rolesMap["no role"] = new List <ISpecies>(); } rolesMap["no role"].Add(species); continue; } foreach (Common.Roles.IRole role in roles_list) { if (!rolesMap.ContainsKey(role.GetName())) { rolesMap[role.GetName()] = new List <ISpecies>(); } rolesMap[role.GetName()].Add(species); } } // Sort the list of species belonging to each role. foreach (List <ISpecies> i in rolesMap.Values) { i.Sort((lhs, rhs) => TaxonFormatter.GetString(lhs, false).CompareTo(TaxonFormatter.GetString(rhs, false))); } // Create a sorted list of keys so that the roles are in order. List <string> sorted_keys = new List <string>(rolesMap.Keys); sorted_keys.Sort(); foreach (string i in sorted_keys) { StringBuilder lines = new StringBuilder(); foreach (ISpecies j in rolesMap[i]) { lines.AppendLine(TaxonFormatter.GetString(j)); } rolesPage.AddField(string.Format("{0}s ({1})", StringUtilities.ToTitleCase(i), rolesMap[i].Count()), lines.ToString(), inline: true); } // Add the page to the builder. message.AddReaction("🇷", async(args) => { if (args.Emoji != "🇷") { return; } args.Message.PaginationEnabled = !args.ReactionAdded; if (args.ReactionAdded) { args.Message.CurrentPage = new Message() { Embed = rolesPage } } ; else { args.Message.CurrentPage = null; } await Task.CompletedTask; }); } await ReplyAsync(message); } }
public static async Task <bool> ReplyValidateZoneTypeAsync(ICommandContext context, IZoneType zoneType) { if (!zoneType.IsValid()) { await context.Channel.SendMessageAsync("No such zone type exists."); return(false); } return(true); }
public static async Task <IEnumerable <IZone> > GetZonesAsync(this SQLiteDatabase database, IZoneType zoneType) { // Returns all zones of the given type. // If the zone type is invalid (null or has an invalid id), returns all zones. return((await GetZonesAsync(database)) .Where(zone => zoneType is null || !zoneType.Id.HasValue || zone.TypeId == zoneType.Id)); }