Last active
April 20, 2017 03:21
-
-
Save preaction/a6fa9d30457e741bc8d375b93ae97aa2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
=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