diff --git a/bashbot.sh b/bashbot.sh index 8d43d72..e3781f9 100755 --- a/bashbot.sh +++ b/bashbot.sh @@ -30,7 +30,7 @@ BOTCOMMANDS="-h help init start stop status suspendback resumeback killb # 8 - curl/wget missing # 10 - not bash! # -#### $$VERSION$$ v1.31-dev-12-g85a178d +#### $$VERSION$$ v1.31-dev-13-g127cc85 ################################################################## # emmbeded system may claim bash but it is not @@ -90,7 +90,7 @@ _is_function() { _round_float() { local digit="$2"; [[ "$2" =~ ^[${o9o9o9}]+$ ]] || digit="0" : "$(LC_ALL=C printf "%.${digit}f" "$1" 2>/dev/null)" - printf "%s" "${_//,/.}" # make more LANG independent + printf "%s" "${_//,/.}" # make more LANG independent } # date is external, printf is much faster _date(){ @@ -185,7 +185,7 @@ fi [ -z "${BASHBOT_VAR}" ] && BASHBOT_VAR="${BASHBOT_HOME}" ADDONDIR="${BASHBOT_ETC:-.}/addons" -RUNUSER="${USER}" # USER is overwritten by bashbot array :-(, save original +RUNUSER="${USER}" # USER is overwritten by bashbot array :-(, save original # provide help case "$1" in @@ -325,7 +325,7 @@ fi ################## # here we start with the real stuff -BASHBOT_RETRY="" # retry by default +BASHBOT_RETRY="" # retry by default URL="${BASHBOT_URL:-https://api.telegram.org/bot}${BOTTOKEN}" ME_URL=${URL}'/getMe' @@ -438,7 +438,7 @@ sendJson(){ local json chat="" if [ -n "$1" ]; then chat='"chat_id":'"$1"',' - [[ "$1" == *[!${o9o9o9}-]* ]] && chat='"chat_id":"'"$1"' NAN",' # chat id not a number! + [[ "$1" == *[!${o9o9o9}-]* ]] && chat='"chat_id":"'"$1"' NAN",' # chat id not a number! fi # compose final json json='{'"${chat} $(iconv -f utf-8 -t utf-8 -c <<<"$2")"'}' @@ -887,7 +887,6 @@ process_message() { CHAT[ALL_ADMIN]="${UPD["result,${num},message,chat,all_members_are_administrators"]}" # user ID is now parsed when update is received - #USER[ID]="${UPD["result,${num},message,from,id"]}" USER[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,from,first_name"]}")" USER[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,from,last_name"]}")" USER[USERNAME]="$(JsonDecode "${UPD["result,${num},message,from,username"]}")" @@ -907,7 +906,7 @@ process_message() { # forwarded message from if [ -n "${UPD["result,${num},message,forward_from,id"]}" ]; then FORWARD[UID]="${UPD["result,${num},message,forward_from,id"]}" - FORWARD[ID]="${MESSAGE[ID]}" # same as message ID + FORWARD[ID]="${MESSAGE[ID]}" # same as message ID FORWARD[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,forward_from,first_name"]}")" FORWARD[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,forward_from,last_name"]}")" FORWARD[USERNAME]="$(JsonDecode "${UPD["result,${num},message,forward_from,username"]}")" @@ -1203,7 +1202,7 @@ if [ -z "${SOURCE}" ]; then [ "$1" = "botname" ] && exit ;;& # used to send output of background and interactive to chats - "outproc") # $2 chat_id $3 identifier of job, internal use only! + "outproc") # $2 chat_id $3 identifier of job, internal use only! [ -z "$3" ] && printf "No job identifier\n" && exit 3 [ -z "$2" ] && printf "No chat to send to\n" && exit 3 ME="$(getConfigKey "botname")" diff --git a/commands.sh b/commands.sh index f3f95a4..0b10d04 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.30-0-g3266427 +#### $$VERSION$$ v1.31-dev-13-g127cc85 # # bashbot locale defaults to c.UTF-8, adjust locale in mycommands.sh if needed @@ -127,7 +127,7 @@ if [ -z "$1" ] || [[ "$1" == *"debug"* ]];then '/help'*) send_markdown_message "${CHAT[ID]}" "${bashbot_help}" ;; - '/leavechat'*) # bot leave chat if user is admin in chat + '/leavechat'*) # bot leave chat if user is admin in chat if user_is_admin "${CHAT[ID]}" "${USER[ID]}" || user_is_allowed "${USER[ID]}" "leave" ; then send_markdown_message "${CHAT[ID]}" "*LEAVING CHAT...*" leave_chat "${CHAT[ID]}" diff --git a/dev/make-standalone.sh b/dev/make-standalone.sh index a9f9e69..90e7c0f 100755 --- a/dev/make-standalone.sh +++ b/dev/make-standalone.sh @@ -11,7 +11,7 @@ # If you your bot is finished you can use make-standalone.sh to create the # the old all-in-one bashbot: bashbot.sh and commands.sh only! # -#### $$VERSION$$ v1.30-0-g3266427 +#### $$VERSION$$ v1.31-dev-13-g127cc85 ################################################################### #shellcheck disable=SC1090 @@ -73,13 +73,14 @@ printf "\n... create unified bashbot.sh\n" # first head of bashbot.sh sed -n '0,/for module in/ p' bashbot.sh | head -n -3 - # then mycommands from first non comment line on + # then modules without shebang printf '\n##############################\n# bashbot modules starts here ...\n' - cat modules/*.sh | sed -e 's/^#\!\/bin\/bash.*//' + # shellcheck disable=SC2016 + cat modules/*.sh | sed -e 's/^#\!\/bin\/bash.*//' -e '/^#.*\$\$VERSION\$\$/d' - # last tail of commands.sh - printf '\n##############################\n# bashbot internal functions starts here ...\n\n' - sed -n '/BASHBOT INTERNAL functions/,$ p' bashbot.sh + # last remaining commands.sh + printf '\n##############################\n' + sed -n '/^# read commands file/,$ p' bashbot.sh } >>$$bashbot.sh @@ -90,11 +91,11 @@ rm -rf modules printf "Create minimized Version of bashbot.sh and commands.sh\n" # shellcheck disable=SC2016 -sed -E -e '/(shellcheck)|(^#!\/)|(\$\$VERSION\$\$)/! s/^[[:space:]]*#.*//' -e 's/^[[:space:]]*//' -e '/^$/d' -e 'N;s/\\\n/ /;P;D' bashbot.sh |\ - sed 'N;s/\\\n/ /;P;D' > bashbot.sh.min +sed -E -e '/(shellcheck)|(^#!\/)|(\$\$VERSION\$\$)/! s/^[[:space:]]*#.*//' -e '/shellcheck/! s/\t+#.*//' -e 's/^[[:space:]]*//'\ + -e '/^$/d' bashbot.sh | sed 'N;s/\\\n/ /;P;D' | sed 'N;s/\\\n/ /;P;D' > bashbot.sh.min # shellcheck disable=SC2016 -sed -E -e '/(shellcheck)|(^#!\/)|(\$\$VERSION\$\$)/! s/^[[:space:]]*#.*//' -e 's/^[[:space:]]*//' -e 's/\)[[:space:]]+#.*/)/' -e '/^$/d' commands.sh |\ - sed 'N;s/\\\n/ /;P;D' > commands.sh.min +sed -E -e '/(shellcheck)|(^#!\/)|(\$\$VERSION\$\$)/! s/^[[:space:]]*#.*//' -e '/shellcheck/! s/\t+#.*//' -e 's/^[[:space:]]*//'\ + -e '/^$/d' commands.sh | sed 'N;s/\\\n/ /;P;D' > commands.sh.min chmod +x bashbot.sh.min # make html doc diff --git a/modules/aliases.sh b/modules/aliases.sh index 0e551a7..f8cfc6e 100644 --- a/modules/aliases.sh +++ b/modules/aliases.sh @@ -1,11 +1,11 @@ #!/bin/bash -# file: modules/alaises.sh +# file: modules/aliases.sh # do not edit, this file will be overwritten on update # This file is public domain in the USA and all free countries. # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying) # -#### $$VERSION$$ v1.30-0-g3266427 +#### $$VERSION$$ v1.31-dev-13-g127cc85 # # will be automatically sourced from bashbot diff --git a/modules/answerInline.sh b/modules/answerInline.sh index 76ffb64..52f450b 100644 --- a/modules/answerInline.sh +++ b/modules/answerInline.sh @@ -5,7 +5,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.30-0-g3266427 +#### $$VERSION$$ v1.31-dev-13-g127cc85 # will be automatically sourced from bashbot @@ -31,70 +31,70 @@ inline_query_compose(){ # title2Json title caption description markup inlinekeyboard case "$2" in # user provided media - "article"|"message") # article ID title message (markup description) + "article"|"message") # article ID title message (markup description) JSON='{"type":"article","id":"'${ID}'","input_message_content": {"message_text":"'$4'"} '$(title2Json "$3" "" "$5" "$6" "$7")'}' ;; - "photo") # photo ID photoURL (thumbURL title description caption) + "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")'}' ;; - "gif") # gif ID photoURL (thumbURL title caption) + "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")'}' ;; - "mpeg4_gif") # mpeg4_gif ID mpegURL (thumbURL title caption) + "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")'}' ;; - "video") # video ID videoURL mime thumbURL title (caption) + "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}")'}' ;; - "audio") # audio ID audioURL title (caption) + "audio") # audio ID audioURL title (caption) JSON='{"type":"audio","id":"'${ID}'","audio_url":"'$3'"'$(title2Json "$4" "$5" "" "" "$6")'}' ;; - "voice") # voice ID voiceURL title (caption) + "voice") # voice ID voiceURL title (caption) JSON='{"type":"voice","id":"'${ID}'","voice_url":"'$3'"'$(title2Json "$4" "$5" "" "" "$6")'}' ;; - "document") # document ID title documentURL mimetype (caption description) + "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")'}' ;; - "location") # location ID lat long title + "location") # location ID lat long title JSON='{"type":"location","id":"'${ID}'","latitude":"'$3'","longitude":"'$4'","title":"'$5'"}' ;; - "venue") # venue ID lat long title (address forsquare) + "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}'}' ;; - "contact") # contact ID phone first (last thumb) + "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}'"}' ;; # title2Json title caption description markup inlinekeyboard # Cached media stored in Telegram server - "cached_photo") # photo ID file (title description caption) + "cached_photo") # photo ID file (title description caption) JSON='{"type":"photo","id":"'${ID}'","photo_file_id":"'$3'"'$(title2Json "$4" "$6" "$5" "$7" "$8")'}' ;; - "cached_gif") # gif ID file (title caption) + "cached_gif") # gif ID file (title caption) JSON='{"type":"gif","id":"'${ID}'","gif_file_id":"'$3'"'$(title2Json "$4" "$5" "$6" "$7" "$8" )'}' ;; - "cached_mpeg4_gif") # mpeg ID file (title caption) + "cached_mpeg4_gif") # mpeg ID file (title caption) JSON='{"type":"mpeg4_gif","id":"'${ID}'","mpeg4_file_id":"'$3'"'$(title2Json "$4" "$5" "" "$6" "$7")'}' ;; - "cached_sticker") # sticker ID file + "cached_sticker") # sticker ID file JSON='{"type":"sticker","id":"'${ID}'","sticker_file_id":"'$3'"}' ;; - "cached_document") # document ID title file (description caption) + "cached_document") # document ID title file (description caption) JSON='{"type":"document","id":"'${ID}'","document_file_id":"'$4'"'$(title2Json "$3" "$6" "$5" "$6" "$7")'}' ;; - "cached_video") # video ID file title (description caption) + "cached_video") # video ID file title (description caption) JSON='{"type":"video","id":"'${ID}'","video_file_id":"'$3'"'$(title2Json "$4" "$6" "$5" "$7" "$8")'}' ;; - "cached_voice") # voice ID file title (caption) + "cached_voice") # voice ID file title (caption) JSON='{"type":"voice","id":"'${ID}'","voice_file_id":"'$3'"'$(title2Json "$4" "$5" "" "" "$6")'}' ;; - "cached_audio") # audio ID file title (caption) + "cached_audio") # audio ID file title (caption) 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 4409616..b793806 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.30-0-g3266427 +#### $$VERSION$$ v1.31-dev-13-g127cc85 # will be automatically sourced from bashbot @@ -51,7 +51,7 @@ restart_back() { log_message "Start background job CHAT=$1 JOB=${fifo##*/} CMD=${2##*/} $4 $5" check_back "$1" "$3" && kill_proc "$1" "back-$3-" nohup bash -c "{ $2 \"$4\" \"$5\" \"${fifo}\" | \"${SCRIPT}\" outproc \"$1\" \"${fifo}\"; }" &>>"${fifo}.log" & - sleep 0.5 # give bg job some time to init + sleep 0.5 # give bg job some time to init } @@ -110,7 +110,7 @@ kill_proc() { # $2 message send_interactive() { local fifo; fifo="${DATADIR:-.}/$(procname "$1")" - [ -p "${fifo}" ] && printf '%s\n' "$2" >"${fifo}" & # not blocking! + [ -p "${fifo}" ] && printf '%s\n' "$2" >"${fifo}" & # not blocking! } # old style but may not work because of local checks @@ -154,7 +154,7 @@ job_control() { "killb"*) printf "Kill Job: %s %s\n" "${proc}" " ${fifo##*/}" kill_proc "${CHAT}" "${job}" - rm -f "${FILE}" # remove job + rm -f "${FILE}" # remove job # inform botadmin about stop [ -n "${ADM}" ] && send_normal_message "${ADM}" "Bot ${BOT} kill background jobs ..." & killall="y" diff --git a/modules/jsonDB.sh b/modules/jsonDB.sh index 9c49c3c..9169aa8 100644 --- a/modules/jsonDB.sh +++ b/modules/jsonDB.sh @@ -5,7 +5,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.30-0-g3266427 +#### $$VERSION$$ v1.31-dev-13-g127cc85 # # source from commands.sh to use jsonDB functions # @@ -42,7 +42,7 @@ JSSH_KEYOK="[-${azAZo9},._]" # $1 - invalid charcaters are replaced with first character # or deleted if $1 is empty jssh_stripKey() { # tr: we must escape first - in [-a-z...] - if [[ "$1" =~ ^${JSSH_KEYOK} ]]; then # tr needs [\-... + if [[ "$1" =~ ^${JSSH_KEYOK} ]]; then # tr needs [\-... tr -c "${JSSH_KEYOK/\[-/[\\-}\r\n" "${1:0:1}" else tr -dc "${JSSH_KEYOK/\[-/[\\-}\r\n" @@ -86,7 +86,7 @@ if [ "$(LC_ALL=C type -t "flock")" = "file" ]; then jssh_updateDB() { # for atomic update we can't use read/writeDB [ -z "$2" ] && return 1 - local DB="$2.jssh" # check in async + local DB="$2.jssh" # check in async [ ! -f "${DB}" ] && return 2 { flock -e -w 10 200; jssh_updateDB_async "$@"; } 200>"${DB}${JSSH_LOCKNAME}" } @@ -95,7 +95,7 @@ if [ "$(LC_ALL=C type -t "flock")" = "file" ]; then # $1 key name, can only contain -a-zA-Z0-9,._ # $2 key value # $3 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..' - alias jssh_insertDB=jssh_insertKeyDB # backward compatibility + alias jssh_insertDB=jssh_insertKeyDB # backward compatibility # renamed to be more consistent jssh_insertKeyDB() { [[ "$1" =~ ^${JSSH_KEYOK}+$ ]] || return 3 @@ -179,7 +179,7 @@ if [ "$(LC_ALL=C type -t "flock")" = "file" ]; then # medium complex, wrapper async jssh_updateArray() { [ -z "$2" ] && return 1 - local DB="$2.jssh" # name check in async + local DB="$2.jssh" # name check in async [ ! -f "${DB}" ] && return 2 declare -n ARRAY="$1" [[ -z "${ARRAY[*]}" || "${DB}" -nt "${DB}.last$3" ]] && touch "${DB}.last$3" && jssh_readDB "$1" "$2" @@ -216,7 +216,7 @@ jssh_newDB_async() { jssh_newDB "$@"; } jssh_newDB() { local DB; DB="$(jssh_checkDB "$1")" [ -z "${DB}" ] && return 1 - [ -f "${DB}" ] && return 2 # already exist + [ -f "${DB}" ] && return 2 # already exist touch "${DB}" } diff --git a/modules/sendMessage.sh b/modules/sendMessage.sh index 55e997a..bd54e86 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.31-dev-9-g6c91a32 +#### $$VERSION$$ v1.31-dev-13-g127cc85 # will be automatically sourced from bashbot @@ -176,7 +176,7 @@ if detect_curl ; then # $1 chat $3 ... $n URL or ID send_album(){ [ -z "$1" ] && return 1 - [ -z "$3" ] && return 2 # minimum 2 files + [ -z "$3" ] && return 2 # minimum 2 files local CHAT JSON IMAGE; CHAT="$1"; shift for IMAGE in "$@" do @@ -212,13 +212,13 @@ send_file(){ else # we have a file, check file location ... media="FILE" - [[ "${file}" = *'..'* || "${file}" = '.'* ]] && err=1 # no directory traversal + [[ "${file}" = *'..'* || "${file}" = '.'* ]] && err=1 # no directory traversal if [[ "${file}" = '/'* ]] ; then - [[ ! "${file}" =~ ${FILE_REGEX} ]] && err=2 # absolute must match REGEX + [[ ! "${file}" =~ ${FILE_REGEX} ]] && err=2 # absolute must match REGEX else - file="${UPLOADDIR:-NOUPLOADDIR}/${file}" # others must be in UPLOADDIR + file="${UPLOADDIR:-NOUPLOADDIR}/${file}" # others must be in UPLOADDIR fi - [ ! -r "${file}" ] && err=3 # and file must exits of course + [ ! -r "${file}" ] && err=3 # and file must exits of course # file path error, generate error response if [ -n "${err}" ]; then BOTSENT=(); BOTSENT[OK]="false" @@ -311,7 +311,7 @@ forward_message() { [ -z "$3" ] && return sendJson "$1" '"from_chat_id": '"$2"', "message_id": '"$3"'' "${URL}/forwardMessage" } -forward() { # backward compatibility +forward() { # backward compatibility forward_message "$@" || return } @@ -339,7 +339,7 @@ send_message() { sent=y fi if [ -n "${keyboard}" ]; then - if [[ "${keyboard}" != *"["* ]]; then # pre 0.60 style + if [[ "${keyboard}" != *"["* ]]; then # pre 0.60 style keyboard="[ ${keyboard//\" \"/\" \] , \[ \"} ]" fi send_keyboard "$1" "${text}" "${keyboard}"