diff --git a/Core/Database.lua b/Core/Database.lua index aa1d9b7..50bb90c 100644 --- a/Core/Database.lua +++ b/Core/Database.lua @@ -230,6 +230,48 @@ function DB:SaveMailbox(mailboxData) end end +-- Add a single mail entry to a character's mailbox +function DB:AddMailToCharacter(name, realm, mailRow) + local fullName = name .. "-" .. (realm or playerRealm) + local char = Guda_DB.characters[fullName] + + if char then + if not char.mailbox then + char.mailbox = {} + end + + -- Check if this exact mail already exists (simplistic check) + local exists = false + for _, m in ipairs(char.mailbox) do + if m.sender == mailRow.sender and m.subject == mailRow.subject and m.money == mailRow.money then + if (not m.item and not mailRow.item) or (m.item and mailRow.item and m.item.name == mailRow.item.name and m.item.count == mailRow.item.count) then + exists = true + -- Update link/itemID if missing in existing but present in new + if mailRow.item and m.item then + if not m.item.link and mailRow.item.link then + m.item.link = mailRow.item.link + addon:Debug("Updated link for existing mail item") + end + if not m.item.itemID and mailRow.item.itemID then + m.item.itemID = mailRow.item.itemID + addon:Debug("Updated itemID for existing mail item") + end + end + break + end + end + end + + if not exists then + table.insert(char.mailbox, 1, mailRow) -- Add to beginning + char.lastUpdate = time() + addon:Debug("Added outgoing mail to %s's mailbox", fullName) + return true + end + end + return false +end + -- Get all characters (optionally filter by faction and/or realm) function DB:GetAllCharacters(sameFactionOnly, currentRealmOnly) local chars = {} diff --git a/Core/Utils.lua b/Core/Utils.lua index 05cd468..9951ea7 100644 --- a/Core/Utils.lua +++ b/Core/Utils.lua @@ -101,10 +101,13 @@ scanTooltip:SetOwner(WorldFrame, "ANCHOR_NONE") -- Get item link from mailbox attachment (WoW 1.12.1 workaround) function Utils:GetInboxItemLink(index, itemIndex) + -- Try global function first (if it exists on this server/version) + if GetInboxItemLink then + local link = GetInboxItemLink(index) + if link then return link end + end + -- In 1.12.1, GameTooltip:GetHyperlink() does not exist. - -- Actually, in 1.12.1, there's no official API to get the link from a mailbox item - -- if GetInboxItemLink(index) is not available (it's often NOT available in Vanilla). - -- Let's try to use GetItemInfo(name) as the primary way. local name = GetInboxItem(index, itemIndex) if name then @@ -114,9 +117,6 @@ function Utils:GetInboxItemLink(index, itemIndex) end end - -- Fallback: If we still don't have it, we might try to scan the tooltip for the name - -- but GetInboxItem already gave us the name. - return nil end diff --git a/Data/MailboxScanner.lua b/Data/MailboxScanner.lua index e981cf0..7f2e6d6 100644 --- a/Data/MailboxScanner.lua +++ b/Data/MailboxScanner.lua @@ -48,11 +48,36 @@ function MailboxScanner:ScanMailItemRows(index) count = count or 1, quality = quality or 0, name = name, + itemID = addon.Modules.Utils:ExtractItemID(itemLink), } + -- Fallback: If link/itemID is missing, try to recover from existing database + if not itemData.itemID or not itemData.link then + local existingMailbox = addon.Modules.DB:GetCharacterMailbox(addon.Modules.DB:GetPlayerFullName()) + for _, oldMail in ipairs(existingMailbox) do + -- Match by sender, subject and item name + if oldMail.sender == sender and oldMail.subject == subject and oldMail.item and oldMail.item.name == name then + if not itemData.link and oldMail.item.link then + itemData.link = oldMail.item.link + addon:Debug("Recovered link from database for %s", name) + end + if not itemData.itemID and oldMail.item.itemID then + itemData.itemID = oldMail.item.itemID + addon:Debug("Recovered itemID from database for %s", name) + end + if itemData.link and itemData.itemID then break end + end + end + end + + -- If we still don't have itemID but have a link (or vice versa), fix it + if itemData.link and not itemData.itemID then + itemData.itemID = addon.Modules.Utils:ExtractItemID(itemData.link) + end + -- If we have a link, try to get more detailed info - if itemLink then - local itemName, link, itemQuality, iLevel, itemCategory, itemType, itemStackCount, itemSubType, itemTexture, itemEquipLoc, itemSellPrice = addon.Modules.Utils:GetItemInfo(itemLink) + if itemData.link then + local itemName, link, itemQuality, iLevel, itemCategory, itemType, itemStackCount, itemSubType, itemTexture, itemEquipLoc, itemSellPrice = addon.Modules.Utils:GetItemInfo(itemData.link) if itemName then itemData.name = itemName itemData.quality = itemQuality or itemData.quality @@ -112,8 +137,73 @@ function MailboxScanner:SaveToDatabase() addon:Debug("Mailbox data saved") end +-- Handle outgoing mail +function MailboxScanner:OnSendMail(recipient, subject, body) + if not recipient or recipient == "" then return end + + -- In WoW 1.12.1, SendMail(recipient, subject, body) is the signature. + -- To get the attached item, we use GetSendMailItem(). + -- GetSendMailItem() returns: name, texture, count, quality + local name, texture, count, quality = GetSendMailItem() + local moneyAmount = GetSendMailMoney() + + local itemData = nil + if name then + local _, link = GetItemInfo(name) + itemData = { + name = name, + texture = texture or "Interface\\Icons\\INV_Misc_Bag_08", + count = count or 1, + quality = quality or 0, + link = link, + itemID = addon.Modules.Utils:ExtractItemID(link), + } + + -- Try to get more info if it's in cache + local itemName, retLink, itemQuality, iLevel, itemCategory, itemType, itemStackCount, itemSubType, itemTexture, itemEquipLoc, itemSellPrice = addon.Modules.Utils:GetItemInfo(name) + if itemName then + itemData.link = retLink or itemData.link + itemData.itemID = addon.Modules.Utils:ExtractItemID(itemData.link) or itemData.itemID + itemData.quality = itemQuality or itemData.quality + itemData.iLevel = iLevel + itemData.type = itemType + itemData.class = itemCategory + itemData.subclass = itemSubType + itemData.equipSlot = itemEquipLoc + if itemTexture then itemData.texture = itemTexture end + end + + -- Double check itemID + if not itemData.itemID and itemData.link then + itemData.itemID = addon.Modules.Utils:ExtractItemID(itemData.link) + end + end + + if itemData or moneyAmount > 0 then + local mailRow = { + sender = UnitName("player"), + subject = (subject and subject ~= "") and subject or "No Subject", + money = moneyAmount, + CODAmount = 0, + daysLeft = 30, -- Outgoing mail typically has 30 days + hasItem = itemData ~= nil, + item = itemData, + wasRead = false, + } + + addon.Modules.DB:AddMailToCharacter(recipient, nil, mailRow) + end +end + -- Initialize mailbox scanner function MailboxScanner:Initialize() + -- Hook SendMail to capture outgoing mail to alts + local originalSendMail = SendMail + SendMail = function(recipient, subject, body) + MailboxScanner:OnSendMail(recipient, subject, body) + return originalSendMail(recipient, subject, body) + end + -- Mailbox opened addon.Modules.Events:OnMailShow(function() mailboxOpen = true @@ -155,7 +245,7 @@ function MailboxScanner:Initialize() -- Mailbox closed addon.Modules.Events:OnMailClosed(function() -- Final save on close - self:SaveToDatabase() + MailboxScanner:SaveToDatabase() mailboxOpen = false addon:Debug("Mailbox closed") end, "MailboxScanner") diff --git a/UI/ItemButton.lua b/UI/ItemButton.lua index 0f44585..758fa5d 100644 --- a/UI/ItemButton.lua +++ b/UI/ItemButton.lua @@ -982,13 +982,19 @@ function Guda_ItemButton_OnEnter(self) -- Mailbox tooltip handling if self.isMail then local currentPlayerName = addon.Modules.DB:GetPlayerFullName() - if (not self.otherChar or self.otherChar == currentPlayerName) and self.mailIndex then - -- Live mailbox for current character + local isMailboxOpen = addon.Modules.MailboxScanner and addon.Modules.MailboxScanner:IsMailboxOpen() + + if (not self.otherChar or self.otherChar == currentPlayerName) and self.mailIndex and isMailboxOpen then + -- Live mailbox for current character (only when mailbox is actually open) GameTooltip:SetInboxItem(self.mailIndex, self.mailItemIndex or 1) - elseif self.itemData and self.itemData.link then - -- Read-only / other character mailbox - GameTooltip.GudaViewedCharacter = self.otherChar - GameTooltip:SetHyperlink(self.itemData.link) + elseif self.itemData and (self.itemData.link or self.itemData.itemID) then + -- Read-only / other character mailbox OR current character mailbox when closed + GameTooltip.GudaViewedCharacter = self.otherChar or currentPlayerName + if self.itemData.link then + GameTooltip:SetHyperlink(self.itemData.link) + else + GameTooltip:SetHyperlink("item:" .. self.itemData.itemID .. ":0:0:0") + end elseif self.itemData and self.itemData.name then -- Money or generic mail GameTooltip:AddLine(self.itemData.name, 1, 1, 1)