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 )