Initial commit
authorBrett Parker <iDunno@sommitrealweird.co.uk>
Tue, 17 Sep 2019 12:35:55 +0000 (13:35 +0100)
committerBrett Parker <iDunno@sommitrealweird.co.uk>
Tue, 17 Sep 2019 12:37:08 +0000 (13:37 +0100)
.gitignore [new file with mode: 0644]
README [new file with mode: 0644]
bashbot.sh [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..c9bd0b7
--- /dev/null
@@ -0,0 +1 @@
+.botsettings.sh
diff --git a/README b/README
new file mode 100644 (file)
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 (file)
index 0000000..b28b146
--- /dev/null
@@ -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