#!/bin/bash # MBB - MyBashBot # ChangeLog see file CHANGELOG included in distribution ### LOCATION OF THE CONFIGFILE ### #export MBB_CONFIG="/home/bonsai/etc/mbb.conf" export MBB_CONFIG="/home/bonsai/devel/bash-scripts/irc-bot/MyBashBot/mbb.conf" ### ERROR CODES ### export ERR_MBB_NOERR=0 export ERR_MBB_CFG_NXFILE=100 export ERR_MBB_CFG_NXKEYWORD=101 export ERR_MBB_CMDPLGIN_NOPLUGIN=110 function _mbb_getconfentry() { local KEYWORD="$1" ### check if $MBB_CONFIG is a valid file, else return if [ ! -e "$MBB_CONFIG" ]; then return $ERR_MBB_CFG_NXFILE fi if (grep -i "^${KEYWORD} " ${MBB_CONFIG} >/dev/null 2>&1); then CONTENT=`grep -i "^${KEYWORD} " ${MBB_CONFIG} | sed -n -e 's/^[^ ]\+ \(.*\)$/\1/p'` echo ${CONTENT} return $ERR_MBB_NOERR else return $ERR_MBB_CFG_NXKEYWORD fi } export -f _mbb_getconfentry function _mbb_displayhelpscreen() { cat <&7 if !(echo "${MBB_COMMANDHANDLERS}" | grep " ${CMD} " >/dev/null 2>&1); then # CMD not in list of registered plugins return $ERR_MBB_CMDPLGIN_NOPLUGIN else # CMD is in list of registeres plugins _mbb_commandhandler_${CMD} "${SOURCE}" "${TARGET}" "${CMDARGS}" & return $ERR_MBB_NOERROR fi } export -f _mbb_callcommandhandler function _mbb_getnickfromident() { local IDENT="$1" NICK="`echo "${IDENT}" | sed -n -e 's/\([^!]\)!.*$/\1/p'`" echo "${NICK}" } export -f _mbb_getnickfromident function _mbb_gettargetfromPRIVMSGmessage() { local MSG="$1" TARGET="`echo "$MSG" | sed -n -e 's/^\([^ ]\+\) .*$/\1/p'`" echo "$TARGET" } function _mbb_getmessagefromPRIVMSGmessage() { local MSG="$1" MESSAGE="`echo "${MSG}" | sed -n -e 's/^[^ ]\+ :\(.*\)/\1/p'`" echo "${MESSAGE}" } export -f _mbb_gettargetfromPRIVMSGmessage _mbb_getmessagefromPRIVMSGmessage ### MAIN ### export MBB_VERSION="0.2" while [ ! -z "$1" ]; do case "$1" in --configfile|-f) export MBB_CONFIG="$2" shift 2 ;; --help|-h) _mbb_displayhelpscreen exit 0 ;; --version|-V) echo "MyBashBot V${MBB_VERSION}" exit 0 ;; *) echo "unknown argument: $1" _mbb_displayhelpscreen exit 1 ;; esac done export BOTNICK=`_mbb_getconfentry BotNick` export BOTUSER=`_mbb_getconfentry BotUser` export BOTRNAME=`_mbb_getconfentry RealName` export BOTSRV=`_mbb_getconfentry Server` export SVRPORT=`_mbb_getconfentry ServerPort` export BOTCHAN=`_mbb_getconfentry Channel` export PLUGINSDIR=`_mbb_getconfentry PluginsDir` export OPLIST=`_mbb_getconfentry Channel` export OWNPID=$$ # source the plugins # plugins MUSTS: # be in a file called .cmdplugin in the $PLUGINSDIR # define and export a function named _mbb_commandhandler_${COMMANDNAME}, where commandname is the string between "^!" and " ", the bot may recieve # call the _mbb_registercommandhandler with the name of the COMMAND to register # e.g. to register the command "op", the function must be named _mbb_commandhandler_op and must be registered with _mbb_registercommandhandler "op" # then it will be called with _mbb_commandhandler_op # when the string "^!op" appears in a PRIVMSG recieved by the bot. echo DEBUG: ${PLUGINSDIR} for i in ${PLUGINSDIR}/*.cmdplugin; do source $i echo $i done # save FD#0 (stdin) to FD#6 and FD#1 (stdout) to FD#7 exec 6<&0 exec 7>&1 # open the socket, redirect stdin and stdout to that socket (to use old in/out use the filedescriptors above) SOCKET="/dev/tcp/${BOTSRV}/${SVRPORT}" exec >$SOCKET exec <&1 # login procedure echo DEBUG: "USER ${BOTUSER} 0 * : ${BOTRNAME}\r\n" >&7 echo -en "NICK ${BOTNICK}\r\n" echo -en "USER ${BOTUSER} 0 * : ${BOTRNAME}\r\n" #echo -en "JOIN ${BOTCHAN}\r\n" # sort of main() loop ;) while read SERVERINPUT; do # remove the odd \r's specified in RFC's SERVERINPUT="`echo "$SERVERINPUT" | tr -d '\r'`" #echo "---DEBUG: ${SERVERINPUT}" >&7 if (echo "$SERVERINPUT" | grep "^:" >/dev/null 2>&1); then # normal message ": " : ORIGIN="`echo "$SERVERINPUT" | sed -n -e 's/^:\([^ ]\+\) .*$/\1/p'`" COMMAND="`echo "$SERVERINPUT" | sed -n -e 's/^:[^ ]\+ \([^ ]\+\) .*$/\1/p'`" CMDARGS="`echo "$SERVERINPUT" | sed -n -e 's/^[^ ]\+ [^ ]\+ \(.*\)$/\1/p'`" echo "---DEBUG: ${COMMAND} from ${ORIGIN} is \"${CMDARGS}\"" >&7 # ---DEBUG: PRIVMSG from TheBonsai!~bonsai@pD9E0C2B1.dip.t-dialin.net is "#botchan :!teststring" case "$COMMAND" in [Nn][Oo][Tt][Ii][Cc][Ee]) # NOTICE echo " ${CMDARGS}" >&7 ;; [Pp][Rr][Ii][Vv][Mm][Ss][Gg]) # PRIVMSG ORIGINNICK="`_mbb_getnickfromident "$ORIGIN"`" MSGTARGET="`_mbb_gettargetfromPRIVMSGmessage "$CMDARGS"`" MSGBODY="`_mbb_getmessagefromPRIVMSGmessage "$CMDARGS"`" echo "<$ORIGINNICK -> $MSGTARGET> $MSGBODY" >&7 if (echo "$MSGBODY" | grep "^\!" >/dev/null 2>&1); then # the MSGBODY is "!......", which is probably a command to the mbb MSGBODY="${MSGBODY} " echo "---MESSAGEBODY is \"${MSGBODY}\"" >&7 BOTCOMMAND=`echo "$MSGBODY" | sed -n -e 's/^\!\([^ ]\+\) .*$/\1/p'` CMDBODY=`echo "$MSGBODY" | sed -n -e 's/^\![^ ]\+ \(.*\)$/\1/p'` echo "---BOT TRIGGERED with \"${BOTCOMMAND}\"" >&7 echo "---where CMDBODY is \"${CMDBODY}\"" >&7 _mbb_callcommandhandler "$BOTCOMMAND" "$CMDBODY" "$ORIGINNICK" "$MSGTARGET" case "$?" in $ERR_MBB_NOERROR) ;; $ERR_MBB_CMDPLGIN_NOPLUGIN) echo -en "PRIVMSG ${MSGTARGET} :from plugin handler: no such plugin (${BOTCOMMAND})\r\n" ;; esac fi if (echo "$MSGBODY" | grep "${BOTNICK}" >/dev/null 2>&1); then echo -en "PRIVMSG ${MSGTARGET} :${ORIGINNICK}, hm?\r\n" fi ;; [Jj][Oo][Ii][Nn]) ORIGINNICK="`_mbb_getnickfromident "$ORIGIN"`" echo -en "PRIVMSG ${MSGTARGET} :Hallo sagen kann jeder... Hallo ${ORIGINNICK} *bleh*\r\n" ;; 37[526]) # RPL_MOTDSTART, RPL_MOTD, RPL_MOTDEND echo " ${CMDARGS}" >&7 ;; 001) # RPL_WELCOME echo "${ORIGIN} welcomes us, joining ${BOTCHAN}" >&7 echo -en "JOIN ${BOTCHAN}\r\n" ;; esac else # message with COMMAND as first argument, message format is now COMMAND [params] (->RFC2812) COMMAND="`echo "$SERVERINPUT" | sed -n -e 's/^\([^ ]\+\) .*$/\1/p'`" CMDARGS="`echo "$SERVERINPUT" | sed -n -e 's/^[^ ]\+ :\(.*\)$/\1/p'`" case "$COMMAND" in [Pp][Ii][Nn][Gg]) echo "PING requested by ${CMDARGS} --> PONG :${CMDARGS}" >&7 echo -en "PONG :${CMDARGS}\r\n" ;; [Ee][Rr][Rr][Oo][Rr]) echo "ERROR sent from server, params: \"${CMDARGS}\"" >&7 ;; *) echo "Currently unknown or misparsed command from server: \"${COMMAND}\" with parameters \"${CMDARGS}\"" >&7 ;; esac fi done