…lines 1–26 unchanged (26 lines)
27 {
28 m_play = false;
29 AddHelpCommand();
30 AddCommand("Clear", static_cast<CModCommand::ModCmdFunc>(&CPlaybackMod::ClearCommand), "<buffer(s)>", "Clears playback for given buffers.");
31 AddCommand("Play", static_cast<CModCommand::ModCmdFunc>(&CPlaybackMod::PlayCommand), "<buffer(s)> [from] [to]", "Sends playback for given buffers.");
32 AddCommand("List", static_cast<CModCommand::ModCmdFunc>(&CPlaybackMod::ListCommand), "[buffer(s)]", "Lists available/matching buffers.");
33 AddCommand("Limit", static_cast<CModCommand::ModCmdFunc>(&CPlaybackMod::LimitCommand), "<client> [limit]", "Get/set the buffer limit (<= 0 to clear) for the given client.");
34 }
35
36 void OnClientCapLs(CClient* client, SCString& caps) override
37 {
38 caps.insert(PlaybackCap);
39 caps.insert(EchoMessageCap);
…lines 40–92 unchanged (53 lines)
93 if (arg.empty() || !line.Token(4).empty())
94 return;
95 double from = line.Token(2).ToDouble();
96 double to = DBL_MAX;
97 if (!line.Token(3).empty())
98 to = line.Token(3).ToDouble();
99 int limit = -1;
100 if (CClient* client = GetClient())
101 limit = GetLimit(client->GetIdentifier());
102 std::vector<CChan*> chans = FindChans(arg);
103 for (CChan* chan : chans) {
104 if (chan->IsOn() && !chan->IsDetached()) {
105 CBuffer lines = GetLines(chan->GetBuffer(), from, to, limit);
106 m_play = true;
107 chan->SendBuffer(GetClient(), lines);
108 m_play = false;
109 }
110 }
111 std::vector<CQuery*> queries = FindQueries(arg);
112 for (CQuery* query : queries) {
113 CBuffer lines = GetLines(query->GetBuffer(), from, to, limit);
114 m_play = true;
115 query->SendBuffer(GetClient(), lines);
116 m_play = false;
117 }
118 }
119
…lines 120–141 unchanged (22 lines)
142 timeval to = UniversalTime(buffer.GetBufLine(buffer.Size() - 1).GetTime());
143 PutModule(query->GetName() + " " + CString(Timestamp(from)) + " " + CString(Timestamp(to)));
144 }
145 }
146 }
147
148 void LimitCommand(const CString& line)
149 {
150 // LIMIT <client> [limit]
151 const CString client = line.Token(1);
152 if (client.empty()) {
153 PutModule("Usage: LIMIT <client> [limit]");
154 return;
155 }
156 const CString arg = line.Token(2);
157 int limit = GetLimit(client);
158 if (!arg.empty()) {
159 limit = arg.ToInt();
160 SetLimit(client, limit);
161 }
162 if (limit <= 0)
163 PutModule(client + " buffer limit: -");
164 else
165 PutModule(client + " buffer limit: " + CString(limit));
166 }
167
168 EModRet OnSendToClient(CString& line, CClient& client) override
169 {
170 if (client.IsAttached() && client.IsCapEnabled(PlaybackCap) && !line.Token(0).Equals("CAP")) {
171 MCString tags = CUtils::GetMessageTags(line);
172 if (tags.find("time") == tags.end()) {
…lines 173–270 unchanged (98 lines)
271 queries.insert(queries.end(), found.begin(), found.end());
272 }
273 }
274 return queries;
275 }
276
277 int GetLimit(const CString& client) const
278 {
279 return GetNV(client).ToInt();
280 }
281
282 void SetLimit(const CString& client, int limit)
283 {
284 if (limit > 0)
285 SetNV(client, CString(limit));
286 else
287 DelNV(client);
288 }
289
290 static CBuffer GetLines(const CBuffer& buffer, double from, double to, int limit)
291 {
292 CBuffer lines(buffer.Size());
293 for (size_t i = 0; i < buffer.Size(); ++i) {
294 const CBufLine& line = buffer.GetBufLine(i);
295 timeval tv = UniversalTime(line.GetTime());
296 if (from < Timestamp(tv) && to >= Timestamp(tv))
297 lines.AddLine(line.GetFormat(), line.GetText(), &tv);
298 }
299 if (limit > 0)
300 lines.SetLineCount(limit);
301 return lines;
302 }
303
304 bool m_play;
305};
306
307GLOBALMODULEDEFS(CPlaybackMod, "An advanced playback module for ZNC")
308