dvpolq
Last Updated: January 05, 2018
·
275
· yanick

Slack notifications for new team protips

Little script that check if there are any new
team protips, and publish them to the relevant Slack
channels:

#!/usr/bin/env perl 

package CoderwallToSlack;

use 5.20.0;

use strict;
use warnings;

use LWP::Simple;
use JSON;
use Web::Query::LibXML;
use Path::Tiny;
use WebService::Slack::WebApi;
use List::AllUtils qw/ uniq /;
use YAML;

use Moose;
use MooseX::MungeHas 'is_ro';

use experimental 'postderef', 'signatures';

has config_file => ();

has config => sub($self) {
    $self->config_file ? YAML::LoadFile($self->config_file) : {};
};

has slack => sub($self) {
    WebService::Slack::WebApi->new(token => $self->config->{token} );
};

has channels => (
    traits => [ qw/ Hash / ],
    lazy => 1,
    default => sub ($self){
        +{ map { $_->{name} => $_->{id} } $self->slack->channels->list->{channels}->@* }
    },
    handles => {
        channel => 'get',
    },
);

has repo => sub { path('repo') };

has protips => ( 
    traits => [ qw/ Array / ],
    lazy => 1,
    default => sub ($self){
        wq( 'https://coderwall.com/team/infinity-interactive' )
            ->find('article h3 a')->map(sub{ $_->attr('href') })
    },
    handles => {
        all_protips => 'elements',
    }
);

sub run($self) {
    $self->process_protip($_) for $self->all_protips;
}

sub process_protip ($self,$url) {
    my $local = $self->repo->child( ( split '/', $url)[-1] );

    return if -f $local;

    $url = "https://coderwall.com$url";

    mirror( $url, $local );

    my $doc = wq( $local->slurp );

    my $title = $doc->find( 'header h1' )->text =~ s/^\s+|\s+$//gr;
    my $author = $doc->find( 'li.user a' )->text =~ s/^\s+|\s+$//gr;
    my @tags = split ' ',  $doc->find( 'ul#tags li' )->text;

    my $post = "new coderwall protip by $author: $title - <$url>";

    my @channels = $self->channels_for(@tags);

    for ( grep { $_ } map { $self->channel($_) } @channels ) {
        $self->slack->chat->post_message(
            channel => $_,
            text    => $post,
        );
    }
}

sub channels_for ($self,@tags){
    uniq map { split ' ', $self->config->{tag_channels}{$_} } @tags;
}

__PACKAGE__->new( config_file => shift )->run;

The script needs a config file that
gives the api token to talk to Slack,
and the mapping from tags to channels
to post to:

token: hush
tag_channels: 
    git: test