AnyEvent-XMPP

 view release on metacpan or  search on metacpan

lib/AnyEvent/XMPP/Client.pm  view on Meta::CPAN

   $j->wait;

=head1 DESCRIPTION

This module tries to implement a straight forward and easy to
use API to communicate with XMPP entities. L<AnyEvent::XMPP::Client>
handles connections and timeouts and all such stuff for you.

For more flexibility please have a look at L<AnyEvent::XMPP::Connection>
and L<AnyEvent::XMPP::IM::Connection>, they allow you to control what
and how something is being sent more precisely.

=head1 METHODS

=head2 new (%args)

Following arguments can be passed in C<%args>:

=over 4

=item debug => 1

This will install callbacks which produce debugging output. This will
require L<XML::Twig> to be installed (as it is used for pretty printing
the "XML" output).

=back

=cut

sub new {
   my $this = shift;
   my $class = ref($this) || $this;
   my $self = { @_ };
   bless $self, $class;

   if ($self->{debug}) {
      $self->reg_cb (
         debug_recv => sub {
            my ($self, $acc, $data) = @_;
            printf "recv>> %s\n%s", $acc->jid, dump_twig_xml ($data)
         },
         debug_send => sub {
            my ($self, $acc, $data) = @_;
            printf "send<< %s\n%s", $acc->jid, dump_twig_xml ($data)
         },
      )
   }
   return $self;
}

sub add_extension {
   my ($self, $ext) = @_;
   $self->add_forward ($ext, sub {
      my ($self, $ext, $ev, $acc, @args) = @_;
      return if $ext->{inhibit_forward}->{$ev};
      $ext->_event ($ev, $acc->connection (), @args);
   });
}

=head2 add_account ($jid, $password, $host, $port, $connection_args)

This method adds a jabber account for connection with the JID C<$jid>
and the password C<$password>.

C<$host> and C<$port> can be undef and their default will be the domain of the
C<$jid> and the default for the C<port> parameter to the constructor of
L<AnyEvent::XMPP::Connection> (look there for details about DNS-SRV lookups).

C<$connection_args> must either be undef or a hash reference to
additional arguments for the constructor of the L<AnyEvent::XMPP::IM::Connection>
that will be used to connect the account.

Returns 1 on success and undef when the account already exists.

=cut

sub add_account {
   my ($self, $jid, $password, $host, $port, $connection_args) = @_;
   my $bj = prep_bare_jid $jid;

   my $acc = $self->{accounts}->{$bj};
   if ($acc) {
      $acc->{password} = $password;
      $acc->{host}     = $host;
      $acc->{port}     = $port;
      $acc->{args}     = $connection_args;
      return;
   }

   $acc =
      $self->{accounts}->{$bj} =
         AnyEvent::XMPP::IM::Account->new (
            jid      => $jid,
            password => $password,
            host     => $host,
            port     => $port,
            args     => $connection_args,
         );

   $self->event (added_account => $acc);

   $self->update_connections
      if $self->{started};

   $acc
}

=head2 start ()

This method initiates the connections to the XMPP servers.

=cut

sub start {
   my ($self) = @_;
   $self->{started} = 1;
   $self->update_connections;
}

=head2 update_connections ()

This method tries to connect all unconnected accounts.

=cut

sub update_connections {
   my ($self) = @_;

   Scalar::Util::weaken $self;

   for (values %{$self->{accounts}}) {
      my $acc = $_;

      if (!$acc->is_connected && !$self->{prep_connections}->{$acc->bare_jid}) {
         my %args = (initial_presence => 10);

         if (defined $self->{presence}) {
            if (defined $self->{presence}->{priority}) {
               $args{initial_presence} = $self->{presence}->{priority};
            }
         }

         my $con = $acc->spawn_connection (%args);
         $self->{prep_connections}->{$acc->bare_jid} = $con;

         $con->add_forward ($self, sub {
            my ($con, $self, $ev, @arg) = @_;
            $self->_event ($ev, $acc, @arg);
         });

         $con->reg_cb (
            session_ready => sub {
               my ($con) = @_;
               delete $self->{prep_connections}->{$acc->bare_jid};

lib/AnyEvent/XMPP/Client.pm  view on Meta::CPAN

               delete $self->{prep_connections}->{$acc->bare_jid};
               $con->unreg_me;
            },
            after_disconnect => sub {
               my ($con, $h, $p, $err) = @_;
               $con->remove_forward ($self);
            }
         );

         $con->connect;
      }
   }
}

=head2 disconnect ($msg)

Disconnect all accounts.

=cut

sub disconnect {
   my ($self, $msg) = @_;
   for my $acc (values %{$self->{accounts}}) {
      if ($acc->is_connected) { $acc->connection ()->disconnect ($msg) }
   }
}

=head2 remove_accounts ($reason)

Removes all accounts and disconnects. C<$reason> should be some descriptive
reason why this account was removed (just for logging purposes).

=cut

sub remove_accounts {
   my ($self, $reason) = @_;
   for my $acc (keys %{$self->{accounts}}) {
      $self->remove_account ($acc, $reason);
   }
}

=head2 remove_account ($acc, $reason)

Removes and disconnects account C<$acc> (which is a L<AnyEvent::XMPP::IM::Account> object).
The reason for the removal can be given via C<$reason>.

=cut

sub remove_account {
   my ($self, $acc, $reason) = @_;
   my $acca = $self->{accounts}->{$acc};
   $self->event (removed_account => $acca);
   if ($acca->is_connected) { $acca->connection ()->disconnect ($reason) }
   delete $self->{accounts}->{$acc};
}

=head2 set_accounts (%$accounts)

Sets the set of (to be connected) accounts. C<$accounts> must be a hash
reference which contains the JIDs of the accounts as keys and the values for
C<$password>, C<$domain>, C<$port> and C<$connection_args> as described in
C<add_account> above.

If the account is not yet connected it will be connected on the next call to
C<update_connections> and if an account is connected that is not in
C<$accounts> it will be disconnected.

=cut

sub set_accounts {
   my ($self, $accounts) = @_;


   for my $accid (keys %{$self->{accounts}}) {
      my $acca = $self->{accounts}->{$accid};
      if (!grep { cmp_bare_jid ($acca->jid, $_) } keys %$accounts) {
         $self->remove_account ($accid, "removed from set");
      }
   }

   for my $acc_jid (keys %$accounts) {
      $self->add_account ($acc_jid, @{$accounts->{$acc_jid}});
   }
}

=head2 send_message ($msg, $dest_jid, $src, $type)

Sends a message to the destination C<$dest_jid>.
C<$msg> can either be a string or a L<AnyEvent::XMPP::IM::Message> object.
If C<$msg> is such an object C<$dest_jid> is optional, but will, when
passed, override the destination of the message.

NOTE: C<$dest_jid> is transformed into a bare JID and the routing
is done by the conversation tracking mechanism which keeps track of
which resource should get the message.

C<$src> is optional. It specifies which account to use
to send the message. If it is not passed L<AnyEvent::XMPP::Client> will try
to find an account itself. First it will look through all rosters
to find C<$dest_jid> and if none found it will pick any of the accounts that
are connected.

C<$src> can either be a JID or a L<AnyEvent::XMPP::IM::Account> object as returned
by C<add_account> and C<get_account>.

C<$type> is optional but overrides the type of the message object in C<$msg>
if C<$msg> is such an object.

C<$type> should be 'chat' for normal chatter. If no C<$type> is specified
the type of the message defaults to the value documented in L<AnyEvent::XMPP::IM::Message>
(should be 'normal').

=cut

sub send_message {
   my ($self, $msg, $dest_jid, $src, $type) = @_;

   unless (ref $msg) {
      $msg = AnyEvent::XMPP::IM::Message->new (body => $msg);
   }



( run in 2.749 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )