Skip to content

Instantly share code, notes, and snippets.

@preaction
Last active April 20, 2017 03:21
Show Gist options
  • Save preaction/a6fa9d30457e741bc8d375b93ae97aa2 to your computer and use it in GitHub Desktop.
Save preaction/a6fa9d30457e741bc8d375b93ae97aa2 to your computer and use it in GitHub Desktop.
=head1 NAME
=head1 SYNOPSIS
=head1 DESCRIPTION
=head1 INSTALLING
=head1 SEE ALSO
=cut
use v5.22;
use Mojolicious::Lite;
use Getopt::Long qw( GetOptionsFromString );
app->moniker('lg');
plugin Config => {
default => {
slack => {
token => '0YznHl9yf5hfzrrlxlh8T2Qp',
},
},
};
# The list of POPs fetched from LookingGlass. We refresh this list every
# 24 hours
helper pop_list => sub {
my ( $c ) = @_;
state $pop_list = [];
state $pop_fetched = 0;
state $ua = Mojo::UserAgent->new;
if ( !@$pop_list || $pop_fetched < time + 60*60*24 ) {
my $tx = $ua->get( 'http://lg.servercentral.com' );
my $options = $tx->res->dom( 'select[name="router"] option' );
$pop_list = [ $options->map( sub { shift->attr( 'value' ) } )->each ];
$pop_fetched = time;
}
return $pop_list;
};
my $route = plugin 'ServerCentral::Plugin::Slack';
$route->post('/lg' => sub {
my $c = shift;
$c->app->log->debug( 'Request: ' . $c->req );
# The incoming Slack request has the following parameters:
# - team_id
# - team_domain
# - channel_id
# - channel_name
# - user_id
# - user_name
# - command
# This is the "/command" entered by the user
# - text
# This is the rest of the text after the "/command"
# - response_url
# If your response will take more than the 3-second timeout,
# this URL can be used up to 5 times within 30 minutes to post
# a response, if the response will be delayed. The format of
# this response should be the same as the JSON response,
# below.
my $user = $c->param('user_name');
my %opt = (
dns => 0, # Default to not doing DNS lookups during traceroute
);
my ( $ok, $args ) = GetOptionsFromString(
$c->param('text'),
\%opt,
'ipv6|6',
'dns!',
'pop|p',
);
my @args = split $args;
if ( !$opt{pop} && !$c->stash( 'payload' ) ) {
# We were not provided a point-of-presence, so ask the user to
# select one from a list.
return $c->render( json => {
text => 'You must specify a PoP',
attachments => [
{
text => 'Select a PoP',
callback_id => 'select_pop',
actions => [
{
name => 'pop_list',
type => 'select',
options => [
map +{ text => $_, value => $_ }, @{ $c->pop_list }
],
},
],
},
],
} );
}
my $pop = $opt{pop} || $c->stash( 'payload' )->{actions}[0]{selected_options}[0]{value};
my %command = (
bgp => 'bgp',
traceroute => 'trace',
ping => 'ping',
);
my %form = (
query => $args[0] eq 'traceroute' && !$opt{dns} ? 'trace-no-resolve' : $command{ $args[0] },
protocol => $opt{ipv6} ? 'IPv6' : 'IPv4',
router => $pop,
);
$c->delay->steps(
sub {
my ( $delay ) = @_;
$delay->data->{ua}->post( 'http://lg.servercentral.com', form => \%form, cb => $delay->begin );
},
sub {
my ( $delay, $ua, $tx ) = @_;
my $text = $tx->res->dom( 'pre code' )->all_text;
$ua->post( $c->param( 'response_url' ), json => {
response_type => 'in_channel',
text => "```$text```",
} );
},
)->data( ua => Mojo::UserAgent->new );
# The response is a JSON object with the following keys:
# - response_type
# The type of response. By default, this is "ephemeral", and
# only seen by the user who issued the command. Other valid
# options are:
# * in_channel
# This message will be displayed in the channel
# - text
# The text of the response. Will be processed as Markdown.
# There are special sequences which use &, <, and >, so if
# you need to use these as text, use HTML encoding.
# See: https://api.slack.com/docs/message-formatting
# - mrkdown
# If true, processes the "text" field as Markdown. Defaults to
# true (turn off Markdown processing by setting this to false)
# - attachments
# Attachments are richer than the regular text and allow
# images, name/value fields, and buttons.
# See: https://api.slack.com/docs/message-attachments
# Rendering this minimal response to indicate the operation is in
# progress.
$c->render(json => { response_type => 'in_channel' } );
});
app->start;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment