wobin@0
|
1 -- A Twitter client of sorts for World of Warcraft
|
wobin@0
|
2 -- Author: Wobin
|
wobin@0
|
3 -- Email: wobster@gmail.com
|
wobin@0
|
4 --
|
wobin@1
|
5 Squawk = LibStub("AceAddon-3.0"):NewAddon("Squawk")
|
wobin@0
|
6
|
wobin@0
|
7 Squawk.Model = {}
|
wobin@0
|
8 Squawk.View = {}
|
wobin@0
|
9 Squawk.Controller = {}
|
wobin@0
|
10
|
wobin@0
|
11 local Model = Squawk.Model
|
wobin@0
|
12 local View = Squawk.View
|
wobin@0
|
13 local Controller = Squawk.Controller
|
wobin@0
|
14
|
wobin@0
|
15 Model.UserSettings = {}
|
wobin@0
|
16 local Settings = Model.UserSettings
|
wobin@0
|
17
|
wobin@0
|
18 local defaults = {
|
wobin@0
|
19 profile = {
|
wobin@0
|
20 Squawks = {},
|
wobin@0
|
21 Follower = {},
|
wobin@0
|
22 Following = {},
|
wobin@7
|
23 Pending = {},
|
wobin@7
|
24 Requested = {},
|
wobin@0
|
25 Blocked = {},
|
wobin@0
|
26 }
|
wobin@0
|
27 }
|
wobin@0
|
28
|
wobin@0
|
29 function Squawk:OnInitialize()
|
wobin@0
|
30 Model.db = LibStub("AceDB-3.0"):New("SquawkDB", defaults)
|
wobin@4
|
31 Model.Squawks = Model.db.profile.Squawks
|
wobin@0
|
32 Settings.Follower = Model.db.profile.Follower
|
wobin@0
|
33 Settings.Following = Model.db.profile.Following
|
wobin@7
|
34 Settings.Pending = Model.db.profile.Pending
|
wobin@7
|
35 Settings.Requested = Model.db.profile.Requested
|
wobin@0
|
36 Settings.Blocked = Model.db.profile.Blocked
|
wobin@0
|
37 Settings.Private = Model.db.profile.Private
|
wobin@0
|
38
|
wobin@0
|
39 LibStub("AceComm-3.0"):Embed(Controller)
|
wobin@3
|
40 Controller:RegisterComm("Squawk", Controller.ReceiveMessage)
|
wobin@3
|
41
|
wobin@3
|
42 LibStub("AceConsole-3.0"):Embed(View)
|
wobin@0
|
43 end
|
wobin@0
|
44
|
wobin@0
|
45 -- Model --
|
wobin@0
|
46 --[[
|
wobin@0
|
47 --Each Squawk will have the following information:
|
wobin@0
|
48 -- * Owner (Name)
|
wobin@0
|
49 -- * Time (Epoch)
|
wobin@0
|
50 -- * Message (140 characters)
|
wobin@0
|
51 -- * ReplyTo (Name)
|
wobin@0
|
52 -- * Related (Names)
|
wobin@0
|
53 --
|
wobin@0
|
54 -- Each User will have the following lists:
|
wobin@0
|
55 -- * Follower
|
wobin@0
|
56 -- * Following
|
wobin@0
|
57 -- * Blocked
|
wobin@7
|
58 -- * Pending (Requests to follow that you haven't acted on)
|
wobin@7
|
59 -- * Requested (Requests to follow that you have made)
|
wobin@0
|
60 -- * Privacy State
|
wobin@7
|
61 --
|
wobin@7
|
62 -- A user can only request to follow an online person. Requests can be approved
|
wobin@7
|
63 -- on or offline, but the initial request must be made online.
|
wobin@7
|
64 --
|
wobin@7
|
65 -- When a user makes a request to follow a private user, the subsequent paths occur:
|
wobin@7
|
66 -- - Followee is added to Settings.Requested
|
wobin@7
|
67 -- - Followee receives 'follow request' -> (their) Settings.Pending
|
wobin@7
|
68 -- - Followee acts on request -> (their) Settings.Pending cleared
|
wobin@7
|
69 -- 1) Follwer is online
|
wobin@7
|
70 -- - Follower receives 'request accepted' -> Added to Settings.Following and
|
wobin@7
|
71 -- cleared from Settings.Requested
|
wobin@7
|
72 -- 2) Follower is offline
|
wobin@7
|
73 -- - The next time Follower is online and recieves a Squawk we check if there
|
wobin@7
|
74 -- is a Settings.Requested for that name, and if so assume they have approved
|
wobin@7
|
75 -- and clear/add records appropriately.
|
wobin@0
|
76 --]]
|
wobin@0
|
77 Model.Squawk = {}
|
wobin@0
|
78 local Squawk = Model.Squawk
|
wobin@0
|
79
|
wobin@0
|
80 function Squawk:new(Message, Owner)
|
wobin@0
|
81 local o = {}
|
wobin@0
|
82 o.Owner = Owner or UnitName("player")
|
wobin@0
|
83 o.Message = Message
|
wobin@10
|
84 o.Time = time()
|
wobin@0
|
85 local reply, to = strsplit("@", ((strsplit(" ", Message))))
|
wobin@0
|
86 if reply == "" then
|
wobin@0
|
87 o.ReplyTo = to
|
wobin@0
|
88 end
|
wobin@0
|
89
|
wobin@0
|
90 o.Related = {}
|
wobin@0
|
91
|
wobin@0
|
92 for word in string.gmatch(Message, "@(%a+)") do
|
wobin@0
|
93 if word ~= o.ReplyTo or "" then
|
wobin@0
|
94 table.insert(o.Related, word)
|
wobin@0
|
95 end
|
wobin@0
|
96 end
|
wobin@0
|
97
|
wobin@0
|
98 return o
|
wobin@0
|
99 end
|
wobin@0
|
100
|
wobin@0
|
101 function Squawk:Sort(Squawks)
|
wobin@0
|
102 return table.sort(Squawks, function(a,b) return a.Time < b.Time end)
|
wobin@0
|
103 end
|
wobin@0
|
104
|
wobin@2
|
105 function Squawk:GetOwn(Squawks)
|
wobin@2
|
106 local mine = {}
|
wobin@2
|
107 for _, squawk in ipairs(Squawks) do
|
wobin@2
|
108 if squawk.Owner == UnitName("player") then
|
wobin@2
|
109 table.insert(mine, squawk)
|
wobin@2
|
110 end
|
wobin@2
|
111 end
|
wobin@2
|
112 return self:Sort(mine)
|
wobin@2
|
113 end
|
wobin@2
|
114
|
wobin@0
|
115 function Settings:IsPrivate()
|
wobin@0
|
116 return Settings.Private
|
wobin@0
|
117 end
|
wobin@0
|
118
|
wobin@10
|
119 function Settings:TogglePrivate()
|
wobin@10
|
120 Settings.Private = not Settings.Private
|
wobin@10
|
121 end
|
wobin@10
|
122
|
wobin@0
|
123 function Settings:AddFollower(Name)
|
wobin@2
|
124 Settings.Follower[Name] = 1
|
wobin@7
|
125 self:RemovePending(Name)
|
wobin@0
|
126 end
|
wobin@0
|
127
|
wobin@0
|
128 function Settings:AddFollowing(Name)
|
wobin@2
|
129 Settings.Following[Name] = 1
|
wobin@7
|
130 self:RemoveRequested(Name)
|
wobin@0
|
131 end
|
wobin@0
|
132
|
wobin@0
|
133 function Settings:AddBlock(Name)
|
wobin@2
|
134 Settings.Blocked[Name] = 1
|
wobin@7
|
135 self:RemoveFollower(Name)
|
wobin@7
|
136 self:RemoveFollowing(Name)
|
wobin@7
|
137 end
|
wobin@7
|
138
|
wobin@7
|
139 function Settings:AddPending(Name)
|
wobin@7
|
140 Settings.Pending[Name] = 1
|
wobin@7
|
141 end
|
wobin@7
|
142
|
wobin@7
|
143 function Settings:AddRequested(Name)
|
wobin@7
|
144 Settings.Requested[Name] = 1
|
wobin@0
|
145 end
|
wobin@0
|
146
|
wobin@0
|
147 function Settings:RemoveFollower(Name)
|
wobin@2
|
148 if Settings.Follower[Name] then
|
wobin@2
|
149 Settings.Follower[Name] = nil
|
wobin@0
|
150 end
|
wobin@0
|
151 end
|
wobin@0
|
152
|
wobin@0
|
153 function Settings:RemoveFollowing(Name)
|
wobin@2
|
154 if Settings.Following[Name] then
|
wobin@2
|
155 Settings.Following[Name] = nil
|
wobin@0
|
156 end
|
wobin@0
|
157 end
|
wobin@0
|
158
|
wobin@0
|
159 function Settings:RemoveBlock(Name)
|
wobin@2
|
160 if Settings.Blocked[Name] then
|
wobin@2
|
161 Settings.Blocked[Name] = nil
|
wobin@0
|
162 end
|
wobin@0
|
163 end
|
wobin@0
|
164
|
wobin@7
|
165 function Settings:RemovePending(Name)
|
wobin@7
|
166 if Settings.Pending[Name] then
|
wobin@7
|
167 Settings.Pending[Name] = nil
|
wobin@7
|
168 end
|
wobin@7
|
169 end
|
wobin@7
|
170
|
wobin@7
|
171 function Settings:RemoveRequested(Name)
|
wobin@7
|
172 if Settings.Requested[Name] then
|
wobin@7
|
173 Settings.Requested[Name] = nil
|
wobin@7
|
174 end
|
wobin@7
|
175 end
|
wobin@7
|
176
|
wobin@0
|
177 --Controller--
|
wobin@0
|
178
|
wobin@0
|
179 function Controller:TheyWantToFollowMe(Name)
|
wobin@0
|
180 if Settings:IsPrivate() then
|
wobin@7
|
181 Settings:AddPending(Name)
|
wobin@0
|
182 self:PutForwardFollowRequest(Name)
|
wobin@0
|
183 self:SendMessageToTarget(Name, "#Pending|"..UnitName("player"))
|
wobin@0
|
184 else
|
wobin@0
|
185 Settings:AddFollower(Name)
|
wobin@0
|
186 View:NotifyOfNewFollower(Name)
|
wobin@0
|
187 self:SendMessageToTarget(Name, "#Follow|"..UnitName("player"))
|
wobin@0
|
188 end
|
wobin@0
|
189 end
|
wobin@0
|
190
|
wobin@7
|
191 function Controller:TheyWantToUnfollowMe(Name)
|
wobin@7
|
192 Settings:RemoveFollower(Name)
|
wobin@7
|
193 end
|
wobin@7
|
194
|
wobin@0
|
195 function Controller:IWantToFollowThem(Name)
|
wobin@2
|
196 self:SendMessageToTarget(Name, "#Request|"..UnitName("player"))
|
wobin@7
|
197 Settings:AddRequested(Name)
|
wobin@7
|
198 end
|
wobin@7
|
199
|
wobin@7
|
200 function Controller:IWantToUnfollowThem(Name)
|
wobin@7
|
201 Settings:RemoveFollowing(Name)
|
wobin@7
|
202 self:SendMessageToTarget(Name, "#Unfollow|"..UnitName("player"))
|
wobin@7
|
203 View:NotifyOfUnfollowing(Name)
|
wobin@0
|
204 end
|
wobin@0
|
205
|
wobin@0
|
206 function Controller:IAmNowFollowingThem(Name)
|
wobin@0
|
207 Settings:AddFollowing(Name)
|
wobin@0
|
208 View:NotifyOfNewFollowing(Name)
|
wobin@0
|
209 end
|
wobin@0
|
210
|
wobin@7
|
211 function Controller:AddANewSquawk(Name, Message, Source)
|
wobin@10
|
212 if not Settings.Blocked[Name] then
|
wobin@7
|
213
|
wobin@7
|
214 if Source == "WHISPER" then
|
wobin@10
|
215 if Settings.Requested[Name] then -- We've been approved offline!
|
wobin@10
|
216 Settings:AddFollowing(Name)
|
wobin@7
|
217 end
|
wobin@7
|
218
|
wobin@10
|
219 if not Settings.Following[Name] then -- If we're no longer following this person
|
wobin@7
|
220 self:SendMessageToTarget(Name, "#Unfollow|"..UnitName("player"))
|
wobin@9
|
221 return
|
wobin@9
|
222 end
|
wobin@10
|
223 end
|
wobin@10
|
224
|
wobin@10
|
225 if Source == "GUILD" and Name == UnitName("player") then
|
wobin@10
|
226 return
|
wobin@7
|
227 end
|
wobin@10
|
228
|
wobin@10
|
229 table.insert(Model.Squawks, Squawk:new(Message, Name))
|
wobin@10
|
230 View:UpdateSquawkList()
|
wobin@7
|
231 end
|
wobin@0
|
232 end
|
wobin@0
|
233
|
wobin@2
|
234 function Controller:SendNewSquawk(Message)
|
wobin@10
|
235 if not Settings:IsPrivate() then
|
wobin@2
|
236 self:SendMessageToGuild("#Squawk|"..UnitName("player").."|"..Message)
|
wobin@2
|
237 end
|
wobin@2
|
238
|
wobin@2
|
239 self:AddANewSquawk(UnitName("player"), Message)
|
wobin@2
|
240
|
wobin@10
|
241 for name, _ in pairs(Settings.Following) do
|
wobin@2
|
242 self:SendMessageToTarget(name, "#Squawk|"..UnitName("player").."|"..Message)
|
wobin@2
|
243 end
|
wobin@2
|
244 end
|
wobin@2
|
245
|
wobin@1
|
246 function Controller:ImPending(Name)
|
wobin@1
|
247 View:NotifyOfPending(Name)
|
wobin@1
|
248 end
|
wobin@1
|
249
|
wobin@7
|
250 function Controller:PutForwardFollowRequest(Name)
|
wobin@7
|
251 View:NotifyOfPendingRequest(Name)
|
wobin@7
|
252 end
|
wobin@7
|
253
|
wobin@10
|
254 function Controller:ApprovePendingRequest(Name)
|
wobin@10
|
255 Settings:AddFollower(Name)
|
wobin@10
|
256 View:NotifyOfNewFollower(Name)
|
wobin@10
|
257 self:SendMessageToTarget(Name, "#Follow|"..UnitName("player"))
|
wobin@10
|
258 end
|
wobin@10
|
259
|
wobin@0
|
260 function Controller:SendMessageToTarget(Name, Message)
|
wobin@10
|
261 self:SendCommMessage("Squawk", Message, "WHISPER", Name)
|
wobin@0
|
262 end
|
wobin@0
|
263
|
wobin@0
|
264 function Controller:SendMessageToGuild(Message)
|
wobin@0
|
265 self:SendCommMessage("Squawk", Message, "GUILD")
|
wobin@0
|
266 end
|
wobin@0
|
267
|
wobin@0
|
268 local Parse = {
|
wobin@1
|
269 ["#Pending"] = Controller.ImPending,
|
wobin@1
|
270 ["#Follow"] = Controller.IAmNowFollowingThem,
|
wobin@7
|
271 ["#Unfollow"] = Controller.TheyWantToUnfollowMe,
|
wobin@2
|
272 ["#Squawk"] = Controller.AddANewSquawk,
|
wobin@2
|
273 ["#Request"] = Controller.TheyWantToFollowMe,
|
wobin@0
|
274 }
|
wobin@0
|
275
|
wobin@10
|
276 function Controller:ReceiveMessage(Message, Distribution, Sender)
|
wobin@0
|
277 local command, name, info = strsplit("|",Message)
|
wobin@10
|
278 View:Print(Distribution..":"..Message)
|
wobin@10
|
279 Parse[command](Controller, name, info, Distribution)
|
wobin@0
|
280 end
|
wobin@0
|
281 -- View --
|
wobin@0
|
282
|
wobin@0
|
283 function View:UpdateSquawkList()
|
wobin@3
|
284 self:Print("Updated Squawk List")
|
wobin@4
|
285 self:ShowMeMySquawks()
|
wobin@0
|
286 end
|
wobin@0
|
287
|
wobin@3
|
288 function View:NotifyOfPending(Name)
|
wobin@3
|
289 self:Print(Name.." will have to approve your request")
|
wobin@0
|
290 end
|
wobin@0
|
291
|
wobin@7
|
292 function View:NotifyOfPendingRequest(Name)
|
wobin@7
|
293 self:Print(Name.." wants to follow you.")
|
wobin@7
|
294 end
|
wobin@7
|
295
|
wobin@0
|
296 function View:NotifyOfNewFollowing(Name)
|
wobin@3
|
297 self:Print("You are now following "..Name)
|
wobin@0
|
298 end
|
wobin@0
|
299
|
wobin@7
|
300 function View:NotifyOfUnfollowing(Name)
|
wobin@7
|
301 self:Print("You are no longer following "..Name)
|
wobin@7
|
302 end
|
wobin@7
|
303
|
wobin@0
|
304 function View:NotifyOfNewFollower(Name)
|
wobin@3
|
305 self:Print(Name.." is now following you")
|
wobin@0
|
306 end
|
wobin@4
|
307
|
wobin@4
|
308 function View:ShowMeMySquawks()
|
wobin@5
|
309 for _,squawk in ipairs(Model.Squawks) do
|
wobin@4
|
310 self:Print(squawk.Message)
|
wobin@4
|
311 end
|
wobin@4
|
312 end
|
wobin@4
|
313
|
wobin@4
|
314 function View:ShowMeMyFollowers()
|
wobin@4
|
315 self:Print("My followers are:")
|
wobin@4
|
316 for name,_ in pairs(Settings.Follower) do
|
wobin@4
|
317 self:Print(name)
|
wobin@4
|
318 end
|
wobin@4
|
319 end
|
wobin@4
|
320
|
wobin@4
|
321 function View:ShowMeWhoImFollowing()
|
wobin@4
|
322 self:Print("I am following:")
|
wobin@4
|
323 for name,_ in pairs(Settings.Following) do
|
wobin@4
|
324 self:Print(name)
|
wobin@4
|
325 end
|
wobin@4
|
326 end
|
wobin@4
|
327
|
wobin@4
|
328 function View:ShowMeWhoIveBlocked()
|
wobin@4
|
329 self:Print("I've blocked:")
|
wobin@6
|
330 for name,_ in pairs(Settings.Blocked) do
|
wobin@4
|
331 self:Print(name)
|
wobin@4
|
332 end
|
wobin@4
|
333 end
|
wobin@10
|
334
|
wobin@10
|
335 local LDBFeed = LibStub("LibDataBroker-1.1"):NewDataObject("Squawk", {type = "data source", text = "Awk!"})
|
wobin@10
|
336 local QTip = LibStub("LibQTip-1.0")
|
wobin@10
|
337
|
wobin@10
|
338 function LDBFeed:OnEnter()
|
wobin@10
|
339 local tooltip = QTip:Acquire("Squawk",3, "LEFT", "LEFT", "RIGHT")
|
wobin@10
|
340 self.tooltip = tooltip
|
wobin@10
|
341 tooltip:AddHeader('Name')
|
wobin@10
|
342 tooltip:AddLine('testUser', 'Squawk!', '3 min ago')
|
wobin@10
|
343 tooltip:SmartAnchorTo(self)
|
wobin@10
|
344 tooltip:Show()
|
wobin@10
|
345 end
|
wobin@10
|
346
|
wobin@10
|
347 function LDBFeed:OnTooltipShow()
|
wobin@10
|
348 end
|
wobin@10
|
349
|
wobin@10
|
350 function LDBFeed:OnLeave()
|
wobin@10
|
351 QTip:Release(self.tooltip)
|
wobin@10
|
352 end
|