Add initial files from envbot v0.1-beta1

This commit is contained in:
Márcio Silva
2017-06-02 15:44:54 -03:00
commit b4830e97ae
81 changed files with 12852 additions and 0 deletions

228
modules/m_assign_mode.sh Normal file
View File

@@ -0,0 +1,228 @@
#!/bin/bash
# -*- coding: utf-8 -*-
###########################################################################
# #
# envbot - an IRC bot in bash #
# Copyright (C) 2007-2008 Arvid Norlander #
# Copyright (C) 2007-2008 EmErgE <halt.system@gmail.com> #
# #
# 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/>. #
# #
###########################################################################
#---------------------------------------------------------------------
## Channel modes
#---------------------------------------------------------------------
module_assign_mode_INIT() {
modinit_API='2'
modinit_HOOKS=''
commands_register "$1" 'op' || return 1
commands_register "$1" 'deop' || return 1
commands_register "$1" 'halfop' || return 1
commands_register "$1" 'dehalfop' || return 1
commands_register "$1" 'voice' || return 1
commands_register "$1" 'devoice' || return 1
commands_register "$1" 'protect' || return 1
commands_register "$1" 'deprotect' || return 1
commands_register "$1" 'topic' || return 1
helpentry_module_assign_mode_description="Provides op, deop and related commands."
local help_cmd
for help_cmd in op deop halfop halfdeop voice devoice protect deprotect; do
printf -v "helpentry_assign_mode_${help_cmd}_syntax" '<#channel> <nick>'
printf -v "helpentry_assign_mode_${help_cmd}_description" "$(tr 'a-z' 'A-Z' <<< "${help_cmd:0:1}")${help_cmd:1} <nick> in <#channel>."
done
helpentry_assign_mode_topic_syntax='<#channel> <new topic>'
helpentry_assign_mode_topic_description='Change topic to <new topic> in <#channel>'
}
module_assign_mode_UNLOAD() {
return 0
}
module_assign_mode_REHASH() {
return 0
}
module_assign_mode_handler_op() {
local sender="$1"
local sendon_channel="$2"
local parameters="$3"
if [[ "$parameters" =~ ^(#[^ ]+)\ ([^ ]+) ]]; then
local channel="${BASH_REMATCH[1]}"
local nick="${BASH_REMATCH[2]}"
if access_check_capab "op" "$sender" "$channel"; then
send_modes "$channel" "+o $nick"
else
access_fail "$sender" "make the bot op somebody" "op"
fi
else
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
feedback_bad_syntax "$sendernick" "op" "<#channel> <nick>"
fi
}
module_assign_mode_handler_deop() {
local sender="$1"
local sendon_channel="$2"
local parameters="$3"
if [[ "$parameters" =~ ^(#[^ ]+)\ ([^ ]+) ]]; then
local channel="${BASH_REMATCH[1]}"
local nick="${BASH_REMATCH[2]}"
if access_check_capab "op" "$sender" "$channel"; then
send_modes "$channel" "-o $nick"
else
access_fail "$sender" "make the bot deop somebody" "op"
fi
else
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
feedback_bad_syntax "$sendernick" "deop" "<#channel> <nick>"
fi
}
module_assign_mode_handler_halfop() {
local sender="$1"
local sendon_channel="$2"
local parameters="$3"
if [[ "$parameters" =~ ^(#[^ ]+)\ ([^ ]+) ]]; then
local channel="${BASH_REMATCH[1]}"
local nick="${BASH_REMATCH[2]}"
if access_check_capab "halfop" "$sender" "$channel"; then
send_modes "$channel" "+h $nick"
else
access_fail "$sender" "make the bot halfop somebody" "halfop"
fi
else
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
feedback_bad_syntax "$sendernick" "halfop" "<#channel> <nick>"
fi
}
module_assign_mode_handler_dehalfop() {
local sender="$1"
local sendon_channel="$2"
local parameters="$3"
if [[ "$parameters" =~ ^(#[^ ]+)\ ([^ ]+) ]]; then
local channel="${BASH_REMATCH[1]}"
local nick="${BASH_REMATCH[2]}"
if access_check_capab "halfop" "$sender" "$channel"; then
send_modes "$channel" "-h $nick"
else
access_fail "$sender" "make the bot dehalfop somebody" "halfop"
fi
else
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
feedback_bad_syntax "$sendernick" "dehalfop" "<#channel> <nick>"
fi
}
module_assign_mode_handler_voice() {
local sender="$1"
local sendon_channel="$2"
local parameters="$3"
if [[ "$parameters" =~ ^(#[^ ]+)\ ([^ ]+) ]]; then
local channel="${BASH_REMATCH[1]}"
local nick="${BASH_REMATCH[2]}"
if access_check_capab "voice" "$sender" "$channel"; then
send_modes "$channel" "+v $nick"
else
access_fail "$sender" "make the bot give voice to somebody" "voice"
fi
else
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
feedback_bad_syntax "$sendernick" "voice" "<#channel> <nick>"
fi
}
module_assign_mode_handler_devoice() {
local sender="$1"
local sendon_channel="$2"
local parameters="$3"
if [[ "$parameters" =~ ^(#[^ ]+)\ ([^ ]+) ]]; then
local channel="${BASH_REMATCH[1]}"
local nick="${BASH_REMATCH[2]}"
if access_check_capab "voice" "$sender" "$channel"; then
send_modes "$channel" "-v $nick"
else
access_fail "$sender" "make the bot take voice from somebody" "voice"
fi
else
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
feedback_bad_syntax "$sendernick" "devoice" "<#channel> <nick>"
fi
}
module_assign_mode_handler_protect() {
local sender="$1"
local sendon_channel="$2"
local parameters="$3"
if [[ "$parameters" =~ ^(#[^ ]+)\ ([^ ]+) ]]; then
local channel="${BASH_REMATCH[1]}"
local nick="${BASH_REMATCH[2]}"
if access_check_capab "protect" "$sender" "$channel"; then
send_modes "$channel" "+a $nick"
else
access_fail "$sender" "make the bot protect somebody" "protect"
fi
else
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
feedback_bad_syntax "$sendernick" "protect" "<#channel> <nick>"
fi
}
module_assign_mode_handler_deprotect() {
local sender="$1"
local sendon_channel="$2"
local parameters="$3"
if [[ "$parameters" =~ ^(#[^ ]+)\ ([^ ]+) ]]; then
local channel="${BASH_REMATCH[1]}"
local nick="${BASH_REMATCH[2]}"
if access_check_capab "protect" "$sender" "$channel"; then
send_modes "$channel" "-a $nick"
else
access_fail "$sender" "make the bot deprotect somebody" "protect"
fi
else
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
feedback_bad_syntax "$sendernick" "deprotect" "<#channel> <nick>"
fi
}
module_assign_mode_handler_topic() {
local sender="$1"
local sendon_channel="$2"
local parameters="$3"
if [[ "$parameters" =~ ^(#[^ ]+)\ (.+) ]]; then
local channel="${BASH_REMATCH[1]}"
local message="${BASH_REMATCH[2]}"
if access_check_capab "topic" "$sender" "$channel"; then
send_topic "$channel" "$message"
else
access_fail "$sender" "change the topic" "topic"
fi
else
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
feedback_bad_syntax "$sendernick" "topic" "<#channel> <new topic>"
fi
}

63
modules/m_autojoin.sh Normal file
View File

@@ -0,0 +1,63 @@
#!/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/>. #
# #
###########################################################################
#---------------------------------------------------------------------
## This module does autojoin after connect.
#---------------------------------------------------------------------
module_autojoin_INIT() {
modinit_API='2'
modinit_HOOKS='after_connect'
helpentry_module_autojoin_description="Provides support for autojoining channels."
}
module_autojoin_UNLOAD() {
unset module_autojoin_join_from_config
}
module_autojoin_REHASH() {
module_autojoin_join_from_config
return 0
}
#---------------------------------------------------------------------
## Autojoin channels from config.
## @Type Private
#---------------------------------------------------------------------
module_autojoin_join_from_config() {
local channel
for channel in "${config_module_autojoin_channels[@]}"; do
# No quotes around channel because second word of it may be a key
# and list_contains just uses the first 2 arguments so a
# third one will be ignored.
if ! list_contains "channels_current" $channel; then
log_info "Joining $channel"
# No quotes here because then second argument can be a key
channels_join $channel
sleep 2
fi
done
}
# Called after bot has connected
module_autojoin_after_connect() {
module_autojoin_join_from_config
}

View File

@@ -0,0 +1,45 @@
#!/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/>. #
# #
###########################################################################
#---------------------------------------------------------------------
## For debugging, report any unknown numerics.
#---------------------------------------------------------------------
module_check_numerics_INIT() {
modinit_API='2'
modinit_HOOKS='on_numeric'
helpentry_module_check_numerics_description="Debugging module to check if any numeric we get is unknown."
}
module_check_numerics_UNLOAD() {
return 0
}
module_check_numerics_REHASH() {
return 0
}
module_check_numerics_on_numeric() {
# Make sure it is in base 10 here.
if [[ -z "${numerics[10#${1}]}" ]]; then
log_warning_file unknown_data.log "Unknown numeric $1 Data: $2"
fi
}

103
modules/m_commands.sh Normal file
View File

@@ -0,0 +1,103 @@
#!/bin/bash
# -*- coding: utf-8 -*-
###########################################################################
# #
# envbot - an IRC bot in bash #
# Copyright (C) 2007-2008 Arvid Norlander #
# Copyright (C) 2007-2008 Vsevolod Kozlov #
# #
# 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/>. #
# #
###########################################################################
#---------------------------------------------------------------------
## Command-related utility commands
#---------------------------------------------------------------------
module_commands_INIT() {
modinit_API='2'
modinit_HOOKS=''
commands_register "$1" 'provides' || return 1
commands_register "$1" 'commands' || return 1
helpentry_module_commands_description="Provides a set of command-related commands."
helpentry_commands_provides_syntax='<command>'
helpentry_commands_provides_description='Shows which module provides command <command>'
helpentry_commands_commands_syntax='[<module>]'
helpentry_commands_commands_description='Lists commands available in <module>. If module name is not given, lists all commands'
}
module_commands_UNLOAD() {
return 0
}
module_commands_REHASH() {
return 0
}
module_commands_handler_provides() {
local sender="$1"
local parameters="$3"
if [[ $parameters =~ ^([a-zA-Z0-9][^ ]*)( [^ ]+)? ]]; then # regex suggested by AnMaster
local command_name="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
local target
if [[ $2 =~ ^# ]]; then
target="$2"
else
parse_hostmask_nick "$sender" 'target'
fi
local module_name
commands_provides "$command_name" module_name
if [[ -z $module_name ]]; then # No such command
send_msg "$target" "Command \"$command_name\" does not exist."
else
send_msg "$target" "Command \"$command_name\" is provided by module \"$module_name\""
fi
else
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
feedback_bad_syntax "$sendernick" "provides" "<modulename>"
fi
}
module_commands_handler_commands() {
local parameters="$3"
local target
if [[ $2 =~ ^# ]]; then
target="$2"
else
parse_hostmask_nick "$1" 'target'
fi
if [[ -z $parameters ]]; then
send_msg "$target" "${format_bold}Available commands${format_bold}: ${commands_commands//,/, }"
else
# So we got a parameter
local module_name
if [[ $parameters =~ ^([^ ]+)\ *$ ]]; then
module_name="${BASH_REMATCH[1]}"
else
send_notice "$target" "\"$parameters\" is not a valid module name"
return 1
fi
local commands_in_module
commands_in_module "$module_name" 'commands_in_module'
if [[ $commands_in_module ]]; then
send_msg "$target" "${format_bold}Available commands (in module \"$module_name\")${format_bold}: ${commands_in_module//,/, }"
elif list_contains "modules_loaded" "$module_name"; then
send_notice "$target" "Module \"$module_name\" provides no commands"
else
send_notice "$target" "Module \"$module_name\" is not loaded"
fi
fi
}

91
modules/m_ctcp.sh Normal file
View File

@@ -0,0 +1,91 @@
#!/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/>. #
# #
###########################################################################
#---------------------------------------------------------------------
## Handle CTCP
#---------------------------------------------------------------------
module_ctcp_INIT() {
modinit_API='2'
modinit_HOOKS='after_load on_PRIVMSG'
helpentry_module_ctcp_description="Answers CTCP requests."
}
module_ctcp_UNLOAD() {
return 0
}
module_ctcp_REHASH() {
return 0
}
module_ctcp_after_load() {
if [[ -z $config_module_ctcp_version_reply ]]; then
log_error "VERSION reply (config_module_ctcp_version_reply) must be set in config to use CTCP module."
return 1
fi
}
# Called on a PRIVMSG
#
# $1 = from who (n!u@h)
# $2 = to who (channel or botnick)
# $3 = the message
module_ctcp_on_PRIVMSG() {
local sender="$1"
local query="$3"
# We can't use regex here. For some unknown reason bash drops \001 from
# regex.
if [[ $query = $'\001'* ]]; then
# Get rid of \001 in the string.
local data="${query//$'\001'}"
local ctcp_command ctcp_parameters
# Split it up into command and any parameters.
read -r ctcp_command ctcp_parameters <<< "$data"
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
case "$ctcp_command" in
"CLIENTINFO")
send_nctcp "$sendernick" "CLIENTINFO CLIENTINFO PING SOURCE TIME VERSION"
;;
"PING")
send_nctcp "$sendernick" "PING $ctcp_parameters"
;;
"SOURCE")
send_nctcp "$sendernick" "SOURCE http://envbot.org"
;;
"TIME")
send_nctcp "$sendernick" "TIME $(date +'%Y-%m-%d %k:%M:%S')"
;;
"VERSION")
send_nctcp "$sendernick" "VERSION $config_module_ctcp_version_reply"
;;
*)
# So we didn't handle this CTCP? Return 0 then, someone else may want it.
return 0
;;
esac
# See above. We didn't fall back to not handle it and did not return
# so therefore we must have handled it.
return 1
fi
return 0
}

84
modules/m_dice.sh Normal file
View File

@@ -0,0 +1,84 @@
#!/bin/bash
# -*- coding: utf-8 -*-
###########################################################################
# #
# envbot - an IRC bot in bash #
# Copyright (C) 2007-2008 Arvid Norlander #
# Copyright (C) 2007-2008 Vsevolod Kozlov #
# #
# 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/>. #
# #
###########################################################################
#---------------------------------------------------------------------
## Rolls dies.
#---------------------------------------------------------------------
module_dice_INIT() {
modinit_API='2'
modinit_HOOKS=''
commands_register "$1" 'roll' || return 1
helpentry_module_dice_description="Rolls dies for you."
helpentry_dice_roll_syntax="<dies>d<sides>"
helpentry_dice_roll_description="Rolls <dies> dies, each <sides> sides."
}
module_dice_UNLOAD() {
return 0
}
module_dice_REHASH() {
return 0
}
module_dice_handler_roll() {
local sender="$1"
local parameters="$3"
if [[ $parameters =~ ^([0-9]+)d([0-9]+)$ ]]; then
local how_much_times="${BASH_REMATCH[1]}"
local how_many_sides="${BASH_REMATCH[2]}"
local target=
if [[ $2 =~ ^# ]]; then
target="$2"
else
parse_hostmask_nick "$sender" 'target'
fi
local insane=0
# Chech if number of dies and sides are sane.
if (( ($how_many_sides < 2 || $how_many_sides > 100)
|| ($how_much_times < 1 || $how_much_times > 100) )); then
log_warning "Tried to roll $how_much_times dies $how_many_sides sides each!"
log_warning "This is above the allowed maximum or below the allowed minimum, and was aborted."
send_msg "$target" "You can't roll that."
return 0
fi
# Roll $how_much_times dies, each with $how_many_sides sides.
local result=""
local total=0
for (( i=0; $i < $how_much_times; i+=1 )); do
local rolled=$(( ($RANDOM % $how_many_sides) + 1 ))
result+="$rolled, "
((total += $rolled))
done
result=${result%, }
if [[ $how_much_times != 1 ]]; then
result+=" with the grand total of $total"
fi
send_msg "$target" "You rolled ${result}."
else
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
feedback_bad_syntax "$sendernick" "roll" "<dies>d<sides>"
fi
}

75
modules/m_die.sh Normal file
View File

@@ -0,0 +1,75 @@
#!/bin/bash
# -*- coding: utf-8 -*-
###########################################################################
# #
# envbot - an IRC bot in bash #
# Copyright (C) 2007-2008 Arvid Norlander #
# Copyright (C) 2007-2008 EmErgE <halt.system@gmail.com> #
# #
# 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/>. #
# #
###########################################################################
#---------------------------------------------------------------------
## Quit the bot.
#---------------------------------------------------------------------
module_die_INIT() {
modinit_API='2'
modinit_HOOKS=''
commands_register "$1" 'die' || return 1
commands_register "$1" 'restart' || return 1
helpentry_module_die_description="Commands to shut down and restart bot."
helpentry_die_die_syntax='[reason]'
helpentry_die_die_description='Quit with an optional quit reason.'
helpentry_die_restart_syntax='[reason]'
helpentry_die_restart_description='Disconnect the bot with an optional quit reason, then rerun itself.'
}
module_die_UNLOAD() {
return 0
}
module_die_REHASH() {
return 0
}
module_die_handler_die() {
local sender="$1"
if access_check_owner "$sender"; then
local parameters="$3"
access_log_action "$sender" "made the bot die with reason: $parameters"
local reason=
if [[ $parameters ]]; then
reason=": $parameters"
fi
bot_quit "Dying ($sender)$reason"
else
access_fail "$sender" "make the bot die" "owner"
fi
}
module_die_handler_restart() {
local sender="$1"
if access_check_owner "$sender"; then
local parameters="$3"
access_log_action "$sender" "made the bot restart with reason: $parameters"
local reason=
if [[ $parameters ]]; then
reason=": $parameters"
fi
bot_restart "Restarting ($sender)$reason"
else
access_fail "$sender" "make the bot restart" "owner"
fi
}

54
modules/m_dumpvars.sh Normal file
View File

@@ -0,0 +1,54 @@
#!/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/>. #
# #
###########################################################################
#---------------------------------------------------------------------
## Debug module, dump all variables to console.
#---------------------------------------------------------------------
module_dumpvars_INIT() {
modinit_API='2'
modinit_HOOKS=''
commands_register "$1" 'dumpvars' || return 1
helpentry_module_dumpvars_description="Debugging module to dump all variables in the bot."
helpentry_dumpvars_dumpvars_syntax=''
helpentry_dumpvars_dumpvars_description='Dump all variables to STDOUT.'
}
module_dumpvars_UNLOAD() {
return 0
}
module_dumpvars_REHASH() {
return 0
}
module_dumpvars_handler_dumpvars() {
local sender="$1"
if access_check_owner "$sender"; then
# This is hackish, we only display
# lines unique to "file" 1.
# Also remove one variable that may fill our scrollback.
access_log_action "$sender" "a dump of variables"
comm -2 -3 <(declare) <(declare -f) | grep -Ev '^module_quote_quotes'
else
access_fail "$sender" "dump variables to STDOUT" "owner"
fi
}

461
modules/m_factoids.sh Normal file
View File

@@ -0,0 +1,461 @@
#!/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/>. #
# #
###########################################################################
#---------------------------------------------------------------------
## Simple factoids module using SQLite3
#---------------------------------------------------------------------
module_factoids_INIT() {
modinit_API='2'
modinit_HOOKS='after_load on_PRIVMSG'
commands_register "$1" 'learn' || return 1
commands_register "$1" 'forget' || return 1
commands_register "$1" 'lock_factoid' 'lock factoid' || return 1
commands_register "$1" 'unlock_factoid' 'unlock factoid' || return 1
commands_register "$1" 'whatis' || return 1
commands_register "$1" 'factoid_stats' 'factoid stats' || return 1
helpentry_module_factoids_description="Provides a factoid database."
helpentry_factoids_learn_syntax='<key> (as|is|are|=) <value>'
helpentry_factoids_learn_description='Teach the bot a new factoid.'
helpentry_factoids_forget_syntax='<key>'
helpentry_factoids_forget_description='Make the bot forget the factoid <key>.'
helpentry_factoids_lock_factoid_syntax='<key>'
helpentry_factoids_lock_factoid_description='Prevent normal users from changing the factoid <key>.'
helpentry_factoids_unlock_factoid_syntax='<key>'
helpentry_factoids_unlock_factoid_description='Allow changes to a previously locked factoid <key>.'
helpentry_factoids_whatis_syntax='<key>'
helpentry_factoids_whatis_description='Look up the factoid <key>.'
helpentry_factoids_factoid_stats_syntax=''
helpentry_factoids_factoid_stats_description='Report some statistics on the factoid database.'
}
module_factoids_UNLOAD() {
# Ok this is a LOT. I hope I got all...
unset module_factoids_set module_factoids_remove module_factoids_parse_assignment
unset module_factoids_parse_key module_factoids_parse_value
unset module_factoids_set_INSERT_or_UPDATE module_factoids_send_factoid
unset module_factoids_get_count module_factoids_get_locked_count
unset module_factoids_is_locked module_factoids_lock module_factoids_unlock
unset module_factoids_SELECT module_factoids_INSERT module_factoids_UPDATE module_factoids_DELETE
}
module_factoids_REHASH() {
return 0
}
# Called after module has loaded.
module_factoids_after_load() {
modules_depends_register "factoids" "sqlite3" || {
# This error reporting is hackish, will fix later.
if ! list_contains "modules_loaded" "sqlite3"; then
log_error "The factoids module depends upon the SQLite3 module being loaded."
fi
return 1
}
if [[ -z $config_module_factoids_table ]]; then
log_error "Factiods table (config_module_factoids_table) must be set in config if you want to use factoids module."
return 1
fi
if ! module_sqlite3_table_exists "$config_module_factoids_table"; then
log_error "factoids module: $config_module_factoids_table does not exist in the database file."
log_error "factoids module: See comment in doc/factoids.sql for how to create the table."
fi
}
#---------------------------------------------------------------------
## Get an item from DB
## @Type Private
## @param Key
## @Stdout The result of the database query.
#---------------------------------------------------------------------
module_factoids_SELECT() {
#$ sqlite3 -list data/factoids.sqlite "SELECT value from factoids WHERE name='factoids';"
#A system that stores useful bits of information
module_sqlite3_exec_sql "SELECT value FROM $config_module_factoids_table WHERE name='$(module_sqlite3_clean_string "$1")';"
}
#---------------------------------------------------------------------
## Insert a new item into DB
## @Type Private
## @param key
## @param value
## @param hostmask of person who added it
#---------------------------------------------------------------------
module_factoids_INSERT() {
module_sqlite3_exec_sql \
"INSERT INTO $config_module_factoids_table (name, value, who) VALUES('$(module_sqlite3_clean_string "$1")', '$(module_sqlite3_clean_string "$2")', '$(module_sqlite3_clean_string "$3")');"
}
#---------------------------------------------------------------------
## Change the item in DB
## @Type Private
## @param key
## @param new value
## @param hostmask of person who changed it
#---------------------------------------------------------------------
module_factoids_UPDATE() {
module_sqlite3_exec_sql \
"UPDATE $config_module_factoids_table SET value='$(module_sqlite3_clean_string "$2")', who='$(module_sqlite3_clean_string "$3")' WHERE name='$(module_sqlite3_clean_string "$1")';"
}
#---------------------------------------------------------------------
## Remove an item
## @Type Private
## @param key
#---------------------------------------------------------------------
module_factoids_DELETE() {
module_sqlite3_exec_sql "DELETE FROM $config_module_factoids_table WHERE name='$(module_sqlite3_clean_string "$1")';"
}
#---------------------------------------------------------------------
## How many factoids are there
## @Type Private
## @Stdout Count of factoids.
#---------------------------------------------------------------------
module_factoids_get_count() {
module_sqlite3_exec_sql "SELECT COUNT(name) FROM $config_module_factoids_table;"
}
#---------------------------------------------------------------------
## How many locked factoids are there
## @Type Private
## @Stdout Count of locked factoids.
#---------------------------------------------------------------------
module_factoids_get_locked_count() {
module_sqlite3_exec_sql "SELECT COUNT(name) FROM $config_module_factoids_table WHERE is_locked='1';"
}
#---------------------------------------------------------------------
## Check if factoid is locked or not.
## @Type Private
## @param key
## @return 0 locked
## @return 1 not locked
#---------------------------------------------------------------------
module_factoids_is_locked() {
local lock="$(module_sqlite3_exec_sql "SELECT is_locked FROM $config_module_factoids_table WHERE name='$(module_sqlite3_clean_string "$1")';")"
if [[ $lock == "1" ]]; then
return 0
else
return 1
fi
}
#---------------------------------------------------------------------
## Lock a factoid against changes from non-owners
## @Type Private
## @param key
#---------------------------------------------------------------------
module_factoids_lock() {
module_sqlite3_exec_sql "UPDATE $config_module_factoids_table SET is_locked='1' WHERE name='$(module_sqlite3_clean_string "$1")';"
}
#---------------------------------------------------------------------
## Unlock a factoid from protection against non-owners
## @Type Private
## @param key
#---------------------------------------------------------------------
module_factoids_unlock() {
module_sqlite3_exec_sql "UPDATE $config_module_factoids_table SET is_locked='0' WHERE name='$(module_sqlite3_clean_string "$1")';"
}
#---------------------------------------------------------------------
## Wrapper, call either INSERT or UPDATE
## @Type Private
## @param key
## @param value
## @param hostmask of person set it
#---------------------------------------------------------------------
module_factoids_set_INSERT_or_UPDATE() {
if [[ $(module_factoids_SELECT "$1") ]]; then
module_factoids_UPDATE "$1" "$2" "$3"
else
module_factoids_INSERT "$1" "$2" "$3"
fi
}
#---------------------------------------------------------------------
## Wrapper, call either INSERT or UPDATE
## @Type Private
## @param key
## @param value
## @param sender
## @param channel
#---------------------------------------------------------------------
module_factoids_set() {
local key="$1"
local value="$2"
local sender="$3"
local channel="$4"
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
if module_factoids_is_locked "$key"; then
if access_check_capab "factoid_admin" "$sender" "GLOBAL"; then
module_factoids_set_INSERT_or_UPDATE "$key" "$value" "$sender"
send_msg "$channel" "Ok ${sendernick}, I will remember, $key is $value"
else
access_fail "$sender" "change a locked factoid" "factoid_admin"
fi
else
module_factoids_set_INSERT_or_UPDATE "$key" "$value" "$sender"
send_msg "$channel" "Ok ${sendernick}, I will remember, $key is $value"
fi
}
#---------------------------------------------------------------------
## Wrapper, check access
## @Type Private
## @param key
## @param sender
## @param channel
#---------------------------------------------------------------------
module_factoids_remove() {
local key="$1"
local sender="$2"
local channel="$3"
local value="$(module_factoids_SELECT "$(tr '[:upper:]' '[:lower:]' <<< "$key")")"
if [[ "$value" ]]; then
if module_factoids_is_locked "$key"; then
if access_check_capab "factoid_admin" "$sender" "GLOBAL"; then
module_factoids_DELETE "$key"
send_msg "$channel" "I forgot $key"
else
access_fail "$sender" "remove a locked factoid" "factoid_admin"
fi
else
module_factoids_DELETE "$key"
send_msg "$channel" "I forgot $key"
fi
else
send_msg "$channel" "I didn't have a factoid matching \"$key\""
fi
}
#---------------------------------------------------------------------
## Send the factoid:
## @Type Private
## @param To where (channel or nick)
## @param What factoid.
#---------------------------------------------------------------------
module_factoids_send_factoid() {
local channel="$1"
local key="$2"
local value="$(module_factoids_SELECT "$(tr '[:upper:]' '[:lower:]' <<< "$key")")"
if [[ "$value" ]]; then
if [[ $value =~ ^\<REPLY\>\ *(.*) ]]; then
send_msg "$channel" "${BASH_REMATCH[1]}"
elif [[ $value =~ ^\<ACTION\>\ *(.*) ]]; then
send_ctcp "$channel" "ACTION ${BASH_REMATCH[1]}"
else
send_msg "$channel" "$key is $value"
fi
else
send_msg "$channel" "I don't know what \"$key\" is."
fi
}
#---------------------------------------------------------------------
## Parse assignment:
## @Type Private
## @param String to parse
## @Note Will return using Global variables
## @Globals $module_factoids_parse_key $module_factoids_parse_value
#---------------------------------------------------------------------
module_factoids_parse_assignment() {
local word key value
# Have we hit a separator yet?
local state=0
while read -rd ' ' word; do
case "$state" in
0)
# If state is 1 the rest is value
if [[ "$word" =~ ^(as|is|are|=)$ ]]; then
state=1
else
key+=" $word"
fi
;;
1)
value+=" $word"
;;
esac
# Extra space at end is intended, to make read work correctly.
done <<< "$1 "
# And clean spaces, fastest way
read -ra module_factoids_parse_key <<< "$key"
read -ra module_factoids_parse_value <<< "$value"
}
module_factoids_handler_learn() {
local sender="$1"
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
local channel="$2"
if ! [[ $2 =~ ^# ]]; then
channel="$sendernick"
fi
local parameters="$3"
if [[ "$parameters" =~ ^(.+)\ (as|is|are|=)\ (.+) ]]; then
# Do the actual parsing elsewhere:
module_factoids_parse_assignment "$parameters"
local key="${module_factoids_parse_key[*]}"
local value="${module_factoids_parse_value[*]}"
unset module_factoids_parse_key module_factoids_parse_value
module_factoids_set "$(tr '[:upper:]' '[:lower:]' <<< "$key")" "$value" "$sender" "$channel"
else
feedback_bad_syntax "$sendernick" "learn" "<key> (as|is|are|=) <value>"
fi
return 1
}
module_factoids_handler_forget() {
local sender="$1"
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
local channel="$2"
if ! [[ $2 =~ ^# ]]; then
channel="$sendernick"
fi
local parameters="$3"
if [[ "$parameters" =~ ^(.+) ]]; then
local key="${BASH_REMATCH[1]}"
module_factoids_remove "$(tr '[:upper:]' '[:lower:]' <<< "$key")" "$sender" "$channel"
else
feedback_bad_syntax "$sendernick" "forget" "<key>"
fi
}
module_factoids_handler_lock_factoid() {
local sender="$1"
if access_check_capab "factoid_admin" "$sender" "GLOBAL"; then
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
local channel="$2"
if ! [[ $2 =~ ^# ]]; then
channel="$sendernick"
fi
local parameters="$3"
if [[ "$parameters" =~ ^(.+) ]]; then
local key="${BASH_REMATCH[1]}"
module_factoids_lock "$(tr '[:upper:]' '[:lower:]' <<< "$key")"
send_msg "$channel" "Ok ${sendernick}, the factoid \"$key\" is now protected from changes"
else
feedback_bad_syntax "$sendernick" "lock" "<key>"
fi
else
access_fail "$sender" "lock a factoid" "factoid_admin"
fi
}
module_factoids_handler_unlock_factoid() {
local sender="$1"
if access_check_capab "factoid_admin" "$sender" "GLOBAL"; then
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
local channel="$2"
if ! [[ $2 =~ ^# ]]; then
channel="$sendernick"
fi
local parameters="$3"
if [[ "$parameters" =~ ^(.+) ]]; then
local key="${BASH_REMATCH[1]}"
module_factoids_unlock "$(tr '[:upper:]' '[:lower:]' <<< "$key")"
send_msg "$channel" "Ok ${sendernick}, the factoid \"$key\" is no longer protected from changes"
else
feedback_bad_syntax "$sendernick" "lock" "<key>"
fi
else
access_fail "$sender" "lock a factoid" "factoid_admin"
fi
}
module_factoids_handler_whatis() {
local sender="$1"
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
local channel="$2"
if ! [[ $2 =~ ^# ]]; then
channel="$sendernick"
fi
local parameters="$3"
if [[ "$parameters" =~ ^(.+) ]]; then
local key="${BASH_REMATCH[1]}"
module_factoids_send_factoid "$channel" "$key"
else
feedback_bad_syntax "$sendernick" "whatis" "<key>"
fi
}
module_factoids_handler_factoid_stats() {
local sender="$1"
local channel="$2"
if ! [[ $2 =~ ^# ]]; then
parse_hostmask_nick "$sender" 'channel'
fi
local count="$(module_factoids_get_count)"
local lockedcount="$(module_factoids_get_locked_count)"
if [[ "$count" ]]; then
send_msg "$channel" "There are $count items in my factoid database. $lockedcount of the factoids are locked."
fi
}
module_factoids_on_PRIVMSG() {
local sender="$1"
local channel="$2"
if ! [[ $2 =~ ^# ]]; then
parse_hostmask_nick "$sender" 'channel'
fi
local query="$3"
# Answer question in channel if we got a factoid.
if [[ "$query" =~ ^((what|where|who|why|how)\ )?((is|are|were|was|to|can I find)\ )?([^\?]+)\?? ]]; then
local key="${BASH_REMATCH[@]: -1}"
local value="$(module_factoids_SELECT "$(tr '[:upper:]' '[:lower:]' <<< "$key")")"
if [[ "$value" ]]; then
module_factoids_send_factoid "$channel" "$key"
return 1
fi
fi
return 0
}

138
modules/m_faq.sh Normal file
View File

@@ -0,0 +1,138 @@
#!/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/>. #
# #
###########################################################################
#---------------------------------------------------------------------
## Simple FAQ module
#---------------------------------------------------------------------
module_faq_INIT() {
modinit_API='2'
modinit_HOOKS='after_load'
commands_register "$1" 'faq' || return 1
helpentry_module_faq_description="FAQ from a file."
helpentry_faq_faq_syntax='[number|string]'
helpentry_faq_faq_description='Show the <number>th faq item or search for a <string> in all the faq items.'
}
module_faq_UNLOAD() {
unset module_faq_array module_faq_last_query_item
unset module_faq_load module_faq_last_query_time
}
module_faq_REHASH() {
module_faq_load
}
#---------------------------------------------------------------------
## Load or reload FAQ items
## @Type Private
#---------------------------------------------------------------------
module_faq_load() {
local i=0
unset module_faq_array
if [[ -z "$config_module_faq_file" ]]; then
log_error "faq module: You need to set config_module_faq_file in your config!"
return 1
elif [[ -r "$config_module_faq_file" ]]; then
while read -d $'\n' line ;do
# Skip empty lines
if [[ "$line" ]]; then
(( i++ ))
module_faq_array[$i]="$line"
fi
done < "${config_module_faq_file}"
log_info 'Loaded FAQ items'
return 0
else
log_error "faq module: Cannot load '${config_module_faq_file}'. File doesn't exist or can't be read."
return 1
fi
}
# Called after module has loaded.
module_faq_after_load() {
module_faq_last_query_item='null'
module_faq_last_query_time='null'
module_faq_load
}
# Called on a PRIVMSG
#
# $1 = from who (n!u@h)
# $2 = to who (channel or botnick)
# $3 = the message
module_faq_handler_faq() {
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 query="$3"
if [[ "$query" ]]; then
if [[ "$query" == "reload" ]]; then
if access_check_capab "faq_admin" "$sender" "GLOBAL"; then
send_msg "$channel" "Reloading FAQ items..."
module_faq_load
send_msg "$channel" "Done."
else
access_fail "$sender" "reload faq items" "faq_admin"
fi
return 0
fi
# Is it a flood? Then 1.
local ok=0
if [[ "$module_faq_last_query_item" == "$line" ]]; then
time_check_interval "$module_faq_last_query_time" 60 || ok=1
fi
if [[ $ok -eq 0 ]] ; then # Must be at least 1 min old or different query...
time_get_current 'module_faq_last_query_time'
# Update anti-flood variables
module_faq_last_query_item="$line"
module_faq_last_query="$query_time"
if [[ "$query" =~ ^\ *([0-9]+)\ *$ ]]; then
local index="${BASH_REMATCH[1]}"
if [[ "${module_faq_array[$index]}" ]]; then
send_msg "$channel" "${module_faq_array[$index]}"
else
send_msg "$channel" "That FAQ item doesn't exist"
fi
# Check length of search to be at least 3 chars
elif [[ "${#query}" -ge 3 ]] ; then
local i=0
while [[ $i -lt "${#module_faq_array[*]}" ]] ; do
(( i++ ))
# FIXME: This code is hard to read.
# This module needs rewriting...
if grep -qiFm 1 "$query" <<< "${module_faq_array[$i]}" ; then
send_msg "$channel" "${module_faq_array[$i]}"
break 1
fi
done
fi
else
log_error "FLOOD DETECTED in FAQ module"
fi
fi
}

151
modules/m_help.sh Normal file
View File

@@ -0,0 +1,151 @@
#!/bin/bash
# -*- coding: utf-8 -*-
###########################################################################
# #
# envbot - an IRC bot in bash #
# Copyright (C) 2007-2008 Arvid Norlander #
# Copyright (C) 2007-2008 Vsevolod Kozlov #
# #
# 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/>. #
# #
###########################################################################
#---------------------------------------------------------------------
## Provides help command.
#---------------------------------------------------------------------
module_help_INIT() {
modinit_API='2'
modinit_HOOKS=''
commands_register "$1" 'help' || return 1
commands_register "$1" 'modinfo' || return 1
helpentry_module_help_description="Provides help and information for commands and modules."
helpentry_help_help_syntax='<command>'
helpentry_help_help_description='Displays help for command <command>'
helpentry_help_modinfo_syntax='<module>'
helpentry_help_modinfo_description='Displays a description for module <module>'
}
module_help_UNLOAD() {
unset module_help_fetch_module_function_data
unset module_help_fetch_module_data
}
module_help_REHASH() {
return 0
}
module_help_fetch_module_function_data() {
local module_name="$1"
local function_name="$2"
local target_syntax="$3"
local target_description="$4"
local varname_syntax="helpentry_${module_name}_${function_name}_syntax"
local varname_description="helpentry_${module_name}_${function_name}_description"
if [[ -z ${!varname_description} ]]; then
return 1
fi
printf -v "$target_description" '%s' "${!varname_description}"
if [[ ${!varname_syntax} ]]; then
printf -v "$target_syntax" '%s' " ${!varname_syntax}"
fi
}
module_help_fetch_module_data() {
local module_name="$1"
local target_description="$2"
local varname_description="helpentry_module_${module_name}_description"
if [[ -z ${!varname_description} ]]; then
return 1
fi
printf -v "$target_description" '%s' "${!varname_description}"
}
module_help_handler_help() {
local sender="$1"
local parameters="$3"
if [[ $parameters =~ ^([a-zA-Z0-9][^ ]*)( [^ ]+)? ]]; then
local command_name="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
# Look where we will reply to. We will not reply in the channel, even if the request was made in a channel, unless appropriate option is set
local target
if [[ $2 =~ ^# && $config_module_help_reply_in_channel == 1 ]]; then
target="$2"
else
parse_hostmask_nick "$sender" 'target'
fi
# Get the module name the command belongs to.
local module_name=
commands_provides "$command_name" 'module_name'
# Extract the function name.
local function_name=
hash_get 'commands_list' "$command_name" 'function_name'
if [[ $function_name =~ ^module_${module_name}_handler_(.+)$ ]]; then
function_name="${BASH_REMATCH[1]}"
fi
# Finally get the data for a specific function in specific module.
local syntax=
local description=
module_help_fetch_module_function_data "$module_name" "$function_name" syntax description || {
send_notice "$target" "Sorry, no help for ${format_bold}${command_name}${format_bold}"
return
}
# And send it back to the user.
if [[ $config_module_help_reply_in_one_line == 1 ]]; then
send_notice "$target" "${format_bold}${command_name}${format_bold}$syntax -- $description"
else
send_notice "$target" "${format_bold}${command_name}${format_bold}$syntax"
send_notice "$target" "$description"
fi
else
local sendernick=
parse_hostmask_nick "$sender" 'sendernick'
feedback_bad_syntax "$sendernick" "help" "<command>"
fi
}
module_help_handler_modinfo() {
local sender="$1"
local parameters="$3"
if [[ $parameters =~ ^([^ ]+) ]]; then
local module_name="${BASH_REMATCH[1]}"
# See module_help_handler_help
local target
if [[ $2 =~ ^# && $config_module_help_reply_in_channel == 1 ]]; then
target="$2"
else
parse_hostmask_nick "$sender" 'target'
fi
local description=
module_help_fetch_module_data "$module_name" description || {
send_notice "$target" "Sorry, no information for module ${format_bold}${module_name}${format_bold}"
return
}
if [[ $config_module_help_reply_in_one_line == 1 ]]; then
send_notice "$target" "${format_bold}${module_name}${format_bold} -- $description"
else
send_notice "$target" "${format_bold}${module_name}${format_bold}"
send_notice "$target" "$description"
fi
else
local sendernick=
parse_hostmask_nick "$sender" sendernick
feedback_bad_syntax "$sendernick" "modinfo" "<module>"
fi
}

92
modules/m_join.sh Normal file
View File

@@ -0,0 +1,92 @@
#!/bin/bash
# -*- coding: utf-8 -*-
###########################################################################
# #
# envbot - an IRC bot in bash #
# Copyright (C) 2007-2008 Arvid Norlander #
# Copyright (C) 2007-2008 EmErgE <halt.system@gmail.com> #
# #
# 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/>. #
# #
###########################################################################
#---------------------------------------------------------------------
## Join/part
#---------------------------------------------------------------------
module_join_INIT() {
modinit_API='2'
modinit_HOOKS=''
commands_register "$1" 'join' || return 1
commands_register "$1" 'part' || return 1
helpentry_module_join_description="Join/part commands."
helpentry_join_join_syntax='<#channel> [<key>]'
helpentry_join_join_description='Join a <#channel>, with an optional channel <key>.'
helpentry_join_part_syntax='<#channel> [<reason>]"'
helpentry_join_part_description='Part a <#channel> with an optional <reason>.'
}
module_join_UNLOAD() {
return 0
}
module_join_REHASH() {
return 0
}
module_join_handler_part() {
local sender="$1"
local parameters="$3"
if [[ "$parameters" =~ ^(#[^ ]+)(\ (.+))? ]]; then
local channel="${BASH_REMATCH[1]}"
local reason="${BASH_REMATCH[3]}"
if access_check_capab "join" "$sender" "$channel"; then
if [[ -z "$reason" ]]; then
channels_part "$channel"
else
channels_part "$channel" "$reason"
fi
else
access_fail "$sender" "make the bot part channel" "join"
fi
else
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
feedback_bad_syntax "$sendernick" "part" "<#channel> [<reason>]"
fi
}
module_join_handler_join() {
local sender="$1"
local parameters="$3"
if [[ "$parameters" =~ ^(#[^ ]+)(\ [^ ]+)? ]]; then
local channel="${BASH_REMATCH[1]}"
local key="${BASH_REMATCH[2]}"
if access_check_capab "join" "$sender" "$channel"; then
key="${key## }"
if [[ -z "$key" ]]; then
channels_join "${channel}"
else
channels_join "${channel}" "$key"
fi
else
access_fail "$sender" "make the join channel" "join"
fi
else
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
feedback_bad_syntax "$sendernick" "join" "<#channel> [<key>]"
fi
}

252
modules/m_karma.sh Normal file
View File

@@ -0,0 +1,252 @@
#!/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/>. #
# #
###########################################################################
#---------------------------------------------------------------------
## Karma module
#---------------------------------------------------------------------
module_karma_INIT() {
modinit_API='2'
modinit_HOOKS='after_load on_PRIVMSG'
commands_register "$1" 'karma' || return 1
helpentry_module_karma_description="Provides karma support. Use ++ and -- after a string in a channel to change karma."
helpentry_karma_karma_syntax='<string>'
helpentry_karma_karma_description='Get current karma for <string>.'
}
module_karma_UNLOAD() {
unset module_karma_SELECT
unset module_karma_INSERT module_karma_UPDATE module_karma_set_INSERT_or_UPDATE
unset module_karma_substract module_karma_add module_karma_check
unset module_karma_is_nick
unset module_karma_check_return
return 0
}
module_karma_REHASH() {
return 0
}
module_karma_after_load() {
modules_depends_register "karma" "sqlite3" || {
# This error reporting is hackish, will fix later.
if ! list_contains "modules_loaded" "sqlite3"; then
log_error "The karma module depends upon the SQLite3 module being loaded."
fi
return 1
}
if [[ -z $config_module_karma_table ]]; then
log_error "Karma table (config_module_karma_table) must be set in config to use the karma module."
return 1
fi
if ! module_sqlite3_table_exists "$config_module_karma_table"; then
log_error "karma module: $config_module_karma_table does not exist in the database file."
log_error "karma module: See comment in doc/karma.sql for how to create the table."
fi
}
#---------------------------------------------------------------------
## Get an item from DB
## @Type Private
## @param key
## @Stdout The result of the database query.
#---------------------------------------------------------------------
module_karma_SELECT() {
module_sqlite3_exec_sql "SELECT rating FROM $config_module_karma_table WHERE target='$(module_sqlite3_clean_string "$1")';"
}
#---------------------------------------------------------------------
## Insert a new item into DB
## @Type Private
## @param key
## @param karma
#---------------------------------------------------------------------
module_karma_INSERT() {
module_sqlite3_exec_sql \
"INSERT INTO $config_module_karma_table (target, rating) VALUES('$(module_sqlite3_clean_string "$1")', '$(module_sqlite3_clean_string "$2")');"
}
#---------------------------------------------------------------------
## Change the item in DB
## @Type Private
## @param key
## @param karma
#---------------------------------------------------------------------
module_karma_UPDATE() {
module_sqlite3_exec_sql \
"UPDATE $config_module_karma_table SET rating='$(module_sqlite3_clean_string "$2")' WHERE target='$(module_sqlite3_clean_string "$1")';"
}
#---------------------------------------------------------------------
## Wrapper, call either INSERT or UPDATE
## @Type Private
## @param key
## @param karma
#---------------------------------------------------------------------
module_karma_set_INSERT_or_UPDATE() {
if [[ $(module_karma_SELECT "$1") ]]; then
module_karma_UPDATE "$1" "$2"
else
module_karma_INSERT "$1" "$2"
fi
}
#---------------------------------------------------------------------
## Remove 1 from key
## @Type Private
## @param key to remove from.
#---------------------------------------------------------------------
module_karma_substract() {
# Clean spaces and convert to lower case
local keyarray
read -ra keyarray <<< "$1"
local key="$(tr '[:upper:]' '[:lower:]' <<< "${keyarray[*]}")"
local old="$(module_karma_SELECT "$key")"
# -1 + any old value (yes looks backwards but works)
local new=-1
if [[ "$old" ]]; then
(( new += old ))
fi
module_karma_set_INSERT_or_UPDATE "$key" "$new"
}
#---------------------------------------------------------------------
## Add 1 from key
## @Type Private
## @param key to add to.
#---------------------------------------------------------------------
module_karma_add() {
# Clean spaces and convert to lower case
local keyarray
read -ra keyarray <<< "$1"
local key="$(tr '[:upper:]' '[:lower:]' <<< "${keyarray[*]}")"
local old="$(module_karma_SELECT "$key")"
# 1 + any old value
local new=1
if [[ "$old" ]]; then
(( new += old ))
fi
module_karma_set_INSERT_or_UPDATE "$key" "$new"
}
#---------------------------------------------------------------------
## Return karma value for key
## The result is returned in $module_karma_check_return
## @Type Private
## @param key to return karma for
## @Globals $module_karma_check_return
#---------------------------------------------------------------------
module_karma_check() {
# Clean spaces and convert to lower case
local keyarray
read -ra keyarray <<< "$1"
local key="$(tr '[:upper:]' '[:lower:]' <<< "${keyarray[*]}")"
module_karma_check_return="$(module_karma_SELECT "$key")"
if [[ -z "$module_karma_check_return" ]]; then
module_karma_check_return=0
fi
}
#---------------------------------------------------------------------
## Check if the key is the nick of sender.
## @Type Private
## @param key
## @param sender
## @return 0 If nick and key are same
## @return 1 Otherwise
#---------------------------------------------------------------------
module_karma_is_nick() {
local keyarray
read -ra keyarray <<< "$1"
local key="$(tr '[:upper:]' '[:lower:]' <<< "${keyarray[*]}")"
local sendernick
parse_hostmask_nick "$2" 'sendernick'
local nickarray
read -ra nickarray <<< "$(tr '[:upper:]' '[:lower:]' <<< "$sendernick")"
local nick="${nickarray[*]}"
if [[ "$key" = "$nick" ]]; then
return 0
fi
return 1
}
# Called on a PRIVMSG
#
# $1 = from who (n!u@h)
# $2 = to who (channel or botnick)
# $3 = the message
module_karma_on_PRIVMSG() {
local sender="$1"
local query="$3"
local sendon_channel
# If it isn't in a channel send message back to person who sent it,
# otherwise send in channel
if [[ $2 =~ ^# ]]; then
sendon_channel="$2"
# An item must begin with an alphanumeric char.
if [[ "$query" =~ ^([a-zA-Z0-9].*)\+\+$ ]]; then
local key="${BASH_REMATCH[1]}"
if module_karma_is_nick "$key" "$sender"; then
send_msg "$sendon_channel" "You can't change karma of yourself."
else
module_karma_add "$key"
fi
elif [[ "$query" =~ ^([a-zA-Z0-9].*)--$ ]]; then
local key="${BASH_REMATCH[1]}"
if module_karma_is_nick "$key" "$sender"; then
send_msg "$sendon_channel" "You can't change karma of yourself."
else
module_karma_substract "$key"
fi
fi
else
parse_hostmask_nick "$sender" 'sendon_channel'
# Karma is only possible in channels
if [[ "$query" =~ ^[a-zA-Z0-9].*(--|\+\+)$ ]]; then
send_notice "$sendon_channel" "You can only change karma in channels."
return 1
fi
fi
return 0
}
module_karma_handler_karma() {
local sender="$1"
local sendon_channel
if [[ $2 =~ ^# ]]; then
sendon_channel="$2"
else
parse_hostmask_nick "$sender" 'sendon_channel'
fi
local parameters="$3"
if [[ $parameters =~ ^(.+)$ ]]; then
local key="${BASH_REMATCH[1]}"
module_karma_check "$key"
send_msg "$sendon_channel" "Karma for $key is $module_karma_check_return"
else
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
feedback_bad_syntax "$sendernick" "karma" "<string>"
fi
}

145
modules/m_kick_ban.sh Normal file
View File

@@ -0,0 +1,145 @@
#!/bin/bash
# -*- coding: utf-8 -*-
###########################################################################
# #
# envbot - an IRC bot in bash #
# Copyright (C) 2007-2008 Arvid Norlander #
# Copyright (C) 2007-2008 EmErgE <halt.system@gmail.com> #
# #
# 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/>. #
# #
###########################################################################
#---------------------------------------------------------------------
## Kicking and banning.
#---------------------------------------------------------------------
module_kick_ban_INIT() {
modinit_API='2'
modinit_HOOKS='after_load after_connect on_numeric'
unset module_kick_ban_next_unset module_kick_ban_timed_bans
commands_register "$1" 'kick' || return 1
commands_register "$1" 'ban' || return 1
helpentry_module_kick_ban_description="Provides kick and ban commands."
helpentry_kick_ban_kick_syntax='[<#channel>] <nick> <reason>'
helpentry_kick_ban_kick_description='Kick someone from a channel. Channel parameter only needed if not sent in a channel.'
helpentry_kick_ban_ban_syntax='<#channel> <nick> [<duration>]'
helpentry_kick_ban_ban_description='Ban someone from a channel. Duration is optional and defaults to infinite.'
}
module_kick_ban_UNLOAD() {
unset module_kick_ban_TBAN_supported
}
module_kick_ban_REHASH() {
return 0
}
# Lets check if TBAN is supported
# :photon.kuonet-ng.org 461 envbot TBAN :Not enough parameters.
# :photon.kuonet-ng.org 304 envbot :SYNTAX TBAN <channel> <duration> <banmask>
module_kick_ban_after_connect() {
module_kick_ban_TBAN_supported=0
send_raw "TBAN"
}
# HACK: If module is loaded after connect, module_kick_ban_after_connect won't
# get called, therefore lets check if we are connected here and check for
# TBAN here if that is the case.
module_kick_ban_after_load() {
if [[ $server_connected -eq 1 ]]; then
module_kick_ban_TBAN_supported=0
send_raw "TBAN"
fi
}
module_kick_ban_on_numeric() {
if [[ $1 == $numeric_ERR_NEEDMOREPARAMS ]]; then
if [[ "$2" =~ ^TBAN\ : ]]; then
module_kick_ban_TBAN_supported=1
fi
fi
}
module_kick_ban_handler_kick() {
# Accept this anywhere, unless someone can give a good reason not to.
local sender="$1"
local sendon_channel="$2"
local parameters="$3"
if [[ $parameters =~ ^((#[^ ]+)\ )(.*) ]]; then
local channel="${BASH_REMATCH[2]}"
parameters="${BASH_REMATCH[3]}"
else
if ! [[ $channel =~ ^# ]]; then
if [[ $sendon_channel =~ ^# ]]; then
local channel="$sendon_channel"
else
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
feedback_bad_syntax "$sendernick" "kick" "[<#channel>] <nick> <reason> # Channel must be send when the message is not sent in a channel"
return 0
fi
fi
fi
if [[ "$parameters" =~ ^([^ ]+)\ (.+) ]]; then
local nick="${BASH_REMATCH[1]}"
local kickmessage="${BASH_REMATCH[2]}"
if access_check_capab "kick" "$sender" "$channel"; then
send_raw "KICK $channel $nick :$kickmessage"
access_log_action "$sender" "kicked $nick from $channel with kick message: $kickmessage"
else
access_fail "$sender" "make the bot kick somebody" "kick"
fi
else
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
feedback_bad_syntax "$sendernick" "kick" "[<#channel>] <nick> <reason> # Channel must be send when the message is not sent in a channel"
fi
}
module_kick_ban_handler_ban() {
local sender="$1"
local sendon_channel="$2"
local parameters="$3"
if [[ "$parameters" =~ ^(#[^ ]+)\ ([^ ]+)(\ ([0-9]+))? ]]; then
local channel="${BASH_REMATCH[1]}"
local nick="${BASH_REMATCH[2]}"
# Optional parameter.
local duration="${BASH_REMATCH[4]}"
if access_check_capab "ban" "$sender" "$channel"; then
if [[ $duration ]]; then
# send_modes "$channel" "+b" get_hostmask $nick <-- not implemented yet
if [[ $module_kick_ban_TBAN_supported -eq 1 ]]; then
send_raw "TBAN $channel $duration $nick"
else
send_modes "$channel" "+b $nick"
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
send_notice "$sendernick" "Sorry ban will not be timed, this IRCd didn't support TBAN command when I checked before."
fi
else
send_modes "$channel" "+b $nick"
fi
access_log_action "$sender" "banned $nick from $channel"
else
access_fail "$sender" "make the bot ban somebody" "ban"
fi
else
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
feedback_bad_syntax "$sendernick" "ban" "<#channel> <nick> [<duration>]"
fi
}

178
modules/m_modules.sh Normal file
View File

@@ -0,0 +1,178 @@
#!/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/>. #
# #
###########################################################################
#---------------------------------------------------------------------
## Manage (load/unload/list) modules.
#---------------------------------------------------------------------
module_modules_INIT() {
modinit_API='2'
modinit_HOOKS=''
commands_register "$1" 'modload' || return 1
commands_register "$1" 'modunload' || return 1
commands_register "$1" 'modreload' || return 1
commands_register "$1" 'modlist' || return 1
helpentry_module_modules_description="Exposes the internal module loading and unloading support to owners."
helpentry_modules_modload_syntax='<module name>'
helpentry_modules_modload_description='Try to load a module.'
helpentry_modules_modunload_syntax='<module name>'
helpentry_modules_modunload_description='Try to unload a module.'
helpentry_modules_modreload_syntax='<module name>'
helpentry_modules_modreload_description='Try to unload and reload a module.'
helpentry_modules_modlist_syntax=''
helpentry_modules_modlist_description='List currently loaded moudules.'
}
module_modules_UNLOAD() {
unset module_modules_doload module_modules_dounload
}
module_modules_REHASH() {
return 0
}
#---------------------------------------------------------------------
## Load a module
## @param Module to load
## @param Sender nick
#---------------------------------------------------------------------
module_modules_doload() {
local target_module="$1"
local sendernick="$2"
modules_load "$target_module"
local status_message status=$?
case $status in
0) status_message="Loaded \"$target_module\" successfully" ;;
2) status_message="Module \"$target_module\" is already loaded" ;;
3) status_message="Failed to source \"$target_module\" in safe subshell, see log for details" ;;
4) status_message="Failed to source \"$target_module\"" ;;
5) status_message="Module \"$target_module\" could not be found" ;;
6) status_message="Getting hooks from \"$target_module\" failed" ;;
7) status_message="after_load failed for \"$target_module\", see log for details" ;;
*) status_message="Unknown error (code $status) for \"$target_module\"" ;;
esac
send_notice "$sendernick" "$status_message"
return $status
}
#---------------------------------------------------------------------
## Unload a module
## @param Module to unload
## @param Sender nick
#---------------------------------------------------------------------
module_modules_dounload() {
local target_module="$1"
local sendernick="$2"
if [[ $target_module == modules ]]; then
send_msg "$sendernick" \
"You can't unload/reload the modules module using itself. (The hackish way would be to use the eval module for this.)"
return 1
fi
modules_unload "$target_module"
local status_message status=$?
case $status in
0) status_message="Unloaded \"$target_module\" successfully" ;;
2) status_message="Module \"$target_module\" is not loaded" ;;
3) status_message="Module \"$target_module\" can't be unloaded, some these module(s) depend(s) on it: $(modules_depends_list_deps "$target_module")" ;;
*) status_message="Unknown error (code $status) for \"$target_module\"" ;;
esac
send_notice "$sendernick" "$status_message"
return $status
}
module_modules_handler_modload() {
# Accept this anywhere, unless someone can give a good reason not to.
local sender="$1"
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
local parameters="$3"
if [[ "$parameters" =~ ^([^ ]+) ]]; then
local target_module="${BASH_REMATCH[1]}"
if access_check_owner "$sender"; then
access_log_action "$sender" "loaded the module $target_module"
module_modules_doload "$target_module" "$sendernick"
else
access_fail "$sender" "load a module" "owner"
fi
else
feedback_bad_syntax "$sendernick" "modload" "<module name>"
fi
}
module_modules_handler_modunload() {
local sender="$1"
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
local parameters="$3"
if [[ "$parameters" =~ ^([^ ]+) ]]; then
local target_module="${BASH_REMATCH[1]}"
if access_check_owner "$sender"; then
access_log_action "$sender" "unloaded the module $target_module"
module_modules_dounload "$target_module" "$sendernick"
else
access_fail "$sender" "unload a module" "owner"
fi
else
feedback_bad_syntax "$sendernick" "modunload" "<module name>"
fi
}
module_modules_handler_modreload() {
local sender="$1"
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
local parameters="$3"
if [[ "$parameters" =~ ^([^ ]+) ]]; then
local target_module="${BASH_REMATCH[1]}"
if access_check_owner "$sender"; then
access_log_action "$sender" "reloaded the module $target_module"
module_modules_dounload "$target_module" "$sendernick"
if [[ $? = 0 ]]; then
module_modules_doload "$target_module" "$sendernick"
else
send_notice "$sendernick" "Reload of $target_module failed because it could not be unloaded."
fi
else
access_fail "$sender" "reload a module" "owner"
fi
else
feedback_bad_syntax "$sendernick" "modreload" "<module name>"
fi
}
module_modules_handler_modlist() {
local sender="$1"
local parameters="$3"
local target
if [[ $2 =~ ^# ]]; then
target="$2"
else
parse_hostmask_nick "$sender" 'target'
fi
local modlist="${modules_loaded## }"
modlist="${modlist%% }"
send_msg "$target" "${format_bold}Modules currently loaded${format_bold}: ${modlist// / }"
}

316
modules/m_nicktracking.sh Normal file
View File

@@ -0,0 +1,316 @@
#!/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/>. #
# #
###########################################################################
#---------------------------------------------------------------------
## Provides nick tracking API for other modules.
#---------------------------------------------------------------------
module_nicktracking_INIT() {
modinit_API='2'
modinit_HOOKS='after_load before_connect on_numeric on_NICK on_QUIT on_KICK on_PART on_JOIN'
helpentry_module_nicktracking_description="Provides nicktracking backend for other modules."
}
module_nicktracking_UNLOAD() {
unset module_nicktracking_channels
hash_reset module_nicktracking_channels_nicks
hash_reset module_nicktracking_nicks
# Private functions
unset module_nicktracking_clear_nick module_nicktracking_clear_chan
unset module_nicktracking_parse_names
unset module_nicktracking_add_channel_nick
unset module_nicktracking_remove_channel_nick
# API functions
unset module_nicktracking_get_hostmask_by_nick
unset module_nicktracking_get_channel_nicks
return 0
}
module_nicktracking_REHASH() {
return 0
}
#################
# API functions #
#################
#---------------------------------------------------------------------
## Return hostmask of a nick
## @Type API
## @param Nick to find hostmask for
## @param Variable to return hostmask in
## @Note If no nick is found (or data about the nick
## @Note is missing currently), the return variable will be empty.
#---------------------------------------------------------------------
module_nicktracking_get_hostmask_by_nick() {
hash_get 'module_nicktracking_nicks' "$(tr '[:upper:]' '[:lower:]' <<< "$1")" "$2"
}
#---------------------------------------------------------------------
## Return list of nicks on a channel
## @Type API
## @param Channel to check
## @param Variable to return space separated list in
## @return 0 Channel data exists.
## @return 1 We don't track this channel.
#---------------------------------------------------------------------
module_nicktracking_get_channel_nicks() {
if list_contains 'module_nicktracking_channels' "$1"; then
hash_get 'module_nicktracking_channels_nicks' "$1" "$2"
return 0
else
return 1
fi
}
#####################
# Private functions #
#####################
#---------------------------------------------------------------------
## Check if a nick should be removed
## @Type Private
## @param Nick to check
#---------------------------------------------------------------------
module_nicktracking_clear_nick() {
# If not on a channel any more, remove knowledge about nick.
if ! hash_search 'module_nicktracking_channels_nicks' "$1"; then
hash_unset 'module_nicktracking_nicks' "$1"
fi
}
#---------------------------------------------------------------------
## Clear a channel (if we part it or such)
## @Type Private
## @param Channel name
#---------------------------------------------------------------------
module_nicktracking_clear_chan() {
list_remove 'module_nicktracking_channels' "$1" 'module_nicktracking_channels'
# Get list and then unset it.
local nicks=
hash_get 'module_nicktracking_channels_nicks' "$1" 'nicks'
hash_unset 'module_nicktracking_channels_nicks' "$1"
# Sigh, this isn't fast I know...
local nick
for nick in $nicks; do
module_nicktracking_clear_nick "$nick"
done
}
#---------------------------------------------------------------------
## Parse RPL_NAMREPLY data.
## @Type Private
## @param NAMES data
#---------------------------------------------------------------------
module_nicktracking_parse_names() {
if [[ $1 =~ ^[=*@]?\ *(#[^ ]+)\ +:(.+) ]]; then
local channel="${BASH_REMATCH[1]}"
local nicks="${BASH_REMATCH[2]}"
local entry nick realnick
# Loop through the entries
for entry in $nicks; do
# This will work both with and without NAMESX
if [[ $entry =~ [$server_PREFIX_prefixes]*([^ ]+) ]]; then
nick="${BASH_REMATCH[1]}"
# Is UHNAMES enabled?
# If yes lets take care of hostmask.
if [[ $server_UHNAMES -eq 1 ]]; then
parse_hostmask_nick "$nick" 'realnick'
realnick="$(tr '[:upper:]' '[:lower:]' <<< "$realnick")"
hash_set 'module_nicktracking_nicks' "$realnick" "$nick"
# Add to nick list of channel if not in list
hash_contains 'module_nicktracking_channels_nicks' "$channel" "$realnick" || \
hash_append 'module_nicktracking_channels_nicks' "$channel" "$realnick"
else
realnick="$(tr '[:upper:]' '[:lower:]' <<< "$nick")"
# Add to nick list of channel if not in list
hash_contains 'module_nicktracking_channels_nicks' "$channel" "$realnick" || \
hash_append 'module_nicktracking_channels_nicks' "$channel" "$realnick"
fi
else
log_error_file unknown_data.log "module_nicktracking_parse_names: Uh uh, regex for inner loop is bad, couldn't parse: $nick"
log_error_file unknown_data.log "module_nicktracking_parse_names: Please report a bug with the above message"
fi
done
else
log_error_file unknown_data.log "module_nicktracking_parse_names: Uh uh, outer regex is bad, couldn't parse: $1"
log_error_file unknown_data.log "module_nicktracking_parse_names: Please report a bug with the above message"
fi
return 0
}
#---------------------------------------------------------------------
## Parse RPL_WHOREPLY data.
## @Type Private
## @param WHO data
#---------------------------------------------------------------------
module_nicktracking_parse_who() {
# Read the who data into an array then extract the data from the array.
local whodata
read -ra whodata <<< "$1"
local channel="${whodata[0]}"
local ident="${whodata[1]}"
local host="${whodata[2]}"
local nick="${whodata[4]}"
local lowernick="$(tr '[:upper:]' '[:lower:]' <<< "$nick")"
# Set the hash tables
hash_set 'module_nicktracking_nicks' "$lowernick" "${nick}!${ident}@${host}"
# We don't want to add twice
hash_contains 'module_nicktracking_channels_nicks' "$channel" "$lowernick" || \
hash_append 'module_nicktracking_channels_nicks' "$channel" "$lowernick"
}
#---------------------------------------------------------------------
## Add a nick to a channel
## @Type Private
## @param Channel
## @param Hostmask
## @param Nick
#---------------------------------------------------------------------
module_nicktracking_add_channel_nick() {
local nick="$(tr '[:upper:]' '[:lower:]' <<< "$3")"
hash_append 'module_nicktracking_channels_nicks' "$1" "$nick"
hash_set 'module_nicktracking_nicks' "$nick" "$2"
}
#---------------------------------------------------------------------
## Remove a nick from a channel
## @Type Private
## @param Channel
## @param Nick
#---------------------------------------------------------------------
module_nicktracking_remove_channel_nick() {
local nick="$(tr '[:upper:]' '[:lower:]' <<< "$2")"
hash_substract 'module_nicktracking_channels_nicks' "$1" "$nick"
module_nicktracking_clear_nick "$nick"
}
#########
# Hooks #
#########
module_nicktracking_after_load() {
# Handle case of loading while bot is running
if [[ $server_connected -eq 1 ]]; then
module_nicktracking_channels="$channels_current"
local channel
for channel in $module_nicktracking_channels; do
send_raw "NAMES $channel"
# We have to send a WHO #channel if servers doesn't support UHNAMES.
if [[ $server_UHNAMES -eq 0 ]]; then
send_raw "WHO $channel"
fi
done
fi
}
module_nicktracking_before_connect() {
# Reset state.
unset module_nicktracking_channels
hash_reset module_nicktracking_channels_nicks
hash_reset module_nicktracking_nicks
return 0
}
##########################
# Message handling hooks #
##########################
module_nicktracking_on_numeric() {
case $1 in
"$numeric_RPL_NAMREPLY")
# TODO: Parse NAMES
module_nicktracking_parse_names "$2"
;;
"$numeric_RPL_WHOREPLY")
module_nicktracking_parse_who "$2"
;;
esac
}
module_nicktracking_on_NICK() {
local oldnick oldident oldhost oldentry
parse_hostmask "$1" 'oldnick' 'oldident' 'oldhost'
local oldlowercase="$(tr '[:upper:]' '[:lower:]' <<< "$oldnick")"
local newlowercase="$(tr '[:upper:]' '[:lower:]' <<< "$2")"
# Remove old and add new.
hash_get 'module_nicktracking_nicks' "$oldlowercase" 'oldentry'
hash_unset 'module_nicktracking_nicks' "$oldlowercase"
hash_set 'module_nicktracking_nicks' "$newlowercase" "${2}!${oldident}@${oldhost}"
local channel
# Loop through the channels
for channel in $module_nicktracking_channels; do
hash_replace 'module_nicktracking_channels_nicks' "$channel" "$oldnick" "$newlowercase"
done
return 0
}
module_nicktracking_on_QUIT() {
local whoquit=
parse_hostmask_nick "$1" 'whoquit'
local nick="$(tr '[:upper:]' '[:lower:]' <<< "$whoquit")"
hash_unset 'module_nicktracking_nicks' "$nick"
local channel
# Remove from channel
for channel in $module_nicktracking_channels; do
hash_substract 'module_nicktracking_channels_nicks' "$channel" "$nick"
done
}
module_nicktracking_on_KICK() {
local whogotkicked="$3"
if [[ $whogotkicked == $server_nick_current ]]; then
module_nicktracking_clear_chan "$2"
else
module_nicktracking_remove_channel_nick "$2" "$whogotkicked"
fi
}
module_nicktracking_on_PART() {
# Check if it was us
local whoparted=
parse_hostmask_nick "$1" 'whoparted'
if [[ $whoparted == $server_nick_current ]]; then
module_nicktracking_clear_chan "$2"
else
module_nicktracking_remove_channel_nick "$2" "$whoparted"
fi
}
module_nicktracking_on_JOIN() {
local whojoined=
parse_hostmask_nick "$1" 'whojoined'
if [[ $whojoined == $server_nick_current ]]; then
module_nicktracking_channels+=" $2"
hash_set 'module_nicktracking_channels_nicks' "$2" "$server_nick_current"
# We have to send a WHO #channel if servers doesn't support UHNAMES.
if [[ $server_UHNAMES -eq 0 ]]; then
send_raw "WHO $2"
fi
else
module_nicktracking_add_channel_nick "$2" "$1" "$whojoined"
fi
}

87
modules/m_ping.sh Normal file
View File

@@ -0,0 +1,87 @@
#!/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/>. #
# #
###########################################################################
#---------------------------------------------------------------------
## Keeps track of latency
#---------------------------------------------------------------------
# TODO: Redo with stored "on pong info".
module_ping_INIT() {
modinit_API='2'
modinit_HOOKS='on_PONG'
commands_register "$1" 'ping' || return 1
commands_register "$1" 'latency' || return 1
helpentry_module_ping_description="Provides latency tracking."
helpentry_ping_ping_syntax=''
helpentry_ping_ping_description='Respond to sender with "PONG!"'
helpentry_ping_latency_syntax=''
helpentry_ping_latency_description='Report current latency to server.'
}
module_ping_UNLOAD() {
return 0
}
module_ping_REHASH() {
return 0
}
module_ping_on_PONG() {
# Is data time_sender?
if [[ $3 =~ ([0-9]+)_(#?[A-Za-z0-9][^ ]+) ]]; then
local time="${BASH_REMATCH[1]}"
local target="${BASH_REMATCH[2]}"
local latency
(( latency = envbot_time - $time ))
local msg=
case $latency in
0) msg="less than one second" ;;
1) msg="1 second" ;;
*) msg="$latency seconds" ;;
esac
send_msg "$target" "Latency is $msg"
fi
}
module_ping_handler_ping() {
local target
local sender_nick
parse_hostmask_nick "$1" 'sender_nick'
if [[ $2 =~ ^# ]]; then
target="$2"
else
target="$sender_nick"
fi
send_msg "$target" "$sender_nick: PONG!"
}
module_ping_handler_latency() {
local target
if [[ $2 =~ ^# ]]; then
target="$2"
else
parse_hostmask_nick "$1" 'target'
fi
send_raw "PING :${envbot_time}_${target}"
}

85
modules/m_quote.sh Normal file
View File

@@ -0,0 +1,85 @@
#!/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/>. #
# #
###########################################################################
#---------------------------------------------------------------------
## Quotes module
#---------------------------------------------------------------------
module_quote_INIT() {
modinit_API='2'
modinit_HOOKS='after_load'
commands_register "$1" 'quote' || return 1
helpentry_module_quote_description="Provides command for random quotes from a file."
helpentry_quote_quote_syntax=''
helpentry_quote_quote_description='Return a random quote.'
}
module_quote_UNLOAD() {
unset module_quote_load
unset module_quote_quotes
}
module_quote_REHASH() {
module_quote_load
}
#---------------------------------------------------------------------
## Load quotes from file
## @Type Private
#---------------------------------------------------------------------
module_quote_load() {
local i=0 line
unset module_quote_quotes
if [[ -z "$config_module_quotes_file" ]]; then
log_error "quotes module: You need to set config_module_quotes_file in your config!"
return 1
elif [[ -r "$config_module_quotes_file" ]]; then
local IFS=$'\n'
module_quote_quotes=( $(<"${config_module_quotes_file}") )
unset IFS
log_info 'Loaded Quotes.'
return 0
else
log_error "quotes module: Quotes failed to load: Cannot load \"$config_module_quotes_file\". File doesn't exist."
return 1
fi
}
module_quote_after_load() {
# Return code from last command in a function
# will be return code for the function by default.
module_quote_load
}
module_quote_handler_quote() {
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 number="$RANDOM"
(( number %= ${#module_quote_quotes[*]} ))
send_msg "$channel" "${module_quote_quotes[$number]}"
}

74
modules/m_rehash.sh Normal file
View File

@@ -0,0 +1,74 @@
#!/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/>. #
# #
###########################################################################
#---------------------------------------------------------------------
## Rehashing
#---------------------------------------------------------------------
module_rehash_INIT() {
modinit_API='2'
modinit_HOOKS=''
commands_register "$1" 'rehash' || return 1
helpentry_module_rehash_description="Exposes the internal rehash support to bot owners."
helpentry_rehash_rehash_syntax=''
helpentry_rehash_rehash_description='Reload configuration file.'
}
module_rehash_UNLOAD() {
unset module_rehash_dorehash
}
module_rehash_REHASH() {
return 0
}
#---------------------------------------------------------------------
## Rehash config
## @Type Private
## @param Sender
#---------------------------------------------------------------------
module_rehash_dorehash() {
local sender="$1" status_message
config_rehash
local status=$?
case $status in
0) status_message="Rehash successful. (Also any loaded modules not listed in config have been unloaded.)" ;;
2) status_message="The new config is not the same version as the bot. Rehash won't work." ;;
3) status_message="Failed to source it, but the bot should not be in an undefined state." ;;
4) status_message="Configuration validation on new config failed, but the bot should not be in an undefined state." ;;
5) status_message="Failed to source it and the bot may be in an undefined state." ;;
*) status_message="Unknown error (code $status)" ;;
esac
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
send_notice "$sendernick" "$status_message"
}
module_rehash_handler_rehash() {
local sender="$1"
if access_check_owner "$sender"; then
access_log_action "$sender" "did a rehash"
module_rehash_dorehash "$sender"
else
access_fail "$sender" "load a module" "owner"
fi
}

98
modules/m_say.sh Normal file
View File

@@ -0,0 +1,98 @@
#!/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 to bot say something
#---------------------------------------------------------------------
module_say_INIT() {
modinit_API='2'
modinit_HOOKS=''
commands_register "$1" 'say' || return 1
commands_register "$1" 'act' || return 1
helpentry_module_say_description="Provides say and act commands."
helpentry_say_act_syntax='<target> <message>'
helpentry_say_act_description='Send a <message> to <target> (nick or channel).'
helpentry_say_act_syntax='<target> <message>'
helpentry_say_act_description='Peform the <message> as a /me to <target> (nick or channel).'
}
module_say_UNLOAD() {
return 0
}
module_say_REHASH() {
return 0
}
module_say_handler_say() {
local sender="$1"
local parameters="$3"
if [[ "$parameters" =~ ^([^ ]+)\ (.+) ]]; then
local target="${BASH_REMATCH[1]}"
local message="${BASH_REMATCH[2]}"
local scope
# Is it a channel?
if [[ $target =~ ^# ]]; then
scope="$target"
else
scope="MSG"
fi
if access_check_capab "say" "$sender" "$scope"; then
access_log_action "$sender" "made the bot say \"$message\" in/to \"$target\""
send_msg "$target" "$message"
else
access_fail "$sender" "make the bot talk with say" "say"
fi
else
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
feedback_bad_syntax "$sendernick" "say" "<target> <message> # Where target is a nick or channel"
fi
}
module_say_handler_act() {
local sender="$1"
local parameters="$3"
if [[ "$parameters" =~ ^([^ ]+)\ (.+) ]]; then
local target="${BASH_REMATCH[1]}"
local message="${BASH_REMATCH[2]}"
local scope
# Is it a channel?
if [[ $target =~ ^# ]]; then
scope="$target"
else
scope="MSG"
fi
if access_check_capab "say" "$sender" "$scope"; then
access_log_action "$sender" "made the bot act \"$message\" in/to \"$target\""
send_ctcp "$target" "ACTION ${message}"
else
access_fail "$sender" "make the bot act" "say"
fi
else
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
feedback_bad_syntax "$sendernick" "act" "<target> <message> # Where target is a nick or channel"
fi
}

209
modules/m_seen.sh Normal file
View File

@@ -0,0 +1,209 @@
#!/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/>. #
# #
###########################################################################
#---------------------------------------------------------------------
## Simple seen module using SQLite3
#---------------------------------------------------------------------
module_seen_INIT() {
modinit_API='2'
modinit_HOOKS='after_load on_PRIVMSG'
commands_register "$1" 'seen' || return 1
helpentry_module_seen_description="Provides last seen information."
helpentry_seen_seen_syntax='<nick>'
helpentry_seen_seen_description='Report when the bot last saw <nick>.'
}
module_seen_UNLOAD() {
unset module_seen_exec_sql module_seen_SELECT module_seen_INSERT module_seen_UPDATE
unset module_seen_set_INSERT_or_UPDATE
unset module_seen_store module_seen_find
}
module_seen_REHASH() {
return 0
}
# Called after module has loaded.
module_seen_after_load() {
modules_depends_register "seen" "sqlite3" || {
# This error reporting is hackish, will fix later.
if ! list_contains "modules_loaded" "sqlite3"; then
log_error "The seen module depends upon the SQLite3 module being loaded."
fi
return 1
}
if [[ -z $config_module_seen_table ]]; then
log_error "\"Seen table\" (config_module_seen_table) must be set in config."
return 1
fi
if ! module_sqlite3_table_exists "$config_module_seen_table"; then
log_error "seen module: $config_module_seen_table does not exist in the database file."
log_error "seen module: See comment in doc/seen.sql for how to create the table."
fi
}
#---------------------------------------------------------------------
## Get the data about nick
## @Type Private
## @param The nick
## @Stdout The result of the database query.
#---------------------------------------------------------------------
module_seen_SELECT() {
module_sqlite3_exec_sql "SELECT timestamp, channel, message FROM $config_module_seen_table WHERE nick='$(module_sqlite3_clean_string "$1")';"
}
#---------------------------------------------------------------------
## Insert a new item into DB
## @Type Private
## @param Nick
## @param Channel
## @param Timestamp
## @param Query
#---------------------------------------------------------------------
module_seen_INSERT() {
module_sqlite3_exec_sql \
"INSERT INTO $config_module_seen_table (nick, channel, timestamp, message) VALUES('$(module_sqlite3_clean_string "$1")', '$(module_sqlite3_clean_string "$2")', '$(module_sqlite3_clean_string "$3")', '$(module_sqlite3_clean_string "$4")');"
}
#---------------------------------------------------------------------
## Change the item in DB
## @Type Private
## @param Nick
## @param Channel
## @param Timestamp
## @param Message
#---------------------------------------------------------------------
module_seen_UPDATE() {
module_sqlite3_exec_sql \
"UPDATE $config_module_seen_table SET channel='$(module_sqlite3_clean_string "$2")', timestamp='$(module_sqlite3_clean_string "$3")', message='$(module_sqlite3_clean_string "$4")' WHERE nick='$(module_sqlite3_clean_string "$1")';"
}
#---------------------------------------------------------------------
## Wrapper, call either INSERT or UPDATE
## @Type Private
## @param Nick
## @param Channel
## @param Timestamp
## @param Message
#---------------------------------------------------------------------
module_seen_set_INSERT_or_UPDATE() {
if [[ $(module_seen_SELECT "$1") ]]; then
module_seen_UPDATE "$1" "$2" "$3" "$4"
else
module_seen_INSERT "$1" "$2" "$3" "$4"
fi
}
#---------------------------------------------------------------------
## Store a line
## @Type Private
## @param Sender
## @param Channel
## @param Timestamp
## @param Query
#---------------------------------------------------------------------
module_seen_store() {
# Clean spaces, fastest way for this
local query
read -ra query <<< "$4"
local sendernick
parse_hostmask_nick "$1" 'sendernick'
module_seen_set_INSERT_or_UPDATE "$(echo -n "$sendernick" | tr '[:upper:]' '[:lower:]')" "$2" "$3" "${query[*]}"
}
#---------------------------------------------------------------------
## Look up a nick and send info to a channel/nick
## @Type Private
## @param Sender
## @param Channel
## @param Nick to look up
#---------------------------------------------------------------------
module_seen_find() {
local sender="$1"
local channel="$2"
local nick="$(tr '[:upper:]' '[:lower:]' <<< "$3")"
local sender_nick=
parse_hostmask_nick "$sender" 'sender_nick'
# Classical ones. We just HAVE to do them.
if [[ "$nick" == "$(tr '[:upper:]' '[:lower:]' <<< "$server_nick_current")" ]]; then
send_msg "$channel" "$sender_nick, you found me!"
return 0
elif [[ "$nick" == "$(tr '[:upper:]' '[:lower:]' <<< "$sender_nick")" ]]; then
send_ctcp "$channel" "ACTION holds up a mirror for $sender_nick"
return 0
fi
local match="$(module_seen_SELECT "$nick")"
if [[ $match ]]; then
# So we got a match
# Lets use regex
if [[ $match =~ ([0-9]+)\|(#[^ |]+)\|(.*) ]]; then
local found_timestamp="${BASH_REMATCH[1]}"
local found_channel="${BASH_REMATCH[2]}"
local found_message="${BASH_REMATCH[3]}"
if [[ $found_message =~ ^ACTION\ (.*) ]]; then
found_message="* $3 ${BASH_REMATCH[1]}"
fi
local difference frmtdiff
time_get_current 'difference'
(( difference -= found_timestamp ))
time_format_difference "$difference" 'frmtdiff'
send_msg "$channel" "$3 was last seen $frmtdiff ago in $found_channel saying \"$found_message\""
fi
else
send_msg "$channel" "Sorry, I have not seen $3."
fi
}
module_seen_on_PRIVMSG() {
local sender="$1"
local channel="$2"
local query="$3"
# If in channel, store
if [[ $channel =~ ^# ]]; then
local now=
time_get_current 'now'
module_seen_store "$sender" "$channel" "$now" "$query"
# If not in channel respond to any commands in /msg
else
parse_hostmask_nick "$sender" 'channel'
fi
}
module_seen_handler_seen() {
local sender="$1"
local channel="$2"
if ! [[ $2 =~ ^# ]]; then
parse_hostmask_nick "$sender" 'channel'
fi
# Lets look up messages
local parameters="$3"
if [[ "$parameters" =~ ^([^ ]+) ]]; then
local nick="${BASH_REMATCH[1]}"
module_seen_find "$sender" "$channel" "$nick"
else
local sendernick
parse_hostmask_nick "$sender" 'sendernick'
feedback_bad_syntax "$sendernick" "seen" "<nick>"
fi
}

53
modules/m_sendraw.sh Normal file
View File

@@ -0,0 +1,53 @@
#!/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 bot send any line.
## THIS IS FOR DEBUGGING MAINLY.
#---------------------------------------------------------------------
module_sendraw_INIT() {
modinit_API='2'
modinit_HOOKS=''
commands_register "$1" 'raw' || return 1
helpentry_module_sendraw_description="Provides raw command to send raw data."
helpentry_sendraw_raw_syntax='<line>'
helpentry_sendraw_raw_description='Send the <line> to the IRC server.'
}
module_sendraw_UNLOAD() {
return 0
}
module_sendraw_REHASH() {
return 0
}
module_sendraw_handler_raw() {
local sender="$1"
if access_check_capab "sendraw" "$sender" "GLOBAL"; then
local parameters="$3"
access_log_action "$sender" "make the bot send a raw line: $parameters"
send_raw "$parameters"
else
access_fail "$sender" "send a raw line" "sendraw"
fi
}

87
modules/m_services.sh Normal file
View File

@@ -0,0 +1,87 @@
#!/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/>. #
# #
###########################################################################
#---------------------------------------------------------------------
## Identify to NickServ
#---------------------------------------------------------------------
module_services_INIT() {
modinit_API='2'
modinit_HOOKS='on_connect after_load after_disconnect'
helpentry_module_services_description="Provides support for identifying with services."
}
module_services_UNLOAD() {
unset module_services_ghost module_services_nickserv_command
}
module_services_REHASH() {
return 0
}
module_services_after_load() {
module_services_ghost=0
if [[ $config_module_services_server_alias -eq 0 ]]; then
module_services_nickserv_command="PRIVMSG $config_module_services_nickserv_name :"
else
module_services_nickserv_command="$config_module_services_nickserv_name "
fi
}
# Called for each line on connect
module_services_on_connect() {
local line="$1"
if [[ "$line" =~ ^:[^\ ]+\ +([0-9]{3})\ +([^ ]+)\ +(.*) ]]; then
local numeric="${BASH_REMATCH[1]}"
local numeric="${BASH_REMATCH[1]}"
# Check if this is a numeric we will handle.
case "$numeric" in
"$numeric_ERR_NICKNAMEINUSE"|"$numeric_ERR_ERRONEUSNICKNAME")
module_services_ghost=1
;;
"$numeric_RPL_ENDOFMOTD"|"$numeric_ERR_NOMOTD")
if [[ $config_module_services_style == 'atheme' ]]; then
send_raw_flood_nolog "NickServ IDENTIFY (password)" "${module_services_nickserv_command}IDENTIFY $config_firstnick $config_module_services_nickserv_passwd"
fi
if [[ $module_services_ghost == 1 ]]; then
log_info_stdout "Recovering ghost"
send_raw_flood_nolog "NickServ GHOST (password)" "${module_services_nickserv_command}GHOST $config_firstnick $config_module_services_nickserv_passwd"
# Try to release too, just in case.
send_raw_flood_nolog "NickServ RELEASE (password)" "${module_services_nickserv_command}RELEASE $config_firstnick $config_module_services_nickserv_passwd"
sleep 2
send_nick "$config_firstnick"
# HACK: This is a workaround for bug #21
server_nick_current="$config_firstnick"
fi
log_info_stdout "Identifying..."
if [[ $config_module_services_style != 'atheme' ]]; then
send_raw_flood_nolog "NickServ IDENTIFY (password)" "${module_services_nickserv_command}IDENTIFY $config_module_services_nickserv_passwd"
fi
sleep 1
;;
esac
fi
}
module_services_after_disconnect() {
# Reset state.
module_services_ghost=0
}

89
modules/m_sqlite3.sh Normal file
View File

@@ -0,0 +1,89 @@
#!/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/>. #
# #
###########################################################################
#---------------------------------------------------------------------
## This module allows other modules to access a SQLite3 database in a
## "simple" way.
#---------------------------------------------------------------------
module_sqlite3_INIT() {
modinit_API='2'
modinit_HOOKS='after_load'
helpentry_module_sqlite3_description="Provides sqlite3 database backend for other modules."
}
module_sqlite3_UNLOAD() {
unset module_sqlite3_clean_string module_sqlite3_exec_sql module_sqlite3_table_exists
}
module_sqlite3_REHASH() {
return 0
}
# Called after module has loaded.
module_sqlite3_after_load() {
# Check (silently) for sqlite3
if ! hash sqlite3 > /dev/null 2>&1; then
log_error "Couldn't find sqlite3 command line tool. The sqlite3 module depend on that tool."
return 1
fi
if [[ -z $config_module_sqlite3_database ]]; then
log_error "You must set config_module_sqlite3_database in your config to use the sqlite3 module."
return 1
fi
if ! [[ -r $config_module_sqlite3_database ]]; then
log_error "sqlite3 module: Database file doesn't exist or can't be read!"
log_error "sqlite3 module: To create one follow the comments in one (or several) of the sql files in the doc directory."
return 1
fi
}
#---------------------------------------------------------------------
## Make string safe for SQLite3.
## @Type API
## @param String to clean
## @Note IMPORTANT FOR SECURITY!: Only use the result inside single
## @Note quotes ('), NEVER inside double quotes (").
## @Note The output isn't safe for that.
#---------------------------------------------------------------------
module_sqlite3_clean_string() {
sed "s/'/''/g" <<< "$1"
}
#---------------------------------------------------------------------
## Run the query against the data base.
## @Type API
## @param Query to run
#---------------------------------------------------------------------
module_sqlite3_exec_sql() {
sqlite3 -list "$config_module_sqlite3_database" "$1"
}
#---------------------------------------------------------------------
## Check if a table exists in the database file.
## @Type API
## @param The table name to check for
## @return 0 If table exists
## @return 1 If table doesn't exist.
#---------------------------------------------------------------------
module_sqlite3_table_exists() {
sqlite3 -list "$config_module_sqlite3_database" ".tables" | grep -qw "$1"
}

63
modules/m_umodes.sh Normal file
View File

@@ -0,0 +1,63 @@
#!/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/>. #
# #
###########################################################################
#---------------------------------------------------------------------
## Set umodes when connecting
#---------------------------------------------------------------------
module_umodes_INIT() {
modinit_API='2'
modinit_HOOKS='after_connect after_load'
helpentry_module_umodes_description="Provides support for setting umodes on connect."
}
module_umodes_UNLOAD() {
unset module_umodes_set_modes
}
module_umodes_REHASH() {
module_umodes_set_modes
return 0
}
#---------------------------------------------------------------------
## Set the umodes
## @Type Private
#---------------------------------------------------------------------
module_umodes_set_modes() {
if [[ $config_module_umodes_default_umodes ]]; then
log_info "Setting umodes: $config_module_umodes_default_umodes"
send_umodes "$config_module_umodes_default_umodes"
fi
}
# Called after bot has connected
module_umodes_after_connect() {
module_umodes_set_modes
}
# Called after bot has connected
module_umodes_after_load() {
# Check if connected first
if [[ $server_connected -eq 1 ]]; then
module_umodes_set_modes
fi
}

56
modules/m_uptime.sh Normal file
View File

@@ -0,0 +1,56 @@
#!/usr/bin/bash
# -*- coding: utf-8 -*-
###########################################################################
# #
# envbot - an IRC bot in bash #
# Copyright (C) 2007-2008 Arvid Norlander #
# Copyright (C) 2007-2008 Vsevolod Kozlov #
# #
# 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/>. #
# #
###########################################################################
#---------------------------------------------------------------------
## Bot's uptime command.
#---------------------------------------------------------------------
module_uptime_INIT() {
modinit_API='2'
modinit_HOOKS=''
commands_register "$1" 'uptime' || return 1
helpentry_module_uptime_description="Provides a command to show bot's uptime."
helpentry_uptime_uptime_syntax=''
helpentry_uptime_uptime_description='Shows the uptime for the bot.'
}
module_uptime_UNLOAD() {
return 0
}
module_uptime_REHASH() {
return 0
}
module_uptime_handler_uptime() {
local sender="$1"
local formatted_time=
time_format_difference $SECONDS formatted_time
local target=
if [[ $2 =~ ^# ]]; then
target="$2"
else
parse_hostmask_nick "$sender" target
fi
send_msg "$target" "The bot has been up for $formatted_time."
}