anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
ngircd.cpp (21128B)
1 /* ngIRCd Protocol module for Anope IRC Services 2 * 3 * (C) 2011-2012, 2014 Alexander Barton <alex@barton.de> 4 * (C) 2011-2022 Anope Team <team@anope.org> 5 * 6 * Please read COPYING and README for further details. 7 * 8 * Based on the original code of Epona by Lara. 9 * Based on the original code of Services by Andy Church. 10 */ 11 12 #include "module.h" 13 14 class ngIRCdProto : public IRCDProto 15 { 16 void SendSVSKillInternal(const MessageSource &source, User *user, const Anope::string &buf) anope_override 17 { 18 IRCDProto::SendSVSKillInternal(source, user, buf); 19 user->KillInternal(source, buf); 20 } 21 22 public: 23 ngIRCdProto(Module *creator) : IRCDProto(creator, "ngIRCd") 24 { 25 DefaultPseudoclientModes = "+oi"; 26 CanCertFP = true; 27 CanSVSNick = true; 28 CanSetVHost = true; 29 CanSetVIdent = true; 30 MaxModes = 5; 31 } 32 33 void SendAkill(User *u, XLine *x) anope_override 34 { 35 // Calculate the time left before this would expire, capping it at 2 days 36 time_t timeleft = x->expires - Anope::CurTime; 37 if (timeleft > 172800 || !x->expires) 38 timeleft = 172800; 39 UplinkSocket::Message(Me) << "GLINE " << x->mask << " " << timeleft << " :" << x->GetReason() << " (" << x->by << ")"; 40 } 41 42 void SendAkillDel(const XLine *x) anope_override 43 { 44 UplinkSocket::Message(Me) << "GLINE " << x->mask; 45 } 46 47 void SendChannel(Channel *c) anope_override 48 { 49 UplinkSocket::Message(Me) << "CHANINFO " << c->name << " +" << c->GetModes(true, true); 50 } 51 52 // Received: :dev.anope.de NICK DukeP 1 ~DukePyro p57ABF9C9.dip.t-dialin.net 1 +i :DukePyrolator 53 void SendClientIntroduction(User *u) anope_override 54 { 55 Anope::string modes = "+" + u->GetModes(); 56 UplinkSocket::Message(Me) << "NICK " << u->nick << " 1 " << u->GetIdent() << " " << u->host << " 1 " << modes << " :" << u->realname; 57 } 58 59 void SendConnect() anope_override 60 { 61 UplinkSocket::Message() << "PASS " << Config->Uplinks[Anope::CurrentUplink].password << " 0210-IRC+ Anope|" << Anope::VersionShort() << ":CLHMSo P"; 62 /* Make myself known to myself in the serverlist */ 63 SendServer(Me); 64 /* finish the enhanced server handshake and register the connection */ 65 this->SendNumeric(376, "*", ":End of MOTD command"); 66 } 67 68 void SendForceNickChange(User *u, const Anope::string &newnick, time_t when) anope_override 69 { 70 UplinkSocket::Message(Me) << "SVSNICK " << u->nick << " " << newnick; 71 } 72 73 void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override 74 { 75 UplinkSocket::Message(bi) << "NOTICE $" << dest->GetName() << " :" << msg; 76 } 77 78 void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override 79 { 80 UplinkSocket::Message(bi) << "PRIVMSG $" << dest->GetName() << " :" << msg; 81 } 82 83 void SendGlobopsInternal(const MessageSource &source, const Anope::string &buf) anope_override 84 { 85 UplinkSocket::Message(source) << "WALLOPS :" << buf; 86 } 87 88 void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override 89 { 90 UplinkSocket::Message(user) << "JOIN " << c->name; 91 if (status) 92 { 93 /* First save the channel status incase uc->Status == status */ 94 ChannelStatus cs = *status; 95 /* If the user is internally on the channel with flags, kill them so that 96 * the stacker will allow this. 97 */ 98 ChanUserContainer *uc = c->FindUser(user); 99 if (uc != NULL) 100 uc->status.Clear(); 101 102 BotInfo *setter = BotInfo::Find(user->GetUID()); 103 for (size_t i = 0; i < cs.Modes().length(); ++i) 104 c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), user->GetUID(), false); 105 106 if (uc != NULL) 107 uc->status = cs; 108 } 109 } 110 111 void SendLogin(User *u, NickAlias *na) anope_override 112 { 113 UplinkSocket::Message(Me) << "METADATA " << u->GetUID() << " accountname :" << na->nc->display; 114 } 115 116 void SendLogout(User *u) anope_override 117 { 118 UplinkSocket::Message(Me) << "METADATA " << u->GetUID() << " accountname :"; 119 } 120 121 /* SERVER name hop descript */ 122 void SendServer(const Server *server) anope_override 123 { 124 UplinkSocket::Message() << "SERVER " << server->GetName() << " " << server->GetHops() << " :" << server->GetDescription(); 125 } 126 127 void SendVhost(User *u, const Anope::string &vIdent, const Anope::string &vhost) anope_override 128 { 129 if (!vIdent.empty()) 130 UplinkSocket::Message(Me) << "METADATA " << u->nick << " user :" << vIdent; 131 132 UplinkSocket::Message(Me) << "METADATA " << u->nick << " cloakhost :" << vhost; 133 if (!u->HasMode("CLOAK")) 134 { 135 u->SetMode(Config->GetClient("HostServ"), "CLOAK"); 136 ModeManager::ProcessModes(); 137 } 138 } 139 140 void SendVhostDel(User *u) anope_override 141 { 142 this->SendVhost(u, u->GetIdent(), ""); 143 } 144 145 Anope::string Format(const Anope::string &source, const Anope::string &message) anope_override 146 { 147 return IRCDProto::Format(source.empty() ? Me->GetSID() : source, message); 148 } 149 }; 150 151 struct IRCDMessage005 : IRCDMessage 152 { 153 IRCDMessage005(Module *creator) : IRCDMessage(creator, "005", 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 154 155 // Please see <http://www.irc.org/tech_docs/005.html> for details. 156 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 157 { 158 size_t pos; 159 Anope::string parameter, data; 160 for (unsigned i = 0, end = params.size(); i < end; ++i) 161 { 162 pos = params[i].find('='); 163 if (pos != Anope::string::npos) 164 { 165 parameter = params[i].substr(0, pos); 166 data = params[i].substr(pos+1, params[i].length()); 167 if (parameter == "MODES") 168 { 169 unsigned maxmodes = convertTo<unsigned>(data); 170 IRCD->MaxModes = maxmodes; 171 } 172 else if (parameter == "NICKLEN") 173 { 174 unsigned newlen = convertTo<unsigned>(data), len = Config->GetBlock("networkinfo")->Get<unsigned>("nicklen"); 175 if (len != newlen) 176 { 177 Log() << "Warning: NICKLEN is " << newlen << " but networkinfo:nicklen is " << len; 178 } 179 } 180 } 181 } 182 } 183 }; 184 185 struct IRCDMessage376 : IRCDMessage 186 { 187 IRCDMessage376(Module *creator) : IRCDMessage(creator, "376", 2) { } 188 189 /* 190 * :ngircd.dev.anope.de 376 services.anope.de :End of MOTD command 191 * 192 * we do nothing here, this function exists only to 193 * avoid the "unknown message from server" message. 194 * 195 */ 196 197 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 198 { 199 } 200 }; 201 202 struct IRCDMessageChaninfo : IRCDMessage 203 { 204 IRCDMessageChaninfo(Module *creator) : IRCDMessage(creator, "CHANINFO", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } 205 206 /* 207 * CHANINFO is used by servers to inform each other about a channel: its 208 * modes, channel key, user limits and its topic. The parameter combination 209 * <key> and <limit> is optional, as well as the <topic> parameter, so that 210 * there are three possible forms of this command: 211 * 212 * CHANINFO <chan> +<modes> 213 * CHANINFO <chan> +<modes> :<topic> 214 * CHANINFO <chan> +<modes> <key> <limit> :<topic> 215 * 216 * The parameter <key> must be ignored if a channel has no key (the parameter 217 * <modes> doesn't list the "k" channel mode). In this case <key> should 218 * contain "*" because the parameter <key> is required by the CHANINFO syntax 219 * and therefore can't be omitted. The parameter <limit> must be ignored when 220 * a channel has no user limit (the parameter <modes> doesn't list the "l" 221 * channel mode). In this case <limit> should be "0". 222 */ 223 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 224 { 225 bool created; 226 Channel *c = Channel::FindOrCreate(params[0], created); 227 228 Anope::string modes = params[1]; 229 230 if (params.size() == 3) 231 { 232 c->ChangeTopicInternal(NULL, source.GetName(), params[2], Anope::CurTime); 233 } 234 else if (params.size() == 5) 235 { 236 for (size_t i = 0, end = params[1].length(); i < end; ++i) 237 { 238 switch(params[1][i]) 239 { 240 case 'k': 241 modes += " " + params[2]; 242 continue; 243 case 'l': 244 modes += " " + params[3]; 245 continue; 246 } 247 } 248 c->ChangeTopicInternal(NULL, source.GetName(), params[4], Anope::CurTime); 249 } 250 251 c->SetModesInternal(source, modes); 252 } 253 }; 254 255 struct IRCDMessageJoin : Message::Join 256 { 257 IRCDMessageJoin(Module *creator) : Message::Join(creator, "JOIN") { SetFlag(IRCDMESSAGE_REQUIRE_USER); } 258 259 /* 260 * <@po||ux> DukeP: RFC 2813, 4.2.1: the JOIN command on server-server links 261 * separates the modes ("o") with ASCII 7, not space. And you can't see ASCII 7. 262 * 263 * if a user joins a new channel, the ircd sends <channelname>\7<umode> 264 */ 265 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 266 { 267 User *user = source.GetUser(); 268 size_t pos = params[0].find('\7'); 269 Anope::string channel, modes; 270 271 if (pos != Anope::string::npos) 272 { 273 channel = params[0].substr(0, pos); 274 modes = '+' + params[0].substr(pos+1, params[0].length()) + " " + user->nick; 275 } 276 else 277 { 278 channel = params[0]; 279 } 280 281 std::vector<Anope::string> new_params; 282 new_params.push_back(channel); 283 284 Message::Join::Run(source, new_params); 285 286 if (!modes.empty()) 287 { 288 Channel *c = Channel::Find(channel); 289 if (c) 290 c->SetModesInternal(source, modes); 291 } 292 } 293 }; 294 295 struct IRCDMessageMetadata : IRCDMessage 296 { 297 IRCDMessageMetadata(Module *creator) : IRCDMessage(creator, "METADATA", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } 298 299 /* 300 * Received: :ngircd.dev.anope.de METADATA DukePyrolator host :anope-e2ee5c7d 301 * 302 * params[0] = nick of the user 303 * params[1] = command 304 * params[2] = data 305 * 306 * following commands are supported: 307 * - "accountname": the account name of a client (can't be empty) 308 * - "certfp": the certificate fingerprint of a client (can't be empty) 309 * - "cloakhost" : the cloaked hostname of a client 310 * - "host": the hostname of a client (can't be empty) 311 * - "info": info text ("real name") of a client 312 * - "user": the user name (ident) of a client (can't be empty) 313 */ 314 315 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 316 { 317 User *u = User::Find(params[0]); 318 if (!u) 319 { 320 Log(LOG_DEBUG) << "received METADATA for nonexistent user " << params[0]; 321 return; 322 } 323 if (params[1].equals_cs("accountname")) 324 { 325 NickCore *nc = NickCore::Find(params[2]); 326 if (nc) 327 u->Login(nc); 328 } 329 else if (params[1].equals_cs("certfp")) 330 { 331 u->fingerprint = params[2]; 332 FOREACH_MOD(OnFingerprint, (u)); 333 } 334 else if (params[1].equals_cs("cloakhost")) 335 { 336 if (!params[2].empty()) 337 u->SetDisplayedHost(params[2]); 338 } 339 else if (params[1].equals_cs("host")) 340 { 341 u->SetCloakedHost(params[2]); 342 } 343 else if (params[1].equals_cs("info")) 344 { 345 u->SetRealname(params[2]); 346 } 347 else if (params[1].equals_cs("user")) 348 { 349 u->SetVIdent(params[2]); 350 } 351 } 352 }; 353 354 struct IRCDMessageMode : IRCDMessage 355 { 356 IRCDMessageMode(Module *creator) : IRCDMessage(creator, "MODE", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 357 358 /* 359 * Received: :DukeP MODE #anope +b *!*@*.aol.com 360 * Received: :DukeP MODE #anope +h DukeP 361 * params[0] = channel or nick 362 * params[1] = modes 363 * params[n] = parameters 364 */ 365 366 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 367 { 368 Anope::string modes = params[1]; 369 370 for (size_t i = 2; i < params.size(); ++i) 371 modes += " " + params[i]; 372 373 if (IRCD->IsChannelValid(params[0])) 374 { 375 Channel *c = Channel::Find(params[0]); 376 377 if (c) 378 c->SetModesInternal(source, modes); 379 } 380 else 381 { 382 User *u = User::Find(params[0]); 383 384 if (u) 385 u->SetModesInternal(source, "%s", params[1].c_str()); 386 } 387 } 388 }; 389 390 struct IRCDMessageNick : IRCDMessage 391 { 392 IRCDMessageNick(Module *creator) : IRCDMessage(creator, "NICK", 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 393 394 /* 395 * NICK - NEW 396 * Received: :dev.anope.de NICK DukeP_ 1 ~DukePyro ip-2-201-236-154.web.vodafone.de 1 + :DukePyrolator 397 * Parameters: <nickname> <hopcount> <username> <host> <servertoken> <umode> :<realname> 398 * source = server 399 * params[0] = nick 400 * params[1] = hopcount 401 * params[2] = username/ident 402 * params[3] = host 403 * params[4] = servertoken 404 * params[5] = modes 405 * params[6] = info 406 * 407 * NICK - change 408 * Received: :DukeP_ NICK :test2 409 * source = oldnick 410 * params[0] = newnick 411 * 412 */ 413 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 414 { 415 if (params.size() == 1) 416 { 417 User *u = source.GetUser(); 418 419 // we have a nickchange 420 if (u) 421 u->ChangeNick(params[0]); 422 } 423 else if (params.size() == 7) 424 { 425 // a new user is connecting to the network 426 Server *s = Server::Find(params[4]); 427 if (s == NULL) 428 { 429 Log(LOG_DEBUG) << "User " << params[0] << " introduced from nonexistent server " << params[4] << "?"; 430 return; 431 } 432 User::OnIntroduce(params[0], params[2], params[3], "", "", s, params[6], Anope::CurTime, params[5], "", NULL); 433 Log(LOG_DEBUG) << "Registered nick \"" << params[0] << "\" on server " << s->GetName() << "."; 434 } 435 else 436 { 437 Log(LOG_DEBUG) << "Received NICK with invalid number of parameters. source = " << source.GetName() << "params[0] = " << params[0] << "params.size() = " << params.size(); 438 } 439 } 440 }; 441 442 struct IRCDMessageNJoin : IRCDMessage 443 { 444 IRCDMessageNJoin(Module *creator) : IRCDMessage(creator, "NJOIN",2) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }; 445 446 /* 447 * RFC 2813, 4.2.2: Njoin Message: 448 * The NJOIN message is used between servers only. 449 * It is used when two servers connect to each other to exchange 450 * the list of channel members for each channel. 451 * 452 * Even though the same function can be performed by using a succession 453 * of JOIN, this message SHOULD be used instead as it is more efficient. 454 * 455 * Received: :dev.anope.de NJOIN #test :DukeP2,@DukeP,%test,+test2 456 */ 457 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 458 { 459 std::list<Message::Join::SJoinUser> users; 460 461 commasepstream sep(params[1]); 462 Anope::string buf; 463 while (sep.GetToken(buf)) 464 { 465 466 Message::Join::SJoinUser sju; 467 468 /* Get prefixes from the nick */ 469 for (char ch; (ch = ModeManager::GetStatusChar(buf[0]));) 470 { 471 buf.erase(buf.begin()); 472 sju.first.AddMode(ch); 473 } 474 475 sju.second = User::Find(buf); 476 if (!sju.second) 477 { 478 Log(LOG_DEBUG) << "NJOIN for nonexistent user " << buf << " on " << params[0]; 479 continue; 480 } 481 users.push_back(sju); 482 } 483 484 Message::Join::SJoin(source, params[0], 0, "", users); 485 } 486 }; 487 488 struct IRCDMessagePong : IRCDMessage 489 { 490 IRCDMessagePong(Module *creator) : IRCDMessage(creator, "PONG", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } 491 492 /* 493 * ngIRCd does not send an EOB, so we send a PING immediately 494 * when receiving a new server and then finish sync once we 495 * get a pong back from that server. 496 */ 497 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 498 { 499 if (!source.GetServer()->IsSynced()) 500 source.GetServer()->Sync(false); 501 } 502 }; 503 504 struct IRCDMessageServer : IRCDMessage 505 { 506 IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 507 508 /* 509 * New directly linked server: 510 * 511 * SERVER tolsun.oulu.fi 1 :Experimental server 512 * New server tolsun.oulu.fi introducing itself 513 * and attempting to register. 514 * 515 * params[0] = servername 516 * params[1] = hop count 517 * params[2] = server description 518 * 519 * New remote server in the network: 520 * 521 * :tolsun.oulu.fi SERVER csd.bu.edu 5 34 :BU Central Server 522 * Server tolsun.oulu.fi is our uplink for csd.bu.edu 523 * which is 5 hops away. The token "34" will be used 524 * by tolsun.oulu.fi when introducing new users or 525 * services connected to csd.bu.edu. 526 * 527 * params[0] = servername 528 * params[1] = hop count 529 * params[2] = server numeric 530 * params[3] = server description 531 */ 532 533 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 534 { 535 if (params.size() == 3) 536 { 537 // our uplink is introducing itself 538 new Server(Me, params[0], 1, params[2], "1"); 539 } 540 else 541 { 542 // our uplink is introducing a new server 543 unsigned int hops = params[1].is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0; 544 new Server(source.GetServer(), params[0], hops, params[3], params[2]); 545 } 546 /* 547 * ngIRCd does not send an EOB, so we send a PING immediately 548 * when receiving a new server and then finish sync once we 549 * get a pong back from that server. 550 */ 551 IRCD->SendPing(Me->GetName(), params[0]); 552 } 553 }; 554 555 struct IRCDMessageTopic : IRCDMessage 556 { 557 IRCDMessageTopic(Module *creator) : IRCDMessage(creator, "TOPIC", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 558 559 // Received: :DukeP TOPIC #anope :test 560 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 561 { 562 Channel *c = Channel::Find(params[0]); 563 if (!c) 564 { 565 Log(LOG_DEBUG) << "TOPIC for nonexistent channel " << params[0]; 566 return; 567 } 568 c->ChangeTopicInternal(source.GetUser(), source.GetName(), params[1], Anope::CurTime); 569 } 570 }; 571 572 573 574 class ProtongIRCd : public Module 575 { 576 ngIRCdProto ircd_proto; 577 578 /* Core message handlers */ 579 Message::Capab message_capab; 580 Message::Error message_error; 581 Message::Invite message_invite; 582 Message::Kick message_kick; 583 Message::Kill message_kill; 584 Message::MOTD message_motd; 585 Message::Notice message_notice; 586 Message::Part message_part; 587 Message::Ping message_ping; 588 Message::Privmsg message_privmsg, message_squery; 589 Message::Quit message_quit; 590 Message::SQuit message_squit; 591 Message::Stats message_stats; 592 Message::Time message_time; 593 Message::Version message_version; 594 Message::Whois message_whois; 595 596 /* Our message handlers */ 597 IRCDMessage005 message_005; 598 IRCDMessage376 message_376; 599 IRCDMessageChaninfo message_chaninfo; 600 IRCDMessageJoin message_join; 601 IRCDMessageMetadata message_metadata; 602 IRCDMessageMode message_mode; 603 IRCDMessageNick message_nick; 604 IRCDMessageNJoin message_njoin; 605 IRCDMessagePong message_pong; 606 IRCDMessageServer message_server; 607 IRCDMessageTopic message_topic; 608 609 void AddModes() 610 { 611 /* Add user modes */ 612 ModeManager::AddUserMode(new UserMode("NOCTCP", 'b')); 613 ModeManager::AddUserMode(new UserMode("BOT", 'B')); 614 ModeManager::AddUserMode(new UserMode("COMMONCHANS", 'C')); 615 ModeManager::AddUserMode(new UserMode("INVIS", 'i')); 616 ModeManager::AddUserMode(new UserModeOperOnly("OPER", 'o')); 617 ModeManager::AddUserMode(new UserModeOperOnly("PROTECTED", 'q')); 618 ModeManager::AddUserMode(new UserModeOperOnly("RESTRICTED", 'r')); 619 ModeManager::AddUserMode(new UserModeNoone("REGISTERED", 'R')); 620 ModeManager::AddUserMode(new UserModeOperOnly("SNOMASK", 's')); 621 ModeManager::AddUserMode(new UserMode("WALLOPS", 'w')); 622 ModeManager::AddUserMode(new UserMode("CLOAK", 'x')); 623 624 /* Add modes for ban, exception, and invite lists */ 625 ModeManager::AddChannelMode(new ChannelModeList("BAN", 'b')); 626 ModeManager::AddChannelMode(new ChannelModeList("EXCEPT", 'e')); 627 ModeManager::AddChannelMode(new ChannelModeList("INVITEOVERRIDE", 'I')); 628 629 /* Add channel user modes */ 630 ModeManager::AddChannelMode(new ChannelModeStatus("VOICE", 'v', '+', 0)); 631 ModeManager::AddChannelMode(new ChannelModeStatus("HALFOP", 'h', '%', 1)); 632 ModeManager::AddChannelMode(new ChannelModeStatus("OP", 'o', '@', 2)); 633 ModeManager::AddChannelMode(new ChannelModeStatus("PROTECT", 'a', '&', 3)); 634 ModeManager::AddChannelMode(new ChannelModeStatus("OWNER", 'q', '~', 4)); 635 636 /* Add channel modes */ 637 ModeManager::AddChannelMode(new ChannelMode("INVITE", 'i')); 638 ModeManager::AddChannelMode(new ChannelModeKey('k')); 639 ModeManager::AddChannelMode(new ChannelModeParam("LIMIT", 'l', true)); 640 ModeManager::AddChannelMode(new ChannelMode("MODERATED", 'm')); 641 ModeManager::AddChannelMode(new ChannelMode("REGMODERATED", 'M')); 642 ModeManager::AddChannelMode(new ChannelMode("NOEXTERNAL", 'n')); 643 ModeManager::AddChannelMode(new ChannelMode("OPERONLY", 'O')); 644 ModeManager::AddChannelMode(new ChannelMode("PERM", 'P')); 645 ModeManager::AddChannelMode(new ChannelMode("NOKICK", 'Q')); 646 ModeManager::AddChannelMode(new ChannelModeNoone("REGISTERED", 'r')); 647 ModeManager::AddChannelMode(new ChannelMode("REGISTEREDONLY", 'R')); 648 ModeManager::AddChannelMode(new ChannelMode("SECRET", 's')); 649 ModeManager::AddChannelMode(new ChannelMode("TOPIC", 't')); 650 ModeManager::AddChannelMode(new ChannelMode("NOINVITE", 'V')); 651 ModeManager::AddChannelMode(new ChannelMode("SSL", 'z')); 652 } 653 654 public: 655 ProtongIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR), 656 ircd_proto(this), 657 message_capab(this), message_error(this), message_invite(this), message_kick(this), message_kill(this), 658 message_motd(this), message_notice(this), message_part(this), message_ping(this), message_privmsg(this), 659 message_squery(this, "SQUERY"), message_quit(this), message_squit(this), message_stats(this), message_time(this), 660 message_version(this), message_whois(this), 661 662 message_005(this), message_376(this), message_chaninfo(this), message_join(this), message_metadata(this), 663 message_mode(this), message_nick(this), message_njoin(this), message_pong(this), message_server(this), 664 message_topic(this) 665 { 666 667 Servers::Capab.insert("QS"); 668 669 this->AddModes(); 670 671 } 672 673 void OnUserNickChange(User *u, const Anope::string &) anope_override 674 { 675 u->RemoveMode(Config->GetClient("NickServ"), "REGISTERED"); 676 } 677 }; 678 679 MODULE_INIT(ProtongIRCd)