]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/commands/cmd_privmsg.cpp
Remove InspIRCd* parameters and fields
[user/henk/code/inspircd.git] / src / commands / cmd_privmsg.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2009 InspIRCd Development Team
6  * See: http://wiki.inspircd.org/Credits
7  *
8  * This program is free but copyrighted software; see
9  *            the file COPYING for details.
10  *
11  * ---------------------------------------------------
12  */
13
14 #include "inspircd.h"
15
16 /** Handle /PRIVMSG. These command handlers can be reloaded by the core,
17  * and handle basic RFC1459 commands. Commands within modules work
18  * the same way, however, they can be fully unloaded, where these
19  * may not.
20  */
21 class CommandPrivmsg : public Command
22 {
23  public:
24         /** Constructor for privmsg.
25          */
26         CommandPrivmsg ( Module* parent) : Command(parent,"PRIVMSG",2,2) { syntax = "<target>{,<target>} <message>"; }
27         /** Handle command.
28          * @param parameters The parameters to the comamnd
29          * @param pcnt The number of parameters passed to teh command
30          * @param user The user issuing the command
31          * @return A value from CmdResult to indicate command success or failure.
32          */
33         CmdResult Handle(const std::vector<std::string>& parameters, User *user);
34 };
35
36 CmdResult CommandPrivmsg::Handle (const std::vector<std::string>& parameters, User *user)
37 {
38         User *dest;
39         Channel *chan;
40         CUList except_list;
41
42         user->idle_lastmsg = ServerInstance->Time();
43
44         if (ServerInstance->Parser->LoopCall(user, this, parameters, 0))
45                 return CMD_SUCCESS;
46
47         if (parameters[0][0] == '$')
48         {
49                 if (!user->HasPrivPermission("users/mass-message"))
50                         return CMD_SUCCESS;
51
52                 ModResult MOD_RESULT;
53                 std::string temp = parameters[1];
54                 FIRST_MOD_RESULT(OnUserPreMessage, MOD_RESULT, (user, (void*)parameters[0].c_str(), TYPE_SERVER, temp, 0, except_list));
55                 if (MOD_RESULT == MOD_RES_DENY)
56                         return CMD_FAILURE;
57
58                 const char* text = temp.c_str();
59                 const char* servermask = (parameters[0].c_str()) + 1;
60
61                 FOREACH_MOD(I_OnText,OnText(user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, except_list));
62                 if (InspIRCd::Match(ServerInstance->Config->ServerName, servermask, NULL))
63                 {
64                         user->SendAll("PRIVMSG", "%s", text);
65                 }
66                 FOREACH_MOD(I_OnUserMessage,OnUserMessage(user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, except_list));
67                 return CMD_SUCCESS;
68         }
69         char status = 0;
70         const char* target = parameters[0].c_str();
71
72         if (ServerInstance->Modes->FindPrefix(*target))
73         {
74                 status = *target;
75                 target++;
76         }
77         if (*target == '#')
78         {
79                 chan = ServerInstance->FindChan(target);
80
81                 except_list.insert(user);
82
83                 if (chan)
84                 {
85                         if (IS_LOCAL(user) && chan->GetPrefixValue(user) < VOICE_VALUE)
86                         {
87                                 if (chan->IsModeSet('n') && !chan->HasUser(user))
88                                 {
89                                         user->WriteNumeric(404, "%s %s :Cannot send to channel (no external messages)", user->nick.c_str(), chan->name.c_str());
90                                         return CMD_FAILURE;
91                                 }
92
93                                 if (chan->IsModeSet('m'))
94                                 {
95                                         user->WriteNumeric(404, "%s %s :Cannot send to channel (+m)", user->nick.c_str(), chan->name.c_str());
96                                         return CMD_FAILURE;
97                                 }
98
99                                 if (ServerInstance->Config->RestrictBannedUsers)
100                                 {
101                                         if (chan->IsBanned(user))
102                                         {
103                                                 user->WriteNumeric(404, "%s %s :Cannot send to channel (you're banned)", user->nick.c_str(), chan->name.c_str());
104                                                 return CMD_FAILURE;
105                                         }
106                                 }
107                         }
108                         ModResult MOD_RESULT;
109
110                         std::string temp = parameters[1];
111                         FIRST_MOD_RESULT(OnUserPreMessage, MOD_RESULT, (user,chan,TYPE_CHANNEL,temp,status,except_list));
112                         if (MOD_RESULT == MOD_RES_DENY)
113                                 return CMD_FAILURE;
114
115                         const char* text = temp.c_str();
116
117                         /* Check again, a module may have zapped the input string */
118                         if (temp.empty())
119                         {
120                                 user->WriteNumeric(412, "%s :No text to send", user->nick.c_str());
121                                 return CMD_FAILURE;
122                         }
123
124                         FOREACH_MOD(I_OnText,OnText(user,chan,TYPE_CHANNEL,text,status,except_list));
125
126                         if (status)
127                         {
128                                 if (ServerInstance->Config->UndernetMsgPrefix)
129                                 {
130                                         chan->WriteAllExcept(user, false, status, except_list, "PRIVMSG %c%s :%c %s", status, chan->name.c_str(), status, text);
131                                 }
132                                 else
133                                 {
134                                         chan->WriteAllExcept(user, false, status, except_list, "PRIVMSG %c%s :%s", status, chan->name.c_str(), text);
135                                 }
136                         }
137                         else
138                         {
139                                 chan->WriteAllExcept(user, false, status, except_list, "PRIVMSG %s :%s", chan->name.c_str(), text);
140                         }
141
142                         FOREACH_MOD(I_OnUserMessage,OnUserMessage(user,chan,TYPE_CHANNEL,text,status,except_list));
143                 }
144                 else
145                 {
146                         /* no such nick/channel */
147                         user->WriteNumeric(401, "%s %s :No such nick/channel", user->nick.c_str(), target);
148                         return CMD_FAILURE;
149                 }
150                 return CMD_SUCCESS;
151         }
152
153         const char* destnick = parameters[0].c_str();
154
155         if (IS_LOCAL(user))
156         {
157                 const char* targetserver = strchr(destnick, '@');
158
159                 if (targetserver)
160                 {
161                         std::string nickonly;
162
163                         nickonly.assign(destnick, 0, targetserver - destnick);
164                         dest = ServerInstance->FindNickOnly(nickonly);
165                         if (dest && strcasecmp(dest->server, targetserver + 1))
166                         {
167                                 /* Incorrect server for user */
168                                 user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
169                                 return CMD_FAILURE;
170                         }
171                 }
172                 else
173                         dest = ServerInstance->FindNickOnly(destnick);
174         }
175         else
176                 dest = ServerInstance->FindNick(destnick);
177
178         if (dest)
179         {
180                 if (parameters[1].empty())
181                 {
182                         user->WriteNumeric(412, "%s :No text to send", user->nick.c_str());
183                         return CMD_FAILURE;
184                 }
185
186                 if (IS_AWAY(dest))
187                 {
188                         /* auto respond with aweh msg */
189                         user->WriteNumeric(301, "%s %s :%s", user->nick.c_str(), dest->nick.c_str(), dest->awaymsg.c_str());
190                 }
191
192                 ModResult MOD_RESULT;
193
194                 std::string temp = parameters[1];
195                 FIRST_MOD_RESULT(OnUserPreMessage, MOD_RESULT, (user, dest, TYPE_USER, temp, 0, except_list));
196                 if (MOD_RESULT == MOD_RES_DENY)
197                         return CMD_FAILURE;
198
199                 const char* text = temp.c_str();
200
201                 FOREACH_MOD(I_OnText,OnText(user, dest, TYPE_USER, text, 0, except_list));
202
203                 if (IS_LOCAL(dest))
204                 {
205                         // direct write, same server
206                         user->WriteTo(dest, "PRIVMSG %s :%s", dest->nick.c_str(), text);
207                 }
208
209                 FOREACH_MOD(I_OnUserMessage,OnUserMessage(user, dest, TYPE_USER, text, 0, except_list));
210         }
211         else
212         {
213                 /* no such nick/channel */
214                 user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
215                 return CMD_FAILURE;
216         }
217         return CMD_SUCCESS;
218 }
219
220 COMMAND_INIT(CommandPrivmsg)