Implementation of brmdoor downstairs

This commit is contained in:
Radek Pilar 2014-06-14 15:14:40 +02:00
parent 01a836bc81
commit 4bc790e97a
7 changed files with 694 additions and 0 deletions

View file

@ -0,0 +1,225 @@
# fifo_remote.pl -- send commands to Irssi through named pipe/fifo
#
# DESCRIPTION
#
# fifo_remote.pl creates a named pipe (a.k.a. fifo). Everything written to the
# fifo will be passed on to Irssi and run as a command. (You need not precede
# you commands with `/', or whatever you've set you `cmdchars' to -- this also
# means that if you want to send a message, you must use the explicit `say'
# command.)
#
# SETTINGS
#
# fifo_remote_file (default is `remote-control')
#
# This is the file name of the named pipe. Any leading `~[USER]' part is
# expanded before use. If the name does not begin with `/' it is taken to
# be relative to Irssi's current configuration dir (usually `~/.irssi').
#
# The default value thus normally means `~/.irssi/remote-control'.
#
# NOTES
#
# This script may have limited use to you, since it cannot bring back *any*
# return values from Irssi. It can only run Irssi commands from the outside. --
# I use it to trigger my online/away messages from any shell, and that's about
# it.
#
# CAVEATS
#
# Due to the way named pipes (or fifos) works one must take extra care when
# writing to one of these beasts -- if not, the writing program may well hang
# forever. This is because the writing process will not terminate until the
# fifo has been read from the other end (see also fifo(4)).
#
# To avoid this problem, I usually use something akin to the below shell
# function to write to the Irssi fifo remote. It simply kills off the writing
# process if it's still around after a certain timeout (e.g. the fifo could be
# present but Irssi not running -- and thus the pipe would never be read). The
# entire process is done in the background, so the caller of the function does
# not have to wait.
#
# FILE="$HOME/.irssi/remote-control"
# irssi_command() {
# if [ -p "$FILE" ]; then
# ( echo "$*" > "$FILE" &
# sleep 5
# kill $! 2>/dev/null )&
# fi
# }
#
# TODO
#
# o Clean up fifo file when Irssi quits -- right now this is not done, so extra
# precautions are required inside your shell scripts to make sure they do not
# hang indefinately when trying to write to the remote control fifo. (See
# above example.)
#
# HISTORY
#
# [2004-08-12, 22.16-00.58] v0.1a - began implementing it
#
# [2004-08-13, 09.52-10-19] v0.2a - began implementing fifo_read
#
# [2004-08-14, 01.12-04.27] v0.3a
#
# [2004-08-14, 14.09-18.13] v0.4a - seems to be fully functional, except for
# the fact that commands aren't run in the proper window/server environment
#
# [2004-08-15, 18.17-19.26] v0.5a - command comming through pipe is now run in
# the active window; removed bug which crashed Irssi, bug was caused by several
# input_add()s being called without having been removed in between
#
# [2004-08-26, 21.46-22.30] v0.5 - wrote above docs
#
our $VERSION = '0.5';
our %IRSSI = (
authors => 'Zrajm C Akfohg',
contact => 'zrajm\@klingonska.org',
name => 'fifo_remote',
description => 'Irssi remote control (for shell scripting etc.) -- ' .
'run all commands written to named pipe.',
license => 'GPLv2',
url => 'http://www.irssi.org/scripts/',
); #
use strict; #
use Irssi; #
use Fcntl; # provides `O_NONBLOCK' and `O_RDONLY' constants
our ( $FIFO, # fifo absolute filename (expanded from Irssi config)
$FIFO_HANDLE, # fifo filehandle for `open' et al.
$FIFO_TAG ); # fifo signal tag for `input_add'
# simple subs
sub TRUE() { 1 } # some constants [perlsyn(1)
sub FALSE() { "" } # "Constant Functions"]
sub DEBUG(@) { print "%B", join(":", @_),"%n" }# DEBUG thingy
# Irssi settings
Irssi::settings_add_str($IRSSI{name}, # default fifo_remote_file
'fifo_remote_file', 'remote-control'); #
# create named fifo and open it for input
# (called on script load and fifo name changes)
sub create_fifo($) { # [2004-08-14]
my ($new_fifo) = @_; # get args
if (not -p $new_fifo) { # create fifo if non-existant
if (system "mkfifo '$new_fifo' &>/dev/null" and
system "mknod '$new_fifo' &>/dev/null"){
print CLIENTERROR "`mkfifo' failed -- could not create named pipe";
# TODO: capture `mkfifo's stderr and show that here
return ""; #
} #
} #
$FIFO = $new_fifo; # remember fifo name
open_fifo($new_fifo); # open fifo for reading
} #
# set up signal to trigger on fifo input
# (called when creating named fifo)
sub open_fifo($) { # [2004-08-14]
my ($fifo) = @_; # get args
if (not sysopen $FIFO_HANDLE, $fifo, # open fifo for non-blocking
O_NONBLOCK | O_RDONLY) { # reading
print CLIENTERROR "could not open named pipe for reading";
return ""; #
} #
Irssi::input_remove($FIFO_TAG) # disable fifo reading signal
if defined $FIFO_TAG; # if there is one
$FIFO_TAG = Irssi::input_add # set up signal called when
fileno($FIFO_HANDLE), INPUT_READ, # there's input in the pipe
\&read_fifo, ''; #
return 1; #
} #
# read from fifo
# (called by fifo input signal)
sub read_fifo() { # [2004-08-14]
foreach (<$FIFO_HANDLE>) { # for each input line
chomp; # strip trailing newline
Irssi::print( #
"%B>>%n $IRSSI{name} received command: \"$_\"",
MSGLEVEL_CLIENTCRAP); #
# Irssi::active_win->print( # show incoming commands
# "\u$IRSSI{name} received command: \"$_\"", #
# MSGLEVEL_CLIENTNOTICE); #
Irssi::active_win->command($_); # run incoming commands
} #
open_fifo($FIFO); # re-open fifo
# TODO: Is the above re-opening of fifo really necessary? -- If not
# invoked here `read_fifo' is called repeatedly, even though no input
# is to be found on the fifo. (This seems a waste of resources to me.)
} #
# disable fifo and erase fifo file
sub destroy_fifo($) { # [2004-08-14]
my ($fifo) = @_; # get args
if (defined $FIFO_TAG) { # if fifo signal is active
Irssi::input_remove($FIFO_TAG); # disable fifo signal
undef $FIFO_TAG; # and forget its tag
} #
if (defined $FIFO_HANDLE) { # if fifo is open
close $FIFO_HANDLE; # close it
undef $FIFO_HANDLE; # and forget handle
} #
if (-p $fifo) { # if named fifo exists
unlink $fifo; # erase fifo file
undef $FIFO; # and forget filename
} #
return 1; # return
} #
# add path to filename (expands `~user', and make
# non-absolute filename relative to Irssi's config dir)
sub absolute_path($) { # [2004-08-14] -- [2004-08-15]
my ($file) = @_; #
return '' if $file eq ''; # don't modify empty value
$file =~ s^(~[^/]*) # expand any leading tilde
my $x; # WORKAROUND: glob()
until($x = glob($1)) { }; # sometimes return empty
$x; # string -- avoid that
ex; #
$file = Irssi::get_irssi_dir() . "/$file" # if full path is not given
unless $file =~ m^/; # prepend irssi config path
# FIXME: clean up multiple slashes, and occuring `/./' and `/../'.
# this sub used in: fifo_remote.pl, xcuses.pl
return $file; #
} #
# clean up fifo on unload
# (called on /script unload)
Irssi::signal_add_first #
'command script unload', sub { # [2004-08-13]
my ($script) = @_; # get args
return unless $script =~ # only do cleanup when
/(?:^|\s) $IRSSI{name} # unloading *this* script
(?:\.[^. ]*)? (?:\s|$) /x; #
destroy_fifo($FIFO) if -p $FIFO; # destroy old fifo
Irssi::print("%B>>%n $IRSSI{name} $VERSION unloaded", MSGLEVEL_CLIENTCRAP);
}; #
# create new fifo (erase any old) and get command prefix
# (called on script loading and on user /set)
sub setup() { # [2004-08-13]
my $new_fifo = absolute_path # get fifo_remote_file
Irssi::settings_get_str # setting from Irssi
'fifo_remote_file'; # (and add path to it)
return if $new_fifo eq $FIFO and -p $FIFO; # do nada if already exists
destroy_fifo($FIFO) if -p $FIFO; # destroy old fifo
create_fifo($new_fifo) # create new fifo
and $FIFO = $new_fifo; # and remember that fifo
} #
setup(); # initialize setup values
Irssi::signal_add('setup changed', \&setup); # re-read setup when it changes
print CLIENTCRAP "%B>>%n $IRSSI{name} $VERSION (by $IRSSI{authors}) loaded";
#print CLIENTCRAP " (Fifo name: $FIFO)";

View file

@ -0,0 +1,168 @@
# thistory.pl v1.05 [10.03.2002]
# Copyright (C) 2001, 2002 Teemu Hjelt <temex@iki.fi>
#
# Written for irssi 0.7.98 and later, idea from JSuvanto.
# Modified by Mrkva to save topics to files
#
# Many thanks to fuchs, shasta, Paladin, Koffa and people
# on #irssi for their help and suggestions.
#
# Keeps information about the most recent topics of the
# channels you are on.
# Usage: /thistory [channel] and /tinfo [channel]
#
# v1.00 - Initial release.
# v1.02 - Months and topics with formatting were shown
# incorrectly. (Found by fuchs and shasta)
# v1.03 - event_topic was occasionally using the wrong
# server tag. Also added few variables to ease
# changing the settings and behaviour of this
# script.
# v1.04 - Minor bug-fixes.
# v1.05 - Made the script more consistent with other
# Irssi scripts.
use Irssi;
use Irssi::Irc;
use vars qw($VERSION %IRSSI);
# Formatting character.
my $fchar = '%';
# Format of the line.
my $format = '"%topic" %nick (%address) [%mday.%mon.%year %hour:%min:%sec]';
# Amount of topics stored.
my $tamount = 10;
###### Don't edit below this unless you know what you're doing ######
$VERSION = "1.05";
%IRSSI = (
authors => "Teemu Hjelt",
contact => "temex\@iki.fi",
name => "topic history",
description => "Keeps information about the most recent topics of the channels you are on.",
license => "GNU GPLv2 or later",
url => "http://www.iki.fi/temex/",
changed => "Sun Mar 10 14:53:59 EET 2002",
);
sub cmd_topicinfo {
my ($channel) = @_;
my $tag = Irssi::active_server()->{'tag'};
$channel =~ s/\s+//;
$channel =~ s/\s+$//;
foreach my $chan (Irssi::channels()) {
open (TOPICLOG, ">/home/brmdoor/.irssi/topics/" . $chan->{name});
print TOPICLOG "$chan->{topic}\n";
close (TOPICLOG);
}
if ($channel eq "") {
if (Irssi::channel_find(Irssi::active_win()->get_active_name())) {
$channel = Irssi::active_win()->get_active_name();
}
}
if ($channel ne "") {
if ($topiclist{lc($tag)}{lc($channel)}{0}) {
Irssi::print("%W$channel%n: " . $topiclist{lc($tag)}{lc($channel)}{0}, MSGLEVEL_CRAP);
} else {
Irssi::print("No topic information for %W$channel%n", MSGLEVEL_CRAP);
}
} else {
Irssi::print("Usage: /tinfo <channel>");
}
}
sub cmd_topichistory {
my ($channel) = @_;
my $tag = Irssi::active_server()->{'tag'};
$channel =~ s/\s+//;
$channel =~ s/\s+$//;
if ($channel eq "") {
if (Irssi::channel_find(Irssi::active_win()->get_active_name())) {
$channel = Irssi::active_win()->get_active_name();
}
}
if ($channel ne "") {
if ($topiclist{lc($tag)}{lc($channel)}{0}) {
my $amount = &getamount($tag, $channel);
Irssi::print("Topic history for %W$channel%n:", MSGLEVEL_CRAP);
for (my $i = 0; $i < $amount; $i++) {
if ($topiclist{lc($tag)}{lc($channel)}{$i}) {
my $num = $i + 1;
if (length($amount) >= length($tamount) && length($i + 1) < length($tamount)) {
for (my $j = length($tamount); $j > length($i + 1); $j--) {
$num = " " . $num;
}
}
Irssi::print($num . ". " . $topiclist{lc($tag)}{lc($channel)}{$i}, MSGLEVEL_CRAP);
} else {
last;
}
}
} else {
Irssi::print("No topic history for %W$channel%n", MSGLEVEL_CRAP);
}
} else {
Irssi::print("Usage: /thistory <channel>");
}
}
sub event_topic {
my ($server, $data, $nick, $address) = @_;
my ($channel, $topic) = split(/ :/, $data, 2);
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
my $tag = $server->{'tag'};
my $output = $format;
$topic =~ s/%/%%/g;
#$topic .= '%n';
$val{'sec'} = $sec < 10 ? "0$sec" : $sec;
$val{'min'} = $min < 10 ? "0$min" : $min;
$val{'hour'} = $hour < 10 ? "0$hour" : $hour;
$val{'mday'} = $mday < 10 ? "0$mday" : $mday;
$val{'mon'} = $mon + 1 < 10 ? "0" . ($mon + 1) : $mon + 1;
$val{'year'} = $year + 1900;
$val{'nick'} = $nick;
$val{'address'} = $address;
$val{'channel'} = $channel;
$val{'topic'} = $topic;
$val{'tag'} = $tag;
$output =~ s/$fchar(\w+)/$val{$1}/g;
for (my $i = (&getamount($tag, $channel) - 1); $i >= 0; $i--) {
if ($topiclist{lc($tag)}{lc($channel)}{$i}) {
$topiclist{lc($tag)}{lc($channel)}{$i + 1} = $topiclist{lc($tag)}{lc($channel)}{$i};
}
}
$topiclist{lc($tag)}{lc($channel)}{0} = $output;
open (TOPICLOG, ">/home/brmdoor/.irssi/topics/".$channel);
print TOPICLOG "$topic\n";
close (TOPICLOG)
}
sub getamount {
my ($tag, $channel) = @_;
my $amount = 0;
for (my $i = 0; $i < $tamount; $i++) {
if ($topiclist{lc($tag)}{lc($channel)}{$i}) {
$amount++;
}
}
return $amount;
}
Irssi::command_bind("topichistory", "cmd_topichistory");
Irssi::command_bind("thistory", "cmd_topichistory");
Irssi::command_bind("topicinfo", "cmd_topicinfo");
Irssi::command_bind("tinfo", "cmd_topicinfo");
Irssi::signal_add("event topic", "event_topic");
Irssi::print("Loaded thistory.pl v$VERSION");