Asa@63
|
1 local ItemAuditor = select(2, ...)
|
Asa@63
|
2 local Events = ItemAuditor:NewModule("Events", "AceEvent-3.0")
|
Asa@3
|
3
|
Asa@92
|
4 local Utils = ItemAuditor:GetModule("Utils")
|
Asa@92
|
5
|
Asa@63
|
6 function ItemAuditor:OnEnable()
|
Asa@3
|
7 self:RegisterEvent("MAIL_SHOW")
|
Asa@4
|
8 self:RegisterEvent("UNIT_SPELLCAST_START")
|
Asa@81
|
9
|
Asa@81
|
10 self:RegisterEvent("BANKFRAME_OPENED", 'BankFrameChanged')
|
Asa@81
|
11 self:RegisterEvent("BANKFRAME_CLOSED", 'BankFrameChanged')
|
Asa@81
|
12
|
Asa@63
|
13 ItemAuditor:UpdateCurrentInventory()
|
Asa@3
|
14 self:WatchBags()
|
Asa@9
|
15
|
Asa@63
|
16 self:SetEnabled(nil, self.db.profile.ItemAuditor_enabled)
|
Asa@38
|
17 end
|
Asa@38
|
18
|
Asa@63
|
19 function ItemAuditor:OnDisable()
|
Asa@38
|
20 self:UnwatchBags()
|
Asa@38
|
21 self:UnregisterAllEvents()
|
Asa@63
|
22 ItemAuditor:HideAllFrames()
|
Asa@3
|
23 end
|
Asa@3
|
24
|
Asa@63
|
25 function ItemAuditor:MAIL_SHOW()
|
Asa@3
|
26 self:Debug("MAIL_SHOW")
|
Asa@113
|
27 self.mailOpen = true
|
Asa@63
|
28 ItemAuditor:UpdateCurrentInventory()
|
Asa@3
|
29 self.lastMailScan = self:ScanMail()
|
Asa@7
|
30
|
Asa@3
|
31 self:UnregisterEvent("MAIL_SHOW")
|
Asa@3
|
32 self:RegisterEvent("MAIL_CLOSED")
|
Asa@3
|
33 self:RegisterEvent("MAIL_INBOX_UPDATE")
|
Asa@39
|
34
|
Asa@39
|
35 self:GenerateBlankOutbox()
|
Asa@39
|
36
|
Asa@39
|
37 self:RegisterEvent("MAIL_SUCCESS")
|
Asa@39
|
38 end
|
Asa@39
|
39
|
Asa@63
|
40 function ItemAuditor:GenerateBlankOutbox()
|
Asa@39
|
41 self.mailOutbox = {
|
Asa@39
|
42 from = UnitName("player"),
|
Asa@39
|
43 to = "",
|
Asa@39
|
44 subject = "",
|
Asa@39
|
45 link = '',
|
Asa@39
|
46 count = 0,
|
Asa@39
|
47 COD = 0,
|
Asa@39
|
48 key = random(10000),
|
Asa@39
|
49 sent = 0,
|
Asa@39
|
50 }
|
Asa@39
|
51
|
Asa@39
|
52 if self.db.factionrealm.outbound_cod[self.mailOutbox.key] ~= nil then
|
Asa@39
|
53 return self:GenerateBlankOutbox()
|
Asa@39
|
54 end
|
Asa@39
|
55 end
|
Asa@39
|
56
|
Asa@40
|
57 local attachedItems = {}
|
Asa@39
|
58 local Orig_SendMail = SendMail
|
Asa@42
|
59 local skipCODTracking = false
|
Asa@92
|
60 local skipCODCheck = false
|
Asa@42
|
61
|
Asa@42
|
62 StaticPopupDialogs["ItemAuditor_Send_COD_without_tracking_number"] = {
|
Asa@42
|
63 text = "ItemAuditor cannot track COD mail with multiple item types attached. Do you want to send this mail without tracking?",
|
Asa@42
|
64 button1 = "Yes",
|
Asa@42
|
65 button2 = "No",
|
Asa@42
|
66 OnAccept = function()
|
Asa@42
|
67 skipCODTracking = true
|
Asa@42
|
68 end,
|
Asa@42
|
69 timeout = 0,
|
Asa@42
|
70 whileDead = true,
|
Asa@42
|
71 hideOnEscape = true,
|
Asa@42
|
72 }
|
Asa@39
|
73
|
Asa@92
|
74 StaticPopupDialogs["ItemAuditor_Insufficient_COD"] = {
|
Asa@92
|
75 text = "The COD on this mail is less than the value of items attached. Are you sure you want to send this?|nTotal value (including postage): %s",
|
Asa@92
|
76 button1 = "Yes",
|
Asa@92
|
77 button2 = "No",
|
Asa@92
|
78 OnAccept = function()
|
Asa@92
|
79 skipCODCheck = true
|
Asa@92
|
80 end,
|
Asa@92
|
81 timeout = 0,
|
Asa@92
|
82 whileDead = true,
|
Asa@92
|
83 hideOnEscape = true,
|
Asa@92
|
84 }
|
Asa@92
|
85
|
Asa@39
|
86 function SendMail(recipient, subject, body, ...)
|
Asa@39
|
87 local self = ItemAuditor
|
Asa@39
|
88 self:GenerateBlankOutbox()
|
Asa@39
|
89
|
Asa@39
|
90 self:Debug(format("[To: %s] [Subject: %s]", recipient, subject))
|
Asa@39
|
91
|
Asa@39
|
92 self.mailOutbox.COD = GetSendMailCOD()
|
Asa@39
|
93
|
Asa@92
|
94 wipe(attachedItems)
|
Asa@40
|
95 local totalStacks = 0
|
Asa@39
|
96 local link
|
Asa@40
|
97 for index = 1, ATTACHMENTS_MAX_SEND do
|
Asa@39
|
98 local itemName, _, itemCount = GetSendMailItem(index)
|
Asa@39
|
99 local newLink = GetSendMailItemLink(index)
|
Asa@39
|
100
|
Asa@40
|
101 if newLink ~= nil then
|
Asa@40
|
102 newLink = self:GetSafeLink(newLink)
|
Asa@40
|
103 totalStacks = totalStacks + 1
|
Asa@40
|
104 attachedItems[newLink] = (attachedItems[newLink] or {stacks = 0, count = 0})
|
Asa@40
|
105 attachedItems[newLink].stacks = attachedItems[newLink].stacks + 1
|
Asa@40
|
106 attachedItems[newLink].count = attachedItems[newLink].count + itemCount
|
Asa@40
|
107 attachedItems[newLink].price = 0 -- This is a placeholder for below.
|
Asa@39
|
108 end
|
Asa@40
|
109 end
|
Asa@92
|
110 local attachedValue = 0
|
Asa@40
|
111 for link, data in pairs(attachedItems) do
|
Asa@53
|
112 data.price = 30 * data.stacks
|
Asa@92
|
113 attachedValue = attachedValue + data.price + (select(2, ItemAuditor:GetItemCost(link)) * data.stacks)
|
Asa@40
|
114 end
|
Asa@40
|
115
|
Asa@92
|
116 local cross_account_mail = true
|
Asa@92
|
117 for name, _ in pairs(DataStore:GetCharacters()) do
|
Asa@97
|
118 if strlower(recipient) == strlower(name) then
|
Asa@92
|
119 cross_account_mail = false
|
Asa@92
|
120 break
|
Asa@92
|
121 end
|
Asa@92
|
122 end
|
Asa@109
|
123 if cross_account_mail and attachedValue > self.mailOutbox.COD and not skipCODCheck and ItemAuditor.db.char.cod_warnings then
|
Asa@92
|
124 self:GenerateBlankOutbox()
|
Asa@92
|
125 skipCODCheck = false;
|
Asa@92
|
126 local vararg = ...
|
Asa@92
|
127 StaticPopupDialogs["ItemAuditor_Insufficient_COD"].OnAccept = function()
|
Asa@92
|
128 skipCODCheck = true
|
Asa@92
|
129 SendMail(recipient, subject, body, vararg)
|
Asa@92
|
130 skipCODCheck = false
|
Asa@92
|
131 end
|
Asa@92
|
132 StaticPopup_Show ("ItemAuditor_Insufficient_COD", Utils.FormatMoney(attachedValue));
|
Asa@92
|
133 return
|
Asa@92
|
134 elseif self.mailOutbox.COD > 0 and skipCODTracking then
|
Asa@42
|
135
|
Asa@42
|
136 elseif self.mailOutbox.COD > 0 then
|
Asa@40
|
137 if self:tcount(attachedItems) > 1 then
|
Asa@39
|
138 self:GenerateBlankOutbox()
|
Asa@42
|
139 local vararg = ...
|
Asa@42
|
140 StaticPopupDialogs["ItemAuditor_Send_COD_without_tracking_number"].OnAccept = function()
|
Asa@42
|
141 skipCODTracking = true
|
Asa@42
|
142 SendMail(recipient, subject, body, vararg)
|
Asa@42
|
143 skipCODTracking = false
|
Asa@42
|
144 end
|
Asa@42
|
145 StaticPopup_Show ("ItemAuditor_Send_COD_without_tracking_number");
|
Asa@39
|
146 return
|
Asa@39
|
147 end
|
Asa@40
|
148 self:Debug("COD mail")
|
Asa@39
|
149
|
Asa@40
|
150 subject = format("[IA: %s] %s", self.mailOutbox.key, subject)
|
Asa@40
|
151 self.mailOutbox.subject = subject
|
Asa@40
|
152 self.mailOutbox.to = recipient
|
Asa@40
|
153
|
Asa@40
|
154 -- At this point we know there is only one item
|
Asa@40
|
155 for link, data in pairs(attachedItems) do
|
Asa@40
|
156 self.mailOutbox.link = link
|
Asa@40
|
157 self.mailOutbox.count = data.count
|
Asa@40
|
158 end
|
Asa@40
|
159 else
|
Asa@40
|
160 self:Debug("Non-COD mail")
|
Asa@39
|
161 end
|
Asa@40
|
162
|
Asa@39
|
163 return Orig_SendMail(recipient, subject, body, ...)
|
Asa@39
|
164 end
|
Asa@39
|
165
|
Asa@63
|
166 function ItemAuditor:MAIL_SUCCESS(event)
|
Asa@42
|
167 skipCODTracking = false
|
Asa@92
|
168 skipCODCheck = false
|
Asa@92
|
169
|
Asa@40
|
170 for link, data in pairs(attachedItems) do
|
Asa@40
|
171 self:SaveValue(link, data.price, data.count)
|
Asa@40
|
172 end
|
Asa@39
|
173 if self.mailOutbox.COD > 0 then
|
Asa@39
|
174 self:Debug(format("MAIL_SUCCESS %d [To: %s] [Subject: %s] [COD: %s]", self.mailOutbox.key, self.mailOutbox.to, self.mailOutbox.subject, self.mailOutbox.COD))
|
Asa@39
|
175
|
Asa@39
|
176 self.mailOutbox.sent = time()
|
Asa@39
|
177 self.db.factionrealm.outbound_cod[self.mailOutbox.key] = self.mailOutbox
|
Asa@39
|
178 end
|
Asa@92
|
179
|
Asa@92
|
180 wipe(attachedItems)
|
Asa@40
|
181 self:GenerateBlankOutbox()
|
Asa@3
|
182 end
|
Asa@3
|
183
|
Asa@63
|
184 function ItemAuditor:MAIL_CLOSED()
|
Asa@23
|
185 self:Debug("MAIL_CLOSED")
|
Asa@63
|
186 ItemAuditor:UnregisterEvent("MAIL_CLOSED")
|
Asa@7
|
187 self:MAIL_INBOX_UPDATE()
|
Asa@3
|
188 self:UnregisterEvent("MAIL_INBOX_UPDATE")
|
Asa@3
|
189 self:RegisterEvent("MAIL_SHOW")
|
Asa@113
|
190 self.mailOpen = nil
|
Asa@3
|
191 end
|
Asa@3
|
192
|
Asa@26
|
193 local storedCountDiff
|
Asa@63
|
194 function ItemAuditor:MAIL_INBOX_UPDATE()
|
Asa@23
|
195 self:Debug("MAIL_INBOX_UPDATE")
|
Asa@63
|
196 local newScan = ItemAuditor:ScanMail()
|
Asa@3
|
197 local diff
|
Asa@39
|
198
|
Asa@6
|
199 for mailType, collection in pairs(self.lastMailScan) do
|
Asa@7
|
200 newScan[mailType] = (newScan[mailType] or {})
|
Asa@26
|
201 for itemName, data in pairs(collection) do
|
Asa@26
|
202 newScan[mailType][itemName] = (newScan[mailType][itemName] or {total=0,count=0})
|
Asa@26
|
203 local totalDiff = data.total - newScan[mailType][itemName].total
|
Asa@26
|
204 local countDiff = data.count - newScan[mailType][itemName].count
|
Asa@26
|
205 --[[
|
Asa@26
|
206 In one update the item will be taken and in the following update the invoice
|
Asa@26
|
207 will be gone. I need to store the item difference in order ot pass it into
|
Asa@26
|
208 SaveValue.
|
Asa@26
|
209 ]]
|
Asa@26
|
210 if countDiff ~= 0 then
|
Asa@26
|
211 storedCountDiff = countDiff
|
Asa@26
|
212 end
|
Asa@26
|
213
|
Asa@26
|
214 if totalDiff ~= 0 then
|
Asa@39
|
215 if mailType == "CODPayment" then
|
Asa@39
|
216 local trackID
|
Asa@39
|
217 trackID, itemName= strsplit("|", itemName, 2)
|
Asa@39
|
218 self.db.factionrealm.outbound_cod[tonumber(trackID)] = nil
|
Asa@39
|
219 self:Debug("Removing COD Tracker: " .. trackID)
|
Asa@39
|
220 end
|
Asa@26
|
221 self:SaveValue(itemName, totalDiff, storedCountDiff)
|
Asa@26
|
222 storedCountDiff = 0
|
Asa@6
|
223 end
|
Asa@6
|
224
|
Asa@3
|
225 end
|
Asa@3
|
226 end
|
Asa@3
|
227
|
Asa@3
|
228 self.lastMailScan = newScan
|
Asa@3
|
229 end
|
Asa@3
|
230
|
Asa@63
|
231 function ItemAuditor:UNIT_SPELLCAST_START(event, target, spell)
|
Asa@5
|
232 if target == "player" and spell == "Milling" or spell == "Prospecting" or spell == "Disenchanting" then
|
Asa@23
|
233 self:Debug(event .. " " .. spell)
|
Asa@4
|
234 self:UnwatchBags()
|
Asa@4
|
235 self:UpdateCurrentInventory()
|
Asa@4
|
236 self:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED")
|
Asa@4
|
237 self:RegisterEvent("LOOT_CLOSED")
|
Asa@3
|
238 end
|
Asa@3
|
239 end
|
Asa@3
|
240
|
Asa@4
|
241 --[[
|
Asa@4
|
242 The item should be destroyed before this point, so the last inventory check
|
Asa@4
|
243 needs to be kept so it can be combined with the up coming loot.
|
Asa@4
|
244 ]]
|
Asa@63
|
245 function ItemAuditor:LOOT_CLOSED()
|
Asa@23
|
246 self:Debug("LOOT_CLOSED")
|
Asa@4
|
247 self:UnregisterEvent("LOOT_CLOSED")
|
Asa@4
|
248 self:UnregisterEvent("UNIT_SPELLCAST_INTERRUPTED")
|
Asa@4
|
249 local inventory = self.lastInventory
|
Asa@4
|
250 self:WatchBags()
|
Asa@4
|
251 self.lastInventory = inventory
|
Asa@4
|
252 end
|
Asa@3
|
253
|
Asa@63
|
254 function ItemAuditor:UNIT_SPELLCAST_INTERRUPTED(event, target, spell)
|
Asa@5
|
255 if target == "player" and spell == "Milling" or spell == "Prospecting" or spell == "Disenchanting" then
|
Asa@23
|
256 self:Debug(event .. " " .. spell)
|
Asa@4
|
257 self:UnregisterEvent("UNIT_SPELLCAST_INTERRUPTED")
|
Asa@4
|
258 self:UnregisterEvent("LOOT_CLOSED")
|
Asa@4
|
259 self:WatchBags()
|
Asa@4
|
260 end
|
Asa@4
|
261 end
|
Asa@4
|
262
|
Asa@63
|
263 function ItemAuditor:UpdateCurrentInventory()
|
Asa@4
|
264 self.lastInventory = self:GetCurrentInventory()
|
Asa@3
|
265 end
|
Asa@3
|
266
|
Asa@49
|
267 local function distributeValue(self, totalValue, targetItems)
|
Asa@46
|
268
|
Asa@46
|
269 local weights = {}
|
Asa@46
|
270 local totalWeight = 0
|
Asa@46
|
271 for link, change in pairs(targetItems) do
|
Asa@46
|
272 --[[
|
Asa@46
|
273 If something has never been seen on the AH, it must not be very valuable.
|
Asa@46
|
274 I'm using 1c so it doesn't have much weight and I can't get a devided by zero error.
|
Asa@46
|
275 The only time I know that this is a problem is when crafting a BOP item, and it
|
Asa@46
|
276 is always crafted 1 at a time, so a weight of 1 will work.
|
Asa@46
|
277 ]]
|
Asa@63
|
278 local ap = (ItemAuditor:GetAuctionPrice(link) or 1) * change
|
Asa@46
|
279 totalWeight = totalWeight + ap
|
Asa@46
|
280 weights[link] = ap
|
Asa@46
|
281 end
|
Asa@46
|
282
|
Asa@46
|
283 for link, change in pairs(targetItems) do
|
Asa@52
|
284 local value = totalValue * (weights[link]/totalWeight)
|
Asa@52
|
285 self:SaveValue(link, value, change)
|
Asa@46
|
286 end
|
Asa@46
|
287 end
|
Asa@46
|
288
|
Asa@63
|
289 function ItemAuditor:UpdateAudit()
|
Asa@23
|
290 -- self:Debug("UpdateAudit " .. event)
|
Asa@3
|
291 local currentInventory = self:GetCurrentInventory()
|
Asa@63
|
292 local diff = ItemAuditor:GetInventoryDiff(self.lastInventory, currentInventory)
|
Asa@3
|
293
|
Asa@5
|
294 local positive, negative = {}, {}
|
Asa@5
|
295 local positiveCount, negativeCount = 0, 0
|
Asa@5
|
296 for item, count in pairs(diff.items) do
|
Asa@5
|
297 if count > 0 then
|
Asa@5
|
298 positive[item] = count
|
Asa@5
|
299 positiveCount = positiveCount + count
|
Asa@5
|
300 elseif count < 0 then
|
Asa@5
|
301 negative[item] = count
|
Asa@5
|
302 negativeCount = negativeCount + abs(count)
|
Asa@5
|
303 end
|
Asa@5
|
304 end
|
Asa@5
|
305
|
Asa@23
|
306 if positiveCount + negativeCount == 0 then
|
Asa@33
|
307 --[[
|
Asa@33
|
308 Nothing needs to be done, but this will prevent mistakenly attributing
|
Asa@33
|
309 the cost of flights to the first item you pick up.
|
Asa@33
|
310 ]]
|
Asa@33
|
311 elseif diff.money > 0 and self:tcount(positive) > 0 and self:tcount(negative) == 0 then
|
Asa@15
|
312 self:Debug("loot")
|
Asa@113
|
313 elseif abs(diff.money) > 0 and self:tcount(diff.items) == 1 and not self.mailOpen then
|
Asa@15
|
314 self:Debug("purchase or sale")
|
Asa@3
|
315
|
Asa@9
|
316 for link, count in pairs(diff.items) do
|
Asa@26
|
317 self:SaveValue(link, 0 - diff.money, count)
|
Asa@3
|
318 end
|
Asa@23
|
319 elseif self:tcount(diff.items) > 1 and self:tcount(positive) > 0 and self:tcount(negative) > 0 then
|
Asa@23
|
320 -- we must have created/converted something
|
Asa@23
|
321 self:Debug("conversion")
|
Asa@3
|
322
|
Asa@23
|
323 local totalChange = 0
|
Asa@23
|
324 for link, change in pairs(negative) do
|
Asa@23
|
325 local _, itemCost, count = self:GetItemCost(link, change)
|
Asa@26
|
326 self:SaveValue(link, itemCost * change, change)
|
Asa@10
|
327
|
Asa@23
|
328 totalChange = totalChange + (itemCost * abs(change))
|
Asa@3
|
329 end
|
Asa@91
|
330 totalChange = totalChange - diff.money
|
Asa@23
|
331
|
Asa@46
|
332 distributeValue(self, totalChange, positive)
|
Asa@23
|
333 else
|
Asa@23
|
334 self:Debug("No match in UpdateAudit.")
|
Asa@3
|
335 end
|
Asa@3
|
336
|
Asa@3
|
337 self.lastInventory = currentInventory
|
Asa@63
|
338 ItemAuditor:WatchBags()
|
Asa@3
|
339 end |