html/irssiq.pl
1 #!/usr/bin/perl
2 #
3 # by Stefan "tommie" Tomanek
4 #
5 use strict;
6
7 use vars qw($VERSION %IRSSI);
8 $VERSION = "2003231101";
9 %IRSSI = (
10 authors => "Stefan 'tommie' Tomanek",
11 contact => "stefan\@pico.ruhr.de",
12 name => "IrssiQ",
13 description => "integrates ICQ instant-messaging into irssi",
14 license => "GPLv2",
15 changed => "$VERSION",
16 modules => "Net::vICQ Data::Dumper",
17 sbitems => "irssiq",
18 commands => "irssiq"
19 );
20
21 use Irssi 20020324;
22 use Irssi::TextUI;
23 use Net::vICQ;
24 use Data::Dumper;
25 use vars qw($icq $timer $old_status %contacts @requested $want_connect);
26
27 sub draw_box ($$$$) {
28 my ($title, $text, $footer, $colour) = @_;
29 my $box = '';
30 $box .= '%R,--[%n%9%U'.$title.'%U%9%R]%n'."\n";
31 foreach (split(/\n/, $text)) {
32 $box .= '%R|%n '.$_."\n";
33 }
34 $box .= '%R`--<%n'.$footer.'%R>->%n';
35 $box =~ s/%.//g unless $colour;
36 return $box;
37 }
38
39 sub show_help() {
40 my $help="IrssiQ $VERSION
41 /irssiq
42 List contact list
43 /irssiq connect
44 Connect to the ICQ network
45 /irssiq disconnect
46 Disconnect from ICQ network
47 /irssiq add <uin>
48 Add uin to contact list
49 /irssiq del <uin>
50 Delete uin from contact list
51 /irssiq auth <uin>
52 Authorize user to add your UIN to his contact list
53 /irssiq info <uin1> <uin2>....
54 Retrieve information about the uins
55 /irssiq invisible <uin>
56 Add or remove the UIN from your invisible list
57 /irssiq visible <uin>
58 Add or remove the UIN from your visible list
59 /irssiq hidden <uin>
60 Hide (or show) a uin in the statusbar
61 /irssiq msg <uin>
62 Send a message to uin
63 /irssiq query <uin>
64 Create a new query window with uin
65 /irssiq email
66 Send an email to uin
67 /irssiq status (away|online|na|occupied|dnd|invisible)
68 Change to the selected status
69 /irssiq save
70 Save contact list to file
71 /irssiq load
72 (Re-)Load contact list (reconnect afterwards)
73 ";
74 my $text = '';
75 foreach (split(/\n/, $help)) {
76 $_ =~ s/^\/(.*)$/%9\/$1%9/;
77 $text .= $_."\n";
78 }
79 print CLIENTCRAP draw_box($IRSSI{name}, $text, "help", 1);
80 }
81
82 sub call_openurl ($) {
83 my ($url) = @_;
84 no strict "refs";
85 # check for a loaded openurl
86 if (defined %{ "Irssi::Script::openurl::" }) {
87 &{ "Irssi::Script::openurl::launch_url" }($url);
88 } else {
89 print CLIENTCRAP "%R>>%n Please install openurl.pl";
90 }
91 }
92
93 sub store_openurl ($$$) {
94 my ($uin, $text, $url) = @_;
95 $url =~ s/\n/ /g;
96 $text =~ s/\n/ /g;
97 no strict "refs";
98 if (defined %{ "Irssi::Script::openurl::" }) {
99 &{ "Irssi::Script::openurl::new_url" }(undef, "IrssiQ", $uin, $text, $url);
100 } else {
101 print CLIENTCRAP "%R>>%n Please install openurl.pl";
102 }
103 }
104
105 sub output ($) {
106 print CLIENTCRAP $_ foreach split(/\n/, $_[0]);
107 }
108
109 sub icq_connect {
110 my $uin = Irssi::settings_get_int('irssiq_uin');
111 my $password = Irssi::settings_get_str('irssiq_password');
112 $icq = Net::vICQ->new($uin, $password, 0);
113 #$icq->{_Hide_IP} = 0;
114 $icq->Add_Hook("Srv_Mes_Received", \&MessageHandler);
115 $icq->Add_Hook("Srv_Srv_Message", \&MessageHandler);
116 $icq->Add_Hook("Srv_BLM_Contact_Online", \&MessageHandler);
117 $icq->Add_Hook("Srv_BLM_Contact_Offline", \&MessageHandler);
118 $icq->{_Status} = 'Online';
119 my $err;
120 output "%R>>%n Trying to connect to ICQ server...";
121 {
122 $icq->{_Auto_Login} = 1;
123 open FOO, '>>/dev/null';
124 my $oldfh = select(FOO);
125 $icq->Connect();
126 if(!($err = $icq->GetError())) {
127 while(!$icq->{_LoggedIn} && !($err = $icq->GetError())) {
128 $icq->Execute_Once();
129 }
130 }
131 select($oldfh);
132 }
133 if(!$err) {
134 output "%R<<%n ..connected!";
135 #my ($details);
136 #$details->{Status} = 'Online';
137 #$icq->Send_Command("Cmd_GSC_Set_Status", $details);
138 add_uin($uin) unless $contacts{$uin};
139 send_contacts();
140 $timer = Irssi::timeout_add(2000, 'icq_cycle', undef);
141 return 1;
142 } else {
143 output "%R<<%n ..failed!";
144 $want_connect = 0;
145 my $s = $err;
146 chomp($s);
147 print("%R>>%n ".$s);
148 return 0;
149 }
150 }
151
152 sub write_to_log ($$$$) {
153 my ($who, $direction, $type, $text) = @_;
154 my $dir = Irssi::get_irssi_dir();
155 mkdir $dir."/irssiq/" unless (-e $dir."/irssiq/");
156
157 my $data = $type." ".$direction." ".$who.":\n";
158 $data .= scalar(localtime())."\n";
159 $data .= $text."\n\n";
160
161 local *F;
162 open(F, '>>'.$dir."/irssiq/".$who);
163 print F $data;
164 close(F);
165 }
166
167 sub MessageHandler ($$) {
168 my ($icq, $details) = @_;
169 if (Irssi::settings_get_bool('irssiq_debug')) {
170 my $text;
171 foreach (keys %$details) {
172 my $content = $details->{$_};
173 no warnings;
174 #$content =~ s/\c.//g;
175 #$content =~ s/\pC//g;
176 $content =~ s/(?:(\n)|\pC)/$1/g;
177 $content =~ s/%/%%/g;
178 $text .= $_." -> <".$content.">\n";
179 }
180 #print CLIENTCRAP $_." -> <".$details->{$_}.">" foreach keys %$details;
181 print CLIENTCRAP &draw_box('IrssiQ', $text, 'debug', 1);
182 }
183 my $type = $details->{MessageType};
184 if ($type eq 'text_message' || $type eq 'offline_text_message' ) {
185 my $text = $details->{text};
186 # FIXME unicode stuff?!
187 no warnings;
188 #$text =~ s/\c.//g;
189 #$text =~ s/\pC//g;
190 $text =~ s/(?:(\n)|\pC)/$1/g;
191 write_to_log($details->{Sender}, 'from', 'msg', $text);
192 $text =~ s/%/%%/g;
193 my $output = draw_box("IrssiQ", $text, "msg from ".get_nick($details->{Sender}), 1);
194 # autocancels if there is already a window
195 start_query($details->{Sender}) if Irssi::settings_get_bool('irssiq_auto_open_query');
196 my $win = Irssi::window_find_name('<IrssiQ-'.$details->{Sender}.'>');
197 if (ref $win) {
198 if (Irssi::settings_get_bool('irssiq_msg_border_in_query')) {
199 $win->print($output, MSGLEVEL_MSGS);
200 } else {
201 $win->print("<".get_nick($details->{Sender})."> ".$text, MSGLEVEL_MSGS);
202 }
203 } else {
204 print MSGS $_ foreach split(/\n/, $output);
205 }
206 } elsif ($type eq 'URL') {
207 write_to_log($details->{Sender}, 'from', 'URL', $details->{URL});
208 my $output = draw_box("IrssiQ", "%U".$details->{URL}."%U", "URL from ".get_nick($details->{Sender}), 1);
209 my $win = Irssi::window_find_name('<IrssiQ-'.$details->{Sender}.'>');
210 unless (ref $win) {
211 print MSGS $_ foreach split(/\n/, $output);
212 } else {
213 $win->print("<".get_nick($details->{Sender})."> ".$details->{URL}, MSGLEVEL_MSGS);
214 }
215 store_openurl($details->{Sender}, $details->{URL}, $details->{URL});
216 } elsif ($type eq 'status_change') {
217 if ($details->{Sender} == Irssi::settings_get_int('irssiq_uin')) {
218 unless ($contacts{$details->{Sender}}{status} eq $details->{Status}) {
219 output "%R<<%n Changed own status to '".$details->{Status}."'.";
220 }
221 }
222 $contacts{$details->{Sender}}{status} = $details->{Status};
223 Irssi::statusbar_items_redraw('irssiq');
224 } elsif ($type eq 'user_info_main') {
225 my $uin = shift(@requested);
226 if ($contacts{$uin}) {
227 foreach (keys %$details) {
228 next if (/Ref|Our_UIN|MessageType|SubMessageType/);
229 $contacts{$uin}{user_info_main}{$_} = $details->{$_};
230 $contacts{$uin}{user_info_main}{$_} =~ s/ /_/g if $_ eq 'Nickname';
231 }
232 }
233 show_short_info($uin, $details);
234 Irssi::statusbar_items_redraw('irssiq');
235 next_info();
236 } elsif ($type eq 'user_info_not_found') {
237 my $uin = shift(@requested);
238 output "%R>>%n Information about UIN ".$uin." not found";
239 next_info();
240 } elsif ($type eq 'add_message') {
241 output draw_box("IrssiQ", $details->{Sender}." added you to his/her contact list", "added by ".$details->{Sender}, 1);
242 } elsif ($type eq 'auth_request') {
243 get_userinfo($details->{Sender});
244 output draw_box("IrssiQ", $details->{reason}, "auth-request from ".$details->{Sender}, 1);
245 } elsif ($type eq 'Invalid tagged message') {
246 # Webmessage
247 my $string = $details->{TaggedDataString};
248 $string =~ s/\pC//g;
249 $string =~ /\d+\.\d+\.\d+\.\d+(.*)/;
250 write_to_log("Webmessage", 'from', 'msg', $1);
251 print CLIENTCRAP &draw_box("IrssiQ", $1, "WebMessage", 1);
252 }
253 }
254
255 sub next_info {
256 return unless defined $requested[0];
257 my $uin = $requested[0];
258 output "%B>>%n Requesting user information for UIN #$uin";
259 my %details = (
260 MessageType => "Get_WP_Info",
261 TargetUIN => $uin,
262 );
263 $icq->Send_Command("Cmd_Srv_Message", \%details);
264 }
265
266 sub get_userinfo ($) {
267 my ($uin) = @_;
268 push @requested, $uin;
269 next_info if (scalar(@requested) == 1);
270 }
271
272 sub icq_cycle {
273 return unless ($icq);
274 $icq->Send_Keep_Alive();
275 $icq->Execute_Once();
276 unless ($icq->{_Connected}) {
277 Irssi::timeout_remove($timer);
278 output "%R>>%n IrssiQ disconnected";
279 $contacts{$_}{status} = 'Offline' foreach keys %contacts;
280 if (Irssi::settings_get_bool('irssiq_auto_reconnect') && $want_connect) {
281 icq_connect();
282 }
283 }
284 }
285
286 sub send_message ($$$) {
287 my ($icq, $uin, $text) = @_;
288 my $details = { uin => $uin,
289 MessageType => 'text',
290 text => $text
291 };
292 write_to_log($uin, 'to', 'msg', $text);
293 $icq->Send_Command("Cmd_Send_Message", $details);
294 my $win = Irssi::window_find_name('<IrssiQ-'.$uin.'>');
295 my $output = draw_box("IrssiQ", $text, "msg to ".get_nick($uin), 1);
296 unless (ref $win) {
297 print CLIENTCRAP $_ foreach split(/\n/, $output);
298 } else {
299 my $my_uin = Irssi::settings_get_int('irssiq_uin');
300 $win->print("<".get_nick($my_uin)."> ".$text, MSGLEVEL_CLIENTCRAP);
301 }
302 }
303
304 sub array2table {
305 my (@array) = @_;
306 my @width;
307 foreach my $line (@array) {
308 for (0..scalar(@$line)) {
309 my $l = $line->[$_];
310 $l =~ s/%[^%]//g;
311 $l =~ s/%%/%/g;
312 $width[$_] = length($l) if $width[$_]<length($l);
313 }
314 }
315 my $text;
316 foreach my $line (@array) {
317 for (0..scalar(@$line)) {
318 my $l = $line->[$_];
319 $text .= $line->[$_];
320 $l =~ s/%[^%]//g;
321 $l =~ s/%%/%/g;
322 $text .= " "x($width[$_]-length($l)+1);
323 }
324 $text .= "\n";
325 }
326 return $text;
327 }
328
329
330 sub list_contacts {
331 my $text;
332 my @array;
333 my $my_uin = Irssi::settings_get_int('irssiq_uin');
334 foreach (sort {$contacts{$a}{status} cmp $contacts{$b}{status}} keys %contacts) {
335 my @line;
336 next if $_ eq $my_uin;
337 my $status = $contacts{$_}{status};
338 next if ($status eq 'Offline' && not Irssi::settings_get_bool('irssiq_list_show_offline'));
339 if ($status eq "Online") {
340 push @line, "%go%n";
341 } else {
342 push @line, "%ro%n";
343 }
344 push @line, $status;
345 if ($contacts{$_}{user_info_main} && $contacts{$_}{user_info_main}{Nickname}) {
346 push @line, '['.$contacts{$_}{user_info_main}{Nickname}.']';
347 } else {
348 push @line, '';
349 }
350 push @line, $_;
351 if ($contacts{$_}{invisible}) {
352 push @line, '%B<Inv>%n';
353 } else {
354 push @line, "";
355 }
356 if ($contacts{$_}{visible}) {
357 push @line, '%G<Vis>%n';
358 } else {
359 push @line, "";
360 }
361 if ($contacts{$_}{hide_in_sb}) {
362 push @line, '%B<Hidden>%n';
363 } else {
364 push @line, "";
365 }
366 push @array, \@line;
367 }
368 my %table = (Online => '%G==Online==%n',
369 Away => '%R===Away===%n',
370 'Do Not Disturb' => '%B===DnD====%n',
371 Occupied => '%Y=Occupied=%n',
372 Invisible => '%C===Inv====%n',
373 'N/A' => '%Y===N/A====%n',
374 Offline => '%R=Offline==%n'
375 );
376 $text = array2table(@array);
377 $text .= $table{$contacts{$my_uin}{status}}."\n";
378 output draw_box('IrssiQ', $text, 'contacts', 1);
379 }
380
381 sub add_uin ($) {
382 my ($uin) = @_;
383 $contacts{$uin} = { status => 'Offline' } unless defined $contacts{$uin};
384 Irssi::statusbar_items_redraw('irssiq');
385 get_userinfo($uin) if ($icq && $icq->{_Connected});
386 }
387
388 sub del_uin ($) {
389 my ($uin) = @_;
390 return unless defined $contacts{$uin};
391 delete $contacts{$uin};
392 }
393
394 sub send_contacts {
395 my ($details, $details2, $details3);
396 my @uins;
397 my @inv;
398 my @vis;
399 foreach (keys(%contacts)) {
400 push @uins, $_;
401 push @inv, $_ if $contacts{$_}{invisible};
402 push @vis, $_ if $contacts{$_}{visible};
403 }
404 $details->{ContactList} = \@uins;
405 $icq->Send_Command("Cmd_Add_ContactList", $details);
406 $icq->Send_Command("Cmd_CTL_UploadList", $details);
407 $details2->{InVisibleList} = \@inv;
408 $details3->{VisibleList} = \@vis;
409 $icq->Send_Command("Cmd_BOS_Add_InVisibleList", $details2) if @inv;
410 $icq->Send_Command("Cmd_BOS_Add_VisibleList", $details3) if @vis;
411 }
412
413 sub save_contacts {
414 my $dir = Irssi::get_irssi_dir();
415 my $dumper = Data::Dumper->new([\%contacts], ['contacts']);
416 $dumper->Purity(1)->Deepcopy(1);
417 my $data = $dumper->Dump;
418 local *F;
419 open(F, '>'.$dir.'/irssiq_contacts');
420 print F $data;
421 close(F);
422 output "%R>>%n IrssiQ contacts saved";
423 }
424
425 sub load_contacts {
426 my $text;
427 my $dir = Irssi::get_irssi_dir();
428 return unless (-e $dir.'/irssiq_contacts');
429 local *F;
430 open F, "<".$dir.'/irssiq_contacts';
431 $text .= $_ foreach (<F>);
432 close(F);
433 if ($text) {
434 no strict;
435 my %friends = %{ eval "$text" };
436 foreach (keys %friends) {
437 next if defined $contacts{$_};
438 $contacts{$_} = $friends{$_};
439 $contacts{$_}{status} = 'Offline';
440 }
441 }
442 }
443
444 sub show_short_info ($$) {
445 my ($uin, $details) = @_;
446 my $text = "== ".$details->{Nickname}." ==\n";
447 $text .= "Name : ".$details->{Firstname}." ".$details->{Lastname}."\n";
448 $text .= "eMail: ".$details->{Email}."\n";
449 output draw_box('IrssiQ', $text, $uin, 1);
450 }
451
452 sub set_status ($) {
453 my ($status) = @_;
454 $status =~ s/ /_/g;
455 my %table = (online => 'Online',
456 away => 'Away',
457 na => 'Not_Available',
458 occupied => 'Occupied',
459 dnd => 'Do_Not_Disturb',
460 invisible => 'Invisible',
461 ffc => 'Free_For_Chat'
462 );
463 my %options = %table;
464 $options{'N/A'} = 'Not_Available';
465 $options{ $table{$_} } = $table{$_} foreach keys %table;
466 unless (defined $options{$status}) {
467 output "%R>>%n '".$status."' is an invalid status";
468 output "%R>>%n Valid options are: ".join(" ", keys(%table));
469 return;
470 }
471 my ($details);
472 $details->{Status} = $options{$status};
473 $icq->Send_Command("Cmd_GSC_Set_Status", $details);
474 }
475
476 sub sig_away ($) {
477 my ($server) = @_;
478 return unless ($icq && $icq->{_Connected});
479 my $away_status = Irssi::settings_get_str('irssiq_away_status');
480 if ($server->{usermode_away}) {
481 my $uin = Irssi::settings_get_str('irssiq_uin');
482 $old_status = $contacts{$uin}{status};
483 set_status($away_status);
484 } else {
485 set_status($old_status);
486 }
487 }
488
489 sub sb_show ($$) {
490 my ($item, $get_size_only) = @_;
491 my $line = "";
492 my %users;
493 my $more = 0;
494 foreach my $uin (sort {$contacts{$a}{status} cmp $contacts{$b}{status}} keys %contacts) {
495 next if $uin eq Irssi::settings_get_str('irssiq_uin');
496 my $status = $contacts{$uin}{status};
497 next if $status eq '';
498 next if ($status eq 'Online' && not Irssi::settings_get_bool('irssiq_statusbar_show_online'));
499 next if ($status eq 'Offline' && not Irssi::settings_get_bool('irssiq_statusbar_show_offline'));
500 next if ($status eq 'Away' && not Irssi::settings_get_bool('irssiq_statusbar_show_away'));
501 next if ($status eq 'Do Not Disturb' && not Irssi::settings_get_bool('irssiq_statusbar_show_dnd'));
502 next if ($status eq 'Occupied' && not Irssi::settings_get_bool('irssiq_statusbar_show_occupied'));
503 next if ($status eq 'Invisible' && not Irssi::settings_get_bool('irssiq_statusbar_show_invisible'));
504 next if ($status eq 'N/A' && not Irssi::settings_get_bool('irssiq_statusbar_show_not_available'));
505 if ($contacts{$uin}{hide_in_sb}) { $more = 1; next; }
506 # FIXME Irssi bug?!
507 my %table = (Online => '%gO%n',
508 Away => '%rA%n',
509 'Do Not Disturb' => '%bD%n',
510 Occupied => '%yOc%n',
511 Invisible => '%cI%n',
512 'N/A' => '%yN%n',
513 'Offline' => '%RO%n'
514 );
515 unless (Irssi::settings_get_bool('irssiq_statusbar_compact')) {
516 $line .= '<';
517 if (defined $table{$status}) {
518 $line .= $table{$status};
519 } else {
520 $line .= substr($status, 0, 1);
521 }
522 $line .= '%bI%n' if $contacts{$uin}{invisible};
523 $line .= '%gV%n' if $contacts{$uin}{visible};
524 $line .= '>';
525 if ($contacts{$uin}{user_info_main} && $contacts{$uin}{user_info_main}{Nickname}) {
526 $line .= $contacts{$uin}{user_info_main}{Nickname}." ";
527 } else {
528 $line .= $uin." ";
529 }
530 } else {
531 push @{ $users{$table{$status}} }, $uin;
532 }
533 }
534 if (Irssi::settings_get_bool('irssiq_statusbar_compact')) {
535 foreach (keys %users) {
536 $line .= '<'.$_;
537 foreach my $uin (@{ $users{$_} }) {
538 $line .= ' '.get_nick($uin);
539 }
540 $line .= '>';
541 }
542 }
543 my %table = (Online => '%G==Online==%n',
544 Away => '%R===Away===%n',
545 'Do Not Disturb' => '%B===DnD====%n',
546 Occupied => '%Y=Occupied=%n',
547 Invisible => '%C===Inv====%n',
548 'N/A' => '%Y===N/A====%n',
549 Offline => '%R=Offline==%n'
550 );
551 if (Irssi::settings_get_bool('irssiq_statusbar_short_status')) {
552 %table = (Online => '%G(On)%n',
553 Away => '%R(Aw)%n',
554 'Do Not Disturb' => '%B(DnD)%n',
555 Occupied => '%Y(Inv)%n',
556 'N/A' => '%Y(NA)%n',
557 Offline => '%R(Off)%n'
558 );
559 }
560 my $my_uin = Irssi::settings_get_int('irssiq_uin');
561 $line .= '...' if $more;
562 $line .= $table{$contacts{$my_uin}{status}};
563
564 my $format = "{sb ".$line."}";
565 $item->{min_size} = $item->{max_size} = length($line);
566 $item->default_handler($get_size_only, $format, 0, 1);
567 }
568
569 sub get_uin ($) {
570 my ($input) = @_;
571 return $input if $input =~ /^[0-9]+$/;
572
573 foreach (keys %contacts) {
574 if ($contacts{$_}{user_info_main} && $contacts{$_}{user_info_main}{Nickname}) {
575 return $_ if lc($contacts{$_}{user_info_main}{Nickname}) eq lc($input);
576 }
577 }
578 return undef;
579 }
580
581 sub get_nick ($) {
582 my ($uin) = @_;
583 if ($contacts{$uin} && $contacts{$uin}{user_info_main}) {
584 return $contacts{$uin}{user_info_main}{Nickname};
585 }
586 # Fallback
587 return $uin;
588 }
589
590 sub send_auth ($) {
591 my ($uin) = @_;
592 return unless $uin =~ /^[0-9]+$/;
593 my ($details);
594 $details->{uin} = $uin;
595 $icq->Send_Command("Cmd_Authorize", $details);
596 output "%R>>%n Authorization sent to ".$uin;
597 }
598
599 sub start_query ($) {
600 my ($uin) = @_;
601 return if ref Irssi::window_find_name('<IrssiQ-'.$uin.'>');
602 Irssi::command("window new hide");
603 my $win = Irssi::active_win;
604 $win->set_name('<IrssiQ-'.$uin.'>');
605 $win->set_history('<IrssiQ-'.$uin.'>');
606 $win->print('Starting IrssiQ query with '.get_nick($uin).' ('.$uin.')');
607 }
608
609 sub sig_send_text ($) {
610 my ($text, $foo1, $foo2) = @_;
611 my $win = Irssi::active_win;
612 return unless (ref $win && $win->{name} =~ /<IrssiQ-(\d+)>/);
613 my $uin = $1;
614 if ($icq && $icq->{_Connected}) {
615 send_message($icq, $uin, $text);
616 } else {
617 $win->print("%R>>%n You are not connected to ICQ", MSGLEVEL_CLIENTCRAP);
618 }
619 }
620
621 sub send_url ($$$) {
622 my ($uin, $url, $description) = @_;
623 return unless ($icq && $icq->{_Connected});
624 my %details = ( uin => $uin,
625 MessageType => 'url',
626 URL => $url,
627 Description => $description
628 );
629 write_to_log($uin, 'to', 'url', $url."\n".$description);
630 $icq->Send_Command("Cmd_Send_Message", \%details);
631 my $win = Irssi::window_find_name('<IrssiQ-'.$uin.'>');
632 my $output = draw_box("IrssiQ", $url, "url to ".get_nick($uin), 1);
633 unless (ref $win) {
634 output $output;
635 } else {
636 my $my_uin = Irssi::settings_get_int('irssiq_uin');
637 $win->print("<".get_nick($my_uin)."> ".$url, MSGLEVEL_CRAP);
638 }
639
640 }
641 # calles by scriptassist on reload
642 sub pre_unload {
643 save_contacts();
644 return unless $icq->{_Connected};
645 $icq->Disconnect() if ($icq && $icq->{_Connected});
646 while ($icq->{_Connected}) {
647 $icq->Execute_Once();
648 }
649 $contacts{$_}{status} = 'Offline' foreach keys %contacts;
650 output "%R>>%n IrssiQ disconnected";
651 }
652
653 sub sig_complete_word ($$$$$) {
654 my ($list, $window, $word, $linestart, $want_space) = @_;
655 return unless $linestart =~ /^.irssiq (\w+)/;
656 my @newlist;
657 if ($1 eq 'status') {
658 foreach (('online', 'away', 'na', 'occupied', 'dnd', 'invisible', 'ffc')) {
659 push @newlist, $_ if /^(\Q$word\E.*)?$/i;
660 }
661 } else {
662 foreach (keys %contacts) {
663 push @newlist, $_ if /^(\Q$word\E.*)?$/;
664 if ($contacts{$_}{user_info_main} && $contacts{$_}{user_info_main}{Nickname}) {
665 push @newlist, $contacts{$_}{user_info_main}{Nickname} if $contacts{$_}{user_info_main}{Nickname} =~ /^(\Q$word\E.*)?$/i;
666 }
667 }
668 }
669 $want_space = 0;
670 push @$list, $_ foreach @newlist;
671
672 }
673
674 sub toggle_inv_list ($) {
675 my ($uin) = @_;
676 return unless defined $contacts{$uin};
677 $contacts{$uin}{invisible} = not $contacts{$uin}{invisible};
678 my ($details);
679 $details->{InVisibleList} = [$uin];
680 if ($contacts{$uin}{invisible}) {
681 $icq->Send_Command("Cmd_BOS_Add_InVisibleList", $details) if $icq->{_Connected};
682 output "%B>>%n You are now invisible for ".get_nick($uin)." (".$uin.")";
683 } else {
684 $icq->Send_Command("Cmd_BOS_Remove_InVisibleList", $details) if $icq->{_Connected};
685 output "%B>>%n You are no longer invisible for ".get_nick($uin)." (".$uin.")";
686 }
687 }
688
689 sub toggle_vis_list ($) {
690 my ($uin) = @_;
691 return unless defined $contacts{$uin};
692 $contacts{$uin}{visible} = not $contacts{$uin}{visible};
693 my ($details);
694 $details->{VisibleList} = [$uin];
695 if ($contacts{$uin}{visible}) {
696 $icq->Send_Command("Cmd_BOS_Add_VisibleList", $details) if $icq->{_Connected};
697 output "%B>>%n You are now visible for ".get_nick($uin)." (".$uin.")";
698 } else {
699 $icq->Send_Command("Cmd_BOS_Remove_VisibleList", $details) if $icq->{_Connected};
700 output "%B>>%n You are no longer visible for ".get_nick($uin)." (".$uin.")";
701 }
702 }
703
704 sub toggle_hidden ($) {
705 my ($uin) = @_;
706 return unless defined $contacts{$uin};
707 $contacts{$uin}{hide_in_sb} = not $contacts{$uin}{hide_in_sb};
708 if ($contacts{$uin}{hide_in_sb}) {
709 output "%B>>%n ".get_nick($uin)." (".$uin.") is now hidden";
710 } else {
711 output "%B>>%n ".get_nick($uin)." (".$uin.") is no longer hidden";
712 }
713 Irssi::statusbar_items_redraw('irssiq');
714 }
715
716 sub cmd_irssiq ($$$) {
717 my ($args, $server, $witem) = @_;
718 my @arg = split / +/, $args;
719 if (scalar(@arg) == 0) {
720 list_contacts();
721 } elsif ($arg[0] eq 'connect') {
722 $want_connect = 1;
723 icq_connect();
724 } elsif ($arg[0] eq 'disconnect') {
725 $want_connect = 0;
726 $icq->Disconnect() if ($icq && $icq->{_Connected});
727 } elsif ($arg[0] eq 'msg' && defined $arg[1] && defined $arg[2]) {
728 my $uin = get_uin($arg[1]);
729 return unless $uin;
730 shift @arg;
731 shift @arg;
732 send_message($icq, $uin, join(" ", @arg));
733 } elsif ($arg[0] eq 'url' && defined $arg[1] && defined $arg[2]) {
734 my $uin = get_uin($arg[1]);
735 return unless $uin;
736 my $url = $arg[2];
737 shift @arg;
738 shift @arg;
739 send_url($uin, $url, join(" ", @arg));
740 } elsif ($arg[0] eq 'auth' && defined $arg[1]) {
741 send_auth($arg[1]) if ($icq && $icq->{_Connected});
742 } elsif ($arg[0] eq 'email' && defined $arg[1]) {
743 my $uin = get_uin($arg[1]);
744 return unless $uin;
745 if ($contacts{$uin} && $contacts{$uin}{user_info_main}) {
746 call_openurl($contacts{$uin}{user_info_main}{Email}) if $contacts{$uin}{user_info_main}{Email};
747 }
748 } elsif ($arg[0] eq 'add' && defined $arg[1]) {
749 shift @arg;
750 foreach (@arg) {
751 next unless $_ =~ /^[0-9]+$/;
752 add_uin($_);
753 output "%B>>%n Added UIN ".$_." to contact list";
754 }
755 send_contacts() if ($icq && $icq->{_Connected});
756 } elsif ($arg[0] eq 'del' && defined $arg[1]) {
757 shift @arg;
758 foreach (@arg) {
759 next unless $_ =~ /^[0-9]+$/;
760 del_uin($_);
761 output "%B>>%n Removed UIN ".$_." from contact list";
762 }
763 send_contacts() if ($icq && $icq->{_Connected});
764 } elsif ($arg[0] eq 'save') {
765 save_contacts();
766 } elsif ($arg[0] eq 'load') {
767 load_contacts();
768 send_contacts if ($icq && $icq->{_Connected});
769 } elsif ($arg[0] eq 'info') {
770 shift @arg;
771 foreach (@arg) {
772 my $uin = get_uin($_);
773 get_userinfo($uin) if $uin;
774 }
775 } elsif ($arg[0] eq 'status' && defined $arg[1]) {
776 set_status($arg[1]) if ($icq && $icq->{_Connected});
777 } elsif ($arg[0] eq 'query' && defined $arg[1]) {
778 my $uin = get_uin($arg[1]);
779 start_query($uin) if $uin;
780 } elsif ($arg[0] eq 'invisible') {
781 my $uin = get_uin($arg[1]);
782 toggle_inv_list($uin);
783 } elsif ($arg[0] eq 'visible') {
784 my $uin = get_uin($arg[1]);
785 toggle_vis_list($uin);
786 } elsif ($arg[0] eq 'hidden') {
787 my $uin = get_uin($arg[1]);
788 toggle_hidden($uin);
789 } elsif ($arg[0] eq 'help') {
790 show_help();
791 }
792 }
793
794 Irssi::settings_add_int($IRSSI{name}, 'irssiq_uin', '');
795 Irssi::settings_add_str($IRSSI{name}, 'irssiq_password', '');
796 Irssi::settings_add_bool($IRSSI{name}, 'irssiq_debug', 0);
797
798 Irssi::settings_add_bool($IRSSI{name}, 'irssiq_statusbar_show_online', 1);
799 Irssi::settings_add_bool($IRSSI{name}, 'irssiq_statusbar_show_offline', 0);
800 Irssi::settings_add_bool($IRSSI{name}, 'irssiq_statusbar_show_away', 1);
801 Irssi::settings_add_bool($IRSSI{name}, 'irssiq_statusbar_show_dnd', 1);
802 Irssi::settings_add_bool($IRSSI{name}, 'irssiq_statusbar_show_occupied', 1);
803 Irssi::settings_add_bool($IRSSI{name}, 'irssiq_statusbar_show_invisible', 1);
804 Irssi::settings_add_bool($IRSSI{name}, 'irssiq_statusbar_show_not_available', 1);
805 Irssi::settings_add_bool($IRSSI{name}, 'irssiq_statusbar_short_status', 0);
806 Irssi::settings_add_bool($IRSSI{name}, 'irssiq_list_show_offline', 1);
807 Irssi::settings_add_bool($IRSSI{name}, 'irssiq_statusbar_compact', 0);
808 Irssi::settings_add_bool($IRSSI{name}, 'irssiq_auto_open_query', 0);
809
810 Irssi::settings_add_str($IRSSI{name}, 'irssiq_away_status', 'away');
811
812 Irssi::settings_add_bool($IRSSI{name}, 'irssiq_msg_border_in_query', 0);
813 Irssi::settings_add_bool($IRSSI{name}, 'irssiq_auto_reconnect', 1);
814
815 Irssi::signal_add_first('complete word', \&sig_complete_word);
816 Irssi::signal_add('setup saved', \&save_contacts);
817 Irssi::signal_add('away mode changed', \&sig_away);
818 Irssi::signal_add('send text', \&sig_send_text);
819
820 Irssi::statusbar_item_register('irssiq', 0, 'sb_show');
821
822 Irssi::command_bind('irssiq', \&cmd_irssiq);
823
824 foreach my $cmd ('help', 'connect', 'disconnect', 'msg', 'auth', 'email', 'save', 'load', 'add', 'del', 'info', 'status', 'query', 'url', 'invisible', 'visible', 'hidden' ) {
825 Irssi::command_bind('irssiq '.$cmd => sub {
826 cmd_scripassist("$cmd ".$_[0], $_[1], $_[2]); });
827 }
828
829 load_contacts();
830
831 print CLIENTCRAP '%B>>%n '.$IRSSI{name}.' '.$VERSION.' loaded: /irssiq help for help';