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> ¶ms) 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)