ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/FreeBSDAdmin/IRC/smart_ison.cpp
Revision: 1265
Committed: 2010-03-21T18:05:14-07:00 (15 years, 3 months ago) by douglas
File size: 7064 byte(s)
Log Message:
More smarts for ISON!

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 1263 SmartISONTimer(CModule *module) : CTimer(module, 15, 0, "Smart ISON", "Smart ISON") {}
24     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     table.SetCell("Command", "Version");
82     table.SetCell("Description", "Display module version");
83 douglas 1263
84     PutModule(table);
85     }
86     else if (theCommand.Equals("Nicks"))
87     if (nicks_.empty())
88     PutModule("Nick status list empty");
89     else
90 douglas 1262 {
91 douglas 1263 CTable table;
92 douglas 1262
93 douglas 1263 table.AddColumn("Nick");
94     table.AddColumn("Status");
95    
96     typedef std::map<CString, bool, Compare> NickMap;
97    
98     _foreach (const NickMap, nick, nicks_)
99     {
100     table.AddRow();
101     table.SetCell("Nick", nick->first);
102     table.SetCell("Status", nick->second ? "Online" : "Offline");
103     }
104    
105     PutModule(table);
106 douglas 1262 }
107 douglas 1263 else if (theCommand.Equals("Queue"))
108     if (queue_.empty())
109     PutModule("Nick queue empty");
110     else
111     {
112     CTable table;
113 douglas 1262
114 douglas 1263 table.AddColumn("Nick");
115 douglas 1262
116 douglas 1263 _foreach (const std::deque<CString>, nick, queue_)
117     {
118     table.AddRow();
119     table.SetCell("Nick", *nick);
120     }
121 douglas 1262
122 douglas 1263 PutModule(table);
123     }
124 douglas 1265 else if (theCommand.Equals("Version"))
125     PutModule("$Id$");
126 douglas 1263 else
127     PutModule("Unknown command [" + theCommand + "] try 'Help'");
128     }
129 douglas 1262
130 douglas 1265 virtual void OnModCTCP(const CString &message)
131     {
132     CString command(message.Token(0));
133    
134     if (command.Equals("PING"))
135     PutModNotice("\001PING " + message.Token(1, true) + "\001");
136     else if (command.Equals("Version"))
137     PutModNotice("\001VERSION $Id$\001");
138     }
139    
140 douglas 1263 virtual void OnNick(const CNick &nick, const CString &newNick, const std::vector<CChan *> &chans)
141     {
142     const CString &oldNick(nick.GetNick());
143 douglas 1262
144 douglas 1263 nicks_[oldNick] = false;
145     nicks_[newNick] = true;
146     }
147 douglas 1262
148 douglas 1265 virtual void OnPart(const CNick &nick, CChan &chan)
149     {
150     queue_.push_front(nick.GetNick());
151     }
152    
153     virtual EModRet OnPrivAction(CNick &nick, CString &message)
154     {
155     nicks_[nick.GetNick()] = true;
156    
157     return CONTINUE;
158     }
159    
160     virtual EModRet OnPrivCTCP(CNick &nick, CString &message)
161     {
162     nicks_[nick.GetNick()] = true;
163    
164     return CONTINUE;
165     }
166    
167     virtual EModRet OnPrivMsg(CNick &nick, CString &message)
168     {
169     nicks_[nick.GetNick()] = true;
170    
171     return CONTINUE;
172     }
173    
174     virtual EModRet OnPrivNotice(CNick &nick, CString &message)
175     {
176     nicks_[nick.GetNick()] = true;
177    
178     return CONTINUE;
179     }
180    
181 douglas 1263 virtual void OnQuit(const CNick &nick, const CString &message, const std::vector<CChan *> &chans)
182     {
183     const CString &theNick(nick.GetNick());
184    
185     nicks_[theNick] = false;
186     }
187    
188     virtual EModRet OnRaw(CString &line)
189     {
190     if (line.Token(1) == "303")
191     {
192     typedef std::set<CString, Compare> NickSet;
193    
194     _foreach (NickSet, nick, request_)
195     nicks_[*nick] = false;
196    
197     std::vector<CString> nicks;
198    
199     line.Token(3, true).TrimLeft_n(":").Split(" ", nicks, false);
200    
201     _foreach (std::vector<CString>, nick, nicks)
202     nicks_[*nick] = true;
203    
204     return HALT;
205 douglas 1262 }
206    
207     return CONTINUE;
208     }
209 douglas 1263
210     virtual EModRet OnUserRaw(CString &line);
211    
212     private:
213     template <typename Type>
214     Type CheckChans()
215     {
216     Type nicks;
217    
218 douglas 1265 _foreach (const std::vector<CChan *>, chan, GetUser()->GetChans())
219 douglas 1263 {
220     typedef std::map<CString, CNick *> NickMap;
221    
222 douglas 1265 _foreach (const NickMap, nick, (*chan)->GetNicks())
223 douglas 1263 {
224     nicks_[nick->first] = true;
225     nicks.insert(nick->first);
226     }
227     }
228    
229     return nicks;
230     }
231    
232     friend void SmartISONTimer::RunJob();
233 douglas 1262 };
234    
235 douglas 1263 struct SmartISONVoid
236     {
237     inline void insert(const CString &value) {}
238     };
239    
240     void SmartISONTimer::RunJob()
241     {
242     SmartISON *module(static_cast<SmartISON *>(GetModule()));
243    
244     module->request_.clear();
245    
246     std::set<CString, SmartISON::Compare> online(module->CheckChans<std::set<CString, SmartISON::Compare> >());
247     size_t size(6);
248    
249     while (module->queue_.size())
250     {
251     CString nick(module->queue_.front());
252    
253     if (!online.count(nick))
254     {
255     if ((size += nick.size() + 1) > 512)
256     break;
257    
258     module->request_.insert(nick);
259     }
260    
261     module->queue_.pop_front();
262     }
263    
264     if (module->request_.size())
265     {
266     CString request("ISON");
267    
268     typedef std::set<CString, SmartISON::Compare> NickSet;
269    
270     _foreach (NickSet, nick, module->request_)
271     request += " " + *nick;
272    
273     module->PutIRC(request);
274     }
275 douglas 1265
276     if (module->queue_.empty())
277     {
278     typedef std::map<CString, bool, SmartISON::Compare> NickMap;
279    
280     _foreach (NickMap, nick, module->nicks_)
281     module->queue_.push_back(nick->first);
282     }
283 douglas 1263 }
284    
285     template <>
286     void SmartISON::CheckChans()
287     {
288     CheckChans<SmartISONVoid>();
289     }
290    
291     CModule::EModRet SmartISON::OnUserRaw(CString &line)
292     {
293     if (line.Token(0).Equals("ISON"))
294     {
295     CheckChans<void>();
296    
297     std::vector<CString> nicks;
298    
299     line.Token(1, true).TrimLeft_n(":").Split(" ", nicks, false);
300    
301     if (nicks.empty())
302     {
303     PutUser(":znc.in 461 " + GetUser()->GetIRCNick().GetNick() + " :Not enough parameters");
304     }
305     else
306     {
307     CString response(":znc.in 303 " + GetUser()->GetIRCNick().GetNick() + " :");
308    
309     _foreach (std::vector<CString>, nick, nicks)
310     {
311     CString prefix(GetUser()->GetStatusPrefix());
312    
313     if (nick->Equals(prefix, false, prefix.size()))
314     {
315     CString modNick(nick->substr(prefix.size()));
316 douglas 1265 CModule *module(NULL);
317 douglas 1263
318 douglas 1265 if (modNick.Equals("status") || (module = GetUser()->GetModules().FindModule(modNick)) || (module = CZNC::Get().GetModules().FindModule(modNick)))
319     {
320     response += (module ? module->GetModNick() : prefix + "status") + " ";
321     continue;
322     }
323 douglas 1263 }
324    
325 douglas 1265 std::map<CString, bool, Compare>::iterator theNick(nicks_.find(*nick));
326    
327     if (theNick == nicks_.end())
328     {
329     nicks_[*nick] = false;
330    
331 douglas 1263 queue_.push_front(*nick);
332 douglas 1265 }
333     else if (theNick->second)
334     response += theNick->first + " ";
335 douglas 1263 }
336    
337     PutUser(response);
338     }
339    
340     return HALT;
341     }
342    
343     return CONTINUE;
344     }
345    
346     MODULEDEFS(SmartISON, "Smart ISON");

Properties

Name Value
svn:keywords Id