Merge pull request #7 from parall4x/master

Added usage functionality to rosbot
This commit is contained in:
John Sinteur 2016-08-18 20:52:42 +02:00 committed by GitHub
commit 381e0ec21d

View File

@ -7,13 +7,127 @@
# Configuration:
# See the various handlers in bash/
#
# Usage:
# build
# Detailed line 1
# Detailed line 2
# Detailed line 3
#
# respond
# Detailed line 11
# Detailed line 22
# Detailed line 33
#
#
# Commands:
# hubot build <repo> <target> - Builds a .pdf file from <target> in <repo>
# hubot convert <repo> <target> - Builds a .xml file from <target> in <repo>
# hubot invoice <repo> <target> - Builds pdf invoice from quote
# hubot quickscope <repo> <namespace> [branch=MASTER] - Converts quickscope into quotation
# hubot startpentest <name> - Bootstraps a pentest
# hubot startquote <name> - Bootstraps a quotation
# hubot validate <parms..> - Validates a report/quotation
# hubot usage [command] - Displays usage information for command. If no command is specified, supported commands are displayed.
#
# Author:
# Peter Mosmans
# John Sinteur
# Daniel Attevelt
#
# This is part of the PenText framework
#
admins = ['admin']
USAGE_LABEL = '# Usage:'
Fs = require 'fs'
Path = require 'path'
admins = ['peter']
###
This will initialise the usage information for the chatops command used in the pentext framework
It will parse the file comment sections in search of usage information. See above for an example
! This section should always be above the commands section and should always be terminated by two consecutive #s !
! Only single word commands are supported !
robot gets a new property .usages which can be used later on
###
init_usage = (robot) ->
robot.usages = []
load_scripts(robot)
###
This will load all the scripts in the same folder as this one. It will then proceed
to parsing those scripts in order to extract the rosbot command usage information
###
load_scripts = (robot) ->
if Fs.existsSync(__dirname)
for file in Fs.readdirSync(__dirname).sort()
fullPath = Path.join __dirname, file
robot.logger.info "File: " + fullPath
body = Fs.readFileSync fullPath, 'utf-8'
parse_scripts(robot, body)
###
This function will parse the script for usage information.
It will do so by looping through every comment line until it hits the # Usage: label
Then it will start to look for a command tag that is identified by:
# (3 spaces) <command>. The will let the function know it's dealing with a command identifiers.
# (5 spaces) <infoline> lets the function know it's dealing with info line that should go together with the previously encountered command.
The sequence is broken by two sequential empty comment lines. e.g.:
#
#
###
parse_scripts = (robot, body) ->
parsing_usage = false
current_command = null
# https://regex101.com
cmd_regex = /^#[ ]{3}[\S]+/i
info_regex = /^#[ ]{5}[\S]+/i
# Loop through each comment line until there is none.
for line in body.split "\n"
break unless line[0] is '#' or line.substr(0, 2) is '//'
# Determine if we've reached the Usage: tag
if line.indexOf(USAGE_LABEL) != -1
parsing_usage = true
if parsing_usage
# Pre-cleaning ...
cleanedLine = line.replace(/^(#|\/\/)\s?/, "").trim()
# Are we dealing with a command?
if line.match cmd_regex
current_command = cleanedLine
robot.usages[current_command] = []
# Are we dealing with an info line ?
if line.match info_regex
if not robot.usages[current_command]
robot.logger.debug "Error parsing chatpos usage info: found info line, but no command line"
else
robot.usages[current_command].push cleanedLine
# Detects two sequential #'s and quits parsing usage when it does
if cleanedLine.length == 0
if current_command == null
parsing_usage = false
else
current_command = null
# Sanity check
robot.logger.info "--- Following usage information parsed ----"
for command, lines of robot.usages
for index, line of lines
robot.logger.info "* #{command} : #{line}"
module.exports = (robot) ->
run_cmd = (cmd, args, cb ) ->
@ -22,6 +136,13 @@ module.exports = (robot) ->
child.stdout.on "data", (buffer) -> cb buffer.toString()
child.stderr.on "data", (buffer) -> cb buffer.toString()
init_usage(robot)
# ***************************************************************************
# ChatOps command handlers
# ***************************************************************************
robot.respond /build (.*)/i, id:'chatops.build', (msg) ->
msg.match[0] = msg.match[0].replace(/^[a-z0-9]+$/i);
msg.match.shift();
@ -93,3 +214,30 @@ module.exports = (robot) ->
args = msg.match[0].split(" ");
cmd = "bash/handler_validate";
run_cmd cmd, args, (text) -> msg.send text.replace("\n","");
# Handler for the usage command.
# Note that the regex option group (.*) also captures the space after the command
# This allows for the case when there is no command specified, supported commands can be displayed
robot.respond /usage(.*)/i, id:'chatops.usage', (msg) ->
msg.match[0] = msg.match[0].replace(/^[a-z0-9]+$/i);
msg.match.shift();
args = msg.match[0].trim().split(" ");
command = args[0]
# If not command is provided, return information on which commands can be handled
if command.trim().length == 0
msg.send "I can provide usage information for the following commands:"
for command of robot.usages
msg.send command
msg.send "Issue the command: usage <command> for usage information for this command"
return
# This deals when unsupported commands
if not robot.usages[command]
msg.send "I have no usage information for: " + command
return
# All odd case have been dealt with, let's get down to business
for index, line of robot.usages[command]
msg.send line