Skip to content

Instantly share code, notes, and snippets.

@malobre
Created September 17, 2016 22:38
Show Gist options
  • Save malobre/1fd79c6910eac52a1ba3d716d753e868 to your computer and use it in GitHub Desktop.
Save malobre/1fd79c6910eac52a1ba3d716d753e868 to your computer and use it in GitHub Desktop.
Teamspeak 3 AFK bot, move clients to the specified channel when they are muted for more than the specified period of time and move them back when they unmute themself.
#!/bin/bash
#
# ts3server-bot.sh
#
# Teamspeak 3 AFK bot, move clients to the specified channel when they are muted
# for more than the specified period of time and move them back when they unmute
# themself.
#
# Copyright 2016, Malobre.
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice and this
# notice are preserved. This file is offered as-is, without any warranty.
ts_serverID="1"
ts_serverQueryHost="localhost"
ts_serverQueryPort="10011"
ts_serverQueryUser="queryUser"
ts_serverQueryPass="queryPass"
ts_afkChannelId="1"
ts_idleTimeBeforeMove="30"
sendCommand() {
echo "${1}" > inpipe
response=""
while read -r tmp; do
if [[ "${tmp}" =~ error\ id=([0-9]+)\ msg=(.*) ]]; then
errorId=${BASH_REMATCH[1]}
errorMsg=${BASH_REMATCH[2]}
if [[ errorId -ne 0 ]]; then
echo "Error ${errorId}: $(sed "s/\\\s/ /g" <<< "${errorMsg}")"
fi
break
fi
response="${response} $(echo "${tmp}" | tr -d "\r")"
done
}
if [[ ! -p inpipe ]]; then mkfifo inpipe; fi
sleep infinity > inpipe &
nc -v $ts_serverQueryHost $ts_serverQueryPort < inpipe | {
sendCommand "use $ts_serverID"
sendCommand "login $ts_serverQueryUser $ts_serverQueryPass"
sendCommand "clientupdate client_nickname=AFK\sbot"
while true; do
sleep 1
sendCommand "clientlist -voice"
clientsConnected=()
while read -r client; do
if [[ ! $client =~ clid=([0-9]+).*cid=([0-9]+).*client_nickname=([^ ]+).*client_output_muted=([01]) ]]; then continue; fi
clid=${BASH_REMATCH[1]}
cid=${BASH_REMATCH[2]}
client_nickname="$(sed "s/\\\s/ /g" <<< "${BASH_REMATCH[3]}")"
client_output_muted=${BASH_REMATCH[4]}
clientsConnected[${clid}]=${clid}
if [[ $client_output_muted -eq 1 ]]; then
if [[ $cid -ne $ts_afkChannelId ]]; then
if [[ ! ${clientsIdleTime[${clid}]+foobar} ]]; then clientsIdleTime[${clid}]=$(date +%s); fi
if [[ $(($(date +%s) - clientsIdleTime[clid])) -ge $ts_idleTimeBeforeMove ]]; then
clientsLastChannel[${clid}]=$cid
echo "Moving ${client_nickname} to channel ${ts_afkChannelId} after $(($(date +%s) - clientsIdleTime[clid])) seconds of inactivity."
sendCommand "clientmove clid=${clid} cid=${ts_afkChannelId}"
unset "clientsIdleTime[${clid}]"
fi
elif [[ ${clientsIdleTime[${clid}]+foobar} ]]; then
unset "clientsIdleTime[${clid}]"
fi
elif [[ ${clientsLastChannel[${clid}]+foobar} ]] && [[ ${clientsLastChannel[${clid}]} -ne $cid ]]; then
echo "${client_nickname} is not AFK anymore, moving back."
sendCommand "clientmove clid=${clid} cid=${clientsLastChannel[${clid}]}"
unset "clientsLastChannel[${clid}]"
fi
done < <(echo "${response}" | tr "|" "\n")
for clid in "${!clientsIdleTime[@]}"; do
if [[ ! "${clientsConnected[@]}" =~ ${clid} ]]; then
unset "clientsIdleTime[${clid}]"
unset "clientsLastChannel[${clid}]"
fi
done
done
} || true
pkill -TERM -P $$
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment