ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/FreeBSDAdmin/IRC/smart_ison.cpp
Revision: 1295
Committed: 2010-04-09T05:48:07-07:00 (15 years, 2 months ago) by douglas
File size: 8699 byte(s)
Log Message:
Useful descriptions; some basic stats reporting in Smart ISON before recording more complex stats.

File Contents

# User Rev Content
1 douglas 1262 // Smart ISON
2     //
3     // Douglas Thrift
4     //
5     // $Id$
6    
7     #include <main.h>
8     #include <Modules.h>
9     #include <Chan.h>
10     #include <User.h>
11 douglas 1263 #include <znc.h>
12 douglas 1262
13 douglas 1263 #include <deque>
14     #include <map>
15     #include <set>
16 douglas 1262
17     #include "foreach.hpp"
18    
19     #pragma GCC diagnostic ignored "-Wshadow"
20    
21 douglas 1263 struct SmartISONTimer : public CTimer
22 douglas 1262 {
23 douglas 1295 SmartISONTimer(CModule *module) : CTimer(module, 15, 0, "Smart ISON", "Keeps track of online and offline nicks so ISON requests from Pidgin are not truncated") {}
24 douglas 1263 virtual ~SmartISONTimer() {}
25 douglas 1262
26 douglas 1263 virtual void RunJob();
27 douglas 1262 };
28    
29 douglas 1263 class SmartISON : public CModule
30     {
31     struct Compare
32     {
33     inline bool operator()(const CString &one, const CString &two) const
34     {
35     return one.AsLower() < two.AsLower();
36     }
37     };
38 douglas 1262
39 douglas 1263 std::map<CString, bool, Compare> nicks_;
40     std::deque<CString> queue_;
41     std::set<CString, Compare> request_;
42 douglas 1262
43     public:
44 douglas 1263 MODCONSTRUCTOR(SmartISON) {}
45     virtual ~SmartISON() {}
46 douglas 1262
47 douglas 1265 virtual EModRet OnCTCPReply(CNick &nick, CString &message)
48     {
49     nicks_[nick.GetNick()] = true;
50    
51     return CONTINUE;
52     }
53    
54     virtual void OnKick(const CNick &nick, const CString &opNick, CChan &chan, const CString &message)
55     {
56     queue_.push_front(nick.GetNick());
57     }
58    
59 douglas 1263 virtual bool OnLoad(const CString &args, CString &message)
60 douglas 1262 {
61 douglas 1263 return AddTimer(new SmartISONTimer(this));
62 douglas 1262 }
63    
64 douglas 1263 virtual void OnModCommand(const CString &command)
65 douglas 1262 {
66 douglas 1263 CString theCommand(command.Token(0));
67    
68     if (theCommand.Equals("Help"))
69 douglas 1262 {
70 douglas 1263 CTable table;
71 douglas 1262
72 douglas 1263 table.AddColumn("Command");
73     table.AddColumn("Description");
74     table.AddRow();
75     table.SetCell("Command", "Nicks");
76     table.SetCell("Description", "List nick statuses");
77     table.AddRow();
78     table.SetCell("Command", "Queue");
79     table.SetCell("Description", "List the nick status queue");
80 douglas 1265 table.AddRow();
81 douglas 1295 table.SetCell("Command", "Request");
82     table.SetCell("Description", "List the last nick request");
83     table.AddRow();
84     table.SetCell("Command", "Stats");
85     table.SetCell("Description", "List nick and queue statistics");
86     table.AddRow();
87 douglas 1265 table.SetCell("Command", "Version");
88     table.SetCell("Description", "Display module version");
89 douglas 1263
90     PutModule(table);
91     }
92     else if (theCommand.Equals("Nicks"))
93     if (nicks_.empty())
94     PutModule("Nick status list empty");
95     else
96 douglas 1262 {
97 douglas 1263 CTable table;
98 douglas 1262
99 douglas 1263 table.AddColumn("Nick");
100     table.AddColumn("Status");
101    
102     typedef std::map<CString, bool, Compare> NickMap;
103    
104     _foreach (const NickMap, nick, nicks_)
105     {
106     table.AddRow();
107     table.SetCell("Nick", nick->first);
108     table.SetCell("Status", nick->second ? "Online" : "Offline");
109     }
110    
111     PutModule(table);
112 douglas 1262 }
113 douglas 1263 else if (theCommand.Equals("Queue"))
114     if (queue_.empty())
115     PutModule("Nick queue empty");
116     else
117     {
118     CTable table;
119 douglas 1262
120 douglas 1263 table.AddColumn("Nick");
121 douglas 1262
122 douglas 1263 _foreach (const std::deque<CString>, nick, queue_)
123     {
124     table.AddRow();
125     table.SetCell("Nick", *nick);
126     }
127 douglas 1262
128 douglas 1263 PutModule(table);
129     }
130 douglas 1295 else if (theCommand.Equals("Request"))
131     if (request_.empty())
132     PutModule("Last nick request empty");
133     else
134     {
135     CTable table;
136    
137     table.AddColumn("Nick");
138    
139     typedef std::set<CString, Compare> NickSet;
140    
141     _foreach (NickSet, nick, request_)
142     {
143     table.AddRow();
144     table.SetCell("Nick", *nick);
145     }
146    
147     PutModule(table);
148     }
149     else if (theCommand.Equals("Stats"))
150     {
151     CTable table;
152    
153     table.AddColumn("Item");
154     table.AddColumn("Count");
155     table.AddRow();
156     table.SetCell("Item", "Nicks");
157     table.SetCell("Count", CString(nicks_.size()));
158    
159     typedef std::map<CString, bool, Compare> NickMap;
160     size_t online(0), offline(0);
161    
162     _foreach (NickMap, nick, nicks_)
163     if (nick->second)
164     ++online;
165     else
166     ++offline;
167    
168     table.AddRow();
169     table.SetCell("Item", "Online");
170     table.SetCell("Count", CString(online));
171     table.AddRow();
172     table.SetCell("Item", "Offline");
173     table.SetCell("Count", CString(offline));
174     table.AddRow();
175     table.SetCell("Item", "Queue");
176     table.SetCell("Count", CString(queue_.size()));
177     table.AddRow();
178     table.SetCell("Item", "Request");
179     table.SetCell("Count", CString(request_.size()));
180    
181     PutModule(table);
182     }
183 douglas 1265 else if (theCommand.Equals("Version"))
184     PutModule("$Id$");
185 douglas 1263 else
186     PutModule("Unknown command [" + theCommand + "] try 'Help'");
187     }
188 douglas 1262
189 douglas 1265 virtual void OnModCTCP(const CString &message)
190     {
191     CString command(message.Token(0));
192    
193     if (command.Equals("PING"))
194     PutModNotice("\001PING " + message.Token(1, true) + "\001");
195     else if (command.Equals("Version"))
196     PutModNotice("\001VERSION $Id$\001");
197     }
198    
199 douglas 1263 virtual void OnNick(const CNick &nick, const CString &newNick, const std::vector<CChan *> &chans)
200     {
201     const CString &oldNick(nick.GetNick());
202 douglas 1262
203 douglas 1263 nicks_[oldNick] = false;
204     nicks_[newNick] = true;
205     }
206 douglas 1262
207 douglas 1265 virtual void OnPart(const CNick &nick, CChan &chan)
208     {
209     queue_.push_front(nick.GetNick());
210     }
211    
212     virtual EModRet OnPrivAction(CNick &nick, CString &message)
213     {
214     nicks_[nick.GetNick()] = true;
215    
216     return CONTINUE;
217     }
218    
219     virtual EModRet OnPrivCTCP(CNick &nick, CString &message)
220     {
221     nicks_[nick.GetNick()] = true;
222    
223     return CONTINUE;
224     }
225    
226     virtual EModRet OnPrivMsg(CNick &nick, CString &message)
227     {
228     nicks_[nick.GetNick()] = true;
229    
230     return CONTINUE;
231     }
232    
233     virtual EModRet OnPrivNotice(CNick &nick, CString &message)
234     {
235     nicks_[nick.GetNick()] = true;
236    
237     return CONTINUE;
238     }
239    
240 douglas 1263 virtual void OnQuit(const CNick &nick, const CString &message, const std::vector<CChan *> &chans)
241     {
242     const CString &theNick(nick.GetNick());
243    
244     nicks_[theNick] = false;
245     }
246    
247     virtual EModRet OnRaw(CString &line)
248     {
249     if (line.Token(1) == "303")
250     {
251     typedef std::set<CString, Compare> NickSet;
252    
253     _foreach (NickSet, nick, request_)
254     nicks_[*nick] = false;
255    
256     std::vector<CString> nicks;
257    
258     line.Token(3, true).TrimLeft_n(":").Split(" ", nicks, false);
259    
260     _foreach (std::vector<CString>, nick, nicks)
261     nicks_[*nick] = true;
262    
263     return HALT;
264 douglas 1262 }
265    
266     return CONTINUE;
267     }
268 douglas 1263
269     virtual EModRet OnUserRaw(CString &line);
270    
271     private:
272     template <typename Type>
273     Type CheckChans()
274     {
275     Type nicks;
276    
277 douglas 1265 _foreach (const std::vector<CChan *>, chan, GetUser()->GetChans())
278 douglas 1263 {
279     typedef std::map<CString, CNick *> NickMap;
280    
281 douglas 1265 _foreach (const NickMap, nick, (*chan)->GetNicks())
282 douglas 1263 {
283     nicks_[nick->first] = true;
284     nicks.insert(nick->first);
285     }
286     }
287    
288     return nicks;
289     }
290    
291     friend void SmartISONTimer::RunJob();
292 douglas 1262 };
293    
294 douglas 1263 struct SmartISONVoid
295     {
296     inline void insert(const CString &value) {}
297     };
298    
299     void SmartISONTimer::RunJob()
300     {
301     SmartISON *module(static_cast<SmartISON *>(GetModule()));
302    
303     module->request_.clear();
304    
305     std::set<CString, SmartISON::Compare> online(module->CheckChans<std::set<CString, SmartISON::Compare> >());
306     size_t size(6);
307    
308     while (module->queue_.size())
309     {
310     CString nick(module->queue_.front());
311    
312 douglas 1268 if (!online.count(nick) && !module->request_.count(nick))
313 douglas 1263 {
314     if ((size += nick.size() + 1) > 512)
315     break;
316    
317     module->request_.insert(nick);
318     }
319    
320     module->queue_.pop_front();
321     }
322    
323     if (module->request_.size())
324     {
325     CString request("ISON");
326    
327     typedef std::set<CString, SmartISON::Compare> NickSet;
328    
329     _foreach (NickSet, nick, module->request_)
330     request += " " + *nick;
331    
332     module->PutIRC(request);
333     }
334 douglas 1265
335     if (module->queue_.empty())
336     {
337     typedef std::map<CString, bool, SmartISON::Compare> NickMap;
338    
339     _foreach (NickMap, nick, module->nicks_)
340     module->queue_.push_back(nick->first);
341     }
342 douglas 1263 }
343    
344     template <>
345     void SmartISON::CheckChans()
346     {
347     CheckChans<SmartISONVoid>();
348     }
349    
350     CModule::EModRet SmartISON::OnUserRaw(CString &line)
351     {
352     if (line.Token(0).Equals("ISON"))
353     {
354     CheckChans<void>();
355    
356     std::vector<CString> nicks;
357    
358     line.Token(1, true).TrimLeft_n(":").Split(" ", nicks, false);
359    
360     if (nicks.empty())
361     {
362     PutUser(":znc.in 461 " + GetUser()->GetIRCNick().GetNick() + " :Not enough parameters");
363     }
364     else
365     {
366     CString response(":znc.in 303 " + GetUser()->GetIRCNick().GetNick() + " :");
367    
368     _foreach (std::vector<CString>, nick, nicks)
369     {
370     CString prefix(GetUser()->GetStatusPrefix());
371    
372     if (nick->Equals(prefix, false, prefix.size()))
373     {
374     CString modNick(nick->substr(prefix.size()));
375 douglas 1265 CModule *module(NULL);
376 douglas 1263
377 douglas 1265 if (modNick.Equals("status") || (module = GetUser()->GetModules().FindModule(modNick)) || (module = CZNC::Get().GetModules().FindModule(modNick)))
378     {
379     response += (module ? module->GetModNick() : prefix + "status") + " ";
380     continue;
381     }
382 douglas 1263 }
383    
384 douglas 1265 std::map<CString, bool, Compare>::iterator theNick(nicks_.find(*nick));
385    
386     if (theNick == nicks_.end())
387     {
388     nicks_[*nick] = false;
389    
390 douglas 1263 queue_.push_front(*nick);
391 douglas 1265 }
392     else if (theNick->second)
393     response += theNick->first + " ";
394 douglas 1263 }
395    
396     PutUser(response);
397     }
398    
399     return HALT;
400     }
401    
402     return CONTINUE;
403     }
404    
405 douglas 1295 MODULEDEFS(SmartISON, "Keeps track of online and offline nicks so ISON requests from Pidgin are not truncated");

Properties

Name Value
svn:keywords Id