-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLibVersionCheck-1.0.lua
More file actions
249 lines (209 loc) · 8.4 KB
/
LibVersionCheck-1.0.lua
File metadata and controls
249 lines (209 loc) · 8.4 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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
--- This library can be freely redistributed and used in addon code for "World of Warcraft".
--- You probably wouldn't want to though, it's not particularly useful, and pretty bad..
--- It's designed for 1 single purpose, and that is to sate my curiosity. So there's no real documentation or whatever.
--- It's designed as a drop-in lib, and has the required dependencies embedded in itself, cause I'm lazy ;-)
--- Oh, and I'd say it's in alpha, for what it's worth.
local embedAddonName = ...;
local MAJOR, MINOR = "LibVersionCheck-1.0", 4;
--- @class LibVersionCheck-1.0
local LibVersionCheck = LibStub:NewLibrary(MAJOR, MINOR);
RunNextFrame(function() LibStub(MAJOR):AutoRegister(embedAddonName); end);
if not LibVersionCheck then return; end
local CTL = ChatThrottleLib;
local player = UnitName("player") .. "-" .. GetRealmName();
local prefix = "LibVCheck-1.0";
local broadcastMsgFormat = "BV1_%s\030%s"; -- broadcast version 1
local broadcastMsgCapture = "^" .. broadcastMsgFormat:format("(.+)", "(.+)") .. "$";
local whisperMsgFormat = "DV1_%s\030%s"; -- direct version 1
local whisperMsgCapture = "^" .. whisperMsgFormat:format("(.+)", "(.+)") .. "$";
--- @return string?
local function getGroupChannel()
local numGroupMembers = GetNumGroupMembers();
if numGroupMembers <= 1 then
return nil;
end
local hasPlayers = false;
for i = 1, numGroupMembers do
if UnitIsPlayer("party" .. i) then
hasPlayers = true;
break;
end
end
if not hasPlayers then
return nil;
end
if IsInInstance() then
return "INSTANCE_CHAT";
end
if IsInRaid() then
return "RAID";
end
if IsInGroup() then
return "PARTY";
end
return nil;
end
do -- setup
--- @type table<string, boolean> [addonName] = true
LibVersionCheck.disableAutoRegister = LibVersionCheck.disableAutoRegister or {};
--- @type table<string, string> [addonName] = version
LibVersionCheck.addonVersions = LibVersionCheck.addonVersions or {};
--- @type table<string, table<string, string>> [addonName] = { [playerName] = version }
LibVersionCheck.playerVersions = LibVersionCheck.playerVersions or {};
LibVersionCheck.onVersionChangedCallbacks = LibVersionCheck.onVersionChangedCallbacks or {};
if not LibVersionCheck.prefixRegistered then
C_ChatInfo.RegisterAddonMessagePrefix(prefix);
LibVersionCheck.prefixRegistered = true;
end
end
--- @param addonName string
--- @public
function LibVersionCheck:DisableAutoRegister(addonName)
self.disableAutoRegister[addonName] = true;
end
--- @param addonName string
--- @param version string
--- @public
function LibVersionCheck:Register(addonName, version)
self.addonVersions[addonName] = version;
self.playerVersions[addonName] = self.playerVersions[addonName] or {};
if self.isInGuild then
self:SendVersion("GUILD", addonName);
end
local channel = getGroupChannel();
if channel then
self:SendVersion(channel, addonName);
end
end
--- @param addonName string
--- @return table<string, string> # [playerName-realmName] = version
--- @public
function LibVersionCheck:GetAddonVersionsForAddon(addonName)
return self.playerVersions[addonName] or {};
end
--- @param playerName string # playerName-realmName
--- @return table<string, string> # [addonName] = version
--- @public
function LibVersionCheck:GetAddonVersionsForPlayer(playerName)
local versions = {};
for addonName, playerVersions in pairs(self.playerVersions) do
versions[addonName] = playerVersions[playerName];
end
return versions;
end
--- @param channel string
--- @param addonName string? # if nil, requests for all registered addons
--- @param target string? # only required for WHISPER channel
--- @public
function LibVersionCheck:RequestVersion(channel, addonName, target)
self:SendVersion(channel, addonName, target);
end
--- @param addonName string
--- @public
function LibVersionCheck:ResetAddonVersionCache(addonName)
self.playerVersions[addonName] = {};
end
--- @param callback fun(playerName: string, addonName: string, version: string, previousVersion: string)
---@param addonName string? # optionally filter to a specific addon
function LibVersionCheck:RegisterOnVersionChangedCallback(callback, addonName)
addonName = addonName or "";
self.onVersionChangedCallbacks[addonName] = self.onVersionChangedCallbacks[addonName] or {};
table.insert(self.onVersionChangedCallbacks[addonName], callback);
end
--- @param addonName string
--- @private
function LibVersionCheck:AutoRegister(addonName)
if self.disableAutoRegister[addonName] then return; end
local version = C_AddOns.GetAddOnMetadata(addonName, "Version");
if not version or version == "" then
version = "Unknown Version";
end
self:Register(addonName, version);
end
--- @param channel string
--- @param addonName string? # if nil, requests for all registered addons
--- @param target string? # only required for WHISPER channel
--- @private
function LibVersionCheck:SendVersion(channel, addonName, target)
if not addonName then
for addonName, _ in pairs(self.addonVersions) do
self:SendVersion(channel, addonName);
end
return;
end
local version = self.addonVersions[addonName];
if not version then return; end
local format = target and whisperMsgFormat or broadcastMsgFormat;
CTL:SendAddonMessage("NORMAL", prefix, format:format(addonName, version), channel, target);
end
--- @param sender string
--- @param addonName string
--- @param version string
--- @param isBroadcast boolean
--- @private
function LibVersionCheck:ReceivedVersion(sender, addonName, version, isBroadcast)
self.playerVersions[addonName] = self.playerVersions[addonName] or {};
local previousVersion = self.playerVersions[addonName][sender];
self.playerVersions[addonName][sender] = version;
if previousVersion ~= version then
self:OnVersionChanged(sender, addonName, version, previousVersion);
end
if not isBroadcast then return; end
self:SendVersion("WHISPER", addonName, sender);
end
--- @private
function LibVersionCheck:OnVersionChanged(sender, addonName, version, previousVersion)
local callbacks = self.onVersionChangedCallbacks[addonName] or {};
for _, callback in ipairs(callbacks) do
securecallfunction(callback, sender, addonName, version, previousVersion);
end
local globalCallbacks = self.onVersionChangedCallbacks[""] or {};
for _, callback in ipairs(globalCallbacks) do
securecallfunction(callback, sender, addonName, version, previousVersion);
end
end
LibVersionCheck.events = LibVersionCheck.events or CreateFrame("Frame");
LibVersionCheck.events:SetScript("OnEvent", function(self, event, ...)
self[event](self, ...);
end);
local e = LibVersionCheck.events;
e:UnregisterAllEvents(); -- unregister all events from unupgraded lib instances
function e:PLAYER_GUILD_UPDATE(unit)
if unit ~= "player" then return; end
RunNextFrame(function()
LibVersionCheck.isInGuild = IsInGuild();
if LibVersionCheck.isInGuild then
local previousGuild = LibVersionCheck.playerGuild;
local guildName, _, _, guildRealm = GetGuildInfo("player");
if not guildName then return; end -- can happen during the initial login
LibVersionCheck.playerGuild = guildName .. "-" .. (guildRealm or '');
if previousGuild ~= LibVersionCheck.playerGuild then
LibVersionCheck:SendVersion("GUILD");
end
end
end);
end
e:RegisterEvent("PLAYER_GUILD_UPDATE");
function e:GROUP_JOINED()
local channel = getGroupChannel();
if not channel or GetNumGroupMembers() <= 1 then return; end
LibVersionCheck:SendVersion(channel);
end
e:RegisterEvent("GROUP_JOINED");
function e:CHAT_MSG_ADDON(receivedPrefix, text, channel, sender)
if receivedPrefix ~= prefix or sender == player then return; end
local addonName, version;
addonName, version = text:match(whisperMsgCapture);
if addonName and version then
local isBroadcast = false;
LibVersionCheck:ReceivedVersion(sender, addonName, version, isBroadcast);
return;
end
addonName, version = text:match(broadcastMsgCapture);
if addonName and version then
local isBroadcast = true;
LibVersionCheck:ReceivedVersion(sender, addonName, version, isBroadcast);
return;
end
end
e:RegisterEvent("CHAT_MSG_ADDON");