From 641727dc99b19104059935d416b5ccf5a3471452 Mon Sep 17 00:00:00 2001 From: "Kay Marquardt (Gnadelwartz)" Date: Mon, 4 Jan 2021 23:08:09 +0100 Subject: [PATCH] fix missing ${xxx} warnings --- addons/antiFlood.sh | 12 ++--- bashbot.sh | 72 ++++++++++++++-------------- commands.sh | 4 +- examples/notify.sh | 4 +- examples/question.sh | 4 +- modules/answerInline.sh | 44 ++++++++--------- modules/background.sh | 4 +- modules/chatMember.sh | 20 ++++---- modules/sendMessage.sh | 103 ++++++++++++++++++++-------------------- mycommands.sh | 44 ++++++++--------- 10 files changed, 155 insertions(+), 156 deletions(-) diff --git a/addons/antiFlood.sh b/addons/antiFlood.sh index b014341..616d938 100644 --- a/addons/antiFlood.sh +++ b/addons/antiFlood.sh @@ -4,7 +4,7 @@ # this addon counts how many files, e.g. stickers, are sent to # a chat and takes actions if threshold is reached # -#### $$VERSION$$ v1.21-0-gc85af77 +#### $$VERSION$$ v1.25-dev-5-ga5aa756 # used events: # @@ -37,7 +37,7 @@ ANTIFL_BAN="5" # 5 minutes # initialize after installation or update if [[ "$1" = "init"* ]]; then - jssh_newDB "addons/$ANTIFL_ME" + jssh_newDB "addons/${ANTIFL_ME}" fi @@ -46,7 +46,7 @@ fi if [[ "$1" = "start"* ]]; then ANTIFL_ADMIN="$(getConfigKey "botadmin")" #load existing chat settings on start - jssh_readDB "ANTIFL_CHATS" "addons/$ANTIFL_ME" + jssh_readDB "ANTIFL_CHATS" "addons/${ANTIFL_ME}" # register to CMD BASHBOT_EVENT_CMD["${ANTIFL_ME}"]="${ANTIFL_ME}_cmd" @@ -71,14 +71,14 @@ if [[ "$1" = "start"* ]]; then "/afdo" | "/afactive") [[ "${CMD[1]}" =~ ^[-0-9]+$ ]] && user_is_botadmin "${USER[ID]}" && chat="$3" ANTIFL_CHATS["${chat}","active"]="yes" - jssh_writeDB "ANTIFL_CHATS" "addons/$ANTIFL_ME" & + jssh_writeDB "ANTIFL_CHATS" "addons/${ANTIFL_ME}" & send_normal_message "${USER[ID]}" "Antiflood activated for chat ${chat}" & ;; # command /afactive starts counter meausares "/afstop") [[ "${CMD[1]}" =~ ^[-0-9]+$ ]] && user_is_botadmin "${USER[ID]}" && chat="$3" ANTIFL_CHATS["${chat}","active"]="no" - jssh_writeDB "ANTIFL_CHATS" "addons/$ANTIFL_ME" & + jssh_writeDB "ANTIFL_CHATS" "addons/${ANTIFL_ME}" & send_normal_message "${USER[ID]}" "Antiflood stopped for chat ${chat}" & ;; esac @@ -90,7 +90,7 @@ if [[ "$1" = "start"* ]]; then # save settings and reset flood level every BAN Min antiFlood_timer(){ ANTIFL_ACTUALS=( ) - jssh_writeDB "ANTIFL_CHATS" "addons/$ANTIFL_ME" & + jssh_writeDB "ANTIFL_CHATS" "addons/${ANTIFL_ME}" & } # register to inline and command diff --git a/bashbot.sh b/bashbot.sh index 8838091..5c8ab7e 100755 --- a/bashbot.sh +++ b/bashbot.sh @@ -30,7 +30,7 @@ # 8 - curl/wget missing # 10 - not bash! # -#### $$VERSION$$ v1.21-7-g0798f1a +#### $$VERSION$$ v1.25-dev-5-ga5aa756 ################################################################## # emmbeded system may claim bash but it is not @@ -42,7 +42,7 @@ fi # are we running in a terminal? NN="\n" -if [ -t 1 ] && [ -n "$TERM" ]; then +if [ -t 1 ] && [ -n "${TERM}" ]; then INTERACTIVE='yes' RED='\e[31m' GREEN='\e[32m' @@ -150,13 +150,13 @@ MODULEDIR="${SCRIPTDIR}/modules" # adjust locations based on source and real name [[ "${SCRIPT}" != "${REALME}" || "$1" == "source" ]] && SOURCE="yes" -if [ -n "$BASHBOT_HOME" ]; then - SCRIPTDIR="$BASHBOT_HOME" +if [ -n "${BASHBOT_HOME}" ]; then + SCRIPTDIR="${BASHBOT_HOME}" else BASHBOT_HOME="${SCRIPTDIR}" fi -[ -z "${BASHBOT_ETC}" ] && BASHBOT_ETC="$BASHBOT_HOME" -[ -z "${BASHBOT_VAR}" ] && BASHBOT_VAR="$BASHBOT_HOME" +[ -z "${BASHBOT_ETC}" ] && BASHBOT_ETC="${BASHBOT_HOME}" +[ -z "${BASHBOT_VAR}" ] && BASHBOT_VAR="${BASHBOT_HOME}" ADDONDIR="${BASHBOT_ETC:-.}/addons" RUNUSER="${USER}" # USER is overwritten by bashbot array :-(, save original @@ -169,16 +169,16 @@ case "$1" in exit;; "help") HELP="${BASHBOT_HOME:-.}/README" if [ -n "${INTERACTIVE}" ];then - _exists w3m && w3m "$HELP.html" && exit - _exists lynx && lynx "$HELP.html" && exit - _exists less && less "$HELP.txt" && exit + _exists w3m && w3m "${HELP}.html" && exit + _exists lynx && lynx "${HELP}.html" && exit + _exists less && less "${HELP}.txt" && exit fi - cat "$HELP.txt" + cat "${HELP}.txt" exit;; esac # OK, ENVIRONMENT is set up, let's do some additional tests -if [[ -z "${SOURCE}" && -z "$BASHBOT_HOME" ]] && ! cd "${RUNDIR}" ; then +if [[ -z "${SOURCE}" && -z "${BASHBOT_HOME}" ]] && ! cd "${RUNDIR}" ; then printf "${RED}ERROR: Can't change to ${RUNDIR} ...${NN}" exit 1 fi @@ -301,10 +301,10 @@ fi BASHBOT_RETRY="" # retry by default URL="${BASHBOT_URL:-https://api.telegram.org/bot}${BOTTOKEN}" -ME_URL=$URL'/getMe' +ME_URL=${URL}'/getMe' -UPD_URL=$URL'/getUpdates?offset=' -GETFILE_URL=$URL'/getFile' +UPD_URL=${URL}'/getUpdates?offset=' +GETFILE_URL=${URL}'/getFile' ################# # BASHBOT COMMON functions @@ -351,8 +351,8 @@ fi # outputs final filename download() { local empty="no.file" file="${2:-${empty}}" - if [[ "$file" = *"/"* ]] || [[ "$file" = "."* ]]; then file="${empty}"; fi - while [ -f "${DATADIR:-.}/${file}" ] ; do file="$RAMDOM-${file}"; done + if [[ "${file}" = *"/"* ]] || [[ "${file}" = "."* ]]; then file="${empty}"; fi + while [ -f "${DATADIR:-.}/${file}" ] ; do file="${RANDOM}-${file}"; done getJson "$1" >"${DATADIR:-.}/${file}" || return printf '%s\n' "${DATADIR:-.}/${file}" } @@ -386,7 +386,7 @@ killallproc() { # $ chat $2 msg_id $3 nolog -declare -xr DELETE_URL=$URL'/deleteMessage' +declare -xr DELETE_URL=${URL}'/deleteMessage' delete_message() { [ -z "$3" ] && log_update "Delete Message CHAT=${1} MSG_ID=${2}" sendJson "${1}" '"message_id": '"${2}"'' "${DELETE_URL}" @@ -435,8 +435,8 @@ if ! _exists iconv; then function iconv() { cat; } fi -TIMEOUT="${BASHBOT_TIMEOUT}" -[[ "$TIMEOUT" =~ ^[${o9o9o9}]+$ ]] || TIMEOUT="20" +TIMEOUT="${BASHBOT_TIMEOUT:-20}" +[[ "${TIMEOUT}" =~ ^[${o9o9o9}]+$ ]] || TIMEOUT="20" # usage: sendJson "chat" "JSON" "URL" sendJson(){ @@ -644,7 +644,7 @@ title2Json(){ # get bot name and id from telegram getBotName() { declare -A BOTARRAY - Json2Array 'BOTARRAY' <<<"$(getJson "$ME_URL" | "${JSONSHFILE}" -b -n 2>/dev/null)" + Json2Array 'BOTARRAY' <<<"$(getJson "${ME_URL}" | "${JSONSHFILE}" -b -n 2>/dev/null)" [ -z "${BOTARRAY["result","username"]}" ] && return 1 # save botname and id setConfigKey "botname" "${BOTARRAY["result","username"]}" @@ -657,7 +657,7 @@ getBotName() { JsonDecode() { local out="$1" remain="" U="" local regexp='(.*)\\u[dD]([0-9a-fA-F]{3})\\u[dD]([0-9a-fA-F]{3})(.*)' - while [[ "${out}" =~ $regexp ]] ; do + while [[ "${out}" =~ ${regexp} ]] ; do U=$(( ( (0xd${BASH_REMATCH[2]} & 0x3ff) <<10 ) | ( 0xd${BASH_REMATCH[3]} & 0x3ff ) + 0x10000 )) remain="$(printf '\\U%8.8x' "${U}")${BASH_REMATCH[4]}${remain}" out="${BASH_REMATCH[1]}" @@ -683,7 +683,7 @@ process_updates() { max="$(grep -F ',"update_id"]' <<< "${UPDATE}" | tail -1 | cut -d , -f 2 )" Json2Array 'UPD' <<<"${UPDATE}" for ((num=0; num<=max; num++)); do - process_client "$num" "${debug}" + process_client "${num}" "${debug}" done } @@ -731,7 +731,7 @@ process_client() { jssh_countKeyDB_async "${CHAT[ID]}" "${COUNTFILE}" } -declare -Ax BASHBOT_EVENT_INLINE BASHBOT_EVENT_MESSAGE BASHBOT_EVENT_CMD BASHBOT_EVENT_REPLY BASHBOT_EVENT_FORWARD BASHBOT_EVENT_SEND +declare -Ax BASHBOT_EVENT_INLINE BASHBOT_EVENT_MESSAGE BASHBOT_EVENT_CMD BASHBOT_EVENT_REPLYTO BASHBOT_EVENT_FORWARD BASHBOT_EVENT_SEND declare -Ax BASHBOT_EVENT_CONTACT BASHBOT_EVENT_LOCATION BASHBOT_EVENT_FILE BASHBOT_EVENT_TEXT BASHBOT_EVENT_TIMER BASHBOT_BLOCKED start_timer(){ @@ -745,7 +745,7 @@ start_timer(){ EVENT_SEND="0" event_send() { # max recursion level 5 to avoid fork bombs - (( EVENT_SEND++ )); [ "$EVENT_SEND" -gt "5" ] && return + (( EVENT_SEND++ )); [ "${EVENT_SEND}" -gt "5" ] && return # shellcheck disable=SC2153 for key in "${!BASHBOT_EVENT_SEND[@]}" do @@ -761,7 +761,7 @@ event_timer() { for key in "${!BASHBOT_EVENT_TIMER[@]}" do timer="${key##*,}" - [[ ! "$timer" =~ ^-*[1-9][0-9]*$ ]] && continue + [[ ! "${timer}" =~ ^-*[1-9][0-9]*$ ]] && continue if [ "$(( EVENT_TIMER % timer ))" = "0" ]; then _exec_if_function "${BASHBOT_EVENT_TIMER[${key}]}" "timer" "${key}" "${debug}" [ "$(( EVENT_TIMER % timer ))" -lt "0" ] && \ @@ -1041,7 +1041,7 @@ start_bot() { # start timer events if [ -n "${BASHBOT_START_TIMER}" ] ; then # shellcheck disable=SC2064 - trap "event_timer $DEBUGMSG" ALRM + trap "event_timer ${DEBUGMSG}" ALRM start_timer & # shellcheck disable=SC2064 trap "kill -9 $!; exit" EXIT INT HUP TERM QUIT @@ -1075,7 +1075,7 @@ start_bot() { OFFSET="$(grep <<< "${UPDATE}" '\["result",[0-9]*,"update_id"\]' | tail -1 | cut -f 2)" ((OFFSET++)) - if [ "$OFFSET" != "1" ]; then + if [ "${OFFSET}" != "1" ]; then nextsleep="100" process_updates "${DEBUGMSG}" fi @@ -1113,22 +1113,22 @@ bot_init() { printf "Done.\n" # setup bashbot [[ "${UID}" -eq "0" ]] && RUNUSER="nobody" - printf "Enter User to run bashbot [$RUNUSER]: " + printf "Enter User to run bashbot [${RUNUSER}]: " read -r TOUSER - [ -z "$TOUSER" ] && TOUSER="$RUNUSER" - if ! id "$TOUSER" &>/dev/null; then - printf "${RED}User \"$TOUSER\" not found!${NN}" + [ -z "${TOUSER}" ] && TOUSER="${RUNUSER}" + if ! id "${TOUSER}" &>/dev/null; then + printf "${RED}User \"${TOUSER}\" not found!${NN}" exit 3 else printf "Adjusting files and permissions for user \"${TOUSER}\" ...\n" - [ -w "bashbot.rc" ] && sed -i '/^[# ]*runas=/ s/runas=.*$/runas="'$TOUSER'"/' "bashbot.rc" + [ -w "bashbot.rc" ] && sed -i '/^[# ]*runas=/ s/runas=.*$/runas="'"${TOUSER}"'"/' "bashbot.rc" chmod 711 . chmod -R o-w ./* chmod -R u+w "${COUNTFILE}"* "${BLOCKEDFILE}"* "${DATADIR}" logs "${LOGDIR}/"*.log 2>/dev/null chmod -R o-r,o-w "${COUNTFILE}"* "${BLOCKEDFILE}"* "${DATADIR}" "${BOTACL}" 2>/dev/null # jsshDB must writeable by owner find . -name '*.jssh*' -exec chmod u+w \{\} + - chown -R "$TOUSER" . ./* + chown -R "${TOUSER}" . ./* printf "Done.\n" fi # ask to check bottoken online @@ -1187,7 +1187,7 @@ if [ -z "${SOURCE}" ]; then else printf "${GREY}Info: Can't get Botname from Telegram, try cached one ...${NN}" ME="$(getConfigKey "botname")" - if [ -z "$ME" ]; then + if [ -z "${ME}" ]; then printf "${RED}ERROR: No cached botname, can't continue! ...${NN}" exit 1 fi @@ -1202,7 +1202,7 @@ if [ -z "${SOURCE}" ]; then ME="$(getConfigKey "botname")" # read until terminated while read -r line ;do - [ -n "$line" ] && send_message "$2" "$line" + [ -n "${line}" ] && send_message "$2" "${line}" done # cleanup datadir, keep logfile if not empty rm -f -r "${DATADIR:-.}/$3" @@ -1256,7 +1256,7 @@ if [ -z "${SOURCE}" ]; then BOTPID="$(proclist "${SESSION}")" # shellcheck disable=SC2086 [ -n "${BOTPID}" ] && kill ${BOTPID} - nohup "$SCRIPT" "startbot" "$2" "${SESSION}" &>/dev/null & + nohup "${SCRIPT}" "startbot" "$2" "${SESSION}" &>/dev/null & printf "Session Name: %s\n" "${SESSION}" sleep 1 if [ -n "$(proclist "${SESSION}")" ]; then diff --git a/commands.sh b/commands.sh index cad0010..dbb5ce8 100644 --- a/commands.sh +++ b/commands.sh @@ -15,7 +15,7 @@ # This file is public domain in the USA and all free countries. # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying) # -#### $$VERSION$$ v1.25-dev-0-gd310805 +#### $$VERSION$$ v1.25-dev-5-ga5aa756 # # bashbot locale defaults to c.UTF-8, adjust locale in mycommands.sh if needed @@ -78,7 +78,7 @@ export FILE_REGEX="${BASHBOT_ETC}/.*" if [ -z "${1}" ] || [[ "${1}" == *"debug"* ]];then # detect inline commands.... # no default commands, all processing is done in myinlines() - if [ "$INLINE" != "0" ] && [ -n "${iQUERY[ID]}" ]; then + if [ "${INLINE}" != "0" ] && [ -n "${iQUERY[ID]}" ]; then # forward iinline query to optional dispatcher _exec_if_function myinlines diff --git a/examples/notify.sh b/examples/notify.sh index 2cc2678..a1e1864 100755 --- a/examples/notify.sh +++ b/examples/notify.sh @@ -13,7 +13,7 @@ # This file is public domain in the USA and all free countries. # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying) # -#### $$VERSION$$ v1.21-0-gc85af77 +#### $$VERSION$$ v1.25-dev-5-ga5aa756 ######################################################################## ###### @@ -47,6 +47,6 @@ printf "Output time every %s seconds ...\n" "${SLEEP}" while true do date "+* It's %k:%M:%S o'clock ..." - sleep $SLEEP + sleep "${SLEEP}" done diff --git a/examples/question.sh b/examples/question.sh index 17479b0..5981f2a 100755 --- a/examples/question.sh +++ b/examples/question.sh @@ -10,7 +10,7 @@ # This file is public domain in the USA and all free countries. # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying) # -#### $$VERSION$$ v1.21-0-gc85af77 +#### $$VERSION$$ v1.25-dev-5-ga5aa756 ######################################################################## ###### @@ -39,7 +39,7 @@ else fi # question with Keyboard, repeating until correct answer given -until [ "$SUCCESS" = "y" ] ;do +until [ "${SUCCESS}" = "y" ] ;do printf 'Do you like Music? mykeyboardstartshere "Yass!" , "No"\n' read -r answer <"${INPUT}" case ${answer,,} in diff --git a/modules/answerInline.sh b/modules/answerInline.sh index 83534da..636fb4d 100644 --- a/modules/answerInline.sh +++ b/modules/answerInline.sh @@ -5,17 +5,17 @@ # This file is public domain in the USA and all free countries. # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying) # -#### $$VERSION$$ v1.21-0-gc85af77 +#### $$VERSION$$ v1.25-dev-5-ga5aa756 # will be automatically sourced from bashbot # source once magic, function named like file eval "$(basename "${BASH_SOURCE[0]}")(){ :; }" -INLINE_QUERY=$URL'/answerInlineQuery' +INLINE_QUERY=${URL}'/answerInlineQuery' answer_inline_query() { - answer_inline_multi "${1}" "$(shift; inline_query_compose "$RANDOM" "$@")" + answer_inline_multi "${1}" "$(shift; inline_query_compose "${RANDOM}" "$@")" } answer_inline_multi() { sendJson "" '"inline_query_id": '"${1}"', "results": ['"${2}"']' "${INLINE_QUERY}" @@ -33,70 +33,70 @@ inline_query_compose(){ case "${2}" in # user provided media "article"|"message") # article ID title message (markup description) - JSON='{"type":"article","id":"'$ID'","input_message_content": {"message_text":"'$4'"} '$(title2Json "$3" "" "$5" "$6" "$7")'}' + JSON='{"type":"article","id":"'${ID}'","input_message_content": {"message_text":"'$4'"} '$(title2Json "$3" "" "$5" "$6" "$7")'}' ;; "photo") # photo ID photoURL (thumbURL title description caption) [ -z "$4" ] && tumb="$3" - JSON='{"type":"photo","id":"'$ID'","photo_url":"'$3'","thumb_url":"'$4${tumb}'"'$(title2Json "$5" "$7" "$6" "$7" "$8")'}' + JSON='{"type":"photo","id":"'${ID}'","photo_url":"'$3'","thumb_url":"'$4${tumb}'"'$(title2Json "$5" "$7" "$6" "$7" "$8")'}' ;; "gif") # gif ID photoURL (thumbURL title caption) [ -z "$4" ] && tumb="$3" - JSON='{"type":"gif","id":"'$ID'","gif_url":"'$3'", "thumb_url":"'$4${tumb}'"'$(title2Json "$5" "$6" "$7" "$8" "$9")'}' + JSON='{"type":"gif","id":"'${ID}'","gif_url":"'$3'", "thumb_url":"'$4${tumb}'"'$(title2Json "$5" "$6" "$7" "$8" "$9")'}' ;; "mpeg4_gif") # mpeg4_gif ID mpegURL (thumbURL title caption) [ -n "$4" ] && tumb='","thumb_url":"'$4'"' - JSON='{"type":"mpeg4_gif","id":"'$ID'","mpeg4_url":"'$3'"'${tumb}$(title2Json "$5" "$6" "" "$7" "$8")'}' + JSON='{"type":"mpeg4_gif","id":"'${ID}'","mpeg4_url":"'$3'"'${tumb}$(title2Json "$5" "$6" "" "$7" "$8")'}' ;; "video") # video ID videoURL mime thumbURL title (caption) - JSON='{"type":"video","id":"'$ID'","video_url":"'$3'","mime_type":"'$4'","thumb_url":"'$5'"'$(title2Json "$6" "$7" "$8" "$9" "${10}")'}' + JSON='{"type":"video","id":"'${ID}'","video_url":"'$3'","mime_type":"'$4'","thumb_url":"'$5'"'$(title2Json "$6" "$7" "$8" "$9" "${10}")'}' ;; "audio") # audio ID audioURL title (caption) - JSON='{"type":"audio","id":"'$ID'","audio_url":"'$3'"'$(title2Json "$4" "$5" "" "" "$6")'}' + JSON='{"type":"audio","id":"'${ID}'","audio_url":"'$3'"'$(title2Json "$4" "$5" "" "" "$6")'}' ;; "voice") # voice ID voiceURL title (caption) - JSON='{"type":"voice","id":"'$ID'","voice_url":"'$3'"'$(title2Json "$4" "$5" "" "" "$6")'}' + JSON='{"type":"voice","id":"'${ID}'","voice_url":"'$3'"'$(title2Json "$4" "$5" "" "" "$6")'}' ;; "document") # document ID title documentURL mimetype (caption description) - JSON='{"type":"document","id":"'$ID'","document_url":"'$4'","mime_type":"'$5'"'$(title2Json "$3" "$6" "$7" "$8" "$9")'}' + JSON='{"type":"document","id":"'${ID}'","document_url":"'$4'","mime_type":"'$5'"'$(title2Json "$3" "$6" "$7" "$8" "$9")'}' ;; "location") # location ID lat long title - JSON='{"type":"location","id":"'$ID'","latitude":"'$3'","longitude":"'$4'","title":"'$5'"}' + JSON='{"type":"location","id":"'${ID}'","latitude":"'$3'","longitude":"'$4'","title":"'$5'"}' ;; "venue") # venue ID lat long title (address forsquare) [ -z "$6" ] && addr="$5" [ -n "$7" ] && fours=',"foursquare_id":"'$7'"' - JSON='{"type":"venue","id":"'$ID'","latitude":"'$3'","longitude":"'$4'","title":"'$5'","address":"'$6${addr}'"'${fours}'}' + JSON='{"type":"venue","id":"'${ID}'","latitude":"'$3'","longitude":"'$4'","title":"'$5'","address":"'$6${addr}'"'${fours}'}' ;; "contact") # contact ID phone first (last thumb) [ -n "$5" ] && last=',"last_name":"'$5'"' [ -n "$6" ] && tumb='","thumb_url":"'$6'"' - JSON='{"type":"contact","id":"'$ID'","phone_number":"'$3'","first_name":"'$4'"'${last}'"}' + JSON='{"type":"contact","id":"'${ID}'","phone_number":"'$3'","first_name":"'$4'"'${last}'"}' ;; # title2Json title caption description markup inlinekeyboard # Cached media stored in Telegram server "cached_photo") # photo ID file (title description caption) - JSON='{"type":"photo","id":"'$ID'","photo_file_id":"'$3'"'$(title2Json "$4" "$6" "$5" "$7" "$8")'}' + JSON='{"type":"photo","id":"'${ID}'","photo_file_id":"'$3'"'$(title2Json "$4" "$6" "$5" "$7" "$8")'}' ;; "cached_gif") # gif ID file (title caption) - JSON='{"type":"gif","id":"'$ID'","gif_file_id":"'$3'"'$(title2Json "$4" "$5" "$6" "$7" "$8" )'}' + JSON='{"type":"gif","id":"'${ID}'","gif_file_id":"'$3'"'$(title2Json "$4" "$5" "$6" "$7" "$8" )'}' ;; "cached_mpeg4_gif") # mpeg ID file (title caption) - JSON='{"type":"mpeg4_gif","id":"'$ID'","mpeg4_file_id":"'$3'"'$(title2Json "$4" "$5" "" "$6" "$7")'}' + JSON='{"type":"mpeg4_gif","id":"'${ID}'","mpeg4_file_id":"'$3'"'$(title2Json "$4" "$5" "" "$6" "$7")'}' ;; "cached_sticker") # sticker ID file - JSON='{"type":"sticker","id":"'$ID'","sticker_file_id":"'$3'"}' + JSON='{"type":"sticker","id":"'${ID}'","sticker_file_id":"'$3'"}' ;; "cached_document") # document ID title file (description caption) - JSON='{"type":"document","id":"'$ID'","document_file_id":"'$4'"'$(title2Json "$3" "$6" "$5" "$6" "$7")'}' + JSON='{"type":"document","id":"'${ID}'","document_file_id":"'$4'"'$(title2Json "$3" "$6" "$5" "$6" "$7")'}' ;; "cached_video") # video ID file title (description caption) - JSON='{"type":"video","id":"'$ID'","video_file_id":"'$3'"'$(title2Json "$4" "$6" "$5" "$7" "$8")'}' + JSON='{"type":"video","id":"'${ID}'","video_file_id":"'$3'"'$(title2Json "$4" "$6" "$5" "$7" "$8")'}' ;; "cached_voice") # voice ID file title (caption) - JSON='{"type":"voice","id":"'$ID'","voice_file_id":"'$3'"'$(title2Json "$4" "$5" "" "" "$6")'}' + JSON='{"type":"voice","id":"'${ID}'","voice_file_id":"'$3'"'$(title2Json "$4" "$5" "" "" "$6")'}' ;; "cached_audio") # audio ID file title (caption) - JSON='{"type":"audio","id":"'$ID'","audio_file_id":"'$3'"'$(title2Json "$4" "$5" "" "" "$6")'}' + JSON='{"type":"audio","id":"'${ID}'","audio_file_id":"'$3'"'$(title2Json "$4" "$5" "" "" "$6")'}' ;; esac diff --git a/modules/background.sh b/modules/background.sh index 5e0513b..7b83af4 100644 --- a/modules/background.sh +++ b/modules/background.sh @@ -6,7 +6,7 @@ # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying) # # shellcheck disable=SC1117,SC2059 -#### $$VERSION$$ v1.21-0-gc85af77 +#### $$VERSION$$ v1.25-dev-5-ga5aa756 # will be automatically sourced from bashbot @@ -65,7 +65,7 @@ start_proc() { printf "%s: Start interacitve script CHAT=%s JOB=%s CMD=%s\n" "$(date)" "${1}" "${fifo##*/}" "${2} ${3} ${4}" >>"${UPDATELOG}" check_proc "$1" && kill_proc "$1" mkfifo "${fifo}" - nohup bash -c "{ $2 \"$4\" \"$5\" \"$fifo\" | \"${SCRIPT}\" outproc \"${1}\" \"${fifo}\" + nohup bash -c "{ $2 \"$4\" \"$5\" \"${fifo}\" | \"${SCRIPT}\" outproc \"${1}\" \"${fifo}\" rm \"${fifo}\"; [ -s \"${fifo}.log\" ] || rm -f \"${fifo}.log\"; }" &>>"${fifo}.log" & } diff --git a/modules/chatMember.sh b/modules/chatMember.sh index 4f23645..796da8b 100644 --- a/modules/chatMember.sh +++ b/modules/chatMember.sh @@ -5,36 +5,36 @@ # This file is public domain in the USA and all free countries. # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying) # -#### $$VERSION$$ v1.21-0-gc85af77 +#### $$VERSION$$ v1.25-dev-5-ga5aa756 # will be automatically sourced from bashbot # source once magic, function named like file eval "$(basename "${BASH_SOURCE[0]}")(){ :; }" -LEAVE_URL=$URL'/leaveChat' -KICK_URL=$URL'/kickChatMember' -UNBAN_URL=$URL'/unbanChatMember' -GETMEMBER_URL=$URL'/getChatMember' +LEAVE_URL=${URL}'/leaveChat' +KICK_URL=${URL}'/kickChatMember' +UNBAN_URL=${URL}'/unbanChatMember' +GETMEMBER_URL=${URL}'/getChatMember' # usage: status="$(get_chat_member_status "chat" "user")" # $1 chat # $2 user get_chat_member_status() { - sendJson "$1" '"user_id":'"$2"'' "$GETMEMBER_URL" + sendJson "$1" '"user_id":'"$2"'' "${GETMEMBER_URL}" # shellcheck disable=SC2154 - JsonGetString '"result","status"' <<< "$res" + JsonGetString '"result","status"' <<< "${res}" } kick_chat_member() { - sendJson "$1" 'user_id: '"$2"'' "$KICK_URL" + sendJson "$1" 'user_id: '"$2"'' "${KICK_URL}" } unban_chat_member() { - sendJson "$1" 'user_id: '"$2"'' "$UNBAN_URL" + sendJson "$1" 'user_id: '"$2"'' "${UNBAN_URL}" } leave_chat() { - sendJson "$1" "" "$LEAVE_URL" + sendJson "$1" "" "${LEAVE_URL}" } user_is_creator() { diff --git a/modules/sendMessage.sh b/modules/sendMessage.sh index e5ef612..2f56287 100644 --- a/modules/sendMessage.sh +++ b/modules/sendMessage.sh @@ -6,7 +6,7 @@ # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying) # # shellcheck disable=SC1117 -#### $$VERSION$$ v1.21-0-gc85af77 +#### $$VERSION$$ v1.25-dev-5-ga5aa756 # will be automatically sourced from bashbot @@ -15,19 +15,19 @@ eval "$(basename "${BASH_SOURCE[0]}")(){ :; }" # source from commands.sh to use the sendMessage functions -MSG_URL=$URL'/sendMessage' -EDIT_URL=$URL'/editMessageText' -PHO_URL=$URL'/sendPhoto' -AUDIO_URL=$URL'/sendAudio' -DOCUMENT_URL=$URL'/sendDocument' -STICKER_URL=$URL'/sendSticker' -VIDEO_URL=$URL'/sendVideo' -VOICE_URL=$URL'/sendVoice' -LOCATION_URL=$URL'/sendLocation' -VENUE_URL=$URL'/sendVenue' -ACTION_URL=$URL'/sendChatAction' -FORWARD_URL=$URL'/forwardMessage' -ALBUM_URL=$URL'/sendMediaGroup' +MSG_URL=${URL}'/sendMessage' +EDIT_URL=${URL}'/editMessageText' +PHO_URL=${URL}'/sendPhoto' +AUDIO_URL=${URL}'/sendAudio' +DOCUMENT_URL=${URL}'/sendDocument' +STICKER_URL=${URL}'/sendSticker' +VIDEO_URL=${URL}'/sendVideo' +VOICE_URL=${URL}'/sendVoice' +LOCATION_URL=${URL}'/sendLocation' +VENUE_URL=${URL}'/sendVenue' +ACTION_URL=${URL}'/sendChatAction' +FORWARD_URL=${URL}'/forwardMessage' +ALBUM_URL=${URL}'/sendMediaGroup' # # send/edit message variants ------------------ @@ -106,7 +106,7 @@ _markdownv2_message_url() { text="${text//$'\n'/\\n}" [ "${#text}" -ge 4096 ] && log_error "Warning: markdownv2 message longer than 4096 characters, message is rejected if formatting crosses 4096 border." # markdown v2 needs additional double escaping! - text="$(sed -E -e 's|([_|~`>+=#{}()!.-])|\\\1|g' <<< "$text")" + text="$(sed -E -e 's|([_|~`>+=#{}()!.-])|\\\1|g' <<< "${text}")" until [ -z "${text}" ]; do sendJson "${1}" '"text":"'"${text:0:4096}"'"'"${3}"'' "${4}" text="${text:4096}" @@ -126,7 +126,7 @@ send_keyboard() { text='"text":"'"${text//$'\n'/\\n}"'"' fi local one_time=', "one_time_keyboard":true' && [ -n "$4" ] && one_time="" - sendJson "${1}" "${text}"', "reply_markup": {"keyboard": [ '"${3}"' ] '"${one_time}"'}' "$MSG_URL" + sendJson "${1}" "${text}"', "reply_markup": {"keyboard": [ '"${3}"' ] '"${one_time}"'}' "${MSG_URL}" # '"text":"$2", "reply_markup": {"keyboard": [ ${3} ], "one_time_keyboard": true}' } @@ -137,7 +137,7 @@ remove_keyboard() { text="$(JsonEscape "${2}")" text='"text":"'"${text//$'\n'/\\n}"'"' fi - sendJson "${1}" "${text}"', "reply_markup": {"remove_keyboard":true}' "$MSG_URL" + sendJson "${1}" "${text}"', "reply_markup": {"remove_keyboard":true}' "${MSG_URL}" # delete message if no message or $3 not empty [[ -z "${2}" || -n "${3}" ]] && delete_message "${1}" "${BOTSENT[ID]}" "nolog" #JSON='"text":"$2", "reply_markup": {"remove_keyboard":true}' @@ -146,7 +146,7 @@ remove_keyboard() { # $1 CHAT $2 message $3 keyboard send_inline_keyboard() { local text; text='"text":"'$(JsonEscape "${2}")'"'; [ -z "${2}" ] && text='"text":"'"Keyboard:"'"' - sendJson "${1}" "${text}"', "reply_markup": {"inline_keyboard": [ '"${3}"' ]}' "$MSG_URL" + sendJson "${1}" "${text}"', "reply_markup": {"inline_keyboard": [ '"${3}"' ]}' "${MSG_URL}" # JSON='"text":"$2", "reply_markup": {"inline_keyboard": [ $3->[{"text":"text", "url":"url"}]<- ]}' } # $1 CHAT $2 message $3 button text $4 URL @@ -192,7 +192,7 @@ send_file() { if [ "${err}" != "0" ]; then BOTSENT=() BOTSENT[OK]="false" - case "$err" in + case "${err}" in 1) BOTSENT[ERROR]="Path to file $2 contains to much '../' or starts with '.'";; 2) BOTSENT[ERROR]="Path to file $2 does not match regex: ${FILE_REGEX} ";; 3) if [[ "$2" == "/"* ]];then @@ -208,63 +208,62 @@ send_file() { upload_file(){ local CUR_URL WHAT STATUS text=$3 file="$2" # file access checks ... - [[ "$file" = *'..'* ]] && return 1 # no directory traversal - [[ "$file" = '.'* ]] && return 1 # no hidden or relative files - if [[ "$file" = '/'* ]] ; then - [[ ! "$file" =~ ${FILE_REGEX} ]] && return 2 # absolute must match REGEX + [[ "${file}" = *'..'* ]] && return 1 # no directory traversal + [[ "${file}" = '.'* ]] && return 1 # no hidden or relative files + if [[ "${file}" = '/'* ]] ; then + [[ ! "${file}" =~ ${FILE_REGEX} ]] && return 2 # absolute must match REGEX else file="${UPLOADDIR:-NOUPLOADDIR}/${file}" # othiers must be in UPLOADDIR fi - [ ! -r "$file" ] && return 3 # and file must exits of course + [ ! -r "${file}" ] && return 3 # and file must exits of course - local ext="${file##*.}" - case $ext in + case "${file##*.}" in mp3|flac) - CUR_URL="$AUDIO_URL" + CUR_URL="${AUDIO_URL}" WHAT="audio" STATUS="upload_audio" ;; png|jpg|jpeg|gif|pic) - CUR_URL="$PHO_URL" + CUR_URL="${PHO_URL}" WHAT="photo" STATUS="upload_photo" ;; webp) - CUR_URL="$STICKER_URL" + CUR_URL="${STICKER_URL}" WHAT="sticker" STATUS="upload_photo" ;; mp4) - CUR_URL="$VIDEO_URL" + CUR_URL="${VIDEO_URL}" WHAT="video" STATUS="upload_video" ;; ogg) - CUR_URL="$VOICE_URL" + CUR_URL="${VOICE_URL}" WHAT="voice" STATUS="upload_audio" ;; *) - CUR_URL="$DOCUMENT_URL" + CUR_URL="${DOCUMENT_URL}" WHAT="document" STATUS="upload_document" ;; esac - send_action "${1}" "$STATUS" + send_action "${1}" "${STATUS}" sendUpload "$1" "${WHAT}" "${file}" "${CUR_URL}" "${text//\\n/$'\n'}" } # typing for text messages, upload_photo for photos, record_video or upload_video for videos, record_audio or upload_audio for audio files, upload_document for general files, find_location for location send_action() { [ -z "$2" ] && return - sendJson "${1}" '"action": "'"${2}"'"' "$ACTION_URL" & + sendJson "${1}" '"action": "'"${2}"'"' "${ACTION_URL}" & } # $1 CHAT $2 lat $3 long send_location() { [ -z "$3" ] && return - sendJson "${1}" '"latitude": '"${2}"', "longitude": '"${3}"'' "$LOCATION_URL" + sendJson "${1}" '"latitude": '"${2}"', "longitude": '"${3}"'' "${LOCATION_URL}" } # $1 CHAT $2 lat $3 long $4 title $5 address $6 foursquard id @@ -272,7 +271,7 @@ send_venue() { local add="" [ -z "$5" ] && return [ -n "$6" ] && add=', "foursquare_id": '"$6"'' - sendJson "${1}" '"latitude": '"${2}"', "longitude": '"${3}"', "address": "'"${5}"'", "title": "'"${4}"'"'"${add}" "$VENUE_URL" + sendJson "${1}" '"latitude": '"${2}"', "longitude": '"${3}"', "address": "'"${5}"'", "title": "'"${4}"'"'"${add}" "${VENUE_URL}" } @@ -283,7 +282,7 @@ send_venue() { # $1 CHAT $2 from chat $3 from msg id forward_message() { [ -z "$3" ] && return - sendJson "${1}" '"from_chat_id": '"${2}"', "message_id": '"${3}"'' "$FORWARD_URL" + sendJson "${1}" '"from_chat_id": '"${2}"', "message_id": '"${3}"'' "${FORWARD_URL}" } forward() { # backward compatibility forward_message "$@" || return @@ -308,35 +307,35 @@ send_message() { title="$(sed <<< "${2}" '/mytitlestartshere /!d;s/.*mytitlestartshere //;s/ *my[kfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')" address="$(sed <<< "${2}" '/myaddressstartshere /!d;s/.*myaddressstartshere //;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')" } - if [ -n "$no_keyboard" ]; then - remove_keyboard "$1" "$text" + if [ -n "${no_keyboard}" ]; then + remove_keyboard "$1" "${text}" sent=y fi - if [ -n "$keyboard" ]; then - if [[ "$keyboard" != *"["* ]]; then # pre 0.60 style + if [ -n "${keyboard}" ]; then + if [[ "${keyboard}" != *"["* ]]; then # pre 0.60 style keyboard="[ ${keyboard//\" \"/\" \] , \[ \"} ]" fi - send_keyboard "$1" "$text" "$keyboard" + send_keyboard "$1" "${text}" "${keyboard}" sent=y fi - if [ -n "$btext" ] && [ -n "$burl" ]; then - send_button "$1" "$text" "$btext" "$burl" + if [ -n "${btext}" ] && [ -n "${burl}" ]; then + send_button "$1" "${text}" "${btext}" "${burl}" sent=y fi - if [ -n "$file" ]; then - send_file "$1" "$file" "$text" + if [ -n "${file}" ]; then + send_file "$1" "${file}" "${text}" sent=y fi - if [ -n "$lat" ] && [ -n "$long" ]; then - if [ -n "$address" ] && [ -n "$title" ]; then - send_venue "$1" "$lat" "$long" "$title" "$address" + if [ -n "${lat}" ] && [ -n "${long}" ]; then + if [ -n "${address}" ] && [ -n "${title}" ]; then + send_venue "$1" "${lat}" "${long}" "${title}" "${address}" else - send_location "$1" "$lat" "$long" + send_location "$1" "${lat}" "${long}" fi sent=y fi - if [ "$sent" != "y" ];then - send_text_mode "$1" "$text" + if [ "${sent}" != "y" ];then + send_text_mode "$1" "${text}" fi } diff --git a/mycommands.sh b/mycommands.sh index 99c8d72..f1eb481 100644 --- a/mycommands.sh +++ b/mycommands.sh @@ -9,7 +9,7 @@ # #### mycommands.clean # # shellcheck disable=SC1117 -#### $$VERSION$$ v1.25-dev-0-gd310805 +#### $$VERSION$$ v1.25-dev-5-ga5aa756 # ########## @@ -193,40 +193,40 @@ else ################## # example commands, replace thm by your own '/echo'*) # example echo command - send_normal_message "${CHAT[ID]}" "$MESSAGE" + send_normal_message "${CHAT[ID]}" "${MESSAGE}" ;; '/question'*) # start interactive questions checkproc - if [ "$res" -gt 0 ] ; then + if [ "${res}" -gt 0 ] ; then startproc "examples/question.sh" || send_normal_message "${CHAT[ID]}" "Can't start question." else - send_normal_message "${CHAT[ID]}" "$MESSAGE already running ..." + send_normal_message "${CHAT[ID]}" "${MESSAGE} already running ..." fi ;; '/cancel'*) # cancel interactive command checkproc - if [ "$res" -gt 0 ] ;then + if [ "${res}" -gt 0 ] ;then killproc && send_normal_message "${CHAT[ID]}" "Command canceled." else send_normal_message "${CHAT[ID]}" "No command is currently running." fi ;; '/run_notify'*) # start notify background job - myback="notify"; checkback "$myback" - if [ "$res" -gt 0 ] ; then - background "examples/notify.sh 60" "$myback" || send_normal_message "${CHAT[ID]}" "Can't start notify." + myback="notify"; checkback "${myback}" + if [ "${res}" -gt 0 ] ; then + background "examples/notify.sh 60" "${myback}" || send_normal_message "${CHAT[ID]}" "Can't start notify." else - send_normal_message "${CHAT[ID]}" "Background command $myback already running ..." + send_normal_message "${CHAT[ID]}" "Background command ${myback} already running ..." fi ;; '/stop_notify'*) # kill notify background job - myback="notify"; checkback "$myback" - if [ "$res" -eq 0 ] ; then - killback "$myback" - send_normal_message "${CHAT[ID]}" "Background command $myback canceled." + myback="notify"; checkback "${myback}" + if [ "${res}" -eq 0 ] ; then + killback "${myback}" + send_normal_message "${CHAT[ID]}" "Background command ${myback} canceled." else - send_normal_message "${CHAT[ID]}" "No background command $myback is currently running.." + send_normal_message "${CHAT[ID]}" "No background command ${myback} is currently running.." fi ;; @@ -262,15 +262,15 @@ else ;; "2"*) # two photos answer_inline_multi "${iQUERY[ID]}" " - $(inline_query_compose "$RANDOM" "photo" "https://avatars.githubusercontent.com/u/13046303"), - $(inline_query_compose "$RANDOM" "photo" "https://avatars.githubusercontent.com/u/4593242") + $(inline_query_compose "${RANDOM}" "photo" "https://avatars.githubusercontent.com/u/13046303"), + $(inline_query_compose "${RANDOM}" "photo" "https://avatars.githubusercontent.com/u/4593242") " ;; "3"*) # three photos answer_inline_multi "${iQUERY[ID]}" " - $(inline_query_compose "$RANDOM" "photo" "https://avatars.githubusercontent.com/u/13046303"), - $(inline_query_compose "$RANDOM" "photo" "https://avatars.githubusercontent.com/u/4593242") - $(inline_query_compose "$RANDOM" "photo" "https://avatars.githubusercontent.com/u/102707") + $(inline_query_compose "${RANDOM}" "photo" "https://avatars.githubusercontent.com/u/13046303"), + $(inline_query_compose "${RANDOM}" "photo" "https://avatars.githubusercontent.com/u/4593242") + $(inline_query_compose "${RANDOM}" "photo" "https://avatars.githubusercontent.com/u/102707") " ;; @@ -279,7 +279,7 @@ else local avatar=("https://avatars.githubusercontent.com/u/13046303" "https://avatars.githubusercontent.com/u/4593242" "https://avatars.githubusercontent.com/u/102707" "https://avatars.githubusercontent.com/u/6460407") answer_inline_multi "${iQUERY[ID]}" " $(for photo in ${avatar[*]} ; do - printf "%s\n" "${sep}"; inline_query_compose "$RANDOM" "photo" "${photo}" "${photo}"; sep="," + printf "%s\n" "${sep}"; inline_query_compose "${RANDOM}" "photo" "${photo}" "${photo}"; sep="," done) " ;; @@ -318,10 +318,10 @@ else local image result sep="" count="1" result="$(wget --user-agent 'Mozilla/5.0' -qO - "https://images.search.yahoo.com/search/images?p=$1" | sed 's/