public async Task Leaderboard() { UserRank[] userRanks = await UserUtils.GetRanksAsync(); List <string> lines = new List <string>(); foreach (UserRank userRank in userRanks) { IUser user = Context.Guild is null ? null : await Context.Guild.GetUserAsync(userRank.User.Id); lines.Add(string.Format("**`{0}`**{1}`{2}` {3}", string.Format("{0}.", userRank.Rank.ToString("000")), userRank.Icon, userRank.User.SubmissionCount.ToString("000"), string.Format(userRank.Rank <= 3 ? "**{0}**" : "{0}", user is null ? userRank.User.Username : user.Username) )); } // Create the embed. Bot.PaginatedMessageBuilder embed = new Bot.PaginatedMessageBuilder(); embed.AddPages(EmbedUtils.LinesToEmbedPages(lines)); embed.SetTitle(string.Format("🏆 Leaderboard ({0})", lines.Count)); embed.SetColor(255, 204, 77); embed.AddPageNumbers(); // Send the embed. await Bot.DiscordUtils.SendMessageAsync(Context, embed.Build()); }
public async Task Favs() { // Get all species fav'd by this user. List <string> lines = new List <string>(); using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM Species WHERE id IN (SELECT species_id FROM Favorites WHERE user_id = $user_id);")) { cmd.Parameters.AddWithValue("$user_id", Context.User.Id); using (DataTable rows = await Database.GetRowsAsync(cmd)) { foreach (DataRow row in rows.Rows) { Species sp = await SpeciesUtils.SpeciesFromDataRow(row); long fav_count = 0; // Get the number of times this species has been favorited. using (SQLiteCommand cmd2 = new SQLiteCommand("SELECT COUNT(*) FROM Favorites WHERE species_id = $species_id;")) { cmd2.Parameters.AddWithValue("$species_id", sp.Id); fav_count = await Database.GetScalar <long>(cmd2); } lines.Add(sp.ShortName + (fav_count > 1 ? string.Format(" (+{0})", fav_count) : "")); } lines.Sort(); } } // Display the species list. if (lines.Count() <= 0) { await BotUtils.ReplyAsync_Info(Context, string.Format("**{0}** has not favorited any species.", Context.User.Username)); } else { Bot.PaginatedMessageBuilder embed = new Bot.PaginatedMessageBuilder(EmbedUtils.LinesToEmbedPages(lines)); embed.SetTitle(string.Format("⭐ Species favorited by {0} ({1})", Context.User.Username, lines.Count())); embed.SetThumbnailUrl(Context.User.GetAvatarUrl(size: 32)); embed.AddPageNumbers(); await Bot.DiscordUtils.SendMessageAsync(Context, embed.Build()); } }
public async Task GetZoneType(string 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. ZoneType type = await ZoneUtils.GetZoneTypeAsync(arg0); if (!ZoneUtils.ZoneTypeIsValid(type)) { // If no zone type exists with this name, attempt to get the type of the zone with this name. Zone zone = await ZoneUtils.GetZoneAsync(arg0); if (zone != null) { type = await ZoneUtils.GetZoneTypeAsync(zone.ZoneTypeId); } } if (ZoneUtils.ZoneTypeIsValid(type)) { // We got a valid zone type, so show information about the zone type. Zone[] zones = await ZoneUtils.GetZonesAsync(type); Bot.PaginatedMessageBuilder embed = new Bot.PaginatedMessageBuilder { Title = string.Format("{0} {1} Zones ({2})", type.Icon, type.Name, zones.Count()), Description = type.Description + "\n\n", Color = Bot.DiscordUtils.ConvertColor(type.Color) }; await BotUtils.ZonesToEmbedPagesAsync(embed, zones, showIcon : false); embed.AddPageNumbers(); await Bot.DiscordUtils.SendMessageAsync(Context, embed.Build()); } else { await BotUtils.ReplyAsync_Error(Context, "No such zone type exists."); } }
public async Task Search([Remainder] string queryString) { // Create and execute the search query. Taxa.SearchQuery query = new Taxa.SearchQuery(Context, queryString); Taxa.SearchQueryResult result = await query.GetResultAsync(); // Build the embed. if (result.Count() <= 0) { await BotUtils.ReplyAsync_Info(Context, "No species matching this query could be found."); } else { if (result.DisplayFormat == Taxa.DisplayFormat.Gallery) { List <Picture> pictures = new List <Picture>(); foreach (Species species in result.ToArray()) { pictures.AddRange(await SpeciesUtils.GetPicturesAsync(species)); } await GalleryCommands.ShowGalleryAsync(Context, string.Format("search results ({0})", result.Count()), pictures.ToArray()); } else if (result.DisplayFormat == Taxa.DisplayFormat.Leaderboard) { // Match each group to a rank depending on how many results it contains. Dictionary <Taxa.SearchQueryResult.Group, long> groupRanks = new Dictionary <Taxa.SearchQueryResult.Group, long>(); long rank = 0; int lastCount = -1; foreach (Taxa.SearchQueryResult.Group group in result.Groups.OrderByDescending(x => x.Count())) { groupRanks[group] = (lastCount >= 0 && group.Count() == lastCount) ? rank : ++rank; lastCount = group.Count(); } // Create a list of groups that will be displayed to the user. List <string> lines = new List <string>(); foreach (Taxa.SearchQueryResult.Group group in result.Groups) { lines.Add(string.Format("**`{0}.`**{1}`{2}` {3}", groupRanks[group].ToString("000"), UserRank.GetRankIcon(groupRanks[group]), group.Count().ToString("000"), string.Format(groupRanks[group] <= 3 ? "**{0}**" : "{0}", string.IsNullOrEmpty(group.Name) ? "Results" : StringUtils.ToTitleCase(group.Name)) )); } Bot.PaginatedMessageBuilder embed = new Bot.PaginatedMessageBuilder { Title = string.Format("Search results ({0})", result.Groups.Count()) }; embed.AddPages(EmbedUtils.LinesToEmbedPages(lines)); embed.AddPageNumbers(); await Bot.DiscordUtils.SendMessageAsync(Context, embed.Build()); } else { if (result.Count() == 1) { // If there's only one result, just show that species. await SpeciesCommands.ShowSpeciesInfoAsync(Context, result.ToArray()[0]); } else { Bot.PaginatedMessageBuilder embed; if (result.HasGroup(Taxa.SearchQuery.DefaultGroupName)) { // If there's only one group, just list the species without creating separate fields. embed = new Bot.PaginatedMessageBuilder(EmbedUtils.ListToEmbedPages(result.DefaultGroup.ToStringArray().ToList(), fieldName: string.Format("Search results ({0})", result.Count()))); } else { embed = new Bot.PaginatedMessageBuilder(); embed.AddPages(EmbedUtils.SearchQueryResultToEmbedPages(result)); } embed.SetFooter(""); embed.AddPageNumbers(); await Bot.DiscordUtils.SendMessageAsync(Context, embed.Build()); } } } }
public async Task Zone(string arg0 = "") { ZoneType zone_type = await ZoneUtils.GetZoneTypeAsync(arg0); if (string.IsNullOrEmpty(arg0) || ZoneUtils.ZoneTypeIsValid(zone_type)) { // Display all zones, or, if the user passed in a valid zone type, all zones of that type. Zone[] zones = await ZoneUtils.GetZonesAsync(zone_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. Bot.PaginatedMessageBuilder embed = new Bot.PaginatedMessageBuilder { Title = StringUtils.ToTitleCase(string.Format("{0} zones ({1})", string.IsNullOrEmpty(arg0) ? "All" : arg0, zones.Count())), Description = string.Format("For detailed zone information, use `{0}zone <zone>` (e.g. `{0}zone {1}`).\n\n", OurFoodChainBot.Instance.Config.Prefix, zones[0].ShortName.Contains(" ") ? string.Format("\"{0}\"", zones[0].ShortName.ToLower()) : zones[0].ShortName.ToLower()) }; // Build paginated message. await BotUtils.ZonesToEmbedPagesAsync(embed, zones); embed.AddPageNumbers(); if (ZoneUtils.ZoneTypeIsValid(zone_type)) { embed.SetColor(Bot.DiscordUtils.ConvertColor(zone_type.Color)); } await Bot.DiscordUtils.SendMessageAsync(Context, embed.Build()); } else { await BotUtils.ReplyAsync_Info(Context, "No zones have been added yet."); } return; } else { Zone zone = await ZoneUtils.GetZoneAsync(arg0); if (await BotUtils.ReplyValidateZoneAsync(Context, zone)) { List <Embed> pages = new List <Embed>(); ZoneType type = await ZoneUtils.GetZoneTypeAsync(zone.ZoneTypeId) ?? new ZoneType(); string title = string.Format("{0} {1}", type.Icon, zone.FullName); string description = zone.GetDescriptionOrDefault(); Color color = Bot.DiscordUtils.ConvertColor(type.Color); // Get all species living in this zone. List <Species> species_list = new List <Species>(await BotUtils.GetSpeciesFromDbByZone(zone)); species_list.Sort((lhs, rhs) => lhs.ShortName.CompareTo(rhs.ShortName)); // Starting building a paginated message. // The message will have a paginated species list, and a toggle button to display the species sorted by role. List <EmbedBuilder> embed_pages = EmbedUtils.SpeciesListToEmbedPages(species_list, fieldName: (string.Format("Extant species in this zone ({0}):", species_list.Count()))); Bot.PaginatedMessageBuilder paginated = new Bot.PaginatedMessageBuilder(embed_pages); if (embed_pages.Count() <= 0) { embed_pages.Add(new EmbedBuilder()); } // Add title, decription, etc., to all pages. paginated.SetTitle(title); paginated.SetDescription(description); paginated.SetThumbnailUrl(zone.Pics); paginated.SetColor(color); // This page will have species organized by role. // Only bother with the role page if species actually exist in this zone. if (species_list.Count() > 0) { EmbedBuilder role_page = new EmbedBuilder(); role_page.WithTitle(title); role_page.WithDescription(description); //role_page.WithThumbnailUrl(zone.pics); role_page.WithColor(color); Dictionary <string, List <Species> > roles_map = new Dictionary <string, List <Species> >(); foreach (Species sp in species_list) { Role[] roles_list = await SpeciesUtils.GetRolesAsync(sp); if (roles_list.Count() <= 0) { if (!roles_map.ContainsKey("no role")) { roles_map["no role"] = new List <Species>(); } roles_map["no role"].Add(sp); continue; } foreach (Role role in roles_list) { if (!roles_map.ContainsKey(role.name)) { roles_map[role.name] = new List <Species>(); } roles_map[role.name].Add(sp); } } // Sort the list of species belonging to each role. foreach (List <Species> i in roles_map.Values) { i.Sort((lhs, rhs) => lhs.ShortName.CompareTo(rhs.ShortName)); } // Create a sorted list of keys so that the roles are in order. List <string> sorted_keys = new List <string>(roles_map.Keys); sorted_keys.Sort(); foreach (string i in sorted_keys) { StringBuilder lines = new StringBuilder(); foreach (Species j in roles_map[i]) { lines.AppendLine(j.ShortName); } role_page.AddField(string.Format("{0}s ({1})", StringUtils.ToTitleCase(i), roles_map[i].Count()), lines.ToString(), inline: true); } // Add the page to the builder. paginated.AddReaction("🇷"); paginated.SetCallback(async(args) => { if (args.Reaction != "🇷") { return; } args.PaginatedMessage.PaginationEnabled = !args.ReactionAdded; if (args.ReactionAdded) { await args.DiscordMessage.ModifyAsync(msg => msg.Embed = role_page.Build()); } else { await args.DiscordMessage.ModifyAsync(msg => msg.Embed = args.PaginatedMessage.Pages[args.PaginatedMessage.PageIndex]); } }); } await Bot.DiscordUtils.SendMessageAsync(Context, paginated.Build()); } } }
public static async Task ShowSpeciesInfoAsync(ICommandContext context, Species species) { if (await BotUtils.ReplyValidateSpeciesAsync(context, species)) { EmbedBuilder embed = new EmbedBuilder(); StringBuilder descriptionBuilder = new StringBuilder(); string embed_title = species.FullName; Color embed_color = Color.Blue; CommonName[] common_names = await SpeciesUtils.GetCommonNamesAsync(species); if (common_names.Count() > 0) { embed_title += string.Format(" ({0})", string.Join(", ", (object[])common_names)); } // Show generation only if generations are enabled. if (OurFoodChainBot.Instance.Config.GenerationsEnabled) { Generation gen = await GenerationUtils.GetGenerationByTimestampAsync(species.Timestamp); embed.AddField("Gen", gen is null ? "???" : gen.Number.ToString(), inline: true); } embed.AddField("Owner", await SpeciesUtils.GetOwnerOrDefaultAsync(species, context), inline: true); SpeciesZone[] zone_list = await SpeciesUtils.GetZonesAsync(species); if (zone_list.Count() > 0) { embed_color = Bot.DiscordUtils.ConvertColor((await ZoneUtils.GetZoneTypeAsync(zone_list .GroupBy(x => x.Zone.ZoneTypeId) .OrderBy(x => x.Count()) .Last() .Key)).Color); } string zones_value = new SpeciesZoneCollection(zone_list).ToString(SpeciesZoneCollectionToStringOptions.Default, Bot.DiscordUtils.MaxFieldLength); embed.AddField("Zone(s)", string.IsNullOrEmpty(zones_value) ? "None" : zones_value, inline: true); // Check if the species is extinct. using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM Extinctions WHERE species_id=$species_id;")) { cmd.Parameters.AddWithValue("$species_id", species.Id); DataRow row = await Database.GetRowAsync(cmd); if (!(row is null)) { embed_title = "[EXTINCT] " + embed_title; embed_color = Color.Red; string reason = row.Field <string>("reason"); long timestamp = (long)row.Field <decimal>("timestamp"); if (!string.IsNullOrEmpty(reason)) { descriptionBuilder.AppendLine(string.Format("**Extinct ({0}):** _{1}_\n", await BotUtils.TimestampToDateStringAsync(timestamp), reason)); } } } descriptionBuilder.Append(species.GetDescriptionOrDefault()); embed.WithTitle(embed_title); embed.WithThumbnailUrl(species.Picture); embed.WithColor(embed_color); if (!string.IsNullOrEmpty(OurFoodChainBot.Instance.Config.WikiUrlFormat)) { // Discord automatically encodes certain characters in URIs, which doesn't allow us to update the config via Discord when we have "{0}" in the URL. // Replace this with the proper string before attempting to call string.Format. string format = OurFoodChainBot.Instance.Config.WikiUrlFormat.Replace("%7B0%7D", "{0}"); embed.WithUrl(string.Format(format, Uri.EscapeUriString(GetWikiPageTitleForSpecies(species, common_names)))); } if (embed.Length + descriptionBuilder.Length > DiscordUtils.MaxEmbedLength) { // If the description puts us over the character limit, we'll paginate. int pageLength = DiscordUtils.MaxEmbedLength - embed.Length; List <EmbedBuilder> pages = new List <EmbedBuilder>(); foreach (string pageText in new StringPaginator(descriptionBuilder.ToString()) { MaxPageLength = pageLength }) { EmbedBuilder page = new EmbedBuilder(); page.WithTitle(embed.Title); page.WithThumbnailUrl(embed.ThumbnailUrl); page.WithFields(embed.Fields); page.WithDescription(pageText); pages.Add(page); } PaginatedMessageBuilder builder = new Bot.PaginatedMessageBuilder(pages); builder.AddPageNumbers(); builder.SetColor(embed_color); await DiscordUtils.SendMessageAsync(context, builder.Build()); } else { embed.WithDescription(descriptionBuilder.ToString()); await context.Channel.SendMessageAsync("", false, embed.Build()); } } }
public static async Task <Bot.PaginatedMessageBuilder> BuildRecentEventsEmbedAsync(long startTimestamp, long endTimestamp, TimeUnits timeUnit = 0) { // Get all species created within the given timespan. List <Species> new_species = new List <Species>(); TimeAmount time_amount = new TimeAmount(endTimestamp - startTimestamp, TimeUnits.Seconds); if (timeUnit != 0) { time_amount = time_amount.ConvertTo(timeUnit); } else { time_amount = time_amount.Reduce(); } using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM Species WHERE timestamp >= $start_ts AND timestamp < $end_ts")) { cmd.Parameters.AddWithValue("$start_ts", startTimestamp); cmd.Parameters.AddWithValue("$end_ts", endTimestamp); using (DataTable table = await Database.GetRowsAsync(cmd)) foreach (DataRow row in table.Rows) { new_species.Add(await SpeciesUtils.SpeciesFromDataRow(row)); } } new_species.Sort(); // Get all extinctions that occurred recently. List <Species> extinct_species = new List <Species>(); using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM Extinctions WHERE timestamp >= $start_ts AND timestamp < $end_ts")) { cmd.Parameters.AddWithValue("$start_ts", startTimestamp); cmd.Parameters.AddWithValue("$end_ts", endTimestamp); using (DataTable table = await Database.GetRowsAsync(cmd)) foreach (DataRow row in table.Rows) { extinct_species.Add(await BotUtils.GetSpeciesFromDb(row.Field <long>("species_id"))); } } extinct_species.Sort(); // Build embed. Bot.PaginatedMessageBuilder embed = new Bot.PaginatedMessageBuilder(); List <EmbedBuilder> pages = new List <EmbedBuilder>(); List <string> field_lines = new List <string>(); if (new_species.Count() > 0) { foreach (Species sp in new_species) { field_lines.Add(sp.FullName); } EmbedUtils.AddLongFieldToEmbedPages(pages, field_lines, fieldName: string.Format("New species ({0})", new_species.Count())); field_lines.Clear(); } if (extinct_species.Count() > 0) { foreach (Species sp in extinct_species) { field_lines.Add(sp.FullName); } EmbedUtils.AddLongFieldToEmbedPages(pages, field_lines, fieldName: string.Format("Extinctions ({0})", extinct_species.Count())); field_lines.Clear(); } embed.AddPages(pages); embed.SetTitle(string.Format("Recent events ({0})", time_amount.ToString())); embed.SetFooter(string.Empty); // remove page numbers added automatically embed.AddPageNumbers(); if (embed.FieldCount <= 0) { embed.SetDescription("No events"); } return(embed); }