void OnUserLogin(User *u) override { ServiceBot *NickServ = Config->GetClient("NickServ"); if (!NickServ) return; std::vector<AutoJoin *> channels = u->Account()->GetRefs<AutoJoin *>(); if (channels.empty()) return; /* Set +r now, so we can ajoin users into +R channels */ ModeManager::ProcessModes(); for (AutoJoin *entry : channels) { Channel *c = Channel::Find(entry->GetChannel()); ChanServ::Channel *ci; if (c) ci = c->ci; else ci = ChanServ::Find(entry->GetChannel()); bool need_invite = false; Anope::string key = entry->GetKey(); ChanServ::AccessGroup u_access; if (ci != NULL) { if (ci->HasFieldS("CS_SUSPENDED")) continue; u_access = ci->AccessFor(u); } if (c != NULL) { if (c->FindUser(u) != NULL) continue; else if (c->HasMode("OPERONLY") && !u->HasMode("OPER")) continue; else if (c->HasMode("ADMINONLY") && !u->HasMode("ADMIN")) continue; else if (c->HasMode("SSL") && !(u->HasMode("SSL") || u->HasExtOK("ssl"))) continue; else if (c->MatchesList(u, "BAN") == true && c->MatchesList(u, "EXCEPT") == false) need_invite = true; else if (c->HasMode("INVITE") && c->MatchesList(u, "INVITEOVERRIDE") == false) need_invite = true; if (c->HasMode("KEY")) { Anope::string k; if (c->GetParam("KEY", k)) { if (u_access.HasPriv("GETKEY")) key = k; else if (key != k) need_invite = true; } } if (c->HasMode("LIMIT")) { Anope::string l; if (c->GetParam("LIMIT", l)) { try { unsigned limit = convertTo<unsigned>(l); if (c->users.size() >= limit) need_invite = true; } catch (const ConvertException &) { } } } } if (need_invite && c != NULL) { if (!u_access.HasPriv("INVITE")) continue; IRCD->SendInvite(NickServ, c, u); } IRCD->SendSVSJoin(NickServ, u, entry->GetChannel(), key); } }
void DoAdd(CommandSource &source, NickServ::Account *nc, const Anope::string &chans, const Anope::string &keys) { std::vector<AutoJoin *> channels = nc->GetRefs<AutoJoin *>(); Anope::string addedchans; Anope::string alreadyadded; Anope::string invalidkey; commasepstream ksep(keys, true); commasepstream csep(chans); for (Anope::string chan, key; csep.GetToken(chan);) { ksep.GetToken(key); unsigned i = 0; for (; i < channels.size(); ++i) if (channels[i]->GetChannel().equals_ci(chan)) break; if (channels.size() >= Config->GetModule(this->GetOwner())->Get<unsigned>("ajoinmax")) { source.Reply(_("Sorry, the maximum of \002{0}\002 auto join entries has been reached."), Config->GetModule(this->GetOwner())->Get<unsigned>("ajoinmax")); return; } if (i != channels.size()) alreadyadded += chan + ", "; else if (IRCD->IsChannelValid(chan) == false) source.Reply(_("\002{0}\002 isn't a valid channel."), chan); else { Channel *c = Channel::Find(chan); Anope::string k; if (c && c->GetParam("KEY", k) && key != k) { invalidkey += chan + ", "; continue; } AutoJoin *entry = Serialize::New<AutoJoin *>(); entry->SetOwner(nc); entry->SetChannel(chan); entry->SetKey(key); addedchans += chan + ", "; } } if (!alreadyadded.empty()) { alreadyadded = alreadyadded.substr(0, alreadyadded.length() - 2); source.Reply(_("\002{0}\002 is already on the auto join list of \002{1}\002."), alreadyadded, nc->GetDisplay()); } if (!invalidkey.empty()) { invalidkey = invalidkey.substr(0, invalidkey.length() - 2); source.Reply(_("\002{0}\002 had an invalid key specified, and was ignored."), invalidkey); } if (addedchans.empty()) return; addedchans = addedchans.substr(0, addedchans.length() - 2); Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to ADD channel " << addedchans << " to " << nc->GetDisplay(); source.Reply(_("\002{0}\002 added to the auto join list of \002{1}\002."), addedchans, nc->GetDisplay()); }