#!/usr/bin/perl # # Simple read-only command-line XMPP client # use strict; use Getopt::Std; use Config::Std; use AnyEvent; use Net::XMPP2::Client; use Term::ANSIColor; use Term::Size; use Time::Piece; use vars qw($VERSION); $VERSION = 0.001004; my %opts = (); getopts('u:v', \%opts); my $user = $opts{u}; my $verbose = $opts{v}; die "Missing \$ENV{HOME}/.clixrc file\n" unless -f "$ENV{HOME}/.clixrc"; read_config "$ENV{HOME}/.clixrc" => my %config; die "Error reading \$ENV{HOME}/.clixrc: $!" unless keys %config; # Use DEFAULTS user if defined, otherwise connect to all defined accounts $user ||= $config{DEFAULTS}{user}; if ($user) { $user = [ $user ] unless ref $user; } else { $user = [ grep !/DEFAULTS/, sort keys %config ]; } # Setup short jid mappings my @map = (); push @map, ref $config{DEFAULTS}{map} ? @{$config{DEFAULTS}{map}} : $config{DEFAULTS}{map} if $config{DEFAULTS}{map}; push @map, ref $config{$user}{map} ? @{$config{$user}{map}} : $config{$user}{map} if $config{$user}{map}; my %map = map { split /\s*:\s*/, $_, 2 } @map; # Initial Setup $SIG{INT} = \&disconnect; my $j = AnyEvent->condvar; my $c = Net::XMPP2::Client->new; # Add accounts for ( @$user ) { my $jid = $config{$_}{user}; my $pass = $config{$_}{pass}; next unless $jid && $pass; $c->add_account( $jid, $pass, undef, undef, { resource => 'clix' }); } my $account_cnt = scalar $c->get_accounts(); binmode(STDOUT, ':utf8'); # Register callbacks $c->reg_cb ( session_ready => sub { my ($c, $acc) = @_; printf "Connected: %s\n", $acc->bare_jid; }, disconnect => sub { my ($c, $acc, $h, $p, $reason) = @_; printf "Disconnected: %s (%s:%s)%s\n", $acc->bare_jid, $h, $p, $reason ? ": $reason" : ''; my $attempts = 0; do { sleep 2; $c->update_connections; $attempts++; } unless $attempts >= 4 || scalar($c->get_connected_accounts()) == $account_cnt; }, error => sub { my ($c, $acc, $err) = @_; print "Error: " . $err->string . "\n"; }, message => sub { my ($c, $acc, $msg) = @_; my $body = $msg->any_body || return; chomp $body; my $jid = $msg->from; my $bare_jid = $jid; $bare_jid =~ s!/ [^/]+$ !!x; print color 'white'; printf "(%s) ", localtime->strftime('%T'); if (exists $map{ $bare_jid }) { print color 'cyan'; printf "[%s] ", $map{ $bare_jid }; } else { print color 'cyan'; printf "%s: ", $bare_jid; } if ($body =~ m/^(\S+:)(.*?)$/s) { print color 'yellow'; print $1; print color 'green'; print $2; } else { print color 'green'; print $body; } print color 'reset'; print "\n"; } ); $c->start; $j->wait; sub disconnect { $c->remove_accounts if $c; exit; } __END__ =head1 NAME clix - a read-only command-line XMPP client =head1 SYNOPSIS clix [-u ] =head1 DESCRIPTION clix is a read-only command-line XMPP client. It is intended for simple merging/monitoring tasks, such as following twitter and RSS feeds via XMPP. =head2 CONFIGURATION clix requires a config file called .clixrc on your home directory, containing a set of jabber accounts to connect to. This is just an ini-style config like the following: [gavin1] user = gavin@example.com pass = password1 [jabber] user = openfusion@jabber.org pass = password2 [google] user = something@gmail.com pass = password3 By default, clix tries to connect to all accounts. You can restrict to just a single account by specifying a user section name via '-u' e.g. clix -u gavin1 for the example above. =head1 AUTHOR Gavin Carr =head1 LICENSE Copyright 2007 Open Fusion Pty. Ltd. This program is free software, licensed under the terms of the GNU General Public License v2. =cut