ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/FreeBSDAdmin/IRC/smart_ison.cpp
(Generate patch)

Comparing FreeBSDAdmin/IRC/smart_ison.cpp (file contents):
Revision 1262 by douglas, 2010-03-20T20:07:58-07:00 vs.
Revision 1268 by douglas, 2010-03-22T14:11:11-07:00

# Line 8 | Line 8
8   #include <Modules.h>
9   #include <Chan.h>
10   #include <User.h>
11 + #include <znc.h>
12  
13 < #include <ext/hash_set>
13 > #include <deque>
14 > #include <map>
15 > #include <set>
16  
17   #include "foreach.hpp"
18  
19   #pragma GCC diagnostic ignored "-Wshadow"
20  
21 < namespace __gnu_cxx
21 > struct SmartISONTimer : public CTimer
22   {
23 +        SmartISONTimer(CModule *module) : CTimer(module, 15, 0, "Smart ISON", "Smart ISON") {}
24 +        virtual ~SmartISONTimer() {}
25  
26 < template <>
22 < struct hash<CString>
23 < {
24 <        size_t operator()(const CString &x) const { return __stl_hash_string(x.c_str()); }
26 >        virtual void RunJob();
27   };
28  
29 < }
28 <
29 < namespace ext { using namespace __gnu_cxx; }
30 <
31 < class CSmartISON : public CModule
29 > class SmartISON : public CModule
30   {
31 <        CString online_;
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 >
39 >        std::map<CString, bool, Compare> nicks_;
40 >        std::deque<CString> queue_;
41 >        std::set<CString, Compare> request_;
42  
43   public:
44 <        MODCONSTRUCTOR(CSmartISON) {}
45 <        virtual ~CSmartISON() {}
44 >        MODCONSTRUCTOR(SmartISON) {}
45 >        virtual ~SmartISON() {}
46  
47 <        virtual EModRet OnRaw(CString &line)
47 >        virtual EModRet OnCTCPReply(CNick &nick, CString &message)
48          {
49 <                DEBUG("smart_ison: OnRaw() " << line.Token(1));
49 >                nicks_[nick.GetNick()] = true;
50  
51                  return CONTINUE;
52          }
53  
54 <        virtual EModRet OnUserRaw(CString &line)
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 >        virtual bool OnLoad(const CString &args, CString &message)
60 >        {
61 >                return AddTimer(new SmartISONTimer(this));
62 >        }
63 >
64 >        virtual void OnModCommand(const CString &command)
65          {
66 <                if (line.Token(0).Equals("ISON"))
66 >                CString theCommand(command.Token(0));
67 >
68 >                if (theCommand.Equals("Help"))
69                  {
70 <                        ext::hash_set<CString> known;
70 >                        CTable table;
71 >
72 >                        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 >                        table.AddRow();
81 >                        table.SetCell("Command", "Version");
82 >                        table.SetCell("Description", "Display module version");
83 >
84 >                        PutModule(table);
85 >                }
86 >                else if (theCommand.Equals("Nicks"))
87 >                        if (nicks_.empty())
88 >                                PutModule("Nick status list empty");
89 >                        else
90 >                        {
91 >                                CTable table;
92 >
93 >                                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 <                        _foreach (std::vector<CChan *>, channel, GetUser()->GetChans())
105 >                                PutModule(table);
106 >                        }
107 >                else if (theCommand.Equals("Queue"))
108 >                        if (queue_.empty())
109 >                                PutModule("Nick queue empty");
110 >                        else
111                          {
112 <                                typedef std::map<CString, CNick *> NickMap;
112 >                                CTable table;
113 >
114 >                                table.AddColumn("Nick");
115  
116 <                                _foreach (NickMap, nick, (*channel)->GetNicks())
117 <                                        known.insert(nick->first);
116 >                                _foreach (const std::deque<CString>, nick, queue_)
117 >                                {
118 >                                        table.AddRow();
119 >                                        table.SetCell("Nick", *nick);
120 >                                }
121 >
122 >                                PutModule(table);
123                          }
124 +                else if (theCommand.Equals("Version"))
125 +                        PutModule("$Id$");
126 +                else
127 +                        PutModule("Unknown command [" + theCommand + "] try 'Help'");
128 +        }
129 +
130 +        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 <                        VCString nicks;
140 >        virtual void OnNick(const CNick &nick, const CString &newNick, const std::vector<CChan *> &chans)
141 >        {
142 >                const CString &oldNick(nick.GetNick());
143 >
144 >                nicks_[oldNick] = false;
145 >                nicks_[newNick] = true;
146 >        }
147 >
148 >        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 <                        line.Token(1, true).TrimLeft_n(":").Split(" ", nicks, false);
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 >        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 <                        CString online, unknown("ISON");
188 >        virtual EModRet OnRaw(CString &line)
189 >        {
190 >                if (line.Token(1) == "303")
191 >                {
192 >                        typedef std::set<CString, Compare> NickSet;
193  
194 <                        _foreach (VCString, nick, nicks)
195 <                                ((known.find(*nick) != known.end()) ? online : unknown) += " " + *nick;
194 >                        _foreach (NickSet, nick, request_)
195 >                                nicks_[*nick] = false;
196  
197 <                        online_ = online.TrimLeft_n(" ");
197 >                        std::vector<CString> nicks;
198  
199 <                        if (unknown != "ISON")
200 <                                line = unknown;
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                  }
206  
207                  return CONTINUE;
208          }
209 +
210 +        virtual EModRet OnUserRaw(CString &line);
211 +
212 + private:
213 +        template <typename Type>
214 +        Type CheckChans()
215 +        {
216 +                Type nicks;
217 +
218 +                _foreach (const std::vector<CChan *>, chan, GetUser()->GetChans())
219 +                {
220 +                        typedef std::map<CString, CNick *> NickMap;
221 +
222 +                        _foreach (const NickMap, nick, (*chan)->GetNicks())
223 +                        {
224 +                                nicks_[nick->first] = true;
225 +                                nicks.insert(nick->first);
226 +                        }
227 +                }
228 +
229 +                return nicks;
230 +        }
231 +
232 +        friend void SmartISONTimer::RunJob();
233 + };
234 +
235 + struct SmartISONVoid
236 + {
237 +        inline void insert(const CString &value) {}
238   };
239  
240 < MODULEDEFS(CSmartISON, "Smart ISON");
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) && !module->request_.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 >
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 > }
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 >                                        CModule *module(NULL);
317 >
318 >                                        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 >                                }
324 >
325 >                                std::map<CString, bool, Compare>::iterator theNick(nicks_.find(*nick));
326 >
327 >                                if (theNick == nicks_.end())
328 >                                {
329 >                                        nicks_[*nick] = false;
330 >
331 >                                        queue_.push_front(*nick);
332 >                                }
333 >                                else if (theNick->second)
334 >                                        response += theNick->first + " ";
335 >                        }
336 >
337 >                        PutUser(response);
338 >                }
339 >
340 >                return HALT;
341 >        }
342 >
343 >        return CONTINUE;
344 > }
345 >
346 > MODULEDEFS(SmartISON, "Smart ISON");

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines