[project @ 2005-06-25 18:11:10 by unknown_lamer]
[clinton/bobotpp.git] / source / Commands.C
CommitLineData
cb21075d 1// Commands.C -*- C++ -*-
2// Copyright (c) 1998 Etienne BERNARD
a6339323 3// Copyright (C) 2002,2005 Clinton Ebadi
cb21075d 4
5// This program is free software; you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation; either version 2 of the License, or
8// any later version.
9
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14
15// You should have received a copy of the GNU General Public License
16// along with this program; if not, write to the Free Software
39b022cb 17// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
cb21075d 18
19#include "Macros.H"
20#include "Message.H"
21#include "Commands.H"
22#include "Utils.H"
23
cb21075d 24
25#define CHECK_CONNECTION if (!bot->serverConnection) return NotConnected
26
27Message
28Commands::Action(Bot *bot, String channel, String message)
29{
30 CHECK_CONNECTION;
31
32 if (!CHANNEL(channel))
33 return NotOnChannel(channel);
34
35 if (message.length() == 0)
36 return InvalidParameters;
37
fd7440f1 38 QUEUE->sendCTCP (channel, "ACTION", message);
cb21075d 39
40 return Ok;
41}
42
43Message
44Commands::AddUser(Bot *bot, String who, String maskChannel, int level,
45 int prot, bool aop, std::time_t expire, String password)
46{
47 // Gah, fix this (makes bot segfault)
48 if (who.length() == 0 ||
49 maskChannel.length() == 0 ||
50 level < 0 ||
51 level > User::FRIEND ||
52 prot < 0 ||
53 prot > User::NO_DEOP)
54 return InvalidParameters;
55
56 String mask;
57
a6339323 58 if (!Utils::wildcard_p(who))
cb21075d 59 {
0316e2c1 60 mask = bot->getUserhost("", who);
61 if (mask.length() == 0)
62 {
63 return NotFound(who);
64 }
65 }
cb21075d 66 // Aha! This was before the brace...segfault gone
a6339323 67 mask = Utils::make_wildcard(mask);
cb21075d 68
69 if (bot->userList->isInUserList(mask, maskChannel))
0316e2c1 70 {
71 return AlreadyInUserlist(mask, maskChannel);
72 }
cb21075d 73
74 bot->userList->addUser(mask, maskChannel, level, prot, aop,
75 expire, password);
76 bot->rehash();
77
78 return Ok;
79}
80
81
82Message
83Commands::AddServer(Bot *bot, String servername, int port)
84{
85 if (port <= 0)
86 return InvalidPort(port);
87
88 bot->serverList->addServer(new class Server(servername, port));
89
90 return Ok;
91}
92
93
94Message
95Commands::AddShit(Bot *bot, String mask, String maskChannel,
96 int level, time_t expiration, String reason)
97{
98 if (mask.length() == 0 || maskChannel.length() == 0 ||
99 level < 0 || level > ShitEntry::SHIT_NODEBAN)
100 return InvalidParameters;
101
102 if (reason == "")
103 reason = "You're on my shitlist, lamer";
104
105 String who = mask;
106
a6339323 107 if (!Utils::wildcard_p(mask)) {
cb21075d 108 mask = bot->getUserhost("", who);
109 if (mask.length() == 0)
110 return NotFound(who);
a6339323 111 mask = Utils::make_wildcard(mask);
cb21075d 112 if (bot->shitList->getShit(mask, maskChannel))
113 return AlreadyInShitlist(mask, maskChannel);
114 }
115
116 if (bot->userList->getMaxProt(mask, maskChannel) > 0)
117 return UserProtected(who, maskChannel);
118
119 bot->shitList->addShit(mask, maskChannel, level, expiration, reason);
120
121 return Ok;
122}
123
124
125Message
126Commands::Ban(Bot *bot, String channel, String who)
127{
128 CHECK_CONNECTION;
129
130 Channel *c = CHANNEL(channel);
131
132 if (!c)
133 return NotOnChannel(channel);
134
135 if (!bot->iAmOp(channel))
136 return NotChannelOp(channel);
137
138 String dest;
139
a6339323 140 if (!Utils::wildcard_p(who))
cb21075d 141 dest = bot->getUserhost(channel, who);
142 else
143 dest = who;
144
145 if (dest.length() == 0)
146 return NotFound(who);
147
a6339323 148 dest = Utils::make_wildcard(dest);
cb21075d 149 Mask m(dest);
150
151 for (std::list<UserListItem *>::iterator it = bot->userList->l.begin();
152 it != bot->userList->l.end();
153 it++)
154 if (m.matches((*it)->mask) &&
155 (*it)->channelMask.matches(channel) &&
156 (*it)->prot >= User::NO_BAN)
157 return UserProtected(who, channel);
158
159 for (std::vector<BanEntry *>::iterator it = c->channelBanlist.begin();
160 it != c->channelBanlist.end(); ++it)
161 if (m.matches((*it)->banMask) && (*it)->banMask.getMask() != m.getMask())
162 QUEUE->sendChannelMode(channel, "-b", (*it)->banMask.getMask());
163
164 QUEUE->sendChannelMode(channel, "+b", dest);
165
166 return Ok;
167}
168
169Message
170Commands::Cycle(Bot *bot, String channel)
171{
172 CHECK_CONNECTION;
173
174 if (!CHANNEL(channel))
175 return NotOnChannel(channel);
176
177 QUEUE->sendPart(channel);
178 QUEUE->sendJoin(channel, bot->wantedChannels[channel]->key);
179
180 return Ok;
181}
182
183Message
184Commands::Deban(Bot *bot, String channel, String who)
185{
186 CHECK_CONNECTION;
187
188 Channel *c = CHANNEL(channel);
189
190 if (!c)
191 return NotOnChannel(channel);
192
193 if (!bot->iAmOp(channel))
194 return NotChannelOp(channel);
195
196 String dest;
197
a6339323 198 if (!Utils::wildcard_p(who))
cb21075d 199 dest = bot->getUserhost(channel, who);
200 else
201 dest = who;
202
203 if (dest.length() == 0)
204 return UserNotFound(who, channel);
205
a6339323 206 dest = Utils::make_wildcard(dest);
cb21075d 207 Mask m(dest);
208
209 for (std::vector<BanEntry *>::iterator it = c->channelBanlist.begin();
210 it != c->channelBanlist.end(); ++it)
211 if (m.matches((*it)->getMask())) {
212 // Let's see if the ban is in the shitlist
213 ShitEntry *se = bot->shitList->getShit((*it)->getMask(), channel);
214 if (!se || !se->isStillValid() ||
215 se->getShitLevel() < ShitEntry::SHIT_NODEBAN)
216 QUEUE->sendChannelMode(channel, "-b", (*it)->getMask());
217 }
218
219 return Ok;
220}
221
222Message
223Commands::DelServer(Bot *bot, int number)
224{
225 if (number < 0 || number >= bot->serverList->size())
226 return InvalidServerNumber(number);
227
228 bot->serverList->delServer(number);
229
230 return Ok;
231}
232
233Message
234Commands::DelUser(Bot *bot, String who, String maskChannel)
235{
236 if (who.length() == 0 || maskChannel.length() == 0)
237 return InvalidParameters;
238
239 String dest;
240
a6339323 241 if (!Utils::wildcard_p(who)) {
cb21075d 242 dest = bot->getUserhost("", who);
243 if (dest.length() == 0)
244 return NotFound(who);
a6339323 245 dest = Utils::make_wildcard(who);
cb21075d 246 }
247
248 if (!bot->userList->isInUserList(dest, maskChannel))
249 return NotInUserlist(who);
250
251 bot->userList->removeUser(dest, maskChannel);
252 bot->rehash();
253
254 return Ok;
255}
256
257Message
258Commands::DelShit(Bot *bot, String who, String maskChannel)
259{
260 if (who.length() == 0 || maskChannel.length() == 0)
261 return InvalidParameters;
262
263 String dest;
264
a6339323 265 if (!Utils::wildcard_p(who)) {
cb21075d 266 dest = bot->getUserhost("", who);
267 if (dest.length() == 0)
268 return NotFound(who);
a6339323 269 dest = Utils::make_wildcard(who);
cb21075d 270 }
271
272 if (!bot->shitList->getShit(dest, maskChannel))
273 return NotInShitlist(who);
274
275 bot->shitList->delShit(dest, maskChannel);
276
277 return Ok;
278}
279
280Message
281Commands::Deop(Bot *bot, String channel, String who)
282{
283 CHECK_CONNECTION;
284
285 Channel *c = CHANNEL(channel);
286
287 if (!c)
288 return NotOnChannel(channel);
289
290 if (!bot->iAmOp(channel))
291 return NotChannelOp(channel);
292
a6339323 293 if (!Utils::wildcard_p(who)) {
cb21075d 294 User *u = c->getUser(who);
295 if (!u)
296 return UserNotFound(who, channel);
297 if (!(u->mode & User::OP_MODE))
298 return UserNotOp(who, channel);
299 if (u->getProt() >= User::NO_DEOP)
300 return UserProtected(who, channel);
301 QUEUE->sendChannelMode(channel, "-o", who);
302 } else {
303 Mask m(who);
304 for (std::map<String, User *, std::less<String> >::iterator
305 it = c->channelMemory.begin();
306 it != c->channelMemory.end(); ++it) {
307 if (m.matches((*it).second->nick + "!" +
308 (*it).second->userhost) &&
309 (*it).second->getProt() < User::NO_DEOP &&
310 ((*it).second->mode & User::OP_MODE))
311 QUEUE->sendChannelMode(channel, "-o", (*it).second->nick);
312 }
313 }
314
315 return Ok;
316}
317
318Message
319Commands::Die(Bot *bot, String reason)
320{
321 CHECK_CONNECTION;
322
323 QUEUE->sendQuit(reason);
324 bot->stop = true;
325
326 return Ok;
327}
328
329Message
330Commands::Do(Bot *bot, String command)
331{
332 CHECK_CONNECTION;
333
334 QUEUE->addLine(command, 0, 0, ServerQueueItem::OTHER);
335 return Ok;
336}
337
338Message
339Commands::Invite(Bot *bot, String channel, String who)
340{
341 CHECK_CONNECTION;
342
343 if (!bot->iAmOp(channel))
344 return NotChannelOp(channel);
345
346 QUEUE->sendInvite(channel, who);
347
348 return Ok;
349}
350
351Message
352Commands::Join(Bot *bot, String channel, String key)
353{
354 CHECK_CONNECTION;
355
a6339323 356 if (!Utils::valid_channel_name_p(channel))
cb21075d 357 return InvalidChannel(channel);
358
359 // We change the key only if we are not on the channel.
360 // We don't trust the user...
361 if (!CHANNEL(channel)) {
362 if (bot->wantedChannels[channel])
363 bot->wantedChannels[channel]->key = key;
364 else {
365 bot->wantedChannels[channel] = new wantedChannel("", "", key);
366 }
367 }
368 QUEUE->sendJoin(channel, bot->wantedChannels[channel]->key);
369
370 return Ok;
371}
372
373Message
374Commands::Keep(Bot *bot, String channel, String modes)
375{
376 CHECK_CONNECTION;
377
378 Channel *c = CHANNEL(channel);
379
380 if (!c)
381 return NotOnChannel(channel);
382
383 c->keepModes = modes;
384
385 return Ok;
386}
387
388Message
389Commands::Kick(Bot *bot, String channel, String who, String reason)
390{
391 CHECK_CONNECTION;
392
393 Channel *c = CHANNEL(channel);
394
395 if (!c)
396 return NotOnChannel(channel);
397
398 if (!bot->iAmOp(channel))
399 return NotChannelOp(channel);
400
a6339323 401 if (Utils::wildcard_p(who)) {
cb21075d 402 Mask m(who);
403 for (std::map<String, User *, std::less<String> >::iterator it =
404 c->channelMemory.begin();
405 it != c->channelMemory.end();
406 ++it)
407 if (m.matches((*it).second->nick + "!" +
408 (*it).second->userhost) &&
409 (*it).second->getProt() < User::NO_KICK)
410 QUEUE->sendKick(channel, (*it).second->nick, reason);
411 } else {
412 User * u = c->getUser(who);
413 if (!u)
414 return UserNotFound(who, channel);
415 if (u->getProt() < User::NO_KICK)
416 QUEUE->sendKick(channel, who, reason);
417 else
418 return UserProtected(who, channel);
419 }
420
421 return Ok;
422}
423
424Message
425Commands::KickBan(Bot *bot, String channel, String who, String reason)
426{
427 CHECK_CONNECTION;
428
429 Message m = Commands::Ban(bot, channel, who);
430
431 if (m.getCode() == 0)
432 m = Commands::Kick(bot, channel, who, reason);
433
434 return m;
435}
436
437Message
438Commands::Lock(Bot *bot, String channel)
439{
440 CHECK_CONNECTION;
441
442 Channel *c = CHANNEL(channel);
443
444 if (!c)
445 return NotOnChannel(channel);
446
447 c->lockedTopic = true;
448
449 return Ok;
450}
451
452Message
453Commands::Mode(Bot *bot, String channel, String mode)
454{
455 CHECK_CONNECTION;
456
457 if (!CHANNEL(channel))
458 return NotOnChannel(channel);
459
460 if (!bot->iAmOp(channel))
461 return NotChannelOp(channel);
462
463 QUEUE->sendChannelMode(String("MODE ") + channel + " " + mode);
464
465 return Ok;
466}
467
468Message
469Commands::Msg(Bot *bot, String who, String message)
470{
471 CHECK_CONNECTION;
472
473 if (who == "")
5c73c60a 474 {
475 return EmptyAddressee;
476 }
cb21075d 477
a6339323 478 if (Utils::channel_p(who))
5c73c60a 479 {
4cc479d8 480 if (!CHANNEL(who))
481 {
482 return NotOnChannel (who);
483 }
5c73c60a 484 }
cb21075d 485
486 if (message == "")
5c73c60a 487 {
488 return EmptyMessage;
489 }
cb21075d 490
491 QUEUE->sendPrivmsg(who, message);
492
493 return Ok;
494}
495
496Message
497Commands::NextServer(Bot *bot)
498{
499 CHECK_CONNECTION;
500
501 if (bot->serverList->size() == 0)
502 return EmptyServerList;
503
504 if (!bot->canChangeServer())
505 return CanNotChangeServer;
506
507 QUEUE->sendQuit("Changing server");
508 bot->nextServer();
509
510 return Ok;
511}
512
513Message
514Commands::Nick(Bot *bot, String nick)
515{
516 CHECK_CONNECTION;
517
a6339323 518 if (nick == "" || !Utils::valid_nickname_p(nick))
cb21075d 519 return InvalidNick(nick);
520
521 bot->wantedNickName = nick;
522 QUEUE->sendNick(nick);
523
524 return Ok;
525}
526
527Message
528Commands::Notice(Bot *bot, String who, String message)
529{
530 CHECK_CONNECTION;
531
532 if (who == "")
533 return EmptyAddressee;
534
5aec4622 535 // if (Utils::channel_p(who))
536 // return NotToChannel;
cb21075d 537
538 if (message == "")
539 return EmptyMessage;
540
541 QUEUE->sendNotice(who, message);
542
543 return Ok;
544}
545
546Message
547Commands::Op(Bot *bot, String channel, String who)
548{
549 CHECK_CONNECTION;
550
551 Channel *c = CHANNEL(channel);
552
553 if (!c)
554 return NotOnChannel(channel);
555
556 if (!bot->iAmOp(channel))
557 return NotChannelOp(channel);
558
a6339323 559 if (Utils::wildcard_p(who))
cb21075d 560 return MassOpNotAllowed;
561
562 User *u = c->getUser(who);
563 if (!u)
564 return UserNotFound(who, channel);
565
566 ShitEntry *se = bot->shitList->getShit(who, channel);
567 if (se && se->isStillValid() && se->getShitLevel() >= ShitEntry::SHIT_NOOP)
568 return UserOnShitList(who);
569
570 QUEUE->sendChannelMode(channel, "+o", who);
571
572 return Ok;
573}
574
575
576Message
577Commands::Part(Bot *bot, String channel)
578{
579 CHECK_CONNECTION;
580
581 if (!CHANNEL(channel))
582 return NotOnChannel(channel);
583
584 wantedChannel *w = bot->wantedChannels[channel];
585 bot->wantedChannels.erase(channel);
586 delete w;
587 QUEUE->sendPart(channel);
588
589 return Ok;
590}
591
592Message
593Commands::Reconnect(Bot *bot)
594{
595 CHECK_CONNECTION;
596
597 if (!bot->canChangeServer())
598 return CanNotChangeServer;
599
600 QUEUE->sendQuit("Reconnecting");
601 bot->reconnect();
602
603 return Ok;
604}
605
606Message
607Commands::Say(Bot *bot, String channel, String message)
608{
4cc479d8 609 return Commands::Msg (bot, channel, message);
cb21075d 610}
611
612
613Message
614Commands::Server(Bot *bot, int number)
615{
616 CHECK_CONNECTION;
617
618 if (number < 0 || number >= bot->serverList->size())
619 return InvalidServerNumber(number);
620
621 if (!bot->canChangeServer())
622 return CanNotChangeServer;
623
624 QUEUE->sendQuit("Changing server");
625 QUEUE->flush();
626 bot->connect(number);
627
628 return Ok;
629}
630
e171dcce 631Message
632Commands::SetFloodRate(Bot *bot, unsigned int num_messages)
633{
634 if (num_messages > 0)
635 {
636 bot->MAX_MESSAGES = num_messages;
637 return Ok;
638 }
639 return InvalidParameters;
640}
641
cb21075d 642Message
643Commands::SetVersion(Bot *bot, String str)
644{
645 if (str.length() == 0)
646 return InvalidParameters;
647
648 bot->versionString = str;
649 return Ok;
650}
651
652Message
653Commands::TBan(Bot *bot, String channel, String who, int seconds)
654{
655 CHECK_CONNECTION;
656
657 Channel *c = CHANNEL(channel);
cf8ea873 658 String dest;
cb21075d 659
cf8ea873 660 // Make sure all of the inputs are valid
cb21075d 661 if (!c)
cf8ea873 662 {
663 return NotOnChannel(channel);
664 }
cb21075d 665
666 if (!bot->iAmOp(channel))
cf8ea873 667 {
668 return NotChannelOp(channel);
669 }
cb21075d 670
671 if (seconds <= 0)
cf8ea873 672 {
673 return InvalidTime(seconds);
674 }
cb21075d 675
cf8ea873 676 // Look for user
a6339323 677 if (!Utils::wildcard_p(who))
cf8ea873 678 {
679 dest = bot->getUserhost(channel, who);
680 }
cb21075d 681 else
cf8ea873 682 {
683 dest = who;
684 }
cb21075d 685
686 if (dest.length() == 0)
cf8ea873 687 {
688 return UserNotFound(who, channel);
689 }
690
cb21075d 691
a6339323 692 dest = Utils::make_wildcard(dest);
cb21075d 693 Mask m(dest);
694
cf8ea873 695 // Make sure the user isn't protected from bans
cb21075d 696 for (std::list<UserListItem *>::iterator it = bot->userList->l.begin();
697 it != bot->userList->l.end();
698 it++)
cf8ea873 699 {
700 if (m.matches((*it)->mask) &&
701 (*it)->channelMask.matches(channel) &&
702 (*it)->prot >= User::NO_BAN)
703 {
704 return UserProtected(who, channel);
705 }
706 }
cb21075d 707
cf8ea873 708 // Clear existing bans on the user
cb21075d 709 for (std::vector<BanEntry *>::iterator it = c->channelBanlist.begin();
710 it != c->channelBanlist.end(); ++it)
cf8ea873 711 {
712 if (m.matches((*it)->banMask))
713 {
714 QUEUE->sendChannelMode(channel, "-b", (*it)->banMask.getMask());
715 }
716 }
cb21075d 717
cf8ea873 718 // Ban them
cb21075d 719 CHANNEL(channel)->addBan(dest, seconds);
720 QUEUE->sendChannelMode(channel, "+b", dest);
721 bot->todoList->addDeban(channel, dest, seconds);
cf8ea873 722
723 return Ok;
cb21075d 724}
725
726
727Message
728Commands::TKBan(Bot *bot, String channel, String who, int seconds, String reason)
729{
730 CHECK_CONNECTION;
731
732 Message m = Commands::TBan(bot, channel, who, seconds);
733
734 if (m.getCode() == 0)
735 m = Commands::Kick(bot, channel, who, reason);
736
737 return m;
738}
739
740
741Message
742Commands::Topic(Bot *bot, String channel, String topic)
743{
744 CHECK_CONNECTION;
745
746 Channel *c = CHANNEL(channel);
747
748 if (!c)
749 return NotOnChannel(channel);
750
751 if (!bot->iAmOp(channel) && !(c->channelMode & Channel::TOPIC_RESTRICTED))
752 return CanNotChangeTopic(channel);
753
754 if (c->lockedTopic)
755 return TopicLocked(channel);
756
757 QUEUE->sendTopic(channel, topic);
758
759 return Ok;
760}
761
762
763Message
764Commands::Unlock(Bot *bot, String channel)
765{
766 CHECK_CONNECTION;
767
768 Channel *c = CHANNEL(channel);
769
770 if (!c)
771 return NotOnChannel(channel);
772
773 c->lockedTopic = false;
774
775 return Ok;
776}