2 * InspIRCd -- Internet Relay Chat Daemon
4 * Copyright (C) 2013 Attila Molnar <attilamolnar@hush.com>
5 * Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
7 * This file is part of InspIRCd. InspIRCd is free software: you can
8 * redistribute it and/or modify it under the terms of the GNU General Public
9 * License as published by the Free Software Foundation, version 2.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "modules/cap.h"
24 class ModuleHostCycle : public Module
26 Cap::Reference chghostcap;
27 const std::string quitmsghost;
28 const std::string quitmsgident;
30 /** Send fake quit/join/mode messages for host or ident cycle.
32 void DoHostCycle(User* user, const std::string& newident, const std::string& newhost, const std::string& reason)
34 // The user has the original ident/host at the time this function is called
35 ClientProtocol::Messages::Quit quitmsg(user, reason);
36 ClientProtocol::Event quitevent(ServerInstance->GetRFCEvents().quit, quitmsg);
38 already_sent_t silent_id = ServerInstance->Users.NextAlreadySentId();
39 already_sent_t seen_id = ServerInstance->Users.NextAlreadySentId();
41 IncludeChanList include_chans(user->chans.begin(), user->chans.end());
42 std::map<User*,bool> exceptions;
44 FOREACH_MOD(OnBuildNeighborList, (user, include_chans, exceptions));
46 // Users shouldn't see themselves quitting when host cycling
47 exceptions.erase(user);
48 for (std::map<User*,bool>::iterator i = exceptions.begin(); i != exceptions.end(); ++i)
50 LocalUser* u = IS_LOCAL(i->first);
51 if ((u) && (!u->quitting) && (!chghostcap.get(u)))
55 u->already_sent = seen_id;
60 u->already_sent = silent_id;
65 std::string newfullhost = user->nick + "!" + newident + "@" + newhost;
67 for (IncludeChanList::const_iterator i = include_chans.begin(); i != include_chans.end(); ++i)
69 Membership* memb = *i;
70 Channel* c = memb->chan;
72 ClientProtocol::Events::Join joinevent(memb, newfullhost);
74 const Channel::MemberMap& ulist = c->GetUsers();
75 for (Channel::MemberMap::const_iterator j = ulist.begin(); j != ulist.end(); ++j)
77 LocalUser* u = IS_LOCAL(j->first);
78 if (u == NULL || u == user)
80 if (u->already_sent == silent_id)
82 if (chghostcap.get(u))
85 if (u->already_sent != seen_id)
88 u->already_sent = seen_id;
98 : chghostcap(this, "chghost")
99 , quitmsghost("Changing host")
100 , quitmsgident("Changing ident")
104 void OnChangeIdent(User* user, const std::string& newident) CXX11_OVERRIDE
106 DoHostCycle(user, newident, user->GetDisplayedHost(), quitmsgident);
109 void OnChangeHost(User* user, const std::string& newhost) CXX11_OVERRIDE
111 DoHostCycle(user, user->ident, newhost, quitmsghost);
114 Version GetVersion() CXX11_OVERRIDE
116 return Version("Cycles users in all their channels when their host or ident changes", VF_VENDOR);
120 MODULE_INIT(ModuleHostCycle)