## This is the IRSSI-version!
## OK, here we go.
## For bugs/suggestions/help contact me at [email protected]
##
## This script does nothing usefull but is extremely usefull to me ;-).
## It should handle CTCP SOUNDs correctly - even if the waves are stored
## in subdirs and/or on SMB shares.
## It can also initiate CTCP SOUNDs, handle sound requests and request
## waves automatically.
##
## This is my first perl script. Please be kind to me ;-).
## I built it on top of someone else's work, but I don't know whom...
use strict;
use vars qw($VERSION %IRSSI);
$VERSION = "0.2.3.23b";
%IRSSI = (
authors => 'Adam Duck',
contact => '[email protected]',
name => 'PGGB_sound',
description => 'does CTCP SOUNDs and other similar things.',
license => 'GPLv2',
url => '',
);
Irssi::settings_add_bool('PGGB', 'SOUND_autosend', 1);
Irssi::settings_add_bool('PGGB', 'SOUND_autoget', 0);
Irssi::settings_add_bool('PGGB', 'SOUND_play', 1);
Irssi::settings_add_int( 'PGGB', 'SOUND_display', 5);
Irssi::settings_add_str( 'PGGB', 'SOUND_hilight', '(none)');
Irssi::settings_add_str( 'PGGB', 'SOUND_DCC', '(none)');
Irssi::settings_add_str( 'PGGB', 'SOUND_dir', '~/.irssi/');
Irssi::settings_add_str( 'PGGB', 'SOUND_command', 'play');
my $autoget = Irssi::settings_get_bool("SOUND_autoget");
# You can use , ".gz" or ".bz2" as extension, the script will
# honour it accordingly. I chose ".gz" because it should be available
# on most systems ...
# Btw, this is NOT the time consuming part. It's `parse_dir'.
my $cachefile = $ENV{HOME} . "/.irssi/wavdir.cache.gz";
########################################
# Changelog
# Sat 23 Mar 2002, 12:26:39 fixed stupid bug in sound_autosend
#
# ------------------------------------------------------------
# Don't edit below this line unless you are prepared to code!
# ------------------------------------------------------------
use File::Listing;
use File::Basename;
Irssi::command_bind("sound", "sound_command");
Irssi::signal_add_last("complete word", "sound_complete");
Irssi::signal_add("event privmsg", "sound_autosend");
Irssi::signal_add("ctcp msg", "CTCP_sound");
Irssi::signal_add('print text', 'hilight_sound');
Irssi::signal_add('dcc created', 'DCC_sound');
#IRC::add_message_handler("PRIVMSG", "sound_autoget");
Irssi::theme_register([
'ctcp', '{ctcp {hilight $0} $1}'
]);
sub help {
Irssi::print("USAGE: /sound setup|(.wav)?");
Irssi::print("\nsetup: creates the (vital) cache file.");
Irssi::print("Please setup all variables through the /SET command (they all begin with \"SOUND_\").");
Irssi::print("\nIf you have copied new waves to your sounddir, be sure to run \"/sound setup\" again!");
}
sub find_wave {
unless ( -e "$cachefile" ) {
Irssi::print("Cache file not found...");
create_cache();}
my $sound = shift(@_);
unless ($sound =~ /^.*\.wav$/i) {$sound = $sound . ".*.wav"}
my $LISTING;
if ( -r $cachefile ) {
if ($cachefile =~ /\.gz$/i) { open(LISTING, "-|", "zcat $cachefile") }
elsif ($cachefile =~ /\.bz2$/i) { open(LISTING, "-|", "bzcat $cachefile") }
else { open(LISTING, "-|", "cat $cachefile") };
} else {
Irssi::print("Cache file not readable. Nani?!?");
return;}
my @dir = parse_dir(\*LISTING, '+0001');
close(LISTING);
my $result = [];
for (@dir) {
my ($fName, $fType, $fSize, $fMtime, $fMode) = @$_;
if (basename($fName) =~ /^$sound$/i) {
#Irssi::print "$fName, $fType, $fSize, $fMtime, $fMode";
push @$result, $fName;}}
return @$result;
}
sub create_cache {
my $sounddir = Irssi::settings_get_str("SOUND_dir") . "/";
# we need the "LC_CTYPE=en" here because dir_parse is unable
# to parse things like "Mär 3" (German locale) ...
Irssi::print("Creating $cachefile (this could take a while...)");
my $command = "/exec LC_CTYPE=en ls -lR $sounddir";
if ($cachefile =~ /\.gz$/i) { $command = $command . " | gzip" }
elsif ($cachefile =~ /\.bz2$/i) { $command = $command . " | bzip2" }
Irssi::command("$command > $cachefile");
}
sub onoff { shift(@_) ? return "ON" : return "OFF"; }
sub sound_command {
my $sounddir = Irssi::settings_get_str("SOUND_dir") . "/";
my $soundcmd = Irssi::settings_get_str("SOUND_command");
my ($data, $server, $witem) = @_;
$data =~ /([\w\.]+)(.*)/;
my $sound = $1;
my $rest = $2;
$rest =~ s/ *//;
unless ($rest eq "") { $rest = " " . $rest;};
if ($sound =~ /^setup$/i) { create_cache(); return; }
if (!($sound =~ /.*\.wav/i)) { $sound = $sound . ".wav";}
if ($witem && ($witem->{type} eq "CHANNEL" ||
$witem->{type} eq "QUERY")) {
my $wavefile = (find_wave($sound))[0];
if ( -r $wavefile ) {
$witem->command("/CTCP $witem->{name} SOUND ".lc(basename($wavefile))."$rest");
my $playcmd = system("$soundcmd $wavefile &"); # that's not so good ...
} else {
$witem->print("\"$sound\" not found in \"$sounddir\" or cache file too old."); }
} else {
Irssi::print "There's no point in running a \"CTCP SOUND\" command here."; }
return 1;
}
sub sound_complete {
my ($complist, $window, $word, $linestart, $want_space) = @_;
if ($linestart =~ /^\/sound$/) {
my $coli = [];
for (find_wave($word)) { push(@$coli, basename($_)); }
my $max = Irssi::settings_get_int('SOUND_display');
if (@$coli > $max) {
$window->print("@$coli[0..($max-1)] ...");
} else {
push @$complist, @$coli; }}}
sub sound_autosend {
if (!Irssi::settings_get_bool("SOUND_autosend")) { return 0; }
my ($server, $data, $nick, $address) = @_;
my $myname = $server->{nick};
$data =~ /(.*) :!$myname +(.*\.wav)/i;
if ($2 eq "") { return 0; }
my $channel = $1;
my $wavefile = (find_wave($2))[0];
if ($wavefile ne "") {
Irssi::print("DCC sending $wavefile to $nick");
$server->command("/DCC SEND $nick $wavefile");
} else {
$server->send_message($nick, "Sorry, $nick. $2 not found.", 1);
}
return 1;
}
sub hilight_sound {
my ($dest, $text, $stripped) = @_;
my $server = $dest->{server};
unless ($server->{usermode_away}) {
my $hiwave = Irssi::settings_get_str('SOUND_hilight');
if (($hiwave ne '(none)') &&
($dest->{level} & (MSGLEVEL_HILIGHT|MSGLEVEL_MSGS)) &&
($dest->{level} & MSGLEVEL_NOHILIGHT) == 0) {
play_wave(find_wave($hiwave));}}}
sub DCC_sound {
my $dcc = shift(@_);
my $server = $dcc->{server};
Irssi::print("$dcc->{type}");
unless ($server->{usermode_away} || ($dcc->{type} eq "SEND")) {
my $hiwave = Irssi::settings_get_str('SOUND_DCC');
if ($hiwave ne '(none)') {
play_wave(find_wave($hiwave));}}}
sub play_wave {
my $wave = shift(@_);
my $sndcmd = Irssi::settings_get_str("SOUND_command");
if (-r "$wave") {
system("$sndcmd \"$wave\" &");}}
sub sound_autoget {
if (!$autoget) { return 0; }
my $sounddir = Irssi::settings_get_str("SOUND_dir") . "/";
my $line = shift (@_);
#:nick!host PRIVMSG channel :message
$line =~ /:(.*)!(\S+) PRIVMSG (.*) :(.*)/i;
my $name = $1;
my $channel = $3;
my $text = $4;
my $name = "$name";
my @wordlist = split(' ',$4);
if ($wordlist[0] eq "\001SOUND") {
my $tempsound = $wordlist[1];
$tempsound =~ s/[\r \001 \n]//;
IRC::print($tempsound);
if (!open(TEMPFILE, "<", $sounddir.$tempsound)) {
IRC::send_raw("PRIVMSG $name :!$name $tempsound\r\n");
} else {
close(TEMPFILE);
}
}
return 0;
}
sub CTCP_sound {
my $play = Irssi::settings_get_bool("SOUND_play");
my $soundcmd = Irssi::settings_get_str("SOUND_command");
my ($server, $args, $nick, $addr, $target) = @_;
$args =~ /^SOUND (.*\.wav)(.*)$/i;
if ($1 eq "") { return 0; }
my $sound = $1;
my $wavfile = (find_wave($1))[0];
my $output = "";
my $rest = $2;
$rest =~ s/^ *//;
if ( $rest ne "" ) { # this one is for P&P & co.
$output = $output . $rest
} else {
$output = $output . " plays $sound";
}
if ($wavfile eq "") {
$output = $output . " (not found)";
if ($autoget) {
Irssi::send_raw("PRIVMSG $nick :!$nick $sound\r\n");
}
} else {
if ($play) {
system("$soundcmd \"$wavfile\" &");
} else {
$output = $output . " (muted)";
}
}
my $wItem = $server->window_find_item($target);
$wItem->printformat(MSGLEVEL_CTCPS, 'ctcp', $nick, $output);
Irssi::signal_stop();
}