544 lines
15 KiB
Lua
544 lines
15 KiB
Lua
|
|
local ADDON_NAME = "MailboxCourier"
|
|||
|
|
|
|||
|
|
local DEFAULTS = {
|
|||
|
|
recipient = "",
|
|||
|
|
subject = "Auto mail",
|
|||
|
|
interval = 1.2,
|
|||
|
|
dryRun = false,
|
|||
|
|
autoConfirmUnknownRecipient = true,
|
|||
|
|
skipSoulbound = true,
|
|||
|
|
skipQuest = true,
|
|||
|
|
skipContainers = true,
|
|||
|
|
blacklist = {
|
|||
|
|
[6948] = true, -- Hearthstone
|
|||
|
|
[7005] = true, -- Skinning Knife
|
|||
|
|
},
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
local state = {
|
|||
|
|
running = false,
|
|||
|
|
mailboxOpen = false,
|
|||
|
|
queue = {},
|
|||
|
|
batch = {},
|
|||
|
|
batchCount = 0,
|
|||
|
|
sentItems = 0,
|
|||
|
|
sentMails = 0,
|
|||
|
|
nextAt = 0,
|
|||
|
|
waitingForSuccess = false,
|
|||
|
|
lastConfirmAt = 0,
|
|||
|
|
lastError = "",
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
local frame = CreateFrame("Frame")
|
|||
|
|
local tooltip = CreateFrame("GameTooltip", "MailboxCourierTooltip", UIParent, "GameTooltipTemplate")
|
|||
|
|
tooltip:SetOwner(UIParent, "ANCHOR_NONE")
|
|||
|
|
|
|||
|
|
local function copyDefaults(src, dst)
|
|||
|
|
dst = dst or {}
|
|||
|
|
for key, value in pairs(src) do
|
|||
|
|
if type(value) == "table" then
|
|||
|
|
dst[key] = copyDefaults(value, dst[key])
|
|||
|
|
elseif dst[key] == nil then
|
|||
|
|
dst[key] = value
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
return dst
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function db()
|
|||
|
|
MailboxCourierDB = copyDefaults(DEFAULTS, MailboxCourierDB or {})
|
|||
|
|
return MailboxCourierDB
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function trim(text)
|
|||
|
|
return tostring(text or ""):gsub("^%s+", ""):gsub("%s+$", "")
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function log(message)
|
|||
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cff33ff99[" .. ADDON_NAME .. "]|r " .. tostring(message))
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function parseItemId(itemLink)
|
|||
|
|
if not itemLink then
|
|||
|
|
return nil
|
|||
|
|
end
|
|||
|
|
local itemId = itemLink:match("item:(%d+)")
|
|||
|
|
return itemId and tonumber(itemId) or nil
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function clearSendMailAttachments()
|
|||
|
|
ClearCursor()
|
|||
|
|
if ClearSendMail then
|
|||
|
|
ClearSendMail()
|
|||
|
|
return
|
|||
|
|
end
|
|||
|
|
for index = 1, 12 do
|
|||
|
|
if HasSendMailItem and HasSendMailItem(index) then
|
|||
|
|
ClickSendMailItemButton(index)
|
|||
|
|
ClearCursor()
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function tooltipHasText(bag, slot, needles)
|
|||
|
|
tooltip:ClearLines()
|
|||
|
|
tooltip:SetBagItem(bag, slot)
|
|||
|
|
for i = 1, tooltip:NumLines() do
|
|||
|
|
local line = _G["MailboxCourierTooltipTextLeft" .. i]
|
|||
|
|
local text = line and line:GetText()
|
|||
|
|
if text then
|
|||
|
|
for _, needle in ipairs(needles) do
|
|||
|
|
if needle and needle ~= "" and text:find(needle, 1, true) then
|
|||
|
|
return true
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
return false
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function isSoulbound(bag, slot)
|
|||
|
|
return tooltipHasText(bag, slot, {
|
|||
|
|
ITEM_SOULBOUND,
|
|||
|
|
"Soulbound",
|
|||
|
|
"灵魂绑定",
|
|||
|
|
"靈魂綁定",
|
|||
|
|
})
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function isQuestItem(bag, slot)
|
|||
|
|
return tooltipHasText(bag, slot, {
|
|||
|
|
ITEM_BIND_QUEST,
|
|||
|
|
"Quest Item",
|
|||
|
|
"任务物品",
|
|||
|
|
"任務物品",
|
|||
|
|
})
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function isContainerItem(itemId, itemLink)
|
|||
|
|
local name, link, quality, itemLevel, reqLevel, itemType, itemSubType, stackCount, equipLoc = GetItemInfo(itemId or itemLink or "")
|
|||
|
|
if equipLoc == "INVTYPE_BAG" then
|
|||
|
|
return true
|
|||
|
|
end
|
|||
|
|
if itemType == ITEM_CLASS_CONTAINER or itemType == "Container" or itemType == "容器" or itemType == "容器" then
|
|||
|
|
return true
|
|||
|
|
end
|
|||
|
|
return false
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function getContainerItemInfoCompat(bag, slot)
|
|||
|
|
local texture, count, locked, quality, readable, lootable, itemLink
|
|||
|
|
if C_Container and C_Container.GetContainerItemInfo then
|
|||
|
|
local info = C_Container.GetContainerItemInfo(bag, slot)
|
|||
|
|
if not info then
|
|||
|
|
return nil
|
|||
|
|
end
|
|||
|
|
texture = info.iconFileID
|
|||
|
|
count = info.stackCount
|
|||
|
|
locked = info.isLocked
|
|||
|
|
quality = info.quality
|
|||
|
|
readable = info.isReadable
|
|||
|
|
lootable = info.hasLoot
|
|||
|
|
itemLink = info.hyperlink
|
|||
|
|
else
|
|||
|
|
texture, count, locked, quality, readable, lootable, itemLink = GetContainerItemInfo(bag, slot)
|
|||
|
|
if not itemLink and GetContainerItemLink then
|
|||
|
|
itemLink = GetContainerItemLink(bag, slot)
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
if not itemLink then
|
|||
|
|
return nil
|
|||
|
|
end
|
|||
|
|
return {
|
|||
|
|
texture = texture,
|
|||
|
|
count = count or 1,
|
|||
|
|
locked = locked,
|
|||
|
|
quality = quality,
|
|||
|
|
readable = readable,
|
|||
|
|
lootable = lootable,
|
|||
|
|
itemLink = itemLink,
|
|||
|
|
itemId = parseItemId(itemLink),
|
|||
|
|
}
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function getContainerNumSlotsCompat(bag)
|
|||
|
|
if C_Container and C_Container.GetContainerNumSlots then
|
|||
|
|
return C_Container.GetContainerNumSlots(bag) or 0
|
|||
|
|
end
|
|||
|
|
return GetContainerNumSlots(bag) or 0
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function shouldSkipItem(bag, slot, info)
|
|||
|
|
local cfg = db()
|
|||
|
|
local itemId = info.itemId
|
|||
|
|
|
|||
|
|
if info.locked then
|
|||
|
|
return true, "locked"
|
|||
|
|
end
|
|||
|
|
if itemId and cfg.blacklist[itemId] then
|
|||
|
|
return true, "blacklisted"
|
|||
|
|
end
|
|||
|
|
if cfg.skipSoulbound and isSoulbound(bag, slot) then
|
|||
|
|
return true, "soulbound"
|
|||
|
|
end
|
|||
|
|
if cfg.skipQuest and isQuestItem(bag, slot) then
|
|||
|
|
return true, "quest"
|
|||
|
|
end
|
|||
|
|
if cfg.skipContainers and isContainerItem(itemId, info.itemLink) then
|
|||
|
|
return true, "container"
|
|||
|
|
end
|
|||
|
|
return false, nil
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function scanBags()
|
|||
|
|
local queue = {}
|
|||
|
|
local skipped = {}
|
|||
|
|
|
|||
|
|
for bag = 0, 4 do
|
|||
|
|
for slot = 1, getContainerNumSlotsCompat(bag) do
|
|||
|
|
local info = getContainerItemInfoCompat(bag, slot)
|
|||
|
|
if info then
|
|||
|
|
local skip, reason = shouldSkipItem(bag, slot, info)
|
|||
|
|
if skip then
|
|||
|
|
skipped[reason] = (skipped[reason] or 0) + 1
|
|||
|
|
else
|
|||
|
|
table.insert(queue, {
|
|||
|
|
bag = bag,
|
|||
|
|
slot = slot,
|
|||
|
|
itemId = info.itemId,
|
|||
|
|
itemLink = info.itemLink,
|
|||
|
|
count = info.count or 1,
|
|||
|
|
})
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
return queue, skipped
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function stop(reason)
|
|||
|
|
state.running = false
|
|||
|
|
state.waitingForSuccess = false
|
|||
|
|
state.queue = {}
|
|||
|
|
state.batch = {}
|
|||
|
|
state.batchCount = 0
|
|||
|
|
state.nextAt = 0
|
|||
|
|
clearSendMailAttachments()
|
|||
|
|
if reason and reason ~= "" then
|
|||
|
|
log(reason)
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function popNextUnlockedItem()
|
|||
|
|
while #state.queue > 0 do
|
|||
|
|
local item = table.remove(state.queue, 1)
|
|||
|
|
local info = getContainerItemInfoCompat(item.bag, item.slot)
|
|||
|
|
if info and not info.locked and parseItemId(info.itemLink) == item.itemId then
|
|||
|
|
local skip = shouldSkipItem(item.bag, item.slot, info)
|
|||
|
|
if not skip then
|
|||
|
|
return item
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
return nil
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function attachNextBatch()
|
|||
|
|
clearSendMailAttachments()
|
|||
|
|
state.batch = {}
|
|||
|
|
state.batchCount = 0
|
|||
|
|
|
|||
|
|
for attachment = 1, 12 do
|
|||
|
|
local item = popNextUnlockedItem()
|
|||
|
|
if not item then
|
|||
|
|
break
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
ClearCursor()
|
|||
|
|
PickupContainerItem(item.bag, item.slot)
|
|||
|
|
if CursorHasItem and not CursorHasItem() then
|
|||
|
|
log("无法拿起物品,跳过: " .. tostring(item.itemLink))
|
|||
|
|
else
|
|||
|
|
ClickSendMailItemButton(attachment)
|
|||
|
|
ClearCursor()
|
|||
|
|
table.insert(state.batch, item)
|
|||
|
|
state.batchCount = state.batchCount + 1
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
return state.batchCount > 0
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function sendCurrentBatch()
|
|||
|
|
local cfg = db()
|
|||
|
|
local recipient = trim(cfg.recipient)
|
|||
|
|
if recipient == "" then
|
|||
|
|
stop("没有收件人。先输入 /mc to 角色名")
|
|||
|
|
return
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local subject = trim(cfg.subject)
|
|||
|
|
if subject == "" then
|
|||
|
|
subject = "Auto mail"
|
|||
|
|
end
|
|||
|
|
subject = subject .. " " .. (state.sentMails + 1)
|
|||
|
|
|
|||
|
|
if cfg.dryRun then
|
|||
|
|
state.sentItems = state.sentItems + state.batchCount
|
|||
|
|
state.sentMails = state.sentMails + 1
|
|||
|
|
log("dry-run: 模拟发送第 " .. state.sentMails .. " 封,附件 " .. state.batchCount .. " 件")
|
|||
|
|
clearSendMailAttachments()
|
|||
|
|
state.nextAt = GetTime() + cfg.interval
|
|||
|
|
return
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
state.waitingForSuccess = true
|
|||
|
|
state.nextAt = GetTime() + 8
|
|||
|
|
SendMail(recipient, subject, "")
|
|||
|
|
log("已提交第 " .. (state.sentMails + 1) .. " 封,附件 " .. state.batchCount .. " 件")
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function maybeConfirmMailPopup()
|
|||
|
|
local cfg = db()
|
|||
|
|
if not cfg.autoConfirmUnknownRecipient then
|
|||
|
|
return false
|
|||
|
|
end
|
|||
|
|
if not state.running or not state.waitingForSuccess then
|
|||
|
|
return false
|
|||
|
|
end
|
|||
|
|
if GetTime() - state.lastConfirmAt < 0.5 then
|
|||
|
|
return false
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local recipient = trim(cfg.recipient)
|
|||
|
|
for i = 1, 4 do
|
|||
|
|
local popup = _G["StaticPopup" .. i]
|
|||
|
|
if popup and popup:IsShown() then
|
|||
|
|
local which = tostring(popup.which or "")
|
|||
|
|
local textFrame = _G["StaticPopup" .. i .. "Text"]
|
|||
|
|
local text = tostring(textFrame and textFrame:GetText() or "")
|
|||
|
|
local lowerText = text:lower()
|
|||
|
|
local looksLikeMailPopup =
|
|||
|
|
which:find("MAIL", 1, true)
|
|||
|
|
or lowerText:find("mail", 1, true)
|
|||
|
|
or lowerText:find("recipient", 1, true)
|
|||
|
|
or lowerText:find("send", 1, true)
|
|||
|
|
or (recipient ~= "" and text:find(recipient, 1, true))
|
|||
|
|
|
|||
|
|
if looksLikeMailPopup then
|
|||
|
|
local button = _G["StaticPopup" .. i .. "Button1"]
|
|||
|
|
if button and (not button.IsEnabled or button:IsEnabled()) then
|
|||
|
|
state.lastConfirmAt = GetTime()
|
|||
|
|
button:Click()
|
|||
|
|
log("Auto-confirmed mail warning popup.")
|
|||
|
|
return true
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
return false
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function process()
|
|||
|
|
if not state.running then
|
|||
|
|
return
|
|||
|
|
end
|
|||
|
|
if state.waitingForSuccess then
|
|||
|
|
maybeConfirmMailPopup()
|
|||
|
|
end
|
|||
|
|
if GetTime() < state.nextAt then
|
|||
|
|
return
|
|||
|
|
end
|
|||
|
|
if state.waitingForSuccess then
|
|||
|
|
stop("等待邮件发送成功超时,已停止。最后错误: " .. tostring(state.lastError))
|
|||
|
|
return
|
|||
|
|
end
|
|||
|
|
if not state.mailboxOpen then
|
|||
|
|
stop("邮箱没有打开,已停止。")
|
|||
|
|
return
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
if attachNextBatch() then
|
|||
|
|
sendCurrentBatch()
|
|||
|
|
else
|
|||
|
|
stop("邮寄完成,共发送 " .. state.sentMails .. " 封," .. state.sentItems .. " 件物品。")
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function beginSend()
|
|||
|
|
local cfg = db()
|
|||
|
|
local recipient = trim(cfg.recipient)
|
|||
|
|
if recipient == "" then
|
|||
|
|
log("没有收件人。用法: /mc to 角色名")
|
|||
|
|
return
|
|||
|
|
end
|
|||
|
|
if not state.mailboxOpen then
|
|||
|
|
log("邮箱还没打开。请先和邮箱交互。")
|
|||
|
|
return
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
state.queue = {}
|
|||
|
|
state.batch = {}
|
|||
|
|
state.batchCount = 0
|
|||
|
|
state.sentItems = 0
|
|||
|
|
state.sentMails = 0
|
|||
|
|
state.lastError = ""
|
|||
|
|
state.waitingForSuccess = false
|
|||
|
|
|
|||
|
|
local skipped
|
|||
|
|
state.queue, skipped = scanBags()
|
|||
|
|
if #state.queue == 0 then
|
|||
|
|
log("没有找到可邮寄物品。")
|
|||
|
|
return
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
state.running = true
|
|||
|
|
state.nextAt = GetTime() + 0.2
|
|||
|
|
log("开始邮寄给 " .. recipient .. ",待发送 " .. #state.queue .. " 个背包格。")
|
|||
|
|
|
|||
|
|
local parts = {}
|
|||
|
|
for reason, count in pairs(skipped or {}) do
|
|||
|
|
table.insert(parts, reason .. "=" .. count)
|
|||
|
|
end
|
|||
|
|
if #parts > 0 then
|
|||
|
|
log("已跳过: " .. table.concat(parts, ", "))
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function showStatus()
|
|||
|
|
local cfg = db()
|
|||
|
|
log("收件人: " .. (trim(cfg.recipient) ~= "" and cfg.recipient or "未设置"))
|
|||
|
|
log("主题: " .. cfg.subject .. ";间隔: " .. tostring(cfg.interval) .. " 秒;dry-run: " .. tostring(cfg.dryRun))
|
|||
|
|
log("命令: /mc to 角色名, /mc send, /mc stop, /mc dryrun on|off, /mc black add|del itemID")
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function setRecipient(name)
|
|||
|
|
name = trim(name)
|
|||
|
|
if name == "" then
|
|||
|
|
log("用法: /mc to 角色名")
|
|||
|
|
return
|
|||
|
|
end
|
|||
|
|
db().recipient = name
|
|||
|
|
log("收件人已设置为: " .. name)
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function setSubject(subject)
|
|||
|
|
subject = trim(subject)
|
|||
|
|
if subject == "" then
|
|||
|
|
log("用法: /mc subject 邮件主题")
|
|||
|
|
return
|
|||
|
|
end
|
|||
|
|
db().subject = subject
|
|||
|
|
log("邮件主题已设置为: " .. subject)
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function setDryRun(value)
|
|||
|
|
value = trim(value):lower()
|
|||
|
|
if value == "on" or value == "1" or value == "true" then
|
|||
|
|
db().dryRun = true
|
|||
|
|
elseif value == "off" or value == "0" or value == "false" then
|
|||
|
|
db().dryRun = false
|
|||
|
|
else
|
|||
|
|
log("用法: /mc dryrun on|off")
|
|||
|
|
return
|
|||
|
|
end
|
|||
|
|
log("dry-run: " .. tostring(db().dryRun))
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function setAutoConfirm(value)
|
|||
|
|
value = trim(value):lower()
|
|||
|
|
if value == "on" or value == "1" or value == "true" then
|
|||
|
|
db().autoConfirmUnknownRecipient = true
|
|||
|
|
elseif value == "off" or value == "0" or value == "false" then
|
|||
|
|
db().autoConfirmUnknownRecipient = false
|
|||
|
|
else
|
|||
|
|
log("Usage: /mc autoconfirm on|off")
|
|||
|
|
return
|
|||
|
|
end
|
|||
|
|
log("auto-confirm unknown recipient: " .. tostring(db().autoConfirmUnknownRecipient))
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function updateBlacklist(rest)
|
|||
|
|
local action, idText = trim(rest):match("^(%S+)%s+(%S+)$")
|
|||
|
|
local itemId = tonumber(idText or "")
|
|||
|
|
if not action or not itemId then
|
|||
|
|
log("用法: /mc black add itemID 或 /mc black del itemID")
|
|||
|
|
return
|
|||
|
|
end
|
|||
|
|
action = action:lower()
|
|||
|
|
if action == "add" then
|
|||
|
|
db().blacklist[itemId] = true
|
|||
|
|
log("已加入黑名单 itemID: " .. itemId)
|
|||
|
|
elseif action == "del" or action == "remove" then
|
|||
|
|
db().blacklist[itemId] = nil
|
|||
|
|
log("已移出黑名单 itemID: " .. itemId)
|
|||
|
|
else
|
|||
|
|
log("用法: /mc black add itemID 或 /mc black del itemID")
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
SLASH_MAILBOXCOURIER1 = "/mc"
|
|||
|
|
SLASH_MAILBOXCOURIER2 = "/mailboxcourier"
|
|||
|
|
SlashCmdList["MAILBOXCOURIER"] = function(msg)
|
|||
|
|
local command, rest = trim(msg):match("^(%S*)%s*(.-)$")
|
|||
|
|
command = (command or ""):lower()
|
|||
|
|
rest = rest or ""
|
|||
|
|
|
|||
|
|
if command == "to" then
|
|||
|
|
setRecipient(rest)
|
|||
|
|
elseif command == "subject" then
|
|||
|
|
setSubject(rest)
|
|||
|
|
elseif command == "send" then
|
|||
|
|
beginSend()
|
|||
|
|
elseif command == "stop" then
|
|||
|
|
stop("已手动停止。")
|
|||
|
|
elseif command == "dryrun" then
|
|||
|
|
setDryRun(rest)
|
|||
|
|
elseif command == "autoconfirm" then
|
|||
|
|
setAutoConfirm(rest)
|
|||
|
|
elseif command == "black" or command == "blacklist" then
|
|||
|
|
updateBlacklist(rest)
|
|||
|
|
else
|
|||
|
|
showStatus()
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
frame:RegisterEvent("ADDON_LOADED")
|
|||
|
|
frame:RegisterEvent("MAIL_SHOW")
|
|||
|
|
frame:RegisterEvent("MAIL_CLOSED")
|
|||
|
|
frame:RegisterEvent("MAIL_SEND_SUCCESS")
|
|||
|
|
frame:RegisterEvent("UI_ERROR_MESSAGE")
|
|||
|
|
|
|||
|
|
frame:SetScript("OnEvent", function(_, event, arg1, arg2)
|
|||
|
|
if event == "ADDON_LOADED" and arg1 == ADDON_NAME then
|
|||
|
|
db()
|
|||
|
|
log("已加载。输入 /mc 查看命令。")
|
|||
|
|
elseif event == "MAIL_SHOW" then
|
|||
|
|
state.mailboxOpen = true
|
|||
|
|
log("邮箱已打开。")
|
|||
|
|
elseif event == "MAIL_CLOSED" then
|
|||
|
|
state.mailboxOpen = false
|
|||
|
|
if state.running then
|
|||
|
|
stop("邮箱关闭,已停止。")
|
|||
|
|
end
|
|||
|
|
elseif event == "MAIL_SEND_SUCCESS" then
|
|||
|
|
state.sentItems = state.sentItems + state.batchCount
|
|||
|
|
state.sentMails = state.sentMails + 1
|
|||
|
|
state.waitingForSuccess = false
|
|||
|
|
state.batch = {}
|
|||
|
|
state.batchCount = 0
|
|||
|
|
clearSendMailAttachments()
|
|||
|
|
state.nextAt = GetTime() + db().interval
|
|||
|
|
log("第 " .. state.sentMails .. " 封发送成功,累计 " .. state.sentItems .. " 件。")
|
|||
|
|
elseif event == "UI_ERROR_MESSAGE" then
|
|||
|
|
state.lastError = tostring(arg2 or arg1 or "")
|
|||
|
|
if state.running and state.lastError ~= "" then
|
|||
|
|
log("错误: " .. state.lastError)
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
end)
|
|||
|
|
|
|||
|
|
frame:SetScript("OnUpdate", process)
|