From 2e202053a88565776eb415cbc5574f6c304689be Mon Sep 17 00:00:00 2001 From: Anna Clemens Date: Tue, 7 Dec 2021 17:06:14 -0500 Subject: [PATCH] feat: add eorzea collection import --- Glamaholic/Ui/MainInterface.cs | 139 +++++++++++++++++++++++++++------ Glamaholic/Util.cs | 57 ++++++++++++++ 2 files changed, 173 insertions(+), 23 deletions(-) diff --git a/Glamaholic/Ui/MainInterface.cs b/Glamaholic/Ui/MainInterface.cs index ad08613..d23a0da 100755 --- a/Glamaholic/Ui/MainInterface.cs +++ b/Glamaholic/Ui/MainInterface.cs @@ -2,7 +2,11 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Net; +using System.Net.Http; using System.Numerics; +using System.Threading.Tasks; +using Dalamud; using Dalamud.Interface; using Dalamud.Interface.Colors; using ImGuiNET; @@ -34,9 +38,9 @@ namespace Glamaholic.Ui { private PluginUi Ui { get; } private List Items { get; } private List FilteredItems { get; set; } + private Dictionary Stains { get; } private bool _visible; - private string _plateName = string.Empty; private int _dragging = -1; private int _selectedPlate = -1; private bool _scrollToSelected; @@ -51,6 +55,8 @@ namespace Glamaholic.Ui { private SavedPlate? _editingPlate; private string _itemFilter = string.Empty; private string _dyeFilter = string.Empty; + private string _ecImport = string.Empty; + private volatile bool _ecImporting; internal MainInterface(PluginUi ui) { this.Ui = ui; @@ -60,6 +66,11 @@ namespace Glamaholic.Ui { .Where(row => row.EquipSlotCategory.Row is not 0 && row.EquipSlotCategory.Value!.SoulCrystal == 0) .ToList(); this.FilteredItems = this.Items; + + this.Stains = this.Ui.Plugin.DataManager.GetExcelSheet(ClientLanguage.English)! + .Where(row => row.RowId != 0) + .Where(row => !string.IsNullOrWhiteSpace(row.Name.RawString)) + .ToDictionary(row => row.Name.RawString, row => (byte) row.RowId); } internal void Open() { @@ -101,28 +112,6 @@ namespace Glamaholic.Ui { this.SwitchPlate(this.Ui.Plugin.Config.Plates.Count - 1, true); } - if (ImGui.BeginMenu("Add from current plate")) { - if (Util.DrawTextInput("current-name", ref this._plateName, message: "Input name and press Enter to save.")) { - var current = GameFunctions.CurrentPlate; - if (current != null) { - var plate = new SavedPlate(this._plateName) { - Items = current, - }; - - this.Ui.Plugin.Config.AddPlate(plate); - - this._plateName = string.Empty; - this.Ui.Plugin.SaveConfig(); - } - } - - if (ImGui.IsWindowAppearing()) { - ImGui.SetKeyboardFocusHere(); - } - - ImGui.EndMenu(); - } - if (ImGui.BeginMenu("Import")) { if (Util.DrawTextInput("import-input", ref this._importInput, 2048, "Press Enter to import.")) { try { @@ -153,6 +142,23 @@ namespace Glamaholic.Ui { ImGui.EndMenu(); } + if (ImGui.BeginMenu("Import from Eorzea Collection")) { + const string msg = "Enter an Eorzea Collection glamour URL and press Enter."; + if (Util.DrawTextInput("ec-import", ref this._ecImport, message: msg, flags: ImGuiInputTextFlags.AutoSelectAll) && !this._ecImporting) { + this.ImportEorzeaCollection(); + } + + if (ImGui.IsWindowAppearing()) { + ImGui.SetKeyboardFocusHere(); + } + + if (this._ecImporting) { + ImGui.TextUnformatted("Working..."); + } + + ImGui.EndMenu(); + } + ImGui.EndMenu(); } @@ -209,6 +215,93 @@ namespace Glamaholic.Ui { ImGui.EndMenuBar(); } + private void ImportEorzeaCollection() { + try { + var uri = new Uri(this._ecImport); + if (uri.Host != "ffxiv.eorzeacollection.com") { + return; + } + } catch (Exception) { + return; + } + + this._ecImporting = true; + + Task.Run(async () => { + var items = new Dictionary(); + + var client = new HttpClient(); + var resp = await client.GetAsync(this._ecImport); + var html = await resp.Content.ReadAsStringAsync(); + + var titleParts = html.Split(""); + var glamName = titleParts.Length > 1 + ? titleParts[1].Split('<')[0].Split('|')[0].Trim() + : "Eorzea Collection plate"; + + var parts = html.Split("c-gear-slot-item-name"); + foreach (var part in parts) { + var nameParts = part.Split('>'); + if (nameParts.Length < 2) { + continue; + } + + var rawName = nameParts[1].Split('<')[0].Trim(); + var name = WebUtility.HtmlDecode(rawName); + if (string.IsNullOrWhiteSpace(name)) { + continue; + } + + var item = this.Items.Find(item => item.Name == name); + if (item == null) { + continue; + } + + var slot = Util.GetSlot(item); + if (slot is PlateSlot.RightRing && items.ContainsKey(PlateSlot.RightRing)) { + slot = PlateSlot.LeftRing; + } + + if (slot == null) { + continue; + } + + var stainId = this.GetStainIdFromPart(part); + items[slot.Value] = new SavedGlamourItem { + ItemId = item.RowId, + StainId = stainId, + }; + } + + this._ecImporting = false; + + var plate = new SavedPlate(glamName) { + Items = items, + }; + this.Ui.Plugin.Config.AddPlate(plate); + this.Ui.Plugin.SaveConfig(); + this.SwitchPlate(this.Ui.Plugin.Config.Plates.Count - 1, true); + this._ecImport = string.Empty; + }); + } + + private byte GetStainIdFromPart(string part) { + var stainParts = part.Split('⬤'); + if (stainParts.Length <= 1) { + return 0; + } + + var stainSubParts = stainParts[1].Split('>'); + if (stainSubParts.Length <= 1) { + return 0; + } + + var rawStainName = stainSubParts[1].Split('<')[0].Trim(); + var stainName = WebUtility.HtmlDecode(rawStainName); + this.Stains.TryGetValue(stainName, out var stainId); + return stainId; + } + private void DrawPlateList() { if (!ImGui.BeginChild("plate list", new Vector2(205 * ImGuiHelpers.GlobalScale, 0), true)) { return; diff --git a/Glamaholic/Util.cs b/Glamaholic/Util.cs index 7b106cd..b306a98 100755 --- a/Glamaholic/Util.cs +++ b/Glamaholic/Util.cs @@ -66,6 +66,63 @@ namespace Glamaholic { ImGui.PopTextWrapPos(); } + internal static PlateSlot? GetSlot(Item item) { + var category = item.EquipSlotCategory.Value; + if (category == null) { + return null; + } + + if (category.MainHand > 0) { + return PlateSlot.MainHand; + } + + if (category.OffHand > 0) { + return PlateSlot.OffHand; + } + + if (category.Head > 0) { + return PlateSlot.Head; + } + + if (category.Body > 0) { + return PlateSlot.Body; + } + + if (category.Gloves > 0) { + return PlateSlot.Hands; + } + + if (category.Legs > 0) { + return PlateSlot.Legs; + } + + if (category.Feet > 0) { + return PlateSlot.Feet; + } + + if (category.Ears > 0) { + return PlateSlot.Ears; + } + + if (category.Neck > 0) { + return PlateSlot.Neck; + } + + if (category.Wrists > 0) { + return PlateSlot.Wrists; + } + + if (category.FingerR > 0) { + return PlateSlot.RightRing; + } + + if (category.FingerL > 0) { + return PlateSlot.LeftRing; + } + + return null; + } + internal static bool MatchesSlot(EquipSlotCategory category, PlateSlot slot) { return slot switch { PlateSlot.MainHand => category.MainHand > 0,