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 }