anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
cs_clone.cpp (7421B)
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/bs_badwords.h" 14 15 class CommandCSClone : public Command 16 { 17 void CopySetting(ChannelInfo *ci, ChannelInfo *target_ci, const Anope::string &setting) 18 { 19 if (ci->HasExt(setting)) 20 target_ci->Extend<bool>(setting); 21 } 22 23 void CopyAccess(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci) 24 { 25 std::set<Anope::string> masks; 26 unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1024"); 27 unsigned count = 0; 28 29 for (unsigned i = 0; i < target_ci->GetAccessCount(); ++i) 30 masks.insert(target_ci->GetAccess(i)->Mask()); 31 32 for (unsigned i = 0; i < ci->GetAccessCount(); ++i) 33 { 34 const ChanAccess *taccess = ci->GetAccess(i); 35 AccessProvider *provider = taccess->provider; 36 37 if (access_max && target_ci->GetDeepAccessCount() >= access_max) 38 break; 39 40 if (masks.count(taccess->Mask())) 41 continue; 42 masks.insert(taccess->Mask()); 43 44 ChanAccess *newaccess = provider->Create(); 45 newaccess->SetMask(taccess->Mask(), target_ci); 46 newaccess->creator = taccess->creator; 47 newaccess->last_seen = taccess->last_seen; 48 newaccess->created = taccess->created; 49 newaccess->AccessUnserialize(taccess->AccessSerialize()); 50 51 target_ci->AddAccess(newaccess); 52 53 ++count; 54 } 55 56 source.Reply(_("%d access entries from \002%s\002 have been cloned to \002%s\002."), count, ci->name.c_str(), target_ci->name.c_str()); 57 } 58 59 void CopyAkick(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci) 60 { 61 target_ci->ClearAkick(); 62 for (unsigned i = 0; i < ci->GetAkickCount(); ++i) 63 { 64 const AutoKick *akick = ci->GetAkick(i); 65 if (akick->nc) 66 target_ci->AddAkick(akick->creator, akick->nc, akick->reason, akick->addtime, akick->last_used); 67 else 68 target_ci->AddAkick(akick->creator, akick->mask, akick->reason, akick->addtime, akick->last_used); 69 } 70 71 source.Reply(_("All akick entries from \002%s\002 have been cloned to \002%s\002."), ci->name.c_str(), target_ci->name.c_str()); 72 } 73 74 void CopyBadwords(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci) 75 { 76 BadWords *target_badwords = target_ci->Require<BadWords>("badwords"), 77 *badwords = ci->Require<BadWords>("badwords"); 78 79 if (!target_badwords || !badwords) 80 { 81 source.Reply(ACCESS_DENIED); // BotServ doesn't exist/badwords isn't loaded 82 return; 83 } 84 85 target_badwords->ClearBadWords(); 86 87 for (unsigned i = 0; i < badwords->GetBadWordCount(); ++i) 88 { 89 const BadWord *bw = badwords->GetBadWord(i); 90 target_badwords->AddBadWord(bw->word, bw->type); 91 } 92 93 badwords->Check(); 94 target_badwords->Check(); 95 96 source.Reply(_("All badword entries from \002%s\002 have been cloned to \002%s\002."), ci->name.c_str(), target_ci->name.c_str()); 97 } 98 99 void CopyLevels(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci) 100 { 101 const Anope::map<int16_t> &cilevels = ci->GetLevelEntries(); 102 103 for (Anope::map<int16_t>::const_iterator it = cilevels.begin(); it != cilevels.end(); ++it) 104 { 105 target_ci->SetLevel(it->first, it->second); 106 } 107 108 source.Reply(_("All level entries from \002%s\002 have been cloned into \002%s\002."), ci->name.c_str(), target_ci->name.c_str()); 109 } 110 111 public: 112 CommandCSClone(Module *creator) : Command(creator, "chanserv/clone", 2, 3) 113 { 114 this->SetDesc(_("Copy all settings from one channel to another")); 115 this->SetSyntax(_("\037channel\037 \037target\037 [\037what\037]")); 116 } 117 118 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 119 { 120 const Anope::string &channel = params[0]; 121 const Anope::string &target = params[1]; 122 Anope::string what = params.size() > 2 ? params[2] : ""; 123 124 if (Anope::ReadOnly) 125 { 126 source.Reply(READ_ONLY_MODE); 127 return; 128 } 129 130 User *u = source.GetUser(); 131 ChannelInfo *ci = ChannelInfo::Find(channel); 132 bool override = false; 133 134 if (ci == NULL) 135 { 136 source.Reply(CHAN_X_NOT_REGISTERED, channel.c_str()); 137 return; 138 } 139 140 ChannelInfo *target_ci = ChannelInfo::Find(target); 141 if (!target_ci) 142 { 143 source.Reply(CHAN_X_NOT_REGISTERED, target.c_str()); 144 return; 145 } 146 147 if (ci == target_ci) 148 { 149 source.Reply(_("Cannot clone channel \002%s\002 to itself!"), target.c_str()); 150 return; 151 } 152 153 if (!source.IsFounder(ci) || !source.IsFounder(target_ci)) 154 { 155 if (!source.HasPriv("chanserv/administration")) 156 { 157 source.Reply(ACCESS_DENIED); 158 return; 159 } 160 else 161 override = true; 162 } 163 164 if (what.equals_ci("ALL")) 165 what.clear(); 166 167 if (what.empty()) 168 { 169 delete target_ci; 170 target_ci = new ChannelInfo(*ci); 171 target_ci->name = target; 172 target_ci->time_registered = Anope::CurTime; 173 (*RegisteredChannelList)[target_ci->name] = target_ci; 174 target_ci->c = Channel::Find(target_ci->name); 175 176 target_ci->bi = NULL; 177 if (ci->bi) 178 ci->bi->Assign(u, target_ci); 179 180 if (target_ci->c) 181 { 182 target_ci->c->ci = target_ci; 183 184 target_ci->c->CheckModes(); 185 186 target_ci->c->SetCorrectModes(u, true); 187 } 188 189 if (target_ci->c && !target_ci->c->topic.empty()) 190 { 191 target_ci->last_topic = target_ci->c->topic; 192 target_ci->last_topic_setter = target_ci->c->topic_setter; 193 target_ci->last_topic_time = target_ci->c->topic_time; 194 } 195 else 196 target_ci->last_topic_setter = source.service->nick; 197 198 const Anope::string settings[] = { "NOAUTOOP", "CS_KEEP_MODES", "PEACE", "PERSIST", "RESTRICTED", 199 "CS_SECURE", "SECUREFOUNDER", "SECUREOPS", "SIGNKICK", "SIGNKICK_LEVEL", "CS_NO_EXPIRE" }; 200 201 for (unsigned int i = 0; i < sizeof(settings) / sizeof(Anope::string); ++i) 202 CopySetting(ci, target_ci, settings[i]); 203 204 CopyAccess(source, ci, target_ci); 205 CopyAkick(source, ci, target_ci); 206 CopyBadwords(source, ci, target_ci); 207 CopyLevels(source, ci, target_ci); 208 209 FOREACH_MOD(OnChanRegistered, (target_ci)); 210 211 source.Reply(_("All settings from \002%s\002 have been cloned to \002%s\002."), ci->name.c_str(), target_ci->name.c_str()); 212 } 213 else if (what.equals_ci("ACCESS")) 214 { 215 CopyAccess(source, ci, target_ci); 216 } 217 else if (what.equals_ci("AKICK")) 218 { 219 CopyAkick(source, ci, target_ci); 220 } 221 else if (what.equals_ci("BADWORDS")) 222 { 223 CopyBadwords(source, ci, target_ci); 224 } 225 else if (what.equals_ci("LEVELS")) 226 { 227 CopyLevels(source, ci, target_ci); 228 } 229 else 230 { 231 this->OnSyntaxError(source, ""); 232 return; 233 } 234 235 Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to clone " << (what.empty() ? "everything from it" : what) << " to " << target_ci->name; 236 } 237 238 bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override 239 { 240 this->SendSyntax(source); 241 source.Reply(" "); 242 source.Reply(_("Copies all settings, access, akicks, etc from \002channel\002 to the\n" 243 "\002target\002 channel. If \037what\037 is \002ACCESS\002, \002AKICK\002, \002BADWORDS\002,\n" 244 "or \002LEVELS\002 then only the respective settings are cloned.\n" 245 "You must be the founder of \037channel\037 and \037target\037.")); 246 return true; 247 } 248 }; 249 250 class CSClone : public Module 251 { 252 CommandCSClone commandcsclone; 253 254 public: 255 CSClone(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), commandcsclone(this) 256 { 257 258 } 259 }; 260 261 MODULE_INIT(CSClone)