AnyEvent-SlackBot
view release on metacpan or search on metacpan
lib/AnyEvent/SlackBot.pm view on Meta::CPAN
package AnyEvent::SlackBot;
use Modern::Perl;
use Moo;
use MooX::Types::MooseLike::Base qw(:all);
use namespace::clean;
use Data::Dumper;
use LWP::UserAgent;
use HTTP::Request;
use URI::Escape;
use HTTP::Request::Common qw(POST);
use AnyEvent::HTTP::MultiGet;
use AnyEvent::WebSocket::Client;
use JSON;
use namespace::clean;
use IO::Socket::SSL;
our $VERSION='1.0005';
BEGIN {
no namespace::clean;
with 'Log::LogMethods','Data::Result::Moo';
}
=head1 NAME
AnyEvent::SlackBot - AnyEvent Driven Slack Bot Interface
=head1 SYNOPSIS
use Modern::Perl;
use Data::Dumper;
use AnyEvent::SlackBot;
use AnyEvent::Loop;
$|=1;
my $sb=AnyEvent::SlackBot->new(
on_event=>sub {
my ($sb,$json,$conn_data)=@_;
if(exists $json->{type} and $json->{type} eq 'desktop_notification') {
my $ref={
type=>'message',
bot_id=>$sb->bot_id,
channel=>$json->{channel},
text=>'this is a test',
subtype=>'bot_message',
};
print Dumper($json,$ref);
$sb->send($ref);
}
},
);
my $result=$sb->connect_and_run;
die $result unless $result;
AnyEvent::Loop::run;
=head1 DESCRIPTION
Slack client. Handles Ping Pong on idle conntions, and transparrently reconnects as needed. The guts of the module wrap AnyEvent::WebSocket::Client, keeping the code base very light.
=head1 OO Arguments and accessors
Required Arguments
on_event: code refrence for handling events
sub { my ($self,$connection,$message,$startup_info)=@_ }
Optional Arguments
on_idle: code refrence for use in idle time
sub { my ($self)=@_ }
on_reply: code refrence called when the server responds to a post
sub { my ($self,$json,$connection_data)=@_ }
lib/AnyEvent/SlackBot.pm view on Meta::CPAN
);
has auto_reconnect=>(
is=>'rw',
isa=>Bool,
required=>1,
default=>1,
);
has connection=>(
is=>'rw',
isa=>Object,
required=>0,
);
has bot_id=>(
is=>'rw',
isa=>Str,
required=>0,
);
has keep_alive_timeout =>(
is=>'ro',
isa=>Int,
requried=>1,
default=>15,
);
# This method runs after the new constructor
sub BUILD {
my ($self)=@_;
$self->{backlog}=[];
$self->{ignore}={};
$self->stats->{service_started_on}=time;
$self->stats->{running_posts}=0;
}
# this method runs before the new constructor, and can be used to change the arguments passed to the module
around BUILDARGS => sub {
my ($org,$class,@args)=@_;
return $class->$org(@args);
};
=head1 OO Methods
=over 4
=item * $self->connect_and_run
COnnects and starts running
=cut
sub connect_and_run {
my ($self)=@_;
my $request=POST $self->rtm_start_url,[token=>$self->token];
my $ua=LWP::UserAgent->new;
$ua->ssl_opts(
SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE,
SSL_hostname => '',
verify_hostname => 0
);
my $response=$ua->request($request);
$self->{timer}=undef;
if($response->code==200) {
my $data=eval { from_json($response->decoded_content) };
if($@) {
return $self->new_false("Failed to decode response, error was: $@");
}
unless(exists $data->{url} and $data->{self}) {
my $msg=exists $data->{error} ? $data->{error} : 'unknown slack error';
return $self->new_false("Failed to get valid connection info, error was: $msg");
}
$self->build_connection($data);
} else {
return $self->new_false("Failed to get conenction info from slack, error was: ".$response->status_line);
}
}
=item * my $id=$self->next_id
Provides an id for the next message.
=cut
sub next_id {
my ($self)=@_;
return ++$self->{next_id}
}
=item * if($self->is_connected) { ... }
Denotes if we are currently connected to slack
=cut
sub is_connected {
return defined($_[0]->connection)
}
=item * $self->send($ref)
Converts $ref to json and sends it on the session.
=cut
sub send {
my ($self,$ref)=@_;
my $json=to_json($ref);
if($self->connection) {
$self->connection->send($json);
++$self->stats->{total_messages_sent};
} else {
push @{$self->{backlog}},$json;
}
}
=item * $self->send_typing($json)
( run in 1.504 second using v1.01-cache-2.11-cpan-39bf76dae61 )