1#                    an example of script in sirc
2#                          by orabidoo '95
3#
4#            .''',   ||    '||                                     '||`
5#            |   |   ||     ||      ''                              ||
6#   `||''|,  |   | ''||''   ||''|,  ||  `||''|,  .|''|,    '||''|,  ||
7#    ||  ||  |   |   ||     ||  ||  ||   ||  ||  ||  ||     ||  ||  ||
8#   .||  ||. `,,,'   `|..' .||  || .||. .||  ||. `|..|| ..  ||..|' .||.
9#                                                    ||     ||
10#                                                 `..|'    .||
11#
12#
13#        a generic toolbox for sirc; to load it, type /load n0thing.pl
14#
15# version 2.5, last modified: 12 June 1997
16# recent improvements:  lots of new shortcut aliases, removed ctcp pong
17#			replies, added /pj and /wall (from wallop.pl),
18#			moved the settings into SET variables, store saved
19#			msgs in memory, toggleable re-join/re-umode on
20#			reconnect, toggleable ignore of duplicated aways,
21#			better unig, and opbeg becomes ctcp op #chn pass.
22
23$add_ons.="+n0thing-v2.5.pl" if $add_ons !~ /n0thing/;
24
25$n_isaway='';
26$n_svefile=$ENV{"HOME"}."/.n0thing-pl.sve";
27
28# time saving aliases
29
30&docommand("^alias fing ctcp \$0 finger");
31&docommand("^alias ver ctcp \$0 version");
32&docommand("^alias tim ctcp \$0 time");
33&docommand("^alias wallop wallops");
34&docommand("^alias printuh set printuh");
35&docommand("^alias printchan set printchan");
36&docommand("^alias localhost set localhost");
37&docommand("^alias logfile set logfile");
38&docommand("^alias log set log");
39&docommand("^alias ex system");
40&docommand("^alias ls system ls -al");
41&docommand("^alias cat system cat");
42&docommand("^alias rm system rm");
43&docommand("^alias ps system ps");
44&docommand("^alias mail system mail");
45&docommand("^alias setfing set finger");
46
47sub cmd_open {
48  &getarg;
49  $newarg=$talkchannel unless $newarg;
50  &tell("*\cbE\cb* Huh? what channel?"), return unless $newarg;
51  $newarg =~ tr/A-Z/a-z/;
52  &sl("MODE $newarg -lsmpik ".$chankey{$newarg});
53}
54&addcmd("open");
55
56sub cmd_l {
57  if ($talkchannel) {
58    &sl("LIST $talkchannel");
59    &sl("NAMES $talkchannel");
60  }
61}
62&addcmd("l");
63
64sub cmd_a {
65  if ($n_lastmsg) {
66    &msg($n_lastmsg, $args);
67  } else {
68    &tell("*\cbE\cb* How about sending a first /m to someone?");
69  }
70}
71&addcmd("a");
72
73sub cmd_pj {
74  if ($talkchannel) {
75    &sl("PART $talkchannel");
76    &sl("JOIN $talkchannel");
77  }
78}
79&addcmd("pj");
80
81# dcc related stuff
82
83&docommand("^alias ds dcc send");
84&docommand("^alias dl dcc list");
85&docommand("^alias cdc dcc close chat");
86&docommand("^alias cdg dcc close get");
87&docommand("^alias cds dcc close send");
88&docommand("^alias dcrename dcc rchat");
89&docommand("^alias dcren dcc rchat");
90&docommand("^alias rdc dcc rchat");
91
92sub cmd_dc {
93  &getarg;
94  if ($newarg) {
95    &docommand("dcc chat $newarg");
96  } elsif ($n_lastdc) {
97    &docommand("dcc chat $n_lastdc");
98    $n_lastdc='';
99  }
100}
101&addcmd("dc");
102
103sub cmd_dg {
104  &getarg;
105  if ($newarg) {
106    &docommand("dcc get $newarg $args");
107  } elsif ($n_lastdcc) {
108    &docommand("dcc get $n_lastdcc");
109    $n_lastdcc='';
110  }
111}
112&addcmd("dg");
113
114# hooks
115
116sub hook_disc {
117  if ($n_rejoinchannels) {
118    $n_old_when=time;
119    $n_old_umode=$umode;
120    @n_old_channels=grep(!&eq($_, $talkchannel), @channels);
121    push(@n_old_channels, $talkchannel) if $talkchannel;
122    %n_old_chankey=%chankey;
123  }
124  &docommand("server 1"), $n_lastreconnect=time if
125      $n_reconnect && time-$n_lastreconnect>15;
126}
127&addhook("disconnect", "disc");
128
129sub hook_reconnect {
130  if ($n_rejoinchannels && ($n_old_umode || @n_old_channels) &&
131      time <= $n_old_when+15) {
132    $n_old_umode =~ tr/o//d;
133    &sl("MODE $nick +$n_old_umode") if $n_old_umode ne '';
134    local($chans, $keys)=('', '');
135    foreach $c (keys (%n_old_chankey)) {
136      $chans .= $c.",";
137      $keys .= $n_old_chankey{$c}.",";
138    }
139    foreach $c (@n_old_channels) {
140      $c =~ tr/A-Z/a-z/;
141      $chans .= $c."," unless defined($n_old_chankey{$c});
142    }
143    $chans =~ s/,$//;
144    $keys =~ s/,$//;
145    &sl("JOIN $chans $keys") if $chans;
146    $n_old_umode='';
147    @n_old_channels=();
148    %n_old_chankey=();
149  }
150}
151&addhook("001", "reconnect");
152
153sub hook_ctcp {
154  if ($_[1] eq 'DCC') {
155    $n_lastdcc=$who if $_[2] =~ /^SEND /;
156    $n_lastdc=$who if $_[2] =~ /^CHAT /;
157  }
158}
159&addhook("ctcp", "ctcp");
160
161sub hook_kicked {
162  local($kicked, $where_from, $reason)=@_;
163  if ($n_autorejoin && &eq($kicked, $nick)) {
164    &sl("JOIN $where_from $chankey{$where_from}");
165  }
166}
167&addhook("kick", "kicked");
168
169sub hook_uhnotify {
170  unless ($n_slowserver) {
171    &userhost($_[0], "&tell(\"*\cb)\cb* Signon by $_[0] (\$user\\\@\$host) detected!\");", "");
172    $silent=1;
173  }
174}
175&addhook("notify_signon", "uhnotify");
176
177sub hook_lastmsg {
178  $n_lastmsg=$_[0] unless $_[0] =~ /^[\#\+]/;
179}
180&addhook("send_text", "lastmsg");
181&addhook("send_action", "lastmsg");
182
183sub hook_away {
184  if ($n_awayonce && $_[0] =~ /^\S+\s+(\S+)\s/) {
185    local($l)=$1;
186    $l =~ tr/A-Z/a-z/;
187    $silent=1 if $n_aways{$l} eq $_[0];
188    $n_aways{$l}=$_[0];
189  }
190}
191&addhook("301", "away");
192
193sub hook_whois {
194  if ($_[0] =~ /^\S+\s+(\S+)\s/) {
195    local($l)=$1;
196    $l =~ tr/A-Z/a-z/;
197    delete $n_aways{$l};
198  }
199}
200&addhook("311", "whois");
201
202# settings; create the $set{} variables with their default values here.
203
204sub set_autorejoin {
205 $set{'AUTOREJOIN'}="on", $n_autorejoin=1 if $_[0] =~ /^on$/i;
206 $set{'AUTOREJOIN'}="off", $n_autorejoin=0 if $_[0] =~ /^off$/i;
207}
208&addset("autorejoin");
209$set{"AUTOREJOIN"}="on";
210$n_autorejoin=1;
211&docommand("^alias rejoin set autorejoin");
212
213sub set_rejoinchannels {
214 $set{'REJOINCHANNELS'}="on", $n_rejoinchannels=1 if $_[0] =~ /^on$/i;
215 $set{'REJOINCHANNELS'}="off", $n_rejoinchannels=0 if $_[0] =~ /^off$/i;
216}
217&addset("rejoinchannels");
218$set{"REJOINCHANNELS"}="on";
219$n_rejoinchannels=1;
220&docommand("^alias rejoinchan set rejoinchannels");
221
222sub set_reconnect {
223 $set{'RECONNECT'}="on", $n_reconnect=1 if $_[0] =~ /^on$/i;
224 $set{'RECONNECT'}="off", $n_reconnect=0 if $_[0] =~ /^off$/i;
225}
226&addset("reconnect");
227$set{"RECONNECT"}="on";
228$n_reconnect=1;
229&docommand("^alias reconnect set reconnect");
230
231sub set_awayonce {
232 $set{'AWAYONCE'}="on", $n_awayonce=1 if $_[0] =~ /^on$/i;
233 $set{'AWAYONCE'}="off", $n_awayonce=0 if $_[0] =~ /^off$/i;
234 %n_awayonce=();
235}
236&addset("awayonce");
237$set{"AWAYONCE"}="on";
238$n_awayonce=1;
239&docommand("^alias awayonce set awayonce");
240
241sub set_slowserver {
242 $set{'SLOWSERVER'}="on", $n_slowserver=1 if $_[0] =~ /^on$/i;
243 $set{'SLOWSERVER'}="off", $n_slowserver=0 if $_[0] =~ /^off$/i;
244}
245&addset("slowserver");
246$set{"SLOWSERVER"}="off";
247$n_slowserver=0;
248&docommand("^alias ss set slowserver");
249
250sub set_wallv {
251  $set{"WALLV"}="on", $n_wallv=1 if $_[0] =~ /^on$/i;
252  $set{"WALLV"}="off", $n_wallv=0 if $_[0] =~ /^off$/i;
253}
254&addset("wallv");
255$set{"WALLV"}="off";
256$n_wallv=0;
257&docommand("^alias wallv set wallv");
258
259sub set_quitmsg {
260  $n_quitmsg=$set{"QUITMSG"}=$_[0];
261}
262&addset("quitmsg");
263$set{"QUITMSG"}=$n_quitmsg='';
264&docommand("^alias setquit set quitmsg");
265
266sub set_autoop {
267  $set{"AUTOOP"}="off", $n_autoops=0 if $_[0] =~ /^(off|none)$/i;
268  $set{"AUTOOP"}="on", $n_autoops=1 if $_[0] =~ /^(on|all)$/i;
269  $set{"AUTOOP"}="oppass", $n_autoops=2 if $_[0] =~ /^op(pass)?$/i;
270}
271&addset("autoop");
272$set{"AUTOOP"}="on";
273$n_autoops=1;
274&docommand("^alias autoop set autoop");
275
276sub set_opdelay {
277  $set{"OPDELAY"}=$n_opdelay=$_[0] if $_[0] =~ /^\d+$/;
278}
279&addset("opdelay");
280$set{"OPDELAY"}="on";
281$n_opdelay=5;
282&docommand("^alias delay set opdelay");
283
284sub set_oppass {
285  $set{"OPPASS"}=$_[0];
286}
287&addset("oppass");
288$set{"OPPASS"}="";
289&docommand("^alias oppass set oppass");
290
291# ignores
292
293sub cmd_ig {
294  &docommand("ignore $args"), return if (!$args || $args =~ /^-/);
295  &getarg;
296  if ($newarg =~ /\@/) {
297    $n_lastignore=$newarg;
298    &docommand("ignore $newarg");
299  } else {
300    &userhost($newarg, "\$host=&n_hostpat(\$host); \$user =~ s/^\\~//; \$n_lastignore=\"*\$user\\\@\$host\"; &docommand(\"ignore *\$user\\\@\$host\");");
301  }
302}
303&addcmd("ig");
304
305sub cmd_sig {
306  &getarg;
307  &userhost($newarg, "\$host=&n_hostpat(\$host); \$n_lastignore=\"*\\\@\$host\"; &docommand(\"ignore *\\\@\$host\");");
308}
309&addcmd("sig");
310
311sub cmd_unig {
312  &getarg;
313  if ($newarg eq '') {
314    &docommand("ignore -$n_lastignore") if $n_lastignore ne '';
315  } elsif ($newarg =~ /\@/) {
316    &docommand("ignore -$newarg");
317  } else {
318    &userhost($newarg, "\$host=&n_hostpat(\$host); \$user =~ s/^\\~//; &docommand(\"ignore -*\$user\\\@\$host\");");
319  }
320}
321&addcmd("unig");
322
323# bans and unbans
324
325sub n_hostpat {
326  if ($_[0] =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) {
327    return "${1}.${2}.${3}.*";
328  } elsif ($_[0] =~ /^([^. \t]+)\.([^. \t]+)\.(.*)$/) {
329    return "*.${2}.${3}";
330  } else {
331    return $_[0];
332  }
333}
334
335sub cmd_kb {
336  &getarg;
337  local($why)=($args);
338  $why="game over, man.  game over." unless $why;
339  &tell("*\cb0\cb* Must specify a nick to kickban"), return unless $newarg;
340  &tell("*\cb0\cb* You're not on a channel"), return unless $talkchannel;
341  &userhost($newarg, "\$host=&n_hostpat(\$host); \$user =~ s/^\\~//;
342&sl(\"MODE $talkchannel -o+b $newarg *!*\$user\\\@\$host\");
343&sl(\"KICK $talkchannel $newarg :$why\");");
344}
345&addcmd("kb");
346
347sub cmd_ksb {
348  &getarg;
349  local($why)=($args);
350  $why="d0rks suck big m00se ballZ" unless $why;
351  &tell("*\cb0\cb* Must specify a nick to kicksiteban"), return unless $newarg;
352  &tell("*\cb0\cb* You're not on a channel"), return unless $talkchannel;
353  &userhost($newarg, "\$host=&n_hostpat(\$host);
354&sl(\"MODE $talkchannel -o+b $newarg *!*\\\@\$host\");
355&sl(\"KICK $talkchannel $newarg :$why\");");
356}
357&addcmd("ksb");
358
359sub cmd_ban {
360  &tell("*\cb0\cb* Must specify a nick to ban"), return unless $args;
361  &tell("*\cb0\cb* You're not on a channel"), return unless $talkchannel;
362  while (&getarg, $newarg ne '') {
363    &userhost($newarg, "\$host=&n_hostpat(\$host); \$user =~ s/^\\~//;
364      &sl(\"MODE $talkchannel +b *!*\$user\\\@\$host\");");
365  }
366}
367&addcmd("ban");
368
369sub cmd_sban {
370  &getarg;
371  &tell("*\cb0\cb* Must specify a nick to site ban"), return unless $newarg;
372  &tell("*\cb0\cb* You're not on a channel"), return unless $talkchannel;
373  &userhost($newarg, "\$host=&n_hostpat(\$host);
374&sl(\"MODE $talkchannel +b *!*\\\@\$host\");");
375}
376&addcmd("sban");
377
378sub n_unbans {
379  local($n, $l)=('0', '');
380  foreach (@n0thing_banlist) {
381    if ($n<4) {
382      $l.=" ".$_;
383      $n++;
384    } else {
385      &sl("MODE $n0thing_channel -bbbb $l");
386      $l=$_;
387      $n=1;
388    }
389  }
390  &sl("MODE $n0thing_channel -".("b" x $n)." $l");
391}
392
393sub cmd_sb {
394  &dosplat;
395  &getarg;
396  $newarg=$talkchannel unless $newarg;
397  return unless $newarg;
398  $n_svbanchannel=$newarg;
399  @n_svbanlist=();
400  $n_nxbannb=1;
401  &sl("MODE $newarg b");
402}
403&addcmd("sb");
404
405sub hook_nbbans {
406  local($c, $theban, $by)=((split(/ +/, $_[0]))[1, 2, 3]);
407  if ($n_nxbannb && &eq($c, $n_svbanchannel)) {
408    push(@n_svbanlist, $theban);
409    &tell("*\cbb\cb* $c $n_nxbannb: $theban $by");
410    $silent=1;
411    $n_nxbannb++;
412  }
413}
414&addhook("367", "nbbans");
415
416sub hook_endofbans {
417  $n_nxbannb=0;
418}
419&addhook("368", "endofbans");
420
421sub cmd_cb {
422  &tell("*\cb0\cb* You're not on a channel"), return unless $talkchannel;
423  &addhook("367", "onecbban");
424  &addhook("368", "donebans");
425  @n0thing_banlist=();
426  $n0thing_channel=$talkchannel;
427  &sl("MODE $talkchannel b");
428}
429&addcmd("cb");
430
431sub hook_onecbban {
432  local($theban)=((split(/ +/, $_[0]))[2]);
433  push(@n0thing_banlist, $theban);
434  $silent=1;
435}
436
437sub hook_donebans {
438  &remhook("367", "onecbban");
439  &remhook("367", "oneubban");
440  &remhook("368", "donebans");
441  &n_unbans;
442}
443
444sub cmd_unban {
445  &getarg;
446  &tell("*\cb0\cb* Must specify a nick or address to unban"), return
447    unless $newarg;
448  &tell("*\cb0\cb* You're not on a channel"), return unless $talkchannel;
449  if ($newarg =~ /^\d+$/) {
450    $n0thing_channel=$talkchannel;
451    @n0thing_banlist=();
452    while(1) {
453      $newarg--;
454      &tell("*\cb0\cb* No banlist available for $talkchannel"), return
455	unless &eq($talkchannel, $n_svbanchannel);
456      &tell("*\cb0\cb* No such ban"), return unless $n_svbanlist[$newarg];
457      push(@n0thing_banlist, $n_svbanlist[$newarg]);
458      &getarg;
459      last unless $newarg;
460      &tell("*\cb0\cb* Cannot mix nicks and numbers"), last
461	unless $newarg =~ /^\d+$/;
462    }
463    &n_unbans;
464  } else {
465    @n0thing_banlist=();
466    $n0thing_channel=$talkchannel;
467    if ($newarg =~ /\@/) {
468      $newarg="*!".$newarg unless $newarg =~ /\!/;
469      $n_pat=$newarg;
470      &addhook("367", "oneubban");
471      &addhook("368", "donebans");
472      &sl("MODE $talkchannel b");
473    } else {
474      &userhost($newarg, "&n_dounban;");
475    }
476  }
477}
478&addcmd("unban");
479&docommand("^alias ub unban");
480
481sub n_dounban {
482  $n_pat=$who."!".$user."\@".$host;
483  &addhook("368", "donebans");
484  @n0thing_banlist=();
485  $n0thing_channel=$talkchannel;
486  &sl("MODE $talkchannel b");
487}
488
489sub hook_oneubban {
490  local($theban)=((split(/ +/, $_[0]))[2]);
491  local($tb0)=($theban);
492  &slashify($theban);
493  push(@n0thing_banlist, $tb0) if ($n_pat =~ /^${theban}$/i);
494  $silent=1;
495}
496
497sub cmd_fkb {
498  &getarg;
499  &tell("*\cb0\cb* Must specify a nick to filter kick ban"), return unless $newarg;
500  &tell("*\cb0\cb* You're not on a channel"), return unless $talkchannel;
501  &userhost($newarg, "\$host=&n_hostpat(\$host);
502&sl(\"MODE $talkchannel +b *!*\\\@\$host\"); &docommand(\"fk \$host $args\");");
503}
504&addcmd("fkb");
505
506
507sub cmd_fk {
508  &getarg;
509  &tell("*\cb0\cb* Must specify a pattern to kick"), return unless $newarg;
510  &tell("*\cb0\cb* You're not on a channel"), return unless $talkchannel;
511  $n0thing_channel=$talkchannel;
512  $n0thing_kickpat=$newarg;
513  &slashify($n0thing_kickpat);
514  $n0thing_kickmsg=$args || "though names may change each face retains the mask it wore";
515  &addhook("352", "dofklist");
516  &addhook("315", "donefk");
517  &sl("WHO $talkchannel");
518}
519&addcmd("fk");
520
521sub hook_dofklist {
522  local($a)=@_;
523  local($c, $c, $u, $h, $s, $n)=split(/ +/, $a);
524  (($n."!".$u."\@".$h) =~ /${n0thing_kickpat}/i) && $n ne $nick &&
525    &sl("KICK $n0thing_channel $n :$n0thing_kickmsg");
526  $silent=1;
527}
528
529sub hook_donefk {
530  &remhook("352", "dofklist");
531  &remhook("315", "donefk");
532}
533
534# the msg logger
535
536sub cmd_setaway {
537  &me("is away - $args - messages will be logged") if $talkchannel;
538  push(@n_savemsg, "-- set away on " . &date(time) . " -- $args");
539  %n_awaysent=();
540  $args="\cb\cb" if $args eq '';
541  &sl("AWAY :$args");
542  $n_isaway=1;
543}
544&addcmd("setaway");
545
546sub cmd_qsetaway {
547  push(@n_savemsg, "-- set away on " . &date(time) . " -- $args");
548  %n_awaysent=();
549  $args="\cb\cb" if $args eq '';
550  &sl("AWAY :$args");
551  $n_isaway=1;
552}
553&addcmd("qsetaway");
554
555sub hook_messages {
556  if ($n_isaway) {
557    local($sec, $min, $hour)=localtime(time);
558    local($w)=$who;
559    $min="0".$min if $min =~ /^\d$/;
560    push(@n_savemsg, ":\cb${who}\cb!${user}\@${host} (${hour}:${min}): $_[0]\n");
561    $w =~ tr/A-Z/a-z/;
562    &sl("NOTICE $who :Your messages are being logged - n0thing.pl"),
563      $n_awaysent{$w}=1 unless $n_awaysent{$w};
564  }
565}
566&addhook("msg", "messages");
567
568sub hook_dmessages {
569  if ($n_isaway) {
570    local($sec, $min, $hour)=localtime(time);
571    $min="0".$min if $min =~ /^\d$/;
572    push(@n_savemsg, "=\cb".$_[0]."\cb (${hour}:${min})= ".$_[1]."\n");
573  }
574}
575&addhook("dcc_chat", "dmessages");
576
577sub cmd_setback {
578  $n_isaway='';
579  &sl("AWAY");
580  foreach (@n_savemsg) {
581    &tell($_);
582  }
583  if ($#n_savemsg>0) {
584    &getuserline("*** Forget saved messages (y/n)? ", "clear? ");
585    @n_savemsg=() if /^y/i;
586  } else {
587    @n_savemsg=();
588  }
589}
590&addcmd("setback");
591
592sub cmd_clearmes {
593  $n_isaway='';
594  @n_savemsg=();
595}
596&addcmd("clearmes");
597
598# wallops
599
600sub cmd_wall {
601  &tell("*\cbE\cb* No text to send"), return unless $args;
602  &tell("*\cbE\cb* You're not on a channel"), return unless $talkchannel;
603  $wallop_text=$args;
604  $wallop_channel=$talkchannel;
605  &addhook("353", "wallopnames");
606  &sl("NAMES $talkchannel");
607}
608&addcmd("wall");
609
610sub hook_wallopnames {
611  local($wallop, $n, $s, @wallop)=("", 0, 0, split(/ +/, $_[0]));
612  shift @wallop; shift @wallop; shift @wallop;
613  $wallop[0] =~ s/^://;
614  foreach (@wallop) {
615    $wallop.=$_.",", $n++ if s/^\@// || ($n_wallv && s/^\+//) || &eq($_, $nick);
616    if ($n>=9) {
617      $wallop =~ s/,$//;
618      &sl("NOTICE $wallop :\cb[WallOp/$wallop_channel]\cb $wallop_text");
619      $n=0;
620      $s=1;
621      $wallop='';
622    }
623  }
624  if ($wallop eq '' && !$s) {
625    &tell("*\cbE\cb* No ops to wallop");
626  } elsif ($wallop ne '') {
627    $wallop =~ s/,$//;
628    &sl("NOTICE $wallop :\cb[WallOp/$wallop_channel]\cb $wallop_text");
629  }
630  &remhook("353", "wallopnames");
631  $silent=1;
632}
633
634
635# the autoop list, with fully-featured delayed and grouped auto-ops
636
637sub n_addwaitop {
638  local($nck, $channel)=@_;
639  if ($n_opdelay) {
640    local($n)=($nck);
641    $channel =~ tr/A-Z/a-z/;
642    $n =~ s/(\W)/\\$1/g;
643    if ($n_waitops{$channel} !~ /:${n}:/i) {
644      $n_waitops{$channel} || ($n_waitops{$channel}=":");
645      $n_waitops{$channel}.=$nck.":";
646    }
647    unless ($n_timerdue) {
648      $n_timerdue=1;
649      &timer($n_opdelay, "&n_doautoops");
650    }
651  } else {
652    &sl("MODE $channel +o $nck");
653  }
654}
655
656sub n_remwaitop {
657  local($nck, $channel)=@_;
658  $channel =~ tr/A-Z/a-z/;
659  $nck =~ s/(\W)/\\$1/g;
660  $n_waitops{$channel} =~ s/:${nck}:/:/gi;
661  delete $n_waitops{$channel} if $n_waitops{$channel} eq ":";
662}
663
664sub n_doautoops {
665  local($l);
666  foreach $c (keys(%n_waitops)) {
667    if ($n_waitops{$c} ne ":" && $n_waitops{$c}) {
668      $l=$n_waitops{$c};
669      $l =~ s/^://;
670      $l =~ s/:$//;
671      $l =~ tr/:/ /;
672      &docommand("o ".$c." ".$l);
673    }
674    delete $n_waitops{$c};
675  }
676  $n_timerdue='';
677}
678
679sub hook_n_nickchange {
680  local($oldnick)=$who;
681  $oldnick =~ s/(\W)/\\$1/g;
682  foreach $c (keys(%n_waitops)) {
683    $n_waitops{$c} =~ s/:${oldnick}:/:$_[0]:/gi;
684  }
685}
686&addhook("nick", "n_nickchange");
687
688sub hook_n_parted {
689  &n_remwaitop($who, $_[0]);
690}
691&addhook("leave", "n_parted");
692
693sub hook_n_quitted {
694  local($w)=$who;
695  $w =~ s/(\W)/\\$1/g;
696  foreach $c (keys(%n_waitops)) {
697    $n_waitops{$c} =~ s/:${w}:/:/gi;
698    delete $n_waitops{$c} if $n_waitops{$c} eq ":";
699  }
700}
701&addhook("signoff", "n_quitted");
702
703sub hook_n_modechange {
704# we only deal with +o, +oo and the like; the worst that can happen
705# is that we op someone again
706  local ($l)=$_[1];
707  return unless $_[0] =~ /^[\#\&\+]/;
708  return unless $l =~ s/^\+o+\s+//;
709  foreach $n (split(/ /, $l)) {
710    &n_remwaitop($n, $_[0]);
711  }
712}
713&addhook("mode", "n_modechange");
714
715sub slashify {
716  $_[0] =~ s/([^\\])\./$1\\./g;
717  $_[0] =~ s/\*/\.\*/g;
718  $_[0] =~ s/([^\.\*\?\\\w])/\\$1/g;
719  $_[0] =~ tr/?/./;
720}
721
722# format of the entries in @n_autooplist :
723# asked:channel:nick!user@host  in regexp format; asked is '.' or '1',
724# channel is '.*' or a #channel name
725
726sub autoopped {
727  local($nuh, $chan, $asked)=@_;
728# chan = what chan for, $asked = whether it was asked
729  local($p);
730  foreach $p (@n_autooplist) {
731    return 1 if ($asked.":".$chan.":".$nuh) =~ /^${p}$/i;
732  }
733  return '';
734}
735
736sub addtoops {
737  local($chan, $auto)=@_;
738  if (&autoopped($who."!".$user."\@".$host, $chan, 1)) {
739    &tell("*\cb0\cb* $who is already on your list");
740  } else {
741    $host=&n_hostpat($host);
742    $user =~ s/^\~//;
743    local($pat)=("*!*".$user."\@".$host);
744    &tell("*\cb0\cb* Adding $who as $pat to your autoop list for $chan");
745    &sl("NOTICE $who :You have been added to ${nick}'s autoop list for ".
746      ($chan eq '*' ? "all channels" : "$chan"));
747    &sl("NOTICE $who :You should feel *very* honored");
748    &slashify($pat);
749    &slashify($chan);
750    push(@n_autooplist, $auto.":".$chan.":".$pat);
751  }
752}
753
754sub cmd_addop {
755  if ($args =~ /^([01])\s+(\S+)\s+(\S+)\s*$/) {
756    local($auto, $chan, $uh)=($1, $2, $3);
757    if ($chan ne '*' && $chan !~ /^[#&]/) {
758      &tell("*\cbE\cb* Invalid channel - use '*' or a #channel name");
759      return;
760    }
761    $chan =~ s/\'//g;
762    $uh="*!".$uh if $uh =~ /\@/ && $uh !~ /\!/;
763    $auto=($auto==0 ? "1" : ".");
764    if ($uh =~ /\!.*\@/) {
765      if (&autoopped($uh, $chan, 1)) {
766	&tell("*\cb0\cb* $uh is already on your list");
767	return;
768      }
769      &tell("*\cb0\cb* Adding $uh to your auto-op list for $chan");
770      &slashify($uh);
771      &slashify($chan);
772      push(@n_autooplist, $auto.":".$chan.":".$uh);
773    } else {
774      &userhost($uh, "&addtoops('$chan', '$auto');");
775    }
776  } else {
777    &tell("*\cb0\cb* Format: /addop (0 or 1) (#chan or *) (nick or user\@host)");
778  }
779}
780&addcmd("addop");
781
782sub hook_joined {
783  local($c)=($_[0]);
784  $c =~ tr/A-Z/a-z/;
785  &n_addwaitop($who, $c) if ($n_autoops==1 && $haveops{$c} &&
786			     &autoopped($who."!".$user."\@".$host, $c, 0));
787}
788&addhook("join", "joined");
789
790sub hook_opbeg {
791  if ($_[1] =~ /^op$/i && $n_autoops && &eq($nick, $_[0])) {
792    local($chn, $pass)=split(/ +/, $_[2]);
793    $chn =~ tr/A-Z/a-z/;
794    &sl("MODE $chn +o $who")
795      if $haveops{$chn} && $pass eq $set{"OPPASS"} &&
796			&autoopped($who."!".$user."\@".$host, $chn, 1);
797  }
798}
799&addhook("ctcp", "opbeg");
800
801sub cmd_listop {
802  local($n, $p, $q, $c, $a, $ch)=(0);
803  &getarg;
804  $ch=$newarg || '*';
805  &tell("*\cb0\cb* That's the people in your autoop list:");
806  foreach $p (@n_autooplist) {
807    ($a, $c, $q)=split(/:/, $p);
808    $c =~ s/\\//g;
809    $c =~ s/\.\*/*/g;
810    next if (!&eq($c, $ch) && $c ne '*' && $ch ne '*');
811    $n++;
812    $q =~ s/\\//g;
813    $q =~ s/\.\*/*/g;
814    &tell("*\cb0\cb* ".($a eq '.' ? "1 " : "0 ").$c." ".$q);
815  }
816  &tell("*\cb0\cb* which makes.. uhm... $n people, I think");
817}
818&addcmd("listop");
819
820sub rem_matches {
821  local($nuh, $ent)=@_;
822  $ent=$' if $ent =~ /:.*:/;
823  return 1 if $nuh =~ /${ent}$/i;
824  # not exactly the same as slashify
825  $nuh =~ s/\*/\.\*/g;
826  $nuh =~ s/([^\\])\.([^\*])/$1\\\\*\\.$2/g;
827  $nuh =~ s/([^\.\*\?\\\w])/\\\\*\\$1/g;
828  $nuh =~ tr/?/./;
829  return ($ent =~ /${nuh}$/i);
830}
831
832sub n_remop {
833  local($nuh)=($who."!".$user."\@".$host);
834  @n_autooplist=grep(!&rem_matches($nuh, $_), @n_autooplist);
835}
836
837sub cmd_remop {
838  &getarg;
839  if (!$newarg) {
840    &tell("*\cb0\cb* Must specify a nick or address");
841  } elsif ($newarg =~ /[\@\*]/) {
842    # $newarg='*!'.$newarg if ($newarg !~ /\!/);
843    &tell("*\cb0\cb* Time to remove $newarg from the autoop list");
844    @n_autooplist=grep(!&rem_matches($newarg, $_), @n_autooplist);
845  } else {
846    &tell("*\cb0\cb* Time to remove $newarg from the autoop list");
847    &userhost($newarg, "&n_remop;");
848  }
849}
850&addcmd("remop");
851
852sub cmd_clearop {
853  @n_autooplist=();
854  &tell("*\cb0\cb* Auto-op list cleared!");
855}
856&addcmd("clearop");
857
858# saving the settings
859
860sub cmd_sve {
861  local($p);
862  if (!open(SVE, "> ".$n_svefile)) {
863    &tell("*\cbE\cb* can't write to save file");
864    return;
865  }
866  # old-style stuff for compatibility with old n0things
867  print SVE $n_autoops+0, "\n";
868  print SVE ($n_autorejoin ? "1" : "0"), "\n";
869  print SVE "\n";	# deprecated, pong reply
870  print SVE $set{"FINGER"}, "\n";
871  print SVE join(" ", keys(%notify)), "\n";
872  print SVE join(" ", @n_autooplist), "\n";
873  print SVE ($n_slowserver ? "1" : "0"), "\n";
874  print SVE $n_opdelay, "\n";
875  print SVE $n_quitmsg, "\n";
876  print SVE "^\n";	# deprecated, command char
877  print SVE ($n_reconnect ? "1" : "0"), "\n";
878  # and new-style saves
879  print SVE $set{"AWAYONCE"}, "\n";
880  print SVE $set{"REJOINCHANNELS"}, "\n";
881  print SVE $set{"CTCP"}, "\n";
882  print SVE $set{"PRINTCHAN"}, "\n";
883  print SVE $set{"PRINTUH"}, "\n";
884  print SVE $set{"SENDAHEAD"}, "\n";
885  print SVE $set{"USERINFO"}, "\n";
886  print SVE $set{"WALLV"}, "\n";
887  print SVE $set{"OPPASS"}, "\n";
888  print SVE $set{"IRCNAME"}, "\n";
889  close SVE;
890  &tell("*\cb0\cb* save completed!");
891}
892&addcmd("sve");
893
894sub cmd_quit {
895  if ($args eq '') {
896    &docommand("/QUIT $n_quitmsg");
897  } else {
898    &docommand("/QUIT $args");
899  }
900}
901&addcmd("quit");
902&docommand("^alias bye quit");
903&docommand("^alias exit quit");
904&docommand("^alias signoff quit");
905
906# some online help
907
908sub cmd_nhelp {
909  &docommand("help n0thing".$args);
910}
911&addcmd("nhelp");
912
913&addhelp("n0thing", "This is \cbn0thing.pl\cb for sirc, by \cborabidoo\cb
914
915For the list of n0thing.pl's general functions, type /nhelp general
916For the list of n0thing.pl's channel functions, type /nhelp channel
917For the list of n0thing.pl's file functions, type /nhelp files
918For the list of n0thing.pl's settings, type /nhelp settings
919
920Arguments between []'s are always optional.
921
922For comments, bug reports, ideas:  email roger.espel.llima\@pobox.com");
923
924&addhelp("n0thinggeneral", "List of \cbn0thing.pl\cb's functions:
925
926/a <message>            sends to the last person you /msg'd
927/ver <nick>             gets version info about <nick>
928/tim <nick>             gets <nick>'s local time
929/setaway <reason>       sets yourself away, logs messages
930/qsetaway <reason>      like /setaway without doing the /me
931/setback                sets yourself back, shows messages
932/clearmes               erases saved messages
933/ig <nick>              ignores <nick> (using a user\@host mask)
934/sig <nick>             ignores <nick>'s site
935/unig [nick]            unignores <nick> or undoes your last /ig
936/sve                    saves your settings and auto-op and notify list");
937
938&addhelp("n0thingchannel", "List of \cbn0thing.pl\cb's channel functions:
939
940/sb [<channel>]         shows ban list on a channel [current one]
941/ban <nick> [<nick>...] bans on current channel
942/sban <nick>            bans the whole site on current channel
943/ub <nick>|<address>    unbans on current channel
944/ub <number> [<nmbr>..] removes bans by number after a /sb
945/cb                     clears all bans on current channel
946/l                      short list of people on the current channel
947/pj                     part and rejoin current channel
948/open [<channel>]       removes weird modes on the channel [current one]
949/kb <nick> [<reason>]   kicks and bans
950/ksb <nick> [<reason>]  kicks and site-bans
951/fk <filter> [<reasn>]  kicks all users matching the filter
952/fkb <nick> [<reasn>]   site-bans and kicks all users from the same site
953/wall <msg>             send a message to the current channel's ops");
954
955&addhelp("n0thingsettings",
956"List of \cbn0thing.pl\cb's SET variables:
957autorejoin [on|off]     toggles auto-rejoin on kick
958rejoinchannels [on|off] toggles rejoining channels on reconnect
959reconnect [on|off]      toggles auto-reconnect
960awayonce [on|off]       toggles hiding duplicate away messages
961slowserver [on|off]     toggles avoiding userhost on notify
962wallv [on|off]          toggles sending walls to +v people
963autoop [on|oppass|off]  toggle autoops (oppass requires a ctcp op w/ the
964                        channel name and a password)
965oppass <password>       toggles your opbeg password
966quitmsg <message>       sets your default /quit message
967
968List of \cbn0thing.pl\cb's setting-related commands:
969/addop <aop> #chn <user> adds to op list; aop is 0 or 1; #chn can be *
970/remop <nick>|<address> removes user from your auto-op list
971/clearop                clears your auto-op list
972/listop [#chn]          lists your auto-op list [for channel #chn]
973/delay			sets your auto-op delay
974/sve                    saves your settings and auto-op and notify list");
975
976&addhelp("n0thingfiles", "List of \cbn0thing.pl\cb's file-oriented functions:
977/dc [<nick>]            starts a dcc chat [last offered]
978/dg [<nick>] [<file>]   gets a file via dcc [last offered]
979/ds <nick> <file>       sends a file via dcc
980/cdc <nick>             closes a /dcc chat
981/cds <nick>             closes a /dcc send connection
982/cdg <nick>             closes a /dcc get connection
983/rdc <nick1> <nick2>    renames a /dcc chat
984/ex <command>           \"shortcut\" for /system
985/ls [<args>]            lists files
986/cat <files>            shows files
987/rm <files>             deletes files
988/ps <options>           lists processes
989/mail                   reads your mail  (you'll get disconnected from the
990                        server if this takes more than a few minutes; exit
991                        with 'q')");
992
993# reading the saved settings
994
995if (open(NOTHING, "< ".$n_svefile)) {
996  local($n, $l);
997
998  chop($l=<NOTHING>);
999  &doset("AUTOOP", ($l ? "on" : "off"));
1000
1001  chop($l=<NOTHING>);
1002  &doset("AUTOREJOIN", ($l ? "on" : "off"));
1003
1004  <NOTHING>;
1005
1006  chop($l=<NOTHING>);
1007  &doset("FINGER", $l) if $l ne '';
1008
1009  chop($l=<NOTHING>);
1010  %notify=();
1011  foreach $n (split(' ', $l)) {
1012    &docommand("^NOTIFY ".$n);
1013  }
1014
1015  chop($l=<NOTHING>);
1016  @n_autooplist=split(' ', $l);
1017  foreach (@n_autooplist) {
1018    $_=".:.*:".$_ unless /:.*:/;
1019  }
1020
1021  chop($l=<NOTHING>);
1022  &doset("SLOWSERVER", ($l ? "on" : "off"));
1023
1024  chop($l=<NOTHING>);
1025  $l=5 if $l !~ /^\d+$/;
1026  &doset("OPDELAY", $l);
1027
1028  chop($l=<NOTHING>);
1029  &doset("QUITMSG", $l);
1030
1031  <NOTHING>;
1032
1033  chop($l=<NOTHING>);
1034  $l=1 unless defined $l;
1035  &doset("RECONNECT", ($l ? "on" : "off"));
1036
1037  chop($l=<NOTHING>);
1038  &doset("AWAYONCE", $l) if $l;
1039
1040  chop($l=<NOTHING>);
1041  &doset("REJOINCHANNELS", $l) if $l;
1042
1043  chop($l=<NOTHING>);
1044  &doset("CTCP", $l) if $l;
1045
1046  chop($l=<NOTHING>);
1047  &doset("PRINTCHAN", $l) if $l;
1048
1049  chop($l=<NOTHING>);
1050  &doset("PRINTUH", $l) if $l;
1051
1052  chop($l=<NOTHING>);
1053  &doset("SENDAHEAD", $l) if $l;
1054
1055  chop($l=<NOTHING>);
1056  &doset("USERINFO", $l) if $l;
1057
1058  chop($l=<NOTHING>);
1059  &doset("WALLV", $l) if $l;
1060
1061  chop($l=<NOTHING>);
1062  &doset("OPPASS", $l) if $l;
1063
1064  chop($l=<NOTHING>);
1065  &doset("IRCNAME", $l) if $l;
1066
1067  close(NOTHING);
1068}
1069
1070&print("*\cb0\cb* \cborabidoo\cb's *\cvn0thing.pl\cv* for sirc loaded, type /nhelp for help");
1071
1072