]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_ircv3.cpp
Merge branch 'insp20' into insp3.
[user/henk/code/inspircd.git] / src / modules / m_ircv3.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2012 Attila Molnar <attilamolnar@hush.com>
5  *
6  * This file is part of InspIRCd.  InspIRCd is free software: you can
7  * redistribute it and/or modify it under the terms of the GNU General Public
8  * License as published by the Free Software Foundation, version 2.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
13  * details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include "inspircd.h"
20 #include "modules/account.h"
21 #include "modules/away.h"
22 #include "modules/cap.h"
23 #include "modules/ircv3.h"
24
25 class AwayMessage : public ClientProtocol::Message
26 {
27  public:
28         AwayMessage(User* user)
29                 : ClientProtocol::Message("AWAY", user)
30         {
31                 SetParams(user, user->awaymsg);
32         }
33
34         AwayMessage()
35                 : ClientProtocol::Message("AWAY")
36         {
37         }
38
39         void SetParams(User* user, const std::string& awaymsg)
40         {
41                 // Going away: 1 parameter which is the away reason
42                 // Back from away: no parameter
43                 if (!awaymsg.empty())
44                         PushParam(awaymsg);
45         }
46 };
47
48 class JoinHook : public ClientProtocol::EventHook
49 {
50         ClientProtocol::Events::Join extendedjoinmsg;
51
52  public:
53         const std::string asterisk;
54         ClientProtocol::EventProvider awayprotoev;
55         AwayMessage awaymsg;
56         Cap::Capability extendedjoincap;
57         Cap::Capability awaycap;
58
59         JoinHook(Module* mod)
60                 : ClientProtocol::EventHook(mod, "JOIN")
61                 , asterisk(1, '*')
62                 , awayprotoev(mod, "AWAY")
63                 , extendedjoincap(mod, "extended-join")
64                 , awaycap(mod, "away-notify")
65         {
66         }
67
68         void OnEventInit(const ClientProtocol::Event& ev) CXX11_OVERRIDE
69         {
70                 const ClientProtocol::Events::Join& join = static_cast<const ClientProtocol::Events::Join&>(ev);
71
72                 // An extended join has two extra parameters:
73                 // First the account name of the joining user or an asterisk if the user is not logged in.
74                 // The second parameter is the realname of the joining user.
75
76                 Membership* const memb = join.GetMember();
77                 const std::string* account = &asterisk;
78                 const AccountExtItem* const accountext = GetAccountExtItem();
79                 if (accountext)
80                 {
81                         const std::string* accountname = accountext->get(memb->user);
82                         if (accountname)
83                                 account = accountname;
84                 }
85
86                 extendedjoinmsg.ClearParams();
87                 extendedjoinmsg.SetSource(join);
88                 extendedjoinmsg.PushParamRef(memb->chan->name);
89                 extendedjoinmsg.PushParamRef(*account);
90                 extendedjoinmsg.PushParamRef(memb->user->GetRealName());
91
92                 awaymsg.ClearParams();
93                 if ((memb->user->IsAway()) && (awaycap.IsActive()))
94                 {
95                         awaymsg.SetSource(join);
96                         awaymsg.SetParams(memb->user, memb->user->awaymsg);
97                 }
98         }
99
100         ModResult OnPreEventSend(LocalUser* user, const ClientProtocol::Event& ev, ClientProtocol::MessageList& messagelist) CXX11_OVERRIDE
101         {
102                 if (extendedjoincap.get(user))
103                         messagelist.front() = &extendedjoinmsg;
104
105                 if ((!awaymsg.GetParams().empty()) && (awaycap.get(user)))
106                         messagelist.push_back(&awaymsg);
107
108                 return MOD_RES_PASSTHRU;
109         }
110 };
111
112 class ModuleIRCv3
113         : public Module
114         , public AccountEventListener
115         , public Away::EventListener
116 {
117         Cap::Capability cap_accountnotify;
118         JoinHook joinhook;
119
120         ClientProtocol::EventProvider accountprotoev;
121
122  public:
123         ModuleIRCv3()
124                 : AccountEventListener(this)
125                 , Away::EventListener(this)
126                 , cap_accountnotify(this, "account-notify")
127                 , joinhook(this)
128                 , accountprotoev(this, "ACCOUNT")
129         {
130         }
131
132         void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
133         {
134                 ConfigTag* conf = ServerInstance->Config->ConfValue("ircv3");
135                 cap_accountnotify.SetActive(conf->getBool("accountnotify", true));
136                 joinhook.awaycap.SetActive(conf->getBool("awaynotify", true));
137                 joinhook.extendedjoincap.SetActive(conf->getBool("extendedjoin", true));
138         }
139
140         void OnAccountChange(User* user, const std::string& newaccount) CXX11_OVERRIDE
141         {
142                 // Logged in: 1 parameter which is the account name
143                 // Logged out: 1 parameter which is a "*"
144                 ClientProtocol::Message msg("ACCOUNT", user);
145                 const std::string& param = (newaccount.empty() ? joinhook.asterisk : newaccount);
146                 msg.PushParamRef(param);
147                 ClientProtocol::Event accountevent(accountprotoev, msg);
148                 IRCv3::WriteNeighborsWithCap(user, accountevent, cap_accountnotify);
149         }
150
151         void OnUserAway(User* user) CXX11_OVERRIDE
152         {
153                 if (!joinhook.awaycap.IsActive())
154                         return;
155
156                 // Going away: n!u@h AWAY :reason
157                 AwayMessage msg(user);
158                 ClientProtocol::Event awayevent(joinhook.awayprotoev, msg);
159                 IRCv3::WriteNeighborsWithCap(user, awayevent, joinhook.awaycap);
160         }
161
162         void OnUserBack(User* user) CXX11_OVERRIDE
163         {
164                 if (!joinhook.awaycap.IsActive())
165                         return;
166
167                 // Back from away: n!u@h AWAY
168                 AwayMessage msg(user);
169                 ClientProtocol::Event awayevent(joinhook.awayprotoev, msg);
170                 IRCv3::WriteNeighborsWithCap(user, awayevent, joinhook.awaycap);
171         }
172
173         Version GetVersion() CXX11_OVERRIDE
174         {
175                 return Version("Provides support for extended-join, away-notify and account-notify CAP capabilities", VF_VENDOR);
176         }
177 };
178
179 MODULE_INIT(ModuleIRCv3)