-
Notifications
You must be signed in to change notification settings - Fork 1
/
ds_set.cpp
322 lines (303 loc) · 11.7 KB
/
ds_set.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
/* ----------------------------------------------------------------------------
* Name : ds_set.cpp
* Author : Naram Qashat (CyberBotX)
* ----------------------------------------------------------------------------
* Description:
*
* The SET and SET IGNORE commands of DiceServ. See diceserv.cpp for more
* information about DiceServ, including version and license.
* ----------------------------------------------------------------------------
*/
#include "diceserv.h"
ServiceReference<DiceServService> DiceServ("DiceServService", "DiceServ");
/** SET command
*
* This base command has no real functionality, it is mainly here to display the help for the sub-commands.
*/
class DSSetCommand : public Command
{
public:
DSSetCommand(Module *creator) : Command(creator, "diceserv/set", 3, 3)
{
this->SetDesc(Anope::printf(_("Set options for %s access"), Config->GetClient("DiceServ")->nick.c_str()));
this->SetSyntax(_("\037option\037 \037parameters\037"));
}
void Execute(CommandSource &source, const std::vector<Anope::string> &) anope_override
{
this->OnSyntaxError(source, "");
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
{
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Currently allows you to set who has %s access.\n"), source.service->nick.c_str());
source.Reply(" ");
source.Reply(_("Available options:"));
source.Reply(" ");
Anope::string this_name = source.command;
bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands"),
hide_registered_commands = Config->GetBlock("options")->Get<bool>("hideregisteredcommands");
for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it)
{
const Anope::string &c_name = it->first;
const CommandInfo &info = it->second;
if (c_name.find_ci(this_name + " ") == 0)
{
ServiceReference<Command> c("Command", info.name);
if (!c)
continue;
else if (hide_registered_commands && !c->AllowUnregistered() && !source.GetAccount())
continue;
else if (hide_privileged_commands && !info.permission.empty() && !source.HasCommand(info.permission))
continue;
source.command = it->first;
c->OnServHelp(source);
}
}
source.Reply(" ");
source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information on a\n"
"particular option.\n"), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), this_name.c_str());
source.Reply(" ");
source.Reply(_("Note: Access to these commands are limited. See help on each\n"
"option for details."));
return true;
}
};
/** SET IGNORE command
*
* Sets a channel or nickname/user to be ignored by DiceServ.
*/
class DSSetIgnoreCommand : public Command
{
/** When this value is true, then channel operators set in ChanServ can ignore channels in addition to the channel's founder(s) */
bool ChanOpCanIgnore;
/** Sets the actual syntax based on the access the user has.
*/
void SetRealSyntax(CommandSource &source)
{
this->ClearSyntax();
if (source.GetAccount() && source.HasCommand("diceserv/set"))
this->SetSyntax(_("{\037channel\037|\037nick\037} {ON|OFF}"));
else
this->SetSyntax(_("\037channel\037 {ON|OFF}"));
}
public:
DSSetIgnoreCommand(Module *creator) : Command(creator, "diceserv/set/ignore", 2, 2)
{
this->SetDesc(_("Change ignored/allowed setting"));
}
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
{
if (Anope::ReadOnly)
{
source.Reply(_("Sorry, dice ignore option setting is temporarily disabled."));
return;
}
Anope::string where = params[0], param = params[1];
// The parameter must be ON or OFF, all others should stop processing
enum
{
IGNORE_ADD,
IGNORE_DEL
} mode;
if (param.equals_ci("ON"))
mode = IGNORE_ADD;
else if (param.equals_ci("OFF"))
mode = IGNORE_DEL;
else
{
this->OnSyntaxError(source, "");
return;
}
bool is_servoper = source.HasCommand("diceserv/set");
// If the thing to ignore starts with a #, assume it's a channel
if (where[0] == '#')
{
// Find the Channel record and ChannelInfo record from ChanServ
Channel *c = Channel::Find(where);
ChannelInfo *ci = ChannelInfo::Find(where);
// If the channel wasn't found and a ChanServ entry wasn't found (or the channel is suspended), display an error
if (!c && (!ci || ci->HasExt("SUSPENDED")))
source.Reply(CHAN_X_INVALID, where.c_str());
// If we found a registered channel, we will store the ignore there
else if (ci)
{
/* The only ones who can set an ignore on a registered channel are Services Admins or the channel's founder (unless chanopcanignore is set, then
* channel operators can as well) */
if (is_servoper || (this->ChanOpCanIgnore ? ci->AccessFor(source.GetUser()).HasPriv("AUTOOP") : false) ||
(ci->HasExt("SECUREFOUNDER") ? source.IsFounder(ci) : source.AccessFor(ci).HasPriv("FOUNDER")))
{
/* Either add or delete the ignore data */
if (mode == IGNORE_ADD)
{
DiceServ->Ignore(ci);
if (c)
DiceServ->Ignore(c);
}
else
{
DiceServ->Unignore(ci);
if (c)
DiceServ->Unignore(c);
}
source.Reply(mode == IGNORE_ADD ? _("\002%s\002 will now ignore all dice rolls sent to \037%s\037.") :
_("\002%s\002 will now allow all dice rolls sent to \037%s\037."), source.service->nick.c_str(), where.c_str());
}
// Otherwise, deny access
else
source.Reply(ACCESS_DENIED);
}
// No registered channel was found, but a channel was, so store temporary data on the channel
else
{
// The only ones who can set an ignore on an unregistered channel are Services Operators with diceserv/set or channel operators
if (is_servoper || c->HasUserStatus(source.GetUser(), "OP"))
{
// Either add or delete the ignore data
if (mode == IGNORE_ADD)
DiceServ->Ignore(c);
else
DiceServ->Unignore(c);
source.Reply(mode == IGNORE_ADD ? _("\002%s\002 will now ignore all dice rolls sent to \037%s\037.") :
_("\002%s\002 will now allow all dice rolls sent to \037%s\037."), source.service->nick.c_str(), where.c_str());
}
// Otherwise, deny access
else
source.Reply(ACCESS_DENIED);
}
}
// Otherwise, the thing to ignore is going to be assumed to be a nick
else
{
// Only Services Operators with diceserv/set can set ignores on nicks, deny access to those who aren't
if (!is_servoper)
source.Reply(ACCESS_DENIED);
// Find the User record and the NickAlias record from NickServ
User *nu = User::Find(where);
NickAlias *na = NickAlias::Find(where);
BotInfo *bot = BotInfo::Find(where);
// If the nick wasn't found and a NickServ entry wasn't found (or the nick is suspended), display an error
if (bot || (!nu && (!na || (na->nc && na->nc->HasExt("SUSPENDED")))))
source.Reply(_("Nick %s is not a valid nick."), where.c_str());
// If we found a registered nick, we will store the ignore there
else if (na)
{
// If a User record was not found, we will check all the users to find one that has a matching NickCore
if (!nu)
{
Anope::hash_map<User *>::const_iterator it = UserListByNick.begin(), it_end = UserListByNick.end();
for (; it != it_end; ++it)
{
nu = it->second;
if (nu->Account() == na->nc)
break;
}
if (it == it_end)
nu = NULL;
}
// Either add or delete the ignore data
if (mode == IGNORE_ADD)
{
DiceServ->Ignore(na->nc);
if (nu)
DiceServ->Ignore(nu);
}
else
{
DiceServ->Unignore(na->nc);
if (nu)
DiceServ->Unignore(nu);
}
source.Reply(mode == IGNORE_ADD ? _("\002%s\002 will now ignore all dice rolls by \037%s\037.") :
_("\002%s\002 will now allow all dice rolls by \037%s\037."), source.service->nick.c_str(), where.c_str());
}
// No registered nick was found, but a user was, so store temporary data on the user
else
{
// Either add or delete the ignore data
if (mode == IGNORE_ADD)
nu->Extend("diceserv_ignore", 1);
else
DiceServ->Unignore(nu);
source.Reply(mode == IGNORE_ADD ? _("\002%s\002 will now ignore all dice rolls by \037%s\037.") :
_("\002%s\002 will now allow all dice rolls by \037%s\037."), source.service->nick.c_str(), where.c_str());
}
}
}
/** Sets the value for if channel operators can set ignores on channels.
* @param chanOpCanIgnore true if channel operators can set ignores, false otherwise
*/
void SetChanOpCanIgnore(bool chanOpCanIgnore)
{
this->ChanOpCanIgnore = chanOpCanIgnore;
}
bool OnHelp(CommandSource &source, const Anope::string &) anope_override
{
this->SetRealSyntax(source);
this->SendSyntax(source);
source.Reply(" ");
BotInfo *ChanServ = Config->GetClient("ChanServ");
if (source.GetAccount() && source.HasCommand("diceserv/set"))
{
BotInfo *NickServ = Config->GetClient("NickServ");
source.Reply(_("This will allow a channel or nick to be set to ignore the\n"
"use of %s commands inside the channel or by that user.\n"
"If ON is given, then %s will be ignored, otherwise, it\n"
"will be allowed.\n"
" \n"
"If the channel in question is registered, then only a\n"
"services admin or the channel's founder (or someone with\n"
"founder-level access) can use this option. The option set\n"
"will be persistent as long as the channel stays registered\n"
"in %s. If the channel is unregistered, then any ops in\n"
"the channel can set this option, but it will only last as\n"
"long as the channel is active.\n"
" \n"
"A nick may also be given, but this option is limited to\n"
"services operators and up. If the nick in question is\n"
"registered, then the option will be set in %s so it\n"
"will stay persistent as long as the nick stays registered.\n"
"If the nick is unregistered, then it will only last as long\n"
"as the user is online."), source.service->nick.c_str(), source.service->nick.c_str(), ChanServ ? ChanServ->nick.c_str() : "ChanServ",
NickServ ? NickServ->nick.c_str() : "NickServ");
}
else
source.Reply(_("This will allow a channel to be set to ignore the use of\n"
"%s commands inside the channel. If ON is given, then\n"
"%s will be ignored, otherwise, it will be allowed.\n"
" \n"
"If the channel in question is registered, then only the\n"
"channel's founder (or someone with founder-level access) can\n"
"use this option. The option set will be persistent as long\n"
"as the channel stays registered in %s. If the channel\n"
"is unregistered, then any ops in the channel can set this\n"
"option, but it will only last as long as the channel is\n"
"active."), source.service->nick.c_str(), source.service->nick.c_str(), ChanServ ? ChanServ->nick.c_str() : "ChanServ");
return true;
}
/** This is being overridden so we can replace the syntax string depending on the access the user has.
*/
void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) anope_override
{
this->SetRealSyntax(source);
Command::OnSyntaxError(source, subcommand);
}
};
class DSSet : public Module
{
DSSetCommand set_cmd;
DSSetIgnoreCommand set_ignore_cmd;
public:
DSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, THIRD), set_cmd(this), set_ignore_cmd(this)
{
this->SetAuthor(DiceServService::Author());
this->SetVersion(DiceServService::Version());
if (!DiceServ)
throw ModuleException("No interface for DiceServ");
}
void OnReload(Configuration::Conf *conf) anope_override
{
this->set_ignore_cmd.SetChanOpCanIgnore(conf->GetModule("diceserv")->Get<bool>("chanopcanignore"));
}
};
MODULE_INIT(DSSet)