start 0.98 dev, create botconfig db

This commit is contained in:
Kay Marquardt (Gnadelwartz) 2020-06-12 21:18:32 +02:00
parent a8fe17882c
commit 8affc94813
2 changed files with 85 additions and 55 deletions

View File

@ -11,7 +11,7 @@
# This file is public domain in the USA and all free countries. # This file is public domain in the USA and all free countries.
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying) # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
# #
#### $$VERSION$$ v0.96-0-g3871ca9 #### $$VERSION$$ v0.98-dev-0-ga8fe178
# #
# Exit Codes: # Exit Codes:
# - 0 sucess (hopefully) # - 0 sucess (hopefully)
@ -69,6 +69,12 @@ Array2Json() {
printf '["%s"]\t"%s"\n' "${key//,/\",\"}" "${ARRAY[${key}]//\"/\\\"}" printf '["%s"]\t"%s"\n' "${key//,/\",\"}" "${ARRAY[${key}]//\"/\\\"}"
done done
} }
getConfigKey() {
[[ "$1" =~ ^[-a-zA-Z0-9,._]+$ ]] || return 3
declare -A confARR
Json2Array "confARR" <"${BOTDATABASE}.jssh"
printf '%s' "${confARR["$1"]}"
}
# get location and name of bashbot.sh # get location and name of bashbot.sh
SCRIPT="$0" SCRIPT="$0"
@ -108,6 +114,7 @@ if [ ! -w "." ]; then
fi fi
# Setup and check environment if BOTTOKEN is NOT set # Setup and check environment if BOTTOKEN is NOT set
BOTDATABASE="${BASHBOT_ETC:-.}/botconfig"
TOKENFILE="${BASHBOT_ETC:-.}/token" TOKENFILE="${BASHBOT_ETC:-.}/token"
BOTADMIN="${BASHBOT_ETC:-.}/botadmin" BOTADMIN="${BASHBOT_ETC:-.}/botadmin"
BOTACL="${BASHBOT_ETC:-.}/botacl" BOTACL="${BASHBOT_ETC:-.}/botacl"
@ -119,13 +126,22 @@ LOGDIR="${RUNDIR:-.}/logs"
if [ ! -d "${LOGDIR}" ] || [ ! -w "${LOGDIR}" ]; then if [ ! -d "${LOGDIR}" ] || [ ! -w "${LOGDIR}" ]; then
LOGDIR="${RUNDIR:-.}" LOGDIR="${RUNDIR:-.}"
fi fi
DEBUGLOG="${LOGDIR}/DEBUG.log"
ERRORLOG="${LOGDIR}/ERROR.log" ERRORLOG="${LOGDIR}/ERROR.log"
UPDATELOG="${LOGDIR}/UPDATE.log"
# we assume everthing is already set up correctly if we have TOKEN # we assume everthing is already set up correctly if we have TOKEN
if [ -z "${BOTTOKEN}" ]; then if [ -z "${BOTTOKEN}" ]; then
# BOTTOKEN empty read from file # DATABASE does not exist, create
if [ ! -f "${TOKENFILE}" ]; then [ ! -f "${BOTDATABASE}.jssh" ] &&
if [ -z "${CLEAR}" ] && [ "$1" != "init" ]; then printf '["bot_config_key"]\t"config_key_value"\n' >"${BOTDATABASE}.jssh"
# BOTTOKEN empty read ask user
if ! grep -qs '\["bottoken"\]' "${BOTDATABASE}.jssh" ; then
# convert old token
if [ -r "${TOKENFILE}" ]; then
printf '["bottoken"]\t"%s"\n' "$(< "${TOKENFILE}")" >>"${BOTDATABASE}.jssh"
# no old token avalible ask user
elif [ -z "${CLEAR}" ] && [ "$1" != "init" ]; then
echo "Running headless, set BOTTOKEN or run ${SCRIPT} init first!" echo "Running headless, set BOTTOKEN or run ${SCRIPT} init first!"
exit 2 exit 2
else else
@ -133,12 +149,9 @@ if [ -z "${BOTTOKEN}" ]; then
echo -e "${RED}TOKEN MISSING.${NC}" echo -e "${RED}TOKEN MISSING.${NC}"
echo -e "${ORANGE}PLEASE WRITE YOUR TOKEN HERE OR PRESS CTRL+C TO ABORT${NC}" echo -e "${ORANGE}PLEASE WRITE YOUR TOKEN HERE OR PRESS CTRL+C TO ABORT${NC}"
read -r BOTTOKEN read -r BOTTOKEN
printf '%s\n' "${BOTTOKEN}" > "${TOKENFILE}" printf '["bottoken"]\t"%s"\n' "${BOTTOKEN}" >> "${BOTDATABASE}.jssh"
fi fi
fi fi
# read BOTTOKEN from file and removen everyting from first newline to end
BOTTOKEN="$(< "${TOKENFILE}")"
BOTTOKEN="${BOTTOKEN%%$'\n'*}"
# setup botadmin file # setup botadmin file
if [ ! -f "${BOTADMIN}" ]; then if [ ! -f "${BOTADMIN}" ]; then
@ -186,10 +199,9 @@ if [ -z "${BOTTOKEN}" ]; then
fi fi
fi fi
# do we have BSD sed # read BOTTOKEN from bot database if not set
if ! sed '1ia' </dev/null 2>/dev/null; then [ -z "${BOTTOKEN}" ] && BOTTOKEN="$(getConfigKey "bottoken")"
echo -e "${ORANGE}Warning: You may run on a BSD style system without gnu utils ...${NC}"
fi
# BOTTOKEN format checks # BOTTOKEN format checks
if [[ ! "${BOTTOKEN}" =~ ^[0-9]{8,10}:[a-zA-Z0-9_-]{35}$ ]]; then if [[ ! "${BOTTOKEN}" =~ ^[0-9]{8,10}:[a-zA-Z0-9_-]{35}$ ]]; then
echo -e "${ORANGE}Warning, your bottoken may incorrect. it should have the following format:${NC}" echo -e "${ORANGE}Warning, your bottoken may incorrect. it should have the following format:${NC}"
@ -213,6 +225,9 @@ ME_URL=$URL'/getMe'
UPD_URL=$URL'/getUpdates?offset=' UPD_URL=$URL'/getUpdates?offset='
GETFILE_URL=$URL'/getFile' GETFILE_URL=$URL'/getFile'
#################
# BASHBOT COMMON functions
declare -rx SCRIPT SCRIPTDIR MODULEDIR RUNDIR ADDONDIR TOKENFILE BOTADMIN BOTACL DATADIR COUNTFILE declare -rx SCRIPT SCRIPTDIR MODULEDIR RUNDIR ADDONDIR TOKENFILE BOTADMIN BOTACL DATADIR COUNTFILE
declare -rx BOTTOKEN URL ME_URL UPD_URL GETFILE_URL declare -rx BOTTOKEN URL ME_URL UPD_URL GETFILE_URL
@ -245,14 +260,17 @@ done
# BASHBOT INTERNAL functions # BASHBOT INTERNAL functions
# #
# do we have BSD sed
if ! sed '1ia' </dev/null 2>/dev/null; then
echo -e "${ORANGE}Warning: You may run on a BSD style system without gnu utils ...${NC}"
fi
#jsonDB is now mandatory #jsonDB is now mandatory
if ! _is_function jssh_newDB ; then if ! _is_function jssh_newDB ; then
echo -e "${RED}ERROR: Mandatory module jsonDB is missing or not readable!" echo -e "${RED}ERROR: Mandatory module jsonDB is missing or not readable!"
exit 6 exit 6
fi fi
#################
# BASHBOT COMMON functions
# $1 URL, $2 filename in DATADIR # $1 URL, $2 filename in DATADIR
# outputs final filename # outputs final filename
download() { download() {
@ -328,11 +346,11 @@ if [ -z "${BASHBOT_WGET}" ] && _exists curl ; then
if [ -n "$5" ]; then if [ -n "$5" ]; then
# shellcheck disable=SC2086 # shellcheck disable=SC2086
res="$("${BASHBOT_CURL}" -s -k ${BASHBOT_CURL_ARGS} "$4" -F "chat_id=$1"\ res="$("${BASHBOT_CURL}" -s -k ${BASHBOT_CURL_ARGS} "$4" -F "chat_id=$1"\
-F "$2=@$3;${3##*/}" -F "caption=$5" | "${JSONSHFILE}" -s -b -n )" -F "$2=@$3;${3##*/}" -F "caption=$5" | "${JSONSHFILE}" -s -b -n 2>/dev/null )"
else else
# shellcheck disable=SC2086 # shellcheck disable=SC2086
res="$("${BASHBOT_CURL}" -s -k ${BASHBOT_CURL_ARGS} "$4" -F "chat_id=$1"\ res="$("${BASHBOT_CURL}" -s -k ${BASHBOT_CURL_ARGS} "$4" -F "chat_id=$1"\
-F "$2=@$3;${3##*/}" | "${JSONSHFILE}" -s -b -n )" -F "$2=@$3;${3##*/}" | "${JSONSHFILE}" -s -b -n 2>/dev/null )"
fi fi
sendJsonResult "${res}" "sendUpload (curl)" "$@" sendJsonResult "${res}" "sendUpload (curl)" "$@"
} }
@ -514,15 +532,13 @@ process_client() {
# process per message type # process per message type
if [ -z "${iQUERY[ID]}" ]; then if [ -z "${iQUERY[ID]}" ]; then
MESSAGE[0]="$(JsonDecode "${UPD["result",${num},"message","text"]}" | sed 's#\\/#/#g')"
process_message "${num}" "${debug}" process_message "${num}" "${debug}"
[[ -n "${debug}" ]] && printf "%s: update received FROM=%s CHAT=%s CMD=%s\n"\ printf "%s: update received FROM=%s CHAT=%s CMD=%s\n" "$(date)" "${USER[USERNAME]:0:20} (${USER[ID]})"\
"$(date)" "${USER[USERNAME]:0:20} (${USER[ID]})"\ "${CHAT[USERNAME]:0:20}${CHAT[TITLE]:0:30} (${CHAT[ID]})" "${MESSAGE:0:30}" >>"${UPDATELOG}"
"${CHAT[USERNAME]:0:20}${CHAT[TITLE]:0:30} (${CHAT[ID]})" "${MESSAGE%%[ \?]*}"
else else
process_inline "${num}" "${debug}" process_inline "${num}" "${debug}"
[[ -n "${debug}" ]] && printf "%s: iQuery received FROM=%s iQUERY=%s\n"\ printf "%s: iQuery received FROM=%s iQUERY=%s\n" "$(date)"\
"$(date)" "${iQUERY[USERNAME]} (${iQUERY[USER_ID]})" "${iQUERY[0]}" "${iQUERY[USERNAME]:0:20} (${iQUERY[USER_ID]})" "${iQUERY[0]}" >>"${UPDATELOG}"
fi fi
##### #####
# process inline and message events # process inline and message events
@ -673,6 +689,7 @@ process_inline() {
process_message() { process_message() {
local num="$1" local num="$1"
# Message # Message
MESSAGE[0]="$(JsonDecode "${UPD["result",${num},"message","text"]}" | sed 's#\\/#/#g')"
MESSAGE[ID]="${UPD["result",${num},"message","message_id"]}" MESSAGE[ID]="${UPD["result",${num},"message","message_id"]}"
# Chat ID is now parsed when update isreceived # Chat ID is now parsed when update isreceived
@ -791,8 +808,8 @@ start_bot() {
local stepsleep="${BASHBOT_SLEEP_STEP:-100}" local stepsleep="${BASHBOT_SLEEP_STEP:-100}"
local maxsleep="${BASHBOT_SLEEP:-5000}" local maxsleep="${BASHBOT_SLEEP:-5000}"
# redirect to Debug.log # redirect to Debug.log
[[ "${DEBUG}" == *"debug" ]] && exec &>>"${LOGDIR}/DEBUG.log" printf "%s: Start BASHBOT updates in Mode \"%s\" ==========\n" "$(date)" "${DEBUG}" >>"${DEBUGLOG}"
[ -n "${DEBUG}" ] && printf "%s: Start BASHBOT in Mode \"%s\" ==========\n" "$(date)" "${DEBUG}" [[ "${DEBUG}" == *"debug" ]] && exec &>>"${DEBUGLOG}"
[[ "${DEBUG}" == "xdebug"* ]] && set -x [[ "${DEBUG}" == "xdebug"* ]] && set -x
#cleaup old pipes and empty logfiles #cleaup old pipes and empty logfiles
find "${DATADIR}" -type p -delete find "${DATADIR}" -type p -delete
@ -826,7 +843,7 @@ start_bot() {
# did we ge an responsn0r # did we ge an responsn0r
if [ -n "${UPDATE}" ]; then if [ -n "${UPDATE}" ]; then
# we got something, do processing # we got something, do processing
[ "${OFFSET}" = "-999" ] && [ "${nextsleep}" -gt "${maxsleep}" ] &&\ [ "${OFFSET}" = "-999" ] && [ "${nextsleep}" -gt "$((maxsleep*2))" ] &&\
printf "%s: Recovered from timeout/broken/no connection, continue with telegram updates\n"\ printf "%s: Recovered from timeout/broken/no connection, continue with telegram updates\n"\
"$(date)" >>"${ERRORLOG}" "$(date)" >>"${ERRORLOG}"
# escape bash $ expansion bug # escape bash $ expansion bug
@ -908,18 +925,6 @@ if [ ! -f "${JSONSHFILE}" ]; then
chmod +x "${JSONSHFILE}" chmod +x "${JSONSHFILE}"
fi fi
if [ "${SOURCE}" != "yes" ] && [ "$1" != "init" ] && [ "$1" != "help" ]; then
ME="$(getBotName)"
if [ -z "$ME" ]; then
echo -e "${RED}ERROR: Can't connect to Telegram! Your TOKEN is invalid or you are blocked by ${URL%/*} ...${NC}"
case "$1" in
"" | "stop" | "kill"* | "suspendb"* ) # warn, but do not exit
echo -e "${RED}Ignored to continue for $1 ... ${NC}";;
*) exit 1;;
esac
fi
fi
# source the script with source as param to use functions in other scripts # source the script with source as param to use functions in other scripts
# do not execute if read from other scripts # do not execute if read from other scripts
@ -928,33 +933,52 @@ if [ "${SOURCE}" != "yes" ]; then
############## ##############
# internal options only for use from bashbot and developers # internal options only for use from bashbot and developers
case "$1" in case "$1" in
"outproc") # forward output from interactive and jobs to chat # all these commands need the botname and a working connection
[ -z "$3" ] && echo "No file to read from" && exit 3 "botname"|"outproc"|"start"*|"stop"*|"kill"*|"resume"*|"suspend"*)
ME="$(getBotName)"
if [ -n "${ME}" ]; then
# ok we have a connection an got botname, save it
echo -e "${GREY}Bottoken is valid ...${NC}"
jssh_updateKeyDB "botname" "${ME}" "${BOTDATABASE}"
rm -f "${BOTDATABASE}.jssh.flock"
else
echo -e "${GREY}Info: Can't get Botname from Telegram, try cached one ...${NC}"
ME="$(getConfigKey "botname")"
if [ -z "$ME" ]; then
echo -e "${RED}ERROR: No cached botname, can't continue! ...${NC}"
exit 1
fi
fi
set +x
printf "Bot Name: %s\n" "${ME}"
SESSION="${ME:-_bot}-startbot"
BOTPID="$(proclist "${SESSION}")"
[ "$1" = "botname" ] && exit
;&
# used to send output of backgrond and interactive to chats
"outproc") # $2 chat_id $3 identifier of job, internal use only!
[ -z "$3" ] && echo "No job identifier" && exit 3
[ -z "$2" ] && echo "No chat to send to" && exit 3 [ -z "$2" ] && echo "No chat to send to" && exit 3
# read until terminated
while read -r line ;do while read -r line ;do
[ -n "$line" ] && send_message "$2" "$line" [ -n "$line" ] && send_message "$2" "$line"
done done
# cleanup datadir, keep logfile if not empty
rm -f -r "${DATADIR:-.}/$3" rm -f -r "${DATADIR:-.}/$3"
[ -s "${DATADIR:-.}/$3.log" ] || rm -f "${DATADIR:-.}/$3.log" [ -s "${DATADIR:-.}/$3.log" ] || rm -f "${DATADIR:-.}/$3.log"
exit exit
;; ;;
# finally starts the read update loop, internal use only1
"startbot" ) "startbot" )
start_bot "$2" start_bot "$2"
exit exit
;; ;;
"init") # adjust users and permissions # run after every update to update files and adjust permissions
"init")
bot_init "$2" bot_init "$2"
exit exit
;; ;;
esac # print usage sats
###############
# "official" arguments as shown to users
SESSION="${ME:-unknown}-startbot"
BOTPID="$(proclist "${SESSION}")"
case "$1" in
"stats"|'count') "stats"|'count')
declare -A STATS declare -A STATS
jssh_readDB_async "STATS" "${COUNTFILE}" jssh_readDB_async "STATS" "${COUNTFILE}"
@ -970,6 +994,7 @@ if [ "${SOURCE}" != "yes" ]; then
echo "A total of ${MESSAGES} messages from ${USERS} users are processed." echo "A total of ${MESSAGES} messages from ${USERS} users are processed."
exit exit
;; ;;
# sedn message to all users
'broadcast') 'broadcast')
declare -A SENDALL declare -A SENDALL
shift shift
@ -988,6 +1013,7 @@ if [ "${SOURCE}" != "yes" ]; then
echo -e "\nMessage \"$*\" sent to ${USERS} users." echo -e "\nMessage \"$*\" sent to ${USERS} users."
exit exit
;; ;;
# does what is says
"status") "status")
if [ -n "${BOTPID}" ]; then if [ -n "${BOTPID}" ]; then
echo -e "${GREEN}Bot is running.${NC}" echo -e "${GREEN}Bot is running.${NC}"
@ -998,11 +1024,13 @@ if [ "${SOURCE}" != "yes" ]; then
fi fi
;; ;;
# start bot as background jod and check if bot is running
"start") "start")
# shellcheck disable=SC2086 # shellcheck disable=SC2086
[ -n "${BOTPID}" ] && kill ${BOTPID} [ -n "${BOTPID}" ] && kill ${BOTPID}
nohup "$SCRIPT" "startbot" "$2" "${SESSION}" &>/dev/null & nohup "$SCRIPT" "startbot" "$2" "${SESSION}" &>/dev/null &
echo "Session Name: ${SESSION}" printf "Session Name: %s\n" "${SESSION}"
sleep 1
if [ -n "$(proclist "${SESSION}")" ]; then if [ -n "$(proclist "${SESSION}")" ]; then
echo -e "${GREEN}Bot started successfully.${NC}" echo -e "${GREEN}Bot started successfully.${NC}"
else else
@ -1010,7 +1038,8 @@ if [ "${SOURCE}" != "yes" ]; then
exit 5 exit 5
fi fi
;; ;;
"kill"|"stop") # does what it says
"stop")
if [ -n "${BOTPID}" ]; then if [ -n "${BOTPID}" ]; then
# shellcheck disable=SC2086 # shellcheck disable=SC2086
if kill ${BOTPID}; then if kill ${BOTPID}; then
@ -1022,7 +1051,8 @@ if [ "${SOURCE}" != "yes" ]; then
fi fi
exit exit
;; ;;
"resumeb"* | "killb"* | "suspendb"*) # suspend, resume or kill backgrund jobs
"suspendb"*|"resumeb"*|"killb"*)
_is_function job_control || { echo -e "${RED}Module background is not availible!${NC}"; exit 3; } _is_function job_control || { echo -e "${RED}Module background is not availible!${NC}"; exit 3; }
job_control "$1" job_control "$1"
;; ;;
@ -1031,8 +1061,8 @@ if [ "${SOURCE}" != "yes" ]; then
exit exit
;; ;;
*) *)
echo -e "${RED}${REALME}: BAD REQUEST${NC}" echo -e "${RED}${REALME##*/}: unknown command${NC}"
echo -e "${ORANGE}Available arguments: ${GREY}start, stop, kill, status, stats, broadcast, help, suspendback, resumeback, killback${NC}" echo -e "${ORANGE}Available commands: ${GREY}start, stop, status, stats, broadcast, help, suspendback, resumeback, killback${NC}"
exit 4 exit 4
;; ;;
esac esac

View File

@ -5,7 +5,7 @@
# This file is public domain in the USA and all free countries. # This file is public domain in the USA and all free countries.
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying) # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
# #
#### $$VERSION$$ v0.96-1-g15e6c7b #### $$VERSION$$ v0.98-dev-0-ga8fe178
# #
# source from commands.sh to use jsonDB functions # source from commands.sh to use jsonDB functions
# #