anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
bots.cpp (6471B)
1 /* 2 * 3 * (C) 2008-2011 Robin Burchell <w00t@inspircd.org> 4 * (C) 2008-2022 Anope Team <team@anope.org> 5 * 6 * Please read COPYING and README for further details. 7 */ 8 9 #include "services.h" 10 #include "anope.h" 11 #include "bots.h" 12 #include "servers.h" 13 #include "protocol.h" 14 #include "xline.h" 15 #include "regchannel.h" 16 #include "channels.h" 17 #include "config.h" 18 #include "language.h" 19 #include "serialize.h" 20 21 Serialize::Checker<botinfo_map> BotListByNick("BotInfo"), BotListByUID("BotInfo"); 22 23 BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const Anope::string &nhost, const Anope::string &nreal, const Anope::string &bmodes) : User(nnick, nuser, nhost, "", "", Me, nreal, Anope::CurTime, "", IRCD ? IRCD->UID_Retrieve() : "", NULL), Serializable("BotInfo"), channels("ChannelInfo"), botmodes(bmodes) 24 { 25 this->lastmsg = this->created = Anope::CurTime; 26 this->introduced = false; 27 this->oper_only = this->conf = false; 28 29 (*BotListByNick)[this->nick] = this; 30 if (!this->uid.empty()) 31 (*BotListByUID)[this->uid] = this; 32 33 FOREACH_MOD(OnCreateBot, (this)); 34 35 // If we're synchronised with the uplink already, send the bot. 36 if (Me && Me->IsSynced()) 37 { 38 Anope::string tmodes = !this->botmodes.empty() ? ("+" + this->botmodes) : IRCD->DefaultPseudoclientModes; 39 if (!tmodes.empty()) 40 this->SetModesInternal(this, tmodes.c_str()); 41 42 XLine x(this->nick, "Reserved for services"); 43 IRCD->SendSQLine(NULL, &x); 44 IRCD->SendClientIntroduction(this); 45 this->introduced = true; 46 } 47 } 48 49 BotInfo::~BotInfo() 50 { 51 UnsetExtensibles(); 52 53 FOREACH_MOD(OnDelBot, (this)); 54 55 // If we're synchronised with the uplink already, send the bot. 56 if (Me && Me->IsSynced()) 57 { 58 IRCD->SendQuit(this, ""); 59 FOREACH_MOD(OnUserQuit, (this, "")); 60 this->introduced = false; 61 XLine x(this->nick); 62 IRCD->SendSQLineDel(&x); 63 } 64 65 for (std::set<ChannelInfo *>::iterator it = this->channels->begin(), it_end = this->channels->end(); it != it_end;) 66 { 67 ChannelInfo *ci = *it++; 68 this->UnAssign(NULL, ci); 69 } 70 71 BotListByNick->erase(this->nick); 72 if (!this->uid.empty()) 73 BotListByUID->erase(this->uid); 74 } 75 76 void BotInfo::Serialize(Serialize::Data &data) const 77 { 78 data["nick"] << this->nick; 79 data["user"] << this->ident; 80 data["host"] << this->host; 81 data["realname"] << this->realname; 82 data["created"] << this->created; 83 data["oper_only"] << this->oper_only; 84 85 Extensible::ExtensibleSerialize(this, this, data); 86 } 87 88 Serializable* BotInfo::Unserialize(Serializable *obj, Serialize::Data &data) 89 { 90 Anope::string nick, user, host, realname, flags; 91 92 data["nick"] >> nick; 93 data["user"] >> user; 94 data["host"] >> host; 95 data["realname"] >> realname; 96 97 BotInfo *bi; 98 if (obj) 99 bi = anope_dynamic_static_cast<BotInfo *>(obj); 100 else if (!(bi = BotInfo::Find(nick, true))) 101 bi = new BotInfo(nick, user, host, realname); 102 103 data["created"] >> bi->created; 104 data["oper_only"] >> bi->oper_only; 105 106 Extensible::ExtensibleUnserialize(bi, bi, data); 107 108 return bi; 109 } 110 111 void BotInfo::GenerateUID() 112 { 113 if (this->introduced) 114 throw CoreException("Changing bot UID when it is introduced?"); 115 116 if (!this->uid.empty()) 117 { 118 BotListByUID->erase(this->uid); 119 UserListByUID.erase(this->uid); 120 } 121 122 this->uid = IRCD->UID_Retrieve(); 123 (*BotListByUID)[this->uid] = this; 124 UserListByUID[this->uid] = this; 125 } 126 127 void BotInfo::OnKill() 128 { 129 this->introduced = false; 130 this->GenerateUID(); 131 IRCD->SendClientIntroduction(this); 132 this->introduced = true; 133 134 for (User::ChanUserList::const_iterator cit = this->chans.begin(), cit_end = this->chans.end(); cit != cit_end; ++cit) 135 IRCD->SendJoin(this, cit->second->chan, &cit->second->status); 136 } 137 138 void BotInfo::SetNewNick(const Anope::string &newnick) 139 { 140 UserListByNick.erase(this->nick); 141 BotListByNick->erase(this->nick); 142 143 this->nick = newnick; 144 145 UserListByNick[this->nick] = this; 146 (*BotListByNick)[this->nick] = this; 147 } 148 149 const std::set<ChannelInfo *> &BotInfo::GetChannels() const 150 { 151 return this->channels; 152 } 153 154 void BotInfo::Assign(User *u, ChannelInfo *ci) 155 { 156 EventReturn MOD_RESULT; 157 FOREACH_RESULT(OnPreBotAssign, MOD_RESULT, (u, ci, this)); 158 if (MOD_RESULT == EVENT_STOP) 159 return; 160 161 if (ci->bi) 162 ci->bi->UnAssign(u, ci); 163 164 ci->bi = this; 165 this->channels->insert(ci); 166 167 FOREACH_MOD(OnBotAssign, (u, ci, this)); 168 } 169 170 void BotInfo::UnAssign(User *u, ChannelInfo *ci) 171 { 172 EventReturn MOD_RESULT; 173 FOREACH_RESULT(OnBotUnAssign, MOD_RESULT, (u, ci)); 174 if (MOD_RESULT == EVENT_STOP) 175 return; 176 177 if (ci->c && ci->c->FindUser(ci->bi)) 178 { 179 if (u) 180 ci->bi->Part(ci->c, "UNASSIGN from " + u->nick); 181 else 182 ci->bi->Part(ci->c); 183 } 184 185 ci->bi = NULL; 186 this->channels->erase(ci); 187 } 188 189 unsigned BotInfo::GetChannelCount() const 190 { 191 return this->channels->size(); 192 } 193 194 void BotInfo::Join(Channel *c, ChannelStatus *status) 195 { 196 if (c->FindUser(this) != NULL) 197 return; 198 199 c->JoinUser(this, status); 200 if (IRCD) 201 IRCD->SendJoin(this, c, status); 202 203 FOREACH_MOD(OnJoinChannel, (this, c)); 204 } 205 206 void BotInfo::Join(const Anope::string &chname, ChannelStatus *status) 207 { 208 bool c; 209 return this->Join(Channel::FindOrCreate(chname, c), status); 210 } 211 212 void BotInfo::Part(Channel *c, const Anope::string &reason) 213 { 214 if (c->FindUser(this) == NULL) 215 return; 216 217 FOREACH_MOD(OnPrePartChannel, (this, c)); 218 219 IRCD->SendPart(this, c, "%s", !reason.empty() ? reason.c_str() : ""); 220 221 c->DeleteUser(this); 222 223 FOREACH_MOD(OnPartChannel, (this, c, c->name, reason)); 224 } 225 226 void BotInfo::OnMessage(User *u, const Anope::string &message) 227 { 228 if (this->commands.empty()) 229 return; 230 231 CommandSource source(u->nick, u, u->Account(), u, this); 232 Command::Run(source, message); 233 } 234 235 CommandInfo& BotInfo::SetCommand(const Anope::string &cname, const Anope::string &sname, const Anope::string &permission) 236 { 237 CommandInfo ci; 238 ci.name = sname; 239 ci.permission = permission; 240 this->commands[cname] = ci; 241 return this->commands[cname]; 242 } 243 244 CommandInfo *BotInfo::GetCommand(const Anope::string &cname) 245 { 246 CommandInfo::map::iterator it = this->commands.find(cname); 247 if (it != this->commands.end()) 248 return &it->second; 249 return NULL; 250 } 251 252 BotInfo* BotInfo::Find(const Anope::string &nick, bool nick_only) 253 { 254 if (!nick_only && IRCD != NULL && IRCD->RequiresID) 255 { 256 botinfo_map::iterator it = BotListByUID->find(nick); 257 if (it != BotListByUID->end()) 258 { 259 BotInfo *bi = it->second; 260 bi->QueueUpdate(); 261 return bi; 262 } 263 264 if (IRCD->AmbiguousID) 265 return NULL; 266 } 267 268 botinfo_map::iterator it = BotListByNick->find(nick); 269 if (it != BotListByNick->end()) 270 { 271 BotInfo *bi = it->second; 272 bi->QueueUpdate(); 273 return bi; 274 } 275 276 return NULL; 277 }