ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/FreeBSDAdmin/IRC/smart_ison.cpp
Revision: 1263
Committed: 2010-03-21T06:30:15-07:00 (15 years, 3 months ago) by douglas
File size: 5515 byte(s)
Log Message:
Smart ISON!

File Contents

# Content
1 // 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 #include <znc.h>
12
13 #include <deque>
14 #include <map>
15 #include <set>
16
17 #include "foreach.hpp"
18
19 #pragma GCC diagnostic ignored "-Wshadow"
20
21 struct SmartISONTimer : public CTimer
22 {
23 SmartISONTimer(CModule *module) : CTimer(module, 15, 0, "Smart ISON", "Smart ISON") {}
24 virtual ~SmartISONTimer() {}
25
26 virtual void RunJob();
27 };
28
29 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
39 std::map<CString, bool, Compare> nicks_;
40 std::deque<CString> queue_;
41 std::set<CString, Compare> request_;
42
43 public:
44 MODCONSTRUCTOR(SmartISON) {}
45 virtual ~SmartISON() {}
46
47 virtual bool OnLoad(const CString &args, CString &message)
48 {
49 return AddTimer(new SmartISONTimer(this));
50 }
51
52 virtual void OnModCommand(const CString &command)
53 {
54 CString theCommand(command.Token(0));
55
56 if (theCommand.Equals("Help"))
57 {
58 CTable table;
59
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 CTable table;
98
99 table.AddColumn("Nick");
100
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 nicks_[oldNick] = false;
118 nicks_[newNick] = true;
119 }
120
121 virtual void OnQuit(const CNick &nick, const CString &message, const std::vector<CChan *> &chans)
122 {
123 const CString &theNick(nick.GetNick());
124
125 nicks_[theNick] = false;
126 }
127
128 virtual EModRet OnRaw(CString &line)
129 {
130 if (line.Token(1) == "303")
131 {
132 typedef std::set<CString, Compare> NickSet;
133
134 _foreach (NickSet, nick, request_)
135 nicks_[*nick] = false;
136
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 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");

Properties

Name Value
svn:keywords Id