App-RoboBot

 view release on metacpan or  search on metacpan

lib/App/RoboBot/Network/Slack.pm  view on Meta::CPAN

    # For now, set an arbitrary limit on responses of 4K (SlackRTM says 16K,
    # which assuming absolute worst-case with wide characters would be 4K
    # glyphs, but even that seems really excesive for a chatbot).
    if (length($output) > 4096) {
        $output = substr($output, 0, 4096) .
            "\n\n... Output truncated ...";
    }

    $self->client->send({
        channel => $response->channel->extradata->{'slack_id'},
        type    => 'message',
        text    => $output,
    });

    $response->clear_content;

    return;
}

sub handle_message {
    my ($self, $msg) = @_;

    $self->log->debug('Received incoming message.');

    return unless exists $msg->{'ts'};
    return if int($msg->{'ts'}) <= $self->start_ts + 5;

    $self->log->debug('Message passed startup timestamp check.');

    # Short circuit if this isn't a 'message' type message.
    return unless defined $msg && ref($msg) eq 'HASH'
        && exists $msg->{'type'} && $msg->{'type'} eq 'message'
        && exists $msg->{'text'} && $msg->{'text'} =~ m{\w+};

    $self->log->debug('Message payload appears valid.');

    # Ignore messages which are hidden or have a subtype (these are generall
    # message edits or similar events).
    # TODO: Consider trapping message_edit subtypes and replacing log history?
    #       Most likely more work than it's worth, especially since it would
    #       require direct and special-snowflake interaction with a plugin.
    return if exists $msg->{'subtype'} && $msg->{'subtype'} =~ m{\w+};
    return if exists $msg->{'hidden'} && $msg->{'hidden'} == 1;

    $self->log->debug('Message has no subtype and is not hidden.');

    $self->log->debug(sprintf('Resolving nick for Slack ID %s.', $msg->{'user'}));
    my $nick    = $self->resolve_nick($msg->{'user'});

    $self->log->debug(sprintf('Resolving channel for Slack ID %s.', $msg->{'channel'}));
    my $channel = $self->resolve_channel($msg->{'channel'});

    return unless defined $nick && defined $channel;

    my $raw_msg = exists $msg->{'text'} && defined $msg->{'text'} ? $msg->{'text'} : '';

    # Remove brackets around URLs. Do alt-named ones first, then URL-only links.
    $raw_msg =~ s{<(http[^|>]+)\|[^>]+>}{$1}g;
    $raw_msg =~ s{<(http[^>]+)>}{$1}g;

    # Unescape a couple things from Slack.
    $raw_msg =~ s{\&amp;}{&}g;
    $raw_msg =~ s{\&lt;}{<}g;
    $raw_msg =~ s{\&gt;}{>}g;

    $self->log->debug('Raw message stripped of markup.');

    my ($message);

    eval {
        $message = App::RoboBot::Message->new(
            bot     => $self->bot,
            raw     => $raw_msg,
            network => $self,
            sender  => $nick,
            channel => $channel,
        );
    };

    return $self->log->fatal($@) if $@;

    $self->log->debug('Message object constructed, preparing to process.');

    $message->process;
}

sub resolve_channel {
    my ($self, $slack_id) = @_;

    return $self->channel_cache->{$slack_id} if exists $self->channel_cache->{$slack_id};

    my $channel;

    my $res = $self->bot->config->db->do(q{
        select id, name, extradata
        from channels
        where network_id = ? and extradata @> ?
    }, $self->id, encode_json({ slack_id => $slack_id }));

    if ($res && $res->next) {
        $channel = App::RoboBot::Channel->new(
            id          => $res->{'id'},
            name        => $res->{'name'},
            extradata   => decode_json($res->{'extradata'}),
            network     => $self,
            config      => $self->bot->config,
        );

        $self->channel_cache->{$slack_id} = $channel;
        return $channel;
    }

    my ($json, $chandata);

    # Slack has different API endpooints for channels and private groups, so
    # make sure we're using the right one based on the first character of the
    # identifier. And some, like direct messages, return fairly different data
    # structures, so each type should handle decoding and massaging their own.
    if (substr($slack_id, 0, 1) eq 'C') {
        $json = get('https://slack.com/api/channels.info?token=' . $self->token . '&channel=' . $slack_id);
        eval { $json = decode_json($json) };



( run in 0.834 second using v1.01-cache-2.11-cpan-39bf76dae61 )