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

# 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 1263 virtual bool OnLoad(const CString &args, CString &message)
48 douglas 1262 {
49 douglas 1263 return AddTimer(new SmartISONTimer(this));
50 douglas 1262 }
51    
52 douglas 1263 virtual void OnModCommand(const CString &command)
53 douglas 1262 {
54 douglas 1263 CString theCommand(command.Token(0));
55    
56     if (theCommand.Equals("Help"))
57 douglas 1262 {
58 douglas 1263 CTable table;
59 douglas 1262
60 douglas 1263 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 douglas 1262 {
76 douglas 1263 CTable table;
77 douglas 1262
78 douglas 1263 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 douglas 1262 }
92 douglas 1263 else if (theCommand.Equals("Queue"))
93     if (queue_.empty())
94     PutModule("Nick queue empty");
95     else
96     {
97     CTable table;
98 douglas 1262
99 douglas 1263 table.AddColumn("Nick");
100 douglas 1262
101 douglas 1263 _foreach (const std::deque<CString>, nick, queue_)
102     {
103     table.AddRow();
104     table.SetCell("Nick", *nick);
105     }
106 douglas 1262
107 douglas 1263 PutModule(table);
108     }
109     else
110     PutModule("Unknown command [" + theCommand + "] try 'Help'");
111     }
112 douglas 1262
113 douglas 1263 virtual void OnNick(const CNick &nick, const CString &newNick, const std::vector<CChan *> &chans)
114     {
115     const CString &oldNick(nick.GetNick());
116 douglas 1262
117 douglas 1263 nicks_[oldNick] = false;
118     nicks_[newNick] = true;
119     }
120 douglas 1262
121 douglas 1263 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 douglas 1262 }
146    
147     return CONTINUE;
148     }
149 douglas 1263
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 douglas 1262 };
174    
175 douglas 1263 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