You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1132 lines
40 KiB
1132 lines
40 KiB
local ADDONNAME, WIC = ...
|
|
|
|
-- luacheck: globals LibStub ItemRefTooltip
|
|
LibStub("AceAddon-3.0"):NewAddon(WIC, ADDONNAME, "AceConsole-3.0", "AceEvent-3.0", "AceHook-3.0")
|
|
|
|
local L = LibStub("AceLocale-3.0"):GetLocale(ADDONNAME)
|
|
|
|
local _G = _G
|
|
local GetTime = GetTime
|
|
|
|
local find, split, lower, format, len, join =
|
|
strfind, strsplit, strlower, format, strlen, strjoin
|
|
local type, select, pairs, error, wipe =
|
|
type, select, pairs, error, wipe
|
|
|
|
-- L["CHAT_MSG_CHANNEL"] = "All Channels"
|
|
|
|
WIC.RegisteredModules = {}
|
|
WIC.RegisteredModulesWithLoadOnDemand = {}
|
|
WIC.RegisteredModulesDescription = {}
|
|
WIC.RegisteredModulesTranslatedName = {}
|
|
WIC.RegisteredModulesList = L["No Modules Registered"]
|
|
|
|
function WIC:RegisterModule(name, handle, addonName)
|
|
self.RegisteredModules[name] = handle
|
|
if type(addonName) == "string" then
|
|
self.RegisteredModulesWithLoadOnDemand[name] = addonName
|
|
end
|
|
end
|
|
function WIC:AddTranslatedNameToModule(name, localeName)
|
|
self.RegisteredModulesTranslatedName[name] = localeName
|
|
end
|
|
function WIC:AddDescriptionToModule(name, description)
|
|
self.RegisteredModulesDescription[name] = description
|
|
end
|
|
|
|
|
|
do-- Adding modules
|
|
WIC:RegisterModule("Basic", "WhisperInviteBasic", "WhisperInviteBasic")
|
|
WIC:AddTranslatedNameToModule("Basic", L["Basic"])
|
|
WIC:AddDescriptionToModule("Basic", L["Invite player when they whisper you with a defined keyword."])
|
|
|
|
WIC:RegisterModule("Advanced", "WhisperInviteAdvanced", "WhisperInviteAdvanced")
|
|
WIC:AddTranslatedNameToModule("Advanced" ,L["Advanced"])
|
|
WIC:AddDescriptionToModule("Advanced" ,L["Invite player when they whisper you with a defined keyword where they are allowed to use."])
|
|
|
|
|
|
-- Search for third-party Modules
|
|
-- Add this to your TOC-File:
|
|
--[[
|
|
RequiredDeps: WhisperInvite
|
|
X-WisperInvite-Name: ModuleName
|
|
X-WisperInvite-Handle: AddonName -> used as in LibStub("AceAddon-3.0"):GetAddon(AddonName, true) or Global Variable Name
|
|
X-WisperInvite-Version: Version -> See MODULEVERSION
|
|
X-WisperInvite-Description: Small Description
|
|
|
|
LoadOnDemand: 1 -> for when you only want be loaded when needed
|
|
--]]
|
|
--Name and Description supports localization e.g: X-WisperInvite-Description-deDE
|
|
|
|
-- Needed functions when not a AceAddon:
|
|
--[[
|
|
Module:Enable()
|
|
Module:Disable()
|
|
Module:IsEnabled()
|
|
--]]
|
|
local tonumber, tinsert =
|
|
tonumber, tinsert
|
|
local GetAddOnInfo, GetAddOnMetadata =
|
|
GetAddOnInfo, GetAddOnMetadata
|
|
|
|
local MODULEVERSION = 0
|
|
local locale = GAME_LOCALE or GetLocale()-- luacheck: ignore
|
|
|
|
for index=1, GetNumAddOns() do
|
|
local addonName, title, notes, enabled, loadable, reason, security = GetAddOnInfo(index)
|
|
|
|
local version = GetAddOnMetadata(addonName, "X-WisperInvite-Version")
|
|
if version and tonumber(version) == MODULEVERSION and loadable then
|
|
local name = GetAddOnMetadata(addonName, "X-WisperInvite-Name")
|
|
local localeName = GetAddOnMetadata(addonName, "X-WisperInvite-Name-"..locale) or name
|
|
local description = GetAddOnMetadata(addonName, "X-WisperInvite-Description-"..locale) or GetAddOnMetadata(addonName, "X-WisperInvite-Description") or L["No description for this module."]
|
|
local handle = GetAddOnMetadata(addonName, "X-WisperInvite-Handle")
|
|
|
|
if name and handle then
|
|
WIC:RegisterModule(name, handle, addonName)
|
|
WIC:AddTranslatedNameToModule(name, name)
|
|
end
|
|
|
|
if name and localeName then
|
|
WIC:AddTranslatedNameToModule(name, localeName)
|
|
end
|
|
if name and description then
|
|
WIC:AddDescriptionToModule(name, description)
|
|
else
|
|
WIC:AddDescriptionToModule(name, L["No description for this module."])
|
|
end
|
|
end
|
|
end
|
|
|
|
local list = {}
|
|
for moduleName in pairs(WIC.RegisteredModules) do
|
|
local name = moduleName--(WIC.RegisteredModulesTranslatedName[name] or name).."<"..name..">"
|
|
|
|
tinsert(list, name)
|
|
end
|
|
WIC.RegisteredModulesList = join(", ", unpack(list) )
|
|
end
|
|
|
|
local LF_QUEUE_PVP = "PVP"
|
|
local LF_QUEUES = {
|
|
['**'] = {
|
|
blockInvites = true,
|
|
sendMessage = false,
|
|
returnMessage = L["I'm currently in a LF-Queue"],
|
|
},
|
|
[LF_QUEUE_PVP] = {},
|
|
}
|
|
|
|
for id, name in pairs(LFG_CATEGORY_NAMES) do
|
|
LF_QUEUES[id] = {}
|
|
end
|
|
|
|
local defaults = {
|
|
global = {},
|
|
char = {
|
|
info = {
|
|
['*'] = 0,
|
|
},
|
|
infoMax = {
|
|
['*'] = 3,
|
|
setup = 5,
|
|
lfr_block = 9,
|
|
},
|
|
},
|
|
profile = {
|
|
active = true,
|
|
selectedModuleName = false,
|
|
convertGroupToRaid = true,
|
|
inviteThrottleTime = 10, -- seconds
|
|
|
|
queueProtection = LF_QUEUES,
|
|
statusProtection = {
|
|
AFK = {
|
|
blockInvites = false,
|
|
sendMessage = false,
|
|
returnMessage = L["I'm currently AFK"],
|
|
},
|
|
DND = {
|
|
blockInvites = false,
|
|
sendMessage = false,
|
|
returnMessage = L["I'm currently DND"],
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
WIC.TYPES = {
|
|
LINK = "whisperinvite",
|
|
H_LINK = "|Hwhisperinvite|h",
|
|
}
|
|
|
|
WIC.LOOKUP_LOCALIZED_CLASS_NAMES = {}
|
|
|
|
-- TODO: handling of profile.active
|
|
function WIC:OnInitialize()
|
|
self.db = LibStub("AceDB-3.0"):New("WhisperInviteCoreDB", defaults, true)
|
|
|
|
self.db.RegisterCallback(self, "OnProfileChanged", "CheckEnabledState")
|
|
self.db.RegisterCallback(self, "OnProfileCopied", "CheckEnabledState")
|
|
|
|
self:RegisterConfig()
|
|
|
|
-- To enable wisperinvite when disabled
|
|
self:RegisterChatCommand("wisperinviteenable", "Enable", true)
|
|
self:RegisterChatCommand("wienable", "Enable", true)
|
|
|
|
self:RegisterChatCommand("wisperinvitedisable", "Disable", true)
|
|
self:RegisterChatCommand("widisable", "Disable", true)
|
|
|
|
self:RegisterChatCommand("wi", "CMD", true)
|
|
self:RegisterChatCommand("wisperinvite", "CMD", true)
|
|
|
|
-- build localized lookup table for class names
|
|
for class, classLocalized in pairs(_G.LOCALIZED_CLASS_NAMES_MALE) do
|
|
self.LOOKUP_LOCALIZED_CLASS_NAMES[classLocalized] = class
|
|
end
|
|
for class, classLocalized in pairs(_G.LOCALIZED_CLASS_NAMES_FEMALE) do
|
|
self.LOOKUP_LOCALIZED_CLASS_NAMES[classLocalized] = class
|
|
end
|
|
|
|
self:SetEnabledState(self.db.profile.active)
|
|
if not self:IsEnabled() and self.db.char.info.enable < self.db.char.infoMax.enable then
|
|
self.db.char.info.enable = self.db.char.info.enable + 1
|
|
self:Print(L["You can run /wienable to enable WisperInvite."])
|
|
end
|
|
end
|
|
|
|
function WIC:Enable_ModuleHandling()
|
|
local showInfo = true
|
|
if type(self.db.profile.selectedModuleName) == "string" then
|
|
local isEnabled = self:EnableSelectedModule()
|
|
|
|
if isEnabled or self:SelectModuleIsEnabled() then
|
|
-- Module is registered and enabled
|
|
showInfo = false
|
|
end
|
|
end
|
|
|
|
if showInfo then
|
|
if self.db.char.info.setup < self.db.char.infoMax.setup then
|
|
self.db.char.info.setup = self.db.char.info.setup + 1
|
|
self:Print(L["Run /wi modules or /wi options to setup WisperInvite."])
|
|
end
|
|
end
|
|
end
|
|
|
|
function WIC:OnEnable()
|
|
self:Enable_ModuleHandling()
|
|
|
|
-- Hooking
|
|
self:SecureHook("ChatFrame_OnHyperlinkShow")
|
|
self:RawHook("HandleModifiedItemClick", true)
|
|
self:RawHook(ItemRefTooltip, "SetHyperlink", "ItemRefTooltip_SetHyperlink", true)
|
|
end
|
|
|
|
function WIC:ItemRefTooltip_SetHyperlink(frame, link, ...)
|
|
if link and find(link, self.TYPES.LINK) then
|
|
return false
|
|
else
|
|
return self.hooks[frame].SetHyperlink(frame, link, ...)
|
|
end
|
|
end
|
|
|
|
function WIC:HandleModifiedItemClick(link, ...)
|
|
if link and find(link, self.TYPES.H_LINK) then
|
|
return false
|
|
else
|
|
return self.hooks.HandleModifiedItemClick(link, ...)
|
|
end
|
|
end
|
|
|
|
function WIC:ChatFrame_OnHyperlinkShow(frame, linkData, link, button, ...)
|
|
if split(":", linkData) == self.TYPES.LINK then
|
|
local _, toonID, toonName, presenceName, presenceID, debug = split(":", linkData)
|
|
--[===[@debug@
|
|
if debug == "DEBUG" then
|
|
self:Printf("Invite: %s(%s), id:%s", toonName, presenceName, toonID)
|
|
return
|
|
end
|
|
--@end-debug@]===]
|
|
|
|
local result, code = self:InviteToon(toonID, toonName, presenceName, presenceID)
|
|
|
|
--[===[@debug@
|
|
self:Printf("Invite Sent: %s", result and "OK" or "Error: "..code )
|
|
--@end-debug@]===]
|
|
--else
|
|
--self.hooks.ChatFrame_OnHyperlinkShow(frame, linkData, link, button, ...)
|
|
end
|
|
end
|
|
|
|
function WIC:Disable_ModuleHandling()
|
|
self:DisableSelectedModule()
|
|
end
|
|
|
|
function WIC:OnDisable()
|
|
self:Disable_ModuleHandling()
|
|
end
|
|
|
|
function WIC:CheckEnabledState(event, db)
|
|
db = db or self.db
|
|
if db.profile.active then
|
|
--[===[@debug@
|
|
self:Print("Active")
|
|
--@end-debug@]===]
|
|
if not self:IsEnabled() then
|
|
--[===[@debug@
|
|
self:Print("Enable")
|
|
--@end-debug@]===]
|
|
self:Enable()
|
|
else
|
|
--[===[@debug@
|
|
self:Print("Enable->Module")
|
|
--@end-debug@]===]
|
|
self:Enable_ModuleHandling()
|
|
end
|
|
elseif self:IsEnabled() then
|
|
--[===[@debug@
|
|
self:Print("Disable")
|
|
--@end-debug@]===]
|
|
self:Disable()
|
|
end
|
|
end
|
|
|
|
do-- CMD
|
|
local InterfaceOptionsFrame_OpenToCategory, InterfaceOptionsFrameAddOnsListScrollBar =
|
|
InterfaceOptionsFrame_OpenToCategory, InterfaceOptionsFrameAddOnsListScrollBar
|
|
|
|
function WIC:CMD(input, editBox)
|
|
--GetArgs(str, numargs, startpos)
|
|
local arg1, lastPos = self:GetArgs(input, 1)
|
|
arg1 = arg1 and lower(arg1) or ""
|
|
|
|
if arg1 == "modules" then
|
|
local moduleName = self:GetArgs(input, 1, lastPos)
|
|
if self.RegisteredModules[moduleName] then
|
|
self:SelectModule(moduleName)
|
|
else
|
|
self:Printf(L["Usage: /wi modules moduleName (case sensitive)"])
|
|
self:Printf(L["Modules: %s"], self.RegisteredModulesList )
|
|
end
|
|
elseif arg1 == "enable" or arg1 == "on" or arg1 == L["enable"] or arg1 == L["on"] then
|
|
self.db.profile.active = true
|
|
self:NotifyChange()
|
|
WIC:CheckEnabledState("", self.db)
|
|
self:Print(L["Enabled"])
|
|
elseif arg1 == "disable" or arg1 == "off" or arg1 == L["disable"] or arg1 == L["off"] then
|
|
self.db.profile.active = false
|
|
self:NotifyChange()
|
|
WIC:CheckEnabledState("", self.db)
|
|
self:Print(L["Disabled"])
|
|
elseif arg1 == "toggle" or arg1 == L["toggle"] then
|
|
self.db.profile.active = not self.db.profile.active
|
|
self:NotifyChange()
|
|
WIC:CheckEnabledState("", self.db)
|
|
if self.db.profile.active then
|
|
self:Print(L["Enabled"])
|
|
else
|
|
self:Print(L["Disabled"])
|
|
end
|
|
elseif not arg1 or arg1 == "" or arg1 == "help" or arg1 == "usage" or arg1 == L["help"] or arg1 == L["usage"] then
|
|
self:Print(L["Usage: /wi <command>\nCommands: modules, options"])
|
|
elseif arg1 == "options" or arg1 == "op" then
|
|
-- Load InterfaceOptionsFrameAddOns frame...
|
|
InterfaceOptionsFrame_OpenToCategory(ADDONNAME)
|
|
|
|
-- Let's scroll down, so your page can be open
|
|
InterfaceOptionsFrameAddOnsListScrollBar:SetValue(select(2, InterfaceOptionsFrameAddOnsListScrollBar:GetMinMaxValues() ) )
|
|
InterfaceOptionsFrame_OpenToCategory(ADDONNAME)
|
|
else
|
|
LibStub("AceConfigCmd-3.0").HandleCommand(self, "wi", ADDONNAME.."Options", input)
|
|
end
|
|
end
|
|
end
|
|
|
|
function WIC:SelectModule(moduleName)
|
|
if self.RegisteredModules[moduleName] then
|
|
local profile = self.db.profile
|
|
profile.selectedModuleName = moduleName
|
|
if profile.active then
|
|
return self:EnableSelectedModule()
|
|
end
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
do-- Module handling
|
|
local IsAddOnLoaded, LoadAddOn =
|
|
IsAddOnLoaded, LoadAddOn
|
|
|
|
local oldModule
|
|
|
|
function WIC:EnableSelectedModule()
|
|
local name = self.db.profile.selectedModuleName
|
|
local addonName = self.RegisteredModulesWithLoadOnDemand[name]
|
|
|
|
if name and addonName then
|
|
if not IsAddOnLoaded(addonName) then
|
|
local loaded, resason = LoadAddOn(self.RegisteredModulesWithLoadOnDemand[name])
|
|
if not loaded then
|
|
self:Printf(L["Can't load module %s because %s"], name, _G["ADDON_"..resason] or resason)
|
|
|
|
return false, resason
|
|
end
|
|
end
|
|
|
|
|
|
local handle = self.RegisteredModules[name]
|
|
local selectModule = LibStub("AceAddon-3.0"):GetAddon(handle, true) or _G[handle]
|
|
if selectModule and type(selectModule.Enable) == "function" then
|
|
if oldModule and type(oldModule.Disable) == "function" then
|
|
oldModule:Disable()
|
|
end
|
|
|
|
oldModule = selectModule
|
|
|
|
return selectModule:Enable()
|
|
else
|
|
self:Print(not selectModule and L["Module not found."] or L["Module hasn't needed functions."] )
|
|
return false
|
|
end
|
|
else
|
|
self:Printf(L["Can't load module. %s"], (not name and L["No module selected!"] or not addonName and L["Addon name not found!"] or "") )
|
|
return false
|
|
end
|
|
end
|
|
|
|
function WIC:SelectModuleIsEnabled()
|
|
local activeModule = oldModule
|
|
if not activeModule then
|
|
local name = self.db.profile.selectedModuleName
|
|
local handle = self.RegisteredModules[name]
|
|
activeModule = LibStub("AceAddon-3.0"):GetAddon(handle, true) or _G[handle]
|
|
end
|
|
if type(activeModule.IsEnabled) == "function" then
|
|
return activeModule:IsEnabled()
|
|
end
|
|
return false
|
|
end
|
|
end
|
|
|
|
function WIC:DisableSelectedModule()
|
|
local name = self.db.profile.selectedModuleName
|
|
--[===[@debug@
|
|
self:Print("Disable Module: ", name)
|
|
--@end-debug@]===]
|
|
if name then
|
|
local handle = self.RegisteredModules[name]
|
|
local selectModule = LibStub("AceAddon-3.0"):GetAddon(handle, true) or _G[handle]
|
|
|
|
--[===[@debug@
|
|
self:Print("selectModule: ", selectModule, ", type: ", type(selectModule), ", selectModule.Disable type: ", type(selectModule.Disable))
|
|
--@end-debug@]===]
|
|
|
|
if selectModule and type(selectModule.Disable) == "function" then
|
|
selectModule:Disable()
|
|
--[===[@debug@
|
|
self:Print("Module disabled")
|
|
--@end-debug@]===]
|
|
end
|
|
end
|
|
end
|
|
|
|
do-- CanInvite
|
|
local IsInGroup, UnitIsGroupLeader, UnitIsGroupAssistant, GetInstanceInfo =
|
|
IsInGroup, UnitIsGroupLeader, UnitIsGroupAssistant, GetInstanceInfo
|
|
local LE_PARTY_CATEGORY_INSTANCE = LE_PARTY_CATEGORY_INSTANCE
|
|
|
|
function WIC:CanInvite()
|
|
--if _G.IsInGroup(_G.LE_PARTY_CATEGORY_INSTANCE) and select(3, _G.GetInstanceInfo() ) ~= 14 then
|
|
--if select(3, _G.GetInstanceInfo() ) ~= 7 then
|
|
if IsInGroup(LE_PARTY_CATEGORY_INSTANCE) then
|
|
-- we can not invite when in a instance group or can we?
|
|
local _, _, difficultyID = GetInstanceInfo()
|
|
if difficultyID ~= 7 -- LFR
|
|
and difficultyID ~= 17 -- LFR 10-30
|
|
and difficultyID ~= 1 -- Normal
|
|
and difficultyID ~= 2 --[[Heroic]] then
|
|
-- Print infos only a limit time
|
|
if self.db.char.info.lfr_block < self.db.char.infoMax.lfr_block then
|
|
self:Printf(L["You are in an instance group and not in LFR or LFG group. When you can invite here players let me know it."])
|
|
local name, instanceType, difficultyName, maxPlayers, dynamicDifficulty, isDynamic, instanceMapID, instanceGroupSize
|
|
name, instanceType, difficultyID, difficultyName, maxPlayers, dynamicDifficulty, isDynamic, instanceMapID, instanceGroupSize = _G.GetInstanceInfo()
|
|
local info = "instanceType:"..instanceType..", difficultyID:"..difficultyID..", difficultyName:"..difficultyName
|
|
self:Printf(L["And show me this infos: %s"], info)
|
|
self.db.char.info.lfr_block = self.db.char.info.lfr_block + 1
|
|
end
|
|
|
|
-- hope nothing explodes..
|
|
return UnitIsGroupLeader("player") or UnitIsGroupAssistant("player") or not IsInGroup()
|
|
end
|
|
return false
|
|
else
|
|
return UnitIsGroupLeader("player") or UnitIsGroupAssistant("player") or not IsInGroup()
|
|
end
|
|
end
|
|
end
|
|
|
|
do-- CheckGroupSize
|
|
local ConvertToRaid, IsInRaid, GetNumGroupMembers
|
|
= ConvertToRaid, IsInRaid, GetNumGroupMembers
|
|
local LE_PARTY_CATEGORY_HOME, MAX_PARTY_MEMBERS
|
|
= LE_PARTY_CATEGORY_HOME, MAX_PARTY_MEMBERS
|
|
|
|
function WIC:CheckGroupSize()
|
|
if not IsInRaid() and GetNumGroupMembers(LE_PARTY_CATEGORY_HOME) > MAX_PARTY_MEMBERS then
|
|
if self.db.profile.convertGroupToRaid then
|
|
ConvertToRaid()
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
end
|
|
|
|
do-- IsQueueProtected / IsStatusProtected
|
|
local BNSendWhisper, SendChatMessage, GetLFGMode, GetMaxBattlefieldID, GetBattlefieldStatus, UnitIsAFK, UnitIsDND, UnitIsUnit, GetCVar, SetCVar =
|
|
BNSendWhisper, SendChatMessage, GetLFGMode, GetMaxBattlefieldID, GetBattlefieldStatus, UnitIsAFK, UnitIsDND, UnitIsUnit, GetCVar, SetCVar
|
|
|
|
local function sendReturnMessage(name, presenceID, message)
|
|
if presenceID then
|
|
BNSendWhisper(presenceID, message)
|
|
elseif name and not UnitIsUnit("player", name) then
|
|
SendChatMessage(message, "WHISPER", nil, name)
|
|
end
|
|
end
|
|
|
|
function WIC:IsQueueProtected(name, presenceName, presenceID)
|
|
if not name or (name and presenceName and not presenceID) or (name and presenceID and not presenceName) then error("Usage: IsQueueProtected(name) or IsQueueProtected(toonName, presenceName, presenceID") end
|
|
|
|
local printName = presenceName and format(L["%s (%s)"], presenceName or L["<No name given>"], name or L["<No toon name given>"]) or name
|
|
|
|
-- Look for queue Protection
|
|
for id, data in pairs(self.db.profile.queueProtection) do
|
|
if type(id) == "number" and data.blockInvites then
|
|
local mode = GetLFGMode(id)
|
|
if mode then
|
|
if data.sendMessage and len(data.returnMessage) > 1 then
|
|
if presenceID then
|
|
sendReturnMessage(name, presenceID, data.returnMessage)
|
|
else
|
|
sendReturnMessage(name, nil, data.returnMessage)
|
|
end
|
|
end
|
|
|
|
self:Printf(L["Your are in a LF-Queue. Can't invite %s"], printName)
|
|
return true
|
|
end
|
|
elseif id == LF_QUEUE_PVP and data.blockInvites then
|
|
for i=1, GetMaxBattlefieldID() do
|
|
local status = GetBattlefieldStatus(i)
|
|
if status ~= "none" then
|
|
if data.sendMessage and len(data.returnMessage) > 1 then
|
|
if presenceID then
|
|
sendReturnMessage(name, presenceID, data.returnMessage)
|
|
else
|
|
sendReturnMessage(name, nil, data.returnMessage)
|
|
end
|
|
end
|
|
|
|
self:Printf(L["Your are in a LF-Queue. Can't invite %s"], printName)
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
function WIC:IsStatusProtected(name, presenceName, presenceID)
|
|
if not name or (name and presenceName and not presenceID) or (name and presenceID and not presenceName) then error("Usage: IsQueueProtected(name) or IsQueueProtected(toonName, presenceName, presenceID") end
|
|
|
|
local printName = presenceName and format(L["%s (%s)"], presenceName or L["<No name given>"], name or L["<No toon name given>"]) or name
|
|
|
|
if UnitIsAFK("player") then
|
|
local afkProtection = self.db.profile.statusProtection.AFK
|
|
|
|
if afkProtection.sendMessage then
|
|
local returnMessage = afkProtection.returnMessage
|
|
if len(returnMessage) > 1 then
|
|
local autoClearAFK = GetCVar("autoClearAFK")
|
|
if autoClearAFK ~= "0" then
|
|
SetCVar("autoClearAFK", "0")
|
|
end
|
|
|
|
if presenceID then
|
|
sendReturnMessage(name, presenceID, returnMessage)
|
|
else
|
|
sendReturnMessage(name, nil, returnMessage)
|
|
end
|
|
|
|
-- re-set autoClearAFK value
|
|
SetCVar("autoClearAFK", autoClearAFK)
|
|
end
|
|
end
|
|
|
|
if afkProtection.blockInvites then
|
|
self:Printf(L["Your are AFK. Invite to %s was not sent."], printName)
|
|
return true
|
|
end
|
|
end
|
|
if UnitIsDND("player") then
|
|
local dndProtection = self.db.profile.statusProtection.DND
|
|
|
|
if dndProtection.sendMessage then
|
|
local returnMessage = dndProtection.returnMessage
|
|
if len(returnMessage) > 1 then
|
|
if presenceID then
|
|
sendReturnMessage(name, presenceID, returnMessage)
|
|
else
|
|
sendReturnMessage(name, nil, returnMessage)
|
|
end
|
|
end
|
|
end
|
|
|
|
if dndProtection.blockInvites then
|
|
self:Printf(L["Your are DND. Haven't send an invite to %s"], printName)
|
|
return true
|
|
end
|
|
end
|
|
|
|
return false
|
|
end
|
|
end
|
|
|
|
--- InviteErrorCodeList
|
|
-- 1: Player is not allowed to invite other players
|
|
-- 2: No BNet/RealID friend is online with this presenceID
|
|
-- 3: Invalid parameters
|
|
-- 4: Maximal group size reached
|
|
-- 5: No WoW toon is online
|
|
-- 6: Invite for this key was throttled
|
|
-- 7: Invite was blocked because of a LF-Queue or Status (AFK/DND)
|
|
|
|
do-- InvitePlayer
|
|
local InviteUnit, Ambiguate =
|
|
InviteUnit, Ambiguate
|
|
|
|
local playerName_Throttle = {}
|
|
|
|
--- Invite player with name
|
|
-- @param (String) name
|
|
-- @return1 (Boolean) true == Invite sent, false == Invite not possible
|
|
-- @return2 (Number) errorCode @see InviteErrorCodeList
|
|
function WIC:InvitePlayer(name)
|
|
if not name then
|
|
return false, 3
|
|
end
|
|
|
|
if self:CanInvite() then
|
|
if self:IsQueueProtected(name) or self:IsStatusProtected(name) then
|
|
return false, 7
|
|
elseif self:CheckGroupSize() then
|
|
local time = GetTime()
|
|
if (playerName_Throttle[name] or 0) < time then
|
|
playerName_Throttle[name] = time + self.db.profile.inviteThrottleTime
|
|
--_G.InviteUnit( self:UniformPlayerName(name) )
|
|
InviteUnit( Ambiguate(name, "none") )
|
|
return true
|
|
else
|
|
return false, 6
|
|
end
|
|
else
|
|
self:Printf(L["Maximal group size reached. Can't invite %s"], name)
|
|
return false, 4
|
|
end
|
|
else
|
|
return false, 1
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
do-- InviteBNet
|
|
local BNGetFriendIndex, BNGetNumFriendGameAccounts, BNGetFriendGameAccountInfo, BNGetFriendInfo, UnitFactionGroup =
|
|
BNGetFriendIndex, BNGetNumFriendGameAccounts, BNGetFriendGameAccountInfo, BNGetFriendInfo, UnitFactionGroup
|
|
local BNET_CLIENT_WOW, RAID_CLASS_COLORS =
|
|
BNET_CLIENT_WOW, RAID_CLASS_COLORS
|
|
|
|
local toonCache = {}
|
|
|
|
--- Invite player over Battle.net
|
|
-- @paramsig presenceID [, friendIndex]
|
|
-- @paramsig nil, friendIndex
|
|
-- @param (presenceID) presenceID
|
|
-- @param (Number) friendIndex
|
|
-- @return1 (Boolean) true: Invite sent, false: Invite not possible
|
|
-- @return2 (Number) errorCode @see InviteErrorCodeList
|
|
--[===[@debug@
|
|
function WIC:InviteBNet(presenceID, friendIndex, debug)
|
|
--@end-debug@]===]
|
|
--@non-debug@
|
|
function WIC:InviteBNet(presenceID, friendIndex)
|
|
--@end-non-debug@
|
|
if not self:CanInvite() then
|
|
return false, 1
|
|
end
|
|
|
|
if type(friendIndex) ~= "number" and presenceID then
|
|
friendIndex = BNGetFriendIndex(presenceID)
|
|
if not friendIndex then
|
|
return false, 2
|
|
end
|
|
elseif type(friendIndex) ~= "number" then
|
|
return false, 3
|
|
end
|
|
|
|
local numToons = BNGetNumFriendGameAccounts(friendIndex)
|
|
local toonCount = 0
|
|
for toonIndex=1, numToons do
|
|
local hasFocus, toonName, client, realmName, realmID, faction, race, classLocalized, guild, zoneName, level, gameText, broadcastText, broadcastTime, canSoR, toonID = BNGetFriendGameAccountInfo(friendIndex, toonIndex)
|
|
if client == BNET_CLIENT_WOW then
|
|
toonCount = toonCount + 1
|
|
toonCache[toonCount] = toonCache[toonCount] or {}
|
|
|
|
toonCache[toonCount].class = self.LOOKUP_LOCALIZED_CLASS_NAMES[classLocalized] or "WARRIOR"
|
|
toonCache[toonCount].toonID = toonID
|
|
toonCache[toonCount].faction = faction
|
|
toonCache[toonCount].toonName = toonName
|
|
toonCache[toonCount].realmName = realmName
|
|
|
|
toonCache[toonCount].presenceID, toonCache[toonCount].presenceName = BNGetFriendInfo(friendIndex)
|
|
end
|
|
end
|
|
|
|
--[===[@debug@
|
|
if debug then
|
|
toonCount = 3
|
|
|
|
toonCache[1] = toonCache[1] or {}
|
|
toonCache[1].class = "DRUID"
|
|
toonCache[1].toonID = 0
|
|
toonCache[1].faction = "Alliance"
|
|
toonCache[1].toonName = "Areko"
|
|
toonCache[1].realmName = "Alleria"
|
|
toonCache[1].presenceName = "Areko#0000"
|
|
toonCache[1].presenceID = 0
|
|
|
|
toonCache[2] = toonCache[2] or {}
|
|
toonCache[2].class = "HUNTER"
|
|
toonCache[2].toonID = 0
|
|
toonCache[2].faction = "Alliance"
|
|
toonCache[2].toonName = "Tânuri"
|
|
toonCache[2].realmName = "Alleria"
|
|
toonCache[2].presenceName = "Tanuri#0000"
|
|
toonCache[2].presenceID = 0
|
|
|
|
toonCache[3] = toonCache[3] or {}
|
|
toonCache[3].class = "MAGE"
|
|
toonCache[3].toonID = 0
|
|
toonCache[3].faction = "Horde"
|
|
toonCache[3].toonName = "Keks"
|
|
toonCache[3].realmName = "Alleria"
|
|
toonCache[3].presenceName = "Keks#0000"
|
|
toonCache[3].presenceID = 0
|
|
end
|
|
--@end-debug@]===]
|
|
|
|
if toonCount > 0 then
|
|
if toonCount == 1 then
|
|
local toon = toonCache[1]
|
|
return self:InviteToon(toon.toonID, toon.toonName, toon.presenceName, toon.presenceID)
|
|
else
|
|
-- \124 > |
|
|
local linkTemplate = "[|H%s:%s|h%s|h]"
|
|
local colourTemplate = "|c%s%s|r"
|
|
local alliance
|
|
local horde
|
|
local colours = _G.CUSTOM_CLASS_COLORS or RAID_CLASS_COLORS
|
|
|
|
for i=1,toonCount do
|
|
local toon = toonCache[i]
|
|
|
|
local linkData = toon.toonID..":"..toon.toonName..":"..toon.presenceName..":"..toon.presenceID
|
|
local name = self:UniformPlayerName(toon.toonName, toon.realmName)
|
|
local colour = colours[toon.class].colorStr or "FFFFFFFF"
|
|
--[===[@debug@
|
|
if debug then
|
|
linkData = linkData..":DEBUG"
|
|
end
|
|
--@end-debug@]===]
|
|
|
|
local msg = format(colourTemplate, colour, format(linkTemplate, self.TYPES.LINK, linkData, name) )
|
|
|
|
if toon.faction == "Horde" then
|
|
horde = horde and horde..", "..msg or msg
|
|
elseif toon.faction == "Alliance" then
|
|
alliance = alliance and alliance..", "..msg or msg
|
|
else
|
|
horde = horde and horde..", "..msg or msg
|
|
alliance = alliance and alliance..", "..msg or msg
|
|
end
|
|
end
|
|
|
|
local factionGroup = UnitFactionGroup("player")
|
|
self:Printf(L["%s is with more then one toon online. Choose which toons should be invited. Click on the name to invite."], toonCache[1].presenceName )
|
|
|
|
if factionGroup == "Alliance" then
|
|
if alliance then
|
|
self:Printf(L["Alliance toons: %s"], alliance )
|
|
end
|
|
if horde then
|
|
self:Printf(L["Horde toons: %s"], horde )
|
|
end
|
|
else
|
|
if horde then
|
|
self:Printf(L["Horde toons: %s"], horde )
|
|
end
|
|
if alliance then
|
|
self:Printf(L["Alliance toons: %s"], alliance )
|
|
end
|
|
end
|
|
|
|
return true, toonCount
|
|
end
|
|
else
|
|
local _, presenceName = BNGetFriendInfo(friendIndex)
|
|
self:Printf(L["%s is not online in World of Warcraft."], presenceName)
|
|
return false, 5
|
|
end
|
|
end
|
|
end
|
|
|
|
do-- InviteToon
|
|
local BNInviteFriend = BNInviteFriend
|
|
|
|
local battleNet_Throttle = {}
|
|
|
|
function WIC:InviteToon(toonID, toonName, presenceName, presenceID)
|
|
if not toonID then
|
|
return false, 3
|
|
end
|
|
|
|
if self:IsQueueProtected(toonName, presenceName, presenceID) or self:IsStatusProtected(toonName, presenceName, presenceID) then
|
|
return false, 7
|
|
elseif self:CheckGroupSize() then
|
|
local time = GetTime()
|
|
if (battleNet_Throttle[toonID] or 0) < time then
|
|
battleNet_Throttle[toonID] = time + self.db.profile.inviteThrottleTime
|
|
BNInviteFriend( toonID )
|
|
return true
|
|
else
|
|
return false, 6
|
|
end
|
|
else
|
|
self:Printf(L["Maximal group size reached. Can't invite %s"], format(L["%s (%s)"], presenceName or L["<No name given>"], toonName or L["<No toon name given>"]) )
|
|
return false, 4
|
|
end
|
|
end
|
|
end
|
|
|
|
--- Returns uniformed player or guild name
|
|
-- @paramsig playerName [, realmOverride]
|
|
-- @param (String) playerName/guildName
|
|
-- @param (String, optional) realmOverride
|
|
--
|
|
-- @return "Name-Realm", "Name", "Realm"
|
|
do
|
|
local homeRealm = GetRealmName()
|
|
local dash = "-"
|
|
function WIC:UniformPlayerName(playerName, realmOverride)
|
|
local name = playerName
|
|
local realm = homeRealm
|
|
|
|
if find(playerName, dash) then
|
|
name, realm = split(dash, playerName, 2)
|
|
end
|
|
|
|
realm = realmOverride or realm
|
|
|
|
return name..dash..realm, name, realm
|
|
end
|
|
|
|
function WIC:UniformGuildName(guildName, realmOverride)
|
|
-- same as player
|
|
return self:UniformPlayerName(guildName, realmOverride)
|
|
end
|
|
end
|
|
|
|
local optionHandler = {}
|
|
function optionHandler:Set(info, value, ...)
|
|
local name = info[#info]
|
|
WIC.db.profile[name] = value
|
|
end
|
|
|
|
function optionHandler:Get(info, value, ...)
|
|
local name = info[#info]
|
|
return WIC.db.profile[name]
|
|
end
|
|
|
|
function optionHandler:SetActive(info, value, ...)
|
|
self:Set(info, value, ...)
|
|
WIC:CheckEnabledState("", WIC.db)
|
|
end
|
|
|
|
function optionHandler:SetModule(info, value, ...)
|
|
self:Set(info, value, ...)
|
|
if WIC:IsEnabled() then
|
|
WIC:EnableSelectedModule()
|
|
end
|
|
end
|
|
function optionHandler:SetQueue(info, value, ...)
|
|
local name = info[#info]
|
|
|
|
WIC.db.profile.queueProtection[info.arg][name] = value
|
|
end
|
|
function optionHandler:GetQueue(info, value, ...)
|
|
local name = info[#info]
|
|
|
|
return WIC.db.profile.queueProtection[info.arg][name]
|
|
end
|
|
function optionHandler:SetStatus(info, value, ...)
|
|
local name = info[#info]
|
|
|
|
WIC.db.profile.statusProtection[info.arg][name] = value
|
|
end
|
|
function optionHandler:GetStatus(info, value, ...)
|
|
local name = info[#info]
|
|
|
|
return WIC.db.profile.statusProtection[info.arg][name]
|
|
end
|
|
function optionHandler:IsReturnMessageHidden(info)
|
|
return not WIC.db.profile.queueProtection[info.arg].sendMessage
|
|
end
|
|
|
|
local options = {
|
|
type = "group",
|
|
name = L["WisperInvite Core Settings"],
|
|
handler = optionHandler,
|
|
set = "Set",
|
|
get = "Get",
|
|
args = {
|
|
active = {
|
|
type = "toggle",
|
|
name = L["Active"],
|
|
desc = L["Is this profile enabled."],
|
|
width = "full",
|
|
set = "SetActive",
|
|
order = 1,
|
|
},
|
|
selectedModuleName = {
|
|
type = "select",
|
|
name = L["Active module"],
|
|
desc = L["Choose active module."],
|
|
values = WIC.RegisteredModulesTranslatedName,
|
|
set = "SetModule",
|
|
order = 2,
|
|
},
|
|
convertGroupToRaid = {
|
|
type = "toggle",
|
|
name = L["Auto convert"],
|
|
desc = L["Convert group to raid when group has reached maximal size."],
|
|
width = "full",
|
|
order = 3,
|
|
},
|
|
inviteThrottleTime = {
|
|
type = "range",
|
|
name = L["Invite Throttle"],
|
|
desc = L["Delay(seconds) needed between to invites of the same player before, WhisperInvite can send a new invite."],
|
|
min = 0.5,
|
|
max = 120,
|
|
softMin = 6,
|
|
softMax = 30,
|
|
bigStep = 1,
|
|
step = 0.1,
|
|
--width = "full",
|
|
order = 4,
|
|
},
|
|
statusProtection = {
|
|
type = "group",
|
|
inline = true,
|
|
name = L["AFK/DND Protection"],
|
|
set = "SetStatus",
|
|
get = "GetStatus",
|
|
args = {
|
|
descriptionText = {
|
|
type = "description",
|
|
name = L["Choose when you don't want to automatic invite other players when you are AFK or DND.\nAnd if to send a message."],
|
|
fontSize = "normal",
|
|
order = 0,
|
|
},
|
|
AFK = {
|
|
type = "group",
|
|
name = DEFAULT_AFK_MESSAGE,
|
|
inline = true,
|
|
args = {
|
|
blockInvites = {
|
|
type = "toggle",
|
|
name = L["Block invites"],
|
|
desc = L["Block invites when you are AFK"],
|
|
arg = "AFK",
|
|
order = 1,
|
|
},
|
|
sendMessage = {
|
|
type = "toggle",
|
|
name = L["Send an answer"],
|
|
desc = L["Send a message to inform that you are AFK."],
|
|
arg = "AFK",
|
|
order = 2,
|
|
},
|
|
returnMessage = {
|
|
type = "input",
|
|
name = L["Answer"],
|
|
desc = L["The message you will send."],
|
|
width = "full",
|
|
arg = "AFK",
|
|
order = 3,
|
|
},
|
|
},
|
|
},
|
|
DND = {
|
|
type = "group",
|
|
name = DEFAULT_DND_MESSAGE,
|
|
inline = true,
|
|
args = {
|
|
blockInvites = {
|
|
type = "toggle",
|
|
name = L["Block invites"],
|
|
desc = L["Block invites when you are DND"],
|
|
arg = "DND",
|
|
order = 1,
|
|
},
|
|
sendMessage = {
|
|
type = "toggle",
|
|
name = L["Send an answer"],
|
|
desc = L["Send a message to inform that you are DND."],
|
|
arg = "DND",
|
|
order = 2,
|
|
},
|
|
returnMessage = {
|
|
type = "input",
|
|
name = L["Answer"],
|
|
desc = L["The message you will send."],
|
|
width = "full",
|
|
arg = "DND",
|
|
order = 3,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
queueProtection = {
|
|
type = "group",
|
|
inline = true,
|
|
name = L["LF-Queue Protection"],
|
|
set = "SetQueue",
|
|
get = "GetQueue",
|
|
args = {},
|
|
},
|
|
},
|
|
}
|
|
|
|
local updateConfig
|
|
do-- updateConfig
|
|
local LFG_CATEGORY_NAMES, QUEUED_STATUS_UNKNOWN, PVP =
|
|
LFG_CATEGORY_NAMES, QUEUED_STATUS_UNKNOWN, PVP
|
|
|
|
function updateConfig()
|
|
local args = wipe(options.args.queueProtection.args)
|
|
for id in pairs(WIC.db.profile.queueProtection) do
|
|
local name
|
|
if type(id) == "number" then
|
|
name = LFG_CATEGORY_NAMES[id] or QUEUED_STATUS_UNKNOWN
|
|
else
|
|
name = PVP
|
|
end
|
|
|
|
args[name] = {
|
|
type = "group",
|
|
name = name,
|
|
inline = true,
|
|
args = {
|
|
blockInvites = {
|
|
type = "toggle",
|
|
name = L["Block invites"],
|
|
desc = format(L["When in the %q Queue block invites."], name),
|
|
arg = id,
|
|
order = 1,
|
|
},
|
|
sendMessage = {
|
|
type = "toggle",
|
|
name = L["Send an answer"],
|
|
desc = L["Send a message to inform that you have not send an invite because your are in a LF-Queue."],
|
|
arg = id,
|
|
order = 2,
|
|
},
|
|
returnMessage = {
|
|
type = "input",
|
|
name = L["Answer"],
|
|
desc = L["The message you will send."],
|
|
arg = id,
|
|
--hidden = "IsReturnMessageHidden",
|
|
width = "full",
|
|
order = 3,
|
|
},
|
|
},
|
|
}
|
|
end
|
|
args.descriptionText = {
|
|
type = "description",
|
|
name = L["Choose when you don't want to automatic invite other players when you are in a LF-Queue.\n"],
|
|
fontSize = "normal",
|
|
order = 0,
|
|
}
|
|
end
|
|
end
|
|
|
|
local configIsRegistered = false
|
|
local unregisteredConfigs = {}
|
|
function WIC:RegisterConfig()
|
|
|
|
updateConfig()
|
|
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable(ADDONNAME.."Options", options)
|
|
LibStub("AceConfigDialog-3.0"):AddToBlizOptions(ADDONNAME.."Options", ADDONNAME)
|
|
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable(ADDONNAME.."Profile", LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db) )
|
|
LibStub("AceConfigDialog-3.0"):AddToBlizOptions(ADDONNAME.."Profile", L["Profile"], ADDONNAME)
|
|
|
|
configIsRegistered = true
|
|
for appName, name in pairs(unregisteredConfigs) do
|
|
self:AddModuleConfig(appName, name)
|
|
end
|
|
wipe(unregisteredConfigs)
|
|
end
|
|
|
|
--- Use to register your DB as namespace of the core DB
|
|
-- @param (String) name
|
|
-- @param (table) defaults
|
|
function WIC:RegisterNamespace(name, namespaceDefaults)
|
|
if type(namespaceDefaults) ~= "table" then
|
|
namespaceDefaults = nil
|
|
end
|
|
return self.db:RegisterNamespace(name, namespaceDefaults)
|
|
end
|
|
|
|
--- Add your config to BlizzOptions as child of WhisperInvite
|
|
-- @param (String) appName - same as used in AceConfigRegistry:RegisterOptionsTable()
|
|
-- @param (String) name - Display name
|
|
function WIC:AddModuleConfig(appName, name)
|
|
if configIsRegistered then
|
|
if appName and LibStub("AceConfigRegistry-3.0"):GetOptionsTable(appName) then
|
|
LibStub("AceConfigDialog-3.0"):AddToBlizOptions(appName, name or appName, ADDONNAME)
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
else
|
|
unregisteredConfigs[appName] = name or appName
|
|
end
|
|
end
|
|
|
|
function WIC:NotifyChange()
|
|
LibStub("AceConfigRegistry-3.0"):NotifyChange(ADDONNAME.."Options")
|
|
end
|
|
|