anope

- supernets anope source code & configuration
git clone git://git.acid.vegas/anope.git
Log | Files | Refs | Archive | README

cs_entrymsg.cpp (8676B)

      1 /* ChanServ core functions
      2  *
      3  * (C) 2003-2022 Anope Team
      4  * Contact us at 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 #include "modules/cs_entrymsg.h"
     14 
     15 struct EntryMsgImpl : EntryMsg, Serializable
     16 {
     17 	EntryMsgImpl() : Serializable("EntryMsg")
     18 	{
     19 	}
     20 
     21 	EntryMsgImpl(ChannelInfo *c, const Anope::string &cname, const Anope::string &cmessage, time_t ct = Anope::CurTime) : Serializable("EntryMsg")
     22 	{
     23 		this->chan = c->name;
     24 		this->creator = cname;
     25 		this->message = cmessage;
     26 		this->when = ct;
     27 	}
     28 
     29 	~EntryMsgImpl();
     30 
     31 	void Serialize(Serialize::Data &data) const anope_override
     32 	{
     33 		data["ci"] << this->chan;
     34 		data["creator"] << this->creator;
     35 		data["message"] << this->message;
     36 		data.SetType("when", Serialize::Data::DT_INT); data["when"] << this->when;
     37 	}
     38 
     39 	static Serializable* Unserialize(Serializable *obj, Serialize::Data &data);
     40 };
     41 
     42 struct EntryMessageListImpl : EntryMessageList
     43 {
     44 	EntryMessageListImpl(Extensible *) { }
     45 
     46 	EntryMsg* Create() anope_override
     47 	{
     48 		return new EntryMsgImpl();
     49 	}
     50 };
     51 
     52 EntryMsgImpl::~EntryMsgImpl()
     53 {
     54 	ChannelInfo *ci = ChannelInfo::Find(this->chan);
     55 	if (!ci)
     56 		return;
     57 
     58 	EntryMessageList *messages = ci->GetExt<EntryMessageList>("entrymsg");
     59 	if (!messages)
     60 		return;
     61 
     62 	std::vector<EntryMsg *>::iterator it = std::find((*messages)->begin(), (*messages)->end(), this);
     63 	if (it != (*messages)->end())
     64 		(*messages)->erase(it);
     65 }
     66 
     67 
     68 Serializable* EntryMsgImpl::Unserialize(Serializable *obj, Serialize::Data &data)
     69 {
     70 	Anope::string sci, screator, smessage;
     71 	time_t swhen;
     72 
     73 	data["ci"] >> sci;
     74 	data["creator"] >> screator;
     75 	data["message"] >> smessage;
     76 
     77 	ChannelInfo *ci = ChannelInfo::Find(sci);
     78 	if (!ci)
     79 		return NULL;
     80 
     81 	if (obj)
     82 	{
     83 		EntryMsgImpl *msg = anope_dynamic_static_cast<EntryMsgImpl *>(obj);
     84 		msg->chan = ci->name;
     85 		data["creator"] >> msg->creator;
     86 		data["message"] >> msg->message;
     87 		data["when"] >> msg->when;
     88 		return msg;
     89 	}
     90 
     91 	EntryMessageList *messages = ci->Require<EntryMessageList>("entrymsg");
     92 
     93 	data["when"] >> swhen;
     94 
     95 	EntryMsgImpl *m = new EntryMsgImpl(ci, screator, smessage, swhen);
     96 	(*messages)->push_back(m);
     97 	return m;
     98 }
     99 
    100 class CommandEntryMessage : public Command
    101 {
    102  private:
    103 	void DoList(CommandSource &source, ChannelInfo *ci)
    104 	{
    105 		EntryMessageList *messages = ci->Require<EntryMessageList>("entrymsg");
    106 
    107 		if ((*messages)->empty())
    108 		{
    109 			source.Reply(_("Entry message list for \002%s\002 is empty."), ci->name.c_str());
    110 			return;
    111 		}
    112 
    113 		source.Reply(_("Entry message list for \002%s\002:"), ci->name.c_str());
    114 
    115 		ListFormatter list(source.GetAccount());
    116 		list.AddColumn(_("Number")).AddColumn(_("Creator")).AddColumn(_("Created")).AddColumn(_("Message"));
    117 		for (unsigned i = 0; i < (*messages)->size(); ++i)
    118 		{
    119 			EntryMsg *msg = (*messages)->at(i);
    120 
    121 			ListFormatter::ListEntry entry;
    122 			entry["Number"] = stringify(i + 1);
    123 			entry["Creator"] = msg->creator;
    124 			entry["Created"] = Anope::strftime(msg->when, NULL, true);
    125 			entry["Message"] = msg->message;
    126 			list.AddEntry(entry);
    127 		}
    128 
    129 		std::vector<Anope::string> replies;
    130 		list.Process(replies);
    131 		for (unsigned i = 0; i < replies.size(); ++i)
    132 			source.Reply(replies[i]);
    133 
    134 		source.Reply(_("End of entry message list."));
    135 	}
    136 
    137 	void DoAdd(CommandSource &source, ChannelInfo *ci, const Anope::string &message)
    138 	{
    139 		EntryMessageList *messages = ci->Require<EntryMessageList>("entrymsg");
    140 
    141 		if ((*messages)->size() >= Config->GetModule(this->owner)->Get<unsigned>("maxentries"))
    142 			source.Reply(_("The entry message list for \002%s\002 is full."), ci->name.c_str());
    143 		else
    144 		{
    145 			(*messages)->push_back(new EntryMsgImpl(ci, source.GetNick(), message));
    146 			Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to add a message";
    147 			source.Reply(_("Entry message added to \002%s\002"), ci->name.c_str());
    148 		}
    149 	}
    150 
    151 	void DoDel(CommandSource &source, ChannelInfo *ci, const Anope::string &message)
    152 	{
    153 		EntryMessageList *messages = ci->Require<EntryMessageList>("entrymsg");
    154 
    155 		if (!message.is_pos_number_only())
    156 			source.Reply(("Entry message \002%s\002 not found on channel \002%s\002."), message.c_str(), ci->name.c_str());
    157 		else if ((*messages)->empty())
    158 			source.Reply(_("Entry message list for \002%s\002 is empty."), ci->name.c_str());
    159 		else
    160 		{
    161 			try
    162 			{
    163 				unsigned i = convertTo<unsigned>(message);
    164 				if (i > 0 && i <= (*messages)->size())
    165 				{
    166 					delete (*messages)->at(i - 1);
    167 					if ((*messages)->empty())
    168 						ci->Shrink<EntryMessageList>("entrymsg");
    169 					Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to remove a message";
    170 					source.Reply(_("Entry message \002%i\002 for \002%s\002 deleted."), i, ci->name.c_str());
    171 				}
    172 				else
    173 					throw ConvertException();
    174 			}
    175 			catch (const ConvertException &)
    176 			{
    177 				source.Reply(_("Entry message \002%s\002 not found on channel \002%s\002."), message.c_str(), ci->name.c_str());
    178 			}
    179 		}
    180 	}
    181 
    182 	void DoClear(CommandSource &source, ChannelInfo *ci)
    183 	{
    184 		ci->Shrink<EntryMessageList>("entrymsg");
    185 
    186 		Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to remove all messages";
    187 		source.Reply(_("Entry messages for \002%s\002 have been cleared."), ci->name.c_str());
    188 	}
    189 
    190  public:
    191 	CommandEntryMessage(Module *creator) : Command(creator, "chanserv/entrymsg", 2, 3)
    192 	{
    193 		this->SetDesc(_("Manage the channel's entry messages"));
    194 		this->SetSyntax(_("\037channel\037 ADD \037message\037"));
    195 		this->SetSyntax(_("\037channel\037 DEL \037num\037"));
    196 		this->SetSyntax(_("\037channel\037 LIST"));
    197 		this->SetSyntax(_("\037channel\037 CLEAR"));
    198 	}
    199 
    200 	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
    201 	{
    202 		ChannelInfo *ci = ChannelInfo::Find(params[0]);
    203 		if (ci == NULL)
    204 		{
    205 			source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
    206 			return;
    207 		}
    208 
    209 		if (Anope::ReadOnly && !params[1].equals_ci("LIST"))
    210 		{
    211 			source.Reply(READ_ONLY_MODE);
    212 			return;
    213 		}
    214 
    215 		if (!source.AccessFor(ci).HasPriv("SET") && !source.HasPriv("chanserv/administration"))
    216 		{
    217 			source.Reply(ACCESS_DENIED);
    218 			return;
    219 		}
    220 
    221 		if (params[1].equals_ci("LIST"))
    222 			this->DoList(source, ci);
    223 		else if (params[1].equals_ci("CLEAR"))
    224 			this->DoClear(source, ci);
    225 		else if (params.size() < 3)
    226 			this->OnSyntaxError(source, "");
    227 		else if (params[1].equals_ci("ADD"))
    228 			this->DoAdd(source, ci, params[2]);
    229 		else if (params[1].equals_ci("DEL"))
    230 			this->DoDel(source, ci, params[2]);
    231 		else
    232 			this->OnSyntaxError(source, "");
    233 	}
    234 
    235 	bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
    236 	{
    237 		this->SendSyntax(source);
    238 		source.Reply(" ");
    239 		source.Reply(_("Controls what messages will be sent to users when they join the channel."));
    240 		source.Reply(" ");
    241 		source.Reply(_("The \002ENTRYMSG ADD\002 command adds the given message to\n"
    242 				"the list of messages shown to users when they join\n"
    243 				"the channel."));
    244 		source.Reply(" ");
    245 		source.Reply(_("The \002ENTRYMSG DEL\002 command removes the specified message from\n"
    246 				"the list of messages shown to users when they join\n"
    247 				"the channel. You can remove a message by specifying its number\n"
    248 				"which you can get by listing the messages as explained below."));
    249 		source.Reply(" ");
    250 		source.Reply(_("The \002ENTRYMSG LIST\002 command displays a listing of messages\n"
    251 				"shown to users when they join the channel."));
    252 		source.Reply(" ");
    253 		source.Reply(_("The \002ENTRYMSG CLEAR\002 command clears all entries from\n"
    254 				"the list of messages shown to users when they join\n"
    255 				"the channel, effectively disabling entry messages."));
    256 		source.Reply(" ");
    257 		source.Reply(_("Adding, deleting, or clearing entry messages requires the\n"
    258 				"SET permission."));
    259 		return true;
    260 	}
    261 };
    262 
    263 class CSEntryMessage : public Module
    264 {
    265 	CommandEntryMessage commandentrymsg;
    266 	ExtensibleItem<EntryMessageListImpl> eml;
    267 	Serialize::Type entrymsg_type;
    268 
    269  public:
    270 	CSEntryMessage(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
    271 	commandentrymsg(this),
    272 	eml(this, "entrymsg"), entrymsg_type("EntryMsg", EntryMsgImpl::Unserialize)
    273 	{
    274 	}
    275 
    276 	void OnJoinChannel(User *u, Channel *c) anope_override
    277 	{
    278 		if (u && c && c->ci && u->server->IsSynced())
    279 		{
    280 			EntryMessageList *messages = c->ci->GetExt<EntryMessageList>("entrymsg");
    281 
    282 			if (messages != NULL)
    283 				for (unsigned i = 0; i < (*messages)->size(); ++i)
    284 					u->SendMessage(c->ci->WhoSends(), "[%s] %s", c->ci->name.c_str(), (*messages)->at(i)->message.c_str());
    285 		}
    286 	}
    287 };
    288 
    289 MODULE_INIT(CSEntryMessage)