The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Bot::ChatBots::Role::Source - Bot::ChatBots Role for sources

SYNOPSIS

   package Bot::ChatBots::Whatever::WebHook;
   use Moo;
   with 'Bot::ChatBots::Role::Source';
   with 'Bot::ChatBots::Role::WebHook';

   sub normalize_record {
      return shift; # not much of a normalization, huh?
   }

   sub parse_request {
      my ($self, $request) = @_;
      my @updates = $request->json;
      return @updates;
   }

   sub render_response {
      my ($self, $controller, $response, $update) = @_;

      # E.g. Telegram allows you to answer directly...
      $response = {text => $response} unless ref $response;
      local $response->{method} = $response->{method}
         // 'sendMessage';
      local $response->{chat_id} = $response->{chat_id}
         // $update->{message}{chat}{id};
      return $controller->render(json => $response);
   }

   1;

DESCRIPTION

This role abstracts elements that identify a source. It is most probably used together with Bot::ChatBots::Role::WebHook (which requires a lot of its methods) but it doesn't have to.

What Should You Provide/Override

This is what you should provide and probably override in the general case:

  • a class_custom_pairs returning key/value pairs you want to add to the source provided back by "pack_source";

  • mandatorily a "normalize_record" method (see below for details);

  • either provide a processor (see "processor") or override "process". This is important if you want to do "something" e.g. with the return value from the "processor", so you might do this:

       around process => sub {
          my ($orig, $self, $record) = @_;
          my $retval = $orig->($self, $record); # call original "super" method
    
          # now you have $retval and $record... do what you deem necessary!
    
          return $retval; # or anything else
       };

ACCESSORS

The following methods have a same-named option that can be passed to the constructor.

custom_pairs

   my $hash_ref = $obj->custom_pairs;
   $obj->custom_pairs(\%some_key_value_pairs);

Accessor for custom key/value pairs. These are expanded in the source section of the record passed to "process".

processor

   my $processor_sub = $obj->processor;

Read-only accessor for a processor sub reference.

By default, "process" calls this to retrieve a sub reference that will be called with the update record. You might want to look at Data::Tubes, although anything supporting the "process" interface will do.

typename

   my $name = $obj->typename;

Read-only accessor to the type of this source of messages. See BUILD_typename for the default value generated from the class name.

METHODS

It should be safe to override the following methods in your classes composing this role.

BUILD_processor

Builder for "processor". Throws an exception. You can override this in your composing class.

BUILD_typename

Builder for "typename". It is derived from the class name by getting the last meaningful part, see examples below:

   WebHook                          --> webhook
   Bot::ChatBots::Telegram::WebHook --> telegram
   Bot::ChatBots::Whatever          --> whatever

In simple terms:

  • if the class name has one single part only, take it

  • otherwise, take last if it's not webhook (case-insensitively)

  • otherwise get the previous to last. This lets you call your class Something::WebHook and get something back, which makes more sense than taking webhook (as it would probably be the name for a lot of adapters!).

Of course you can set "typename" directly on construction if you want.

pack_source

   my $hashref = $obj->pack_source(%args);
      $hashref = $obj->pack_source(\%args);

Make a nice pack of info available for easy pushing inside a record and provide info along the line. This hash reference will most probably be available under key source in the record passed to "process".

The following fields will be set:

class

the class name;

refs

a Bot::ChatBots::Weak instance containing the following fields:

self

the instance itself;

type

whatever "typename" returns

After these fields, if the class can('class_custom_pairs'), they are retrieved and added. They might override the fields above of course.

After this, all pairs recorded in "custom_pairs" are added, again overriding whatever was already present.

After this, all pairs in $args{source_pairs} are added. so they can override everything.

If $args{refs} is present, its element are added to the Bot::ChatBots::Weak object at key ref (see above). This allows you to add elements that you want to keep around but do not want to propagate in case you want to freeze the record (e.g. to queue for execution elsewhere).

process

   my $outcome = $obj->process($hashref);

Process an incoming record. This is built by the relevant actual source, e.g. a webhook or a long-poll based class/object.

By default it is a thin wrapper around "processor", in order to ease your library's client to provide a processing sub reference.

process_updates

   my @results = $obj->process_updates(%args);
   my $results = $obj->process_updates(%args);
      @results = $obj->process_updates(\%args);
      $results = $obj->process_updates(\%args);

Process incoming updates. Note that a record is a wrapper to an update, because it usually contains the update at key update.

The input %args can contain the following keys:

rethrow

process_updates by default catches all exceptions and goes on, set this to a true value if you want the exception to be rethrown. You can also define a method rethrow to return a boolean value, which will be used in case this key is not present in %args; otherwise false is assumed, meaning that the exceptions will NOT be rethrown;

record_pairs

hash reference with key/value pairs that will be fit directly inside the record. These key/value pairs override whatever is put in the record, so use with caution; see also source_pairs below for something less invasive, and keep in mind that the object will still receive the record via "process";

refs

hash reference with key/value pairs of references that should not be propagated in case the object is frozen. See "pack_source";

source_pairs

hash reference with key/value pairs that will be fit inside the source hash reference inside the record. These values are actually used by "pack_source", see there for additional details;

updates

array reference with the list of updates

should_rethrow

   die $exception if $obj->should_rethrow(%args); # OR
   die $exception if $obj->should_rethrow(\%args);

Assess whether a rethrow is requestes or not, according to the following procedure:

  • first of all %args is searched to look for key rethrow, if present this is returned, OTHERWISE

  • if $obj supports method rethrow, it is called and provided back, OTHERWISE

  • 0 (i.e. a false value) is returned, under the assumption that you don't want to get exceptions back by default.

REQUIRED METHODS

This class defines a Moo::Role, so it's not a standalone thing by itself. The following methods are required to exist in the class that composes this role.

normalize_record

   my $record = $obj->normalize_record($input_record);

Give $input_record a possibly better shape to allow for tubes down along the road to work on a common format.

SEE ALSO

Bot::ChatBots, Bot::ChatBots::Role::WebHook.

AUTHOR

Flavio Poletti <polettix@cpan.org>

COPYRIGHT AND LICENSE

Copyright (C) 2016 by Flavio Poletti <polettix@cpan.org>

This module is free software. You can redistribute it and/or modify it under the terms of the Artistic License 2.0.

This program is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose.