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 1263 by douglas, 2010-03-21T06:30:15-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 bool OnLoad(const CString &args, CString &message)
48          {
49 <                DEBUG("smart_ison: OnRaw() " << line.Token(1));
42 <
43 <                return CONTINUE;
49 >                return AddTimer(new SmartISONTimer(this));
50          }
51  
52 <        virtual EModRet OnUserRaw(CString &line)
52 >        virtual void OnModCommand(const CString &command)
53          {
54 <                if (line.Token(0).Equals("ISON"))
54 >                CString theCommand(command.Token(0));
55 >
56 >                if (theCommand.Equals("Help"))
57                  {
58 <                        ext::hash_set<CString> known;
58 >                        CTable table;
59  
60 <                        _foreach (std::vector<CChan *>, channel, GetUser()->GetChans())
60 >                        table.AddColumn("Command");
61 >                        table.AddColumn("Description");
62 >                        table.AddRow();
63 >                        table.SetCell("Command", "Nicks");
64 >                        table.SetCell("Description", "List nick statuses");
65 >                        table.AddRow();
66 >                        table.SetCell("Command", "Queue");
67 >                        table.SetCell("Description", "List the nick status queue");
68 >
69 >                        PutModule(table);
70 >                }
71 >                else if (theCommand.Equals("Nicks"))
72 >                        if (nicks_.empty())
73 >                                PutModule("Nick status list empty");
74 >                        else
75 >                        {
76 >                                CTable table;
77 >
78 >                                table.AddColumn("Nick");
79 >                                table.AddColumn("Status");
80 >
81 >                                typedef std::map<CString, bool, Compare> NickMap;
82 >
83 >                                _foreach (const NickMap, nick, nicks_)
84 >                                {
85 >                                        table.AddRow();
86 >                                        table.SetCell("Nick", nick->first);
87 >                                        table.SetCell("Status", nick->second ? "Online" : "Offline");
88 >                                }
89 >
90 >                                PutModule(table);
91 >                        }
92 >                else if (theCommand.Equals("Queue"))
93 >                        if (queue_.empty())
94 >                                PutModule("Nick queue empty");
95 >                        else
96                          {
97 <                                typedef std::map<CString, CNick *> NickMap;
97 >                                CTable table;
98 >
99 >                                table.AddColumn("Nick");
100  
101 <                                _foreach (NickMap, nick, (*channel)->GetNicks())
102 <                                        known.insert(nick->first);
101 >                                _foreach (const std::deque<CString>, nick, queue_)
102 >                                {
103 >                                        table.AddRow();
104 >                                        table.SetCell("Nick", *nick);
105 >                                }
106 >
107 >                                PutModule(table);
108                          }
109 +                else
110 +                        PutModule("Unknown command [" + theCommand + "] try 'Help'");
111 +        }
112 +
113 +        virtual void OnNick(const CNick &nick, const CString &newNick, const std::vector<CChan *> &chans)
114 +        {
115 +                const CString &oldNick(nick.GetNick());
116  
117 <                        VCString nicks;
117 >                nicks_[oldNick] = false;
118 >                nicks_[newNick] = true;
119 >        }
120  
121 <                        line.Token(1, true).TrimLeft_n(":").Split(" ", nicks, false);
121 >        virtual void OnQuit(const CNick &nick, const CString &message, const std::vector<CChan *> &chans)
122 >        {
123 >                const CString &theNick(nick.GetNick());
124  
125 <                        CString online, unknown("ISON");
125 >                nicks_[theNick] = false;
126 >        }
127  
128 <                        _foreach (VCString, nick, nicks)
129 <                                ((known.find(*nick) != known.end()) ? online : unknown) += " " + *nick;
128 >        virtual EModRet OnRaw(CString &line)
129 >        {
130 >                if (line.Token(1) == "303")
131 >                {
132 >                        typedef std::set<CString, Compare> NickSet;
133  
134 <                        online_ = online.TrimLeft_n(" ");
134 >                        _foreach (NickSet, nick, request_)
135 >                                nicks_[*nick] = false;
136  
137 <                        if (unknown != "ISON")
138 <                                line = unknown;
137 >                        std::vector<CString> nicks;
138 >
139 >                        line.Token(3, true).TrimLeft_n(":").Split(" ", nicks, false);
140 >
141 >                        _foreach (std::vector<CString>, nick, nicks)
142 >                                nicks_[*nick] = true;
143 >
144 >                        return HALT;
145                  }
146  
147                  return CONTINUE;
148          }
149 +
150 +        virtual EModRet OnUserRaw(CString &line);
151 +
152 + private:
153 +        template <typename Type>
154 +        Type CheckChans()
155 +        {
156 +                Type nicks;
157 +
158 +                _foreach (const std::vector<CChan *>, channel, GetUser()->GetChans())
159 +                {
160 +                        typedef std::map<CString, CNick *> NickMap;
161 +
162 +                        _foreach (const NickMap, nick, (*channel)->GetNicks())
163 +                        {
164 +                                nicks_[nick->first] = true;
165 +                                nicks.insert(nick->first);
166 +                        }
167 +                }
168 +
169 +                return nicks;
170 +        }
171 +
172 +        friend void SmartISONTimer::RunJob();
173 + };
174 +
175 + struct SmartISONVoid
176 + {
177 +        inline void insert(const CString &value) {}
178   };
179  
180 < MODULEDEFS(CSmartISON, "Smart ISON");
180 > void SmartISONTimer::RunJob()
181 > {
182 >        SmartISON *module(static_cast<SmartISON *>(GetModule()));
183 >
184 >        if (module->queue_.empty())
185 >        {
186 >                typedef std::map<CString, bool, SmartISON::Compare> NickMap;
187 >
188 >                _foreach (NickMap, nick, module->nicks_)
189 >                        module->queue_.push_back(nick->first);
190 >        }
191 >
192 >        module->request_.clear();
193 >
194 >        std::set<CString, SmartISON::Compare> online(module->CheckChans<std::set<CString, SmartISON::Compare> >());
195 >        size_t size(6);
196 >
197 >        while (module->queue_.size())
198 >        {
199 >                CString nick(module->queue_.front());
200 >
201 >                if (!online.count(nick))
202 >                {
203 >                        if ((size += nick.size() + 1) > 512)
204 >                                break;
205 >
206 >                        module->request_.insert(nick);
207 >                }
208 >
209 >                module->queue_.pop_front();
210 >        }
211 >
212 >        if (module->request_.size())
213 >        {
214 >                CString request("ISON");
215 >
216 >                typedef std::set<CString, SmartISON::Compare> NickSet;
217 >
218 >                _foreach (NickSet, nick, module->request_)
219 >                        request += " " + *nick;
220 >
221 >                module->PutIRC(request);
222 >        }
223 > }
224 >
225 > template <>
226 > void SmartISON::CheckChans()
227 > {
228 >        CheckChans<SmartISONVoid>();
229 > }
230 >
231 > CModule::EModRet SmartISON::OnUserRaw(CString &line)
232 > {
233 >        if (line.Token(0).Equals("ISON"))
234 >        {
235 >                CheckChans<void>();
236 >
237 >                std::vector<CString> nicks;
238 >
239 >                line.Token(1, true).TrimLeft_n(":").Split(" ", nicks, false);
240 >
241 >                if (nicks.empty())
242 >                {
243 >                        PutUser(":znc.in 461 " + GetUser()->GetIRCNick().GetNick() + " :Not enough parameters");
244 >                }
245 >                else
246 >                {
247 >                        CString response(":znc.in 303 " + GetUser()->GetIRCNick().GetNick() + " :");
248 >
249 >                        _foreach (std::vector<CString>, nick, nicks)
250 >                        {
251 >                                CString prefix(GetUser()->GetStatusPrefix());
252 >
253 >                                if (nick->Equals(prefix, false, prefix.size()))
254 >                                {
255 >                                        CString modNick(nick->substr(prefix.size()));
256 >
257 >                                        if (modNick.Equals("status") || GetUser()->GetModules().FindModule(modNick) || CZNC::Get().GetModules().FindModule(modNick))
258 >                                                goto online;
259 >                                }
260 >
261 >                                if (!nicks_.count(*nick))
262 >                                        queue_.push_front(*nick);
263 >
264 >                                if (nicks_[*nick])
265 > online:                         response += *nick + " ";
266 >                        }
267 >
268 >                        PutUser(response);
269 >                }
270 >
271 >                return HALT;
272 >        }
273 >
274 >        return CONTINUE;
275 > }
276 >
277 > MODULEDEFS(SmartISON, "Smart ISON");

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines