-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRoster.lua
More file actions
182 lines (169 loc) · 4.65 KB
/
Copy pathRoster.lua
File metadata and controls
182 lines (169 loc) · 4.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
local ADDON_NAME, ns = ...
local Roster = {}
ns.Roster = Roster
-- Normalize "Player-Realm" -> "player" for stable keying.
local function normalize(name)
if not name or name == "" then
return nil
end
local n = name:match("^([^%-]+)") or name
n = n:gsub("%s+$", ""):gsub("^%s+", "")
if n == "" then
return nil
end
return n:lower()
end
Roster.Normalize = normalize
function Roster:Initialize(addon)
self.addon = addon
self.pendingScan = false
self.lastScanAt = 0
addon:RegisterEvent("UPDATE_MOUSEOVER_UNIT", function()
self:LearnFromUnit("mouseover")
end)
addon:RegisterEvent("PLAYER_TARGET_CHANGED", function()
self:LearnFromUnit("target")
end)
addon:RegisterEvent("WHO_LIST_UPDATE", function()
self:OnWhoListUpdate()
end)
end
-- GetGuildInfo() can return nil right after the unit becomes available; retry briefly.
function Roster:LearnFromUnit(unit, retries)
if not UnitExists(unit) or not UnitIsPlayer(unit) then
return
end
local guild = GetGuildInfo(unit)
local target = self.addon.db.realm.targetGuild
if not guild then
retries = retries or 0
if retries < 3 then
C_Timer.After(0.25, function()
self:LearnFromUnit(unit, retries + 1)
end)
end
return
end
if not target or guild:lower() ~= target:lower() then
return
end
local name = UnitName(unit)
if name then
self:Add(name, "auto")
end
end
function Roster:Add(rawName, source)
local key = normalize(rawName)
if not key then
return false
end
if self.addon.db.realm.muted[key] then
return false
end
self.addon.db.realm.muted[key] = true
self.addon.db.realm.learnedAt[key] = time()
return true
end
function Roster:Remove(rawName)
local key = normalize(rawName)
if not key then
return false
end
if not self.addon.db.realm.muted[key] then
return false
end
self.addon.db.realm.muted[key] = nil
self.addon.db.realm.learnedAt[key] = nil
return true
end
function Roster:Has(rawName)
local key = normalize(rawName)
if not key then
return false
end
return self.addon.db.realm.muted[key] == true
end
function Roster:Clear()
wipe(self.addon.db.realm.muted)
wipe(self.addon.db.realm.learnedAt)
end
function Roster:PrintList()
local names = {}
for k in pairs(self.addon.db.realm.muted) do
table.insert(names, k)
end
if #names == 0 then
self.addon:Print("mute list is empty")
return
end
table.sort(names)
self.addon:Print(("muted (%d):"):format(#names))
for _, n in ipairs(names) do
self.addon:Print(" - " .. n)
end
end
-- NOTE: SendWho()/C_FriendList.SendWho() is a protected function. It only works
-- when called from a hardware event (keypress/click), e.g. the user typing
-- "/gm scan". It cannot be driven automatically from a timer, so there is no
-- periodic auto-scan -- the roster fills passively (mouseover/target) plus manual scans.
local SCAN_COOLDOWN = 6 -- /who is rate-limited; ~5s server-side
function Roster:RequestWhoScan()
local guild = self.addon.db.realm.targetGuild
if not guild or guild == "" then
self.addon:Print("no target guild set; use /gm guild <Name>")
return
end
local now = GetTime()
local wait = SCAN_COOLDOWN - (now - self.lastScanAt)
if wait > 0 then
self.addon:Print(("/who is rate-limited, retry in %ds"):format(math.ceil(wait)))
return
end
self.lastScanAt = now
self.pendingScan = true
self.addon:Print(('scanning /who g-"%s" ...'):format(guild))
local query = 'g-"' .. guild .. '"'
if C_FriendList and C_FriendList.SendWho then
C_FriendList.SendWho(query)
else
SendWho(query)
end
end
local function getNumWhoResults()
if C_FriendList and C_FriendList.GetNumWhoResults then
return C_FriendList.GetNumWhoResults()
end
return GetNumWhoResults()
end
local function getWhoInfo(i)
if C_FriendList and C_FriendList.GetWhoInfo then
local info = C_FriendList.GetWhoInfo(i)
if info then
return info.fullName, info.fullGuildName
end
return nil, nil
end
local name, guild = GetWhoInfo(i)
return name, guild
end
function Roster:OnWhoListUpdate()
if not self.pendingScan then
return
end
self.pendingScan = false
local count = getNumWhoResults() or 0
local target = (self.addon.db.realm.targetGuild or ""):lower()
local added = 0
for i = 1, count do
local name, guild = getWhoInfo(i)
if name and guild and guild:lower() == target then
if self:Add(name, "scan") then
added = added + 1
end
end
end
self.addon:Print(("scan: +%d new (%d /who results)"):format(added, count))
if count >= 49 then
self.addon:Print("note: /who returns at most 49 hits; large guilds may need multiple scans with level filters")
end
end