diff options
Diffstat (limited to 'contrib/modules')
-rw-r--r-- | contrib/modules/m_bugzilla.sh | 231 | ||||
-rw-r--r-- | contrib/modules/m_calc.sh | 74 | ||||
-rw-r--r-- | contrib/modules/m_convert.sh | 117 | ||||
-rw-r--r-- | contrib/modules/m_eix.sh | 101 | ||||
-rw-r--r-- | contrib/modules/m_eval.sh | 55 | ||||
-rw-r--r-- | contrib/modules/m_helloworld.sh | 193 | ||||
-rw-r--r-- | contrib/modules/m_perl/__main__.sh | 74 | ||||
-rw-r--r-- | contrib/modules/m_perl/safe_eval.pl | 25 |
8 files changed, 870 insertions, 0 deletions
diff --git a/contrib/modules/m_bugzilla.sh b/contrib/modules/m_bugzilla.sh new file mode 100644 index 0000000..c428cdc --- /dev/null +++ b/contrib/modules/m_bugzilla.sh @@ -0,0 +1,231 @@ +#!/bin/bash +# -*- coding: utf-8 -*- +########################################################################### +# # +# envbot - an IRC bot in bash # +# Copyright (C) 2007-2008 Arvid Norlander # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see <http://www.gnu.org/licenses/>. # +# # +########################################################################### +#--------------------------------------------------------------------- +## Check bugs using the program bugz and return output from it. +## @pybugz bugz is a tool to search Gentoo bug reports (or other bugzillas)<br /> +## @pybugz From eix pybugz:<br /> +## @pybugz Description: Command line interface to (Gentoo) Bugzilla +## @Dependencies This module therefore depends on:<br /> +## @Dependencies pybugz +## @Config_variables To set bugzilla to use something like this in config:<br /> +## @Config_variables <pre>config_module_bugzilla_tracker_name[0]='gentoo' +## @Config_variables config_module_bugzilla_tracker_url[0]='https://bugs.gentoo.org/'</pre> +## @Config_variables Must end in trailing slash! Also the first entry will be the default.<br /> +## @Config_variables You also need to specify flood limiting<br /> +## @Config_variables (how often in seconds)<br /> +## @Config_variables <tt>config_module_bugzilla_rate='10'</tt> +#--------------------------------------------------------------------- + +module_bugzilla_INIT() { + modinit_API='2' + modinit_HOOKS='after_load' + commands_register "$1" 'bugs_search' 'bugs search' || return 1 + commands_register "$1" 'bug' || return 1 + helpentry_module_bugzilla_description="Search in bugzilla bug trackers." + + helpentry_bugzilla_bugs_search_syntax='[-t <tracker>] [-(all|closed)] <pattern>' + helpentry_bugzilla_bugs_search_description='Search for <pattern> in <tracker> (or the default tracker).' + + helpentry_bugzilla_bug_syntax='[-t <tracker>] <id>' + helpentry_bugzilla_bug_description='Look up the bug with <id> in <tracker> (or the default tracker).' +} + +module_bugzilla_UNLOAD() { + unset module_bugzilla_last_query module_bugzilla_default_bugtracker + unset module_bugzilla_parse_config module_bugzilla_find_tracker + hash_reset 'bugzilla_tracker' +} + +module_bugzilla_REHASH() { + module_bugzilla_parse_config +} + +#--------------------------------------------------------------------- +## Initialize the hash of name -> url mapping +## @Type Private +#--------------------------------------------------------------------- +module_bugzilla_parse_config() { + hash_reset 'bugzilla_tracker' + local index + for index in "${!config_module_bugzilla_tracker_name[@]}"; do + hash_set 'bugzilla_tracker' \ + "${config_module_bugzilla_tracker_name[index]}" \ + "${config_module_bugzilla_tracker_url[index]}" + done + module_bugzilla_default_bugtracker="${config_module_bugzilla_tracker_url[0]}" +} + +#--------------------------------------------------------------------- +## Find what tracker to use from the parameters. +## @param Name of parameter variable. +## @param Name of bugtracker variable. +## @Type Private +#--------------------------------------------------------------------- +module_bugzilla_find_tracker() { + if [[ "${!1}" =~ ^(-(tracker|t)\ +([A-Za-z0-9]+)\ +)(.+) ]]; then + local tindex="${BASH_REMATCH[3]}" + # Store result back in variable. + printf -v "$1" '%s' "${BASH_REMATCH[4]}" + local turl + hash_get 'bugzilla_tracker' "$tindex" 'turl' + if [[ $turl ]]; then + printf -v "$2" '%s' "$turl" + else + feedback_generic_error "$sendernick" "bugs search" "No such bug tracker found." + fi + else + printf -v "$2" '%s' "${module_bugzilla_default_bugtracker}" + fi +} + +# Called after module has loaded. +# Check for bugz +module_bugzilla_after_load() { + if ! hash bugz > /dev/null 2>&1; then + log_error "Couldn't find bugz command line tool. The bugzilla module depend on that tool (emerge pybugz to get it on Gentoo)." + return 1 + fi + if [[ -z ${config_module_bugzilla_tracker_url[0]} ]]; then + log_error "Please set at least config_module_bugzilla_url[0] in config." + return 1 + fi + if [[ -z ${config_module_bugzilla_tracker_name[0]} ]]; then + log_error "Please set at least config_module_bugzilla_name[0] in config." + return 1 + fi + if [[ -z $config_module_bugzilla_rate ]]; then + log_error "Please set config_module_bugzilla_rate in config." + return 1 + fi + module_bugzilla_parse_config + unset module_bugzilla_last_query + module_bugzilla_last_query='0' +} + +module_bugzilla_handler_bugs_search() { + # Accept this anywhere, unless someone can give a good reason not to. + local sender="$1" + local channel="$2" + local sendernick= + parse_hostmask_nick "$sender" 'sendernick' + # If it isn't in a channel send message back to person who send it, + # otherwise send in channel + if ! [[ $2 =~ ^# ]]; then + channel="$sendernick" + fi + local parameters="$3" + local bugtracker + module_bugzilla_find_tracker 'parameters' 'bugtracker' + if [[ "$parameters" =~ ^(-(all|closed)\ +)?(.+) ]]; then + local mode="${BASH_REMATCH[2]}" + local pattern="${BASH_REMATCH[@]: -1}" + # Simple flood limiting + if time_check_interval "$module_bugzilla_last_query" "$config_module_bugzilla_rate"; then + time_get_current 'module_bugzilla_last_query' + local bugs_parameters="" + if [[ $mode = "all" ]]; then + bugs_parameters="-s all" + elif [[ $mode = "closed" ]]; then + bugs_parameters="-s CLOSED -s RESOLVED" + fi + log_info_file bugzilla.log "$sender made the bot run pybugz search on \"$pattern\"" + # We unset TERM because otherwise bugz output some control codes + local result="$(unset TERM; ulimit -t 4; bugz -fqb "$bugtracker" search $bugs_parameters "$pattern")" + local lines="$(wc -l <<< "$result")" + local header footer + # Some odd formatting chars are always returned (in some versions of pybugz), so we can't check for empty string. + if [[ ${#result} -le 10 ]]; then + header="No bugs matching \"$pattern\" found" + elif [[ $lines -gt 1 ]]; then + header="First bug matching \"$pattern\": " + footer=" ($lines more bugs found)" + else + header="One bug matching \"$pattern\" found: " + fi + if [[ $(head -n 1 <<< "$result") =~ \ ([0-9]+)\ +([^ ]+)\ +(.*)$ ]]; then + local pretty_result="${format_bold}${bugtracker}${BASH_REMATCH[1]}${format_bold} ${format_bold}Description${format_bold}: ${BASH_REMATCH[3]} ${format_bold}Assigned To${format_bold}: ${BASH_REMATCH[2]}" + fi + send_msg "$channel" "${header}${pretty_result}${footer}" + else + log_error_file bugzilla.log "FLOOD DETECTED in bugzilla module" + fi + else + feedback_bad_syntax "$sendernick" "bugs search" "[-t tracker] [-(all|closed)] <pattern>" + fi +} + +module_bugzilla_handler_bug() { + # Accept this anywhere, unless someone can give a good reason not to. + local sender="$1" + local channel="$2" + local sendernick= + parse_hostmask_nick "$sender" 'sendernick' + # If it isn't in a channel send message back to person who send it, + # otherwise send in channel + if ! [[ $2 =~ ^# ]]; then + channel="$sendernick" + fi + local parameters="$3" + local bugtracker + module_bugzilla_find_tracker 'parameters' 'bugtracker' + # Extract bug ID + if [[ "$parameters" =~ ^([0-9]+) ]]; then + local id="${BASH_REMATCH[1]}" + # Simple flood limiting + if time_check_interval "$module_bugzilla_last_query" "$config_module_bugzilla_rate"; then + time_get_current 'module_bugzilla_last_query' + log_info_file bugzilla.log "$sender made the bot check with pybugz for bug \"$id\"" + # We unset TERM because otherwise bugz output some control codes + local result="$(unset TERM; ulimit -t 4; bugz -fqb "$bugtracker" get -n "$id" | grep -E 'Title|Status|Resolution')" + local resultread pretty_result + local title status resolution + # Read the data out of the multiline result. + while read -r resultread; do + if [[ $resultread =~ ^Title[\ :]+([^ ].*) ]]; then + title="${BASH_REMATCH[1]}" + elif [[ $resultread =~ ^Status[\ :]+([^ ].*) ]]; then + status="${BASH_REMATCH[1]}" + elif [[ $resultread =~ ^Resolution[\ :]+([^ ].*) ]]; then + resolution="${BASH_REMATCH[1]}" + fi + done <<< "$result" + # Yes this is a bit of a mess + if [[ "$title" ]]; then + # This info is always here + pretty_result="${format_bold}Bug $id${format_bold} (${format_bold}Status${format_bold} $status" + # The resolution may not exist, add it if it does. + if [[ $resolution ]]; then + pretty_result+=", ${format_bold}Resolution${format_bold} $resolution" + fi + # And add the title in. Does not depend on if resolution exist. + pretty_result+="): $title (${bugtracker}${id})" + else + pretty_result="Bug $id not found" + fi + send_msg "$channel" "${pretty_result}" + else + log_error_file bugzilla.log "FLOOD DETECTED in bugzilla module" + fi + else + feedback_bad_syntax "$sendernick" "bug" "[-t tracker] <id>" + fi +} diff --git a/contrib/modules/m_calc.sh b/contrib/modules/m_calc.sh new file mode 100644 index 0000000..fa1d98d --- /dev/null +++ b/contrib/modules/m_calc.sh @@ -0,0 +1,74 @@ +#!/bin/bash +# -*- coding: utf-8 -*- +########################################################################### +# # +# envbot - an IRC bot in bash # +# Copyright (C) 2007-2008 EmErgE <halt.system@gmail.com> # +# Copyright (C) 2007-2008 Arvid Norlander # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see <http://www.gnu.org/licenses/>. # +# # +########################################################################### +#--------------------------------------------------------------------- +## Calculate with bc +## @Dependencies This module depends on bc +## @Dependencies (http://www.gnu.org/software/bc/bc.html) +#--------------------------------------------------------------------- + +module_calc_INIT() { + modinit_API='2' + modinit_HOOKS='' + if ! hash bc > /dev/null 2>&1; then + log_error "Couldn't find \"bc\" command line tool. The calc module depend on that tool." + return 1 + fi + commands_register "$1" 'calc' || return 1 + helpentry_module_calc_description="Simple calculator module." + helpentry_calc_calc_syntax='<expression>' + helpentry_calc_calc_description='Try to calculate <expression> using bc.' +} + +module_calc_UNLOAD() { + return 0 +} + +module_calc_REHASH() { + return 0 +} + +module_calc_handler_calc() { + local sender="$1" + local channel="$2" + local sendernick= + parse_hostmask_nick "$sender" 'sendernick' + # If it isn't in a channel send message back to person who send it, + # otherwise send in channel + if ! [[ $2 =~ ^# ]]; then + channel="$sendernick" + fi + local parameters="$3" + + # Sanity check on parameters + parameters="$(tr -d '\n\r\t' <<< "$parameters")" + if grep -Eq "scale=|read|while|if|for|break|continue|print|return|define|[e|j] *\(" <<< "$parameters"; then + send_msg "$channel" "${sendernick}: Can't calculate that, it contains a potential unsafe/very slow function." + elif [[ $parameters =~ \^[0-9]{4,} ]]; then + send_msg "$channel" "${sendernick}: Some too large numbers." + else + # Force some security guards + local myresult="$(ulimit -t 4; echo "$parameters" | bc -l 2>&1 | head -n 1)" + send_msg "$channel" "${sendernick}: $myresult" + fi + +} diff --git a/contrib/modules/m_convert.sh b/contrib/modules/m_convert.sh new file mode 100644 index 0000000..3910379 --- /dev/null +++ b/contrib/modules/m_convert.sh @@ -0,0 +1,117 @@ +#!/bin/bash +# -*- coding: utf-8 -*- +########################################################################### +# # +# envbot - an IRC bot in bash # +# Copyright (C) 2007-2008 Arvid Norlander # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see <http://www.gnu.org/licenses/>. # +# # +########################################################################### +#--------------------------------------------------------------------- +## Convert values with units +## @Dependencies This module depends on units +## @Dependencies (http://www.gnu.org/software/units/units.html) +#--------------------------------------------------------------------- + +module_convert_INIT() { + modinit_API='2' + modinit_HOOKS='' + if ! hash units > /dev/null 2>&1; then + log_error "Couldn't find \"units\" command line tool. The convert module depend on that tool." + return 1 + fi + # Is it GNU units? + if units --help > /dev/null 2>&1; then + module_convert_gnu=1 + else + module_convert_gnu=0 + fi + commands_register "$1" 'convert' || return 1 + helpentry_module_convert_description="Convert between different units." + helpentry_convert_convert_syntax='<value> <unit> [to] <unit>' + helpentry_convert_convert_description='Convert the value from one unit to another.' +} + +module_convert_UNLOAD() { + return 0 +} + +module_convert_REHASH() { + return 0 +} + +module_convert_handler_convert() { + local sender="$1" + local channel="$2" + local sendernick= + parse_hostmask_nick "$sender" 'sendernick' + # If it isn't in a channel send message back to person who send it, + # otherwise send in channel + if ! [[ $2 =~ ^# ]]; then + channel="$sendernick" + fi + local parameters="$3" + # Format: convert <value> <in unit> <out unit> + if [[ "$parameters" =~ ^([-0-9.]+)\ +([a-zA-Z0-9^/*]+)\ +(to\ +)?([a-zA-Z0-9^/*]+) ]]; then + local value="${BASH_REMATCH[1]}" + local inunit="${BASH_REMATCH[2]}" + local outunit="${BASH_REMATCH[@]: -1}" + # Construct expression of value and inunit, + # needed because of temperature + case $inunit in + C|F|K) + # This only work on GNU units. + if [[ $module_convert_gnu = 1 ]]; then + local inexpr="temp${inunit}($value)" + else + local inexpr="$value deg${inunit}" + fi + ;; + *) + local inexpr="$value $inunit" + ;; + esac + # Out: Temperature + case $outunit in + C|F|K) + # This only work on GNU units + if [[ $module_convert_gnu = 1 ]]; then + local outexpr="temp${outunit}" + else + local outexpr="deg${outunit}" + fi + local outunit="degrees $outunit" + ;; + *) + local outexpr="$outunit" + ;; + esac + + # Need to do the local separately or return code will be messed up. + local myresult + # Force some security guards + # We can't use -t, that doesn't work on *BSD units... + # so we use awk to get interesting lines. + # Then check pipestatus to give nice return code + myresult="$(ulimit -t 4; units -q "$inexpr" "$outexpr" 2>&1 | awk '/^\t[0-9]+/ {print $1} /\*/ {print $2} /[Ee]rror|[Uu]nknown/'; [[ ${PIPESTATUS[0]} -eq 0 ]] || exit 1)" + if [[ $? -eq 0 ]]; then + send_msg "$channel" "${sendernick}: $myresult $outunit" + else + send_msg "$channel" "${sendernick}: Error: $myresult" + fi + else + feedback_bad_syntax "$sendernick" "convert" "<value> <in unit> [to] <out unit>" + fi +} diff --git a/contrib/modules/m_eix.sh b/contrib/modules/m_eix.sh new file mode 100644 index 0000000..46ba964 --- /dev/null +++ b/contrib/modules/m_eix.sh @@ -0,0 +1,101 @@ +#!/bin/bash +# -*- coding: utf-8 -*- +########################################################################### +# # +# envbot - an IRC bot in bash # +# Copyright (C) 2007-2008 Arvid Norlander # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see <http://www.gnu.org/licenses/>. # +# # +########################################################################### +#--------------------------------------------------------------------- +## Check eix and return output from it. +## @eix eix is a tool to search Gentoo packages<br /> +## @eix From eix eix:<br /> +## @eix <tt> Description: Small utility for searching ebuilds with indexing for fast results</tt> +## @Dependencies This module therefore depends on:<br /> +## @Dependencies Gentoo<br /> +## @Dependencies eix<br /> +## @Config_variables You need to specify flood limiting in config.<br /> +## @Config_variables (how often in seconds)<br /> +## @Config_variables <tt>config_module_eix_rate='5'</tt><br /> +#--------------------------------------------------------------------- + +module_eix_INIT() { + modinit_API='2' + modinit_HOOKS='after_load' + commands_register "$1" 'eix' || return 1 + helpentry_module_eix_description="Search in Gentoo package database." + + helpentry_eix_eix_syntax='<pattern>' + helpentry_eix_eix_description='Search for wildcard pattern in the local copy of the Gentoo package database.' +} + +module_eix_UNLOAD() { + unset module_eix_format_string module_eix_last_query +} + +module_eix_REHASH() { + return 0 +} + +# Called after module has loaded. +# Check for eix and config being sane. +module_eix_after_load() { + # Check (silently) for eix + if ! hash eix >/dev/null 2>&1; then + log_error "Couldn't find \"eix\" command line tool. The eix module depend on that tool." + return 1 + fi + if [[ -z $config_module_eix_rate ]]; then + log_error_file eix.log "YOU MUST SET config_module_eix_rate IN YOUR CONFIG IN ORDER TO USE THE EIX MODULE" + return 1 + fi + # Flood limiting. + unset module_eix_last_query + module_eix_last_query='0' +} + +#--------------------------------------------------------------------- +## eix format string. +## @Type Private +#--------------------------------------------------------------------- +module_eix_format_string="<category>/${format_bold}<name>${format_bold} \(<availableversionsshort>\) \(${format_bold}<homepage>${format_bold}\): <description>" + +module_eix_handler_eix() { + # Accept this anywhere, unless someone can give a good reason not to. + local sender="$1" + local channel="$2" + # If it isn't in a channel send message back to person who send it, + # otherwise send in channel + if ! [[ $2 =~ ^# ]]; then + parse_hostmask_nick "$sender" 'channel' + fi + local parameters="$3" + if [[ "$parameters" =~ ^(.+) ]]; then + local pattern="${BASH_REMATCH[1]}" + # Simple flood limiting + if time_check_interval "$module_eix_last_query" "$config_module_eix_rate"; then + time_get_current 'module_eix_last_query' + log_info_file eix.log "$sender made the bot run eix on \"$pattern\"" + send_msg "$channel" "$(ulimit -t 4; EIX_PRINT_IUSE='false' eix -pSCxs --format "$module_eix_format_string" "$pattern" | head -n 1)" + else + log_error_file eix.log "FLOOD DETECTED in eix module" + fi + else + local sendernick + parse_hostmask_nick "$sender" 'sendernick' + feedback_bad_syntax "$sendernick" "eix" "<pattern>" + fi +} diff --git a/contrib/modules/m_eval.sh b/contrib/modules/m_eval.sh new file mode 100644 index 0000000..c3a03c4 --- /dev/null +++ b/contrib/modules/m_eval.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# -*- coding: utf-8 -*- +########################################################################### +# # +# envbot - an IRC bot in bash # +# Copyright (C) 2007-2008 Arvid Norlander # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see <http://www.gnu.org/licenses/>. # +# # +########################################################################### +#--------------------------------------------------------------------- +## Allow owners to make the bot eval any code<br /> +## THIS IS FOR DEBUGGING ONLY!!!! Don't use it in other cases +#--------------------------------------------------------------------- + +module_eval_INIT() { + modinit_API='2' + modinit_HOOKS='' + commands_register "$1" 'eval' || return 1 + helpentry_module_eval_description="Eval command for developers debugging the bot. Don't use if you don't know what you are doing." + + helpentry_eval_eval_syntax='<expression>' + helpentry_eval_eval_description='Evaluate <expression> in global scope.' +} + +module_eval_UNLOAD() { + return 0 +} + +module_eval_REHASH() { + return 0 +} + +module_eval_handler_eval() { + # Accept anywhere + local sender="$1" + if access_check_owner "$sender"; then + local parameters="$3" + access_log_action "$sender" "did eval with: $parameters" + eval "$parameters" + else + access_fail "$sender" "eval a command" "owner" + fi +} diff --git a/contrib/modules/m_helloworld.sh b/contrib/modules/m_helloworld.sh new file mode 100644 index 0000000..25b6a10 --- /dev/null +++ b/contrib/modules/m_helloworld.sh @@ -0,0 +1,193 @@ +#!/bin/bash +# -*- coding: utf-8 -*- +########################################################################### +# # +# envbot - an IRC bot in bash # +# Copyright (C) 2007-2008 Arvid Norlander # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see <http://www.gnu.org/licenses/>. # +# # +########################################################################### +#--------------------------------------------------------------------- +## Example module meant to help people who want to make modules for envbot +#--------------------------------------------------------------------- + +#--------------------------------------------------------------------- +## This is called to get a list of hooks that the module provides. +## Use the hook after_load to do other things +## @Type Module hook +## @Stdout A list of hooks. +#--------------------------------------------------------------------- +module_helloworld_INIT() { + modinit_API='2' + # Set modinit_HOOKS to the hooks we have. + modinit_HOOKS='after_load' + # Register commands, each command handler will have a name like: + # module_modulename_handler_function + # Example: module_helloworld_handler_hi + # If command name and function name are the same you can skip + # command name. + commands_register "$1" 'hi' || return 1 + # Here the function name and command name can't be the same, + # as the command name got space in it. Note that a command can + # be at most two words. + commands_register "$1" 'hello_world' 'hello world' || return 1 + helpentry_module_helloworld_description="This is an example module." + + helpentry_helloworld_hi_syntax='<target> <message>' + helpentry_helloworld_hi_description='Send a greeting to <target> (nick or channel) with the <message>.' + + helpentry_helloworld_helloworld_syntax='<message>' + helpentry_helloworld_helloworld_description='Send a greeting to the current scope with the one word <message>.' +} + +#--------------------------------------------------------------------- +## Here we do anything needed to unload the module. +## @Type Module hook +## @return 0 Unloaded correctly +## @return 1 Failed to unload. On this the bot will quit. +## @Note This function is NOT called when the bot is exiting. To check for that +## @Note use the FINALISE hook! +#--------------------------------------------------------------------- +module_helloworld_UNLOAD() { + # Here we unset any functions and variables that we have defined + # except the hook functions. + unset module_helloworld_variable module_helloworld_function +} + +#--------------------------------------------------------------------- +## Here do anything needed at rehash +## @Type Module hook +## @return 0 Rehashed correctly +## @return 1 Non fatal error for the bot itself. The bot will call UNLOAD on the module. +## @return 2 Fatal error of some kind. On this the bot will quit. +#--------------------------------------------------------------------- +module_helloworld_REHASH() { + # We don't have anything to do here. + return 0 +} + +#--------------------------------------------------------------------- +## Called after all the hooks are added for the module. +## @Type Module hook +## @return 0 Unloaded correctly +## @return 1 Failed. On this the bot will call unload on the module. +#--------------------------------------------------------------------- +module_helloworld_after_load() { + # Set a global variable, this can't be done in INIT. + # Remember to unset all global variables on UNLOAD! + module_helloworld_variable="world!" +} + +#--------------------------------------------------------------------- +## This logs "hello world" as an informative level log item +## when called +## @Type Private +## @Note Note that this is a custom function used by +## @Note some other part of the script +#--------------------------------------------------------------------- +module_helloworld_function() { + # Lets use the variable defined above! + log_info "Hello $module_helloworld_variable" +} + +#--------------------------------------------------------------------- +## Called on the command "hello world" +## @Type Function handler +## @param From who (n!u@h) +## @param To who (channel or botnick) +## @param The parameters to the command +#--------------------------------------------------------------------- +module_helloworld_handler_hello_world() { + local sender="$1" + local target + # If it isn't in a channel send message back to person who send it, + # otherwise send in channel + if [[ $2 =~ ^# ]]; then + target="$2" + else + # parse_hostmask_nick gets the nick from a hostmask. + parse_hostmask_nick "$sender" 'target' + fi + + local parameters="$3" + # Check if the syntax for the parameters is correct! + # Lets check for one parameter without spaces + if [[ "$parameters" =~ ^([^ ]+) ]]; then + # Store the bit in the first group of the regex into + # the variable message + local message="${BASH_REMATCH[1]}" + # Send a hello world message: + send_msg "$target" "Hello world! I had the parameter $message" + else + # So the regex for matching parameters didn't work, lets provide + # the user with some feedback! + local sendernick + parse_hostmask_nick "$sender" 'sendernick' + feedback_bad_syntax "$sendernick" "hello world" "<message> # Where message is one word!" + fi +} + +#--------------------------------------------------------------------- +## Called on the command "hi" +## @Type Function handler +## @param From who (n!u@h) +## @param To who (channel or botnick) +## @param The parameters to the command +#--------------------------------------------------------------------- +module_helloworld_handler_hi() { + local sender="$1" + + local parameters="$3" + # Two parameters, one is single word, the other matches to + # end of line. + if [[ "$parameters" =~ ^([^ ]+)\ (.+) ]]; then + # Store the groups in some variables. + local target_channel="${BASH_REMATCH[1]}" + local message="${BASH_REMATCH[2]}" + # This is used for the access check below. + # Check if target is a channel or nick. + local scope + if [[ $target_channel =~ ^# ]]; then + scope="$target_channel" + else + scope="MSG" + fi + + # Lets check for access. + # First variable is capability to check for + # Second variable is the hostmask of the sender of the message + # Third variable is the scope, that we set above. + if access_check_capab "hi" "$sender" "$scope"; then + # Such important events for security as a "hi" should + # really get logged even if it fails! ;) + access_log_action "$sender" "made the hi channel \"$message\" in/to \"$target_channel\"" + local sendernick + parse_hostmask_nick "$sender" 'sendernick' + send_msg "${target_channel}" "Hi $target_channel! $sendernick wants you to know ${message}" + # As an example also call our function. + module_helloworld_function + else + # Lets tell the sender they lack access! + # access_fail will send a PRIVMSG to the sender saying permission denied + # and also log the failed attempt. + access_fail "$sender" "make the bot hi" "hi" + fi + else + # As above, provide feedback about bad syntax. + local sendernick + parse_hostmask_nick "$sender" 'sendernick' + feedback_bad_syntax "$sendernick" "hi" "<target> <message> # Where target is a nick or channel" + fi +} diff --git a/contrib/modules/m_perl/__main__.sh b/contrib/modules/m_perl/__main__.sh new file mode 100644 index 0000000..36906a5 --- /dev/null +++ b/contrib/modules/m_perl/__main__.sh @@ -0,0 +1,74 @@ +#!/bin/bash +# -*- coding: utf-8 -*- +########################################################################### +# # +# envbot - an IRC bot in bash # +# Copyright (C) 2007-2008 EmErgE <halt.system@gmail.com> # +# Copyright (C) 2007-2008 Vsevolod Kozlov # +# Copyright (C) 2007-2008 Arvid Norlander # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see <http://www.gnu.org/licenses/>. # +# # +########################################################################### +#--------------------------------------------------------------------- +## Evaluate with perl +## @Dependencies This module depends on perl +## @Dependencies (http://www.perl.org/about.html) +## @Note This may not be safe! +#--------------------------------------------------------------------- + +module_perl_INIT() { + modinit_API='2' + modinit_HOOKS='' + if ! hash perl > /dev/null 2>&1; then + log_error "Couldn't find \"perl\" binary. The perl module depends on it." + return 1 + fi + module_perl_working_dir="$MODULE_BASE_PATH" + commands_register "$1" 'perl' || return 1 + helpentry_module_perl_description="Execute perl code." + + helpentry_perl_perl_syntax='<code>' + helpentry_perl_perl_description='Execute perl code.' +} + +module_perl_UNLOAD() { + unset module_perl_working_dir + unset module_perl_handler_perl + return 0 +} + +module_perl_REHASH() { + return 0 +} + +module_perl_handler_perl() { + local sender="$1" + local channel="$2" + local sendernick= + parse_hostmask_nick "$sender" 'sendernick' + if access_check_capab "perl_eval" "$sender" "$channel"; then + # If it isn't in a channel send message back to person who send it, + # otherwise send in channel + if ! [[ $2 =~ ^# ]]; then + channel="$sendernick" + fi + local parameters="$3" + # Extremely Safe Perl Evaluation + local myresult="$(perl "${module_perl_working_dir}/safe_eval.pl" "$parameters")" + send_msg "$channel" "${sendernick}: $myresult" + else + access_fail "$sender" "make the bot evalute perl expressions" "perl_eval" + fi +} diff --git a/contrib/modules/m_perl/safe_eval.pl b/contrib/modules/m_perl/safe_eval.pl new file mode 100644 index 0000000..1e6489f --- /dev/null +++ b/contrib/modules/m_perl/safe_eval.pl @@ -0,0 +1,25 @@ +#!/usr/bin/perl +use strict; +use Safe; + +my $expr = shift; + +my $cpt = new Safe; + +#Basic variable IO and traversal + +$cpt->permit(':base_core'); + +$SIG{ALRM} = sub { + die "Alarm"; +}; + +alarm(4); + +my $ret = $cpt->reval($expr); + +if ($@) { + print $@; +} else { + print $ret; +} |