Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
102 lines (89 sloc) 2.86 KB
use strict;
use warnings;
our $VERSION = '0.3'; # e43de0fd9100921
our %IRSSI = (
authors => 'Nei',
contact => 'Nei @ anti@conference.jabber.teamidiot.de',
url => "http://anti.teamidiot.de/",
name => 'fix_slackirc',
description => 'Some workarounds to improve irssi experience on the Slack IRC gateway',
license => 'ISC',
);
# Usage
# =====
# Load and enjoy
use Irssi;
my $SLACK_ADDRESS = 'irc.tinyspeck.com';
# Work-around for 2 bugs in the Slack IRC bridge
# * Format of 315 is broken - the nick is missing
# * No Reply to the MODE b command
# * Empty real names are given as string "null" instead
# these issues will stop channel sync from working properly
my %timer;
my %chanlist;
Irssi::signal_register({
'chanquery who end' => [qw[iobject string]],
});
# Accessor for the Rawlog
sub _s2r {
my $ref = shift;
if ($ref =~ /=SCALAR/) {
bless +{ _irssi => $$ref } => ref $ref
} else {
$ref
}
}
sub queue_ban_end {
my ($server, $raw) = @_;
return unless $server && $server->{real_address} eq $SLACK_ADDRESS;
my (@p) = split ' :', $raw, 2;
unshift @p, (split / /, shift @p);
my $tag = $server->{tag};
push @{ $chanlist{$tag} }, split /,/, $p[1];
if (my $t = delete $timer{$tag}) {
Irssi::timeout_remove($t);
}
# Gross hack due to Irssi missing a signal. We expect that irssi will ask for bans "soon" and in order
$timer{$tag} = Irssi::timeout_add_once(5_000, 'send_end_of_bans', $tag);
}
sub send_end_of_bans {
my ($tag) = @_;
delete $timer{$tag};
return unless $chanlist{$tag} && @{$chanlist{$tag}};
my $chan = shift @{ $chanlist{$tag} // [] } || return;
if (my $server = Irssi::server_find_tag($tag)) {
my $raw = ':'.$server->{real_address}.' 368 '.$server->{nick}.' '.$chan.' :Slack has no Ban List';
_s2r($server->{rawlog})->input("[FAKED] $raw") if $server->{rawlog};
Irssi::signal_emit('server incoming', $server, $raw);
if (@{$chanlist{$tag}}) {
# We expect that irssi will ask for the "next" ban soon
$timer{$tag} = Irssi::timeout_add_once(2_000, 'send_end_of_bans', $tag);
}
else {
delete $chanlist{$tag};
}
}
}
sub fix_incoming {
my ($server, $raw) = @_;
my $nick = $server->{nick};
my $continue;
# fix end of wholist
if ($raw =~ s/:$SLACK_ADDRESS 315 \K /$nick /) {
$continue = 1;
}
# fix "null" realnames
elsif ($raw =~ s/:$SLACK_ADDRESS 352 .* :\d+ \Knull$//) {
$continue = 1;
}
# support self msgs
elsif ($raw =~ s/^:(?:(\S+)!\S+(\@$SLACK_ADDRESS)) PRIVMSG ([^#\s]\S*) :\[\3\] /:$3!$3$2 PRIVMSG $1 :/) {
$continue = 1;
}
if ($continue) {
_s2r($server->{rawlog})->input("[FIXED] $raw") if $server->{rawlog};
Irssi::signal_continue($server, $raw);
}
}
Irssi::signal_add_last('chanquery who end' => 'queue_ban_end');
Irssi::signal_add_first('server incoming' => 'fix_incoming');