]> git.donarmstrong.com Git - infobot.git/blob - src/UserExtra.pl
* Rename of insertDB.pl to factpack.pl
[infobot.git] / src / UserExtra.pl
1 #
2 # UserExtra.pl: User Commands, Public.
3 #       Author: dms
4 #
5
6 use strict;
7 use vars qw($message $arg $qWord $verb $lobotomized $who $result $chan
8   $conn $msgType $query $talkchannel $ident $memusage);
9 use vars qw(%channels %chanstats %cmdstats %count %forked %ircstats %param
10   %cache %mask %userstats);
11
12 ### hooks get added in CommandHooks.pl.
13
14 ###
15 ### Start of commands for hooks.
16 ###
17
18 sub chaninfo {
19     my $chan = lc shift(@_);
20     my $mode;
21
22     if ( $chan eq '' ) {    # all channels.
23         my $i = keys %channels;
24         my $reply = "I'm on \002$i\002 " . &fixPlural( 'channel', $i );
25         my $tucount = 0;    # total user count.
26         my $uucount = 0;    # unique user count.
27         my %chans;
28         my @array;
29
30         ### line 1.
31         foreach ( keys %channels ) {
32             if ( /^\s*$/ or / / ) {
33                 &status('chanstats: fe channels: chan == NULL.');
34
35                 #&ircCheck();
36                 next;
37             }
38             next if (/^_default$/);
39
40             $chans{$_} = scalar( keys %{ $channels{$_}{''} } );
41         }
42         foreach $chan ( sort { $chans{$b} <=> $chans{$a} } keys %chans ) {
43             push( @array, "$chan/" . $chans{$chan} );
44         }
45         &performStrictReply( $reply . ': ' . join( ', ', @array ) );
46
47         ### total user count.
48         foreach $chan ( keys %channels ) {
49             $tucount += scalar( keys %{ $channels{$chan}{''} } );
50         }
51
52         ### unique user count.
53         my %nicks = ();
54         foreach $chan ( keys %channels ) {
55             my $nick;
56             foreach $nick ( keys %{ $channels{$chan}{''} } ) {
57                 $nicks{$nick}++;
58             }
59         }
60         $uucount = scalar( keys %nicks );
61
62         my $chans = scalar( keys %channels );
63         &performStrictReply( "i've cached \002$tucount\002 "
64               . &fixPlural( 'user', $tucount )
65               . ", \002$uucount\002 unique "
66               . &fixPlural( 'user', $uucount )
67               . ", distributed over \002$chans\002 "
68               . &fixPlural( 'channel', $chans )
69               . '.' );
70         &ircCheck();
71
72         return;
73     }
74
75     # channel specific.
76
77     if ( &validChan($chan) == 0 ) {
78         &msg( $who, "error: invalid channel \002$chan\002" );
79         return;
80     }
81
82     # Step 1:
83     my @array;
84     foreach ( sort keys %{ $chanstats{$chan} } ) {
85         my $int = $chanstats{$chan}{$_};
86         next unless ($int);
87
88         push( @array, "\002$int\002 " . &fixPlural( $_, $int ) );
89     }
90     my $reply =
91         "On \002$chan\002, there "
92       . &fixPlural( 'has', scalar(@array) )
93       . ' been '
94       . &IJoin(@array);
95
96     # Step 1b: check channel inconstencies.
97     $chanstats{$chan}{'Join'}    ||= 0;
98     $chanstats{$chan}{'SignOff'} ||= 0;
99     $chanstats{$chan}{'Part'}    ||= 0;
100
101     my $delta_stats = $chanstats{$chan}{'Join'} - $chanstats{$chan}{'SignOff'} -
102       $chanstats{$chan}{'Part'};
103
104     if ($delta_stats) {
105         my $total = scalar( keys %{ $channels{$chan}{''} } );
106         &status(
107             "chaninfo: join ~= signoff + part (drift of $delta_stats < $total)."
108         );
109
110         if ( $delta_stats > $total ) {
111             &ERROR('chaninfo: delta_stats exceeds total users.');
112         }
113     }
114
115     # Step 2:
116     undef @array;
117     my $type;
118     foreach ( 'v', 'o', '' ) {
119         my $int = scalar( keys %{ $channels{$chan}{$_} } );
120         next unless ($int);
121
122         $type = 'Voice' if ( $_ eq 'v' );
123         $type = 'Opped' if ( $_ eq 'o' );
124         $type = 'Total' if ( $_ eq '' );
125
126         push( @array, "\002$int\002 $type" );
127     }
128     $reply .= '.  At the moment, ' . &IJoin(@array);
129
130     # Step 3:
131     my %new;
132     foreach ( keys %userstats ) {
133         next unless ( exists $userstats{$_}{'Count'} );
134         if ( $userstats{$_}{'Count'} =~ /^\D+$/ ) {
135             &WARN("userstats{$_}{Count} is non-digit.");
136             next;
137         }
138
139         $new{$_} = $userstats{$_}{'Count'};
140     }
141
142     # TODO: show top 3 with percentages?
143     my ($count) = ( sort { $new{$b} <=> $new{$a} } keys %new )[0];
144     if ($count) {
145         $reply .=
146 ".  \002$count\002 has said the most with a total of \002$new{$count}\002 messages";
147     }
148     &performStrictReply("$reply.");
149 }
150
151 # Command statistics.
152 sub cmdstats {
153     my @array;
154
155     if ( !scalar( keys %cmdstats ) ) {
156         &performReply('no-one has run any commands yet');
157         return;
158     }
159
160     my %countstats;
161     foreach ( keys %cmdstats ) {
162         $countstats{ $cmdstats{$_} }{$_} = 1;
163     }
164
165     foreach ( sort { $b <=> $a } keys %countstats ) {
166         my $int = $_;
167         next unless ($int);
168
169         foreach ( keys %{ $countstats{$int} } ) {
170             push( @array, "\002$int\002 of $_" );
171         }
172     }
173     &performStrictReply( 'command usage include ' . &IJoin(@array) . '.' );
174 }
175
176 # Factoid extension info. xk++
177 sub factinfo {
178     my $faqtoid = lc shift(@_);
179     my $query   = '';
180
181     if ( $faqtoid =~ /^\-(\S+)(\s+(.*))$/ ) {
182         &msg( $who,
183             'error: individual factoid info queries not supported as yet.' );
184         &msg( $who,
185             "it's possible that the factoid mistakenly begins with '-'." );
186         return;
187
188         $query   = lc $1;
189         $faqtoid = lc $3;
190     }
191
192     &CmdFactInfo( $faqtoid, $query );
193 }
194
195 sub factstats {
196     my $type = shift(@_);
197
198     &Forker(
199         'Factoids',
200         sub {
201             &performStrictReply( &CmdFactStats($type) );
202         }
203     );
204 }
205
206 sub karma {
207     my $target = lc( shift || $who );
208     my $karma =
209       &sqlSelect( 'stats', 'counter', { nick => $target, type => 'karma' } )
210       || 0;
211
212     if ( $karma != 0 ) {
213         &performStrictReply("$target has karma of $karma");
214     }
215     else {
216         &performStrictReply("$target has neutral karma");
217     }
218 }
219
220 sub tell {
221     my $args = shift;
222     my ( $target, $tell_obj ) = ( '', '' );
223     my $dont_tell_me = 0;
224     my $reply;
225
226     ### is this fixed elsewhere?
227     $args =~ s/\s+/ /g;         # fix up spaces.
228     $args =~ s/^\s+|\s+$//g;    # again.
229
230     # this one catches most of them
231     if ( $args =~ /^(\S+) (-?)about (.*)$/i ) {
232         $target       = $1;
233         $tell_obj     = $3;
234         $dont_tell_me = ($2) ? 1 : 0;
235
236         $tell_obj = $who if ( $tell_obj =~ /^(me|myself)$/i );
237         $query = $tell_obj;
238     }
239     elsif ( $args =~ /^(\S+) where (\S+) can (\S+) (.*)$/i ) {
240
241         # i'm sure this could all be nicely collapsed
242         $target   = $1;
243         $tell_obj = $4;
244         $query    = $tell_obj;
245
246     }
247     elsif ( $args =~ /^(\S+) (what|where) (.*?) (is|are)[.?!]*$/i ) {
248         $target   = $1;
249         $qWord    = $2;
250         $tell_obj = $3;
251         $verb     = $4;
252         $query    = "$qWord $verb $tell_obj";
253
254     }
255     elsif ( $args =~ /^(.*?) to (\S+)$/i ) {
256         $target   = $3;
257         $tell_obj = $2;
258         $query    = $tell_obj;
259     }
260
261     # check target type. Deny channel targets.
262     if ( $target !~ /^$mask{nick}$/ or $target =~ /^$mask{chan}$/ ) {
263         &msg( $who, "No, $who, I won't. (target invalid?)" );
264         return;
265     }
266
267     $target = $talkchannel if ( $target =~ /^us$/i );
268     $target = $who         if ( $target =~ /^(me|myself)$/i );
269
270     &status("tell: target = $target, query = $query");
271
272     # 'intrusive'.
273     #    if ($target !~ /^$mask{chan}$/ and !&IsNickInAnyChan($target)) {
274     #   &msg($who, "No, $target is not in any of my chans.");
275     #   return;
276     #    }
277
278     # self.
279     if ( $target =~ /^\Q$ident\E$/i ) {
280         &msg( $who, "Isn't that a bit silly?" );
281         return;
282     }
283
284     my $oldwho   = $who;
285     my $oldmtype = $msgType;
286     $who = $target;
287     my $result = &doQuestion($tell_obj);
288
289     # ^ returns '0' if nothing was found.
290     $who = $oldwho;
291
292     # no such factoid.
293     if ( !defined $result || $result =~ /^0?$/ ) {
294         $who     = $target;
295         $msgType = 'private';
296
297         # support command redirection.
298         # recursive cmdHooks aswell :)
299         my $done = 0;
300         $done++ if &parseCmdHook($tell_obj);
301         $message = $tell_obj;
302         $done++ unless ( &Modules() );
303
304         &VERB( 'tell: setting old values of who and msgType.', 2 );
305         $who     = $oldwho;
306         $msgType = $oldmtype;
307
308         if ($done) {
309             &msg( $who, "told $target about CMD '$tell_obj'" );
310         }
311         else {
312             &msg( $who, "i dunno what is '$tell_obj'." );
313         }
314
315         return;
316     }
317
318     # success.
319     &status("tell: <$who> telling $target about $tell_obj.");
320     if ( $who ne $target ) {
321         if ($dont_tell_me) {
322             &msg( $who, "told $target about $tell_obj." );
323         }
324         else {
325             &msg( $who, "told $target about $tell_obj ($result)" );
326         }
327
328         $reply = "$who wants you to know: $result";
329     }
330     else {
331         $reply = "telling yourself: $result";
332     }
333
334     &msg( $target, $reply );
335 }
336
337 sub countryStats {
338     if ( exists $cache{countryStats} ) {
339         &msg( $who, 'countrystats is already running!' );
340         return;
341     }
342
343     if ( $chan eq '' ) {
344         $chan = $_[0];
345     }
346
347     if ( $chan eq '' ) {
348         &help('countrystats');
349         return;
350     }
351
352     $conn->who($chan);
353     $cache{countryStats}{chan}  = $chan;
354     $cache{countryStats}{mtype} = $msgType;
355     $cache{countryStats}{who}   = $who;
356     $cache{on_who_Hack}         = 1;
357 }
358
359 sub do_countrystats {
360     $chan    = $cache{countryStats}{chan};
361     $msgType = $cache{countryStats}{mtype};
362     $who     = $cache{countryStats}{who};
363
364     my $total = 0;
365     my %cstats;
366     foreach ( keys %{ $cache{nuhInfo} } ) {
367         my $h = $cache{nuhInfo}{$_}{Host};
368
369         if ( $h =~ /^.*\.(\D+)$/ ) {    # host
370             $cstats{$1}++;
371         }
372         else {                          # ip
373             $cstats{unresolve}++;
374         }
375         $total++;
376     }
377     my %count;
378     foreach ( keys %cstats ) {
379         $count{ $cstats{$_} }{$_} = 1;
380     }
381
382     my @list;
383     foreach ( sort { $b <=> $a } keys %count ) {
384         my $str = join( ', ', sort keys %{ $count{$_} } );
385
386         #       push(@list, "$str ($_)");
387         my $perc = sprintf( '%.01f', 100 * $_ / $total );
388         $perc =~ s/\.0+$//;
389         push( @list, "$str ($_, $perc %)" );
390     }
391
392     # TODO: move this into a scheduler
393     $msgType = 'private';
394     &performStrictReply( &formListReply( 0, 'Country Stats ', @list ) );
395
396     delete $cache{countryStats};
397     delete $cache{on_who_Hack};
398 }
399
400 ###
401 ### amalgamated commands.
402 ###
403
404 sub userCommands {
405
406     # conversion: ascii.
407     if ( $message =~ /^(asci*|chr) (\d+)$/ ) {
408         &DEBUG('ascii/chr called ...');
409         return unless ( &IsChanConfOrWarn('allowConv') );
410
411         &DEBUG('ascii/chr called');
412
413         $arg    = $2;
414         $result = chr($arg);
415         $result = 'NULL' if ( $arg == 0 );
416
417         &performReply( sprintf( "ascii %s is '%s'", $arg, $result ) );
418
419         return;
420     }
421
422     # conversion: ord.
423     if ( $message =~ /^ord(\s+(.*))$/ ) {
424         return unless ( &IsChanConfOrWarn('allowConv') );
425
426         $arg = $2;
427
428         if ( !defined $arg or length $arg != 1 ) {
429             &help('ord');
430             return;
431         }
432
433         if ( ord($arg) < 32 ) {
434             $arg = chr( ord($arg) + 64 );
435             if ( $arg eq chr(64) ) {
436                 $arg = 'NULL';
437             }
438             else {
439                 $arg = '^' . $arg;
440             }
441         }
442
443         &performReply( sprintf( "'%s' is ascii %s", $arg, ord $arg ) );
444         return;
445     }
446
447     # hex.
448     if ( $message =~ /^hex(\s+(.*))?$/i ) {
449         return unless ( &IsChanConfOrWarn('allowConv') );
450         my $arg = $2;
451
452         if ( !defined $arg ) {
453             &help('hex');
454             return;
455         }
456
457         if ( length $arg > 80 ) {
458             &msg( $who, 'Too long.' );
459             return;
460         }
461
462         my $retval;
463         foreach ( split //, $arg ) {
464             $retval .= sprintf( ' %X', ord($_) );
465         }
466
467         &performStrictReply("$arg is$retval");
468
469         return;
470     }
471
472     # crypt.
473     if ( $message =~ /^crypt\s+(\S*)?\s*(.*)?$/i ) {
474         &status("crypt: $1:$2:$3");
475         if ( "$2" ne '' ) {
476             &performStrictReply( crypt( $2, $1 ) );
477         }
478         else {
479             &performStrictReply( &mkcrypt($1) );
480         }
481         return;
482     }
483
484     # cycle.
485     if ( $message =~ /^(cycle)(\s+(\S+))?$/i ) {
486         return unless ( &hasFlag('o') );
487         my $chan = lc $3;
488
489         if ( $chan eq '' ) {
490             if ( $msgType =~ /public/ ) {
491                 $chan = $talkchannel;
492                 &DEBUG("cycle: setting chan to '$chan'.");
493             }
494             else {
495                 &help('cycle');
496                 return;
497             }
498         }
499
500         if ( &validChan($chan) == 0 ) {
501             &msg( $who, "error: invalid channel \002$chan\002" );
502             return;
503         }
504
505         &msg( $chan, "I'm coming back. (courtesy of $who)" );
506         &part($chan);
507 ###     &ScheduleThis(5, 'getNickInUse') if (@_);
508         &status("Schedule rejoin in 5secs to $chan by $who.");
509         $conn->schedule( 5, sub { &joinchan($chan); } );
510
511         return;
512     }
513
514     # reload.
515     if ( $message =~ /^reload$/i ) {
516         return unless ( &hasFlag('n') );
517
518         &status("USER reload $who");
519         &performStrictReply('reloading...');
520         my $modules = &reloadAllModules();
521         &performStrictReply("reloaded:$modules");
522         return;
523     }
524
525     # redir.
526     if ( $message =~ /^redir(\s+(.*))?/i ) {
527         return unless ( &hasFlag('o') );
528         my $factoid = $2;
529
530         if ( !defined $factoid ) {
531             &help('redir');
532             return;
533         }
534
535         my $val = &getFactInfo( $factoid, 'factoid_value' );
536         if ( !defined $val or $val eq '' ) {
537             &msg( $who, "error: '$factoid' does not exist." );
538             return;
539         }
540         &DEBUG("val => '$val'.");
541         my @list =
542           &searchTable( 'factoids', 'factoid_key', 'factoid_value', "^$val\$" );
543
544         if ( scalar @list == 1 ) {
545             &msg( $who, "hrm... '$factoid' is unique." );
546             return;
547         }
548         if ( scalar @list > 5 ) {
549             &msg( $who, 'A bit too many factoids to be redirected, hey?' );
550             return;
551         }
552
553         my @redir;
554         &status( "Redirect '$factoid' (" . ($#list) . ')...' );
555         for (@list) {
556             my $x = $_;
557             next if (/^\Q$factoid\E$/i);
558
559             &status("  Redirecting '$_'.");
560             my $was = &getFactoid($_);
561             if ( $was =~ /<REPLY> see/i ) {
562                 &status('warn: not redirecting a redirection.');
563                 next;
564             }
565
566             &DEBUG("  was '$was'.");
567             push( @redir, $x );
568             &setFactInfo( $x, 'factoid_value', "<REPLY> see $factoid" );
569         }
570         &status('Done.');
571
572         &msg( $who,
573             &formListReply( 0, "'$factoid' is redirected to by '", @redir ) );
574
575         return;
576     }
577
578     # rot13 it.
579     if ( $message =~ /^rot([0-9]*)(\s+(.*))?/i ) {
580         my $reply = $3;
581
582         if ( !defined $reply ) {
583             &help('rot13');
584             return;
585         }
586         my $num   = $1 % 26;
587         my $upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
588         my $lower = 'abcdefghijklmnopqrstuvwxyz';
589         my $to =
590             substr( $upper, $num )
591           . substr( $upper, 0, $num )
592           . substr( $lower, $num )
593           . substr( $lower, 0, $num );
594         eval "\$reply =~ tr/$upper$lower/$to/;";
595
596         #$reply =~ y/A-Za-z/N-ZA-Mn-za-m/;
597         &performStrictReply($reply);
598
599         return;
600     }
601
602     # cpustats.
603     if ( $message =~ /^cpustats$/i ) {
604         if ( $^O !~ /linux/ ) {
605             &ERROR('cpustats: your OS is not supported yet.');
606             return;
607         }
608
609         ### poor method to get info out of file, please fix.
610         open( STAT, "/proc/$$/stat" );
611         my $line = <STAT>;
612         chop $line;
613         my @data = split( / /, $line );
614         close STAT;
615
616         # utime(13) + stime(14).
617         my $cpu_usage = sprintf( '%.01f', ( $data[13] + $data[14] ) / 100 );
618
619         # cutime(15) + cstime (16).
620         my $cpu_usage2 = sprintf( '%.01f', ( $data[15] + $data[16] ) / 100 );
621         my $time       = time() - $^T;
622         my $raw_perc   = $cpu_usage * 100 / $time;
623         my $raw_perc2  = $cpu_usage2 * 100 / $time;
624         my $perc;
625         my $perc2;
626         my $total;
627         my $ratio;
628
629         if ( $raw_perc > 1 ) {
630             $perc  = sprintf( '%.01f', $raw_perc );
631             $perc2 = sprintf( '%.01f', $raw_perc2 );
632             $total = sprintf( '%.01f', $raw_perc + $raw_perc2 );
633         }
634         elsif ( $raw_perc > 0.1 ) {
635             $perc  = sprintf( '%.02f', $raw_perc );
636             $perc2 = sprintf( '%.02f', $raw_perc2 );
637             $total = sprintf( '%.02f', $raw_perc + $raw_perc2 );
638         }
639         else {    # <=0.1
640             $perc  = sprintf( '%.03f', $raw_perc );
641             $perc2 = sprintf( '%.03f', $raw_perc2 );
642             $total = sprintf( '%.03f', $raw_perc + $raw_perc2 );
643         }
644         $ratio = sprintf( '%.01f', 100 * $perc / ( $perc + $perc2 ) );
645
646         &performStrictReply( "Total CPU usage: \002$cpu_usage\002 s ... "
647               . "Total used: \002$total\002 % "
648               . "(parent/child ratio: $ratio %)" );
649
650         return;
651     }
652
653     # ircstats.
654     if ( $message =~ /^ircstats?$/i ) {
655         $ircstats{'TotalTime'} ||= 0;
656         $ircstats{'OffTime'}   ||= 0;
657
658         my $count       = $ircstats{'ConnectCount'};
659         my $format_time = &Time2String( time() - $ircstats{'ConnectTime'} );
660         my $total_time =
661           time() - $ircstats{'ConnectTime'} + $ircstats{'TotalTime'};
662         my $reply;
663
664         my $connectivity =
665           100 * ( $total_time - $ircstats{'OffTime'} ) / $total_time;
666         my $p = sprintf( '%.03f', $connectivity );
667         $p =~ s/(\.\d*)0+$/$1/;
668         if ( $p =~ s/\.0$// ) {
669
670             # this should not happen... but why...
671         }
672         else {
673             $p =~ s/\.$//;
674         }
675
676         if ( $total_time != ( time() - $ircstats{'ConnectTime'} ) ) {
677             my $tt_format = &Time2String($total_time);
678             &DEBUG("tt_format => $tt_format");
679         }
680
681         ### RECONNECT COUNT.
682         if ( $count == 1 ) {    # good.
683             $reply =
684                 "I'm connected to $ircstats{'Server'} and have been so"
685               . " for $format_time";
686         }
687         else {
688             $reply =
689                 "Currently I'm hooked up to $ircstats{'Server'} but only"
690               . " for $format_time.  "
691               . "I had to reconnect \002$count\002 times."
692               . "   Connectivity: $p %";
693         }
694
695         ### REASON.
696         my $reason = $ircstats{'DisconnectReason'};
697         if ( defined $reason ) {
698             $reply .= ".  I was last disconnected for '$reason'.";
699         }
700
701         &performStrictReply($reply);
702
703         return;
704     }
705
706     # status.
707     if ( $message =~ /^statu?s$/i ) {
708         my $startString = scalar( gmtime $^T );
709         my $upString    = &Time2String( time() - $^T );
710         my ( $puser, $psystem, $cuser, $csystem ) = times;
711         my $factoids = &countKeys('factoids');
712         my $forks    = 0;
713         foreach ( keys %forked ) {
714             $forks += scalar keys %{ $forked{$_} };
715         }
716         $forks /= 2;
717         $count{'Commands'} = 0;
718         foreach ( keys %cmdstats ) {
719             $count{'Commands'} += $cmdstats{$_};
720         }
721
722         &performStrictReply( "Since $startString, there have been"
723               . " \002$count{'Update'}\002 "
724               . &fixPlural( 'modification', $count{'Update'} )
725               . ", \002$count{'Question'}\002 "
726               . &fixPlural( 'question', $count{'Question'} )
727               . ", \002$count{'Dunno'}\002 "
728               . &fixPlural( 'dunno', $count{'Dunno'} )
729               . ", \002$count{'Moron'}\002 "
730               . &fixPlural( 'moron', $count{'Moron'} )
731               . " and \002$count{'Commands'}\002 "
732               . &fixPlural( 'command', $count{'Commands'} )
733               . ".  I have been awake for $upString this session, and "
734               . "currently reference \002$factoids\002 factoids.  "
735               . "I'm using about \002$memusage\002 "
736               . "kB of memory. With \002$forks\002 active "
737               . &fixPlural( 'fork', $forks )
738               . ". Process time user/system $puser/$psystem child $cuser/$csystem"
739         );
740
741         return;
742     }
743
744     # wantNick. xk++
745     # FIXME does not try to get nick 'back', just switches nicks
746     if ( $message =~ /^wantNick\s(.*)?$/i ) {
747         return unless ( &hasFlag('o') );
748         my $wantnick = lc $1;
749         my $mynick   = $conn->nick();
750
751         if ( $mynick eq $wantnick ) {
752             &msg( $who,
753 "I hope you're right. I'll try anyway (mynick=$mynick, wantnick=$wantnick)."
754             );
755         }
756
757         # fallback check, I guess.  needed?
758         if ( !&IsNickInAnyChan($wantnick) ) {
759             my $str = "attempting to change nick from $mynick to $wantnick";
760             &status($str);
761             &msg( $who, $str );
762             &nick($wantnick);
763             return;
764         }
765
766         # idea from dondelecarlo :)
767         # TODO: use cache{nickserv}
768         if ( $param{'nickServ_pass'} ) {
769             my $str = "someone is using nick $wantnick; GHOSTing";
770             &status($str);
771             &msg( $who, $str );
772             &msg( 'NickServ', "GHOST $wantnick $param{'nickServ_pass'}" );
773
774             $conn->schedule(
775                 5,
776                 sub {
777                     &status(
778 "going to change nick from $mynick to $wantnick after GHOST."
779                     );
780                     &nick($wantnick);
781                 }
782             );
783
784             return;
785         }
786
787         return;
788     }
789
790     return 'CONTINUE';
791 }
792
793 1;
794
795 # vim:ts=4:sw=4:expandtab:tw=80