From fa4b586320ccada8a2eb263c053ff8852058416e Mon Sep 17 00:00:00 2001 From: Brett Parker Date: Tue, 17 Sep 2019 13:35:55 +0100 Subject: [PATCH] Initial commit --- .gitignore | 1 + README | 1 + bashbot.sh | 211 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 213 insertions(+) create mode 100644 .gitignore create mode 100644 README create mode 100644 bashbot.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c9bd0b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.botsettings.sh diff --git a/README b/README new file mode 100644 index 0000000..92f1704 --- /dev/null +++ b/README @@ -0,0 +1 @@ +An IRC bot, written in bash... no... really! diff --git a/bashbot.sh b/bashbot.sh new file mode 100644 index 0000000..b28b146 --- /dev/null +++ b/bashbot.sh @@ -0,0 +1,211 @@ +#!/bin/bash + +set -u + +version="0.0.1" + +# make us a fifo... +rm -f .bashbotfifo{in,out} +mkfifo .bashbotfifoin +mkfifo .bashbotfifoout + +# Setup some fds to talk to IRC +exec 3<> .bashbotfifoin +exec 4<> .bashbotfifoout + +irc_process= +keeprunning=1 +declare -A reminders + +cleanup() { + echo "QUIT :Going back to hell" >&4 + keeprunning=0 + sleep 0.2 + if [[ $irc_process -gt 0 ]]; then + if (ps -p $irc_process > /dev/null); then + kill $irc_process + fi + fi + rm .bashbotfifo{in,out} + trap - EXIT + exit 0 +} + +my_hostname="$(hostname)" +my_irc_channel="#alug" +my_irc_password="" +my_irc_nick="bpbot" +my_irc_server="irc.alug.org.uk" +my_irc_port="6697" + +# now if there's a settings file, source that... +if [ -e "$(dirname $(readlink -f $0))/.botsettings.sh" ]; then + . "$(dirname $(readlink -f $0))/.botsettings.sh" +fi + +connect_to_server() { + gnutls-cli --crlf $my_irc_server:$my_irc_port <&4 >&3 2>&3 & + irc_process=$! + connected=0 + while [ $connected == 0 ]; do + read -t 0.2 -u 3 line + if [[ "$line" =~ NOTICE\ ]]; then + echo $line + send_line PASS $my_irc_password + send_line NICK $my_irc_nick + send_line USER $my_irc_nick $my_hostname $my_irc_server $my_irc_nick + send_line JOIN $my_irc_channel + connected=1 + fi + done +} + +# Format of server messages +#:thingsendingmessage command params +# e.g. PRIVMSG +#:iDunno!~brettp@mail.ipv6.sommitrealweird.co.uk PRIVMSG #bp :hello. + +process_irc() { + line="$@" + echo "$line" + ping_regex="^PING " + privmsg_regex="^[^ ]* PRIVMSG" + if [[ "${line}" =~ $ping_regex ]]; then + send_line PONG + echo PONG + elif [[ "${line}" =~ $privmsg_regex ]]; then + parse_privmsg "$line" + fi +} + +parse_privmsg() { + line="$@" + echo "Processing $line" + read -a parts <<-EOF +$line +EOF + + # last character of the last element is going to be a \r so remove it + parts[-1]=${parts[-1]%$'\r'} + + if [[ "${parts[1]}" == "PRIVMSG" ]]; then + sender=${parts[0]} + channel=${parts[2]} + do_command=0 + case $channel in + $my_irc_channel) + if [[ ${parts[3]} =~ [:]*$my_irc_nick[:]*$ ]]; then + do_command=1 + fi + bot_command=${parts[4]} + options="${parts[@]:5}" + ;; + $my_irc_nick) + bot_command=${parts[3]} + bot_command=${bot_command#:} + channel=${parts[0]%\!*} + channel=${channel#:} + options="${parts[@]:4}" + do_command=1 + ;; + esac + if [[ $do_command -gt 0 ]]; then + case $bot_command in + help) + send_help_message $channel + ;; + quit) + cleanup + ;; + version) + send_version $channel + ;; + add) + add_reminder $channel "$options" + ;; + list) + list_reminders $channel + ;; + *) + send_line "PRIVMSG $channel :Sorry, don't know how to $bot_command." + ;; + esac + fi + fi +} + +send_line() { + echo "$@" >&4 + sleep 0.1 +} + +send_help_message() { + channel=$1 + echo "Sending help!" + send_line "PRIVMSG $channel :Help:" + send_line "PRIVMSG $channel : An IRC bot written in bash!" + send_line "PRIVMSG $channel : help - display this message" + send_line "PRIVMSG $channel : version - display version number" + send_line "PRIVMSG $channel : quit - make the bot quit IRC" + send_line "PRIVMSG $channel : add YYYY-mm-dd HH:MM reminder text" + send_line "PRIVMSG $channel : list - list reminders" +} + +send_version() { + channel=$1 + send_line "PRIVMSG $channel :Version: $version" +} + +add_reminder() { + channel="$1" + data="$2" + read -a dataparts <<-EOF +$data +EOF + # we now have a list of parts, they should be of the form + # YYYY-mm-dd HH:MM the text of the reminder + timestamp=$(date +"%s" --date="${dataparts[0]} ${dataparts[1]}") + if [[ $? -ne 0 ]]; then + send_line "PRIVMSG $channel :Couldn't parse date/time ${dataparts[0]} ${dataparts[1]}" + else + send_line "PRIVMSG $channel :Added reminder for ${dataparts[0]} ${dataparts[1]}: ${dataparts[@]:2}" + reminders[$timestamp]="${dataparts[@]:2}" + fi +} + +check_reminders() { + current_timestamp="$(date +"%s")" + # loop through the reminders keys to see if it's past and alert if so + for ts in ${!reminders[@]}; do + if [[ $ts -le $current_timestamp ]]; then + send_line "PRIVMSG $my_irc_channel :${reminders[$ts]}" + # we need to remove this from the array now + unset "reminders[$ts]" + fi + done +} + +list_reminders() { + channel=$1 + for ts in ${!reminders[@]}; do + date_stamp="$(date --date="@$ts" +"%Y-%m-%d %H:%M")" + send_line "PRIVMSG $channel :$date_stamp ${reminders[$ts]}" + done +} + +connect_to_server +trap cleanup EXIT SIGINT + +while true; do + # see if there's anything to read + read -t 0.2 -u 3 aline + if [ $? == 0 ]; then + process_irc "$aline" + sleep 0.2 + fi + check_reminders + # check that the irc_process is still running, restart it if not + if ( ! kill -0 $irc_process ); then + connect_to_server + fi +done -- 2.30.2