html/friends_peder.pl


   1 # friends - irssi 0.8.4.CVS
   2 #
   3 #    $Id: friends.pl,v 1.34 2004/03/08 21:47:12 peder Exp $
   4 #
   5 # Copyright (C) 2001, 2002, 2003 by Peder Stray <peder@ninja.no>
   6 #
   7 
   8 use strict;
   9 use Irssi 20020427.2353;
  10 use Irssi::Irc;
  11 use Irssi::TextUI;
  12 
  13 use Data::Dumper;
  14 $Data::Dumper::Indent = 1;
  15 
  16 # ======[ Script Header ]===============================================
  17 
  18 use vars qw{$VERSION %IRSSI};
  19 ($VERSION) = '$Revision: 1.34 $' =~ / (\d+\.\d+) /;
  20 %IRSSI = (
  21           name        => 'friends',
  22           authors     => 'Peder Stray',
  23           contact     => 'peder@ninja.no',
  24           url         => 'http://ninja.no/irssi/friends.pl',
  25           license     => 'GPL',
  26           description => 'Basicly an autoop script with a nice interface and nick coloring ;)',
  27          );
  28 
  29 # ======[ Variables ]===================================================
  30 
  31 my(%friends, @friends);
  32 
  33 my(%flagshort) = (
  34 		  op => 'o',
  35 		  voice => 'v',
  36 		  color => 'c',
  37 		 );
  38 my(%flaglong) = map { $flagshort{$_} => $_ } keys %flagshort;
  39 
  40 # ======[ Helper functions ]============================================
  41 
  42 # --------[ crap ]------------------------------------------------------
  43 
  44 sub crap {
  45     my $template = shift;
  46     my $msg = sprintf $template, @_;
  47     Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'friends_crap', $msg);
  48 }
  49 
  50 # --------[ load_friends ]----------------------------------------------
  51 
  52 sub load_friends {
  53     my($file) = Irssi::get_irssi_dir."/friends";
  54     my($count) = 0;
  55     my($mask,$net,$channel,$flags,$flag);
  56     local(*FILE);
  57 
  58     %friends = ();
  59     open FILE, "< $file";
  60     while (<FILE>) {
  61 	($mask,$net,$channel,$flags) = split;
  62 	for (split //, $flags) {
  63 	    if ($flag = $flaglong{$_}) {
  64 		$friends{$mask}{lc $net}{lc $channel}{$flag} = 1;
  65 	    }
  66 	}
  67     }
  68     close FILE;
  69     $count = keys %friends;
  70     
  71     crap("Loaded $count friends from $file");
  72 }
  73 
  74 # --------[ save_friends ]----------------------------------------------
  75 
  76 sub save_friends {
  77     my($auto) = @_;
  78     my($file) = Irssi::get_irssi_dir."/friends";
  79     my($count) = 0;
  80     local(*FILE);
  81 
  82     return if $auto && !Irssi::settings_get_bool('friends_autosave');
  83 
  84     open FILE, "> $file";
  85     for my $mask (keys %friends) {
  86 	$count++;
  87 	for my $net (keys %{$friends{$mask}}) {
  88 	    for my $channel (keys %{$friends{$mask}{$net}}) {
  89 		print FILE "$mask\t$net\t$channel\t".
  90 		  join("", sort map {$flagshort{$_}} keys %{$friends{$mask}{$net}{$channel}}).
  91 		    "\n";
  92 	    }
  93 	}
  94     }
  95     close FILE;
  96 
  97     crap("Saved $count friends to $file")
  98       unless $auto;
  99 }
 100 
 101 # --------[ is_friends_window ]-----------------------------------------
 102 
 103 sub is_friends_window {
 104     my($win) = @_;
 105     return $win->{name} eq '<Friends>';
 106 }
 107 
 108 # --------[ get_friends_window ]----------------------------------------
 109 
 110 sub get_friends_window {
 111     my($win) = Irssi::window_find_name('<Friends>');
 112     if ($win) {
 113 	$win->set_active;
 114     } else {
 115 	Irssi::command("window new hide");
 116 	$win = Irssi::active_win;
 117 	$win->set_name('<Friends>');
 118 	$win->set_history('<Friends>');
 119     }
 120     return $win;
 121 }
 122 
 123 # --------[ get_friend ]------------------------------------------------
 124 
 125 sub get_friend {
 126     my($channel,$nick) = @_;
 127     my($server) = $channel->{server};
 128     my($chan) = lc $channel->{name};
 129     my($net) = lc $server->{chatnet};
 130     my($flags,@friend);
 131     
 132     for my $mask (keys %friends) {
 133 	next unless $server->mask_match_address($mask, 
 134 						$nick->{nick},
 135 						$nick->{host});
 136 	for my $n ('*', $net) {
 137 	    for my $c ('*', $chan) {
 138 		if (exists $friends{$mask}{$n}{$c}) {
 139 		    for my $flag (keys %{$friends{$mask}{$n}{$c}}) {
 140 			$flags->{$flag} = 1;
 141 		    }
 142 		}
 143 	    }
 144 	}
 145 	return $flags if $flags;
 146     }
 147     return undef;
 148 }
 149 
 150 # --------[ check_friends ]---------------------------------------------
 151 
 152 sub check_friends {
 153     my($channel, @nicks) = @_;
 154     my(%op,%voice);
 155     my($nick,$friend,$list); 
 156     my(@friends);
 157 
 158     return unless $channel->{chanop} || $channel->{ownnick}{op};
 159 
 160     for $nick (@nicks) {
 161 	$friend = get_friend($channel, $nick);
 162 	next unless $friend;
 163 	next if $nick->{nick} eq $channel->{server}{nick};
 164 	if ($friend->{op} && !$nick->{op}) {
 165 	    $op{$nick->{nick}} = 1;
 166 	}
 167 	if ($friend->{voice} && !$nick->{voice}) {
 168 	    $voice{$nick->{nick}} = 1;
 169 	}
 170 	push @friends, ($nick->{op}?'@':'').
 171 	  ($nick->{voice}?'+':'').$nick->{nick};
 172     }
 173 
 174     if (@friends && Irssi::settings_get_bool("friends_show_check")) {
 175 	my($max) = Irssi::settings_get_int("friends_max_nicks");
 176 	@friends = sort @friends;
 177 	$channel->printformat(MSGLEVEL_CLIENTCRAP,
 178 			      @friends>$max 
 179 			      ? 'friends_check_more' : 'friends_check',
 180 			      join(" ", splice @friends, 0, $max),
 181 			      scalar @friends);
 182     }
 183 
 184     if ($list = join " ", sort keys %op) {
 185         $channel->command("op $list");
 186     }
 187     if ($list = join " ", sort keys %voice) {
 188         $channel->command("voice $list");
 189     }
 190 }
 191 
 192 # --------[ update_friends_hash ]---------------------------------------
 193 
 194 sub update_friends_hash {
 195     %friends = ();
 196     for (@friends) {
 197 	my($num,$mask,$chan,$net,$flags) = @$_;
 198 	for (split //, $flags) {
 199 	    $friends{$mask}{$net}{$chan}{$flaglong{$_}} = 1;
 200 	}
 201     }
 202 }
 203 
 204 # --------[ update_friends_window ]-------------------------------------
 205 
 206 sub update_friends_window {
 207     my($win) = Irssi::window_find_name('<Friends>');
 208     my($view);
 209     my($num) = 0;
 210     my($mask,$net,$channel,$flags);
 211 
 212     my(%net);
 213 
 214     if ($win) {
 215 	@friends = ();
 216 	for $mask (sort keys %friends) {
 217 	    for $net (sort keys %{$friends{$mask}}) {
 218 		for $channel (sort keys %{$friends{$mask}{$net}}) {
 219 		    $flags = join "", sort map {$flagshort{$_}} 
 220 		      keys %{$friends{$mask}{$net}{$channel}};
 221 		    push @friends, [ ++$num, $mask, $channel, $net, $flags ];
 222 		}
 223 	    }
 224 	}
 225 
 226 	$view = $win->view;
 227 	$view->remove_all_lines();
 228 	$view->clear();
 229 	$win->printformat(MSGLEVEL_NEVER, 'friends_header',
 230 			  '##', 'Mask', 'Channel', 'ChatNet', 'Flags');
 231 	for (@friends) {
 232 	    ($num,$mask,$channel,$net,$flags) = @$_;
 233 	    if (!$net{$net}) {
 234 		my($n) = Irssi::chatnet_find($net);
 235 		$net{$net} = $n?$n->{name}:$net;
 236 	    }
 237 	    $win->printformat(MSGLEVEL_NEVER, 'friends_line',
 238 			      $num, $mask, $channel, $net{$net}, $flags);
 239 	}
 240 	$win->printformat(MSGLEVEL_NEVER, 'friends_footer', scalar @friends);
 241     }
 242 }
 243 
 244 # ======[ Signal Hooks ]================================================
 245 
 246 # --------[ sig_send_command ]------------------------------------------
 247 
 248 sub sig_send_command {
 249     my($win) = Irssi::active_win;
 250     if (is_friends_window($win)) {
 251 	my($cmd,@param) = split " ", $_[0];
 252 	my($changed) = 0;
 253 
 254 	Irssi::signal_stop;
 255 
 256 	for (lc $cmd) {
 257 	    s,^/,,;
 258 	    if (/^m(ask)?$/) {
 259 		$changed = subcmd_friends_mask($win,@param);
 260 
 261 	    } elsif (/^c(han(nel)?)?$/) {
 262 		$changed = subcmd_friends_channel($win,@param);
 263 
 264 	    } elsif (/^(?:n(et)?|chat(net)?)$/) {
 265 		$changed = subcmd_friends_net($win,@param);
 266 		
 267 	    } elsif (/^del(ete)?$/) {
 268 		$changed = subcmd_friends_delete($win,@param);
 269 		
 270 	    } elsif (/^f(lags?)?$/) {
 271 		$changed = subcmd_friends_flags($win,@param);
 272 
 273 	    } elsif (/^s(ave)?/) {
 274 		save_friends();
 275 
 276 	    } elsif (/^(?:e(xit)?|q(uit)?)$/) {
 277 		$win->destroy;
 278 
 279 	    } elsif (/^(?:h(elp)?|\?)$/) {
 280 		subcmd_friends_help($win);
 281 
 282 	    } else {
 283 		$win->print("CMD: $cmd @{[map{\"[$_]\"}@param]}");
 284 
 285 	    }
 286 	}
 287 
 288 	if ($changed) {
 289 	    update_friends_hash();
 290 	    update_friends_window();
 291 	    save_friends(1);
 292 	}
 293     }
 294 }
 295 
 296 # --------[ sig_massjoin ]----------------------------------------------
 297 
 298 sub sig_massjoin {
 299     my($channel, $nicks) = @_;
 300     check_friends($channel, @$nicks);
 301 }
 302 
 303 # --------[ sig_nick_mode_changed ]-------------------------------------
 304 
 305 sub sig_nick_mode_changed {
 306     my($channel, $nick) = @_;
 307     if ($channel->{synced} && $channel->{server}{nick} eq $nick->{nick}) {
 308 	check_friends($channel, $channel->nicks);
 309     }
 310 }
 311 
 312 # --------[ sig_channel_sync ]------------------------------------------
 313 
 314 sub sig_channel_sync {
 315     my($channel) = @_;
 316     check_friends($channel, $channel->nicks);
 317 }
 318 
 319 # --------[ sig_setup_reread ]------------------------------------------
 320 
 321 sub sig_setup_reread {
 322     load_friends;
 323 }
 324 
 325 # --------[ sig_setup_save ]--------------------------------------------
 326 
 327 sub sig_setup_save {
 328     my($mainconf,$auto) = @_;
 329     save_friends($auto);
 330 }
 331 
 332 # --------[ sig_window_changed ]----------------------------------------
 333 
 334 sub sig_window_changed {
 335     my($new,$old) = @_;
 336     if (is_friends_window($new)) {
 337 	update_friends_window();
 338     }
 339 }
 340 
 341 # --------[ sig_message_public ]----------------------------------------
 342 
 343 sub sig_message_public {
 344     my($server, $msg, $nick, $addr, $target) = @_;
 345     my($window,$theme,$friend,$oform,$nform);
 346     my($channel) = $server->channel_find($target);
 347 
 348     return unless $channel;
 349 
 350     my($color) = Irssi::settings_get_str("friends_nick_color");
 351 
 352     $friend = get_friend($channel, $channel->nick_find($nick));
 353 
 354     if ($friend && $color =~ /^[rgbcmykpwRGBCMYKPWFU0-9_]$/) {
 355 	$window = $server->window_find_item($target);
 356 	$theme = $window->{theme} || Irssi::current_theme;
 357 	
 358 	$oform = $nform = $theme->get_format('fe-common/core', 'pubmsg');
 359 	$nform =~ s/(\$(\[-?\d+\])?0)/%$color$1%n/g;
 360 
 361 	$window->command("^format pubmsg $nform");
 362 	Irssi::signal_continue(@_);
 363 	$window->command("^format pubmsg $oform");
 364     }
 365 }
 366 
 367 # --------[ sig_message_irc_action ]------------------------------------
 368 
 369 sub sig_message_irc_action {
 370     my($server, $msg, $nick, $addr, $target) = @_;
 371     my($window,$theme,$friend,$oform,$nform);
 372     my($channel) = $server->channel_find($target);
 373 
 374     return unless $channel;
 375 
 376     my($color) = Irssi::settings_get_str("friends_nick_color");
 377 
 378     $friend = get_friend($channel, $channel->nick_find($nick));
 379 
 380     if ($friend && $color =~ /^[rgbcmykpwRGBCMYKPWFU0-9_]$/) {
 381 	$window = $server->window_find_item($target);
 382 	$theme = $window->{theme} || Irssi::current_theme;
 383 	
 384 	$oform = $nform = $theme->get_format('fe-common/irc', 
 385 					     'action_public');
 386 	$nform =~ s/(\$(\[-?\d+\])?0)/%$color$1%n/g;
 387 
 388 	$window->command("^format action_public $nform");
 389 	Irssi::signal_continue(@_);
 390 	$window->command("^format action_public $oform");
 391     }
 392 }
 393 
 394 # ======[ Commands ]====================================================
 395 
 396 # --------[ FRIENDS ]---------------------------------------------------
 397 
 398 # Usage: /FRIENDS
 399 sub cmd_friends {
 400     my($win) = get_friends_window;
 401     update_friends_window();
 402 }
 403 
 404 # --------[ subcmd_friends_channel ]------------------------------------
 405 
 406 sub subcmd_friends_channel {
 407     my($win,$num,$chan) = @_;
 408 
 409     unless ($chan && defined $num) {
 410 	$win->print("Syntax: CHANNEL <num> <channel>", MSGLEVEL_NEVER);
 411 	return;
 412     }
 413 
 414     unless (0 < $num && $num <= @friends) {
 415 	$win->print("Error: Element $num not in list", MSGLEVEL_NEVER);
 416 	return;
 417     }
 418 
 419     $friends[$num-1][2] = $chan;
 420 
 421     return 1;
 422 }
 423 
 424 # --------[ subcmd_friends_delete ]-------------------------------------
 425 
 426 sub subcmd_friends_delete {
 427     my($win,$num) = @_;
 428 
 429     unless (defined $num) {
 430 	$win->print("Syntax: DELETE <num>", MSGLEVEL_NEVER);
 431 	return;
 432     }
 433     
 434     unless (0 < $num && $num <= @friends) {
 435 	$win->print("Error: Element $num not in list", MSGLEVEL_NEVER);
 436 	return;
 437     }
 438     
 439     splice @friends, $num-1, 1;
 440 
 441     return 1;
 442 }
 443 
 444 # --------[ subcmd_friends_flags ]--------------------------------------
 445 
 446 sub subcmd_friends_flags {
 447     my($win,$num,$flags) = @_;
 448     my(%f);
 449     
 450     unless ($flags && defined $num) {
 451 	$win->print("Syntax: FLAGS <num> <flags>", MSGLEVEL_NEVER);
 452 	return;
 453     }
 454 
 455     unless (0 < $num && $num <= @friends) {
 456 	$win->print("Error: Element $num not in list", MSGLEVEL_NEVER);
 457 	return;
 458     }
 459     
 460     $friends[$num-1][4] = join "", sort grep {!$f{$_}++}
 461       split //, $flags;
 462 
 463     return 1;
 464 }
 465 
 466 # --------[ subcmd_friends_help ]---------------------------------------
 467 
 468 sub subcmd_friends_help {
 469     my($win) = @_;
 470 
 471     $win->print(q{CHANNEL <num> <channel>    - set channel
 472 
 473         <channel> is either a channel name or * for all
 474 }, MSGLEVEL_NEVER);
 475 
 476     $win->print(q{DELETE  <num>              - delete entry
 477 }, MSGLEVEL_NEVER);
 478 
 479     $win->print(q{FLAGS   <num> <flags>      - set flags
 480 
 481         <flags> is a list of c (color), o (give op), v (give voice)
 482 }, MSGLEVEL_NEVER);
 483 
 484     $win->print(q{MASK    <num> <mask>       - set mask
 485 
 486         <mask> is in the usual nick!user@host format
 487 }, MSGLEVEL_NEVER);
 488 
 489     $win->print(q{NET     <num> <net>        - set net
 490 
 491       <net> is one of your defined ircnets or * for all
 492 }, MSGLEVEL_NEVER);
 493 
 494 }
 495 
 496 # --------[ subcmd_friends_mask ]---------------------------------------
 497 
 498 sub subcmd_friends_mask {
 499     my($win, $num, $mask) = @_;
 500 
 501     unless ($mask && defined $num) {
 502 	$win->print("Syntax: MASK <num> <mask>", MSGLEVEL_NEVER);
 503 	return;
 504     }
 505     
 506     unless (0 < $num && $num <= @friends) {
 507 	$win->print("Error: Element $num not in list", MSGLEVEL_NEVER);
 508 	return;
 509     }
 510     
 511     unless ($mask =~ /^.+!.+@.+$/) {
 512 	$win->print("Error: Mask $mask is not valid", MSGLEVEL_NEVER);
 513     }
 514     
 515     $friends[$num-1][1] = $mask;
 516 
 517     return 1;
 518 }
 519 
 520 # --------[ subcmd_friends_net ]----------------------------------------
 521 
 522 sub subcmd_friends_net {
 523     my($win,$num,$net) = @_;
 524     my($n);
 525 
 526     unless ($net && defined $num) {
 527 	$win->print("Syntax: NET <num> <net>", MSGLEVEL_NEVER);
 528 	return;
 529     }
 530 
 531     unless (0 < $num && $num <= @friends) {
 532 	$win->print("Error: Element $num not in list", MSGLEVEL_NEVER);
 533 	return;
 534     }
 535     
 536     if ($net eq '*') {
 537 	# all is well
 538     } elsif ($n = Irssi::chatnet_find($net)) {
 539 	$net = $n->{name};
 540     } else {
 541 	$win->print("Error: No defined chatnet named $net",
 542 		    MSGLEVEL_NEVER);
 543 	return;
 544     }
 545     
 546     $friends[$num-1][3] = $net;
 547 
 548     return 1;
 549 }
 550 
 551 # --------[ ADDFRIEND ]-------------------------------------------------
 552 
 553 # Usage: /ADDFRIEND <nick>|<mask> [<channel>|* [<net>|*]]
 554 #                                 [-mask host|normal|domain|full]
 555 #			          [-flags <flags>]
 556 sub cmd_addfriend {
 557     my($param,$serv,$chan) = @_;
 558     my(@param,@flags);
 559     my($type) = Irssi::Irc::MASK_USER | Irssi::Irc::MASK_DOMAIN;
 560     my($mask,$flags,$channel,$net);
 561     my(@split) = split " ", $param;
 562 
 563     while (@split) {
 564 	$_ = shift @split;
 565 	if (/^-m(ask)?$/) {
 566 	    $_ = shift @split;
 567 	    if (/^h(ost)?$/) {
 568 		$type = Irssi::Irc::MASK_HOST;
 569 	    } elsif (/^n(ormal)?$/) {
 570 		$type = Irssi::Irc::MASK_USER
 571 	              | Irssi::Irc::MASK_DOMAIN;
 572 	    } elsif (/^d(omain)?$/) {
 573 		$type = Irssi::Irc::MASK_DOMAIN;
 574 	    } elsif (/^f(ull)?$/) {
 575 		$type = Irssi::Irc::MASK_NICK
 576 	              | Irssi::Irc::MASK_USER
 577 		      | Irssi::Irc::MASK_HOST;
 578 	    } else {
 579 		# fjekk
 580 	    }
 581 	} elsif (/^-flags?$/) {
 582 	    $flags = shift @split;
 583 	} else {
 584 	    push @param, $_;
 585 	}
 586     }
 587     ($mask,$channel,$net) = @param;
 588 
 589     unless ($mask) {
 590 	crap("/ADDFRIEND [-mask full|normal|host|domain] [-flags <[o][v][c]>] <nick|mask> [<channel> [<chatnet>]]]");
 591 	return;
 592     }
 593 
 594     $flags ||= "o";
 595 
 596     unless ($channel) {
 597 	if ($chan) {
 598 	    $channel = $chan->{name};
 599 	} else {
 600 	    crap("/ADDFRIEND needs a channel.");
 601 	    return;
 602 	}
 603     }
 604 
 605     unless ($net) {
 606 	if ($serv) {
 607 	    $net = $serv->{chatnet};
 608 	} else {
 609 	    crap("/ADDFRIEND needs a chatnet.");
 610 	    return;
 611 	}
 612     }
 613 
 614     # is this a nick we need to expand?
 615     unless ($mask =~ /.+!.+@.+/) {
 616 	my($nick);
 617 	if ($net ne '*') {
 618 	    unless ($serv = Irssi::server_find_chatnet($net)) {
 619 		crap("Error locating server for $net.");
 620 		return;
 621 	    }
 622 	} else {
 623 	    unless ($serv) {
 624 		crap("Need a server for nick expansion");
 625 		return
 626 	    }
 627 	}
 628 	if ($channel ne '*') {
 629 	    unless ($chan = $serv->channel_find($channel)) {
 630 		crap("Error locating channel $channel.");
 631 		return;
 632 	    }
 633 	} else {
 634 	    unless ($chan) {
 635 		crap("Need a channel for nick expansion");
 636 		return;
 637 	    }
 638 	}
 639 	unless ($nick = $chan->nick_find($mask)) {
 640 	    crap("Error locating nick $mask.");
 641 	    return;
 642 	}
 643 	$mask = Irssi::Irc::get_mask($nick->{nick}, $nick->{host}, $type);
 644     }
 645 
 646     for my $flag (split //, $flags) {
 647 	unless ($flag = $flaglong{$flag}) {
 648 	    crap("Unknown flag [$flag]");
 649 	    next;
 650 	}
 651 	push @flags, $flag;
 652 	$friends{$mask}{lc $net}{lc $channel}{$flag} = 1;
 653     }
 654 
 655     if (@flags) {
 656 	crap("Added %s for %s in %s on %s.",
 657 	     join(",", @flags), $mask, $channel, $net);
 658     }
 659 
 660     save_friends(1);
 661 }
 662 
 663 # ======[ Setup ]=======================================================
 664 
 665 # --------[ Register settings ]-----------------------------------------
 666 
 667 Irssi::settings_add_bool('friends', 'friends_autosave', 1);
 668 Irssi::settings_add_int('friends', 'friends_max_nicks', 10);
 669 Irssi::settings_add_bool('friends', 'friends_show_check', 1);
 670 
 671 Irssi::settings_add_str('friends', 'friends_nick_color', '');
 672 
 673 # --------[ Register formats ]------------------------------------------
 674 
 675 Irssi::theme_register(
 676 [
 677  'friends_crap',
 678  '{line_start}{hilight Friends:} $0',
 679 
 680  'friends_check',
 681  '{line_start}{hilight Friends} checked: $0',
 682 
 683  'friends_check_more',
 684  '{line_start}{hilight Friends} checked: $0 (+$1 more)',
 685 
 686  'friends_header',
 687  '<%W$[2]0%n> <%W$[33]1%n> <%W$[13]2%n> <%W$[13]3%n> <%W$[5]4%n>',
 688 
 689  'friends_line',
 690  '[%R$[-2]0%n] $[35]1 $[15]2 $[15]3 $[7]4',
 691 
 692  'friends_footer',
 693  "\n".'%4 List contains $0 friends %>%n',
 694 
 695 ]);
 696 
 697 # --------[ Register signals ]------------------------------------------
 698 
 699 Irssi::signal_add_first("send command", "sig_send_command");
 700 
 701 Irssi::signal_add_last("massjoin", "sig_massjoin");
 702 Irssi::signal_add_last("nick mode changed", "sig_nick_mode_changed");
 703 Irssi::signal_add_last("channel sync", "sig_channel_sync");
 704 
 705 Irssi::signal_add('setup saved', 'sig_setup_save');
 706 Irssi::signal_add('setup reread', 'sig_setup_reread');
 707 
 708 Irssi::signal_add('window changed', 'sig_window_changed');
 709 
 710 Irssi::signal_add_first('message public', 'sig_message_public');
 711 Irssi::signal_add_first('message irc action', 'sig_message_irc_action');
 712 
 713 # --------[ Register commands ]-----------------------------------------
 714 
 715 Irssi::command_bind('friends', 'cmd_friends');
 716 Irssi::command_bind('addfriend', 'cmd_addfriend');
 717 
 718 # --------[ Register timers ]-------------------------------------------
 719 
 720 # --------[ Load config ]-----------------------------------------------
 721 
 722 load_friends;
 723 
 724 # ======[ END ]=========================================================
 725 
 726 # Local Variables:
 727 # header-initial-hide: t
 728 # mode: header-minor
 729 # end: