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();