changeset 144:03e108d12ef1

Ticket 45 - Added the ability suppress COD warnings when mailing to characters on other accounts in Altoholic/DataStore. Instead of sending COD, ItemAuditor will send tracking info in the message. Thanks to Zerotorescue for giving me the solution to detect whether or not Postal or MailOpener is processing. It was the last step holding this back from being released.
author Asa Ayers <Asa.Ayers@Gmail.com>
date Sat, 09 Oct 2010 00:21:06 -0700
parents 4d7955b2d240
children b15c19200af8
files .pkgmeta CHANGELOG.txt Core.lua Modules/Events.lua embeds.xml
diffstat 5 files changed, 162 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/.pkgmeta	Wed Oct 06 22:11:26 2010 -0700
+++ b/.pkgmeta	Sat Oct 09 00:21:06 2010 -0700
@@ -29,6 +29,12 @@
     Libs/AceTimer-3.0:
         url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceTimer-3.0
         tag: latest
+    Libs/AceSerializer-3.0:
+        url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceSerializer-3.0
+        tag: latest
+    Libs/AceTimer-3.0:
+        url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceTimer-3.0
+        tag: latest
     Libs/lib-st: 
         url: svn://svn.wowace.com/wow/lib-st/mainline/trunk
         tag: latest
@@ -37,12 +43,26 @@
         tag: latest
 
 
-required-dependencies: Altoholic
+required-dependencies:
+    - datastore
+    - datastore_containers
+    - datastore_auctions
+    - datastore_inventory
+    - datastore_mails
+    - datastore_currencies
+    - datastore_characters
 
 optional-dependencies:
-    - QuickAuctions
-    - Skillet
-    - LilSparkysWorkshop
+    - quickauctions
+    - skillet
+    - lilsparkysworkshop
+    - auctionator
+    - auctioneer
+    - auctionlite
+    - auctionmaster
+    - arkinventory
+    - devtools
+    - wowunit
 
 manual-changelog: CHANGELOG.txt
 
--- a/CHANGELOG.txt	Wed Oct 06 22:11:26 2010 -0700
+++ b/CHANGELOG.txt	Sat Oct 09 00:21:06 2010 -0700
@@ -1,3 +1,7 @@
+2010-10-08  Asa Ayers  <Asa.Ayers@Gmail.com>
+
+- Ticket 45 - Added the ability suppress COD warnings when mailing to characters on other accounts in Altoholic/DataStore. Instead of sending COD, ItemAuditor will send tracking info in the message. Thanks to Zerotorescue for giving me the solution to detect whether or not Postal or MailOpener is processing. It was the last step holding this back from being released.
+
 2010-10-06  Asa Ayers  <Asa.Ayers@Gmail.com>
 
 - Ticket 46 - Added DataStore_Characters to the list of dependencies. It should have been added with Ticket 43.
--- a/Core.lua	Wed Oct 06 22:11:26 2010 -0700
+++ b/Core.lua	Sat Oct 09 00:21:06 2010 -0700
@@ -1,6 +1,6 @@
 local ItemAuditor = select(2, ...)
 local Utils
-ItemAuditor = LibStub("AceAddon-3.0"):NewAddon(ItemAuditor, "ItemAuditor", "AceEvent-3.0", "AceBucket-3.0")
+ItemAuditor = LibStub("AceAddon-3.0"):NewAddon(ItemAuditor, "ItemAuditor", "AceEvent-3.0", "AceBucket-3.0", "AceSerializer-3.0", "AceTimer-3.0")
 --@debug@
 	_G['ItemAuditor'] = ItemAuditor
 --@end-debug@
@@ -10,6 +10,8 @@
 	end
 end
 
+ItemAuditor.TRACKING_DATA_DIVIDER = "\n==ItemAuditor Tracking Data==\n"
+
 local allMailboxes = {}
 local myMailbox = {}
 
@@ -53,6 +55,7 @@
 		qa_extra = 0,
 		output_chat_frame = nil,
 		cod_warnings = true,
+		incoming_tracking_ids = {}
 	},
 	profile = {
 		messages = {
@@ -267,6 +270,7 @@
 function ItemAuditor:ScanMail()
 	local results = {}
 	local CODPaymentRegex = gsub(COD_PAYMENT, "%%s", "(.*)")
+	local ia_tracking = {}
 
 	for mailIndex = 1, GetInboxNumItems() or 0 do
 		local sender, msgSubject, msgMoney, msgCOD, daysLeft, msgItem, _, _, msgText, _, isGM = select(3, GetInboxHeaderInfo(mailIndex))
@@ -356,8 +360,29 @@
 		elseif mailType == "AHExpired" or mailType == "AHCancelled" or mailType == "AHOutbid" then
 			-- These should be handled when you pay the deposit at the AH
 		else
-			-- self:Debug("Unhandled mail type: " .. mailType)
-			-- self:Debug(msgSubject)
+			
+			local body = GetInboxText(mailIndex)
+			if body and body:find(ItemAuditor.TRACKING_DATA_DIVIDER) then
+				local serialized = body:gsub('.*'..ItemAuditor.TRACKING_DATA_DIVIDER, '')
+				local body = body:gsub(ItemAuditor.TRACKING_DATA_DIVIDER..'.*', '')
+				local success, trackingID, data = ItemAuditor:Deserialize(serialized)
+				if success then
+					if not self.db.char.incoming_tracking_ids[trackingID] then
+						for link, d in pairs(data) do
+							self:SaveValue(link, d.costEach * d.count, d.count)
+						end
+					end
+					if body == '' and msgItem == nil then
+						self.deleteQueue = self.deleteQueue or {}
+						local ni = #(self.deleteQueue)+1
+						print(deleteQueue, ni, mailIndex)
+						self.deleteQueue[ni] = mailIndex
+					end
+					ia_tracking[trackingID] = true
+					self.db.char.incoming_tracking_ids[trackingID] = true
+				end
+			end
+
 		end
 
 	end
@@ -373,6 +398,12 @@
 			-- self:Print(format("|cFF00FF00MailScan|r: %s - %s - %s x %s", mailType, item, data.total, data.count))
 		end
 	end
+	if self:tcount(ia_tracking) > 0 then
+		for id, _ in pairs(self.db.char.incoming_tracking_ids) do
+			self.db.char.incoming_tracking_ids[id] = ia_tracking[id]
+		end
+	end
+
 	return results
 end
 
--- a/Modules/Events.lua	Wed Oct 06 22:11:26 2010 -0700
+++ b/Modules/Events.lua	Sat Oct 09 00:21:06 2010 -0700
@@ -105,22 +105,28 @@
 			attachedItems[newLink].stacks = attachedItems[newLink].stacks + 1
 			attachedItems[newLink].count = attachedItems[newLink].count + itemCount
 			attachedItems[newLink].price = 0 -- This is a placeholder for below.
+			attachedItems[newLink].costEach = select(2, ItemAuditor:GetItemCost(newLink))
 		end
 	end
 	local attachedValue = 0
 	for link, data in pairs(attachedItems) do
 		data.price = 30 * data.stacks
-		attachedValue = attachedValue + data.price + (select(2, ItemAuditor:GetItemCost(link)) * data.stacks)
+		attachedValue = attachedValue + data.price + (data.costEach * data.count)
 	end
-	
-	local cross_account_mail = true
-	for name, _ in pairs(DataStore:GetCharacters()) do
-		if strlower(recipient) == strlower(name) then
-			cross_account_mail = false
-			break
+
+	local destinationType = 'unknown'
+	local realm = GetRealmName()
+	for account in pairs(DataStore:GetAccounts()) do
+		for character in pairs(DataStore:GetCharacters(realm, account)) do
+			if strlower(recipient) == strlower(character) then
+				destinationType = (account == 'Default') and 'same_account' or 'owned_account'
+				destinationType = 'owned_account'
+				break
+			end
 		end
 	end
-	if cross_account_mail and attachedValue > self.mailOutbox.COD and not skipCODCheck and ItemAuditor.db.char.cod_warnings then
+	self.mailOutbox.destinationType = destinationType
+	if destinationType == 'unknown' and attachedValue > self.mailOutbox.COD and not skipCODCheck and ItemAuditor.db.char.cod_warnings then
 		self:GenerateBlankOutbox()
 		skipCODCheck = false;
 		local vararg = ...
@@ -131,6 +137,14 @@
 		end
 		StaticPopup_Show ("ItemAuditor_Insufficient_COD", Utils.FormatMoney(attachedValue));
 		return
+	elseif destinationType == 'owned_account' then
+		-- If we are mailing to an alt on a different account, a uniqueue tracking number
+		-- is generated and all of the needed data is attached to the message.
+		-- The tracking number is only used to make sure the other character doesn't count the
+		-- mail more than once.
+		local key = time()..":"..random(10000)
+		self.mailOutbox.attachedItems = attachedItems
+		body = body .. ItemAuditor.TRACKING_DATA_DIVIDER .. ItemAuditor:Serialize(key, attachedItems)
 	elseif self.mailOutbox.COD > 0 and skipCODTracking then
 		
 	elseif self.mailOutbox.COD > 0 then
@@ -168,6 +182,14 @@
 	skipCODCheck = false
 
 	for link, data in pairs(attachedItems) do
+		-- When mailing to an alt on a different account, we still
+		-- should add the price of postage, but need to subtract the
+		-- cost of the items. This will simulate CODing the mail and
+		-- getting the money back, except that postage is paid by the
+		-- sender
+		if self.mailOutbox.destinationType == 'owned_account' then
+			data.price = data.price - (data.costEach * data.count)
+		end
 		self:SaveValue(link, data.price, data.count)
 	end
 	if self.mailOutbox.COD > 0 then
@@ -190,10 +212,37 @@
 	self.mailOpen = nil
 end
 
+local function CanMailBeDeleted(mailIndex)
+	local msgMoney, _, _, msgItem = select(5, GetInboxHeaderInfo(mailIndex))
+	local body = GetInboxText(mailIndex)
+	if msgMoney == 0 and msgItem == nil and body and body:find(ItemAuditor.TRACKING_DATA_DIVIDER) then
+		local serialized = body:gsub('.*'..ItemAuditor.TRACKING_DATA_DIVIDER, '')
+		local body = body:gsub(ItemAuditor.TRACKING_DATA_DIVIDER..'.*', '')
+		local success, trackingID, data = ItemAuditor:Deserialize(serialized)
+		if success and body == '' then
+			return true
+		end
+	end
+	return false
+end
+
+local Postal_L
+local function blockMailOperations()
+	if MailAddonBusy == 'ItemAuditor' then
+		return false
+	end
+	if Postal_L == nil then
+		local locale = LibStub("AceLocale-3.0", true)
+		Postal_L = locale and locale:GetLocale("Postal", true)
+	end
+	return MailAddonBusy or PostalOpenAllButton and Postal_L and PostalOpenAllButton:GetText() == Postal_L["In Progress"]
+end
+
 local storedCountDiff
 function ItemAuditor:MAIL_INBOX_UPDATE()
 	self:Debug("MAIL_INBOX_UPDATE")
-	local newScan = ItemAuditor:ScanMail()
+	self.deleteQueue = nil
+	local newScan = self:ScanMail()
 	local diff
 	
 	for mailType, collection in pairs(self.lastMailScan) do
@@ -226,6 +275,44 @@
 	end
 
 	self.lastMailScan = newScan
+
+	if self.deleteQueue and not self.deleteScheduled then
+		-- For some reason DeleteInboxItem will not trigger a MAIL_INBOX_UPDATE
+		-- if it is called from here, so I have to use a timer to get it
+		-- to run outside of this function.
+
+		-- If the mailbox is full of items to be deleted, this will speed up because
+		-- postal shouldn't be running at this point. Keeping at 0.1 breaks postal.
+		local delay = (GetInboxNumItems() > #(self.deleteQueue)) and 1 or 0.1
+		self:ScheduleTimer("ProcessDeleteQueue", delay)
+		self.deleteScheduled = true
+	elseif MailAddonBusy == 'ItemAuditor' then
+		MailAddonBusy = nil
+	end
+end
+
+function ItemAuditor:ProcessDeleteQueue()
+	if blockMailOperations() then
+		self:ScheduleTimer("ProcessDeleteQueue", 1)
+		return
+	end
+	self.deleteScheduled = false
+	if self.deleteQueue then
+		MailAddonBusy = 'ItemAuditor'
+		while  #(self.deleteQueue) > 0 do
+			local mailIndex = table.remove(self.deleteQueue)
+			if CanMailBeDeleted(mailIndex) then
+				DeleteInboxItem(mailIndex)
+				-- This returns after the first item because you can't delete
+				-- all mail at once and this is in a loop so that if for some
+				-- reason CanMailBeDeleted returns false, we can delete the next
+				-- mail in the queue instead.
+				return
+			end
+		end
+	else
+		MailAddonBusy = nil
+	end
 end
 
 function ItemAuditor:UNIT_SPELLCAST_START(event, target, spell)
--- a/embeds.xml	Wed Oct 06 22:11:26 2010 -0700
+++ b/embeds.xml	Sat Oct 09 00:21:06 2010 -0700
@@ -8,7 +8,10 @@
 	<Include file="Libs\AceDbOptions-3.0\AceDbOptions-3.0.xml"/>   
 	<Include file="Libs\AceConfig-3.0\AceConfig-3.0.xml"/>   
 	<Include file="Libs\AceBucket-3.0\AceBucket-3.0.xml"/>   
-	<Include file="Libs\AceTimer-3.0\AceTimer-3.0.xml"/>   
+	<Include file="Libs\AceTimer-3.0\AceTimer-3.0.xml"/>
+	<Include file="Libs\AceSerializer-3.0\AceSerializer-3.0.xml"/>
+	<Include file="Libs\AceTimer-3.0\AceTimer-3.0.xml"/>
+
 	<Include file="Libs\lib-st\lib-st.xml"/>
 	<Script file="Libs\LibPeriodicTable-3.1\LibPeriodicTable-3.1.lua"/>
 </Ui>