AnyEvent-Discord

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

Revision history for perl module AnyEvent::Discord

0.7 2021-10-25

 - Update to AnyEvent::WebSocket::Client 0.54
 - Change initial delay for reconnect to 1 second from 4 seconds
 - Fire an AnyEvent->condvar->send on timer end
 - Add timestamp to debug messages when debug is true
 - Randomize heartbeat interval to Discord spec

0.4 2021-01-28

 - Back to Moops

0.2 2021-01-28

 - Fix indexing for Zydeco

doc/AnyEvent-Discord.md  view on Meta::CPAN

    identify itself, begin a heartbeat, and once complete, Discord will fire a
    'ready' event to the handler.

- send($channel\_id, $content)

    Send a message to the provided channel.

- typing($channel\_id)

    Starts the "typing..." indicator in the provided channel. This method issues the
    typing request, and starts a timer on the caller's behalf to keep the indicator
    active. Returns an instance of that timer to allow the caller to undef it when
    the typing indicator should be stopped.

        my $instance = $client->typing($channel);
        # ... perform some actions
        $instance = undef;
        # typing indicator disappears

- close()

    Close the connection to the server.

lib/AnyEvent/Discord.pm  view on Meta::CPAN

  has users => ( is => 'ro', isa => HashRef, default => sub { {} } );

  # UserAgent
  has _ua => ( is => 'rw', default => sub { LWP::UserAgent->new() } );
  # Caller-defined event handlers
  has _events => ( is => 'ro', isa => HashRef, default => sub { {} } );
  # Internal-defined event handlers
  has _internal_events => ( is => 'ro', isa => HashRef, builder => '_build_internal_events' );
  # WebSocket
  has _socket => ( is => 'rw' );
  # Heartbeat timer
  has _heartbeat => ( is => 'rw' );
  # Last Sequence
  has _sequence => ( is => 'rw', isa => Num, default => 0 );
  # True if caller manually disconnected, to avoid reconnection
  has _force_disconnect => ( is => 'rw', isa => Bool, default => 0 );
  # Host the backoff algorithm for reconnection
  has _backoff => ( is => 'ro', default => sub { Algorithm::Backoff::Exponential->new( initial_delay => 1 ) } );

  method _build_internal_events() {
    return {

lib/AnyEvent/Discord.pm  view on Meta::CPAN


      # Handle reconnection
      $socket->on('finish', sub {
        my ($c) = @_;
        $self->_debug('Received disconnect');
        $self->_handle_internal_event('disconnected');
        unless ($self->_force_disconnect()) {
          my $seconds = $self->_backoff->failure();
          $self->_debug('Reconnecting in ' . $seconds);
          my $reconnect;
          $reconnect = AnyEvent->timer(
            after => $seconds,
            cb    => sub {
              $self->connect();
              $reconnect = undef;
              AnyEvent->condvar->send();
            }
          );
        }
      });

lib/AnyEvent/Discord.pm  view on Meta::CPAN

      $self->_backoff->success();
      AnyEvent->condvar->send();
    });
  }

  method send($channel_id, $content) {
    return $self->_discord_api('POST', 'channels/' . $channel_id . '/messages', encode_json({content => $content}));
  }

  method typing($channel_id) {
    return AnyEvent->timer(
      after    => 0,
      interval => 5,
      cb       => sub {
        $self->_discord_api('POST', 'channels/' . $channel_id . '/typing');
        AnyEvent->condvar->send();
      },
    );
  }

  method close() {

lib/AnyEvent/Discord.pm  view on Meta::CPAN


  # Send trace messages to console if verbose is 2
  method _trace(Str $message) {
    say time . ' ' . $message if ($self->verbose and $self->verbose == 2);
  }

  # Called when Discord provides the 'hello' event
  method _event_hello(AnyEvent::Discord::Payload $payload) {
    $self->_debug('Received hello event');
    my $interval = $payload->d->{'heartbeat_interval'};
    my $timer = AnyEvent->timer(
      after    => $interval * rand() / 1000,
      interval => $interval / 1000,
      cb       => sub {
        $self->_debug('Heartbeat');
        $self->_ws_send_payload(AnyEvent::Discord::Payload->from_hashref({
          op => 1,
          d  => $self->_sequence()
        }));
        AnyEvent->condvar->send();
      }
    );
    $self->_heartbeat($timer);
  }

  # GUILD_CREATE event
  method _event_guild_create($client, HashRef $data, Num $opcode?) {
    $self->guilds->{$data->{'id'}} = $data->{'name'};

    # We get channel and user information along with the guild, populate those
    # at the same time
    foreach my $channel (@{$data->{'channels'}}) {
      if ($channel->{'type'} == 0) {

lib/AnyEvent/Discord.pm  view on Meta::CPAN

identify itself, begin a heartbeat, and once complete, Discord will fire a
'ready' event to the handler.

=item send($channel_id, $content)

Send a message to the provided channel.

=item typing($channel_id)

Starts the "typing..." indicator in the provided channel. This method issues the
typing request, and starts a timer on the caller's behalf to keep the indicator
active. Returns an instance of that timer to allow the caller to undef it when
the typing indicator should be stopped.

  my $instance = $client->typing($channel);
  # ... perform some actions
  $instance = undef;
  # typing indicator disappears

=item close()

Close the connection to the server.



( run in 0.242 second using v1.01-cache-2.11-cpan-cba739cd03b )