Big refactoring done. - annna - Annna the nice friendly bot.
 (HTM) git clone git://bitreich.org/annna/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/annna/
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Tags
 (DIR) README
       ---
 (DIR) commit 7a7a2a9db786688ba9aedf387f56b8fe267f32b5
 (DIR) parent 006db5ec8be7e7f867b63fa5eba7f98d216c42e6
 (HTM) Author: Annna Robert-Houdin <annna@bitreich.org>
       Date:   Tue, 14 Oct 2025 20:43:15 +0200
       
       Big refactoring done.
       
       Diffstat:
         M annna-channel-message               |      19 +++++++++----------
         M annna-channel-service               |      72 ++++++-------------------------
         M annna-join-channels                 |      49 +++++++------------------------
         M annna-message-common                |       9 +++------
         M annna-message-radio                 |       2 +-
         D annna-restart-services              |       7 -------
         M annna-say                           |      33 +++++++++++++++++--------------
         A annna-sleep-well                    |      44 +++++++++++++++++++++++++++++++
         M annna-sleeps                        |       2 --
         M annna-start                         |       8 ++++++--
         D annna-start-channel-service         |      22 ----------------------
         D annna-start-checker                 |      24 ------------------------
         D annna-start-checker-dbg             |      25 -------------------------
         M annna-start-server                  |     132 +++++++++++++------------------
         D annna-start-services                |      21 ---------------------
         M annna-stop                          |      26 ++++++++++++++++++++------
         D annna-stop-checker                  |       6 ------
         D annna-stop-ii                       |       4 ----
         D annna-stop-services                 |       7 -------
         A annna-wakeup                        |       4 ++++
         M modules/radio/radio-channel-servic… |      29 ++++++-----------------------
       
       21 files changed, 189 insertions(+), 356 deletions(-)
       ---
 (DIR) diff --git a/annna-channel-message b/annna-channel-message
       @@ -1,15 +1,14 @@
        #!/bin/sh
        
       -set -x
       -
       -case "${IRC_CHANNEL}" in
       -\#bitreich-radio) annna-message-radio;;
       -\#bitreich-wikigame) annna-message-wikigame;;
       -\#bitreich-sauna) annna-message-sauna;;
       -\#bitreich-idle)
       -        # This one runs its own daemon, so we have to give it a raw message. TODO: Fix
       -        [ "${IRC_CMD}" == "PRIVMSG" ] && printf "$(date +%s) <%s> %s\n" "$IRC_USER" "$IRC_PRIVMSG_TEXT" >> "${IRC_SERVERBASE}/${IRC_CHANNEL}/out"
       -        ;;
       +case "${IRC_SERVER}" in
       +*bitreich.org)
       +        case "${IRC_CHANNEL}" in
       +        \#bitreich-radio) annna-message-radio;;
       +        \#bitreich-wikigame) annna-message-wikigame;;
       +        \#bitreich-sauna) annna-message-sauna;;
       +        \#bitreich-idle);; # TODO: Fix idle service for new architecture.
       +        *) annna-message-common;;
       +        esac;;
        *) annna-message-common;;
        esac
        
 (DIR) diff --git a/annna-channel-service b/annna-channel-service
       @@ -1,63 +1,17 @@
        #!/bin/sh
       -#
       -# Per-IRC_CHANNEL daemon that monitors incoming messages from ii out script.
       -#
        
       -set -x
       -
       -pgrep -f "$0 $*" | grep -vxq "$$" && exec echo "$0 $* already running"
       -#trap 'exec pkill -U annna -f "entr .* ${PWD}/out"' INT TERM EXIT HUP
       -
       -case "${IRC_CHANNEL}" in
       -\#bitreich-idle)
       -        idlebase="${ANNNA_MODBASE}/idlerpg"
       -        $idlebase/idlerpg-channel-service.py \
       -                "${IRC_USER}" "${idlebase}" "${ANNNA_IRCBASE}" "${IRC_SERVER}" "${IRC_CHANNEL}" &
       -        exit $?
       -        ;;
       -\#bitreich-radio)
       -        radiobase="${ANNNA_MODBASE}/radio"
       -        $radiobase/radio-channel-service.sh \
       -                "${IRC_USER}" "${radiobase}" "${ANNNA_IRCBASE}" "${IRC_SERVER}" "${IRC_CHANNEL}" &
       -esac
       -
       -ls "${IRC_SERVERBASE}/${IRC_CHANNEL}/out" \
       -        | entr tail -n 1 "${IRC_SERVERBASE}/${IRC_CHANNEL}/out" 2>/dev/null \
       -        | {
       -while read -r line;
       -do
       -        secondword="$(printf "%s\n" "${line}" | cut -d' ' -f 2)"
       -        case "${secondword}" in
       -        "-!-")
       -                fifthword="$(printf "%s\n" "${line}" | cut -d' ' -f 5)"
       -                cmd=""
       -                # TODO: Add error, mode, nick, topic, kick, notice support.
       -                case "${fifthword}" in
       -                joined) cmd="JOIN";;
       -                left) cmd="PART";;
       -                quit) cmd="QUIT";;
       -                esac
       -                [ -z "$cmd" ] && break
       -                export IRC_CMD="${cmd}"
       -                export IRC_CMD_USER="$(printf "%s\n" "${line}" | cut -d' ' -f 3 | cut -d'(' -f 1)"
       -                export IRC_PRIVMSG_TEXT=""
       -                annna-channel-message
       -                ;;
       -        "<"*">")
       -                cmd="PRIVMSG"
       -                printf "%s\n" "${line}" \
       -                | sed -nu 's,[0-9]* <\([^ >]*\)> \(.*\),\1 \2,p' \
       -                | {
       -                while read -r user text;
       -                do
       -                        export IRC_PRIVMSG_TEXT="${text}"
       -                        export IRC_CMD="${cmd}"
       -                        export IRC_CMD_USER="${user}"
       -                        annna-channel-message
       -                done
       -                }
       +case "${IRC_SERVER}" in
       +*bitreich.org)
       +        case "${IRC_CHANNEL}" in
       +        \#bitreich-idle)
       +                export SERVICE_BASE="${ANNNA_MODBASE}/idlerpg"
       +                # TODO: Fix idle service for new architecture.
       +                # ${SERVICE_BASE}/idlerpg-channel-service.py &
       +                exit $?
                        ;;
       -        esac
       -done
       -}
       +        \#bitreich-radio)
       +                export SERVICE_BASE="${ANNNA_MODBASE}/radio"
       +                "${SERVICE_BASE}/radio-channel-service.sh" &
       +        esac;;
       +esac
        
 (DIR) diff --git a/annna-join-channels b/annna-join-channels
       @@ -1,47 +1,20 @@
        #!/bin/sh
        
       -# Do not expose this to channels.
       -export IRC_PASS=
       -
       -maxretries=32
        # Channels
       -for chan in ${IRC_CHANNELS};
       +for IRC_CHANNEL in ${IRC_CHANNELS};
        do
       -        export IRC_CHANNEL="${chan}"
       -        printf "/j %s\n" "${chan}" > "${IRC_SERVERBASE}/in"
       -        sleep 1
       +        printf "/j %s\n" "${IRC_CHANNEL}" > "${IRC_SERVERBASE}/in"
        
       -        ## Make sure the pipes are there.
       -        tries=0
       -        while [ ! -e "${IRC_SERVERBASE}/${chan}/out" ];
       -        do
       -                annna-alive || exit 1
       -                tries=$(($tries + 1))
       -                [ $tries -gt $maxretries ] && exit 1
       -                sleep 1
       -        done
       -
       -        tries=0
       -        while [ ! -e "${IRC_SERVERBASE}/${chan}/in" ];
       -        do
       -                annna-alive || exit 1
       -                tries=$(($tries + 1))
       -                [ $tries -gt $maxretries ] && exit 1
       -                sleep 1
       -        done
       +        # We are nice.
       +        sleep 1
        
       -        tries=0
       -        ## Check if we have joined and received the message from the IRC_SERVER.
       -        while [ -z "$(cat "${IRC_SERVERBASE}/${chan}/out" \
       -                        | head -n 1 \
       -                        | grep ".* ${IRC_USER}.* ${chan}.*")" ];
       -        do
       -                annna-alive || exit 1
       -                tries=$(($tries + 1))
       -                [ $tries -gt $maxretries ] && exit 1
       -                sleep 2
       -        done
       +        # Permissions for helpers.
       +        [ -d ${ANNNA_IRCBASE} ] && chmod o+rx ${ANNNA_IRCBASE}
       +        [ -d ${IRC_SERVERBASE} ] && chmod o+rx ${IRC_SERVERBASE}
       +        # annna-say
       +        [ -p "${IRC_SERVERBASE}/${IRC_CHANNEL}/in" ] \
       +                && chmod o+w "${IRC_SERVERBASE}/${IRC_CHANNEL}/in"
        
       -        annna-start-channel-service
       +        annna-channel-service
        done
        
 (DIR) diff --git a/annna-message-common b/annna-message-common
       @@ -1,11 +1,8 @@
        #!/bin/bash
        
       -set -x
       -
       -#printf "%s %s %s %s\n" "${0##*/}" "${IRC_CHANNEL}" "${IRC_CMD_USER}" "${IRC_PRIVMSG_TEXT}"
       -
        [ "${IRC_CMD_USER}" = "${IRC_USER}" ] && exit 0
        [ -z "${IRC_PRIVMSG_TEXT}" ] && exit 0
       +[ ! "$IRC_CMD" = "PRIVMSG" ] && exit 1
        
        hashtagfile="${ANNNA_MODBASE}/hashtags/hashtags.txt"
        idontcaredb="${ANNNA_MODBASE}/i-dont-care/i-dont-care.txt"
       @@ -2062,10 +2059,10 @@ done
        case "${IRC_PRIVMSG_TEXT}" in
        "${IRC_USER}, please go to sleep.")
                annna-say "Going to sleep ... Zzzz ..."
       -        touch "${ANNNA_BASE}/sleeping"
       +        annna-sleep-well
                ;;
        "${IRC_USER}, please wake up.")
       -        rm -f "${ANNNA_BASE}/sleeping"
       +        annna-wakeup
                annna-say "Good morning BITREICH!"
                ;;
        "${IRC_USER}, can you show me the uptime please?")
 (DIR) diff --git a/annna-message-radio b/annna-message-radio
       @@ -42,5 +42,5 @@ case "${IRC_PRIVMSG_TEXT}" in
                exit;;
        esac
        
       -annna-message-common "${IRC_SERVER}" "${IRC_CHANNEL}" "${IRC_CMD_USER}" "${IRC_PRIVMSG_TEXT}" "${IRC_CMD}"
       +annna-message-common
        
 (DIR) diff --git a/annna-restart-services b/annna-restart-services
       @@ -1,7 +0,0 @@
       -#!/bin/sh
       -
       -export PATH="$HOME/bin:$PATH"
       -
       -annna-stop-services
       -annna-start-services
       -
 (DIR) diff --git a/annna-say b/annna-say
       @@ -5,8 +5,6 @@
        # annna-say -c 'irc.bitreich.org/#bitreich-en' Hello World!
        #
        
       -set -x
       -
        usage() {
                printf "usage: %s [-h] [-a ANNNA_BASE] [-s IRC_SERVER] -c \"[IRC_SERVER/]channel0 ... [IRC_SERVER/]channel1 ...\" text\n" \
                        "$(basename "$1")" >&2
       @@ -56,25 +54,30 @@ do
                if [ -e "$ircpath/in" ];
                then
                        case "${outfile}" in
       -                "in")
       -                        printf "%s\n" "$@" | fold -w 250 -s > "${ircpath}/${outfile}"
       -                        ;;
       +                "in") printf "%s\n" "$@" | fold -w 250 -s > "${ircpath}/${outfile}";;
                        "out")
       -                        printf "%s <%s> %s\n" "$(date +%s)" "annna-cmd" "$@" \
       -                                         > "${ircpath}/${outfile}"
       +                        export IRC_PASS=
       +                        export IRC_CMD="PRIVMSG"
       +                        export IRC_CMD_USER="annna-cmd"
       +                        export IRC_PRIVMSG_TEXT="$@"
       +                        export IRC_SERVER="${cserver}"
       +                        annna-channel-message
                                ;;
                        esac
                else
                        ircpath="${ANNNA_IRCBASE}/${cserver}"
       -                # Might be a user. Do not bother with outfile, he/she is not in our control.
       -                printf "%s\n" "$@" \
       -                | fold -w 250 -s \
       -                | while read -r line;
       -                do
       -                        printf "/j %s %s\n" "$c" "$line" > "${ircpath}/in"
       -                done
       +                case "${outfile}" in
       +                "in")
       +                        printf "%s\n" "$@" \
       +                        | fold -w 250 -s \
       +                        | while read -r line;
       +                        do
       +                                printf "/j %s %s\n" "$c" "$line" > "${ircpath}/in"
       +                        done
       +                        ;;
       +                "out");; # We do not give users commands.
       +                esac
                fi
       -
        done
        
        exit 0
 (DIR) diff --git a/annna-sleep-well b/annna-sleep-well
       @@ -0,0 +1,44 @@
       +#!/bin/sh
       +#
       +# Sweet Dreams, Annna
       +# Verse 1
       +# Close your eyes, dear Annna, the stars are shining bright,
       +# Let the moonlight guide you to dreamland tonight.
       +# Whispers of the night breeze will sing you a song,
       +# Drifting off to slumber, where you truly belong.
       +#
       +# Chorus
       +# Dream of rainbows and soft, gentle skies,
       +# Where all your wishes can truly arise.
       +# With a heart full of magic and a spirit so free,
       +# Sleep tight, little Annna, just let it all be.
       +#
       +# Verse 2
       +# Clouds like pillows will cradle you so,
       +# Guarding your dreams as you gentle glow.
       +# The world's waiting for you with laughter and cheer,
       +# But for now, dear Annna, just stay close and near.
       +#
       +# Chorus
       +# Dream of rainbows and soft, gentle skies,
       +# Where all your wishes can truly arise.
       +# With a heart full of magic and a spirit so free,
       +# Sleep tight, little Annna, just let it all be.
       +#
       +# Bridge
       +# When dawn breaks softly and the sun starts to rise,
       +# You'll wake up refreshed, with joy in your eyes.
       +# But for now, dear Annna, let the night take you in,
       +# With dreams sweetly waiting, let the magic begin.
       +#
       +# Final Chorus
       +# Dream of rainbows and soft, gentle skies,
       +# Where all your wishes can truly arise.
       +# With a heart full of magic and a spirit so free,
       +# Sleep tight, little Annna, just let it all be.
       +#
       +# Sleep tight, dear Annna, the stars are your guide,
       +# With love all around you, there's nothing to hide.
       +
       +touch "${ANNNA_BASE}/sleeping"
       +
 (DIR) diff --git a/annna-sleeps b/annna-sleeps
       @@ -6,8 +6,6 @@
        # if annna-sleeps; then do-something; fi
        #
        
       -set -x
       -
        [ -f "${ANNNA_BASE}/sleeping" ] && exit 0
        exit 1 
        
 (DIR) diff --git a/annna-start b/annna-start
       @@ -27,8 +27,9 @@ export PATH="$PATH:${ANNNA_BINBASE}"
        
        cd "${ANNNA_BASE}"
        touch running
       -for server in $(find . -maxdepth 1 -type d | tail -n +2 | cut -c 3-);
       +for server in $(find . -maxdepth 1 -type d | cut -c 3-);
        do
       +        [ -z "$server" ] && continue
                export IRC_SERVER="${server}"
                [ ! -f ${server}/autoconnect ] && continue
                export IRC_CHANNELS="$(cat ${server}/channels | tr '\n' ' ')"
       @@ -43,6 +44,9 @@ do
                export IRC_NAME="Gode"
                [ -f ${server}/name ] && export IRC_NAME="$(cat ${server}/name)"
        
       -        annna-start-server
       +        annna-start-server &
       +        printf "%s\n" "$!" > "$IRC_SERVER.pid"
        done
        
       +printf "%s is ALIVE. Have fun! :-)\n" "${IRC_USER}"
       +
 (DIR) diff --git a/annna-start-channel-service b/annna-start-channel-service
       @@ -1,22 +0,0 @@
       -#!/bin/sh
       -
       -set -x
       -
       -# Permissions
       -[ -d ${ANNNA_IRCBASE} ] && chmod o+rx ${ANNNA_IRCBASE}
       -[ -d ${IRC_SERVERBASE} ] && chmod o+rx ${IRC_SERVERBASE}
       -## Channel handlers
       -[ -d "${IRC_SERVERBASE}/${IRC_CHANNEL}" ] \
       -        && chmod o+rx "${IRC_SERVERBASE}/${IRC_CHANNEL}"
       -# For annna-say.
       -[ -p "${IRC_SERVERBASE}/${IRC_CHANNEL}/in" ] \
       -        && chmod o+w "${IRC_SERVERBASE}/${IRC_CHANNEL}/in"
       -# For annna-cmd.
       -[ -f "${IRC_SERVERBASE}/${IRC_CHANNEL}/out" ] \
       -        && chmod o+w "${IRC_SERVERBASE}/${IRC_CHANNEL}/out"
       -
       -if [ -f "${IRC_SERVERBASE}/${IRC_CHANNEL}/out" ];
       -then
       -        annna-channel-service &
       -fi
       -
 (DIR) diff --git a/annna-start-checker b/annna-start-checker
       @@ -1,24 +0,0 @@
       -#!/bin/sh
       -#
       -# Watch for annna, she's worth it.
       -#
       -
       -export PATH="$PATH:/home/annna/bin"
       -
       -{
       -while /bin/true;
       -do
       -        # Is annna still in her world?
       -        iipid="$(pgrep -U annna -x ii)"
       -
       -        if [ -z "$iipid" ];
       -        then
       -                annna-stop-services >/dev/null 2>&1
       -                sleep 2
       -                annna-start-main >/dev/null 2>&1
       -        fi
       -
       -        sleep 5
       -done
       -} &
       -
 (DIR) diff --git a/annna-start-checker-dbg b/annna-start-checker-dbg
       @@ -1,25 +0,0 @@
       -#!/bin/sh
       -#
       -# Watch for annna, she's worth it.
       -#
       -
       -export PATH="$PATH:/home/annna/bin"
       -
       -while /bin/true;
       -do
       -        # Is annna still in her world?
       -        socatpid="$(pgrep -U annna -x socat)"
       -        iipid="$(pgrep -U annna -x ii)"
       -
       -        if [ -z "$socatpid" ] || [ -z "$iipid" ];
       -        then
       -                printf "checker: Starting annna.\n"
       -                sh -x annna-stop-socat
       -                sh -x annna-stop-services
       -                sh -x annna-start-main
       -        fi
       -
       -        printf "checker: sleeping 5 seconds.\n"
       -        sleep 5
       -done
       -
 (DIR) diff --git a/annna-start-server b/annna-start-server
       @@ -1,83 +1,59 @@
        #!/bin/sh
        
       -set -x
       -
       -maxtries=10
       -maxnicktries=5
       -#{
       -        nicktries=0
       -        iipid=0
       -        while annna-alive;
       +export IRC_SERVERBASE="${ANNNA_IRCBASE}/${IRC_SERVER}"
       +while annna-alive;
       +do
       +        rm -rf "${IRC_SERVERBASE}"
       +        mkdir -p "${IRC_SERVERBASE}"
       +
       +        [ $IRC_TLS -gt 0 ] && tlsparam=" -v -t"
       +        [ -n "${IRC_USER}" ] && ircuserparam=" -n ${IRC_USER}"
       +        ircpassparam=""
       +        [ -n "${IRC_PASS}" ] && ircpassparam=" -k IRC_PASS"
       +
       +        ii -s "${IRC_SERVER}"${ircpassparam}${ircuserparam}${tlsparam} \
       +                -f "${IRC_NAME}" -p ${IRC_PORT} 2>&1 \
       +        | while read -r servermsg;
                do
       -                export IRC_SERVERBASE="${ANNNA_IRCBASE}/${IRC_SERVER}"
       -                rm -rf "${IRC_SERVERBASE}"
       -                mkdir -p "${IRC_SERVERBASE}"
       -
       -                [ $IRC_TLS -gt 0 ] && tlsparam=" -v -t"
       -                [ -n "${IRC_USER}" ] && ircuserparam=" -n ${IRC_USER}"
       -                ircpassparam=""
       -                [ -n "${IRC_PASS}" ] && ircpassparam=" -k IRC_PASS"
       -                # For debugging.
       -                #ii -s "${IRC_SERVER}"${ircpassparam}${ircuserparam}${tlsparam} \
       -                #        -f "${fullname}" -p ${IRC_PORT} &
       -
       -                [ $iipid -gt 0 ] && kill -KILL $iipid >/dev/null 2>&1
       -                ii -s "${IRC_SERVER}"${ircpassparam}${ircuserparam}${tlsparam} \
       -                        -f "${IRC_NAME}" -p ${IRC_PORT} >/dev/null 2>&1 &
       -                #ii -s "${IRC_SERVER}"${ircpassparam}${ircuserparam}${tlsparam} \
       -                #        -f "${fullname}" -p ${IRC_PORT}
       -                iipid=$!
       -                sleep 5
       -
       -                tries=0
       -                ## Waiting for the socket to be available.
       -                while [ ! -e "${IRC_SERVERBASE}/out" ];
       -                do
       -                        kill -0 $iipid >/dev/null 2>&1 || exit 1
       -                        annna-alive || exit 1
       -                        tries=$(($tries + 1))
       -                        [ $tries -gt $maxtries ] && break
       -                        sleep 4
       -                done
       -                [ $tries -gt $maxtries ] && continue
       -
       -                # 433: Nickname is already in use.
       -                if [ -n "$(grep " 433 " "${IRC_SERVERBASE}/out")" ];
       -                then
       -                        nicktries=$(($nicktries + 1))
       -                        [ $nicktries -gt $maxnicktries ] && exit 3
       -                        sleep 30
       -                        continue
       -                fi
       -
       -                tries=0
       -                # Check for end of motd.
       -                while [ -z "$(grep " 376 " "${IRC_SERVERBASE}/out")" ];
       -                do
       -                        annna-alive || exit 1
       -                        # Sometimes the connection is too fast and the ii USER
       -                        # and NICK is slurped.
       -                        printf "USER %s\r\nUSER %s localhost %s :%s" \
       -                                "${IRC_USER}" "${IRC_USER}" "$(hostname)" \
       -                                "${IRC_NAME}" \
       -                                > "${ANNNA_IRCBASE}/${IRC_SERVER}/in"
       -                        tries=$(($tries + 1))
       -                        [ $tries -gt $maxtries ] && break
       -                        sleep 2
       -                done
       -                [ $tries -gt $maxtries ] && continue
       -
       -                #{
       -                        annna-join-channels
       -                #} &
       -
       -                # Watch for ii to exit. Then remove the used directory to have all
       -                # services disappear.
       -                while kill -0 $iipid >/dev/null 2>&1;
       -                do
       -                        sleep 30
       -                done
       -                rm -rf "${IRC_SERVERBASE}"
       +        annna-alive || exit 1
       +        export IRC_PASS=
       +        export IRC_CMD_USER="$(printf "%s\n" "${servermsg}" \
       +                | cut -d' ' -f 2 \
       +                | cut -d':' -f 2 \
       +                | cut -d'!' -f 1)"
       +        export IRC_CMD="$(printf "%s\n" "${servermsg}" \
       +                | cut -d' ' -f 3)"
       +        export IRC_PRIVMSG_TEXT=""
       +
       +        case "${IRC_CMD}" in
       +        "433") exit 1;; # Nickname in use.
       +        "001") annna-join-channels;; # Welcome.
       +        "NICK"|"353"|"332"|"PING");;
       +        "PART")
       +                export IRC_CHANNEL="$(printf "%s\n" "${servermsg}" \
       +                        | cut -d' ' -f 4)"
       +                annna-channel-message
       +                ;;
       +        "JOIN")
       +                export IRC_CHANNEL="$(printf "%s\n" "${servermsg}" \
       +                        | cut -d' ' -f 4 \
       +                        | cut -d':' -f 2-)"
       +                annna-channel-message
       +                ;;
       +        "PRIVMSG"|"NOTICE")
       +                export IRC_CHANNEL="$(printf "%s\n" "${servermsg}" \
       +                        | cut -d' ' -f 4)"
       +                export IRC_PRIVMSG_TEXT="$(printf "%s\n" "${servermsg}" \
       +                        | cut -d' ' -f 5- \
       +                        | cut -d':' -f 2- \
       +                        | sed -e 's,\r$,,')"
       +                annna-channel-message
       +                ;;
       +        esac
                done
       -#} &
       +
       +        rm -rf "${IRC_SERVERBASE}"
       +        [ ! -f "${IRC_SERVER}/reconnect" ] && break
       +        sleep 5
       +done
        
 (DIR) diff --git a/annna-start-services b/annna-start-services
       @@ -1,21 +0,0 @@
       -#!/bin/sh
       -
       -export PATH="$PATH:/home/annna/bin"
       -
       -#cfgbase="$(pwd)"
       -cfgbase="$HOME/annna"
       -touch ${cfgbase}/running
       -
       -cd ${cfgbase}
       -for server in $(find . -maxdepth 1 -type d | tail -n +2 | cut -c 3-);
       -do
       -        [ ! -f ${server}/autoconnect ] && continue
       -
       -        channels="$(cat ${server}/channels | tr '\n' ' ')"
       -
       -        for chan in ${channels};
       -        do
       -                annna-start-service "${server}" "${chan}"
       -        done
       -done
       -
 (DIR) diff --git a/annna-stop b/annna-stop
       @@ -3,12 +3,26 @@
        # Dare you to execute this script! You are cruel!
        #
        
       -export PATH="$PATH:/home/annna/bin"
       +if [ $# -lt 1 ];
       +then
       +        printf "usage: %s cfgdir\n" "$(basename "$0")" >&2
       +        exit 1
       +fi
        
       -cfgbase="$HOME/annna"
       -[ -f "${cfgbase}/running" ] && rm -f "${cfgbase}/running"
       +export ANNNA_BASE="$1"
       +[ ! -d "${ANNNA_BASE}" ] && printf "%s not a directory.\n" "${ANNNA_BASE}" >&2 && exit 1
       +[ ! -e "${ANNNA_BASE}/binbase" ] && printf "No /binbase exists.\n" >&2 && exit 1
       +export ANNNA_BINBASE="$(cat "${ANNNA_BASE}/binbase")"
       +[ ! -d "${ANNNA_BINBASE}" ] && printf "%s not a directory.\n" "${ANNNA_BINBASE}" >&2 && exit 1
       +export PATH="$PATH:${ANNNA_BINBASE}"
        
       -annna-stop-ii
       -annna-stop-checker
       -annna-stop-services
       +annna-die
       +cd "${ANNNA_BASE}"
       +for pidfile in $(find . -maxdepth 1 -type f -name "*.pid" | cut -c 3-);
       +do
       +        serverpid="$(cat "${pidfile}")"
       +        [ -z "${serverpid}" ] && continue
       +        kill -0 "${serverpid} && kill -KILL "${serverpid}"
       +        rm "${pidfile}"
       +done
        
 (DIR) diff --git a/annna-stop-checker b/annna-stop-checker
       @@ -1,6 +0,0 @@
       -#!/bin/sh
       -
       -export PATH="$PATH:/home/annna/bin"
       -
       -pkill -KILL -U annna -f annna-checker
       -
 (DIR) diff --git a/annna-stop-ii b/annna-stop-ii
       @@ -1,4 +0,0 @@
       -#!/bin/sh
       -
       -pkill ii
       -
 (DIR) diff --git a/annna-stop-services b/annna-stop-services
       @@ -1,7 +0,0 @@
       -#!/bin/sh
       -
       -pkill -f "entr tail -n 1 /home/annna/irc.*"
       -pkill -f "annna-channel-service"
       -pkill -f "idlerpg-channel-service.py"
       -pkill -f "radio-channel-service.sh"
       -
 (DIR) diff --git a/annna-wakeup b/annna-wakeup
       @@ -0,0 +1,4 @@
       +#!/bin/sh
       +
       +rm -f "${ANNNA_BASE}/sleeping"
       +
 (DIR) diff --git a/modules/radio/radio-channel-service.sh b/modules/radio/radio-channel-service.sh
       @@ -1,29 +1,12 @@
        #!/bin/sh
        
       -export PATH="/home/annna/bin:$PATH"
       -
       -ircuser="$1"
       -radiobase="$2"
       -ircbase="$3"
       -server="$4"
       -channel="$5"
       -
       -# Wait for mpd to be alive.
       -while /bin/true;
       +while annna-alive;
        do
       -        while ! mpc -q;
       -        do
       -                sleep 5
       -        done
       -
       -        while mpc -q;
       -        do
       -                currentsong="$(mpc current --wait)"
       -                if [ -n "${currentsong}" ];
       -                then
       -                        annna-say -s "${server}" -c "${channel}" "Now playing: ${currentsong}"
       -                fi
       -        done
       +        currentsong="$(mpc current --wait)"
       +        annna-alive || exit 0
       +        [ -n "${currentsong}" ] && annna-say "Now playing: ${currentsong}"
                sleep 5
        done
        
       +exit 0
       +