-
Notifications
You must be signed in to change notification settings - Fork 0
/
m_xlinesync.cpp
262 lines (227 loc) · 7.39 KB
/
m_xlinesync.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
/*
* X-line sync: Sync InspIRCd X-lines with Anope X-Lines
* Currently supports: CBAN,Q,G,Z,R-lines -> AKILL, SQLine
*
* Copyright (C) 2021 Michael Hazell <[email protected]>
*
* You may use this module as long as you follow the terms of the GPLv3
* Parts based on m_xlinetoakill by genius3000
*
* Configuration:
* module { name = "m_xlinesync"; silent = false; }
* command { service = "OperServ"; name = "XLINESYNC"; command = "operserv/xlinesync"; permission = "operserv/xlinesync" ; }
*/
#include "module.h"
static ServiceReference<XLineManager> akills("XLineManager", "xlinemanager/sgline");
static ServiceReference<XLineManager> sqlines("XLineManager", "xlinemanager/sqline");
enum InspIRCdXLineType
{
TYPE_CBAN,
TYPE_GLINE,
TYPE_QLINE,
TYPE_RLINE,
TYPE_ZLINE
};
class CommandOSXLineSync : public Command
{
public:
CommandOSXLineSync(Module *creator) : Command(creator, "operserv/xlinesync", 1, 1)
{
this->SetDesc(_("Sync X-Lines in Anope to the IRCd"));
this->SetSyntax(_("SYNC"));
}
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
{
// Send AKILLs
for (size_t i = 0; i < akills->GetCount(); ++i)
{
XLine *x = akills->GetEntry(i);
if (x)
akills->Send(NULL, x);
}
// Send SQLines
for (size_t i = 0; i < sqlines->GetCount(); ++i)
{
XLine *x = sqlines->GetEntry(i);
if (x)
sqlines->Send(NULL, x);
}
source.Reply("Synced AKILLs and SQLines with the IRCd");
Log(LOG_ADMIN, source, this) << "to sync AKILLs and SQLines with the IRCd";
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
{
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Sync X-Lines in Anope to the IRCd. This currently supports AKILL and SQLINE."));
return true;
}
};
class XLineSync : public Module
{
BotInfo *OperServ;
CommandOSXLineSync commandosxlinesync;
bool silent;
public:
XLineSync(const Anope::string &modname, const Anope::string &creator)
: Module(modname, creator, THIRD)
, OperServ(NULL)
, commandosxlinesync(this)
{
if (Anope::VersionMajor() != 2 || Anope::VersionMinor() != 0)
throw ModuleException("This module only works on Anope 2.0.x.");
if (IRCD->GetProtocolName().find("InspIRCd") == Anope::string::npos)
throw ModuleException("This module only works on InspIRCd.");
if (!ModuleManager::FindModule("operserv") || !ModuleManager::FindModule("os_akill") || !ModuleManager::FindModule("os_sxline"))
throw ModuleException("This module requires OperServ, as well as the os_akill and os_sxline modules.");
this->SetAuthor("Techman");
this->SetVersion("1.1.0");
}
void OnReload(Configuration::Conf *conf) anope_override
{
OperServ = conf->GetClient("OperServ");
if (!OperServ)
throw ModuleException("OperServ could not be found.");
Configuration::Block *block = conf->GetModule(this);
silent = block->Get<bool>("silent", "false");
}
EventReturn OnMessage(MessageSource &source, Anope::string &command, std::vector<Anope::string> ¶ms)
{
// If it isn't InspIRCd-related X-line additions or removals, move on
if ((command != "ADDLINE" && command != "DELLINE") || params.size() < 2 || !akills || !sqlines)
return EVENT_CONTINUE;
// Pull out the X-line type and the mask
const Anope::string &rawtype = params[0];
Anope::string mask = params[1];
// Now, set the type for processing later
int etype;
if (rawtype == "CBAN")
etype = TYPE_CBAN;
else if (rawtype == "G")
etype = TYPE_GLINE;
else if (rawtype == "Q")
etype = TYPE_QLINE;
else if (rawtype == "R")
etype = TYPE_RLINE;
else if (rawtype == "Z")
etype = TYPE_ZLINE;
// Are we adding or removing? Parameter count will us
if (command == "ADDLINE" && params.size() == 6)
{
// Pull out common variables that will be used for all types
const Anope::string setby = params[2];
time_t settime = convertTo<time_t>(params[3]);
time_t duration = convertTo<time_t>(params[4]);
const Anope::string reason = params[5];
time_t expires = (duration == 0) ? duration : settime + duration;
switch (etype)
{
// CBAN = Channel Q-line
case TYPE_CBAN:
case TYPE_QLINE:
{
// Check if entry alreay exists
if (sqlines->HasEntry(mask))
return EVENT_CONTINUE;
XLine *x = new XLine(mask, setby, expires, reason, XLineManager::GenerateUID());
sqlines->AddXLine(x);
if (!silent)
Log(OperServ, "sqline/sync") << "X-line (" << rawtype << ") sync added SQLINE on " << mask << " (" << reason << "), expires in " << (expires ? Anope::Duration(expires - settime) : "never") << " [set by " << setby << "]";
break;
}
// R-Lines are sent as 'n!u@h\sreal\sname' and need to be '/n!u@h#real name/'
case TYPE_RLINE:
{
size_t space = mask.find("\\s");
if (space != Anope::string::npos)
{
mask = mask.replace(space, 2, "#");
mask = mask.replace_all_cs("\\s", " ");
}
mask = "/" + mask + "/";
if (akills->HasEntry(mask))
return EVENT_CONTINUE;
XLine *x = new XLine(mask, setby, expires, reason, XLineManager::GenerateUID());
akills->AddXLine(x);
if (!silent)
Log(OperServ, "akill/sync") << "X-line (" << rawtype << ") sync added AKILL on " << mask << " (" << reason << "), expires in " << (expires ? Anope::Duration(expires - settime) : "never") << " [set by " << setby << "]";
break;
}
case TYPE_ZLINE:
{
// InspIRCd Z-lines are just IPs, akills need to be *@IP
mask = "*@" + mask;
}
case TYPE_GLINE:
{
// No conversions necessary for G-lines
if (akills->HasEntry(mask))
return EVENT_CONTINUE;
XLine *x = new XLine(mask, setby, expires, reason, XLineManager::GenerateUID());
akills->AddXLine(x);
if (!silent)
Log(OperServ, "akill/sync") << "X-line (" << rawtype << ") sync added AKILL on " << mask << " (" << reason << "), expires in " << (expires ? Anope::Duration(expires - settime) : "never") << " [set by " << setby << "]";
break;
}
default:
break;
}
}
else if (command == "DELLINE")
{
switch (etype)
{
case TYPE_CBAN:
case TYPE_QLINE:
{
// Find matching X-Line, if it exists
XLine *x = sqlines->HasEntry(mask);
if (!x)
return EVENT_CONTINUE;
sqlines->DelXLine(x);
if (!silent)
Log(OperServ, "sqline/sync") << "X-line (" << rawtype << ") sync removed SQLINE on " << mask;
break;
}
case TYPE_RLINE:
{
size_t space = mask.find("\\s");
if (space != Anope::string::npos)
{
mask = mask.replace(space, 2, "#");
mask = mask.replace_all_cs("\\s", " ");
}
mask = "/" + mask + "/";
// Find matching X-Line if it exists
XLine *x = akills->HasEntry(mask);
if (!x)
return EVENT_CONTINUE;
akills->DelXLine(x);
if (!silent)
Log(OperServ, "akill/sync") << "X-line (" << rawtype << ") sync removed AKILL on " << mask;
break;
}
case TYPE_ZLINE:
{
mask = "*@" + mask;
}
case TYPE_GLINE:
{
XLine *x = akills->HasEntry(mask);
if (!x)
return EVENT_CONTINUE;
akills->DelXLine(x);
if (!silent)
Log(OperServ, "akill/sync") << "X-line (" << rawtype << ") sync removed AKILL on " << mask;
break;
}
default:
break;
}
}
// Standard protocol modules do nothing with ADDLINE and DELLINE,
// allow other modules to act on these though.
return EVENT_CONTINUE;
}
};
MODULE_INIT(XLineSync)