Describes installation and initial setup of BitlBee in Debian, and some notes on interaction with irssi.

About

BitlBee is an IRC-server with a twist. It uses backends to connect to various IM-protocols, and relay messages/files/etc. in a regular IRC fashion. This makes it possible to use e.g. irssi as an IM client, using its powerful scripting and user support. It also gives you probably the best CLI IM client, which you can easily SSH to from all over the world. Marvellous.

irssi is a story of its own in terms of usage guides. This text concerns only a quick intro to BitlBee and mentions some irssi scripts useful in combination with BitlBee.

Installation

sudo aptitude install bitlbee

After installation, BitlBee automatically starts and is registered for automatic startup for subsequent boots. It creates a local IRC server at port 6667. Be sure to block this port in your firewall if you don't want external connections to your server.

Setup

Add network and server in irssi:

/network add bitlbee
/server add -auto -network bitlbee localhost

Connect to local server:

/connect bitlbee

Register a server account (will be associated with your current IRC nick):

register
/oper
mysecretpassword

You can also give mysecretpassword as a final argument in the first command above and skip the other two, but then it might be sustained in IRC logs and such. /oper is safer.

Set up autojoin and an automatic identification prompt on subsequent irssi startups:

/channel add -auto -botcmd '/say identify\; /oper' &bitlbee bitlbee
/save

Add an IM accounts to your server account:

  • MSN

      account add msn powerpuff84@hotmail.com
      /oper
      mymsnpassword
    
  • Google Talk

      account add jabber powerpuff84@gmail.com
      /oper
      mygmailpassword
    

Additional setup is needed; a server must be specified. To change account settings, first issue

account list
<@root>  0 (msn): msn, powerpuff84@hotmail.com
<@root>  1 (gtalk): jabber, powerpuff84@gmail.com

The first number is an account index. Use it to change settings on account 1 by issuing:

account 1 server talk.google.com:5223:ssl

UPDATE: Since BitlBee 3.0.5, Google Talk supports OAuth2. This makes you not having to save your password on disk. Instead you log in via a browser where you have your open Google session, and register BitlBee as a trusted application.

account 1 oauth on

This will trigger a msg from BitlBee, giving you instructions on how to continue with the OAuth2 process.

To enable all available accounts:

account on

To view buddies:

blist

To get further instructions:

help
help quickstart

...and follow the leads.

Logging

I like logging IM conversations. Pidgin (my previous client of choice (well, more of "convenience" perhaps)) does this easily. irssi does not by default. There is no specific BitlBee logging mechanism that I am aware of.

To turn on irssi logging:

/set autolog_path ~/.irssi/logs/$tag/$0/%Y-%m-%d.log
/set autolog on

Add contacts

add 0 optimusrhyme@hotmail.com

where 0 is the wanted account index.

Single or multiple query windows?

You can communicate with contacts in two ways. Either by talking to them directly in the &bitlbee window, prefixed by their nick, e.g.

<powerpuff84> optimusrhyme: give me some lyrics!
<optimusrhyme> powerpuff84: please stop.

If you want to open a separate query window, just type e.g.

/msg optimusrhyme pleeeaaasee!

Separate query windows are the default option for new incoming conversations. BitlBee says that it remembers the common/separate window setting on a contact basis. For persistent default setting, see

help set private

Query order

When I connected an account I got 8 friend requests simultaneously. BitlBee told me to simply write yes/no to answer, but which one was I answering?

qlist

gives a list of the queries, numbered from 0→7. Giving a yes/no command will as default answer the last question in the list! This fooled me the first time. This behaviour is configurable by the query_order setting. See help set query_order for the two available alternatives.

Rename contacts on account basis

I choose to suffix contact names by my connected account, which can easily be done through nick_format.

First, set account tags:

account 0 set tag MSN
account 1 set tag GTalk

Next, issue the global version of nick_format:

set nick_format %full_name|%account

See help nick_format for information on available substitutions.

Interaction with irssi

Not much to say, since BitlBee is quite client agnostic by its nature. Some irssi scripts can be helpful though.

nicklist.pl

nicklist.pl provides an automatically updating list of users currently in a channel, which irssi by default does not provide. It is preferably run in a separate terminal through its FIFO mode. If you run irssi through tmux or GNU Screen, this is no drawback.

Install the plugin in ~/.irssi/scripts/. Then in irssi, run

/run nicklist.pl
/nicklist fifo
/set nicklist_height 66
/set nicklist_width 20

Modify height after your terminal. This creates a FIFO with the nicklist for the active channel. Split the irssi session in tmux and start listening to the FIFO by issuing the tmux command

:split-window -h -l 20 'cat ~/.irssi/nicklistfifo'

Sync width with the earlier irssi command and modify it after your taste.

Now, in irssi start the FIFO with:

/nicklist fifo

This is useful not only, but especially, for BitlBee.

Bind Alt+PageDown/Alt+PageUp to scroll the nicklist:

/bind ^[[5;3~ command nicklist scroll -10
/bind ^[[6;3~ command nicklist scroll +10

The seemingly weird keycodes above work at least for me and others. meta-prior and meta-next "should" be the correct way to bind, but it does not seem to work.

If you want the FIFO to initialize automatically on irssi startup, run

echo "nicklist fifo" >> ~/.irssi/startup

Auto update tmux pane size for nicklist.pl

I use a right-oriented tmux pane to read the nicklist FIFO. When I attach to the irssi tmux session from smaller terminals, tmux will resize the panes (to an unusable size as far as nicklist.pl is concerned) and not restore them when the window is made larger again, leaving the nicklist pane unnecessarily wide.

nicklist.pl includes a solution when using GNU Screen. I made my own script, nicklist-tmux_auto_resize to solve it with tmux.

The script works well, but needs trivial customization if you don't, as I do, have the nicklist pane to the right of irssi.

View script

use strict;
use warnings;
use Irssi;

our $VERSION = 1.0;
our %IRSSI = (
    authors     => 'Daniel Andersson',
    contact     => 'sskraep@gmail.com',
    name        => 'nicklist-tmux_auto_resize',
    description => 'Keeps a tmux pane at a certain size, even after terminal resize (for use with nicklist.pl)',
    license     => 'GPL',
    url     => 'http://510x.se/notes',
);

Irssi::command_bind('help', sub { if ($_[0] =~ '^nicklist-tmux_auto_resize ?') {&sig_help; Irssi::signal_stop;} });
sub sig_help
{
    my $usage = <<USAGEEND;
NICKLIST-TMUX_AUTO_RESIZE  -  Automatically resizes nicklist.pl pane in tmux

USAGE
    Load script and have a tmux pane open. By default it then resizes
    automatically.

    /nicklist tmuxresize
         Resize the nicklist manually.

REQUIRES
    tmux

SETTINGS
    nicklist_tmux_auto_resize <bool>
        Activate automatic resizing on terminal size change.

    nicklist_tmux_pane_index <int>
        Pane index in irssi window. If nicklist is to the right and only two
        panes exist, this is '1'. For other cases, see (*).

ABOUT
    Started as an external shell script, but was easy to implement directly in
    Perl. I find it very useful.

    It would be nice if tmux implemented a command to resize a tmux pane
    directly to a given size, and/or start taking negative numbers as resize
    arguments.

NOTES
    (*):
        By default it assumes that the pane in question is right-aligned. To
        support left/up/down-aligned panes, some simple conditional cases needs
        to be defined in the script (specifically in &tmux_get_resize_option).
        Not in my current interest, but it should be simple.
USAGEEND
    Irssi::print($usage, MSGLEVEL_CLIENTCRAP);
}

# Script output formatting
Irssi::theme_register(['nicklist-tmux_auto_resize', '{line_start}{hilight '.$IRSSI{'name'}.':} $0']);

### Start internal variable declaration
my $tmux = '/usr/bin/tmux';
sub first_line{ return substr($_[0], 0, index($_[0], "\n")) }
my $tmux_session_window = &first_line(qx/$tmux list-windows -F '#{session_name}'/).':'.&first_line(qx/$tmux list-panes -F '#{window_index}'/);
my $current_width;
my $current_height;
### End internal variable declaration

### Start external settings handling
Irssi::settings_add_bool('nicklist-tmux_auto_resize', 'nicklist_tmux_auto_resize', 1);
Irssi::settings_add_int ('nicklist-tmux_auto_resize', 'nicklist_tmux_pane_index', 1);

my $nicklist_tmux_auto_resize;
my $nicklist_tmux_pane_index;
my $nicklist_width;
# $nicklist_height not yet needed since only right-alignment is considered.
#my $nicklist_height;
sub load_settings
{
    $nicklist_tmux_auto_resize = Irssi::settings_get_bool('nicklist_tmux_auto_resize');
    $nicklist_tmux_pane_index =  Irssi::settings_get_int ('nicklist_tmux_pane_index');
    $nicklist_width =            Irssi::settings_get_int ('nicklist_width');
    unless ($nicklist_width > 0) {
        Irssi::printformat(MSGLEVEL_CLIENTNOTICE, 'nicklist-tmux_auto_resize', 'You need to set nicklist_width >0 to be able to resize the pane');
        return;
    }
    # $nicklist_height not yet needed since only right-alignment is
    # considered.

    # Could make the below call dependant on whether the settings have
    # actually changed or not, but irssi does not provide such a signal and
    # it is much coding for in practice almost no gain, so just resize it
    # if auto-resizing is enabled.
    &tmux_resize_nicklist if $nicklist_tmux_auto_resize;
}
# I need to wait for nicklist_width from nicklist.pl to be set. Without the
# below timeout, the script will fail on autoload with
# -!- Irssi: warning settings_get(nicklist_width) : not found
# even though the setting exists in '~/.irssi/config'.
Irssi::timeout_add_once(10, \&load_settings, undef);

Irssi::signal_add('setup changed', \&sig_setup_changed);
sub sig_setup_changed
{
    &load_settings;
}
### End external settings handling

sub sig_terminal_resized
{
    &tmux_resize_nicklist if $nicklist_tmux_auto_resize;
}

sub tmux_get_current_dimensions
{
    my $pane_iterator;
    my $delimiter = 'x';
    # If _anything_ generates output (including debug statements...) while
    # the pipe is open, irssi will randomly crash without a trace.
    open(TMUXPANEDIMENSIONS, '-|', $tmux, 'list-panes', '-t', $tmux_session_window, '-F', '#{pane_width}'.$delimiter.'#{pane_height}');
    while (<TMUXPANEDIMENSIONS>) {
        next if $pane_iterator++ < $nicklist_tmux_pane_index;
        chomp;
        close(TMUXPANEDIMENSIONS);
        return split($delimiter, $_);
    }
    close(TMUXPANEDIMENSIONS);
    return;
}

sub tmux_get_resize_option
{
    # Only implemented for right-aligned panes. Height/width/±/-R/-L need
    # to be reconsidered on alignment basis.
    #return unless (my $tmux_pane_resize_right = $current_width - Irssi::settings_get_int('nicklist_width'));
    return unless (my $tmux_pane_resize_right = $current_width - $nicklist_width);
    return ('-L', -$tmux_pane_resize_right) if ($tmux_pane_resize_right < 0);
    return ('-R', $tmux_pane_resize_right);
}

sub tmux_resize_nicklist
{
    return unless (($current_width, $current_height) = &tmux_get_current_dimensions);
    # Set nicklist height to tmux pane height
    Irssi::settings_set_int('nicklist_height', $current_height);
    # Set tmux pane width to nicklist width
    return unless (my @resize_option = &tmux_get_resize_option);
    system($tmux, '-q', 'resize-pane', '-t', $tmux_session_window, @resize_option);
}

Irssi::command_bind('nicklist tmuxresize',\&tmux_resize_nicklist);
Irssi::signal_add('terminal resized', \&sig_terminal_resized);

hide script.

Load the script and issue

/help nicklist-tmux_auto_resize

to get instructions (or read the source directly, e.g. above).

The script can also be found at http://510x.se/hg/program/nicklist-tmux_auto_resize.

Tab completion of BitlBee commands

BitlBee's commands are not by default tab completed in irssi. BitlBee_tab_completion fixes this though.

cd ~/.irssi/scripts
wget http://the-timing.nl/files/irssi-bitlbee/old/bitlbee_tab_completion.pl

Then load it in irssi with

/run bitlbee_tab_completion.pl

The plugin fetches a current command list from your currently running BitlBee server, so it will by design be up to date.