File: userlist

package info (click to toggle)
epic5 3.0.3-1
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 5,328 kB
  • sloc: ansic: 75,810; makefile: 648; ruby: 227; python: 215; sh: 78; perl: 13
file content (364 lines) | stat: -rw-r--r-- 9,570 bytes parent folder | download | duplicates (3)
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
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
if (word(2 $loadinfo()) != [pf]) {
	load -pf $word(1 $loadinfo());
	return;
};

if (J !~ [EPIC5*]) {
	xecho -b ERROR: userlist: load: EPIC5 is required;
	return;
};

package userlist;

## Userlist script for EPIC5.
## Written by zlonix@efnet, public domain.
##
## Version: 1.0 (October, 2014)
##  - Initial roll-out
##
## Version: 1.1 (December, 2014)
##  - Check if joined person hasn't been opped already before we op
##    him (helps to not mode-flood chans on netjoins when servers op
##    people automatically)

## This script provides basic userlist functionality found in most
## modern bots.  It allows automatic mode setting (op, voice, kickban)
## and on-demand operation, based on remote user CTCP requests (op,
## voice, invite, unban). Authentication is based only on hostmasks,
## password support is not presented. The script requires addset and ban
## scripts from base EPIC5 distribution.
##
## Userlist (op, voice, etc) globally turned on or off by boolean /set
## userlist command.  Offensive actions (kickban for now) controlled by
## /set excludelist.
##
## Following aliases provides list management:
##
##   /adduser <user> <host> [[host] [host] ...] - add user and
##   corresponding hosts, script also checks that given host can be
##   assigned only to one user
##
##   /addflag <user> <chan> <flag> [[flag] [flag] ...] - add flags to
##   specified <user> on the <chan>, based on this flags script will
##   take automatic or on-demand actions, possible flags are:
##      autoop - auto op user on join (in random 5 sec interval;
##               implies access to 'op' flag)
##      autovoice - auto voice user on join (in random 5 sec interval
##                  implies access to 'voice' flag
##      op - op user after /ctcp <yournick> OP <chan>
##      voice - voice user after /ctcp <yournick> VOICE <chan>
##      unban - unban user after /ctcp <yournick> UNBAN <chan> (only
##              current user host is unbanned)
##      invite - invite user after /ctcp <yournick> INVITE <chan>
##      kickban - auto kickban user on join (ban mask is hardcoded to
##                *@domain.tld - this is type '2' from mask() help page,
##                works only if /set excludelist is on)
##      friend - combination of op, voice, unban and invite flags
##
##   /showuser [user] - show information about the [user] or about all
##   users if no arguments are given
##
##   /saveuser <file> - save current userlist to a file, file is deleted
##   first if it's exist, you must load this file (not with PF loader)
##   in your ~/.ircrc to preserve your userlist between client runs
##
##   /delhost <user> <host> [[host] [host] ...] - delete hosts from user
##
##   /delflag <user> <chan> <flag> [[flag] [flag] ...] - delete flags
##   from user on the <chan>
##   
##   /deluser <user> [[user] [user] ...] - delete users from userlist,
##   all corresponding information is deleted (hosts, flags)
##
##   /dumpuser - clears userlist (primary usage - in userlist config
##   file)
##
## Examples:
##
##   /adduser testnick test@nick.com foo@example.com
##   /addflag testnick #epic autoop unban
##   /addflag testnick #epic2 voice
##
##   /adduser badnick *@badhost.com
##   /addflag badnick #epic kickban
##
## Bugs: user name maynot contain things which can't be used in variable
##       name, for example, |, although it doesn't matter much, because
##       all authentication is done by hostmask, not by nick

load addset;
load ban;

alias adduser (user, host, ...) {
	if (@user && @host) {
		fe ($host $*) hh {
			@ :badhost = 0;

			foreach userlist uu {
				if (findw($hh $userlist[$uu]) > -1) {
					if (uu == user) {
						xecho -c -b adduser: host $hh already presented for $user;
					} else {
						xecho -c -b adduser: conflict - $hh already added for user $tolower($uu);
					};
					@ :badhost = 1;
					break;
				};
			};
			if (!badhost) {
				push ::userlist[$user] $hh;
				xecho -s -c -b Added host [$hh] for user $user;
			};
		};
	} else {
		xecho -c -b Usage: /adduser <user> <host> [[host] [host] ...];
	};
};

alias addflag (user, chan, flag, ...) {
	if (@user && @chan && @flag) {
		if (!userlist[$user]) {
			xecho -c -b addflag: unknown user $user;
			return;
		};
		if (!ischannel($chan)) {
			xecho -c -b addflag: $chan is not a channel;
			return;
		};
		fe ($flag $*) ff {
			if (findw($ff autoop autovoice op voice invite unban kickban friend) == -1) {
				xecho -c -b addflag: unknown flag $ff;
				continue;
			};
			if (findw($ff $userlist[$user][$encode($chan)]) == -1) {
				push ::userlist[$user][$encode($chan)] $ff;
				push :tmp $ff;
			} else {
				xecho -c -b addflag: flag $ff already added for $user on $chan;
			};
		};
		if (@tmp) {
			xecho -s -c -b Added flags [$tmp] for user $user on channel $chan;
		};
	} else {
		xecho -c -b Usage: /addflag <user> <chan> <flag> [[flag] [flag] ...];
	};
};

alias delflag (user, chan, flag, ...) {
	if (@user && @chan && @flag) {
		if (!userlist[$user]) {
			xecho -c -b delflag: unknown user $user;
			return;
		};
		if (!ischannel($chan)) {
			xecho -c -b delflag: $chan is not a channel;
			return;
		};
		fe ($flag $*) ff {
			if (findw($ff autoop autovoice op voice invite unban protect kickban) == -1) {
				xecho -c -b addflag: unknown flag $ff;
				continue;
			};
			if (findw($ff $userlist[$user][$encode($chan)]) > -1) {
				@ ::userlist[$user][$encode($chan)] = remw($ff $::userlist[$user][$encode($chan)]);
				push :tmp $ff;
			} else {
				xecho -c -b delflag: flag $ff doesn't  exist for user $user on $chan;
			};
		};
		if (@tmp) {
			xecho -c -b Removed flags [$tmp] for user $user on channel $chan;
		};
	} else {
		xecho -c -b Usage: /delfalg <user> <chan> <flag> [[flag] [flag] ...];
	};
};

alias deluser (user, ...) {
	if (@user) {
		fe ($user $*) uu {
			if (userlist[$uu]) {
				foreach userlist[$uu] cc {
					^assign -userlist[$uu][$cc];
				};
				^assign -userlist[$user];
			} else {
				xecho -c -b deluser: user $uu doesn't exist;
			};
		};
	} else {
		xecho -c -b Usage: /deluser <user> [[user] [user] ...];
	};
};

alias delhost (user, host, ...) {
	if (@user && @host) {
		if (!userlist[$user]) {
			xecho -c -b delhost: user $user doesn't exist;
			return;
		};
		fe ($host $*) hh {
			if (findw($hh $userlist[$user]) > -1) {
				@ ::userlist[$user] = remw($hh $::userlist[$user]);
				push :tmp $hh;
			} else {
				xecho -c -b delhost: host $hh doesn't belong to user $user;
			};
		};
		if (@tmp) {
			xecho -c -b Removed hosts [$tmp] for user $user;
		};
	} else {
		xecho -c -b Usage: /delhost <user> <host> [[host] [host] ...];
	};
};

alias showuser (user) {
	if (@user) {
		showuser.echo $user;
	} else {
		foreach userlist ii {
			showuser.echo $ii;
		};
	};
};

alias showuser.echo (user) {
	if (@user) {
		xecho -b User: $tolower($user);
		xecho -b   Hostmasks: $userlist[$user];
		foreach userlist.${user} ii {
			xecho -b   Channel: $tolower($decode($ii)) - $sort($userlist[$user][$ii]);
		};
	};
};

alias saveuser (file) {
	if (@file) {
		if (fexist($file) == 1 && unlink($file) > 0) {
			xecho -c -b saveuser: can't unlink existing $file before writing - abort;
			return;
		};
		@ :fd = open($file W);
		if (isfilevalid($fd) == 1) {
			@ write($fd ^dumpuser);
			foreach userlist uu {
				@ :data = [^adduser $tolower($uu) $userlist[$uu]];
				@ write($fd $data);
			};
			foreach userlist uu {
				foreach userlist.${uu} cc {
					@ :data = [^addflag $tolower($uu) $decode($cc) $userlist[$uu][$cc]];
					@ write($fd $data);
				};
			};
			@ close($fd);
			xecho -c -b Userlist saved to $file;
		} else {
			xecho -c -b saveuser: isfilevalid() not equal 1;
		};
	} else {
		xecho -c -b Usage: /saveuser <file>;
	};
};

alias userflags (host, chan, void) {
	foreach userlist uu {
		if ((:idx = rmatch($host $userlist[$uu])) > 0) {
			@ :idx--;

			push :users $uu;
			push :hosts $word($idx $userlist[$uu]);
		};
	};
	if ((:idx = rmatch($host $hosts)) > 0) {
		@ :idx--;

		return $userlist[$word($idx $users)][$encode($chan)];
	} else {
		return;
	};
};

alias isfriend (nick, chan, void) {
	return ${findw(friend $userflags($userhost($nick) $chan)) > -1};
};

alias friends (chan, void) {
	fe ($strip(?.%+@ $channel($chan))) uu {
		if (isfriend($uu $chan)) {
			push :tmp $uu;
		};
	};

	return $tmp;
};

alias dumpuser (void) {
	foreach userlist uu {
		deluser $uu;
	};
	^assign -userlist;
};

alias userlist.doop (chan, nick, void) {
	if (!ischanop($nick $chan) && ischanop($servernick() $chan)) {
		mode $chan +o $nick;
	};
};

alias userlist.dovoice (chan, nick, void) {
	if (!ischanvoice($nick $chan) && ischanop($servernick() $chan)) {
		mode $chan +v $nick;
	};
};

on #-join 100 * {
	switch ($userflags($userhost() $1)) {
		(*kickban*) {
			if (excludelist == [on]) {
				mode $1 -o+b $0 $mask(2 $userhost());
				kick $1 $0 user has been banned;
			};
		};
		(*autoop*) {
			if (userlist == [on]) {
				timer 5 userlist.doop $1 $0;
			};
		};
		(*autovoice*) {
			if (userlist == [on]) {
				timer 5 userlist.dovoice $1 $0;
			};
		};
	};
};

on #-ctcp 100 '% $$servernick() \\\\[op voice invite unban\\\\] %' {
	if (userlist != [on]) {
		return;
	};

	@ :uf = userflags($userhost() $3);

	if ((findw($2 $uf) > -1 || findw(friend $uf) > -1) && ischanop($servernick() $3)) {
		switch ($2) {
			(*op) {
				timer 5 userlist.doop $3 $0;
			};
			(*voice) {
				timer 5 userlist.dovoice $3 $0;
			};
			(invite) {
				invite $0 $3;
			};
			(unban) {
				unban $3 $0;
				notice $0 You've been unbanned on channel $3;
			};
		};
	};
};
addset userlist bool;
addset excludelist bool;