Quantcast

New Mail Grab System

Xruptor [09-15-16 - 18:33]
New Mail Grab System
Filename
xanAutoMail.lua
diff --git a/xanAutoMail.lua b/xanAutoMail.lua
index ac61e99..4f7c3f5 100644
--- a/xanAutoMail.lua
+++ b/xanAutoMail.lua
@@ -6,21 +6,18 @@ local DB_PLAYER
 local DB_RECENT
 local currentPlayer
 local currentRealm
-local inboxAllButton
-local old_InboxFrame_OnClick
-local triggerStop = false
-local numInboxItems = 0
-local timeChk, timeDelay = 0, 1
-local stopLoop = 10
-local loopChk = 0
-local skipCount = 0
-local moneyCount = 0
-
 local origHook = {}
+local inboxAllButton
+local inboxInfoText

 local xanAutoMail = CreateFrame("frame","xanAutoMailFrame",UIParent)
 xanAutoMail:SetScript("OnEvent", function(self, event, ...) if self[event] then return self[event](self, event, ...) end end)

+local debugf = tekDebug and tekDebug:GetFrame("xanAutoMail")
+local function Debug(...)
+    if debugf then debugf:AddMessage(string.join(", ", tostringall(...))) end
+end
+
 --[[------------------------
 	CORE
 --------------------------]]
@@ -36,7 +33,9 @@ function xanAutoMail:PLAYER_LOGIN()
 	--increase the mailbox history lines to 15
 	SendMailNameEditBox:SetHistoryLines(15)

-	--do the hooks
+	--HOOKS FOR CHARACTER NAME HISTORY
+	---------------------------------
+	---------------------------------
 	origHook["SendMailFrame_Reset"] = SendMailFrame_Reset
 	SendMailFrame_Reset = self.SendMailFrame_Reset

@@ -51,17 +50,25 @@ function xanAutoMail:PLAYER_LOGIN()
 	origHook[SendMailNameEditBox]["OnChar"] = SendMailNameEditBox:GetScript("OnChar")
 	SendMailNameEditBox:SetScript("OnEditFocusGained", self.OnEditFocusGained)
 	SendMailNameEditBox:SetScript("OnChar", self.OnChar)
+	---------------------------------
+	---------------------------------

 	--make the open all button
 	inboxAllButton = CreateFrame("Button", "xanAutoMail_OpenAllBTN", InboxFrame, "UIPanelButtonTemplate")
 	inboxAllButton:SetWidth(100)
 	inboxAllButton:SetHeight(20)
-	inboxAllButton:SetPoint("CENTER", InboxFrame, "TOP", 0, -55)
+	inboxAllButton:SetPoint("CENTER", InboxFrame, "TOP", -80, -55)
 	inboxAllButton:SetText("Open All")
-	inboxAllButton:SetScript("OnClick", function() xanAutoMail.GetMail() end)
+	inboxAllButton:SetScript("OnClick", function() xanAutoMail.StartMailGrab() end)
+
+	inboxInfoText = InboxFrame:CreateFontString("xanAutoMail_InfoText", "ARTWORK", "GameFontNormalSmall")
+	inboxInfoText:SetJustifyH("LEFT")
+	inboxInfoText:SetFontObject("GameFontNormal")
+	inboxInfoText:SetPoint("TOPLEFT", inboxAllButton, "TOPRIGHT", 5, -5)

 	self:UnregisterEvent("PLAYER_LOGIN")
 	self.PLAYER_LOGIN = nil
+
 end

 function xanAutoMail:StartupDB()
@@ -80,6 +87,11 @@ function xanAutoMail:StartupDB()
 	if DB_PLAYER[currentPlayer] == nil then DB_PLAYER[currentPlayer] = true end
 end

+
+---------------------------------------------------
+---------------CHARACTER NAME DB ------------------
+---------------------------------------------------
+
 --This is called when mailed is sent
 function xanAutoMail:SendMailFrame_Reset()

@@ -189,10 +201,21 @@ function xanAutoMail:AutoComplete_Update(editBoxText, utf8Position, ...)
 	end
 end

+---------------------------------------------------
+---------------------------------------------------
+---------------------------------------------------
+
 --[[------------------------
 	OPEN ALL MAIL
 --------------------------]]

+local delayCount = {}
+local moneyCount = 0
+local errorCount = 0
+local errorCheckCount = 0
+local currentStatus = "STOP"
+
+xanAutoMail:RegisterEvent("MAIL_CLOSED")
 xanAutoMail:RegisterEvent("MAIL_INBOX_UPDATE")
 xanAutoMail:RegisterEvent("MAIL_SHOW")

@@ -220,7 +243,7 @@ local function colorMoneyText(value)
 	end
 end

-local function bagCheck()
+local function freeSpace()
 	local totalFree = 0
 	for i=0, NUM_BAG_SLOTS do
 		local numberOfFreeSlots = GetContainerNumFreeSlots(i)
@@ -229,120 +252,191 @@ local function bagCheck()
 	return totalFree
 end

-local function mailLoop(this, arg1)
-	timeChk = timeChk + arg1
-	if triggerStop then return end
-
-	if (timeChk > timeDelay) then
-		timeChk = 0
-
-		--check for last or no messages
-		if numInboxItems <= 0 then
-			--double check that there aren't anymore mail items
-			--we use a loop check just in case to prevent infinite loops
-			if GetInboxNumItems() > 0 and skipCount ~= GetInboxNumItems() and loopChk < stopLoop then
-				loopChk = loopChk + 1
-				numInboxItems = GetInboxNumItems()
-			else
-				triggerStop = true
-				xanAutoMail:StopMail()
-				return
+local function inboxFullCheck()
+	--sometimes the mailbox is full, if this happens we have to make changes to the button position
+	local nItem, nTotal = GetInboxNumItems()
+	if nItem and nTotal then
+		if ( nTotal > nItem) or InboxTooMuchMail:IsVisible() and not inboxAllButton.movedBottom then
+			inboxAllButton:ClearAllPoints()
+			inboxAllButton:SetPoint("CENTER", InboxFrame, "BOTTOM", -60, 100)
+			inboxAllButton.movedBottom = true
+			inboxInfoText:ClearAllPoints()
+			inboxInfoText:SetPoint("TOPLEFT", inboxAllButton, "TOPRIGHT", 5, -5)
+		elseif (( nTotal < nItem) or not InboxTooMuchMail:IsVisible()) and inboxAllButton.movedBottom then
+			inboxAllButton.movedBottom = nil
+			inboxAllButton:ClearAllPoints()
+			inboxAllButton:SetPoint("CENTER", InboxFrame, "TOP", -80, -55)
+			inboxInfoText:ClearAllPoints()
+			inboxInfoText:SetPoint("TOPLEFT", inboxAllButton, "TOPRIGHT", 5, -5)
+		end
+	end
+end
+
+xanAutoMail:SetScript("OnUpdate",
+	function( self, elapsed )
+		if #delayCount > 0 then
+			for i = #delayCount, 1, -1 do
+				if delayCount[i].endTime and delayCount[i].endTime <= GetTime() then
+					local func = delayCount[i].callbackFunction
+					tremove(delayCount, i)
+					func()
+				end
 			end
 		end
+	end
+)
+
+function xanAutoMail:Delay(name, duration, callbackFunction, force)
+	if not force and currentStatus == "STOP" then return end
+	for k, q in ipairs(delayCount) do
+		if q.name == name then
+			--don't run the same delay more than once
+			return
+		end
+	end
+	tinsert(delayCount, {name=name, duration=duration, endTime=(GetTime()+duration), callbackFunction=callbackFunction})
+end
+
+function xanAutoMail:UpdateInfoText()
+	local nItem, nTotal = GetInboxNumItems()
+	if nTotal == nItem then
+		inboxInfoText:SetText(format("Showing all %d mail.", nItem))
+	else
+		inboxInfoText:SetText(format("Showing %d of %d mail.", nItem, nTotal))
+	end
+	--hide the stupid icon if necessary
+	if nTotal <= 0 and MiniMapMailFrame:IsVisible() then
+		MiniMapMailFrame:Hide()
+	end
+end
+
+function xanAutoMail:MAIL_SHOW()
+	inboxFullCheck()
+	CheckInbox()
+	inboxInfoText:SetText("Waiting...")
+	xanAutoMail:Delay("mailInfoText", 1, xanAutoMail.UpdateInfoText, true)
+end
+
+function xanAutoMail:MAIL_CLOSED()
+	inboxFullCheck()
+	delayCount = {} --reset any delay in queue
+	inboxInfoText:SetText("")
+end
+
+function xanAutoMail:MAIL_INBOX_UPDATE()
+	if currentStatus == "STOP" then return end
+	inboxFullCheck()
+	xanAutoMail:Delay("mailGrabNextItem", 0.2, xanAutoMail.GrabNextMailItem)
+end

-		--lets get the mail
-		local _, _, _, _, money, COD, _, numItems, wasRead, _, _, _, isGM = GetInboxHeaderInfo(numInboxItems)
+function xanAutoMail:UI_ERROR_MESSAGE(event, arg1)
+	local stopMailGrab = false
+	if arg1 == ERR_MAIL_DATABASE_ERROR then
+		DEFAULT_CHAT_FRAME:AddMessage("xanAutoMail: (ERROR) There was a mailbox database error from the server.")
+		stopMailGrab = true
+	elseif arg1 == ERR_INV_FULL then
+		DEFAULT_CHAT_FRAME:AddMessage("xanAutoMail: (ERROR) Your inventory is full.")
+		stopMailGrab = true
+	elseif arg1 == ERR_ITEM_MAX_COUNT then
+		DEFAULT_CHAT_FRAME:AddMessage("xanAutoMail: (ERROR) Cannot loot anymore unique items from Mailbox.")
+	end
+
+	if stopMailGrab then
+		xanAutoMail:StopMailGrab()
+		return
+	end
+end
+
+function xanAutoMail:GrabNextMailItem()
+	if currentStatus == "STOP" then return end
+
+	--do inbox check
+	if currentStatus == "CHECK" then
+		CheckInbox()
+		currentStatus = "SKIPCHECK"
+		xanAutoMail:Delay("mailGrabNextItem", 1, xanAutoMail.GrabNextMailItem)
+		return
+	end
+
+	local nItem, nTotal = GetInboxNumItems()
+
+	xanAutoMail:UpdateInfoText()
+
+	--check to see if the last messages were read or if we have nothing to work with
+	if nTotal == errorCount or nTotal <= 0 or errorCheckCount > 10 then
+		xanAutoMail:StopMailGrab()
+		return
+	elseif freeSpace() < 1 then
+		xanAutoMail:StopMailGrab()
+		DEFAULT_CHAT_FRAME:AddMessage("xanAutoMail: (ERROR) Your inventory is full.")
+		return
+	elseif nItem <= 0 and nTotal > 0 then
+		--if we still have something to work with then fire in another 60 seconds
+		currentStatus = "CHECK"
+		errorCheckCount = 0
+		xanAutoMail:Delay("mailInboxCheck", 60, xanAutoMail.GrabNextMailItem)
+		inboxInfoText:SetText("Waiting 60 seconds")
+		DEFAULT_CHAT_FRAME:AddMessage("xanAutoMail: Waiting 60 seconds for next mail batch.")
+		return
+	end
+
+	errorCount = 0
+
+	for i = 1, nItem do
+		local _, _, _, _, money, COD, _, numItems, wasRead, _, _, _, isGM = GetInboxHeaderInfo(i)

 		if money > 0 or (numItems and numItems > 0) and COD <= 0 and not isGM then
-			--stop the loop if the mail was already read
-			if wasRead and loopChk > 0 then
-				triggerStop = true
-				xanAutoMail:StopMail()
-				return
-			elseif bagCheck() < 1 then
-				triggerStop = true
-				xanAutoMail:StopMail()
-				DEFAULT_CHAT_FRAME:AddMessage("xanAutoMail: Your bags are full")
+			if wasRead then
+				errorCount = errorCount + 1
 			else
 				if money > 0 then moneyCount = moneyCount + money end
-				AutoLootMailItem(numInboxItems)
+				AutoLootMailItem(i)
+				--we looted something so lets wait for next update
+				return
 			end
 		else
-			skipCount = skipCount + 1
+			errorCount = errorCount + 1
 		end
-
-		--decrease count
-		numInboxItems = numInboxItems - 1
+	end
+
+	--if absolutely nothing happened then exit the loop just in case
+	if errorCount <= 0 then
+		xanAutoMail:StopMailGrab()
+		return
+	else
+		--there was an error so lets try to grab again just in case our total = total errors
+		xanAutoMail:Delay("mailGrabNextItem", 0.2, xanAutoMail.GrabNextMailItem)
+		errorCheckCount = errorCheckCount + 1 --this is another emergency stop, don't do more than 10 error checks
 	end
 end

-function xanAutoMail:GetMail()
+function xanAutoMail:StartMailGrab()
 	if GetInboxNumItems() == 0 then return end
-
-	xanAutoMail_OpenAllBTN:Disable() --disable the button to prevent further clicks
-	triggerStop = false
-	timeChk, timeDelay = 0, 0.5
-	loopChk = 0
-	skipCount = 0
-	moneyCount = 0
-	numInboxItems = GetInboxNumItems()
-
-	old_InboxFrame_OnClick = InboxFrame_OnClick
-	InboxFrame_OnClick = function() end
+	currentStatus = "START"
+	inboxAllButton:Disable()

 	--register for inventory full error
 	xanAutoMail:RegisterEvent("UI_ERROR_MESSAGE")

-	--initiate the loop
-	xanAutoMail:SetScript("OnUpdate", mailLoop)
+	moneyCount = 0
+	errorCount = 0
+	errorCheckCount = 0
+	xanAutoMail:Delay("mailGrabNextItem", 0.2, xanAutoMail.GrabNextMailItem)
 end

-function xanAutoMail:StopMail()
-	xanAutoMail_OpenAllBTN:Enable() --enable the button again
-	if old_InboxFrame_OnClick then
-		InboxFrame_OnClick = old_InboxFrame_OnClick
-		old_InboxFrame_OnClick = nil
-	end
+function xanAutoMail:StopMailGrab()
+	currentStatus = "STOP"
+	delayCount = {}
+	inboxAllButton:Enable()
 	xanAutoMail:UnregisterEvent("UI_ERROR_MESSAGE")
-	xanAutoMail:SetScript("OnUpdate", nil)
-	--check for money output
 	if moneyCount > 0 then
 		DEFAULT_CHAT_FRAME:AddMessage("xanAutoMail: Total money from mailbox ["..colorMoneyText(moneyCount).."]")
 	end
+
+	CheckInbox()
+	xanAutoMail:Delay("mailInfoText", 1, xanAutoMail.UpdateInfoText, true)
 end

---this is to stop the loop if our bags are filled
-function xanAutoMail:UI_ERROR_MESSAGE(event, arg1)
-	if arg1 == ERR_INV_FULL then
-		triggerStop = true
-		xanAutoMail:StopMail()
-		DEFAULT_CHAT_FRAME:AddMessage("xanAutoMail: Your bags are full")
-	end
-end
-
---sometimes the mailbox is full, if this happens we have to make changes to the button position
-local function inboxFullCheck()
-	local nItem, nTotal = GetInboxNumItems()
-	if nItem and nTotal then
-		if ( nTotal > nItem) or InboxTooMuchMail:IsVisible() and not inboxAllButton.movedBottom then
-			inboxAllButton:ClearAllPoints()
-			inboxAllButton:SetPoint("CENTER", InboxFrame, "BOTTOM", -10, 100)
-			inboxAllButton.movedBottom = true
-		elseif (( nTotal < nItem) or not InboxTooMuchMail:IsVisible()) and inboxAllButton.movedBottom then
-			inboxAllButton.movedBottom = nil
-			inboxAllButton:ClearAllPoints()
-			inboxAllButton:SetPoint("CENTER", InboxFrame, "TOP", 0, -55)
-		end
-	end
-end
-
-function xanAutoMail:MAIL_INBOX_UPDATE()
-	inboxFullCheck()
-end
-
-function xanAutoMail:MAIL_SHOW()
-	inboxFullCheck()
-end

 if IsLoggedIn() then xanAutoMail:PLAYER_LOGIN() else xanAutoMail:RegisterEvent("PLAYER_LOGIN") end