html/bitlbee_typing_notice-pre-3.0.pl


   1 # INSTALLATION
   2 # [&bitlbee] set typing_notice true
   3 # <@root> typing_notice = `true'
   4 # AND
   5 # /statusbar window add typing_notice
   6 #
   7 # SETTINGS
   8 # [bitlbee]
   9 # bitlbee_send_typing = ON
  10 #   -> send typing messages to buddies
  11 # bitlbee_typing_allwin = OFF
  12 #   -> show typing notifications in all windows
  13 #
  14 # 
  15 # Changelog:
  16 #
  17 # 2006-11-02 (version 1.6.1_
  18 # * Sending typing works again.
  19 #
  20 # 2006-10-27 (version 1.6)
  21 # * 'channel sync' re-implemented.
  22 # * bitlbee_send_typing was a string setting, It's a boolean now, like it should.
  23 #
  24 # 2006-10-24 (version 1.5)
  25 #
  26 # * Sending notices to online users only.
  27 # * Using the new get_channel function;
  28 #
  29 # 2005-12-15 (version 1.42):
  30 # * Fixed small bug with typing notices disappearing under certain circumstances
  31 #   in channels
  32 # * Fixed bug that caused outgoing notifications not to work 
  33 # * root cares not about our typing status.
  34 #
  35 # 2005-12-04 (version 1.41):
  36 # * Implemented stale states in statusbar (shows "(stale)" for OSCAR connections) 
  37 # * Introduced bitlbee_typing_allwin (default OFF). Set this to ON to make
  38 #   typing notifications visible in all windows.
  39 #
  40 # 2005-12-03 (version 1.4):
  41 # * Major code cleanups and rewrites for bitlbee 1.0 with the updated typing
  42 #   scheme. TYPING 0, TYPING 1, and TYPING 2 are now supported from the server.
  43 # * Stale states (where user has typed in text but has stopped typing) are now
  44 #   recognized.
  45 # * Bug where user thinks you are still typing if you close the window after
  46 #   typing something and then erasing it quickly.. fixed.
  47 # * If a user signs off while they are still typing, the notification is removed
  48 # This update by Matt "f0rked" Sparks
  49 #
  50 # 2005-08-26:
  51 # Some fixes for AIM, Thanks to Dracula.
  52 #
  53 # 2005-08-16:
  54 # AIM supported, for sending notices, using CTCP TYPING 0. (Use the AIM patch from Hanji http://get.bitlbee.org/patches/)
  55 # 
  56 # 2004-10-31:
  57 # Sends typing notice to the bitlbee server when typing a message in irssi. bitlbee > 0.92
  58 #
  59 # 2004-06-11:
  60 # shows [typing: ] in &bitlbee with multiple users.
  61 #
  62 use strict;
  63 use Irssi::TextUI;
  64 
  65 use vars qw($VERSION %IRSSI);
  66 
  67 $VERSION = '1.6.1';
  68 %IRSSI = (
  69     authors     => 'Tijmen "timing" Ruizendaal, Matt "f0rked" Sparks',
  70     contact     => 'tijmen.ruizendaal@gmail.com, root@f0rked.com',
  71     name        => 'Bitlbee_typing_notice-pre-3.0',
  72     description => '1. Adds an item to the status bar wich shows [typing] when someone is typing a message on the supported IM-networks
  73                                         2. Sending typing notices to the supported IM networks (the other way arround)
  74                                         (For bitlbee 1.2.x)',
  75     license     => 'GPLv2',
  76     url         => 'http://the-timing.nl/stuff/irssi-bitlbee,
  77                                         http://f0rked.com',
  78     changed     => '2006-11-02',
  79 );
  80 
  81 my $bitlbee_channel = "&bitlbee";
  82 my $bitlbee_server_tag = "localhost";
  83 
  84 my $KEEP_TYPING_TIMEOUT = 1;
  85 my $STOP_TYPING_TIMEOUT = 7; # How often to check if we are typing, or on msn,
  86                              # how long to keep the typing notice up, or check
  87                              # if the other user is still typing...
  88 
  89 my %timer_tag;
  90 
  91 my %typing;
  92 my %tag;
  93 my $line;
  94 my %out_typing;
  95 my $lastkey;
  96 my $keylog_active = 1;
  97 my $command_char = Irssi::settings_get_str('cmdchars');
  98 my $to_char = Irssi::settings_get_str("completion_char");
  99 
 100 get_channel();
 101 
 102 Irssi::signal_add_last 'channel sync' => sub {
 103         my( $channel ) = @_;
 104         if( $channel->{topic} eq "Welcome to the control channel. Type \x02help\x02 for help information." ){
 105                 $bitlbee_server_tag = $channel->{server}->{tag};
 106                 $bitlbee_channel = $channel->{name};
 107         }
 108 };
 109 
 110 sub get_channel {
 111         my @channels = Irssi::channels();
 112         foreach my $channel(@channels) {
 113                 if ($channel->{topic} eq "Welcome to the control channel. Type \x02help\x02 for help information.") {
 114                         $bitlbee_channel = $channel->{name};
 115                         $bitlbee_server_tag = $channel->{server}->{tag};
 116 			return 1;
 117                 }
 118         }
 119 	return 0;
 120 }
 121 
 122 sub event_ctcp_msg {
 123     my ($server, $msg, $from, $address) = @_;
 124     #print "CTCP: $msg $from $address";
 125     return if $server->{tag} ne $bitlbee_server_tag;
 126     if (my($type) = $msg =~ "TYPING ([0-9])") {
 127         Irssi::signal_stop();
 128         if ($type == 0) {
 129             unset_typing($from);
 130         }
 131         elsif ($type == 1) {
 132             $typing{$from}=1;
 133             if ($address !~ /\@login\.oscar\.aol\.com/
 134                 and $address !~ /\@YAHOO/
 135                 and $address !~ /\@login\.icq\.com/) {
 136                 Irssi::timeout_remove($tag{$from});
 137                 $tag{$from}=Irssi::timeout_add_once($STOP_TYPING_TIMEOUT*1000,"unset_typing",$from);
 138             }
 139             redraw($from);
 140         }
 141         elsif ($type == 2) {
 142             stale_typing($from);
 143         }
 144     }
 145 }
 146 
 147 sub unset_typing {
 148     my($from,$no_redraw)=@_;
 149     delete $typing{$from} if $typing{$from};
 150     Irssi::timeout_remove($tag{$from});
 151     redraw($from) if !$no_redraw;
 152 }
 153 
 154 sub stale_typing {
 155     my($from)=@_;
 156     $typing{$from}=2;
 157     redraw($from);
 158 }
 159 
 160 sub redraw {
 161     my($from)=@_;
 162     my $window = Irssi::active_win();
 163     my $channel = $window->get_active_name();
 164     if ($from eq $channel || $channel eq $bitlbee_channel
 165         || $channel =~ /&chat_0/ 
 166         || Irssi::settings_get_bool("bitlbee_typing_allwin")) {
 167         Irssi::statusbar_items_redraw('typing_notice');
 168     }
 169 }    
 170 
 171 sub event_msg {
 172     my ($server,$data,$from,$address,$target) = @_;
 173     return if $server->{tag} ne $bitlbee_server_tag;
 174     my $channel=Irssi::active_win()->get_active_name();
 175     unset_typing $from, "no redraw";
 176     unset_typing $channel;
 177 }
 178 
 179 sub event_quit {
 180     my($server,$nick,$address,$reason)=@_;
 181     return if $server->{tag} ne $bitlbee_server_tag;
 182     unset_typing $nick;
 183 }
 184 
 185 sub typing_notice {
 186     my ($item, $get_size_only) = @_;
 187     my $window = Irssi::active_win();
 188     my $channel = $window->get_active_name();
 189     
 190     if (exists($typing{$channel})) {
 191         my $append=$typing{$channel}==2 ? " (stale)" : "";
 192         $item->default_handler($get_size_only, "{sb typing$append}", 0, 1);
 193     }
 194     else {
 195         $item->default_handler($get_size_only, "", 0, 1);
 196         Irssi::timeout_remove($tag{$channel});
 197     }
 198     if ($channel eq $bitlbee_channel || $channel =~ /&chat_0/
 199         || Irssi::settings_get_bool("bitlbee_typing_allwin")) {
 200         foreach my $key (keys(%typing)) {
 201             $line .= " ".$key;
 202             if ($typing{$key}==2) { $line .= " (stale)"; }
 203         }
 204         if ($line ne "") {
 205             $item->default_handler($get_size_only, "{sb typing:$line}", 0, 1);
 206             $line = "";
 207         }
 208     } 
 209 }
 210 
 211 sub empty {
 212     my $from = shift;
 213     delete($typing{$from});
 214     Irssi::statusbar_items_redraw('typing_notice');
 215 }
 216 
 217 sub window_change {
 218     Irssi::statusbar_items_redraw('typing_notice');
 219     my $win = !Irssi::active_win() ? undef : Irssi::active_win()->{active};
 220     if (ref $win && ($win->{server}->{tag} eq $bitlbee_server_tag)) {
 221         if (!$keylog_active) {
 222             $keylog_active = 1;
 223             Irssi::signal_add_last('gui key pressed', 'key_pressed');
 224             #print "Keylog started";
 225         }
 226     } 
 227     else {
 228         if ($keylog_active) {
 229             $keylog_active = 0;
 230             Irssi::signal_remove('gui key pressed', 'key_pressed');
 231             #print "Keylog stopped";
 232         }
 233     }
 234 }
 235 
 236 sub key_pressed {
 237     return if !Irssi::settings_get_bool("bitlbee_send_typing");
 238     my $key = shift;
 239     if ($key != 9 && $key != 10 && $lastkey != 27 && $key != 27 
 240        && $lastkey != 91 && $key != 126 && $key != 127) 
 241     {
 242         my $server = Irssi::active_server();
 243         my $window = Irssi::active_win();
 244         my $nick = $window->get_active_name();
 245         if ($server->{tag} eq $bitlbee_server_tag && 
 246             $nick ne "(status)" &&
 247             $nick ne "root") 
 248         {
 249             if ($nick eq $bitlbee_channel) {
 250                 my $input = Irssi::parse_special("\$L");
 251                 my ($first_word) = split(/ /,$input);
 252                 if ($input !~ /^$command_char.*/ && $first_word =~ s/$to_char$//){
 253                     send_typing($first_word);
 254                 }
 255             } 
 256             else {
 257                 my $input = Irssi::parse_special("\$L");
 258                 if ($input !~ /^$command_char.*/ && length($input) > 0){
 259                     send_typing($nick);
 260                 }
 261             }
 262         }
 263     }
 264     $lastkey = $key;
 265 }
 266 
 267 sub out_empty {
 268     my ($a) = @_;
 269     my($nick,$tag)=@{$a};
 270     delete($out_typing{$nick});
 271     #print $winnum."|".$nick;
 272     if (my $server=Irssi::server_find_tag($tag)) {
 273         $server->command("^CTCP $nick TYPING 0");
 274     }
 275 }
 276 
 277 sub send_typing {
 278     my $nick = shift;
 279     if (!exists($out_typing{$nick}) || time - $out_typing{$nick} > $KEEP_TYPING_TIMEOUT) {
 280 
 281 	my @nicks = Irssi::server_find_tag($bitlbee_server_tag)->channel_find($bitlbee_channel)->nicks();
 282     	my $exists=0;
 283     	foreach my $nick1(@nicks) { #check if the nickname is in the BitlBee channel
 284 		if($nick1->{'nick'} eq $nick) {
 285 		#	print "Exists!";
 286 			$exists=1;
 287 		}
 288     	}
 289     	if (!$exists) {
 290 		#print "Does not exist";
 291 		return;
 292     	}
 293 
 294     	#print "Send typing";
 295         my $server = Irssi::active_server();
 296         $server->command("^CTCP $nick TYPING 1");
 297                
 298         $out_typing{$nick} = time;
 299         
 300         ### Reset 'stop-typing' timer
 301         if ($timer_tag{$nick}) {
 302             Irssi::timeout_remove($timer_tag{$nick});
 303             delete($timer_tag{$nick});
 304         }
 305         $timer_tag{$nick} = Irssi::timeout_add_once($STOP_TYPING_TIMEOUT*1000, 'out_empty', ["$nick", $server->{tag}]);
 306     }
 307 }
 308 
 309  #README: Delete the old bitlbee_send_typing string from ~/.irssi/config. A boolean is better.
 310 
 311 Irssi::settings_add_bool("bitlbee","bitlbee_send_typing",1);
 312 Irssi::settings_add_bool("bitlbee","bitlbee_typing_allwin",0);
 313 
 314 Irssi::signal_add("ctcp msg", "event_ctcp_msg");
 315 Irssi::signal_add("message private", "event_msg");
 316 Irssi::signal_add("message public", "event_msg");
 317 Irssi::signal_add("message quit", "event_quit");
 318 Irssi::signal_add_last('window changed', 'window_change');
 319 Irssi::signal_add_last('gui key pressed', 'key_pressed');
 320 Irssi::statusbar_item_register('typing_notice', undef, 'typing_notice');
 321 Irssi::statusbars_recreate_items();