diff --git a/ChaosBot/Discord/Modules/LodestoneCommands.cs b/ChaosBot/Discord/Modules/LodestoneCommands.cs index 0da5c63..1845133 100644 --- a/ChaosBot/Discord/Modules/LodestoneCommands.cs +++ b/ChaosBot/Discord/Modules/LodestoneCommands.cs @@ -25,32 +25,7 @@ namespace ChaosBot.Discord.Modules { CharacterDetailed character = LodestoneManager.GetCharacter(id); - var sb = new StringBuilder(); - var embed = new EmbedBuilder(); - - embed.WithColor(new Color(255, 255,0)); - embed.Title = $"Character Information"; - embed.Url = $"https://na.finalfantasyxiv.com/lodestone/character/{character.Character.ID}/"; - embed.ImageUrl = character.Character.Avatar; - embed.Footer = new EmbedFooterBuilder().WithText($"Lodestone ID {character.Character.ID}"); - - char genderIcon = character.Character.Gender == 1 ? '♂' : '♀'; - sb.AppendLine($"{character.Character.Name} {genderIcon} ({character.Character.Server})"); - sb.AppendLine($"Bio: {character.Character.Bio}"); - sb.AppendLine(); - sb.AppendLine($"Current Job: {character.Character.ActiveClassJob.Name} (level {character.Character.ActiveClassJob.Level})"); - sb.AppendLine(); - sb.AppendLine("All Jobs:"); - foreach (CharacterClassJob characterClassJob in character.Character.ClassJobs.ToArray()) - { - if (characterClassJob.Level == 0) continue; - sb.AppendLine($"{characterClassJob.Name} (level {characterClassJob.Level})"); - } - - /* - * Add the string to the Embed - */ - embed.Description = sb.ToString(); + var embed = BuildEmbedFromCharacter(character); /* * Reply with the Embed created above @@ -62,29 +37,16 @@ namespace ChaosBot.Discord.Modules _logger.Error($"InfoCommands.InfoCommand: Exception [{ex}] thrown, <[{ex.Message}]>."); } } - + [Command("lodestone character")] public async Task GetCharacter(string server, params string[] name) { try { - Character character = LodestoneManager.GetCharacter(server, string.Join(" ", name)); + CharacterDetailed character = LodestoneManager.GetCharacter(server, string.Join(" ", name)); + + var embed = BuildEmbedFromCharacter(character); - var sb = new StringBuilder(); - var embed = new EmbedBuilder(); - - embed.WithColor(new Color(255, 255,0)); - embed.Title = $"Character Information"; - embed.Url = $"https://na.finalfantasyxiv.com/lodestone/character/{character.ID}/"; - embed.ImageUrl = character.Avatar; - embed.Footer = new EmbedFooterBuilder().WithText($"Lodestone ID {character.ID}"); - sb.AppendLine($"{character.Name} ({character.Server})"); - - /* - * Add the string to the Embed - */ - embed.Description = sb.ToString(); - /* * Reply with the Embed created above */ @@ -152,18 +114,33 @@ namespace ChaosBot.Discord.Modules { try { - FreeCompany freeCompany = LodestoneManager.GetFreeCompany(server, name); + FreeCompanyDetailed freeCompany = LodestoneManager.GetFreeCompany(server, name); var sb = new StringBuilder(); var embed = new EmbedBuilder(); embed.WithColor(new Color(255, 255,0)); embed.Title = $"Free Company Information"; - embed.Url = $"https://na.finalfantasyxiv.com/lodestone/freecompany/{freeCompany.ID}/"; - embed.ImageUrl = freeCompany.Crest.First(); - embed.Footer = new EmbedFooterBuilder().WithText($"Lodestone ID {freeCompany.ID}"); - - sb.AppendLine($"{freeCompany.Name} ({freeCompany.Server})"); + embed.Url = $"https://na.finalfantasyxiv.com/lodestone/freecompany/{freeCompany.FreeCompany.ID}/"; + embed.ImageUrl = freeCompany.FreeCompany.Crest.First(); + embed.Footer = new EmbedFooterBuilder().WithText($"Lodestone ID {freeCompany.FreeCompany.ID}"); + + sb.AppendLine($"{freeCompany.FreeCompany.Name} ({freeCompany.FreeCompany.Server}, rank {freeCompany.FreeCompany.Rank})"); + sb.AppendLine($"{freeCompany.FreeCompany.Slogan}"); + sb.AppendLine(); + sb.AppendLine($"{freeCompany.FreeCompany.ActiveMemberCount} active members."); + sb.AppendLine($"Company estate {freeCompany.FreeCompany.Estate.Plot}"); + sb.AppendLine($"Pledged to Grand Company {freeCompany.FreeCompany.GrandCompany}"); + sb.AppendLine(); + + var rankCounts = freeCompany.FreeCompanyMembers.GroupBy(m => m.Rank).Select(g => new {Rank = g.Key, Count = g.Count()}) + .OrderBy(x => x.Rank); + + foreach (string rank in new List{"Council", "Mentor", "Member", "Initiate"}) + { + var rankCount = rankCounts.First(e => e.Rank == rank); + sb.AppendLine($"{rankCount.Count} members are of rank {rankCount.Rank} "); + } /* * Add the string to the Embed @@ -180,5 +157,61 @@ namespace ChaosBot.Discord.Modules _logger.Error($"InfoCommands.InfoCommand: Exception [{ex}] thrown, <[{ex.Message}]>."); } } + + private static EmbedBuilder BuildEmbedFromCharacter(CharacterDetailed character) + { + var sb = new StringBuilder(); + var embed = new EmbedBuilder(); + + embed.WithColor(new Color(255, 255, 0)); + embed.Title = $"Character Information"; + embed.Url = $"https://na.finalfantasyxiv.com/lodestone/character/{character.Character.ID}/"; + embed.ImageUrl = character.Character.Avatar; + embed.Footer = new EmbedFooterBuilder().WithText($"Lodestone ID {character.Character.ID}"); + + char genderIcon = character.Character.Gender == 1 ? '♂' : '♀'; + sb.AppendLine($"{character.Character.Name} {genderIcon} ({character.Character.Server})"); + sb.AppendLine($"Bio: {character.Character.Bio}"); + sb.AppendLine(); + sb.AppendLine( + $"Current Job: {LodestoneManager.Classes.GetValueOrDefault(character.Character.ActiveClassJob.UnlockedState.Name)?.Item1.ToString()} {character.Character.ActiveClassJob.Level}"); + sb.AppendLine(); + sb.AppendLine("All Jobs:"); + + sb.Append("```"); + List> classInfoList = new List>(); + foreach (CharacterClassJob characterClassJob in character.Character.ClassJobs.ToArray()) + { + if (characterClassJob.Level == 0) continue; + Tuple classInfo = + LodestoneManager.Classes.GetValueOrDefault(characterClassJob.UnlockedState.Name); + classInfoList.Add(new Tuple(classInfo.Item1, classInfo.Item2, characterClassJob.Level)); + } + + foreach (var classTypeList in classInfoList.GroupBy(ci => ci.Item2) + .Select(group => new {ClassType = @group.Key, classList = @group.ToArray()}).OrderBy(g => g.ClassType)) + { + sb.Append($"{classTypeList.ClassType.ToString()}:"); + + for (int i = 0; i < classTypeList.classList.Length; i++) + { + if ((i % 4) == 0) + sb.AppendLine(); + + Tuple classItem = classTypeList.classList[i]; + sb.Append(String.Format(" {0,3}: {1,2}", classItem.Item1, classItem.Item3)); + } + + sb.AppendLine("\n"); + } + + sb.Append("```"); + + /* + * Add the string to the Embed + */ + embed.Description = sb.ToString(); + return embed; + } } } \ No newline at end of file diff --git a/ChaosBot/Services/LodestoneManager.cs b/ChaosBot/Services/LodestoneManager.cs index f156d66..a2ebd7a 100644 --- a/ChaosBot/Services/LodestoneManager.cs +++ b/ChaosBot/Services/LodestoneManager.cs @@ -15,18 +15,61 @@ namespace ChaosBot.Services {Endpoints.FREECOMPANY_SEARCH, "freecompany/search"}, }; + public static readonly Dictionary> Classes = new Dictionary> + { + { "Marauder", new Tuple("MRD", ClassType.Tank) }, + { "Warrior", new Tuple("WAR", ClassType.Tank) }, + { "Gladiator", new Tuple("GLA", ClassType.Tank) }, + { "Paladin", new Tuple("PLD", ClassType.Tank) }, + { "Lancer", new Tuple("LNC", ClassType.Dps) }, + { "Dragoon", new Tuple("DRG", ClassType.Dps) }, + { "Pugilist", new Tuple("PGL", ClassType.Dps) }, + { "Monk", new Tuple("MNK", ClassType.Dps) }, + { "Rogue", new Tuple("ROG", ClassType.Dps) }, + { "Ninja", new Tuple("NIN", ClassType.Dps) }, + { "Archer", new Tuple("ARC", ClassType.Dps) }, + { "Bard", new Tuple("BRD", ClassType.Dps) }, + { "Thaumaturge", new Tuple("THM", ClassType.Dps) }, + { "Black Mage", new Tuple("BLM", ClassType.Dps) }, + { "Arcanist", new Tuple("ACN", ClassType.Dps) }, + { "Summoner", new Tuple("SMN", ClassType.Dps) }, + { "Scholar", new Tuple("SCH", ClassType.Healer) }, + { "Conjurer", new Tuple("CNJ", ClassType.Healer) }, + { "White Mage", new Tuple("WHM", ClassType.Healer) }, + { "Blue Mage (Limited Job)", new Tuple("BLU", ClassType.Dps) }, + { "Dark Knight", new Tuple("DRK", ClassType.Tank) }, + { "Astrologian", new Tuple("AST", ClassType.Healer) }, + { "Machinist", new Tuple("MCH", ClassType.Dps) }, + { "Samurai", new Tuple("SAM", ClassType.Dps) }, + { "Red Mage", new Tuple("RDM", ClassType.Dps) }, + { "Gunbreaker", new Tuple("GNB", ClassType.Tank) }, + { "Dancer", new Tuple("DNC", ClassType.Dps) }, + { "Miner", new Tuple("MIN", ClassType.Gathering) }, + { "Botanist", new Tuple("BTN", ClassType.Gathering) }, + { "Fisher", new Tuple("FSH", ClassType.Gathering) }, + { "Alchemist", new Tuple("ALC", ClassType.Gathering) }, + { "Armorer", new Tuple("ARM", ClassType.Crafting) }, + { "Blacksmith", new Tuple("BSM", ClassType.Crafting) }, + { "Carpenter", new Tuple("CRP", ClassType.Crafting) }, + { "Culinarian", new Tuple("CUL", ClassType.Crafting) }, + { "Goldsmith", new Tuple("GSM", ClassType.Crafting) }, + { "Leatherworker", new Tuple("LTW", ClassType.Crafting) }, + { "Weaver", new Tuple("WVR", ClassType.Crafting) } + }; + public static string GetEndpointPaths(Endpoints endpoint, params object[] parameters) { return string.Format(EndpointPaths.GetValueOrDefault(endpoint, string.Empty)!, parameters); } - public static Character GetCharacter(string server, string name) + public static CharacterDetailed + GetCharacter(string server, string name) { Dictionary parameters = new Dictionary {{"name", name}, {"server", server}}; PaginationWrapper characterWrapper = LodestoneHttpProxy.Fetch>(GetEndpointPaths(Endpoints.CHARACTER_SEARCH), parameters); - return characterWrapper.Results.First(); + return GetCharacter(characterWrapper.Results.First().ID); } public static CharacterDetailed GetCharacter(long id) @@ -37,13 +80,13 @@ namespace ChaosBot.Services return character; } - public static FreeCompany GetFreeCompany(string server, string name) + public static FreeCompanyDetailed GetFreeCompany(string server, string name) { Dictionary parameters = new Dictionary {{"name", name}, {"server", server}}; PaginationWrapper freeCompanyWrapper = LodestoneHttpProxy.Fetch>(GetEndpointPaths(Endpoints.FREECOMPANY_SEARCH), parameters); - return freeCompanyWrapper.Results.First(); + return GetFreeCompanyById(freeCompanyWrapper.Results.First().ID); } public static FreeCompanyDetailed GetFreeCompanyById(string id) { @@ -61,4 +104,13 @@ namespace ChaosBot.Services FREECOMPANY_SEARCH_BY_ID, FREECOMPANY_SEARCH } + + public enum ClassType + { + Tank, + Dps, + Healer, + Gathering, + Crafting + } } \ No newline at end of file