Agent-TCLI
view release on metacpan or search on metacpan
lib/Agent/TCLI/Transport/XMPP.pm view on Meta::CPAN
=cut
use warnings;
use strict;
use Carp;
use Date::Parse;
use POE;
use Net::Jabber;
use Socket;
use Agent::TCLI::Control;
use Agent::TCLI::Request;
require Agent::TCLI::Transport::Base;
use Object::InsideOut qw( Agent::TCLI::Transport::Base );
use Params::Validate qw(validate_with);
sub VERBOSE () { 0 }
our $VERSION = '0.031.'.sprintf "%04d", (qw($Id: XMPP.pm 62 2007-05-03 15:55:17Z hacker $))[2];
=head1 INTERFACE
=head2 ATTRIBUTES
The following attributes are accessible through standard accessor/mutator
methods and may be set as a parameter to new unless otherwise noted.
=over
=item jid
xmpp id of user we're connecting as'
B<set_jid> will only accept SCALAR type values.
=cut
my @jid :Field('All' => 'jid', 'Type' => 'Net::XMPP::JID' );
=item jserver
B<jserver> will only accept SCALAR type values.
=cut
my @jserver :Field('All' => 'jserver' );
=item jpassword
The password for the transport to use to log in to the server.
B<jpassword> will only accept scalar type values.
=cut
my @jpassword :Field('All' => 'jpassword');
=item xmpp_debug
Sets the debug (verbosity) level for the XMPP libraries
=cut
my @xmpp_debug :Field :All('xmpp_debug');
=item xmpp_process_time
Sets the time in seconds to wait before calling XMPP Process to look for
more XMPP data. Defaults to 1 and shouldn't be much larger.
=cut
my @xmpp_process_time :Field
:Arg('name'=>'xmpp_process_time', 'default'=> 1 )
:Acc('xmpp_process_time');
=item peers
An array of peers
B<set_peers> will only accept ARRAYREF type values.
=cut
#my @peers :Field('All' => 'peers', 'Type' => 'ARRAY' );
# Holds the XMPP connection session
my @xmpp :Field('Get' => 'xmpp');
=item connection_retries
A max number to retry connection before giving up.
B<connection_retries> will only accept NUMERIC type values.
=cut
my @connection_retries
:Field
:Arg('name'=>'connection_retries','default'=>10)
:Acc('connection_retries')
:Type('NUMERIC' );
=item connection_delay
How long to wait beteen connection attempts when failed. Defaults to 30 seconds.
B<connection_delay> will only accept NUMERIC type values.
=cut
my @connection_delay
:Field
:Arg('name'=>'connection_delay','default'=>30)
:Acc('connection_delay')
:Type('NUMERIC' );
=item roster
Holds the Net::XMPP::Roster if enabled. To enable the roster,
a paramater of 'roster' => 1, must be passed in with new.
B<roster> will contain a Net::XMPP::Roster object after initialization if enabled.
=cut
my @roster :Field
:All('roster');
=item server_time
The time at the server. Useful for determining if messages were sent before we started up.
B<server_time> should only contain hash values.
=cut
my @server_time :Field
# :Type('hash')
:All('server_time');
=item group_mode
The default setting to determine how to interact with groups. Options are:
'all' - process everything said in room
'named' - process only when called by name: (name followed by colon).
'log' - don't listen to anything, but log events there (which ones?)
'prefixed' - named + anything beginning with a designated prefix character
B<group_mode> should only contain scalar values.
=cut
my @group_mode :Field
# :Type('scalar')
:Arg('name'=>'group_mode', 'Default' => 'named' )
:Acc('group_mode');
=item group_prefix
The group_prefix used for group moded prefixed.
B<group_prefix> should only contain a single scalar value.
=cut
my @group_prefix :Field
# :Type('scalar')
:Arg('name'=>'group_prefix', 'Default' => ':' )
:Acc('group_prefix');
# Standard class utils are inherited
#u_ subs can't be private if used in %init_args
#named u_ to sort nicer in Eclipse
sub u_is_text {
return (
validate_pos( @_, { type => Params::Validate::SCALAR | Params::Validate::SCALARREF } )
)
}
sub u_is_num {
return (
Scalar::Utils->looks_like_number($_[0])
)
}
sub u_is_int {
my $arg = $_[0];
return (Scalar::Util::looks_like_number($arg) &&
(int($arg) == $arg));
}
sub _preinit :Preinit {
my ($self, $args) = @_;
$args->{'alias'} = 'transport_xmpp' unless defined( $args->{'alias'} );
$args->{'session'} = POE::Session->create(
object_states => [
$self => [ qw(
_start
_stop
_shutdown
_default
_child
ControlExecute
Disconnected
JoinPeerRooms
JoinChatRoom
lib/Agent/TCLI/Transport/XMPP.pm view on Meta::CPAN
my @login;
if ( $xmpp[$$self]->Connected() )
{
#log in
$self->Verbose("login: XMPP trying login as ".$self->jid()->GetUserID );
@login = $xmpp[$$self]->AuthSend(
username => $self->jid()->GetUserID,
password => $jpassword[$$self],
resource => $self->jid()->GetResource,
);
$self->Verbose("login: Did login for ".$self->jid()->GetUserID." Got ".$login[0] );
if ( defined($login[0]) && $login[0] eq 'ok')
{
$kernel->yield('Online');
}
elsif ( defined($login[1]) )
{
$txt .= "Login error-> ".$login[1];
}
else
{
$txt .= "Bad Login error-> ".$xmpp[$$self]->GetErrorCode();
}
}
else
{
$txt .= "Connection error-> ".$xmpp[$$self]->GetErrorCode();
}
if ($txt ne '' )
{
$self->Verbose("login: ".$txt."\n",1,$xmpp[$$self]->GetErrorCode());
$kernel->delay_set('Disconnected' => 10 , 1 );
}
} # end sub login
sub Online {
my ($kernel, $self, ) =
@_[KERNEL, OBJECT, ];
$self->Verbose("Online: \n" ,1);
my %server_time = $self->xmpp->TimeQuery('mode'=>'block');
$self->Verbose("Online: server_time($server_time{display})", 1,\%server_time );
$self->set(\@server_time, $server_time{utc});
# start roster
if ($self->roster)
{
$self->Verbose("Online: enabling Roster ");
$self->set(\@roster, $self->xmpp->Roster);
}
if (defined($self->control_options) )
{
$self->control_options->{'local_address'} = $self->Address
unless defined($self->control_options->{'local_address'});
}
$kernel->delay_set( 'Process' => $xmpp_process_time[$$self] );
$kernel->yield('send_presence',(
{
status => 'Online',
priority => '1',
} ) );
$kernel->yield('JoinPeerRooms') if defined($self->peers);
} #end sub Online
=item Process ( )
This event interfaces with the XMPP Process to have it check for new data
=cut
sub Process {
my ($kernel, $self, ) =
@_[KERNEL, OBJECT, ];
$self->Verbose("Process: " , 4);
my $result = $xmpp[$$self]->Process(1);
if ( defined($result) )
{
$self->Verbose("Process: (".$result.") for ".$self->alias." as ".$jid[$$self]->GetJID('full') );
$kernel->delay_set( 'Process' => $xmpp_process_time[$$self] );
}
else
{
$kernel->yield( 'Disconnected' );
}
} # End Process
# When we recv anything from XMPP the $response will be
# an array of the XMPP Session ID and then the XML message
# In ARG1 for some reason...
sub recv_pres {
my ($kernel, $self, $jSessionID, $response) =
@_[KERNEL, OBJECT, ARG0, ARG1 ];
my $msg = $response->[1];
$self->Verbose( "\tRP\tGot no response \n") if ( !defined ($response) );
# my $thread = $self->get_thread($msg);
# $self->Verbose( "\tRP\tThread: ".$thread->id()." \n") if ( defined ($thread));
# If we get our own presence, ignore it.
my $from = $msg->GetFrom('jid');
return if ( $from eq $self->jid->GetUserID );
# TODO more presence handling
# need to put presence into thread participant state? Maybe but we
# don't get the thread with the presence.
# how would we find group participants in a groupchat?
# do we need have presence of groupchat participants for anything
return ();
}
sub GetRequestForNode {
my ($self, $node ) = @_;
# This is used to package up a simple request easily
my $input = $node->GetBody;
$self->Verbose("GetRequestForNode: input($input)\n",2);
my $request = Agent::TCLI::Request->new({
'sender' => $self->alias,
'postback' => 'PostResponse',
'input' => $input,
'response_verbose' => 1,
'verbose' => $self->verbose,
'do_verbose' => $self->do_verbose,
});
$request->set_recv($node);
return( $request );
}
sub recvmsg {
my ($kernel, $self, $jSessionID, $response) =
@_[KERNEL, OBJECT, ARG0, ARG1 ];
my $msg = $response->[1];
$self->Verbose("recvmsg: got message from ".
( run in 0.989 second using v1.01-cache-2.11-cpan-39bf76dae61 )