John@98
|
1 local bsk=bsk
|
John@98
|
2 local _G=_G
|
John@98
|
3 local table=table
|
John@98
|
4 local pairs=pairs
|
John@98
|
5 local setmetatable=setmetatable
|
John@98
|
6 local ipairs=ipairs
|
John@98
|
7 local string=string
|
John@98
|
8 local sformat=string.format
|
John@98
|
9 local strsplit=strsplit
|
John@98
|
10 local tostring=tostring
|
John@98
|
11 local type=type
|
John@98
|
12 local unpack=unpack
|
John@98
|
13 local getn=getn
|
John@98
|
14 setfenv(1,bsk)
|
John@98
|
15
|
John@98
|
16 adminList = {}
|
John@98
|
17
|
John@105
|
18 local lastZoneTime = 0
|
John@105
|
19 local function ZoneChanged()
|
John@105
|
20 lastZoneTime = _G.time()
|
John@105
|
21 end
|
John@98
|
22 local function GuildRosterUpdate()
|
John@98
|
23 local guildInfoText = _G.GetGuildInfoText()
|
John@105
|
24 if lastZoneTime+5 > _G.time() then return end -- silly workaround - GGIT() returns "" when you zone in
|
John@98
|
25 local newAdminList = {}
|
John@98
|
26 for line in guildInfoText:gmatch("[^\r\n]+") do
|
John@98
|
27 local l,r = line:match("(.*):(.*)") -- could use wow strsplit had I known about it before writing this
|
John@98
|
28 l = string.trim(l or "")
|
John@98
|
29 r = string.trim(r or "")
|
John@99
|
30 if l == "BSKADMIN" then -- found a juicy line. may contain multiple, comma or space delimited
|
John@98
|
31 local admins = {strsplit(", ",r)}
|
John@98
|
32 for _,a in pairs(admins) do
|
John@98
|
33 a = string.trim(a or "")
|
John@98
|
34 if a ~= "" then
|
John@98
|
35 newAdminList[a] = true
|
John@98
|
36 end
|
John@98
|
37 end
|
John@98
|
38 end
|
John@98
|
39 end
|
John@98
|
40
|
John@103
|
41 if me == "Breuemama" then -- todo: strictly debugging ...
|
John@103
|
42 newAdminList[me] = true
|
John@103
|
43 newAdminList["Breue"] = true
|
John@103
|
44 end
|
John@103
|
45
|
John@98
|
46 if _G.next(adminList) ~= nil then -- had old admins. don't want to spam on initial load
|
John@98
|
47 -- diff new vs old
|
John@98
|
48 for a in pairs(adminList) do
|
John@98
|
49 if not newAdminList[a] then
|
John@98
|
50 print("Admin removed:", a)
|
John@98
|
51 end
|
John@98
|
52 end
|
John@98
|
53 for a in pairs(newAdminList) do
|
John@98
|
54 if not adminList[a] then
|
John@98
|
55 print("Admin added:",a)
|
John@98
|
56 end
|
John@98
|
57 end
|
John@98
|
58 end
|
John@98
|
59 adminList = newAdminList
|
John@99
|
60
|
John@103
|
61 if adminList[me] then -- I'm an admin!
|
John@99
|
62 admin = true
|
John@99
|
63 bsk.db.profile.admin = true
|
John@99
|
64 RegisterAdminChannels()
|
John@99
|
65 else
|
John@99
|
66 admin = false
|
John@99
|
67 bsk.db.profile.admin = false
|
John@99
|
68 UnregisterAdminChannels()
|
John@99
|
69 end
|
John@99
|
70 end
|
John@99
|
71
|
John@99
|
72 function RemoteAdminUpdateReceived(sender,remoteAdminStatusTable)
|
John@99
|
73 if not admin then return end
|
John@99
|
74
|
John@105
|
75 local rs,base,changes = unpack(remoteAdminStatusTable)
|
John@99
|
76 for i,_ in pairs(adminList) do -- update each admin's entry in your own DB
|
John@99
|
77
|
John@105
|
78 if i ~= me then
|
John@105
|
79 -- grab the db copy and the incoming copy for that admin
|
John@105
|
80 if not db.profile.adminStatus then db.profile.adminStatus = {} end
|
John@105
|
81 local dbs = db.profile.adminStatus[i] or {base=0, changes={}}
|
John@105
|
82 local ics = rs[i] or {base=0, changes={}}
|
John@99
|
83
|
John@105
|
84 -- figure out which is better and keep that one
|
John@105
|
85 -- winning criteria:
|
John@105
|
86 -- * broadcast was actually from that person (ie best
|
John@105
|
87 -- verification possible)
|
John@105
|
88 -- * newer base
|
John@105
|
89 -- * same base, more entries
|
John@105
|
90 -- * todo: see if date last observed is a better option
|
John@99
|
91
|
John@105
|
92 if i==sender then
|
John@105
|
93 db.profile.adminStatus[i] = ics
|
John@105
|
94 elseif ics.base > dbs.base or (ics.base==dbs.base and getn(ics.changes) > getn(dbs.changes)) then
|
John@105
|
95 db.profile.adminStatus[i] = ics
|
John@105
|
96 end
|
John@99
|
97 end
|
John@99
|
98 end
|
John@103
|
99
|
John@105
|
100 if changes and getn(changes)>0 then
|
John@105
|
101 IntegrateChangeDiff(base,changes)
|
John@105
|
102 end
|
John@103
|
103
|
John@105
|
104 -- trim if the replies said it's safe
|
John@103
|
105
|
John@105
|
106 local trimPoint = db.profile.time
|
John@105
|
107 -- come up with a tentative starting point (max base)
|
John@105
|
108 for i,v in pairs(db.profile.adminStatus) do
|
John@105
|
109 if v.base > trimPoint then trimPoint = v.base end
|
John@105
|
110 end
|
John@105
|
111
|
John@105
|
112 local pointer = {}
|
John@105
|
113 -- fast forward pointers *past* the trimPoint in each list
|
John@105
|
114 for p,l in pairs(db.profile.adminStatus) do
|
John@105
|
115 pointer[p] = 1
|
John@105
|
116 for i,v in ipairs(l.changes) do
|
John@105
|
117 if v <= trimPoint then
|
John@105
|
118 pointer[p] = i+1 -- "past" the trim point - might point to nil
|
John@105
|
119 else
|
John@105
|
120 break
|
John@103
|
121 end
|
John@103
|
122 end
|
John@103
|
123 end
|
John@105
|
124 print("pointers")
|
John@105
|
125 PrintTable(pointer)
|
John@105
|
126
|
John@103
|
127 for i,v in ipairs(db.profile.changes) do
|
John@105
|
128 if v.time > trimPoint then -- advance to the trim point estimate before doing anything
|
John@105
|
129 -- into uncharted territory, let's see how far we can push it
|
John@105
|
130 local continue = true
|
John@105
|
131 for p,t in pairs(pointer) do
|
John@105
|
132 local dbpapct = db.profile.adminStatus[p].changes[t]
|
John@105
|
133 if dbpapct and dbpapct==v.time then
|
John@105
|
134 pointer[p] = pointer[p]+1
|
John@105
|
135 else
|
John@105
|
136 continue=false
|
John@105
|
137 break
|
John@105
|
138 end
|
John@105
|
139 trimPoint = v.time
|
John@105
|
140 end
|
John@105
|
141 if not continue then break end
|
John@105
|
142 end
|
John@103
|
143 end
|
John@105
|
144 print("pointers")
|
John@105
|
145 PrintTable(pointer)
|
John@105
|
146 if trimPoint > db.profile.time then
|
John@105
|
147
|
John@105
|
148 -- protect trimming back to beginning of previous month so we're not
|
John@105
|
149 -- trimming like madmen
|
John@105
|
150 local ct = _G.date("*t",_G.time())
|
John@105
|
151 ct.month = ct.month-1
|
John@105
|
152 if ct.month < 1 then ct.month = 12 end
|
John@105
|
153 ct.day = 1
|
John@105
|
154 ct.hour = 1
|
John@105
|
155 ct.minute = 0
|
John@105
|
156 ct.sec = 0
|
John@105
|
157 local ts = _G.time(ct)
|
John@105
|
158 print("I think I can trim to",trimPoint,ts)
|
John@105
|
159 TrimLists(ts)
|
John@105
|
160 else
|
John@105
|
161 print("no bother trimming",trimPoint)
|
John@103
|
162 end
|
John@98
|
163 end
|
John@98
|
164
|
John@98
|
165 function InitializeAdmin()
|
John@98
|
166 if not event then
|
John@98
|
167 _G.error("BSK: Improper order of initialization")
|
John@98
|
168 end
|
John@103
|
169 me = _G.UnitName("player")
|
John@99
|
170
|
John@99
|
171 if admin then -- if at last login I was an admin ...
|
John@99
|
172
|
John@99
|
173 -- note that we're not transmitting anything here. we'll do that once we
|
John@99
|
174 -- know for certain we're an admin
|
John@99
|
175
|
John@99
|
176 -- cache the onload status in case it changes in memory later
|
John@99
|
177 onloadAdminStatus = {}
|
John@99
|
178 tcopy(onloadAdminStatus,db.profile.adminStatus)
|
John@99
|
179
|
John@99
|
180 -- update our own entry - safe because comms shouldn't have happened yet
|
John@99
|
181 if not onloadAdminStatus then onloadAdminStatus = {} end
|
John@99
|
182 if not onloadAdminStatus[me] then onloadAdminStatus[me] = {} end
|
John@99
|
183 onloadAdminStatus[me].base = db.profile.time or 0
|
John@99
|
184 onloadAdminStatus[me].changes= {}
|
John@99
|
185 for _,v in ipairs(db.profile.changes) do
|
John@99
|
186 table.insert(onloadAdminStatus[me].changes,v.time) -- only timestamps
|
John@99
|
187 end
|
John@99
|
188
|
John@99
|
189 else -- otherwise store a blank slate
|
John@99
|
190 onloadAdminStatus = {}
|
John@99
|
191 db.profile.adminStatus = nil
|
John@99
|
192 end
|
John@99
|
193
|
John@98
|
194 event:RegisterEvent("GUILD_ROSTER_UPDATE",GuildRosterUpdate)
|
John@105
|
195 event:RegisterEvent("ZONE_CHANGED_NEW_AREA",ZoneChanged)
|
John@105
|
196 event:RegisterEvent("ZONE_CHANGED_INDOORS",ZoneChanged)
|
John@105
|
197 event:RegisterEvent("ZONE_CHANGED",ZoneChanged)
|
John@98
|
198 _G.GuildRoster() -- will eventually force the event to fire
|
John@103
|
199
|
John@103
|
200 if me == "Breuemama" then -- debugging only
|
John@103
|
201 GuildRosterUpdate()
|
John@103
|
202 end
|
John@98
|
203 end
|
John@98
|
204
|
John@98
|
205
|